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