/***** spin: spinlex.c *****/ /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. *//* All Rights Reserved. This software is for educational purposes only. *//* No guarantee whatsoever is expressed or implied by the distribution of *//* this code. Permission is given to distribute this code provided that *//* this introductory message is not removed and no monies are exchanged. *//* Software written by Gerard J. Holzmann. For tool documentation see: *//* http://spinroot.com/ *//* Send all bug-reports and/or questions to: bugs@spinroot.com */ #include <stdlib.h>#include "spin.h"#include "y.tab.h" #define MAXINL 16 /* max recursion depth inline fcts */#define MAXPAR 32 /* max params to an inline call */#define MAXLEN 512 /* max len of an actual parameter text */ typedef struct IType { Symbol *nm; /* name of the type */ Lextok *cn; /* contents */ Lextok *params; /* formal pars if any */ char **anms; /* literal text for actual pars */ char *prec; /* precondition for c_code or c_expr */ int uiid; /* unique inline id */ int dln, cln; /* def and call linenr */ Symbol *dfn, *cfn; /* def and call filename */ struct IType *nxt; /* linked list */} IType; typedef struct C_Added { Symbol *s; Symbol *t; Symbol *ival; struct C_Added *nxt;} C_Added; extern RunList *X;extern ProcList *rdy;extern Symbol *Fname, *oFname;extern Symbol *context, *owner;extern YYSTYPE yylval;extern short has_last, has_code;extern int verbose, IArgs, hastrack, separate, ltl_mode; short has_stack = 0;int lineno = 1;int scope_seq[128], scope_level = 0;char CurScope[MAXSCOPESZ];char yytext[2048];FILE *yyin, *yyout; static C_Added *c_added, *c_tracked;static IType *Inline_stub[MAXINL];static char *ReDiRect;static char *Inliner[MAXINL], IArg_cont[MAXPAR][MAXLEN];static unsigned char in_comment=0;static int IArgno = 0, Inlining = -1;static int check_name(char *); #if 1#define Token(y) { if (in_comment) goto again; \ yylval = nn(ZN,0,ZN,ZN); return y; } #define ValToken(x, y) { if (in_comment) goto again; \ yylval = nn(ZN,0,ZN,ZN); yylval->val = x; return y; } #define SymToken(x, y) { if (in_comment) goto again; \ yylval = nn(ZN,0,ZN,ZN); yylval->sym = x; return y; }#else#define Token(y) { yylval = nn(ZN,0,ZN,ZN); \ if (!in_comment) return y; else goto again; } #define ValToken(x, y) { yylval = nn(ZN,0,ZN,ZN); yylval->val = x; \ if (!in_comment) return y; else goto again; } #define SymToken(x, y) { yylval = nn(ZN,0,ZN,ZN); yylval->sym = x; \ if (!in_comment) return y; else goto again; }#endif static int getinline(void);static void uninline(void); #if 1#define Getchar() ((Inlining<0)?getc(yyin):getinline())#define Ungetch(c) {if (Inlining<0) ungetc(c,yyin); else uninline();} #else static intGetchar(void){ int c; if (Inlining<0) c = getc(yyin); else c = getinline(); if (0) { printf("<%c:%d>[%d] ", c, c, Inlining); } else { printf("%c", c); } return c;} static voidUngetch(int c){ if (Inlining<0) ungetc(c,yyin); else uninline(); if (0) { printf("<bs>"); }}#endif static intnotdollar(int c){ return (c != '$' && c != '\n');} static intnotquote(int c){ return (c != '\"' && c != '\n');} intisalnum_(int c){ return (isalnum(c) || c == '_');} static intisalpha_(int c){ return isalpha(c); /* could be macro */} static intisdigit_(int c){ return isdigit(c); /* could be macro */} static voidgetword(int first, int (*tst)(int)){ int i=0, c; yytext[i++]= (char) first; while (tst(c = Getchar())) { yytext[i++] = (char) c; if (c == '\\') { c = Getchar(); yytext[i++] = (char) c; /* no tst */ } } yytext[i] = '\0'; Ungetch(c);} static intfollow(int tok, int ifyes, int ifno){ int c; if ((c = Getchar()) == tok) return ifyes; Ungetch(c); return ifno;} static IType *seqnames; static voiddef_inline(Symbol *s, int ln, char *ptr, char *prc, Lextok *nms){ IType *tmp; int cnt = 0; char *nw = (char *) emalloc(strlen(ptr)+1); strcpy(nw, ptr); for (tmp = seqnames; tmp; cnt++, tmp = tmp->nxt) if (!strcmp(s->name, tmp->nm->name)) { non_fatal("procedure name %s redefined", tmp->nm->name); tmp->cn = (Lextok *) nw; tmp->params = nms; tmp->dln = ln; tmp->dfn = Fname; return; } tmp = (IType *) emalloc(sizeof(IType)); tmp->nm = s; tmp->cn = (Lextok *) nw; tmp->params = nms; if (strlen(prc) > 0) { tmp->prec = (char *) emalloc(strlen(prc)+1); strcpy(tmp->prec, prc); } tmp->dln = ln; tmp->dfn = Fname; tmp->uiid = cnt+1; /* so that 0 means: not an inline */ tmp->nxt = seqnames; seqnames = tmp;} voidgencodetable(FILE *fd){ IType *tmp; char *q; int cnt; if (separate == 2) return; fprintf(fd, "struct {\n"); fprintf(fd, " char *c; char *t;\n"); fprintf(fd, "} code_lookup[] = {\n"); if (has_code) for (tmp = seqnames; tmp; tmp = tmp->nxt) if (tmp->nm->type == CODE_FRAG || tmp->nm->type == CODE_DECL) { fprintf(fd, "\t{ \"%s\", ", tmp->nm->name); q = (char *) tmp->cn; while (*q == '\n' || *q == '\r' || *q == '\\') q++; fprintf(fd, "\""); cnt = 0; while (*q && cnt < 1024) /* pangen1.h allows 2048 */ { switch (*q) { case '"': fprintf(fd, "\\\""); break; case '%': fprintf(fd, "%%"); break; case '\n': fprintf(fd, "\\n"); break; default: putc(*q, fd); break; } q++; cnt++; } if (*q) fprintf(fd, "..."); fprintf(fd, "\""); fprintf(fd, " },\n"); } fprintf(fd, " { (char *) 0, \"\" }\n"); fprintf(fd, "};\n");} static intiseqname(char *t){ IType *tmp; for (tmp = seqnames; tmp; tmp = tmp->nxt) { if (!strcmp(t, tmp->nm->name)) return 1; } return 0;} static intgetinline(void){ int c; if (ReDiRect) { c = *ReDiRect++; if (c == '\0') { ReDiRect = (char *) 0; c = *Inliner[Inlining]++; } } else c = *Inliner[Inlining]++; if (c == '\0') { lineno = Inline_stub[Inlining]->cln; Fname = Inline_stub[Inlining]->cfn; Inlining--;#if 0 if (verbose&32) printf("spin: %s:%d, done inlining %s\n", Fname, lineno, Inline_stub[Inlining+1]->nm->name);#endif return Getchar(); } return c;} static voiduninline(void){ if (ReDiRect) ReDiRect--; else Inliner[Inlining]--;} intis_inline(void){ if (Inlining < 0) return 0; /* i.e., not an inline */ if (Inline_stub[Inlining] == NULL) fatal("unexpected, inline_stub not set", 0); return Inline_stub[Inlining]->uiid;} IType *find_inline(char *s){ IType *tmp; for (tmp = seqnames; tmp; tmp = tmp->nxt) if (!strcmp(s, tmp->nm->name)) break; if (!tmp) fatal("cannot happen, missing inline def %s", s); return tmp;} voidc_state(Symbol *s, Symbol *t, Symbol *ival) /* name, scope, ival */{ C_Added *r; r = (C_Added *) emalloc(sizeof(C_Added)); r->s = s; /* pointer to a data object */ r->t = t; /* size of object, or "global", or "local proctype_name" */ r->ival = ival; r->nxt = c_added; c_added = r;} voidc_track(Symbol *s, Symbol *t, Symbol *stackonly) /* name, size */{ C_Added *r; r = (C_Added *) emalloc(sizeof(C_Added)); r->s = s; r->t = t; r->ival = stackonly; /* abuse of name */ r->nxt = c_tracked; c_tracked = r; if (stackonly != ZS) { if (strcmp(stackonly->name, "\"Matched\"") == 0) r->ival = ZS; /* the default */ else if (strcmp(stackonly->name, "\"UnMatched\"") != 0 && strcmp(stackonly->name, "\"unMatched\"") != 0 && strcmp(stackonly->name, "\"StackOnly\"") != 0) non_fatal("expecting '[Un]Matched', saw %s", stackonly->name); else has_stack = 1; /* unmatched stack */ }} char *jump_etc(char *op){ char *p = op; /* kludgy - try to get the type separated from the name */ while (*p == ' ' || *p == '\t') p++; /* initial white space */ while (*p != ' ' && *p != '\t') p++; /* type name */ while (*p == ' ' || *p == '\t') p++; /* white space */ while (*p == '*') p++; /* decorations */ while (*p == ' ' || *p == '\t') p++; /* white space */ if (*p == '\0') fatal("c_state format (%s)", op); if (strchr(p, '[') && !strchr(p, '{')) { non_fatal("array initialization error, c_state (%s)", p); return (char *) 0; } return p;} voidc_add_globinit(FILE *fd){ C_Added *r; char *p, *q; fprintf(fd, "void\nglobinit(void)\n{\n"); for (r = c_added; r; r = r->nxt) { if (r->ival == ZS) continue; if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0) { for (q = r->ival->name; *q; q++) { if (*q == '\"') *q = ' '; if (*q == '\\') *q++ = ' '; /* skip over the next */ } p = jump_etc(r->s->name); /* e.g., "int **q" */ if (p) fprintf(fd, " now.%s = %s;\n", p, r->ival->name); } else if (strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0) { for (q = r->ival->name; *q; q++) { if (*q == '\"') *q = ' '; if (*q == '\\') *q++ = ' '; /* skip over the next */ } p = jump_etc(r->s->name); /* e.g., "int **q" */ if (p) fprintf(fd, " %s = %s;\n", p, r->ival->name); /* no now. prefix */ } } fprintf(fd, "}\n");} voidc_add_locinit(FILE *fd, int tpnr, char *pnm){ C_Added *r; char *p, *q, *s; int frst = 1; fprintf(fd, "void\nlocinit%d(int h)\n{\n", tpnr); for (r = c_added; r; r = r->nxt) if (r->ival != ZS && strncmp(r->t->name, " Local", strlen(" Local")) == 0) { for (q = r->ival->name; *q; q++) if (*q == '\"') *q = ' '; p = jump_etc(r->s->name); /* e.g., "int **q" */ q = r->t->name + strlen(" Local"); while (*q == ' ' || *q == '\t') q++; /* process name */ s = (char *) emalloc(strlen(q)+1); strcpy(s, q); q = &s[strlen(s)-1]; while (*q == ' ' || *q == '\t') *q-- = '\0'; if (strcmp(pnm, s) != 0) continue; if (frst) { fprintf(fd, "\tuchar *this = pptr(h);\n"); frst = 0; } if (p) fprintf(fd, " ((P%d *)this)->%s = %s;\n", tpnr, p, r->ival->name); } fprintf(fd, "}\n");} /* tracking: 1. for non-global and non-local c_state decls: add up all the sizes in c_added 2. add a global char array of that size into now 3. generate a routine that memcpy's the required values into that array 4. generate a call to that routine */ voidc_preview(void){ C_Added *r; hastrack = 0; if (c_tracked) hastrack = 1; else for (r = c_added; r; r = r->nxt) if (strncmp(r->t->name, " Global ", strlen(" Global ")) != 0 && strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) != 0 && strncmp(r->t->name, " Local", strlen(" Local")) != 0) { hastrack = 1; /* c_state variant now obsolete */ break; }} intc_add_sv(FILE *fd) /* 1+2 -- called in pangen1.c */{ C_Added *r; int cnt = 0; if (!c_added && !c_tracked) return 0; Lines 1–500 of 1521. Load more
/***** spin: spinlex.c *****/ /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */ /* All Rights Reserved. This software is for educational purposes only. */ /* No guarantee whatsoever is expressed or implied by the distribution of */ /* this code. Permission is given to distribute this code provided that */ /* this introductory message is not removed and no monies are exchanged. */ /* Software written by Gerard J. Holzmann. For tool documentation see: */ /* http://spinroot.com/ */ /* Send all bug-reports and/or questions to: bugs@spinroot.com */ #include <stdlib.h> #include "spin.h" #include "y.tab.h" #define MAXINL 16 /* max recursion depth inline fcts */ #define MAXPAR 32 /* max params to an inline call */ #define MAXLEN 512 /* max len of an actual parameter text */ typedef struct IType { Symbol *nm; /* name of the type */ Lextok *cn; /* contents */ Lextok *params; /* formal pars if any */ char **anms; /* literal text for actual pars */ char *prec; /* precondition for c_code or c_expr */ int uiid; /* unique inline id */ int dln, cln; /* def and call linenr */ Symbol *dfn, *cfn; /* def and call filename */ struct IType *nxt; /* linked list */ } IType; typedef struct C_Added { Symbol *s; Symbol *t; Symbol *ival; struct C_Added *nxt; } C_Added; extern RunList *X; extern ProcList *rdy; extern Symbol *Fname, *oFname; extern Symbol *context, *owner; extern YYSTYPE yylval; extern short has_last, has_code; extern int verbose, IArgs, hastrack, separate, ltl_mode; short has_stack = 0; int lineno = 1; int scope_seq[128], scope_level = 0; char CurScope[MAXSCOPESZ]; char yytext[2048]; FILE *yyin, *yyout; static C_Added *c_added, *c_tracked; static IType *Inline_stub[MAXINL]; static char *ReDiRect; static char *Inliner[MAXINL], IArg_cont[MAXPAR][MAXLEN]; static unsigned char in_comment=0; static int IArgno = 0, Inlining = -1; static int check_name(char *); #if 1 #define Token(y) { if (in_comment) goto again; \ yylval = nn(ZN,0,ZN,ZN); return y; } #define ValToken(x, y) { if (in_comment) goto again; \ yylval = nn(ZN,0,ZN,ZN); yylval->val = x; return y; } #define SymToken(x, y) { if (in_comment) goto again; \ yylval = nn(ZN,0,ZN,ZN); yylval->sym = x; return y; } #else #define Token(y) { yylval = nn(ZN,0,ZN,ZN); \ if (!in_comment) return y; else goto again; } #define ValToken(x, y) { yylval = nn(ZN,0,ZN,ZN); yylval->val = x; \ if (!in_comment) return y; else goto again; } #define SymToken(x, y) { yylval = nn(ZN,0,ZN,ZN); yylval->sym = x; \ if (!in_comment) return y; else goto again; } #endif static int getinline(void); static void uninline(void); #if 1 #define Getchar() ((Inlining<0)?getc(yyin):getinline()) #define Ungetch(c) {if (Inlining<0) ungetc(c,yyin); else uninline();} #else static int Getchar(void) { int c; if (Inlining<0) c = getc(yyin); else c = getinline(); if (0) { printf("<%c:%d>[%d] ", c, c, Inlining); } else { printf("%c", c); } return c; } static void Ungetch(int c) { if (Inlining<0) ungetc(c,yyin); else uninline(); if (0) { printf("<bs>"); } } #endif static int notdollar(int c) { return (c != '$' && c != '\n'); } static int notquote(int c) { return (c != '\"' && c != '\n'); } int isalnum_(int c) { return (isalnum(c) || c == '_'); } static int isalpha_(int c) { return isalpha(c); /* could be macro */ } static int isdigit_(int c) { return isdigit(c); /* could be macro */ } static void getword(int first, int (*tst)(int)) { int i=0, c; yytext[i++]= (char) first; while (tst(c = Getchar())) { yytext[i++] = (char) c; if (c == '\\') { c = Getchar(); yytext[i++] = (char) c; /* no tst */ } } yytext[i] = '\0'; Ungetch(c); } static int follow(int tok, int ifyes, int ifno) { int c; if ((c = Getchar()) == tok) return ifyes; Ungetch(c); return ifno; } static IType *seqnames; static void def_inline(Symbol *s, int ln, char *ptr, char *prc, Lextok *nms) { IType *tmp; int cnt = 0; char *nw = (char *) emalloc(strlen(ptr)+1); strcpy(nw, ptr); for (tmp = seqnames; tmp; cnt++, tmp = tmp->nxt) if (!strcmp(s->name, tmp->nm->name)) { non_fatal("procedure name %s redefined", tmp->nm->name); tmp->cn = (Lextok *) nw; tmp->params = nms; tmp->dln = ln; tmp->dfn = Fname; return; } tmp = (IType *) emalloc(sizeof(IType)); tmp->nm = s; tmp->cn = (Lextok *) nw; tmp->params = nms; if (strlen(prc) > 0) { tmp->prec = (char *) emalloc(strlen(prc)+1); strcpy(tmp->prec, prc); } tmp->dln = ln; tmp->dfn = Fname; tmp->uiid = cnt+1; /* so that 0 means: not an inline */ tmp->nxt = seqnames; seqnames = tmp; } void gencodetable(FILE *fd) { IType *tmp; char *q; int cnt; if (separate == 2) return; fprintf(fd, "struct {\n"); fprintf(fd, " char *c; char *t;\n"); fprintf(fd, "} code_lookup[] = {\n"); if (has_code) for (tmp = seqnames; tmp; tmp = tmp->nxt) if (tmp->nm->type == CODE_FRAG || tmp->nm->type == CODE_DECL) { fprintf(fd, "\t{ \"%s\", ", tmp->nm->name); q = (char *) tmp->cn; while (*q == '\n' || *q == '\r' || *q == '\\') q++; fprintf(fd, "\""); cnt = 0; while (*q && cnt < 1024) /* pangen1.h allows 2048 */ { switch (*q) { case '"': fprintf(fd, "\\\""); break; case '%': fprintf(fd, "%%"); break; case '\n': fprintf(fd, "\\n"); break; default: putc(*q, fd); break; } q++; cnt++; } if (*q) fprintf(fd, "..."); fprintf(fd, "\""); fprintf(fd, " },\n"); } fprintf(fd, " { (char *) 0, \"\" }\n"); fprintf(fd, "};\n"); } static int iseqname(char *t) { IType *tmp; for (tmp = seqnames; tmp; tmp = tmp->nxt) { if (!strcmp(t, tmp->nm->name)) return 1; } return 0; } static int getinline(void) { int c; if (ReDiRect) { c = *ReDiRect++; if (c == '\0') { ReDiRect = (char *) 0; c = *Inliner[Inlining]++; } } else c = *Inliner[Inlining]++; if (c == '\0') { lineno = Inline_stub[Inlining]->cln; Fname = Inline_stub[Inlining]->cfn; Inlining--; #if 0 if (verbose&32) printf("spin: %s:%d, done inlining %s\n", Fname, lineno, Inline_stub[Inlining+1]->nm->name); #endif return Getchar(); } return c; } static void uninline(void) { if (ReDiRect) ReDiRect--; else Inliner[Inlining]--; } int is_inline(void) { if (Inlining < 0) return 0; /* i.e., not an inline */ if (Inline_stub[Inlining] == NULL) fatal("unexpected, inline_stub not set", 0); return Inline_stub[Inlining]->uiid; } IType * find_inline(char *s) { IType *tmp; for (tmp = seqnames; tmp; tmp = tmp->nxt) if (!strcmp(s, tmp->nm->name)) break; if (!tmp) fatal("cannot happen, missing inline def %s", s); return tmp; } void c_state(Symbol *s, Symbol *t, Symbol *ival) /* name, scope, ival */ { C_Added *r; r = (C_Added *) emalloc(sizeof(C_Added)); r->s = s; /* pointer to a data object */ r->t = t; /* size of object, or "global", or "local proctype_name" */ r->ival = ival; r->nxt = c_added; c_added = r; } void c_track(Symbol *s, Symbol *t, Symbol *stackonly) /* name, size */ { C_Added *r; r = (C_Added *) emalloc(sizeof(C_Added)); r->s = s; r->t = t; r->ival = stackonly; /* abuse of name */ r->nxt = c_tracked; c_tracked = r; if (stackonly != ZS) { if (strcmp(stackonly->name, "\"Matched\"") == 0) r->ival = ZS; /* the default */ else if (strcmp(stackonly->name, "\"UnMatched\"") != 0 && strcmp(stackonly->name, "\"unMatched\"") != 0 && strcmp(stackonly->name, "\"StackOnly\"") != 0) non_fatal("expecting '[Un]Matched', saw %s", stackonly->name); else has_stack = 1; /* unmatched stack */ } } char * jump_etc(char *op) { char *p = op; /* kludgy - try to get the type separated from the name */ while (*p == ' ' || *p == '\t') p++; /* initial white space */ while (*p != ' ' && *p != '\t') p++; /* type name */ while (*p == ' ' || *p == '\t') p++; /* white space */ while (*p == '*') p++; /* decorations */ while (*p == ' ' || *p == '\t') p++; /* white space */ if (*p == '\0') fatal("c_state format (%s)", op); if (strchr(p, '[') && !strchr(p, '{')) { non_fatal("array initialization error, c_state (%s)", p); return (char *) 0; } return p; } void c_add_globinit(FILE *fd) { C_Added *r; char *p, *q; fprintf(fd, "void\nglobinit(void)\n{\n"); for (r = c_added; r; r = r->nxt) { if (r->ival == ZS) continue; if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0) { for (q = r->ival->name; *q; q++) { if (*q == '\"') *q = ' '; if (*q == '\\') *q++ = ' '; /* skip over the next */ } p = jump_etc(r->s->name); /* e.g., "int **q" */ if (p) fprintf(fd, " now.%s = %s;\n", p, r->ival->name); } else if (strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0) { for (q = r->ival->name; *q; q++) { if (*q == '\"') *q = ' '; if (*q == '\\') *q++ = ' '; /* skip over the next */ } p = jump_etc(r->s->name); /* e.g., "int **q" */ if (p) fprintf(fd, " %s = %s;\n", p, r->ival->name); /* no now. prefix */ } } fprintf(fd, "}\n"); } void c_add_locinit(FILE *fd, int tpnr, char *pnm) { C_Added *r; char *p, *q, *s; int frst = 1; fprintf(fd, "void\nlocinit%d(int h)\n{\n", tpnr); for (r = c_added; r; r = r->nxt) if (r->ival != ZS && strncmp(r->t->name, " Local", strlen(" Local")) == 0) { for (q = r->ival->name; *q; q++) if (*q == '\"') *q = ' '; p = jump_etc(r->s->name); /* e.g., "int **q" */ q = r->t->name + strlen(" Local"); while (*q == ' ' || *q == '\t') q++; /* process name */ s = (char *) emalloc(strlen(q)+1); strcpy(s, q); q = &s[strlen(s)-1]; while (*q == ' ' || *q == '\t') *q-- = '\0'; if (strcmp(pnm, s) != 0) continue; if (frst) { fprintf(fd, "\tuchar *this = pptr(h);\n"); frst = 0; } if (p) fprintf(fd, " ((P%d *)this)->%s = %s;\n", tpnr, p, r->ival->name); } fprintf(fd, "}\n"); } /* tracking: 1. for non-global and non-local c_state decls: add up all the sizes in c_added 2. add a global char array of that size into now 3. generate a routine that memcpy's the required values into that array 4. generate a call to that routine */ void c_preview(void) { C_Added *r; hastrack = 0; if (c_tracked) hastrack = 1; else for (r = c_added; r; r = r->nxt) if (strncmp(r->t->name, " Global ", strlen(" Global ")) != 0 && strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) != 0 && strncmp(r->t->name, " Local", strlen(" Local")) != 0) { hastrack = 1; /* c_state variant now obsolete */ break; } } int c_add_sv(FILE *fd) /* 1+2 -- called in pangen1.c */ { C_Added *r; int cnt = 0; if (!c_added && !c_tracked) return 0;