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