1 | /* Merge parameters into a termcap entry string.
|
---|
2 | Copyright (C) 1985, 87, 93, 95 Free Software Foundation, Inc.
|
---|
3 |
|
---|
4 | This program is free software; you can redistribute it and/or modify
|
---|
5 | it under the terms of the GNU General Public License as published by
|
---|
6 | the Free Software Foundation; either version 2, or (at your option)
|
---|
7 | any later version.
|
---|
8 |
|
---|
9 | This program is distributed in the hope that it will be useful,
|
---|
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
12 | GNU General Public License for more details.
|
---|
13 |
|
---|
14 | You should have received a copy of the GNU General Public License
|
---|
15 | along with this program; see the file COPYING. If not, write to the
|
---|
16 | Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
---|
17 |
|
---|
18 | /* Emacs config.h may rename various library functions such as malloc. */
|
---|
19 | #ifdef HAVE_CONFIG_H
|
---|
20 | #include <config.h>
|
---|
21 |
|
---|
22 | #ifdef HAVE_STDLIB_H
|
---|
23 | # include <stdlib.h>
|
---|
24 | #else
|
---|
25 | extern char *getenv ();
|
---|
26 | extern char *malloc ();
|
---|
27 | extern char *realloc ();
|
---|
28 | #endif
|
---|
29 |
|
---|
30 | #else /* not HAVE_CONFIG_H */
|
---|
31 |
|
---|
32 | #if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
|
---|
33 | #define bcopy(s, d, n) memcpy ((d), (s), (n))
|
---|
34 | #endif
|
---|
35 |
|
---|
36 | #ifdef STDC_HEADERS
|
---|
37 | #include <stdlib.h>
|
---|
38 | #include <string.h>
|
---|
39 | #else
|
---|
40 | char *malloc ();
|
---|
41 | char *realloc ();
|
---|
42 | #endif
|
---|
43 |
|
---|
44 | #endif /* not HAVE_CONFIG_H */
|
---|
45 |
|
---|
46 | #include "ltcap.h"
|
---|
47 |
|
---|
48 | #ifndef NULL
|
---|
49 | #define NULL (char *) 0
|
---|
50 | #endif
|
---|
51 | |
---|
52 |
|
---|
53 | #ifndef emacs
|
---|
54 | static void
|
---|
55 | memory_out ()
|
---|
56 | {
|
---|
57 | write (2, "virtual memory exhausted\n", 25);
|
---|
58 | exit (1);
|
---|
59 | }
|
---|
60 |
|
---|
61 | static char *
|
---|
62 | xmalloc (size)
|
---|
63 | unsigned size;
|
---|
64 | {
|
---|
65 | register char *tem = malloc (size);
|
---|
66 |
|
---|
67 | if (!tem)
|
---|
68 | memory_out ();
|
---|
69 | return tem;
|
---|
70 | }
|
---|
71 |
|
---|
72 | static char *
|
---|
73 | xrealloc (ptr, size)
|
---|
74 | char *ptr;
|
---|
75 | unsigned size;
|
---|
76 | {
|
---|
77 | register char *tem = realloc (ptr, size);
|
---|
78 |
|
---|
79 | if (!tem)
|
---|
80 | memory_out ();
|
---|
81 | return tem;
|
---|
82 | }
|
---|
83 | #endif /* not emacs */
|
---|
84 | |
---|
85 |
|
---|
86 | /* Assuming STRING is the value of a termcap string entry
|
---|
87 | containing `%' constructs to expand parameters,
|
---|
88 | merge in parameter values and store result in block OUTSTRING points to.
|
---|
89 | LEN is the length of OUTSTRING. If more space is needed,
|
---|
90 | a block is allocated with `malloc'.
|
---|
91 |
|
---|
92 | The value returned is the address of the resulting string.
|
---|
93 | This may be OUTSTRING or may be the address of a block got with `malloc'.
|
---|
94 | In the latter case, the caller must free the block.
|
---|
95 |
|
---|
96 | The fourth and following args to tparam serve as the parameter values. */
|
---|
97 |
|
---|
98 | static char *tparam1 ();
|
---|
99 |
|
---|
100 | /* VARARGS 2 */
|
---|
101 | char *
|
---|
102 | tparam (string, outstring, len, arg0, arg1, arg2, arg3)
|
---|
103 | char *string;
|
---|
104 | char *outstring;
|
---|
105 | int len;
|
---|
106 | int arg0, arg1, arg2, arg3;
|
---|
107 | {
|
---|
108 | int arg[4];
|
---|
109 |
|
---|
110 | arg[0] = arg0;
|
---|
111 | arg[1] = arg1;
|
---|
112 | arg[2] = arg2;
|
---|
113 | arg[3] = arg3;
|
---|
114 | return tparam1 (string, outstring, len, NULL, NULL, arg);
|
---|
115 | }
|
---|
116 |
|
---|
117 | __private_extern__ char *BC;
|
---|
118 | __private_extern__ char *UP;
|
---|
119 |
|
---|
120 | static char tgoto_buf[50];
|
---|
121 |
|
---|
122 | __private_extern__
|
---|
123 | char *
|
---|
124 | tgoto (cm, hpos, vpos)
|
---|
125 | char *cm;
|
---|
126 | int hpos, vpos;
|
---|
127 | {
|
---|
128 | int args[2];
|
---|
129 | if (!cm)
|
---|
130 | return NULL;
|
---|
131 | args[0] = vpos;
|
---|
132 | args[1] = hpos;
|
---|
133 | return tparam1 (cm, tgoto_buf, 50, UP, BC, args);
|
---|
134 | }
|
---|
135 |
|
---|
136 | static char *
|
---|
137 | tparam1 (string, outstring, len, up, left, argp)
|
---|
138 | char *string;
|
---|
139 | char *outstring;
|
---|
140 | int len;
|
---|
141 | char *up, *left;
|
---|
142 | register int *argp;
|
---|
143 | {
|
---|
144 | register int c;
|
---|
145 | register char *p = string;
|
---|
146 | register char *op = outstring;
|
---|
147 | char *outend;
|
---|
148 | int outlen = 0;
|
---|
149 |
|
---|
150 | register int tem;
|
---|
151 | int *old_argp = argp;
|
---|
152 | int doleft = 0;
|
---|
153 | int doup = 0;
|
---|
154 |
|
---|
155 | outend = outstring + len;
|
---|
156 |
|
---|
157 | while (1)
|
---|
158 | {
|
---|
159 | /* If the buffer might be too short, make it bigger. */
|
---|
160 | if (op + 5 >= outend)
|
---|
161 | {
|
---|
162 | register char *new;
|
---|
163 | if (outlen == 0)
|
---|
164 | {
|
---|
165 | outlen = len + 40;
|
---|
166 | new = (char *) xmalloc (outlen);
|
---|
167 | outend += 40;
|
---|
168 | bcopy (outstring, new, op - outstring);
|
---|
169 | }
|
---|
170 | else
|
---|
171 | {
|
---|
172 | outend += outlen;
|
---|
173 | outlen *= 2;
|
---|
174 | new = (char *) xrealloc (outstring, outlen);
|
---|
175 | }
|
---|
176 | op += new - outstring;
|
---|
177 | outend += new - outstring;
|
---|
178 | outstring = new;
|
---|
179 | }
|
---|
180 | c = *p++;
|
---|
181 | if (!c)
|
---|
182 | break;
|
---|
183 | if (c == '%')
|
---|
184 | {
|
---|
185 | c = *p++;
|
---|
186 | tem = *argp;
|
---|
187 | switch (c)
|
---|
188 | {
|
---|
189 | case 'd': /* %d means output in decimal. */
|
---|
190 | if (tem < 10)
|
---|
191 | goto onedigit;
|
---|
192 | if (tem < 100)
|
---|
193 | goto twodigit;
|
---|
194 | case '3': /* %3 means output in decimal, 3 digits. */
|
---|
195 | if (tem > 999)
|
---|
196 | {
|
---|
197 | *op++ = tem / 1000 + '0';
|
---|
198 | tem %= 1000;
|
---|
199 | }
|
---|
200 | *op++ = tem / 100 + '0';
|
---|
201 | case '2': /* %2 means output in decimal, 2 digits. */
|
---|
202 | twodigit:
|
---|
203 | tem %= 100;
|
---|
204 | *op++ = tem / 10 + '0';
|
---|
205 | onedigit:
|
---|
206 | *op++ = tem % 10 + '0';
|
---|
207 | argp++;
|
---|
208 | break;
|
---|
209 |
|
---|
210 | case 'C':
|
---|
211 | /* For c-100: print quotient of value by 96, if nonzero,
|
---|
212 | then do like %+. */
|
---|
213 | if (tem >= 96)
|
---|
214 | {
|
---|
215 | *op++ = tem / 96;
|
---|
216 | tem %= 96;
|
---|
217 | }
|
---|
218 | case '+': /* %+x means add character code of char x. */
|
---|
219 | tem += *p++;
|
---|
220 | case '.': /* %. means output as character. */
|
---|
221 | if (left)
|
---|
222 | {
|
---|
223 | /* If want to forbid output of 0 and \n and \t,
|
---|
224 | and this is one of them, increment it. */
|
---|
225 | while (tem == 0 || tem == '\n' || tem == '\t')
|
---|
226 | {
|
---|
227 | tem++;
|
---|
228 | if (argp == old_argp)
|
---|
229 | doup++, outend -= strlen (up);
|
---|
230 | else
|
---|
231 | doleft++, outend -= strlen (left);
|
---|
232 | }
|
---|
233 | }
|
---|
234 | *op++ = tem ? tem : 0200;
|
---|
235 | case 'f': /* %f means discard next arg. */
|
---|
236 | argp++;
|
---|
237 | break;
|
---|
238 |
|
---|
239 | case 'b': /* %b means back up one arg (and re-use it). */
|
---|
240 | argp--;
|
---|
241 | break;
|
---|
242 |
|
---|
243 | case 'r': /* %r means interchange following two args. */
|
---|
244 | argp[0] = argp[1];
|
---|
245 | argp[1] = tem;
|
---|
246 | old_argp++;
|
---|
247 | break;
|
---|
248 |
|
---|
249 | case '>': /* %>xy means if arg is > char code of x, */
|
---|
250 | if (argp[0] > *p++) /* then add char code of y to the arg, */
|
---|
251 | argp[0] += *p; /* and in any case don't output. */
|
---|
252 | p++; /* Leave the arg to be output later. */
|
---|
253 | break;
|
---|
254 |
|
---|
255 | case 'a': /* %a means arithmetic. */
|
---|
256 | /* Next character says what operation.
|
---|
257 | Add or subtract either a constant or some other arg. */
|
---|
258 | /* First following character is + to add or - to subtract
|
---|
259 | or = to assign. */
|
---|
260 | /* Next following char is 'p' and an arg spec
|
---|
261 | (0100 plus position of that arg relative to this one)
|
---|
262 | or 'c' and a constant stored in a character. */
|
---|
263 | tem = p[2] & 0177;
|
---|
264 | if (p[1] == 'p')
|
---|
265 | tem = argp[tem - 0100];
|
---|
266 | if (p[0] == '-')
|
---|
267 | argp[0] -= tem;
|
---|
268 | else if (p[0] == '+')
|
---|
269 | argp[0] += tem;
|
---|
270 | else if (p[0] == '*')
|
---|
271 | argp[0] *= tem;
|
---|
272 | else if (p[0] == '/')
|
---|
273 | argp[0] /= tem;
|
---|
274 | else
|
---|
275 | argp[0] = tem;
|
---|
276 |
|
---|
277 | p += 3;
|
---|
278 | break;
|
---|
279 |
|
---|
280 | case 'i': /* %i means add one to arg, */
|
---|
281 | argp[0] ++; /* and leave it to be output later. */
|
---|
282 | argp[1] ++; /* Increment the following arg, too! */
|
---|
283 | break;
|
---|
284 |
|
---|
285 | case '%': /* %% means output %; no arg. */
|
---|
286 | goto ordinary;
|
---|
287 |
|
---|
288 | case 'n': /* %n means xor each of next two args with 140. */
|
---|
289 | argp[0] ^= 0140;
|
---|
290 | argp[1] ^= 0140;
|
---|
291 | break;
|
---|
292 |
|
---|
293 | case 'm': /* %m means xor each of next two args with 177. */
|
---|
294 | argp[0] ^= 0177;
|
---|
295 | argp[1] ^= 0177;
|
---|
296 | break;
|
---|
297 |
|
---|
298 | case 'B': /* %B means express arg as BCD char code. */
|
---|
299 | argp[0] += 6 * (tem / 10);
|
---|
300 | break;
|
---|
301 |
|
---|
302 | case 'D': /* %D means weird Delta Data transformation. */
|
---|
303 | argp[0] -= 2 * (tem % 16);
|
---|
304 | break;
|
---|
305 | }
|
---|
306 | }
|
---|
307 | else
|
---|
308 | /* Ordinary character in the argument string. */
|
---|
309 | ordinary:
|
---|
310 | *op++ = c;
|
---|
311 | }
|
---|
312 | *op = 0;
|
---|
313 | while (doup-- > 0)
|
---|
314 | strcat (op, up);
|
---|
315 | while (doleft-- > 0)
|
---|
316 | strcat (op, left);
|
---|
317 | return outstring;
|
---|
318 | }
|
---|
319 | |
---|
320 |
|
---|
321 | #ifdef DEBUG
|
---|
322 |
|
---|
323 | main (argc, argv)
|
---|
324 | int argc;
|
---|
325 | char **argv;
|
---|
326 | {
|
---|
327 | char buf[50];
|
---|
328 | int args[3];
|
---|
329 | args[0] = atoi (argv[2]);
|
---|
330 | args[1] = atoi (argv[3]);
|
---|
331 | args[2] = atoi (argv[4]);
|
---|
332 | tparam1 (argv[1], buf, "LEFT", "UP", args);
|
---|
333 | printf ("%s\n", buf);
|
---|
334 | return 0;
|
---|
335 | }
|
---|
336 |
|
---|
337 | #endif /* DEBUG */
|
---|