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