⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 moon.c

📁 compiler-compiler. This is a compiler-compiler with table-driven scanner, table-driven parser.
💻 C
📖 第 1 页 / 共 3 页
字号:
void next () {	char *t = token.symval;	short op;	strcpy(oldval, token.symval);	while (*bp == ' ' || *bp == '\t')		bp++;	token.pos = bp;	if (isalpha(*bp)) {		/* Read a register, op code, directive, or symbol */		while (issymchar(*bp))			*t++ = *bp++;		*t = '\0';/*		printf("<%s>\n", token.symval);*/		if (isreg(token.symval)) {			token.kind = T_REG;			return;			}		for (op = lw; op < last; op++) {			if (!strcmp(token.symval, opnames[op])) {				token.op = op;				token.kind = T_OP;				return;				}			}		token.kind = T_SYM;		return;		}	else if (*bp == '-' || *bp == '+' || isdigit(*bp)) {		/* Read a signed decimal integer */		*t++ = *bp++;		while (isdigit(*bp))			*t++ = *bp++;		*t = '\0';		sscanf(token.symval, "%ld", &token.intval);		token.kind = T_NUM;		return;		}	else if (*bp == '"') {		/* Read a character string enclosed in quotes */		bp++;		while (1) {			if (*bp == '"') {				*t = '\0';				token.kind = T_STR;				bp++;				break;				}			if (*bp == '\0' || *bp == '\n') {				syntaxerror("unterminated string");				token.kind = T_BAD;				*t = '\0';				break;				}			*t++ = *bp++;			}		return;		}	else if (*bp == ',') {		bp++;		token.kind = T_COMMA;		strcpy(token.symval, ",");		return;		}	else if (*bp == '(') {		bp++;		token.kind = T_LP;		strcpy(token.symval, "(");		return;		}	else if (*bp == ')') {		bp++;		token.kind = T_RP;		strcpy(token.symval, ")");		return;		}	else if (*bp == '%' || *bp == '\n' || *bp == '\0') {		token.kind = T_NULL;		strcpy(token.symval, " ");		return;		}	else {		token.kind = T_BAD;		strcpy(token.symval, " ");		}	}/* Match a token */void match (enum tokentype kind) {	if (token.kind == kind) {		next();		return;		}	switch (kind) {		case T_COMMA:			syntaxerror("',' expected");			break;		case T_LP:			syntaxerror("'(' expected");			break;		case T_RP:			syntaxerror("')' expected");			break;		default:			syntaxerror("Syntax error");			break;		}	}/* Parse an opcode.  The error should never occur, since this function * is called only when the token type is know. */short getop () {	if (token.kind == T_OP) {		short res = token.op;		next();		return res;		}	syntaxerror("Opcode expected");	return 0;	}/* Parse a register and return the register number */short getreg () {	if (token.kind == T_REG) {		short res = token.reg;		next();		return res;		}	syntaxerror("Register expected");	return 0;	}/* Parse a constant (number or symbol) and return value */long getlong (long addr) {	if (token.kind == T_NUM) {		long res = token.intval;		next();		return res;		}	else if (token.kind == T_SYM) {		usesymbol(token.symval, addr);		next();		return 0;		}	syntaxerror("Constant expected");	return 0;	}/* 	Similar to getlong(), but checks that its argument can be stored * in 16 bits. */int getint (long addr) {	long val = getlong(addr);	if (labs(val) <= 32767)		return (int) val;	syntaxerror("Value cannot be represented with 16 bits");	return 0;	}char buffer [BUFLEN];		/* Input buffer */long addr = 0;int linenum = 0;/* Parse one line of source code from the buffer. */void readline () {	wordtype word;	word.data = 0;	bp = buffer;	strcpy(errmes, "");	strcpy(oldval, "");	next();	while (token.kind == T_SYM) {		defsymbol(token.symval, addr);		next();		}	if (token.kind == T_OP) {		switch (token.op) {			/* Format A -- registers only */			/* Operands Ri, Rj, Rk */			case add:			case sub:			case mul:			case divr:			case mod:			case and:			case or:			case ceq:			case cne:			case clt:			case cle:			case cgt:			case cge:				word.fmta.op = getop();				word.fmta.ri = getreg();				match(T_COMMA);				word.fmta.rj = getreg();				match(T_COMMA);				word.fmta.rk = getreg();				putmeminstr(addr, word, 'a');				addr += 4;				break;			/* Operands Ri, Rj */			case not:			case jlr:				word.fmta.op = getop();				word.fmta.ri = getreg();				match(T_COMMA);				word.fmta.rj = getreg();				putmeminstr(addr, word, 'a');				addr += 4;				break;			/* No operands */			case nop:			case hlt:				word.fmta.op = getop();				putmeminstr(addr, word, 'a');				addr += 4;				break;			/* Format B - operands and constant fields */			/* Operands Ri, K(Rj) */			case lw:			case lb:				word.fmtb.op = getop();				word.fmtb.ri = getreg();				match(T_COMMA);				word.fmtb.k = getint(addr);				match(T_LP);				word.fmtb.rj = getreg();				match(T_RP);				putmeminstr(addr, word, 'b');				addr += 4;				break;			/* Operands K(Rj), Ri */			case sw:			case sb:				word.fmtb.op = getop();				word.fmtb.k = getint(addr);				match(T_LP);				word.fmtb.rj = getreg();				match(T_RP);				match(T_COMMA);				word.fmtb.ri = getreg();				putmeminstr(addr, word, 'b');				addr += 4;				break;			/* Operands Ri, Rj, K */			case addi:			case subi:			case muli:			case divi:			case modi:			case andi:			case ori:			case ceqi:			case cnei:			case clti:			case clei:			case cgti:			case cgei:				word.fmtb.op = getop();				word.fmtb.ri = getreg();				match(T_COMMA);				word.fmtb.rj = getreg();				match(T_COMMA);				word.fmtb.k = getint(addr);				putmeminstr(addr, word, 'b');				addr += 4;				break;			/* Operands Ri, K */			case sl:			case sr:			case bz:			case bnz:			case jl:				word.fmtb.op = getop();				word.fmtb.ri = getreg();				match(T_COMMA);				word.fmtb.k = getint(addr);				putmeminstr(addr, word, 'b');				addr += 4;				break;			/* Operands Ri */			case gtc:			case ptc:			case jr:				word.fmtb.op = getop();				word.fmtb.ri = getreg();				putmeminstr(addr, word, 'b');				addr += 4;				break;			/* Operands K */			case j:				word.fmtb.op = getop();				word.fmtb.k = getint(addr);				putmeminstr(addr, word, 'b');				addr += 4;				break;			/* Set the entry point of the program. */			case entry:				next();				if (entrypoint < 0) {					entrypoint = addr;					break;					}				syntaxerror("More than one entry point");				break;			/* Adjust the address to the next word boundary. */			case align:				next();				if (addr & 3)					addr = (addr & ~3) + 4;				break;			/* Set the address to the given value. */			case org:				next();				addr = getlong(addr);				break;			/* Store words. */			case dw:				next();				while (token.kind == T_NUM || token.kind == T_SYM) {					word.data = getlong(addr);					putmeminstr(addr, word, 'd');					addr += 4;					if (token.kind == T_COMMA)						next();					else						break;					}				break;			/* Store bytes */			case db:				next();				while (1) {					if (token.kind == T_NUM) {						if (0 <= token.intval && token.intval <= 255) {							putmemchar(addr, token.intval, 'd');							addr++;							}						else							syntaxerror("Value cannot be represented with 8 bits");						next();						}					else if (token.kind == T_STR) {						char *t = token.symval;						while (*t) {							putmemchar(addr, *t++, 'd');							addr++;							}						next();						}					if (token.kind == T_COMMA)						next();					else if (token.kind == T_NULL)						break;					else {						syntaxerror("Syntax error in byte list");						break;						}					}				break;			/* Reserve the given number of words. */			case res:				next();				addr += getlong(addr);				break;			/* Should never get here. */			default:				syntaxerror("Unrecognized statement");				break;			}		}	if (token.kind != T_NULL && errorcount < 5) {		printf("Warning: junk following `%s' on next line.\n", token.symval);		printf("%4d  %s\n", linenum, buffer);		errorcount++;		}	}/* Load a source file. */void load (FILE *inp, FILE *out, short listing) {	linenum = 0;	while (fgets(buffer, BUFLEN - 1, inp)) {		long oldaddr = addr;		linenum++;		readline();		if (listing)			fprintf(out, "%5d %5ld %s", linenum, oldaddr, buffer);		if (strcmp(errmes, "")) {			printf("%5d %5ld %s", linenum, oldaddr, buffer);			printf("      >>>>> %s\n", errmes);			if (listing)				fprintf(out, "      >>>>> %s\n", errmes);			}		}	}/*************************** USER INSTRUCTION *******************************/void showusage () {	printf("Usage:\n");	printf("         moon { option | filename }\n");	printf("The command line may contain source file names and options in any order.\n");	printf("There should be at least one source file.  Source files will be loaded\n");	printf("in the order in which they are given.\n");	printf("Options:\n");	printf("       +p           print listing\n");	printf("       -p (default) do not print listing\n");	printf("       +s           display symbol values\n");	printf("       -s (default) do not display symbol values\n");	printf("       +t           start in trace mode\n");	printf("       -t (default) execute without tracing\n");	printf("       +x (default) execute the program\n");	printf("       -x           do not execute the program\n");	printf("Input files:\n");	printf("       If an input file name does not contain `.', the suffix\n");	printf("       `.n' will be appended to it.\n");	printf("Listing files:\n");	printf("       Source files may be listed selectively.  The command\n");	printf("            moon -p lib +p appl\n");	printf("       would create a listing for `appl.m' but not for `lib.m'.\n");	printf("       The list file is named `moon.prn' by default.\n");	printf("       Use +o or -o followed by a name to changes the list file name.\n");	}/*************************** MAIN PROGRAM ***********************************/int main (int argc, char *argv[]) {	struct {		char name [MAXNAMELEN];		short list;		} filedescs [MAXINFILES];	int numfiles = 0;	char outname [MAXNAMELEN] = "";	short dump = FALSE;			/* D Dump memory */	short listing = FALSE;		/* P Generate a listing of the source code */	short symbols = FALSE;		/* S Display symbol values */	short tracing = FALSE;		/* T Execute program in trace mode */	short execute = TRUE;		/* X Execute the program after loading */	short listreq = FALSE;		/* A listing is needed */	long addr;	int arg, fil;	FILE *inp, *out;	regs[0] = 0;   /* Register 0 is always 0. */	/* If there are no arguments, help the poor user. */	if (argc <= 1) {		showusage();		exit(0);		}	/* Process command line arguments.	 * There should be at least one argument.  Arguments that start with	 * + (-) turn flags on (off).  Other arguments are input file names.	 * The listing switch (+-l) is processed in sequence so that files	 * may be listed selectively.	 */	for (arg = 1; arg < argc; arg++) {		char *p = argv[arg];		if (*p == '+') {			p++;			switch (*p++) {				case 'd': case 'D':					dump = TRUE;					break;				case 'o': case 'O':					strcpy(outname, p);					break;				case 'p': case 'P':					listing = TRUE;					break;				case 's': case 'S':					symbols = TRUE;					break;				case 't': case 'T':					tracing = TRUE;					break;				case 'x': case 'X':					execute = TRUE;					break;				default:					printf("Illegal option: +%s\n", --p);					exit(1);				}			}		else if (*p == '-') {			p++;			switch (*p++) {				case 'd': case 'D':					dump = FALSE;					break;				case 'o': case 'O':					strcpy(outname, p);					break;				case 'p': case 'P':					listing = FALSE;					break;				case 's': case 'S':					symbols = FALSE;					break;				case 't': case 'T':					tracing = FALSE;					break;				case 'x': case 'X':					execute = FALSE;					break;				default:					printf("Illegal option: -%s\n", --p);					exit(1);				}			}		else {			if (numfiles >= MAXINFILES) {				printf("Too many input files!\n");				exit(1);				}			strcpy(filedescs[numfiles].name, p);			filedescs[numfiles].list = listing;			if (listing)				listreq = TRUE;			numfiles++;			}		}	/* Nothing to do if there were no files on the command line. */	if (numfiles == 0) {		printf("No input files!\n");		exit(1);		}	/* 	Attempt to open an output file if a listing is required.	 * If no output file was named, use a default name.	 */	if (listreq) {		if (strlen(outname) == 0)			strcpy(outname,"moon.prn");		if ((out = fopen(outname, "w")) == NULL) {			printf("Unable to open listing file %s.\n", outname);			exit(1);			}		printf("Writing listing to %s.\n", outname);		}	/* Process each input file. If no extension is given, assume .m.	 * If the file can be opened, load assembler code from it.	 */	initmem();	defsymbol("topaddr", 4 * MEMSIZE);	for (fil = 0; fil < numfiles; fil++) {		if (!strchr(filedescs[fil].name, '.'))			strcat(filedescs[fil].name, ".m");		if ((inp = fopen(filedescs[fil].name, "r")) == NULL) {			printf("Unable to open input file: %s.\n", filedescs[fil].name);			exit(1);			}		else {			short listing = filedescs[fil].list;			printf("Loading %s.\n", filedescs[fil].name);			if (listing) {				fprintf(out, "MOON listing of %s.\n\n", filedescs[fil].name);				load(inp, out, TRUE);				fprintf(out, "\n");				}			else				load(inp, out, FALSE);			fclose(inp);			}		}	if (listreq)		fclose(out);	/* Check symbols and entry point. If there are errors, stop now. */	errorcount += checksymbols();	if (entrypoint < 0) {		printf("There is no `entry' directive.\n");		errorcount++;		}	if (errorcount > 0) {		printf("Loader errors -- no execution.\n");		exit(1);		}	/* Store values of symbols where they are used in the program.	 * Display them if requested.	 */	storesymbols();	if (symbols)		showsymbols();	/* If a dump was requested, dump the memory.  This option is not	 * advertised and therefore need not be supported.	 */	if (dump) {		printf("Memory dump:\n");		for (addr = 0; addr < MEMSIZE; addr += 4) {			if (mem[addr >> 2].cont != 'u') {				showword(addr);				printf("\n");				}			}		printf("\n");		}	/* Execute the program in normal or trace mode. */	if (execute) {		if (tracing)			exectrace();		else exec();		}   return 0;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -