/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ //#pragma ident "%Z%%M% %I% %E% SMI" #include "dextern.h" #include #define NOMORE -1000 static void gin (int); static void stin (int); static void osummary (void); static void aoutput (void); static void arout (char *, int *, int); static int nxti (void); static int gtnm (void); static int *ggreed; static int *pgo; static int *yypgo; static int maxspr = 0; /* maximum spread of any entry */ static int maxoff = 0; /* maximum offset into an array */ int *optimmem; static int *maxa; static int nxdb = 0; static int adb = 0; /* I/O descriptors */ extern FILE *finput; /* input file */ extern FILE *faction; /* file for saving actions */ extern FILE *fdefine; /* file for #defines */ extern FILE *fudecl; /* file for user declarations */ extern FILE *ftable; /* parser tables file */ extern FILE *fsppout; /* SPP output file */ extern FILE *ftemp; /* tempfile to pass 2 */ extern FILE *foutput; /* y.output file */ void callopt () { int i, *p, j, k, *q; ggreed = (int *) malloc (sizeof (int) * size); pgo = (int *) malloc (sizeof (int) * size); yypgo = &nontrst[0].tvalue; /* read the arrays from tempfile and set parameters */ if ((finput = fopen (TEMPNAME, "r")) == NULL) /* * TRANSLATION_NOTE -- This is a message from yacc. * This message is passed to error() function. * tempfile can be translated as temporary file. */ error ("optimizer cannot open tempfile"); optimmem = tracemem; pgo[0] = 0; temp1[0] = 0; nstate = 0; nnonter = 0; for (;;) { switch (gtnm ()) { case '\n': temp1[++nstate] = (--optimmem) - tracemem; /* FALLTHRU */ case ',': continue; case '$': break; default: error ("bad tempfile"); } break; } temp1[nstate] = yypgo[0] = (--optimmem) - tracemem; for (;;) { switch (gtnm ()) { case '\n': yypgo[++nnonter] = optimmem - tracemem; /* FALLTHRU */ case ',': continue; case EOF: break; default: /* * TRANSLATION_NOTE -- This is a message from yacc. * This message is passed to error() function. * tempfile can be translated as 'temporary file'. */ error ("bad tempfile"); } break; } yypgo[nnonter--] = (--optimmem) - tracemem; for (i = 0; i < nstate; ++i) { k = 32000; j = 0; q = tracemem + temp1[i + 1]; for (p = tracemem + temp1[i]; p < q; p += 2) { if (*p > j) j = *p; if (*p < k) k = *p; } if (k <= j) { /* * nontrivial situation * temporarily, kill this for compatibility */ /* j -= k; j is now the range */ if (k > maxoff) maxoff = k; } tystate[i] = (temp1[i + 1] - temp1[i]) + 2 * j; if (j > maxspr) maxspr = j; } /* initialize ggreed table */ for (i = 1; i <= nnonter; ++i) { ggreed[i] = 1; j = 0; /* minimum entry index is always 0 */ q = tracemem + yypgo[i + 1] - 1; for (p = tracemem + yypgo[i]; p < q; p += 2) { ggreed[i] += 2; if (*p > j) j = *p; } ggreed[i] = ggreed[i] + 2 * j; if (j > maxoff) maxoff = j; } /* now, prepare to put the shift actions into the amem array */ for (i = 0; i < new_actsize; ++i) amem[i] = 0; maxa = amem; for (i = 0; i < nstate; ++i) { if (tystate[i] == 0 && adb > 1) (void) fprintf (ftable, "State %d: null\n", i); indgo[i] = YYFLAG1; } while ((i = nxti ()) != NOMORE) { if (i >= 0) stin (i); else gin (-i); } if (adb > 2) { /* print a array */ for (p = amem; p <= maxa; p += 10) { (void) fprintf (ftable, "%4" PRIdPTR " ", p - amem); for (i = 0; i < 10; ++i) (void) fprintf (ftable, "%4d ", p[i]); (void) fprintf (ftable, "\n"); } } /* write out the output appropriate to the language */ aoutput (); osummary (); ZAPFILE (TEMPNAME); } static void gin (int i) { int *r, *s, *q1, *q2; int *p; /* enter gotos on nonterminal i into array amem */ ggreed[i] = 0; q2 = tracemem + yypgo[i + 1] - 1; q1 = tracemem + yypgo[i]; /* now, find a place for it */ /* for( p=amem; p < &amem[new_actsize]; ++p ){ */ p = amem; for (;;) { while (p >= &amem[new_actsize]) exp_act (&p); if (*p) goto nextgp; for (r = q1; r < q2; r += 2) { s = p + *r + 1; /* * Check if action table needs to * be expanded or not. If so, * expand it. */ while (s >= &amem[new_actsize]) { exp_act (&p); s = p + *r + 1; } if (*s) goto nextgp; if (s > maxa) { while ((maxa = s) >= &amem[new_actsize]) /* error( "amem array overflow" ); */ exp_act (&p); } } /* we have found a spot */ *p = *q2; if (p > maxa) { while ((maxa = p) >= &amem[new_actsize]) /* error("amem array overflow"); */ exp_act (&p); } for (r = q1; r < q2; r += 2) { s = p + *r + 1; /* * Check if action table needs to * be expanded or not. If so, * expand it. */ while (s >= &amem[new_actsize]) { exp_act (&p); s = p + *r + 1; } *s = r[1]; } pgo[i] = p - amem; if (adb > 1) (void) fprintf (ftable, "Nonterminal %d, entry at %d\n", i, pgo[i]); goto nextgi; nextgp: ++p; } /* error( "cannot place goto %d\n", i ); */ nextgi:; } static void stin (int i) { int *r, n, nn, flag, j, *q1, *q2; int *s; tystate[i] = 0; /* Enter state i into the amem array */ q2 = tracemem + temp1[i + 1]; q1 = tracemem + temp1[i]; /* Find an acceptable place */ nn = -maxoff; more: for (n = nn; n < new_actsize; ++n) { flag = 0; for (r = q1; r < q2; r += 2) { s = *r + n + amem; if (s < amem) goto nextn; /* * Check if action table needs to * be expanded or not. If so, * expand it. */ while (s >= &amem[new_actsize]) { exp_act ((int **) NULL); s = *r + n + amem; } if (*s == 0) ++flag; else if (*s != r[1]) goto nextn; } /* * check that the position equals another * only if the states are identical */ for (j = 0; j < nstate; ++j) { if (indgo[j] == n) { if (flag) /* * we have some disagreement. */ goto nextn; if (temp1[j + 1] + temp1[i] == temp1[j] + temp1[i + 1]) { /* states are equal */ indgo[i] = n; if (adb > 1) (void) fprintf (ftable, "State %d: entry at" " %d equals state %d\n", i, n, j); return; } goto nextn; /* we have some disagreement */ } } for (r = q1; r < q2; r += 2) { while ((s = *r + n + amem) >= &amem[new_actsize]) { /* * error( "out of space"); */ exp_act ((int **) NULL); } if (s > maxa) maxa = s; if (*s != 0 && *s != r[1]) /* * TRANSLATION_NOTE -- This is a message from yacc. * This message is passed to error() function. * Leave this untrasnlated. Yacc internal error. */ error ("clobber of amem array, pos'n %d, by %d", s - amem, r[1]); *s = r[1]; } indgo[i] = n; if (adb > 1) (void) fprintf (ftable, "State %d: entry at %d\n", i, indgo[i]); return; nextn:; } /* error( "Error; failure to place state %d\n", i ); */ exp_act ((int **) NULL); nn = new_actsize - ACTSIZE; goto more; /* NOTREACHED */ } static int nxti () { /* finds the next i */ int i, max, maxi; max = 0; maxi = 0; for (i = 1; i <= nnonter; ++i) if (ggreed[i] >= max) { max = ggreed[i]; maxi = -i; } for (i = 0; i < nstate; ++i) if (tystate[i] >= max) { max = tystate[i]; maxi = i; } if (nxdb) (void) fprintf (ftable, "nxti = %d, max = %d\n", maxi, max); if (max == 0) return (NOMORE); else return (maxi); } static void osummary () { /* write summary */ int i, *p; if (foutput == NULL) return; i = 0; for (p = maxa; p >= amem; --p) { if (*p == 0) ++i; } (void) fprintf (foutput, "Optimizer space used: input %" PRIdPTR "/%d, output %" PRIdPTR "/%d\n", optimmem - tracemem + 1, new_memsize, maxa - amem + 1, new_actsize); (void) fprintf (foutput, "%" PRIdPTR " table entries, %d zero\n", (maxa - amem) + 1, i); (void) fprintf (foutput, "maximum spread: %d, maximum offset: %d\n", maxspr, maxoff); } /* AOUTPUT -- This version is for SPP. */ static void aoutput () { /* write out the optimized parser */ fprintf (fsppout, "define\tYYLAST\t\t%d\n", (int) (maxa - amem + 1)); arout ("yyact", amem, (maxa - amem) + 1); arout ("yypact", indgo, nstate); arout ("yypgo", pgo, nnonter + 1); } /* AROUT -- Output SPP declarations and initializations for a Yacc table. */ # define NDP_PERLINE 8 static void arout (s, v, n) char *s; int *v, n; { register int i, j; fprintf (ftable, "short\t%s[%d]\n", s, n); for (j = 0; j < n; j += NDP_PERLINE) { fprintf (ftable, "data\t(%s(i),i=%3d,%3d)\t/", s, j + 1, (j + NDP_PERLINE < n) ? j + NDP_PERLINE : n); for (i = j; i < j + NDP_PERLINE && i < n; i++) { if ((i == j + NDP_PERLINE - 1) || i >= n - 1) fprintf (ftable, "%4d/\n", v[i]); else fprintf (ftable, "%4d,", v[i]); } } } static int gtnm () { int s, val, c; /* read and convert an integer from the standard input */ /* return the terminating character */ /* blanks, tabs, and newlines are ignored */ s = 1; val = 0; while ((c = getc (finput)) != EOF) { if (iswdigit (c)) val = val * 10 + c - '0'; else if (c == '-') s = -1; else break; } *optimmem++ = s * val; if (optimmem >= &tracemem[new_memsize]) exp_mem (0); return (c); } void exp_act (ptr) int **ptr; { static int *actbase; int i; new_actsize += ACTSIZE; actbase = amem; amem = (int *) realloc ((char *) amem, sizeof (int) * new_actsize); if (amem == NULL) /* * TRANSLATION_NOTE -- This is a message from yacc. * This message is passed to error() function. * * You may just translate this as: * 'Could not allocate internally used memory.' */ error ("couldn't expand action table"); for (i = new_actsize - ACTSIZE; i < new_actsize; ++i) amem[i] = 0; if (ptr != NULL) *ptr = *ptr - actbase + amem; if (memp >= amem) memp = memp - actbase + amem; if (maxa >= amem) maxa = maxa - actbase + amem; }