150 lines · 2.6 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */  #include <u.h>#include <libc.h>#include <bio.h>#include "String.h" struct Sinstack{	int	depth;	Biobuf	*fp[32];	/* hard limit to avoid infinite recursion */}; /* initialize */extern Sinstack *s_allocinstack(char *file){	Sinstack *sp;	Biobuf *fp; 	fp = Bopen(file, OREAD);	if(fp == nil)		return nil; 	sp = malloc(sizeof *sp);	sp->depth = 0;	sp->fp[0] = fp;	return sp;} extern voids_freeinstack(Sinstack *sp){	while(sp->depth >= 0)		Bterm(sp->fp[sp->depth--]);	free(sp);} /*  Append an input line to a String. * *  Empty lines and leading whitespace are removed. */static char *rdline(Biobuf *fp, String *to){	int c;	int len = 0; 	c = Bgetc(fp); 	/* eat leading white */	while(c==' ' || c=='\t' || c=='\n' || c=='\r')		c = Bgetc(fp); 	if(c < 0)		return 0; 	for(;;){		switch(c) {		case -1:			goto out;		case '\\':			c = Bgetc(fp);			if (c != '\n') {				s_putc(to, '\\');				s_putc(to, c);				len += 2;			}			break;		case '\r':			break;		case '\n':			if(len != 0)				goto out;			break;		default:			s_putc(to, c);			len++;			break;		}		c = Bgetc(fp);	}out:	s_terminate(to);	return to->ptr - len;} /* Append an input line to a String. * * Returns a pointer to the character string (or 0). * Leading whitespace and newlines are removed. * Lines starting with #include cause us to descend into the new file. * Empty lines and other lines starting with '#' are ignored. */ extern char *s_rdinstack(Sinstack *sp, String *to){	char *p;	Biobuf *fp, *nfp; 	s_terminate(to);	fp = sp->fp[sp->depth]; 	for(;;){		p = rdline(fp, to);		if(p == nil){			if(sp->depth == 0)				break;			Bterm(fp);			sp->depth--;			return s_rdinstack(sp, to);		} 		if(strncmp(p, "#include", 8) == 0 && (p[8] == ' ' || p[8] == '\t')){			to->ptr = p;			p += 8; 			/* sanity (and looping) */			if(sp->depth >= nelem(sp->fp))				sysfatal("s_recgetline: includes too deep"); 			/* skip white */			while(*p == ' ' || *p == '\t')				p++; 			nfp = Bopen(p, OREAD);			if(nfp == nil)				continue;			sp->depth++;			sp->fp[sp->depth] = nfp;			return s_rdinstack(sp, to);		} 		/* got milk? */		if(*p != '#')			break; 		/* take care of comments */		to->ptr = p;		s_terminate(to);	}	return p;}