/*
* geninstr.c
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
static int
parse_descriptor_line(const char *line, char *name, char *mode)
{
while (isspace((int)*line) && (*line != '\0')) {
line++;
}
if (*line != '%')
return 0;
line++;
while (isspace((int)*line) && (*line != '\0')) {
line++;
}
while (!isspace((int)*line) && (*line != '\0')) {
*name = *line;
name++;
line++;
}
*name = '\0';
while (isspace((int)*line) && (*line != '\0')) {
line++;
}
while (!isspace((int)*line) && (*line != '\0')) {
*mode = *line;
mode++;
line++;
}
*mode = '\0';
return 1;
}
int
main(int argc, char **argv)
{
FILE *instrtab, *instrenum, *instrlab, *vm, *localtypes;
static char line[512], name[80], mode[80];
argc = argc;
argv = argv;
if ((instrtab = fopen("instrtab.c", "w")) == NULL) {
perror("Couldn't open instrtab.c for writing");
exit(1);
}
if ((instrenum = fopen("instrenum.h", "w")) == NULL) {
perror("Couldn't open instrenum.h for writing");
exit(1);
}
if ((instrlab = fopen("instrlab.h", "w")) == NULL) {
perror("Couldn't open instrlab.h for writing");
exit(1);
}
if ((vm = fopen("vm.c", "r")) == NULL) {
perror("Couldn't open vm.c for reading");
exit(1);
}
fputs(
"/*\n"
" * instrtab.c\n"
" * Table of VM instructions, mapping names to opcodes.\n"
" * NOTE: THIS FILE WAS AUTOMATICALLY GENERATED from vm.c by geninstr\n"
" */\n"
"\n"
"#include \"lib.h\"\n"
"\n"
"#include \"instrtab.h\"\n"
"\n"
"struct opcode_entry opcode_table[] = {\n", instrtab);
fputs(
"/*\n"
" * instrenum.h\n"
" * C 'enum' type for VM instructions.\n"
" * NOTE: THIS FILE WAS AUTOMATICALLY GENERATED from vm.c by geninstr\n"
" */\n"
"\n"
"#ifndef __INSTRENUM_H_\n"
"#define __INSTRENUM_H_\n"
"\n"
"enum opcode {\n", instrenum);
fputs(
"/*\n"
" * instrlab.h\n"
" * gcc labels for VM instructions, to support direct threading.\n"
" * NOTE: THIS FILE WAS AUTOMATICALLY GENERATED from vm.c by geninstr\n"
" */\n"
"\n"
"#ifndef __INSTRLAB_H_\n"
"#define __INSTRLAB_H_\n"
"\n"
"static clabel instr_label[] = {\n", instrlab);
while (fgets(line, 510, vm)) {
int arity = 1;
const char *optype = "NONE";
if (!parse_descriptor_line(line, name, mode))
continue;
switch (mode[0]) {
case 'i':
optype = "INT";
break;
case 'a':
optype = "ADDR";
break;
case 'v':
optype = "VALUE";
break;
default:
arity = 0;
break;
}
fprintf(instrtab, "\t{ \"%s\",\tINSTR_%s,\t%d,\tOPTYPE_%s\t},\n",
name, name, arity, optype);
fprintf(instrenum, "\tINSTR_%s,\n", name);
fprintf(instrlab, "\t&&LABEL_INSTR_%s,\n", name);
}
fclose(vm);
fputs("\t{ NULL,\t\tINSTR_NULL,\t0,\tOPTYPE_NONE }\n};\n", instrtab);
fclose(instrtab);
fputs("\tINSTR_NULL\n};\n\n#endif /* !__INSTRENUM_H_ */\n", instrenum);
fclose(instrenum);
fputs("\tNULL\n};\n\n#endif /* !__INSTRLAB_H_ */\n", instrlab);
fclose(instrlab);
if ((localtypes = fopen("localtypes.h", "w")) == NULL) {
perror("Couldn't open localtypes.h for writing");
exit(1);
}
fputs(
"/*\n"
" * localtypes.h\n"
" * Define some types for the local system.\n"
" * NOTE: THIS FILE WAS AUTOMATICALLY GENERATED by geninstr\n"
" */\n"
"\n"
"#ifndef __LOCALTYPES_H_\n"
"#define __LOCALTYPES_H_\n"
"\n", localtypes);
if (sizeof(void *) == sizeof(unsigned int)) {
fputs("#define PTR_INT unsigned int\n", localtypes);
} else if (sizeof(void *) == sizeof(unsigned long int)) {
fputs("#define PTR_INT unsigned long int\n", localtypes);
} else {
fputs("#define PTR_INT not_supported\n", localtypes);
}
fputs("\n#endif /* !__LOCALTYPES_H_ */\n", localtypes);
fclose(localtypes);
exit(0);
}