332 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			332 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/*
 | 
						|
 * eval.c
 | 
						|
 * Facility: m4 macro processor
 | 
						|
 * by: oz
 | 
						|
 */
 | 
						|
 | 
						|
#include "mdef.h"
 | 
						|
#include "extr.h"
 | 
						|
 | 
						|
/*
 | 
						|
 * eval - evaluate built-in macros.
 | 
						|
 *	  argc - number of elements in argv.
 | 
						|
 *	  argv - element vector :
 | 
						|
 *			argv[0] = definition of a user
 | 
						|
 *				  macro or nil if built-in.
 | 
						|
 *			argv[1] = name of the macro or
 | 
						|
 *				  built-in.
 | 
						|
 *			argv[2] = parameters to user-defined
 | 
						|
 *			   .	  macro or built-in.
 | 
						|
 *			   .
 | 
						|
 *
 | 
						|
 * Note that the minimum value for argc is 3. A call in the form
 | 
						|
 * of macro-or-builtin() will result in:
 | 
						|
 *			argv[0] = nullstr
 | 
						|
 *			argv[1] = macro-or-builtin
 | 
						|
 *			argv[2] = nullstr
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
void eval (argv, argc, td)
 | 
						|
register char *argv[];
 | 
						|
register int argc;
 | 
						|
register int  td;
 | 
						|
{
 | 
						|
	register int c, n;
 | 
						|
	static int sysval;
 | 
						|
 | 
						|
#ifdef DEBUG
 | 
						|
	printf("argc = %d\n", argc);
 | 
						|
	for (n = 0; n < argc; n++)
 | 
						|
		printf("argv[%d] = %s\n", n, argv[n]);
 | 
						|
#endif
 | 
						|
	/*
 | 
						|
	 * if argc == 3 and argv[2] is null,
 | 
						|
	 * then we have macro-or-builtin() type call.
 | 
						|
	 * We adjust argc to avoid further checking..
 | 
						|
	 *
 | 
						|
	 */
 | 
						|
	if (argc == 3 && !*(argv[2]))
 | 
						|
		argc--;
 | 
						|
 | 
						|
	switch (td & ~STATIC) {
 | 
						|
 | 
						|
	case DEFITYPE:
 | 
						|
		if (argc > 2)
 | 
						|
			dodefine(argv[2], (argc > 3) ? argv[3] : null);
 | 
						|
		break;
 | 
						|
 | 
						|
	case PUSDTYPE:
 | 
						|
		if (argc > 2)
 | 
						|
			dopushdef(argv[2], (argc > 3) ? argv[3] : null);
 | 
						|
		break;
 | 
						|
 | 
						|
	case DUMPTYPE:
 | 
						|
		dodump(argv, argc);
 | 
						|
		break;
 | 
						|
 | 
						|
	case EXPRTYPE:
 | 
						|
		/*
 | 
						|
		 * doexpr - evaluate arithmetic expression
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		if (argc > 2)
 | 
						|
			pbnum(expr(argv[2]));
 | 
						|
		break;
 | 
						|
 | 
						|
	case IFELTYPE:
 | 
						|
		if (argc > 4)
 | 
						|
			doifelse(argv, argc);
 | 
						|
		break;
 | 
						|
 | 
						|
	case IFDFTYPE:
 | 
						|
		/*
 | 
						|
		 * doifdef - select one of two alternatives based
 | 
						|
		 *	     on the existence of another definition
 | 
						|
		 */
 | 
						|
		if (argc > 3) {
 | 
						|
			if (lookup(argv[2]) != nil)
 | 
						|
				pbstr(argv[3]);
 | 
						|
			else if (argc > 4)
 | 
						|
				pbstr(argv[4]);
 | 
						|
		}
 | 
						|
		break;
 | 
						|
 | 
						|
	case LENGTYPE:
 | 
						|
		/*
 | 
						|
		 * dolen - find the length of the argument
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		if (argc > 2)
 | 
						|
			pbnum((argc > 2) ? strlen(argv[2]) : 0);
 | 
						|
		break;
 | 
						|
 | 
						|
	case INCRTYPE:
 | 
						|
		/*
 | 
						|
		 * doincr - increment the value of the argument
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		if (argc > 2)
 | 
						|
			pbnum(atoi(argv[2]) + 1);
 | 
						|
		break;
 | 
						|
 | 
						|
	case DECRTYPE:
 | 
						|
		/*
 | 
						|
		 * dodecr - decrement the value of the argument
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		if (argc > 2)
 | 
						|
			pbnum(atoi(argv[2]) - 1);
 | 
						|
		break;
 | 
						|
 | 
						|
#if unix || vms
 | 
						|
 | 
						|
	case SYSCTYPE:
 | 
						|
		/*
 | 
						|
		 * dosys - execute system command
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		if (argc > 2)
 | 
						|
			sysval = system(argv[2]);
 | 
						|
		break;
 | 
						|
 | 
						|
	case SYSVTYPE:
 | 
						|
		/*
 | 
						|
		 * dosysval - return value of the last system call.
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		pbnum(sysval);
 | 
						|
		break;
 | 
						|
#endif
 | 
						|
 | 
						|
	case INCLTYPE:
 | 
						|
		if (argc > 2)
 | 
						|
			if (!doincl(argv[2])) {
 | 
						|
				fprintf(stderr,"m4: %s: ",argv[2]);
 | 
						|
				error("cannot open for read.");
 | 
						|
			}
 | 
						|
		break;
 | 
						|
 | 
						|
	case SINCTYPE:
 | 
						|
		if (argc > 2)
 | 
						|
			(void) doincl(argv[2]);
 | 
						|
		break;
 | 
						|
#ifdef EXTENDED
 | 
						|
	case PASTTYPE:
 | 
						|
		if (argc > 2)
 | 
						|
			if (!dopaste(argv[2])) {
 | 
						|
				fprintf(stderr,"m4: %s: ",argv[2]);
 | 
						|
				error("cannot open for read.");
 | 
						|
			}
 | 
						|
		break;
 | 
						|
 | 
						|
	case SPASTYPE:
 | 
						|
		if (argc > 2)
 | 
						|
			(void) dopaste(argv[2]);
 | 
						|
		break;
 | 
						|
#endif
 | 
						|
	case CHNQTYPE:
 | 
						|
		dochq(argv, argc);
 | 
						|
		break;
 | 
						|
 | 
						|
	case CHNCTYPE:
 | 
						|
		dochc(argv, argc);
 | 
						|
		break;
 | 
						|
 | 
						|
	case SUBSTYPE:
 | 
						|
		/*
 | 
						|
		 * dosub - select substring
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		if (argc > 3)
 | 
						|
			dosub(argv,argc);
 | 
						|
		break;
 | 
						|
 | 
						|
	case SHIFTYPE:
 | 
						|
		/*
 | 
						|
		 * doshift - push back all arguments except the
 | 
						|
		 *	     first one (i.e. skip argv[2])
 | 
						|
		 */
 | 
						|
		if (argc > 3) {
 | 
						|
			for (n = argc-1; n > 3; n--) {
 | 
						|
				putback(rquote);
 | 
						|
				pbstr(argv[n]);
 | 
						|
				putback(lquote);
 | 
						|
				putback(',');
 | 
						|
			}
 | 
						|
			putback(rquote);
 | 
						|
			pbstr(argv[3]);
 | 
						|
			putback(lquote);
 | 
						|
		}
 | 
						|
		break;
 | 
						|
 | 
						|
	case DIVRTYPE:
 | 
						|
		if (argc > 2 && (n = atoi(argv[2])) != 0)
 | 
						|
			dodiv(n);
 | 
						|
		else {
 | 
						|
			active = stdout;
 | 
						|
			oindex = 0;
 | 
						|
		}
 | 
						|
		break;
 | 
						|
 | 
						|
	case UNDVTYPE:
 | 
						|
		doundiv(argv, argc);
 | 
						|
		break;
 | 
						|
 | 
						|
	case DIVNTYPE:
 | 
						|
		/*
 | 
						|
		 * dodivnum - return the number of current
 | 
						|
		 * output diversion
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		pbnum(oindex);
 | 
						|
		break;
 | 
						|
 | 
						|
	case UNDFTYPE:
 | 
						|
		/*
 | 
						|
		 * doundefine - undefine a previously defined
 | 
						|
		 *		macro(s) or m4 keyword(s).
 | 
						|
		 */
 | 
						|
		if (argc > 2)
 | 
						|
			for (n = 2; n < argc; n++)
 | 
						|
				remhash(argv[n], ALL);
 | 
						|
		break;
 | 
						|
 | 
						|
	case POPDTYPE:
 | 
						|
		/*
 | 
						|
		 * dopopdef - remove the topmost definitions of
 | 
						|
		 *	      macro(s) or m4 keyword(s).
 | 
						|
		 */
 | 
						|
		if (argc > 2)
 | 
						|
			for (n = 2; n < argc; n++)
 | 
						|
				remhash(argv[n], TOP);
 | 
						|
		break;
 | 
						|
 | 
						|
	case MKTMTYPE:
 | 
						|
		/*
 | 
						|
		 * dotemp - create a temporary file
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		if (argc > 2)
 | 
						|
			pbstr(mktemp(argv[2]));
 | 
						|
		break;
 | 
						|
 | 
						|
	case TRNLTYPE:
 | 
						|
		/*
 | 
						|
		 * dotranslit - replace all characters in the
 | 
						|
		 *		source string that appears in
 | 
						|
		 *		the "from" string with the corresponding
 | 
						|
		 *		characters in the "to" string.
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		if (argc > 3) {
 | 
						|
			char temp[MAXTOK];
 | 
						|
			if (argc > 4)
 | 
						|
				map(temp, argv[2], argv[3], argv[4]);
 | 
						|
			else
 | 
						|
				map(temp, argv[2], argv[3], null);
 | 
						|
			pbstr(temp);
 | 
						|
		}
 | 
						|
		else
 | 
						|
		    if (argc > 2)
 | 
						|
			pbstr(argv[2]);
 | 
						|
		break;
 | 
						|
 | 
						|
	case INDXTYPE:
 | 
						|
		/*
 | 
						|
		 * doindex - find the index of the second argument
 | 
						|
		 *	     string in the first argument string.
 | 
						|
		 *	     -1 if not present.
 | 
						|
		 */
 | 
						|
		pbnum((argc > 3) ? indx(argv[2], argv[3]) : -1);
 | 
						|
		break;
 | 
						|
 | 
						|
	case ERRPTYPE:
 | 
						|
		/*
 | 
						|
		 * doerrp - print the arguments to stderr file
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		if (argc > 2) {
 | 
						|
			for (n = 2; n < argc; n++)
 | 
						|
				fprintf(stderr,"%s ", argv[n]);
 | 
						|
			fprintf(stderr, "\n");
 | 
						|
		}
 | 
						|
		break;
 | 
						|
 | 
						|
	case DNLNTYPE:
 | 
						|
		/*
 | 
						|
		 * dodnl - eat-up-to and including newline
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		while ((c = gpbc()) != '\n' && c != EOF)
 | 
						|
			;
 | 
						|
		break;
 | 
						|
 | 
						|
	case M4WRTYPE:
 | 
						|
		/*
 | 
						|
		 * dom4wrap - set up for wrap-up/wind-down activity
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		m4wraps = (argc > 2) ? strsave(argv[2]) : null;
 | 
						|
		break;
 | 
						|
 | 
						|
	case EXITTYPE:
 | 
						|
		/*
 | 
						|
		 * doexit - immediate exit from m4.
 | 
						|
		 *
 | 
						|
		 */
 | 
						|
		exit((argc > 2) ? atoi(argv[2]) : 0);
 | 
						|
		break;
 | 
						|
 | 
						|
	case DEFNTYPE:
 | 
						|
		if (argc > 2)
 | 
						|
			for (n = 2; n < argc; n++)
 | 
						|
				dodefn(argv[n]);
 | 
						|
		break;
 | 
						|
 | 
						|
	default:
 | 
						|
		error("m4: major botch in eval.");
 | 
						|
		break;
 | 
						|
	}
 | 
						|
}
 |