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