Example #1
0
void
pbnumbase(int n, int base, int d)
{
	static char digits[36] = "0123456789abcdefghijklmnopqrstuvwxyz";
	int num;
	int printed = 0;

	if (base > 36)
		m4errx(1, "base %d > 36: not supported.", base);

	if (base < 2)
		m4errx(1, "bad base %d for conversion.", base);

	num = (n < 0) ? -n : n;
	do {
		pushback(digits[num % base]);
		printed++;
	}
	while ((num /= base) > 0);

	if (n < 0)
		printed++;
	while (printed++ < d)
		pushback('0');

	if (n < 0)
		pushback('-');
}
Example #2
0
void
doformat(const char *argv[], int argc)
{
	const char *format = argv[2];
	int pos = 3;
	int left_padded;
	long width;
	size_t l;
	const char *thisarg = NULL;
	char temp[2];
	long extra;

	while (*format != 0) {
		if (*format != '%') {
			addchar(*format++);
			continue;
		}

		format++;
		if (*format == '%') {
			addchar(*format++);
			continue;
		}
		if (*format == 0) {
			addchar('%');
			break;
		}

		if (*format == '*') {
			format++;
			if (pos >= argc)
				m4errx(1,
				    "Format with too many format specifiers.");
			width = strtol(argv[pos++], NULL, 10);
		} else {
			width = strtol(format, __DECONST(char **,&format), 10);
		}
		if (width < 0) {
			left_padded = 1;
			width = -width;
		} else {
			left_padded = 0;
		}
		if (*format == '.') {
			format++;
			if (*format == '*') {
				format++;
				if (pos >= argc)
					m4errx(1,
					    "Format with too many format specifiers.");
				extra = strtol(argv[pos++], NULL, 10);
			} else {
				extra = strtol(format, __DECONST(char **, &format), 10);
			}
		} else {
Example #3
0
/*
 * dopushdef - install a definition in the hash table
 *      without removing a previous definition. Since
 *      each new entry is entered in *front* of the
 *      hash bucket, it hides a previous definition from
 *      lookup.
 */
static void
dopushdef(const char *name, const char *defn)
{
	if (!*name && !mimic_gnu)
		m4errx(1, "null definition.");
	else
		macro_pushdef(name, defn);
}
Example #4
0
/*
 * dodefine - install definition in the table
 */
void
dodefine(const char *name, const char *defn)
{
	if (!*name && !mimic_gnu)
		m4errx(1, "null definition.");
	else
		macro_define(name, defn);
}
Example #5
0
static void
exit_regerror(int er, regex_t *re, const char *source)
{
	size_t	errlen;
	char	*errbuf;

	errlen = regerror(er, re, NULL, 0);
	errbuf = xalloc(errlen,
	    "malloc in regerror: %lu", (unsigned long)errlen);
	regerror(er, re, errbuf, errlen);
	m4errx(1, "regular expression error in %s: %s.", source, errbuf);
}
Example #6
0
void
dobuiltin(const char *argv[], int argc)
{
	ndptr p;

	argv[1] = NULL;
	p = macro_getbuiltin(argv[2]);
	if (p != NULL)
		eval(argv+1, argc-1, macro_builtin_type(p), is_traced(p));
	else
		m4errx(1, "unknown builtin %s.", argv[2]);
}
Example #7
0
/*
 * read in a diversion file, and dispose it.
 */
void
getdiv(int n)
{
	int c;

	if (active == outfile[n])
		m4errx(1, "undivert: diversion still active.");
	rewind(outfile[n]);
	while ((c = getc(outfile[n])) != EOF)
		putc(c, active);
	(void) fclose(outfile[n]);
	outfile[n] = NULL;
}
Example #8
0
void
doindir(const char *argv[], int argc)
{
	ndptr n;
	struct macro_definition *p;

	n = lookup(argv[2]);
	if (n == NULL || (p = macro_getdef(n)) == NULL)
		m4errx(1, "indir: undefined macro %s.", argv[2]);
	argv[1] = p->defn;

	eval(argv+1, argc-1, p->type, is_traced(n));
}
Example #9
0
/*
 * eval - eval all macros and builtins calls
 *	  argc - number of elements in argv.
 *	  argv - element vector :
 *			argv[0] = definition of a user
 *				  macro or NULL if built-in.
 *			argv[1] = name of the macro or
 *				  built-in.
 *			argv[2] = parameters to user-defined
 *			   .	  macro or built-in.
 *			   .
 *
 * A call in the form of macro-or-builtin() will result in:
 *			argv[0] = nullstr
 *			argv[1] = macro-or-builtin
 *			argv[2] = nullstr
 *
 * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin
 */
void
eval(const char *argv[], int argc, int td, int is_traced)
{
	size_t mark = SIZE_MAX;

	expansion_id++;
	if (td & RECDEF)
		m4errx(1, "expanding recursive definition for %s.", argv[1]);
	if (is_traced)
		mark = trace(argv, argc, infile+ilevel);
	if (td == MACRTYPE)
		expand_macro(argv, argc);
	else
		expand_builtin(argv, argc, td);
	if (mark != SIZE_MAX)
		finish_trace(mark);
}
Example #10
0
/*
 * expand_builtin - evaluate built-in macros.
 */
void
expand_builtin(const char *argv[], int argc, int td)
{
	int c, n;
	int ac;
	static int sysval = 0;

#ifdef DEBUG
	printf("argc = %d\n", argc);
	for (n = 0; n < argc; n++)
		printf("argv[%d] = %s\n", n, argv[n]);
	fflush(stdout);
#endif

 /*
  * if argc == 3 and argv[2] is null, then we
  * have macro-or-builtin() type call. We adjust
  * argc to avoid further checking..
  */
 /* we keep the initial value for those built-ins that differentiate
  * between builtin() and builtin.
  */
	ac = argc;

	if (argc == 3 && !*(argv[2]) && !mimic_gnu)
		argc--;

	switch (td & TYPEMASK) {

	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 TRACEONTYPE:
		dotrace(argv, argc, 1);
		break;

	case TRACEOFFTYPE:
		dotrace(argv, argc, 0);
		break;

	case EXPRTYPE:
	/*
	 * doexpr - evaluate arithmetic
	 * expression
	 */
	{
		int base = 10;
		int maxdigits = 0;
		const char *errstr;

		if (argc > 3) {
			base = strtonum(argv[3], 2, 36, &errstr);
			if (errstr) {
				m4errx(1, "expr: base %s invalid.", argv[3]);
			}
		}
		if (argc > 4) {
			maxdigits = strtonum(argv[4], 0, INT_MAX, &errstr);
			if (errstr) {
				m4errx(1, "expr: maxdigits %s invalid.", argv[4]);
			}
		}
		if (argc > 2)
			pbnumbase(expr(argv[2]), base, maxdigits);
		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_macro_definition(argv[2]) != NULL)
				pbstr(argv[3]);
			else if (argc > 4)
				pbstr(argv[4]);
		}
		break;

	case LENGTYPE:
	/*
	 * dolen - find the length of the
	 * argument
	 */
		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;

	case SYSCTYPE:
	/*
	 * dosys - execute system command
	 */
		if (argc > 2) {
			fflush(stdout);
			sysval = system(argv[2]);
		}
		break;

	case SYSVTYPE:
	/*
	 * dosysval - return value of the last
	 * system call.
	 *
	 */
		pbnum(sysval);
		break;

	case ESYSCMDTYPE:
		if (argc > 2)
			doesyscmd(argv[2]);
		break;
	case INCLTYPE:
		if (argc > 2)
			if (!doincl(argv[2])) {
				if (mimic_gnu) {
					warn("%s at line %lu: include(%s)",
					    CURRENT_NAME, CURRENT_LINE, argv[2]);
					exit_code = 1;
				} else
					err(1, "%s at line %lu: include(%s)",
					    CURRENT_NAME, CURRENT_LINE, argv[2]);
			}
		break;

	case SINCTYPE:
		if (argc > 2)
			(void) doincl(argv[2]);
		break;
#ifdef EXTENDED
	case PASTTYPE:
		if (argc > 2)
			if (!dopaste(argv[2]))
				err(1, "%s at line %lu: paste(%s)", 
				    CURRENT_NAME, CURRENT_LINE, argv[2]);
		break;

	case SPASTYPE:
		if (argc > 2)
			(void) dopaste(argv[2]);
		break;
	case FORMATTYPE:
		doformat(argv, argc);
		break;
#endif
	case CHNQTYPE:
		dochq(argv, ac);
		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--) {
				pbstr(rquote);
				pbstr(argv[n]);
				pbstr(lquote);
				pushback(COMMA);
			}
			pbstr(rquote);
			pbstr(argv[3]);
			pbstr(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++)
				macro_undefine(argv[n]);
		break;

	case POPDTYPE:
	/*
	 * dopopdef - remove the topmost
	 * definitions of macro(s) or m4
	 * keyword(s).
	 */
		if (argc > 2)
			for (n = 2; n < argc; n++)
				macro_popdef(argv[n]);
		break;

	case MKTMTYPE:
	/*
	 * dotemp - create a temporary file
	 */
		if (argc > 2) {
			int fd;
			char *temp;

			temp = xstrdup(argv[2]);

			fd = mkstemp(temp);
			if (fd == -1)
				err(1,
	    "%s at line %lu: couldn't make temp file %s",
	    CURRENT_NAME, CURRENT_LINE, argv[2]);
			close(fd);
			pbstr(temp);
			free(temp);
		}
		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;

			temp = xalloc(strlen(argv[2])+1, NULL);
			if (argc > 4)
				map(temp, argv[2], argv[3], argv[4]);
			else
				map(temp, argv[2], argv[3], null);
			pbstr(temp);
			free(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
	 */
		if (argc > 2)
			dom4wrap(argv[2]);
		break;

	case EXITTYPE:
	/*
	 * doexit - immediate exit from m4.
	 */
		killdiv();
		exit((argc > 2) ? atoi(argv[2]) : 0);
		break;

	case DEFNTYPE:
		if (argc > 2)
			for (n = 2; n < argc; n++)
				dodefn(argv[n]);
		break;

	case INDIRTYPE:	/* Indirect call */
		if (argc > 2)
			doindir(argv, argc);
		break;

	case BUILTINTYPE: /* Builtins only */
		if (argc > 2)
			dobuiltin(argv, argc);
		break;

	case PATSTYPE:
		if (argc > 2)
			dopatsubst(argv, argc);
		break;
	case REGEXPTYPE:
		if (argc > 2)
			doregexp(argv, argc);
		break;
	case LINETYPE:
		doprintlineno(infile+ilevel);
		break;
	case FILENAMETYPE:
		doprintfilename(infile+ilevel);
		break;
	case SELFTYPE:
		pbstr(rquote);
		pbstr(argv[1]);
		pbstr(lquote);
		break;
	default:
		m4errx(1, "eval: major botch.");
		break;
	}
}
Example #11
0
void
doformat(const char *argv[], int argc)
{
	const char *format = argv[2];
	int pos = 3;
	int left_padded;
	long width;
	size_t l;
	const char *thisarg;
	char temp[2];
	long extra;

	while (*format != 0) {
		if (*format != '%') {
			addchar(*format++);
			continue;
		}

		format++;
		if (*format == '%') {
			addchar(*format++);
			continue;
		}
		if (*format == 0) {
			addchar('%');
			break;
		}

		if (*format == '*') {
			format++;
			if (pos >= argc)
				m4errx(1,
				    "Format with too many format specifiers.");
			width = strtol(argv[pos++], NULL, 10);
		} else {
			width = strtol(format, (char **)&format, 10);
		}
		if (width < 0) {
			left_padded = 1;
			width = -width;
		} else {
			left_padded = 0;
		}
		if (*format == '.') {
			format++;
			if (*format == '*') {
				format++;
				if (pos >= argc)
					m4errx(1,
					    "Format with too many format specifiers.");
				extra = strtol(argv[pos++], NULL, 10);
			} else {
				extra = strtol(format, (char **)&format, 10);
			}
		} else {
			extra = LONG_MAX;
		}
		if (pos >= argc)
			m4errx(1, "Format with too many format specifiers.");
		switch(*format) {
		case 's':
			thisarg = argv[pos++];
			break;
		case 'c':
			temp[0] = strtoul(argv[pos++], NULL, 10);
			temp[1] = 0;
			thisarg = temp;
			break;
		default:
			m4errx(1, "Unsupported format specification: %s.",
			    argv[2]);
		}
		format++;
		l = strlen(thisarg);
		if (l > extra)
			l = extra;
		if (!left_padded) {
			while (l < width--)
				addchar(' ');
		}
		addchars(thisarg, l);
		if (left_padded) {
			while (l < width--)
				addchar(' ');
		}
	}
	pbstr(getstring());
}