| char rcsid_lex[] = "$Id$"; | 
 |  | 
 | #include <ctype.h> | 
 | #include <stdio.h> | 
 | #include <string.h> | 
 | #include "b.h" | 
 | #include "fe.h" | 
 | #include "gram.tab.h" | 
 |  | 
 | static char buf[BUFSIZ]; | 
 |  | 
 | static int yyline = 1; | 
 |  | 
 | typedef int (*ReadFn) ARGS((void)); | 
 |  | 
 | static char *StrCopy ARGS((char *)); | 
 | static int code_get ARGS((void)); | 
 | static int simple_get ARGS((void)); | 
 | static void ReadCharString ARGS((ReadFn, int)); | 
 | static void ReadCodeBlock ARGS((void)); | 
 | static void ReadOldComment ARGS((ReadFn)); | 
 |  | 
 | static char * | 
 | StrCopy(s) char *s; | 
 | { | 
 | 	char *t = (char *)zalloc(strlen(s) + 1); | 
 | 	strcpy(t,s); | 
 | 	return t; | 
 | } | 
 |  | 
 | static int | 
 | simple_get() | 
 | { | 
 | 	int ch; | 
 | 	if ((ch = getchar()) == '\n') { | 
 | 		yyline++; | 
 | 	} | 
 | 	return ch; | 
 | } | 
 |  | 
 | static int | 
 | code_get() | 
 | { | 
 | 	int ch; | 
 | 	if ((ch = getchar()) == '\n') { | 
 | 		yyline++; | 
 | 	} | 
 | 	if (ch != EOF) { | 
 | 		fputc(ch, outfile); | 
 | 	} | 
 | 	return ch; | 
 | } | 
 |  | 
 | void | 
 | yypurge() | 
 | { | 
 | 	while (code_get() != EOF) ; | 
 | } | 
 |  | 
 |  | 
 | static void | 
 | ReadCharString(rdfn, which) ReadFn rdfn; int which; | 
 | { | 
 | 	int ch; | 
 | 	int backslash = 0; | 
 | 	int firstline = yyline; | 
 |  | 
 | 	while ((ch = rdfn()) != EOF) { | 
 | 		if (ch == which && !backslash) { | 
 | 			return; | 
 | 		} | 
 | 		if (ch == '\\' && !backslash) { | 
 | 			backslash = 1; | 
 | 		} else { | 
 | 			backslash = 0; | 
 | 		} | 
 | 	} | 
 | 	yyerror1("Unexpected EOF in string on line "); | 
 | 	fprintf(stderr, "%d\n", firstline); | 
 | 	exit(1); | 
 | } | 
 |  | 
 | static void | 
 | ReadOldComment(rdfn) ReadFn rdfn; | 
 | { | 
 | 	/* will not work for comments delimiter in string */ | 
 |  | 
 | 	int ch; | 
 | 	int starred = 0; | 
 | 	int firstline = yyline; | 
 |  | 
 | 	while ((ch = rdfn()) != EOF) { | 
 | 		if (ch == '*') { | 
 | 			starred = 1; | 
 | 		} else if (ch == '/' && starred) { | 
 | 			return; | 
 | 		} else { | 
 | 			starred = 0; | 
 | 		} | 
 | 	} | 
 | 	yyerror1("Unexpected EOF in comment on line "); | 
 | 	fprintf(stderr, "%d\n", firstline); | 
 | 	exit(1); | 
 | } | 
 |  | 
 | static void | 
 | ReadCodeBlock() | 
 | { | 
 | 	int ch; | 
 | 	int firstline = yyline; | 
 |  | 
 | 	while ((ch = getchar()) != EOF) { | 
 | 		if (ch == '%') { | 
 | 			ch = getchar(); | 
 | 			if (ch != '}') { | 
 | 				yyerror("bad %%"); | 
 | 			} | 
 | 			return; | 
 | 		} | 
 | 		fputc(ch, outfile); | 
 | 		if (ch == '\n') { | 
 | 			yyline++; | 
 | 		} | 
 | 		if (ch == '"' || ch == '\'') { | 
 | 			ReadCharString(code_get, ch); | 
 | 		} else if (ch == '/') { | 
 | 			ch = getchar(); | 
 | 			if (ch == '*') { | 
 | 				fputc(ch, outfile); | 
 | 				ReadOldComment(code_get); | 
 | 				continue; | 
 | 			} else { | 
 | 				ungetc(ch, stdin); | 
 | 			} | 
 | 		} | 
 | 	} | 
 | 	yyerror1("Unclosed block of C code started on line "); | 
 | 	fprintf(stderr, "%d\n", firstline); | 
 | 	exit(1); | 
 | } | 
 |  | 
 | static int done; | 
 | void | 
 | yyfinished() | 
 | { | 
 | 	done = 1; | 
 | } | 
 |  | 
 | int | 
 | yylex() | 
 | { | 
 | 	int ch; | 
 | 	char *ptr = buf; | 
 |  | 
 | 	if (done) return 0; | 
 | 	while ((ch = getchar()) != EOF) { | 
 | 		switch (ch) { | 
 | 		case ' ': | 
 | 		case '\f': | 
 | 		case '\t': | 
 | 			continue; | 
 | 		case '\n': | 
 | 			yyline++; | 
 | 			continue; | 
 | 		case '(': | 
 | 		case ')': | 
 | 		case ',': | 
 | 		case ':': | 
 | 		case ';': | 
 | 		case '=': | 
 | 			return(ch); | 
 | 		case '/': | 
 | 			ch = getchar(); | 
 | 			if (ch == '*') { | 
 | 				ReadOldComment(simple_get); | 
 | 				continue; | 
 | 			} else { | 
 | 				ungetc(ch, stdin); | 
 | 				yyerror("illegal char /"); | 
 | 				continue; | 
 | 			} | 
 | 		case '%': | 
 | 			ch = getchar(); | 
 | 			switch (ch) { | 
 | 			case '%': | 
 | 				return (K_PPERCENT); | 
 | 			case '{': | 
 | 				ReadCodeBlock(); | 
 | 				continue; | 
 | 			case 's': | 
 | 			case 'g': | 
 | 			case 't': | 
 | 				do { | 
 | 					if (ptr >= &buf[BUFSIZ]) { | 
 | 						yyerror("ID too long"); | 
 | 						return(ERROR); | 
 | 					} else { | 
 | 						*ptr++ = ch; | 
 | 					} | 
 | 					ch = getchar(); | 
 | 				} while (isalpha(ch) || isdigit(ch) || ch == '_'); | 
 | 				ungetc(ch, stdin); | 
 | 				*ptr = '\0'; | 
 | 				if (!strcmp(buf, "term")) return K_TERM; | 
 | 				if (!strcmp(buf, "start")) return K_START; | 
 | 				if (!strcmp(buf, "gram")) return K_GRAM; | 
 | 				yyerror("illegal character after %%"); | 
 | 				continue; | 
 | 			default: | 
 | 				yyerror("illegal character after %%"); | 
 | 				continue; | 
 | 			} | 
 | 		default: | 
 | 			if (isalpha(ch) ) { | 
 | 				do { | 
 | 					if (ptr >= &buf[BUFSIZ]) { | 
 | 						yyerror("ID too long"); | 
 | 						return(ERROR); | 
 | 					} else { | 
 | 						*ptr++ = ch; | 
 | 					} | 
 | 					ch = getchar(); | 
 | 				} while (isalpha(ch) || isdigit(ch) || ch == '_'); | 
 | 				ungetc(ch, stdin); | 
 | 				*ptr = '\0'; | 
 | 				yylval.y_string = StrCopy(buf); | 
 | 				return(ID); | 
 | 			}  | 
 | 			if (isdigit(ch)) { | 
 | 				int val=0; | 
 | 				do { | 
 | 					val *= 10; | 
 | 					val += (ch - '0'); | 
 | 					ch = getchar(); | 
 | 				} while (isdigit(ch)); | 
 | 				ungetc(ch, stdin); | 
 | 				yylval.y_int = val; | 
 | 				return(INT); | 
 | 			} | 
 | 			yyerror1("illegal char "); | 
 | 			fprintf(stderr, "(\\%03o)\n", ch); | 
 | 			exit(1); | 
 | 		} | 
 | 	} | 
 | 	return(0); | 
 | } | 
 |  | 
 | void yyerror1(const char *str) | 
 | { | 
 | 	fprintf(stderr, "line %d: %s", yyline, str); | 
 | } | 
 |  | 
 | void | 
 | yyerror(const char *str) | 
 | { | 
 | 	yyerror1(str); | 
 | 	fprintf(stderr, "\n"); | 
 | 	exit(1); | 
 | } |