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 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #ifndef lint 38 static char sccsid[] = "@(#)eval.c 5.4 (Berkeley) 2/26/91"; 39 #endif /* not lint */ 40 41 /* 42 * eval.c 43 * Facility: m4 macro processor 44 * by: oz 45 */ 46 47 #include <unistd.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include "mdef.h" 52 #include "extr.h" 53 54 extern ndptr lookup(); 55 56 /* 57 * eval - evaluate built-in macros. 58 * argc - number of elements in argv. 59 * argv - element vector : 60 * argv[0] = definition of a user 61 * macro or nil if built-in. 62 * argv[1] = name of the macro or 63 * built-in. 64 * argv[2] = parameters to user-defined 65 * . macro or built-in. 66 * . 67 * 68 * Note that the minimum value for argc is 3. A call in the form 69 * of macro-or-builtin() will result in: 70 * argv[0] = nullstr 71 * argv[1] = macro-or-builtin 72 * argv[2] = nullstr 73 * 74 */ 75 76 eval (argv, argc, td) 77 register char *argv[]; 78 register int argc; 79 register int td; 80 { 81 register int c, n; 82 static int sysval; 83 84 #ifdef DEBUG 85 printf("argc = %d\n", argc); 86 for (n = 0; n < argc; n++) 87 printf("argv[%d] = %s\n", n, argv[n]); 88 #endif 89 /* 90 * if argc == 3 and argv[2] is null, 91 * then we have macro-or-builtin() type call. 92 * We adjust argc to avoid further checking.. 93 * 94 */ 95 if (argc == 3 && !*(argv[2])) 96 argc--; 97 98 switch (td & ~STATIC) { 99 100 case DEFITYPE: 101 if (argc > 2) 102 dodefine(argv[2], (argc > 3) ? argv[3] : null); 103 break; 104 105 case PUSDTYPE: 106 if (argc > 2) 107 dopushdef(argv[2], (argc > 3) ? argv[3] : null); 108 break; 109 110 case DUMPTYPE: 111 dodump(argv, argc); 112 break; 113 114 case EXPRTYPE: 115 /* 116 * doexpr - evaluate arithmetic expression 117 * 118 */ 119 if (argc > 2) 120 pbnum(expr(argv[2])); 121 break; 122 123 case IFELTYPE: 124 if (argc > 4) 125 doifelse(argv, argc); 126 break; 127 128 case IFDFTYPE: 129 /* 130 * doifdef - select one of two alternatives based 131 * on the existence of another definition 132 */ 133 if (argc > 3) { 134 if (lookup(argv[2]) != nil) 135 pbstr(argv[3]); 136 else if (argc > 4) 137 pbstr(argv[4]); 138 } 139 break; 140 141 case LENGTYPE: 142 /* 143 * dolen - find the length of the argument 144 * 145 */ 146 if (argc > 2) 147 pbnum((argc > 2) ? strlen(argv[2]) : 0); 148 break; 149 150 case INCRTYPE: 151 /* 152 * doincr - increment the value of the argument 153 * 154 */ 155 if (argc > 2) 156 pbnum(atoi(argv[2]) + 1); 157 break; 158 159 case DECRTYPE: 160 /* 161 * dodecr - decrement the value of the argument 162 * 163 */ 164 if (argc > 2) 165 pbnum(atoi(argv[2]) - 1); 166 break; 167 168 case SYSCTYPE: 169 /* 170 * dosys - execute system command 171 * 172 */ 173 if (argc > 2) 174 sysval = system(argv[2]); 175 break; 176 177 case SYSVTYPE: 178 /* 179 * dosysval - return value of the last system call. 180 * 181 */ 182 pbnum(sysval); 183 break; 184 185 case INCLTYPE: 186 if (argc > 2) 187 if (!doincl(argv[2])) { 188 fprintf(stderr,"m4: %s: ",argv[2]); 189 error("cannot open for read."); 190 } 191 break; 192 193 case SINCTYPE: 194 if (argc > 2) 195 (void) doincl(argv[2]); 196 break; 197 #ifdef EXTENDED 198 case PASTTYPE: 199 if (argc > 2) 200 if (!dopaste(argv[2])) { 201 fprintf(stderr,"m4: %s: ",argv[2]); 202 error("cannot open for read."); 203 } 204 break; 205 206 case SPASTYPE: 207 if (argc > 2) 208 (void) dopaste(argv[2]); 209 break; 210 #endif 211 case CHNQTYPE: 212 dochq(argv, argc); 213 break; 214 215 case CHNCTYPE: 216 dochc(argv, argc); 217 break; 218 219 case SUBSTYPE: 220 /* 221 * dosub - select substring 222 * 223 */ 224 if (argc > 3) 225 dosub(argv,argc); 226 break; 227 228 case SHIFTYPE: 229 /* 230 * doshift - push back all arguments except the 231 * first one (i.e. skip argv[2]) 232 */ 233 if (argc > 3) { 234 for (n = argc-1; n > 3; n--) { 235 putback(rquote); 236 pbstr(argv[n]); 237 putback(lquote); 238 putback(','); 239 } 240 putback(rquote); 241 pbstr(argv[3]); 242 putback(lquote); 243 } 244 break; 245 246 case DIVRTYPE: 247 if (argc > 2 && (n = atoi(argv[2])) != 0) 248 dodiv(n); 249 else { 250 active = stdout; 251 oindex = 0; 252 } 253 break; 254 255 case UNDVTYPE: 256 doundiv(argv, argc); 257 break; 258 259 case DIVNTYPE: 260 /* 261 * dodivnum - return the number of current 262 * output diversion 263 * 264 */ 265 pbnum(oindex); 266 break; 267 268 case UNDFTYPE: 269 /* 270 * doundefine - undefine a previously defined 271 * macro(s) or m4 keyword(s). 272 */ 273 if (argc > 2) 274 for (n = 2; n < argc; n++) 275 remhash(argv[n], ALL); 276 break; 277 278 case POPDTYPE: 279 /* 280 * dopopdef - remove the topmost definitions of 281 * macro(s) or m4 keyword(s). 282 */ 283 if (argc > 2) 284 for (n = 2; n < argc; n++) 285 remhash(argv[n], TOP); 286 break; 287 288 case MKTMTYPE: 289 /* 290 * dotemp - create a temporary file 291 * 292 */ 293 if (argc > 2) 294 pbstr(mktemp(argv[2])); 295 break; 296 297 case TRNLTYPE: 298 /* 299 * dotranslit - replace all characters in the 300 * source string that appears in 301 * the "from" string with the corresponding 302 * characters in the "to" string. 303 * 304 */ 305 if (argc > 3) { 306 char temp[MAXTOK]; 307 if (argc > 4) 308 map(temp, argv[2], argv[3], argv[4]); 309 else 310 map(temp, argv[2], argv[3], null); 311 pbstr(temp); 312 } 313 else 314 if (argc > 2) 315 pbstr(argv[2]); 316 break; 317 318 case INDXTYPE: 319 /* 320 * doindex - find the index of the second argument 321 * string in the first argument string. 322 * -1 if not present. 323 */ 324 pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1); 325 break; 326 327 case ERRPTYPE: 328 /* 329 * doerrp - print the arguments to stderr file 330 * 331 */ 332 if (argc > 2) { 333 for (n = 2; n < argc; n++) 334 fprintf(stderr,"%s ", argv[n]); 335 fprintf(stderr, "\n"); 336 } 337 break; 338 339 case DNLNTYPE: 340 /* 341 * dodnl - eat-up-to and including newline 342 * 343 */ 344 while ((c = gpbc()) != '\n' && c != EOF) 345 ; 346 break; 347 348 case M4WRTYPE: 349 /* 350 * dom4wrap - set up for wrap-up/wind-down activity 351 * 352 */ 353 m4wraps = (argc > 2) ? strdup(argv[2]) : null; 354 break; 355 356 case EXITTYPE: 357 /* 358 * doexit - immediate exit from m4. 359 * 360 */ 361 exit((argc > 2) ? atoi(argv[2]) : 0); 362 break; 363 364 case DEFNTYPE: 365 if (argc > 2) 366 for (n = 2; n < argc; n++) 367 dodefn(argv[n]); 368 break; 369 370 default: 371 error("m4: major botch in eval."); 372 break; 373 } 374 } 375