plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

input.c (5436B)


      1 #include "e.h"
      2 #include "y.tab.h"
      3 #include <ctype.h>
      4 
      5 Infile	infile[10];
      6 Infile	*curfile = infile;
      7 
      8 #define	MAXSRC	50
      9 Src	src[MAXSRC];	/* input source stack */
     10 Src	*srcp	= src;
     11 
     12 extern int getarg(char *);
     13 extern	void eprint(void);
     14 
     15 void pushsrc(int type, char *ptr)	/* new input source */
     16 {
     17 	if (++srcp >= src + MAXSRC)
     18 		ERROR "inputs nested too deep" FATAL;
     19 	srcp->type = type;
     20 	srcp->sp = ptr;
     21 	if (dbg > 1) {
     22 		printf("\n%3ld ", (long)(srcp - src));
     23 		switch (srcp->type) {
     24 		case File:
     25 			printf("push file %s\n", ((Infile *)ptr)->fname);
     26 			break;
     27 		case Macro:
     28 			printf("push macro <%s>\n", ptr);
     29 			break;
     30 		case Char:
     31 			printf("push char <%c>\n", *ptr);
     32 			break;
     33 		case String:
     34 			printf("push string <%s>\n", ptr);
     35 			break;
     36 		case Free:
     37 			printf("push free <%s>\n", ptr);
     38 			break;
     39 		default:
     40 			ERROR "pushed bad type %d\n", srcp->type FATAL;
     41 		}
     42 	}
     43 }
     44 
     45 void popsrc(void)	/* restore an old one */
     46 {
     47 	if (srcp <= src)
     48 		ERROR "too many inputs popped" FATAL;
     49 	if (dbg > 1) {
     50 		printf("%3ld ", (long)(srcp - src));
     51 		switch (srcp->type) {
     52 		case File:
     53 			printf("pop file\n");
     54 			break;
     55 		case Macro:
     56 			printf("pop macro\n");
     57 			break;
     58 		case Char:
     59 			printf("pop char <%c>\n", *srcp->sp);
     60 			break;
     61 		case String:
     62 			printf("pop string\n");
     63 			break;
     64 		case Free:
     65 			printf("pop free\n");
     66 			break;
     67 		default:
     68 			ERROR "pop weird input %d\n", srcp->type FATAL;
     69 		}
     70 	}
     71 	srcp--;
     72 }
     73 
     74 Arg	args[10];	/* argument frames */
     75 Arg	*argfp = args;	/* frame pointer */
     76 int	argcnt;		/* number of arguments seen so far */
     77 
     78 void dodef(tbl *stp)	/* collect args and switch input to defn */
     79 {
     80 	int i, len;
     81 	char *p;
     82 	Arg *ap;
     83 
     84 	ap = argfp+1;
     85 	if (ap >= args+10)
     86 		ERROR "more than arguments\n" FATAL;
     87 	argcnt = 0;
     88 	if (input() != '(')
     89 		ERROR "disaster in dodef\n"FATAL;
     90 	if (ap->argval == 0)
     91 		ap->argval = malloc(1000);
     92 	for (p = ap->argval; (len = getarg(p)) != -1; p += len) {
     93 		ap->argstk[argcnt++] = p;
     94 		if (input() == ')')
     95 			break;
     96 	}
     97 	for (i = argcnt; i < MAXARGS; i++)
     98 		ap->argstk[i] = "";
     99 	if (dbg)
    100 		for (i = 0; i < argcnt; i++)
    101 			printf("arg %ld.%d = <%s>\n", (long)(ap-args), i+1, ap->argstk[i]);
    102 	argfp = ap;
    103 	pushsrc(Macro, stp->cval);
    104 }
    105 
    106 int
    107 getarg(char *p)	/* pick up single argument, store in p, return length */
    108 {
    109 	int n, c, npar;
    110 
    111 	n = npar = 0;
    112 	for ( ;; ) {
    113 		c = input();
    114 		if (c == EOF)
    115 			ERROR "end of file in getarg!\n" FATAL;
    116 		if (npar == 0 && (c == ',' || c == ')'))
    117 			break;
    118 		if (c == '"')	/* copy quoted stuff intact */
    119 			do {
    120 				*p++ = c;
    121 				n++;
    122 			} while ((c = input()) != '"' && c != EOF);
    123 		else if (c == '(')
    124 			npar++;
    125 		else if (c == ')')
    126 			npar--;
    127 		n++;
    128 		*p++ = c;
    129 	}
    130 	*p = 0;
    131 	unput(c);
    132 	return(n + 1);
    133 }
    134 
    135 #define	PBSIZE	2000
    136 char	pbuf[PBSIZE];		/* pushback buffer */
    137 char	*pb	= pbuf-1;	/* next pushed back character */
    138 
    139 char	ebuf[200];		/* collect input here for error reporting */
    140 char	*ep	= ebuf;
    141 
    142 int
    143 input(void)
    144 {
    145 	register int c = 0;
    146 
    147   loop:
    148 	switch (srcp->type) {
    149 	case File:
    150 		c = getc(curfile->fin);
    151 		if (c == EOF) {
    152 			if (curfile == infile)
    153 				break;
    154 			if (curfile->fin != stdin) {
    155 				fclose(curfile->fin);
    156 				free(curfile->fname);	/* assumes allocated */
    157 			}
    158 			curfile--;
    159 			printf(".lf %d %s\n", curfile->lineno, curfile->fname);
    160 			popsrc();
    161 			goto loop;
    162 		}
    163 		if (c == '\n')
    164 			curfile->lineno++;
    165 		break;
    166 	case Char:
    167 		if (pb >= pbuf) {
    168 			c = *pb--;
    169 			popsrc();
    170 			break;
    171 		} else {	/* can't happen? */
    172 			popsrc();
    173 			goto loop;
    174 		}
    175 	case String:
    176 		c = *srcp->sp++;
    177 		if (c == '\0') {
    178 			popsrc();
    179 			goto loop;
    180 		} else {
    181 			if (*srcp->sp == '\0')	/* empty, so pop */
    182 				popsrc();
    183 			break;
    184 		}
    185 	case Macro:
    186 		c = *srcp->sp++;
    187 		if (c == '\0') {
    188 			if (--argfp < args)
    189 				ERROR "argfp underflow" FATAL;
    190 			popsrc();
    191 			goto loop;
    192 		} else if (c == '$' && isdigit((unsigned char)*srcp->sp)) {
    193 			int n = 0;
    194 			while (isdigit((unsigned char)*srcp->sp))
    195 				n = 10 * n + *srcp->sp++ - '0';
    196 			if (n > 0 && n <= MAXARGS)
    197 				pushsrc(String, argfp->argstk[n-1]);
    198 			goto loop;
    199 		}
    200 		break;
    201 	case Free:	/* free string */
    202 		free(srcp->sp);
    203 		popsrc();
    204 		goto loop;
    205 	}
    206 	if (ep >= ebuf + sizeof ebuf)
    207 		ep = ebuf;
    208 	*ep++ = c;
    209 	return c;
    210 }
    211 
    212 int
    213 unput(int c)
    214 {
    215 	if (++pb >= pbuf + sizeof pbuf)
    216 		ERROR "pushback overflow\n"FATAL;
    217 	if (--ep < ebuf)
    218 		ep = ebuf + sizeof(ebuf) - 1;
    219 	*pb = c;
    220 	pushsrc(Char, pb);
    221 	return c;
    222 }
    223 
    224 void pbstr(char *s)
    225 {
    226 	pushsrc(String, s);
    227 }
    228 
    229 void error(int die, char *s)
    230 {
    231 	extern char *cmdname;
    232 
    233 	if (synerr)
    234 		return;
    235 	fprintf(stderr, "%s: %s", cmdname, s);
    236 	if (errno > 0)
    237 		perror("???");
    238 	if (curfile->fin)
    239 		fprintf(stderr, " near %s:%d",
    240 			curfile->fname, curfile->lineno+1);
    241 	fprintf(stderr, "\n");
    242 	eprint();
    243 	synerr = 1;
    244 	errno = 0;
    245 	if (die) {
    246 		if (dbg)
    247 			abort();
    248 		else
    249 			exit(1);
    250 	}
    251 }
    252 
    253 void yyerror(char *s)
    254 {
    255 	error(0, s);	/* temporary */
    256 }
    257 
    258 char errbuf[2000];
    259 
    260 void eprint(void)	/* try to print context around error */
    261 {
    262 	char *p, *q;
    263 
    264 	if (ep == ebuf)
    265 		return;				/* no context */
    266 	p = ep - 1;
    267 	if (p > ebuf && *p == '\n')
    268 		p--;
    269 	for ( ; p >= ebuf && *p != '\n'; p--)
    270 		;
    271 	while (*p == '\n')
    272 		p++;
    273 	fprintf(stderr, " context is\n\t");
    274 	for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
    275 		;
    276 	while (p < q)
    277 		putc(*p++, stderr);
    278 	fprintf(stderr, " >>> ");
    279 	while (p < ep)
    280 		putc(*p++, stderr);
    281 	fprintf(stderr, " <<< ");
    282 	while (pb >= pbuf)
    283 		putc(*pb--, stderr);
    284 	if (curfile->fin)
    285 		fgets(ebuf, sizeof ebuf, curfile->fin);
    286 	fprintf(stderr, "%s", ebuf);
    287 	pbstr("\n.EN\n");	/* safety first */
    288 	ep = ebuf;
    289 }