1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Ozan Yigit. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)eval.c 5.4 (Berkeley) 02/26/91"; 13 #endif /* not lint */ 14 15 /* 16 * eval.c 17 * Facility: m4 macro processor 18 * by: oz 19 */ 20 21 #include <unistd.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include "mdef.h" 26 #include "extr.h" 27 28 extern ndptr lookup(); 29 30 /* 31 * eval - evaluate built-in macros. 32 * argc - number of elements in argv. 33 * argv - element vector : 34 * argv[0] = definition of a user 35 * macro or nil if built-in. 36 * argv[1] = name of the macro or 37 * built-in. 38 * argv[2] = parameters to user-defined 39 * . macro or built-in. 40 * . 41 * 42 * Note that the minimum value for argc is 3. A call in the form 43 * of macro-or-builtin() will result in: 44 * argv[0] = nullstr 45 * argv[1] = macro-or-builtin 46 * argv[2] = nullstr 47 * 48 */ 49 50 eval (argv, argc, td) 51 register char *argv[]; 52 register int argc; 53 register int td; 54 { 55 register int c, n; 56 static int sysval; 57 58 #ifdef DEBUG 59 printf("argc = %d\n", argc); 60 for (n = 0; n < argc; n++) 61 printf("argv[%d] = %s\n", n, argv[n]); 62 #endif 63 /* 64 * if argc == 3 and argv[2] is null, 65 * then we have macro-or-builtin() type call. 66 * We adjust argc to avoid further checking.. 67 * 68 */ 69 if (argc == 3 && !*(argv[2])) 70 argc--; 71 72 switch (td & ~STATIC) { 73 74 case DEFITYPE: 75 if (argc > 2) 76 dodefine(argv[2], (argc > 3) ? argv[3] : null); 77 break; 78 79 case PUSDTYPE: 80 if (argc > 2) 81 dopushdef(argv[2], (argc > 3) ? argv[3] : null); 82 break; 83 84 case DUMPTYPE: 85 dodump(argv, argc); 86 break; 87 88 case EXPRTYPE: 89 /* 90 * doexpr - evaluate arithmetic expression 91 * 92 */ 93 if (argc > 2) 94 pbnum(expr(argv[2])); 95 break; 96 97 case IFELTYPE: 98 if (argc > 4) 99 doifelse(argv, argc); 100 break; 101 102 case IFDFTYPE: 103 /* 104 * doifdef - select one of two alternatives based 105 * on the existence of another definition 106 */ 107 if (argc > 3) { 108 if (lookup(argv[2]) != nil) 109 pbstr(argv[3]); 110 else if (argc > 4) 111 pbstr(argv[4]); 112 } 113 break; 114 115 case LENGTYPE: 116 /* 117 * dolen - find the length of the argument 118 * 119 */ 120 if (argc > 2) 121 pbnum((argc > 2) ? strlen(argv[2]) : 0); 122 break; 123 124 case INCRTYPE: 125 /* 126 * doincr - increment the value of the argument 127 * 128 */ 129 if (argc > 2) 130 pbnum(atoi(argv[2]) + 1); 131 break; 132 133 case DECRTYPE: 134 /* 135 * dodecr - decrement the value of the argument 136 * 137 */ 138 if (argc > 2) 139 pbnum(atoi(argv[2]) - 1); 140 break; 141 142 case SYSCTYPE: 143 /* 144 * dosys - execute system command 145 * 146 */ 147 if (argc > 2) 148 sysval = system(argv[2]); 149 break; 150 151 case SYSVTYPE: 152 /* 153 * dosysval - return value of the last system call. 154 * 155 */ 156 pbnum(sysval); 157 break; 158 159 case INCLTYPE: 160 if (argc > 2) 161 if (!doincl(argv[2])) { 162 fprintf(stderr,"m4: %s: ",argv[2]); 163 error("cannot open for read."); 164 } 165 break; 166 167 case SINCTYPE: 168 if (argc > 2) 169 (void) doincl(argv[2]); 170 break; 171 #ifdef EXTENDED 172 case PASTTYPE: 173 if (argc > 2) 174 if (!dopaste(argv[2])) { 175 fprintf(stderr,"m4: %s: ",argv[2]); 176 error("cannot open for read."); 177 } 178 break; 179 180 case SPASTYPE: 181 if (argc > 2) 182 (void) dopaste(argv[2]); 183 break; 184 #endif 185 case CHNQTYPE: 186 dochq(argv, argc); 187 break; 188 189 case CHNCTYPE: 190 dochc(argv, argc); 191 break; 192 193 case SUBSTYPE: 194 /* 195 * dosub - select substring 196 * 197 */ 198 if (argc > 3) 199 dosub(argv,argc); 200 break; 201 202 case SHIFTYPE: 203 /* 204 * doshift - push back all arguments except the 205 * first one (i.e. skip argv[2]) 206 */ 207 if (argc > 3) { 208 for (n = argc-1; n > 3; n--) { 209 putback(rquote); 210 pbstr(argv[n]); 211 putback(lquote); 212 putback(','); 213 } 214 putback(rquote); 215 pbstr(argv[3]); 216 putback(lquote); 217 } 218 break; 219 220 case DIVRTYPE: 221 if (argc > 2 && (n = atoi(argv[2])) != 0) 222 dodiv(n); 223 else { 224 active = stdout; 225 oindex = 0; 226 } 227 break; 228 229 case UNDVTYPE: 230 doundiv(argv, argc); 231 break; 232 233 case DIVNTYPE: 234 /* 235 * dodivnum - return the number of current 236 * output diversion 237 * 238 */ 239 pbnum(oindex); 240 break; 241 242 case UNDFTYPE: 243 /* 244 * doundefine - undefine a previously defined 245 * macro(s) or m4 keyword(s). 246 */ 247 if (argc > 2) 248 for (n = 2; n < argc; n++) 249 remhash(argv[n], ALL); 250 break; 251 252 case POPDTYPE: 253 /* 254 * dopopdef - remove the topmost definitions of 255 * macro(s) or m4 keyword(s). 256 */ 257 if (argc > 2) 258 for (n = 2; n < argc; n++) 259 remhash(argv[n], TOP); 260 break; 261 262 case MKTMTYPE: 263 /* 264 * dotemp - create a temporary file 265 * 266 */ 267 if (argc > 2) 268 pbstr(mktemp(argv[2])); 269 break; 270 271 case TRNLTYPE: 272 /* 273 * dotranslit - replace all characters in the 274 * source string that appears in 275 * the "from" string with the corresponding 276 * characters in the "to" string. 277 * 278 */ 279 if (argc > 3) { 280 char temp[MAXTOK]; 281 if (argc > 4) 282 map(temp, argv[2], argv[3], argv[4]); 283 else 284 map(temp, argv[2], argv[3], null); 285 pbstr(temp); 286 } 287 else 288 if (argc > 2) 289 pbstr(argv[2]); 290 break; 291 292 case INDXTYPE: 293 /* 294 * doindex - find the index of the second argument 295 * string in the first argument string. 296 * -1 if not present. 297 */ 298 pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1); 299 break; 300 301 case ERRPTYPE: 302 /* 303 * doerrp - print the arguments to stderr file 304 * 305 */ 306 if (argc > 2) { 307 for (n = 2; n < argc; n++) 308 fprintf(stderr,"%s ", argv[n]); 309 fprintf(stderr, "\n"); 310 } 311 break; 312 313 case DNLNTYPE: 314 /* 315 * dodnl - eat-up-to and including newline 316 * 317 */ 318 while ((c = gpbc()) != '\n' && c != EOF) 319 ; 320 break; 321 322 case M4WRTYPE: 323 /* 324 * dom4wrap - set up for wrap-up/wind-down activity 325 * 326 */ 327 m4wraps = (argc > 2) ? strdup(argv[2]) : null; 328 break; 329 330 case EXITTYPE: 331 /* 332 * doexit - immediate exit from m4. 333 * 334 */ 335 exit((argc > 2) ? atoi(argv[2]) : 0); 336 break; 337 338 case DEFNTYPE: 339 if (argc > 2) 340 for (n = 2; n < argc; n++) 341 dodefn(argv[n]); 342 break; 343 344 default: 345 error("m4: major botch in eval."); 346 break; 347 } 348 } 349