/* * File: gensn.c * * Program to generate tables for handling special names in IMP80 compiler * * Bob Eager August 2002 * */ /* * Compile time options * * Define exactly one target language name to be 1; all the rest should be 0. * */ #define C 1 /* C language */ #define IMP 0 /* IMP80 language */ #ifdef __IBMC__ #pragma strings(readonly) #endif #include #include #include #include #include #define FALSE 0 #define TRUE 1 #define MAXCC 132 /* Max length of line buffer */ #define MAXNAME 20 /* Max length of a special name */ #define MAXPARAM 40 /* Max length of parameter text */ #define MAXSN 80 /* Max number of special names */ #define MAXTYPE 25 /* Max length of type text */ /* Type definitions */ typedef void VOID, *PVOID; typedef int BOOL, *PBOOL; typedef char CHAR, *PCHAR; typedef unsigned char UCHAR, *PUCHAR; typedef int INT, *PINT; typedef unsigned int UINT, *PUINT; typedef long LONG, *PLONG; typedef unsigned long ULONG, *PULONG; /* Forward references */ static VOID do_comments(VOID); static VOID do_names(VOID); static VOID do_tables(VOID); static FILE *openio(PUCHAR, PUCHAR); static VOID readline(VOID); static VOID usage(VOID); /* Local data */ static UCHAR cc[MAXCC]; /* Input line buffer */ static FILE *infp; /* File pointer for input file */ static FILE *comfp; /* File pointer for comment file */ static FILE *namefp; /* File pointer for name file */ static INT num = 0; /* Number of names */ static PUCHAR progname; /* Program name */ static INT ptype[MAXSN]; /* Special name type */ static UCHAR sname[MAXSN][MAXNAME]; /* Special name text */ static INT sninfo[MAXSN]; /* Special name information */ static UCHAR sparam[MAXSN][MAXPARAM];/* Special name parameter text */ static UCHAR stype[MAXSN][MAXTYPE]; /* Special name textual type info */ static FILE *tabfp; /* File pointer for table file */ INT main(INT argc, PUCHAR argv[]) { INT i; time_t now; /* Binary date and time */ UCHAR s_now[26]; /* String date and time */ UCHAR temp[MAXCC]; /* Temporary input buffer */ PUCHAR p; progname = argv[0]; p = strrchr(progname, '\\'); if(p != (PUCHAR) NULL) progname = ++p; for(i = 0; progname[i] != '\0'; i++) progname[i] = (UCHAR) tolower(progname[i]); if(argc != 5) usage(); infp = openio(argv[1], "r"); tabfp = openio(argv[2], "w"); namefp = openio(argv[3], "w"); comfp = openio(argv[4], "w"); now = time((time_t *) NULL); /* Get binary date and time */ strcpy(s_now, ctime(&now)); /* Copy string version */ s_now[24] = '\0'; /* Truncate to remove newline */ /* Main input loop */ for(;;) { if(num >= MAXSN) { fprintf(stderr, "%s: too many names\n", progname); exit(EXIT_FAILURE); } readline(); if(cc[0] == '\0') break; /* Finished */ if(cc[0] == '!') continue; /* Comment line - ignore */ sscanf(cc, "%x %x %s %[^\n]", &ptype[num], &sninfo[num], stype[num], temp); /* Read and decompose line */ p = strpbrk(temp, "("); /* See if any parameters */ if(p != (unsigned char *) NULL) { (VOID) strncpy(sname[num], temp, (UINT) (p-temp)); (VOID) strcpy(sparam[num], p+1); } else { (VOID) strcpy(sname[num], temp); sparam[num][0] = '\0'; } num++; /* Count of items read */ } fclose(infp); /* Generate the tables file */ do_tables(); do_names(); do_comments(); return(EXIT_SUCCESS); } /* * Function to generate a comment line framed by asterisks, and write * it to the comment file. * */ #if C static VOID com(PUCHAR s) { INT i; fprintf(comfp, " * %s", s); for(i = 0; i < 71 - strlen(s); i++) fputc(' ', comfp); fputs("*\n", comfp); } #endif /* * Function to generate a comment line framed by asterisks, and write * it to the comment file. * */ #if IMP static VOID com(PUCHAR s) { int i; fprintf(comfp, "!* %s", s); for(i = 0; i < 71 - strlen(s); i++) fputc(' ', comfp); fputs("*\n", comfp); } #endif /* * Function to generate comment block for head of CSNAME * */ #if C static VOID do_comments() { INT i; UCHAR line[MAXCC+1]; fputc('/', comfp); for(i = 0; i < 79; i++) fputc('*', comfp); fputc('\n', comfp); com(""); com("Compile a special name - 'ptype' = 1006 (=%routine %label)"); com("Their true 'ptype' is in global array 'tsname'."); com("'sninfo' has a four byte record for each name:"); com(" 2 byte extra information"); com(" 1 byte pointer (various uses)"); com(" 1 byte flags:"); com(" Bits 0-2 - number of parameters"); com(" Bit 3 - set if first parameter is of %name type"); com(" Bit 4 - set if ad-hoc code planted by this routine"); com(" Bit 5 - set for built in mapping functions"); com(" Bit 6 - set for 'iocp' call"); com(" Bit 7 - set for implicitly specified items"); com(""); for(i = 0; i < num; i++) { sprintf(line, "%2d = %s %s%s%s", i, stype[i], sname[i], sparam[i][0] == '\0' ? "" : "(", sparam[i]); com(line); } com(""); fputc(' ', comfp); for(i = 0; i < 77; i++) fputc('*', comfp); fputs("*/\n", comfp); } #endif /* * Function to generate comment block for head of CSNAME * */ #if IMP static VOID do_comments() { INT i; UCHAR line[MAXCC+1]; fputc('!', comfp); for(i = 0; i < 79; i++) fputc('*', comfp); fputc('\n', comfp); com(""); com("Compile a special name - 'ptype' = 1006 (=%routine %label)"); com("Their true 'ptype' is in global array 'tsname'."); com("'sninfo' has a four byte record for each name:"); com(" 2 byte extra information"); com(" 1 byte pointer (various uses)"); com(" 1 byte flags:"); com(" Bits 0-2 - number of parameters"); com(" Bit 3 - set if first parameter is of %name type"); com(" Bit 4 - set if ad-hoc code planted by this routine"); com(" Bit 5 - set for built in mapping functions"); com(" Bit 6 - set for 'iocp' call"); com(" Bit 7 - set for implicitly specified items"); com(""); for(i = 0; i < num; i++) { sprintf(line, "%2d = %s %s%s%s", i, stype[i], sname[i], sparam[i] == '\0' ? "" : "(", sparam[i]); com(line); } com(""); fputc('!', comfp); for(i = 0; i < 79; i++) fputc('*', comfp); fputc('\n', comfp); } #endif /* * Function to generate name table * */ #if C static VOID do_names() { INT i, j; UINT nmax = 0; INT online = 0; PUCHAR s; /* Work out total length required */ for(i = 0; i < num; i++) nmax += (strlen(sname[i]) + 1); fprintf(namefp, "const\tunsigned char\tilett[%d] = {\n", nmax+1); for(i = 0; i < num; i++) { s = sname[i]; for(j = 0; j <= strlen(s); j++) { if(online == 16) { fputc('\n', namefp); online = 0; } if(j == 0) fprintf(namefp, "%3d, ", strlen(s)); else fprintf(namefp, "'%c', ", toupper(s[j-1])); online++; } } if(online++ == 16) { fputc('\n', namefp); online = 1; } fprintf(namefp, "%3d\n};\n", 255); } #endif /* * Function to generate name table * */ #if IMP static VOID do_names() { INT i, j; INT nmax = 0; INT online = 0; PUCHAR s; /* Work out total length required */ for(i = 0; i < num; i++) nmax += (strlen(sname[i]) + 1); fprintf(namefp, "%%constantbyteintegerarray ilett(0:%d) = %%c\n", nmax); for(i = 0; i < num; i++) { s = sname[i]; for(j = 0; j <= strlen(s); j++) { if(online == 16) { fputc('\n', namefp); online = 0; } if(j == 0) fprintf(namefp, "%3d, ", strlen(s)); else fprintf(namefp, "'%c',", toupper(s[j-1])); online++; } } if(online++ == 16) { fputc('\n', namefp); online = 1; } fprintf(namefp, "%3d;\n", 255); } #endif /* * Function to generate the subsidiary tables * */ #if C static VOID do_tables() { INT i; /* First the PTYPE table */ fprintf(tabfp, "#define\tNOOFSNS\t\t%d\n\n", num); fputs("const\tunsigned short\ttsname[NOOFSNS] = {\n", tabfp); for(i = 0; i < num; i++) { fprintf(tabfp, "0x%04x%s", ptype[i], (i == num - 1) ? "" : ","); if((i+1)%8 == 0) fputc('\n', tabfp); } if(num%8 != 0) fputc('\n', tabfp); fputs("};\n", tabfp); /* Now the special name information table */ fputs("\nconst\tunsigned int\tsninfo[NOOFSNS] = {\n", tabfp); for(i = 0; i < num; i++) { fprintf(tabfp, "0x%08x%s", sninfo[i], (i == num - 1) ? "" : ","); if((i+1)%4 == 0) fputc('\n', tabfp); } if(num%4 != 0) fputc('\n', tabfp); fputs("};\n", tabfp); } #endif /* * Function to generate the subsidiary tables * */ #if IMP static VOID do_tables() { INT i; /* First the PTYPE table */ fprintf(tabfp, "%%constantinteger no of sns = %d\n", num-1); fputs("%constanthalfintegerarray tsname(0:no of sns) = %c\n", tabfp); for(i = 0; i < num; i++) { fprintf(tabfp, "x'%04x'%c", ptype[i], (i == num - 1) ? ';' : ','); if((i+1)%8 == 0) fputc('\n', tabfp); } if(num%8 != 0) fputc('\n', tabfp); /* Now the special name information table */ fputs("!\n%constantintegerarray sninfo(0:no of sns) = %c\n", tabfp); for(i = 0; i < num; i++) { fprintf(tabfp, "x'%08x'%c", sninfo[i], (i == num - 1) ? ';' : ','); if((i+1)%4 == 0) fputc('\n', tabfp); } if(num%4 != 0) fputc('\n', tabfp); } #endif /* * Function to open a file in a specified mode * Does not return if there is a failure, but outputs an error * message and exits * */ static FILE *openio(PUCHAR file, PUCHAR mode) { FILE *fp; fp = fopen(file, mode); if(fp == (FILE *) NULL) { fprintf(stderr, "%s: cannot open '%s'\n", progname, file); exit(EXIT_FAILURE); } return(fp); } /* * Routine to read a line from the input file into 'cc'. * Blank lines are ignored. * * On exit, 'cc' contains the string, null terminated. * */ static VOID readline(VOID) { INT i = 0; INT ch; do { for(;;) { ch = fgetc(infp); if(ch == EOF) break; if(ch == '\n') break; cc[i++] = (unsigned char) ch; } cc[i] = '\0'; } while((cc[0] == '\0') && (ch == '\n')); if(ch == EOF) cc[0] = '\0'; } /* * Routine to output brief usage information, then exit. * */ static VOID usage() { fprintf(stderr, "Usage: %s input tables names comments\n", progname); exit(EXIT_SUCCESS); } /* * End of file: gensn.c * */