|
|
/** opprec.c - compute operator predecence function values
* R. A. Garmoe 89/05/09 */
/* This program accepts a directed graph (in matrix form) and calculates
* the operator precedence function values f(op) and g(op). For more * information see Compilers: Principles, Techniques and Tools, by Aho, * Sethi and Ullman [Addison-Wesley], Section 4.6. A value of 1 in the * matrix indicates an edge; a value of 0 indicates no edge. Note * also that the entries fx -> fy and gx -> gy are only present as * placeholders (to make the matrix easier to read in); these values * should always be zero. * * To use this program, first generate the directed graph file expr2.z and * run it through the C preprocessor to remove comments: * * cl -P expr2.z * * This will produce the file expr2.i, which can then be run through * opprec.exe: * * graph {option} expr2.i > expr2.out * * The output file expr2.out then contains the precedence function * values in either assembler or C format. */
/* Call
* * opprec vca file * * where * v include operator values in output as comments * c generate C compilable output * a generate MASM assemblable output * file input file stripped of comments */
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "opprec.h"
struct token { struct token *next; char precstr[17]; char type[17]; char tclass[17]; char bind[17]; char eval[17]; }; struct token *tokhead = NULL; struct token *toktail = NULL; int asmout = FALSE; //output assembler form if true
int verbose = FALSE; //output operator group data if true
void cdecl main(int argc, char **argv) { int i; int j; int d; int *pMat; int *pPrec; char **pStr; int cEnt; FILE *fh; char *p, *q; int len, f, g; struct token *pt; int ntoken = 0; char str[200];
// check arguments
if (argc != 3) { printf ("Usage: graph -vca file\n"); exit (1); }
for (i = 0; argv[1][i] != 0; i++) { switch (argv[1][i]) { case 'a': asmout = TRUE; break;
case 'c': asmout = FALSE; break;
case 'v': verbose = TRUE; break;
default: printf ("Unknown argument %c\n", argv[1][i]); exit (1); } } if ((fh = fopen (argv[2], "r")) == NULL) { printf ("Unable to open '%s'\n", argv[1]); exit (1); }
// read and print token class definitions
for (;;) { if ((p = SkipBlank (fh, str, 200)) == NULL) { printf ("EOF reached\n"); exit (1); } while (isspace (*p)) { p++; } q = strpbrk (p, " \t"); if ( q ) *q = 0; if (strcmp (p, "END") == 0) { break; } if (asmout) { printf ("OPCDAT %s\n", p); } else { printf ("OPCDAT (%s)\n", p); } } printf ("\n");
// read token definitions
for (;;) { if ((p = SkipBlank (fh, str, 200)) == NULL) { printf ("EOF reached\n"); exit (1); } while (isspace (*p)) { p++; } if (strcmp (p, "END") == 0) { break; } if ((q = strpbrk (p, " \t")) == NULL) { printf ("Bad format (%s)\n", str); exit (1); } *q = 0; ntoken++; if ((pt = (struct token *)malloc (sizeof (struct token))) == NULL) { printf ("insufficient memory\n"); exit (2); } pt->next = NULL; strcpy (pt->precstr, p); p = q + 1; while (isspace (*p)) { p++; } if ((q = strpbrk (p, " \t")) == NULL) { printf ("Bad format (%s)\n", str); exit (1); } *q = 0; strcpy (pt->type, p); p = q + 1; while (isspace (*p)) { p++; } if ((q = strpbrk (p, " \t")) != NULL) { *q = 0; } strcpy (pt->tclass, p); p = q + 1; while (isspace (*p)) { p++; } if ((q = strpbrk (p, " \t")) != NULL) { *q = 0; } strcpy (pt->bind, p); p = q + 1; while (isspace (*p)) { p++; } if ((q = strpbrk (p, " \t")) != NULL) { *q = 0; } strcpy (pt->eval, p);
if (tokhead == NULL) { tokhead = pt; toktail = pt; } else { toktail->next = pt; toktail = pt; } } if (asmout) { printf ("OPCNT COPS_EXPR,\t%d\n\n", ntoken); } else { printf ("OPCNT (COPS_EXPR,\t%d\t)\n\n", ntoken); }
// read dimension of matrix. note that the upper left and lower right
// quadrants of the matrix must be zero.
if (SkipBlank (fh, str, 200) == NULL) { printf ("EOF reached\n"); exit (1); } cEnt = atoi (str);
// allocate space for the matrix and the description strings
pMat = (int *)malloc (cEnt * cEnt * sizeof(int)); pStr = malloc (cEnt * sizeof (char *)); pPrec = (int *)malloc (cEnt * sizeof (int)); if ((pMat == NULL) || (pStr == NULL) || (pPrec == NULL)) { printf ("insufficient memory\n"); exit (2); }
ReadMat (fh, pMat, pStr, cEnt);
AddClosure (pMat, cEnt);
// check for acyclic graph
for (i = 0; i < cEnt; ++i) { if (pMat[i * cEnt + i] != 0) { printf ("Graph is cyclic for %s!!!\n", pStr[i]); exit(3); } }
// print precedence function values
for (i = 0; i < cEnt; ++i) { d = 0; for (j = 0; j < cEnt; ++j) { if (pMat[i * cEnt + j] > d) { d = pMat[i * cEnt + j]; } } pPrec[i] = d; if (verbose) { if (asmout) { printf (";%-4s : %3d\n", pStr[i], d); } else { printf ("/*%-4s : %3d*/\n", pStr[i], d); } } }
// print token definitions
for (pt = tokhead; pt != NULL; pt = pt->next) { len = strlen (pt->precstr);
// search for F string in list of precedence groupings
for (i = 0; i < cEnt; i++) { if ((p = strstr(pStr[i], pt->precstr)) && ((*(p + len) == 0) || (*(p + len) == 'G'))) { break; } } if (i == cEnt) { printf ("F precedence string \"%s\" not found\n", pt->precstr); exit (4); } else { f = pPrec[i]; }
// search for G string in list of precedence groupings
*pt->precstr = 'G'; for (i = 0; i < cEnt; i++) { // search for string in list of precedence groupings
if ((p = strstr(pStr[i], pt->precstr)) && (*(p + len) == 0)) { break; } } if (i == cEnt) { printf ("G precedence string \"%s\" not found\n", pt->precstr); exit (4); } else { g = pPrec[i]; } if (asmout) { printf ("OPDAT %-16s,%4d,%4d,\t%-16s\n", pt->type, f, g,pt->tclass); } else { printf ("OPDAT (%-16s,%4d,%4d,\t%-16s,%-16s,%-16s\t)\n", pt->type, f, g,pt->tclass, pt->bind, pt->eval); } } fclose (fh); }
char *SkipBlank (FILE *fh, char *pStr, int cnt) { int len;
for (;;) { if (fgets (pStr, cnt, fh) == NULL) { return (NULL); } len = strlen (pStr); if ((len == 1) || (*pStr == '#')) { continue; } *(pStr + len - 1) = 0; return (pStr); } }
|