293 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			293 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * misc.c
 | |
|  * Facility: m4 macro processor
 | |
|  * by: oz
 | |
|  */
 | |
|  
 | |
| #include "mdef.h"
 | |
| #include "extr.h" 
 | |
|  
 | |
| /*
 | |
|  * indx - find the index of second str in the
 | |
|  *        first str.
 | |
|  */
 | |
| int indx(s1, s2)
 | |
| char *s1;
 | |
| char *s2;
 | |
| {
 | |
|         register char *t;
 | |
|         register char *p;
 | |
|         register char *m;
 | |
|  
 | |
|         for (p = s1; *p; p++) {
 | |
|                 for (t = p, m = s2; *m && *m == *t; m++, t++)
 | |
|                         ;
 | |
|                 if (!*m)
 | |
|                         return(p - s1);
 | |
|         }
 | |
|         return (-1);
 | |
| }
 | |
|  
 | |
| /*
 | |
|  *  putback - push character back onto input
 | |
|  *
 | |
|  */
 | |
| void putback (c)
 | |
| char c;
 | |
| {
 | |
|         if (bp < endpbb)
 | |
|                 *bp++ = c;
 | |
|         else
 | |
|                 error("m4: too many characters pushed back");
 | |
| }
 | |
|  
 | |
| /*
 | |
|  *  pbstr - push string back onto input
 | |
|  *          putback is replicated to improve
 | |
|  *          performance.
 | |
|  *
 | |
|  */
 | |
| void pbstr(s)
 | |
| register char *s;
 | |
| {
 | |
|         register char *es;
 | |
| 	register char *zp;
 | |
| 
 | |
| 	es = s;
 | |
| 	zp = bp;
 | |
| 
 | |
|         while (*es)
 | |
|                 es++;
 | |
|         es--;
 | |
|         while (es >= s)
 | |
|                 if (zp < endpbb)
 | |
|                         *zp++ = *es--;
 | |
|         if ((bp = zp) == endpbb)
 | |
|                 error("m4: too many characters pushed back");
 | |
| }
 | |
|  
 | |
| /*
 | |
|  *  pbnum - convert number to string, push back on input.
 | |
|  *
 | |
|  */
 | |
| void pbnum (n)
 | |
| int n;
 | |
| {
 | |
|         register int num;
 | |
|  
 | |
|         num = (n < 0) ? -n : n;
 | |
|         do {
 | |
|                 putback(num % 10 + '0');
 | |
|         }
 | |
|         while ((num /= 10) > 0);
 | |
| 
 | |
|         if (n < 0) putback('-');
 | |
| }
 | |
|  
 | |
| /*
 | |
|  *  chrsave - put single char on string space
 | |
|  *
 | |
|  */
 | |
| void chrsave (c)
 | |
| char c;
 | |
| {
 | |
| /***        if (sp < 0)
 | |
|                 putc(c, active);
 | |
|         else ***/ if (ep < endest)
 | |
|                 *ep++ = c;
 | |
|         else
 | |
|                 error("m4: string space overflow");
 | |
| }
 | |
|  
 | |
| /*
 | |
|  * getdiv - read in a diversion file, and
 | |
|  *          trash it.
 | |
|  */
 | |
| void getdiv(ind)
 | |
| int ind;
 | |
| {
 | |
|         register int c;
 | |
|         register FILE *dfil;
 | |
|  
 | |
|         if (active == outfile[ind])
 | |
|                 error("m4: undivert: diversion still active.");
 | |
|         (void) fclose(outfile[ind]);
 | |
|         outfile[ind] = NULL;
 | |
|         m4temp[UNIQUE] = ind + '0';
 | |
|         if ((dfil = fopen(m4temp, "r")) == NULL)
 | |
|                 error("m4: cannot undivert.");
 | |
|         else
 | |
|                 while((c = getc(dfil)) != EOF)
 | |
|                         putc(c, active);
 | |
|         (void) fclose(dfil);
 | |
| 
 | |
| #if vms
 | |
|         if (remove(m4temp))
 | |
| #else
 | |
| 	if (unlink(m4temp) == -1)
 | |
| #endif
 | |
|                 error("m4: cannot unlink.");
 | |
| }
 | |
|  
 | |
| /*
 | |
|  * Very fatal error. Close all files
 | |
|  * and die hard.
 | |
|  */
 | |
| void error(s)
 | |
| char *s;
 | |
| {
 | |
|         killdiv();
 | |
|         fprintf(stderr,"%s\n",s);
 | |
|         exit(1);
 | |
| }
 | |
|  
 | |
| /*
 | |
|  * Interrupt handling
 | |
|  */
 | |
| static char *msg = "\ninterrupted.";
 | |
|  
 | |
| void onintr(s) 
 | |
| int s;				/* ANSI requires the parameter */
 | |
| {
 | |
|         error(msg);
 | |
| }
 | |
|  
 | |
| /*
 | |
|  * killdiv - get rid of the diversion files
 | |
|  *
 | |
|  */
 | |
| void killdiv() {
 | |
|         register int n;
 | |
|  
 | |
|         for (n = 0; n < MAXOUT; n++)
 | |
|                 if (outfile[n] != NULL) {
 | |
|                         (void) fclose (outfile[n]);
 | |
|                         m4temp[UNIQUE] = n + '0';
 | |
| #if vms
 | |
| 			(void) remove (m4temp);
 | |
| #else
 | |
|                         (void) unlink (m4temp);
 | |
| #endif
 | |
|                 }
 | |
| }
 | |
|  
 | |
| /*
 | |
|  * save a string somewhere..
 | |
|  *
 | |
|  */
 | |
| char *strsave(s)
 | |
| char *s;
 | |
| {
 | |
| 	register int n;
 | |
|         char *p;
 | |
| 
 | |
| 	n = strlen(s)+1;
 | |
| 	p = (char *) malloc(n);
 | |
|         if (p != NULL) (void) memcpy(p, s, n);
 | |
|         return (p);
 | |
| }
 | |
|  
 | |
| void usage() {
 | |
|         fprintf(stderr, "Usage: m4 [-Dname[=val]] [-Uname]\n");
 | |
|         exit(1);
 | |
| }
 | |
| 
 | |
| #ifdef GETOPT
 | |
| /*
 | |
|  * H. Spencer getopt - get option letter from argv
 | |
|  * 
 | |
|  *
 | |
| #include <stdio.h>
 | |
|  *
 | |
|  */
 | |
| 
 | |
| char	*optarg;	/* Global argument pointer. */
 | |
| int	optind = 0;	/* Global argv index. */
 | |
| 
 | |
| static char	*scan = NULL;	/* Private scan pointer. */
 | |
| 
 | |
| int
 | |
| getopt(argc, argv, optstring)
 | |
| int argc;
 | |
| char *argv[];
 | |
| char *optstring;
 | |
| {
 | |
| 	register char c;
 | |
| 	register char *place;
 | |
| 
 | |
| 	optarg = NULL;
 | |
| 
 | |
| 	if (scan == NULL || *scan == '\0') {
 | |
| 		if (optind == 0)
 | |
| 			optind++;
 | |
| 	
 | |
| 		if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
 | |
| 			return(EOF);
 | |
| 		if (strcmp(argv[optind], "--")==0) {
 | |
| 			optind++;
 | |
| 			return(EOF);
 | |
| 		}
 | |
| 	
 | |
| 		scan = argv[optind]+1;
 | |
| 		optind++;
 | |
| 	}
 | |
| 
 | |
| 	c = *scan++;
 | |
| 	place = index(optstring, c);
 | |
| 
 | |
| 	if (place == NULL || c == ':') {
 | |
| 		fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
 | |
| 		return('?');
 | |
| 	}
 | |
| 
 | |
| 	place++;
 | |
| 	if (*place == ':') {
 | |
| 		if (*scan != '\0') {
 | |
| 			optarg = scan;
 | |
| 			scan = NULL;
 | |
| 		} else {
 | |
| 			optarg = argv[optind];
 | |
| 			optind++;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return(c);
 | |
| }
 | |
|    
 | |
| #endif
 | |
| 
 | |
| #ifdef DUFFCP
 | |
| /*
 | |
|  * This code uses Duff's Device (tm Tom Duff)
 | |
|  * to unroll the copying loop:
 | |
|  * while (count-- > 0)
 | |
|  *	*to++ = *from++;
 | |
|  */
 | |
| 
 | |
| #define COPYBYTE 	*to++ = *from++
 | |
| 
 | |
| void memcpy(to, from, count)
 | |
| register char *from, *to;
 | |
| register int count;
 | |
| {
 | |
| 	if (count > 0) {
 | |
| 		register int loops = (count+8-1) >> 3;	/* div 8 round up */
 | |
| 
 | |
| 		switch (count&(8-1)) {			/* mod 8 */
 | |
| 		case 0: do {
 | |
| 			COPYBYTE;
 | |
| 		case 7:	COPYBYTE;
 | |
| 		case 6:	COPYBYTE;
 | |
| 		case 5:	COPYBYTE;
 | |
| 		case 4:	COPYBYTE;
 | |
| 		case 3:	COPYBYTE;
 | |
| 		case 2:	COPYBYTE;
 | |
| 		case 1:	COPYBYTE;
 | |
| 			} while (--loops > 0);
 | |
| 		}
 | |
| 
 | |
| 	}
 | |
| }
 | |
| 
 | |
| #endif
 | 
