Home | History | Annotate | Line # | Download | only in m4
eval.c revision 1.1
      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