/* This file is in the public domain. */ static const char def_prefix_file[] = PFXFILE; #include #include #include #include extern const char *__progname; #include #include "defs.h" #include "tok.h" #include "lex-externs.h" #include "yacc-externs.h" #define UNUSED_ARG(x) x __attribute__((__unused__)) #define TRIG_ANY (-1) #define TRIG_ANYOF (-2) #define TRIG_BINARY (-3) #define TRIG_DECIMAL (-4) #define TRIG_DIGIT (-5) #define TRIG_EOS (-6) #define TRIG_HEX (-7) #define TRIG_LAMBDA (-8) #define TRIG_OCTAL (-9) #define TRIG_STRING (-10) #define TRIG_SUBEXP (-11) #define TRIG_SYMBOL (-12) typedef struct state STATE; typedef struct tran TRAN; typedef struct tran_list TRAN_LIST; typedef struct anyof ANYOF; struct state { STATE *nflink; STATE *nblink; STATE *aflink; STATE *ablink; char *name; char defined; unsigned short int number; TRAN *trans; TRAN *last_tran; TRAN_LIST *into; } ; struct tran_list { TRAN_LIST *link; TRAN *ptr; } ; struct tran { TRAN *link; signed char trigger; char condition; union { STATE *subexp; struct { int maxlen; char *first; char *second; } string; ANYOF *anyof; } trig_aux; STATE *next; char *action; int actargs; int actargat; } ; struct anyof { ANYOF *link; char *name; int number; char in[256]; } *anyof; static STATE s__exit; #define NEXT_EXIT (&s__exit) static STATE s__fail; #define NEXT_FAIL (&s__fail) static char *pfx; static char *trace_fxn; static char *action_fxn; static char *initial_fxn; static const char *prefix_file; static STATE *this_state; static STATE *next_state; static STATE *first_state; static STATE listhead; static ANYOF *anyofs; static ANYOF *last_anyof; static int needed; #define NEED_CMP 0x01 #define NEED_HEX 0x02 #define NEED_REC 0x04 #define NEED_TRC 0x08 #define NEED_INI 0x10 #if 0 static char *getc_routine; #endif void copy_in(char **dest, const char *src) { if (*dest) free(*dest); *dest = malloc(strlen(src)+1); strcpy(*dest,src); } static void pfxfile_skip(FILE *f) { int istilde; int c; istilde = 0; while (1) { c = getc(f); if (c == EOF) break; if (istilde && (c == '\\')) break; istilde = (c == '~'); } } static void write_action_cond(TRAN *tran) { if (tran->action && tran->condition) { printf("char*%ssave=%sinp->string;\n",pfx,pfx); } } static int bqvw(UNUSED_ARG(void *cookie), const char *s, int len) { int n; for (n=0;len>0;len--,s++,n++) { switch (*s) { case '"': case '\\': putchar('\\'); break; } putchar(*s); } return(n); } static void backslash_quote_vprintf(const char *, va_list) __attribute__ ((__format__(printf,1,0))); static void backslash_quote_vprintf(const char *fmt, va_list ap) { FILE *f; f = fwopen(0,bqvw); vfprintf(f,fmt,ap); fclose(f); } static void write_action(TRAN *, const char *, ...) __attribute__ ((__format__(printf,2,3))); static void write_action(TRAN *tran, const char *fmt, ...) { va_list ap; int i; va_start(ap,fmt); if (tran->action) { if (action_fxn) { const char *s; printf("\t\t\t\t\t%s(\"",action_fxn); for (s=tran->action,i=0;*s;s++,i++) { if (tran->actargs && (i == tran->actargat)) { backslash_quote_vprintf(fmt,ap); } switch (*s) { case '"': case '\\': putchar('\\'); break; } putchar(*s); } if (! tran->actargs) printf("()"); printf("\");\n"); } if (tran->condition) { if (tran->actargs) { if (tran->actargat >= 0) { printf("if(!\t\t\t\t\t%.*s",tran->actargat,tran->action); vprintf(fmt,ap); printf("%s ){\n"/*}*/,tran->action+tran->actargat); } else { printf("if(!\t\t\t\t\t%s ){\n"/*}*/,tran->action); } } else { printf("if(!\t\t\t\t\t%s() ){\n"/*}*/,tran->action); } printf("%sinp->string=%ssave;\n",pfx,pfx); printf(/*{*/"}else{\n"/*}*/); } else { if (tran->actargs) { if (tran->actargat >= 0) { printf("\t\t\t\t\t%.*s",tran->actargat,tran->action); vprintf(fmt,ap); printf("%s ;{\n"/*}*/,tran->action+tran->actargat); } else { printf("\t\t\t\t\t%s ;{\n"/*}*/,tran->action); } } else { printf("\t\t\t\t\t%s() ;{\n"/*}*/,tran->action); } } } else { printf("{\n"/*}*/); } va_end(ap); } int main(void); int main(void) { STATE *sp; TRAN *tp; int i; FILE *f; char c; int max_string_len; line_no = 1; tran_string = 0; tran_string_1 = 0; this_state = 0; next_state = 0; first_state = 0; listhead.nflink = &listhead; listhead.nblink = &listhead; listhead.aflink = &listhead; listhead.ablink = &listhead; pfx = 0; trace_fxn = 0; action_fxn = 0; initial_fxn = 0; anyofs = 0; needed = 0; copy_in(&pfx,"FSM"); set_lex_nrm(); yyparse(); i = 0; for (sp=listhead.aflink;sp!=&listhead;sp=sp->aflink) { i ++; if (sp->number && (sp != first_state)) { fprintf(stderr,"Warning: unreachable un-named state %d\n",i); } sp->number = i; } prefix_file = def_prefix_file; f = fopen(prefix_file,"r"); if (f == 0) { fprintf(stderr,"Sorry, can't open %s\n",prefix_file); exit(1); } max_string_len = 0; for (sp=listhead.aflink;sp!=&listhead;sp=sp->aflink) { for (tp=sp->trans;tp;tp=tp->link) { if ((tp->trigger == TRIG_STRING) && tp->action && (tp->trig_aux.string.maxlen > max_string_len)) { max_string_len = tp->trig_aux.string.maxlen; /* fprintf(stderr,"new max string len: state %d (%s), tran trigger %d: %d\n", sp->number,sp->name?sp->name:"no name",tp->trigger,max_string_len); */ } } } while ((c=getc(f)),(!feof(f))) { if (c == '~') { c = getc(f); switch (c) { default: fprintf(stderr,"Prefix file has unrecognized escape ~%c\n",c); exit(1); break; case 'a': { ANYOF *ap; register int count = 0; register int i; register int j; for (ap=anyofs;ap;ap=ap->link) { printf("static char %sanyof%d[128] = {\n"/*}*/, pfx,ap->number=count++); for (j=0;j<128;j+=32) { for (i=0;i<32;i++) { printf("%d%s",ap->in[i+j],(i+j==127)?/*{*/"};":","); } putchar('\n'); } } } break; case 'd': pfxfile_skip(f); break; case 'f': printf("%d",first_state->number); break; case 'n': { int bit; c = getc(f); switch (c) { case 'c': bit = NEED_CMP; break; case 'i': bit = NEED_INI; break; case 'r': bit = NEED_REC; break; case 't': bit = NEED_TRC; break; case 'x': bit = NEED_HEX; break; default: bit = 0; break; } if (! (needed & bit)) pfxfile_skip(f); } break; case 'p': printf("%s",pfx); break; case 'z': if (max_string_len > 0) { printf(" static char %stmp[%d];\n\n",pfx,max_string_len+1); } break; case '\\': /* ignore - a true ~n is ignored, not stacked */ break; case 'I': printf("%s",initial_fxn); break; case 'S': printf("%s",trace_fxn); break; case 'T': { int maxnum; int i; int col; STATE **numbers; STATE *s; char buf[64]; maxnum = 0; for (s=listhead.aflink;s!=&listhead;s=s->aflink) { if (maxnum < s->number) { maxnum = s->number; } } maxnum ++; numbers = (STATE **) malloc(maxnum*sizeof(STATE *)); for (i=0;iaflink) { numbers[s->number] = s; } printf("static const char *%sstatenames[%d] = \n",pfx,maxnum); col = 0; for (i=0;iname) { cp = numbers[i]->name; } else { sprintf(buf,"State %d",i); cp = buf; } l = strlen(cp); if (col+2+l+1 > 75) { printf("\n"); col = 0; } printf(" \"%s\"",cp); col += 2 + l + 1; } printf(/*{*/" };\n"); } break; } } else { putchar(c); } } fclose(f); for (sp=listhead.aflink;sp!=&listhead;sp=sp->aflink) { if (! sp->defined) { if (sp->name) { fprintf(stderr,"Warning: state `%s' undefined\n",sp->name); } else { fprintf(stderr,"Warning: undefined unnamed state\n"); fprintf(stderr, " (probably `unspecified next' transition on the last state)\n"); } } if (!sp->into && (sp != first_state)) { if (sp->name) { fprintf(stderr,"Warning: no way to reach state `%s'\n",sp->name); } else { fprintf(stderr,"Warning: no way to reach state #%d\n",sp->number); } } printf( sp->name?"\t\t\t\tcase %d: /* %s */\n":"\t\t\t\tcase %d:\n", sp->number, sp->name ); for (tp=sp->trans;tp;tp=tp->link) { if (tp->trigger >= 0) { const char *fmt; if (tp->trigger < ' ') { fmt = "if(%schar=='\\%03o'){\n\t\t\t\t\t/* '\\%03o' */\n"/*}*/; } else if (tp->trigger == '\177') { fmt = "if(%schar=='\\177'){\n\t\t\t\t\t/* '\\177' */\n"/*}*/; } else if ((tp->trigger == '\'') || (tp->trigger == '\\')) { fmt = "if(%schar=='\\%c'){\n\t\t\t\t\t/* '\\%c' */\n"/*}*/; } else { fmt = "if(%schar=='%c'){\n\t\t\t\t\t/* '%c' */\n"/*}*/; } printf(fmt,pfx,tp->trigger,tp->trigger); write_action_cond(tp); write_action(tp,"%schar",pfx); printf("%sget;\n",pfx); } else if (tp->trigger == TRIG_ANY) { printf("if(%schar!='\\0'){\n\t\t\t\t\t/* $any */\n"/*}*/,pfx); write_action_cond(tp); write_action(tp,"%schar",pfx); printf("%sget;\n",pfx); } else if (tp->trigger == TRIG_ANYOF) { printf("if(%sanyof%d[%schar]){\n"/*}*/, pfx,tp->trig_aux.anyof->number,pfx); printf("\t\t\t\t\t/* $anyof %s */\n",tp->trig_aux.anyof->name); write_action_cond(tp); write_action(tp,"%schar",pfx); printf("%sget;\n",pfx); } else if (tp->trigger == TRIG_BINARY) { printf( "if((%schar=='1')||(%schar=='0')){\n\t\t\t\t\t/* $binary */\n"/*}*/, pfx,pfx); write_action_cond(tp); printf("unsigned long int %si=%schar-'0';\n",pfx,pfx); printf("while((%sget==0)||(%schar=='1'))\n",pfx,pfx); printf("%si=(%si<<1)+%schar-'0';\n",pfx,pfx,pfx); write_action(tp,"%si",pfx); } else if (tp->trigger == TRIG_DECIMAL) { printf("if(isdigit(%schar)){\n\t\t\t\t\t/* $decimal */\n"/*}*/,pfx); write_action_cond(tp); printf("unsigned long int %si=%schar-'0';\n",pfx,pfx); printf("while(isdigit(%sget))\n",pfx); printf("%si=(%si*10)+%schar-'0';\n",pfx,pfx,pfx); write_action(tp,"%si",pfx); } else if (tp->trigger == TRIG_DIGIT) { printf("if(isdigit(%schar)){\n\t\t\t\t\t/* $digit */\n"/*}*/,pfx); write_action_cond(tp); write_action(tp,"%schar",pfx); printf("%sget;\n",pfx); } else if (tp->trigger == TRIG_EOS) { printf("if(%schar=='\\0'){\n\t\t\t\t\t/* $eos */\n"/*}*/,pfx); write_action_cond(tp); write_action(tp,"0"); } else if (tp->trigger == TRIG_HEX) { printf("if(isxdigit(%schar)){\n\t\t\t\t\t/* $hex */\n"/*}*/,pfx); write_action_cond(tp); printf("unsigned long int %si=%sxval(%schar);\n",pfx,pfx,pfx); printf("while(isxdigit(%sget))\n",pfx); printf("%si=(%si<<4)+%sxval(%schar);\n",pfx,pfx,pfx,pfx); write_action(tp,"%si",pfx); } else if (tp->trigger == TRIG_LAMBDA) { printf("if(1){\n\t\t\t\t\t/* $lambda */\n"/*}*/); write_action_cond(tp); write_action(tp,"0"); } else if (tp->trigger == TRIG_OCTAL) { printf( "if((%schar<='7')&&(%schar>='0')){\n\t\t\t\t\t/* $octal */\n"/*}*/, pfx,pfx); write_action_cond(tp); printf("unsigned long int %si=%schar-'0';\n",pfx,pfx); printf("while(isdigit(%sget)&&(%schar<='7'))\n",pfx,pfx); printf("%si=(%si<<3)+%schar-'0';\n",pfx,pfx,pfx); write_action(tp,"%si",pfx); } else if (tp->trigger == TRIG_STRING) { printf("if(%scmp(%sinp,%s,%s,", pfx,pfx, tp->trig_aux.string.first, tp->trig_aux.string.second ? tp->trig_aux.string.second : "0" ); if (tp->action) printf("&%stmp[0]",pfx); else printf("0"); printf(")){\n\t\t\t\t\t"/*}*/); if (tp->trig_aux.string.second) { printf("/* %s * %s */\n",tp->trig_aux.string.first,tp->trig_aux.string.second); } else { printf("/* %s */\n",tp->trig_aux.string.first); } write_action_cond(tp); write_action(tp,"&%stmp[0]",pfx); } else if (tp->trigger == TRIG_SUBEXP) { printf("if(%srec(%sinp,%d)){\n\t\t\t\t\t/* !%s */\n"/*}*/, pfx,pfx, tp->trig_aux.subexp->number, tp->trig_aux.subexp->name); write_action_cond(tp); write_action(tp,"0"); } else if (tp->trigger == TRIG_SYMBOL) { printf("if(isalpha(%schar)||\n\t\t\t\t\t/* $symbol */\n",pfx); printf("(%schar=='$')||\n",pfx); printf("(%schar=='_')){\n"/*}*/,pfx); write_action_cond(tp); printf("char %sstr[256];int %si=0;\n",pfx,pfx); printf("do %sstr[%si++]=%schar;\n",pfx,pfx,pfx); printf("while(isalnum(%sget)||\n",pfx); printf("(%schar=='$')||\n",pfx); printf("(%schar=='_'));\n",pfx); printf("%sstr[%si]='\\0';\n",pfx,pfx); write_action(tp,"%sstr",pfx); } if (tp->next == NEXT_EXIT) { printf(/*{{*/"return(1);}}\n\t\t\t\t\t/* ... -> $exit */\n"); } else if (tp->next == NEXT_FAIL) { printf(/*{{*/"return(0);}}\n\t\t\t\t\t/* ... -> $fail */\n"); } else { printf(/*{{*/"%sstate=%d;break;}}\n\t\t\t\t\t/* ... -> %s */\n", pfx, tp->next->number, tp->next->name?tp->next->name:"[next state]"); } } printf("return(0);break;\n"); } printf(/*{{{*/"}}}\n"); exit(0); } void yyerror(UNUSED_ARG(const char *s)) { } void synx_error(void) { fprintf(stderr,"%s: syntax error, line %d\n",__progname,line_no); } void unnamed_state(void) { this_state = next_state; if (this_state) { next_state = 0; } else { this_state = malloc(sizeof(STATE)); this_state->name = 0; this_state->trans = 0; this_state->last_tran = 0; this_state->into = 0; this_state->number = 1; } this_state->defined = 1; this_state->aflink = &listhead; this_state->ablink = listhead.ablink; this_state->aflink->ablink = this_state; this_state->ablink->aflink = this_state; if (first_state == 0) { first_state = this_state; } } static STATE *find_state(const char *name, int create) { STATE *sp; for (sp=listhead.nflink;sp!=&listhead;sp=sp->nflink) { if (strcmp(sp->name,name) == 0) { return(sp); } } if (create) { sp = malloc(sizeof(STATE)); sp->aflink = &listhead; sp->ablink = listhead.ablink; sp->ablink->aflink = sp; sp->aflink->ablink = sp; sp->nflink = &listhead; sp->nblink = listhead.nblink; sp->nblink->nflink = sp; sp->nflink->nblink = sp; sp->trans = 0; sp->last_tran = 0; sp->defined = 0; sp->into = 0; sp->number = 0; sp->name = malloc(strlen(name)+1); strcpy(sp->name,name); return(sp); } return(0); } static void into_fix(TRAN *tran, STATE *old, STATE *new) { if (tran->next == old) tran->next = new; if ((tran->trigger == TRIG_SUBEXP) && (tran->trig_aux.subexp == old)) { tran->trig_aux.subexp = new; } } /* here we must be careful in case some named state is an unspecified next state (ie. is both next_state and found by find_state). This is what into_fix is all about. */ void named_state(void) { STATE *sp; this_state = next_state; if (this_state) { next_state = 0; } else { this_state = malloc(sizeof(STATE)); this_state->name = 0; this_state->trans = 0; this_state->last_tran = 0; this_state->into = 0; this_state->number = 0; } sp = find_state(tran_string,0); if (sp) { TRAN_LIST *tlp; if (sp->into) { for (tlp=sp->into;tlp->link;tlp=tlp->link) { into_fix(tlp->ptr,sp,this_state); } into_fix(tlp->ptr,sp,this_state); tlp->link = this_state->into; this_state->into = sp->into; } sp->ablink->aflink = sp->aflink; sp->aflink->ablink = sp->ablink; sp->nblink->nflink = sp->nflink; sp->nflink->nblink = sp->nblink; free(sp->name); free(sp); } this_state->defined = 1; this_state->aflink = &listhead; this_state->ablink = listhead.ablink; this_state->ablink->aflink = this_state; this_state->aflink->ablink = this_state; this_state->nflink = &listhead; this_state->nblink = listhead.nblink; this_state->nblink->nflink = this_state; this_state->nflink->nblink = this_state; this_state->name = malloc(strlen(tran_string)+1); strcpy(this_state->name,tran_string); if (first_state == 0) { first_state = this_state; } } void transition(void) { TRAN *tp; tp = malloc(sizeof(TRAN)); tp->link = 0; if (this_state->trans == 0) { this_state->trans = this_state->last_tran = tp; } else { this_state->last_tran->link = tp; this_state->last_tran = tp; } tp->trigger = 0; } void set_prefix(void) { copy_in(&pfx,tran_string); } void set_trace(void) { copy_in(&trace_fxn,tran_string); needed |= NEED_TRC; } void set_action(void) { copy_in(&action_fxn,tran_string); } void set_initial(void) { copy_in(&initial_fxn,tran_string); needed |= NEED_INI; } static ANYOF *find_anyof(const char *name, int create) { ANYOF *ap; for (ap=anyofs;ap;ap=ap->link) { if (strcmp(name,ap->name) == 0) { return(ap); } } if (create) { ap = malloc(sizeof(ANYOF)); ap->link = anyofs; anyofs = ap; ap->name = malloc(strlen(name)+1); strcpy(ap->name,name); bzero(ap->in,sizeof(ap->in)); return(ap); } return(0); } void begin_anyof(void) { last_anyof = find_anyof(tran_string,1); set_lex_flush(); } void store_anyof_char(void) { last_anyof->in[tran_char] = 1; } void end_anyof(void) { set_lex_nrm(); } void store_trigger(void) { TRAN_LIST *tlp; switch (tran_char) { case '!': if (this_state->last_tran->trigger == TRIG_SUBEXP) { STATE *sp; sp = find_state(tran_string,1); this_state->last_tran->trig_aux.subexp = sp; tlp = malloc(sizeof(TRAN_LIST)); tlp->link = sp->into; sp->into = tlp; tlp->ptr = this_state->last_tran; } else { this_state->last_tran->trigger = tran_char; } break; case Any: this_state->last_tran->trigger = TRIG_ANY; break; case Anyof: this_state->last_tran->trigger = TRIG_ANYOF; this_state->last_tran->trig_aux.anyof = last_anyof; break; case Binary: this_state->last_tran->trigger = TRIG_BINARY; break; case Digit: this_state->last_tran->trigger = TRIG_DIGIT; break; case Decimal: this_state->last_tran->trigger = TRIG_DECIMAL; break; case Eos: this_state->last_tran->trigger = TRIG_EOS; break; case Hex: this_state->last_tran->trigger = TRIG_HEX; needed |= NEED_HEX; break; case Lambda: this_state->last_tran->trigger = TRIG_LAMBDA; break; case Octal: this_state->last_tran->trigger = TRIG_OCTAL; break; case String: this_state->last_tran->trigger = TRIG_STRING; this_state->last_tran->trig_aux.string.first = malloc(strlen(tran_string_1)+1); strcpy(this_state->last_tran->trig_aux.string.first,tran_string_1); if (two_strings) { this_state->last_tran->trig_aux.string.second = malloc(strlen(tran_string)+1); strcpy(this_state->last_tran->trig_aux.string.second,tran_string); this_state->last_tran->trig_aux.string.maxlen = strlen(tran_string_1) + strlen(tran_string) - 4; /* fprintf(stderr,"state %d maxlen %d (%s + %s)\n", this_state->number, this_state->last_tran->trig_aux.string.maxlen, tran_string_1, tran_string ); */ } else { this_state->last_tran->trig_aux.string.second = 0; this_state->last_tran->trig_aux.string.maxlen = strlen(tran_string_1) - 2; /* fprintf(stderr,"state %d maxlen %d (%s)\n", this_state->number, this_state->last_tran->trig_aux.string.maxlen, tran_string_1 ); */ } needed |= NEED_CMP; break; case Symbol: this_state->last_tran->trigger = TRIG_SYMBOL; break; default: this_state->last_tran->trigger = tran_char; break; } } void set_anyof_trigger(void) { tran_char = Anyof; last_anyof = find_anyof(tran_string,0); } void first_string_set(void) { copy_in(&tran_string_1,tran_string); copy_in(&tran_string,""); two_strings = 0; } void second_string_set(void) { two_strings = 1; } void string_action(int n) { printf("string_action %d, this_state %s\n",n,this_state->name?:"(unnamed)"); } void set_string_trigger(void) { tran_char = String; } void set_subexp(void) { this_state->last_tran->trigger = TRIG_SUBEXP; needed |= NEED_REC; } void store_action(void) { this_state->last_tran->action = malloc(strlen(tran_string)+2); sprintf(this_state->last_tran->action,"%s",tran_string); this_state->last_tran->actargs = 0; this_state->last_tran->actargat = -1; this_state->last_tran->condition = 0; } void store_condition(void) { this_state->last_tran->action = malloc(strlen(tran_string)+2); sprintf(this_state->last_tran->action,"%s",tran_string); this_state->last_tran->actargs = 0; this_state->last_tran->actargat = -1; this_state->last_tran->condition = 1; } void null_action(void) { this_state->last_tran->action = 0; this_state->last_tran->actargs = 0; this_state->last_tran->actargat = -1; } void action_args(void) { int i; int pc; int c; char *cp; int have; int len; int startline; i = 0; pc = 1; cp = this_state->last_tran->action; len = strlen(cp); have = len+64; cp = realloc(cp,have+1); cp[len++] = '('; startline = line_no; while (pc > 0) { c = lex_input(); if (c == EOF) { fprintf(stderr,"%s: line %d: EOF inside action routine args (begun at line %d)\n",__progname,line_no,startline); exit(1); } if (c == '\n') line_no ++; switch (c) { case '(': pc ++; break; case ')': pc --; break; } if (len >= have) cp = realloc(cp,(have=len+64)+1); cp[len++] = c; switch (c) { case ')': case ',': if ( (pc <= 1) && (len >= 6) && ((cp[len-6] == '(') || (cp[len-6] == ',')) && (cp[len-5] == '$') && (cp[len-4] == 'a') && (cp[len-3] == 'r') && (cp[len-2] == 'g') ) { if (this_state->last_tran->actargat >= 0) { fprintf(stderr,"%s: line %d: warning: $arg used multiple times\n",__progname,line_no); } this_state->last_tran->actargat = len - 5; cp[len-5] = cp[len-1]; len -= 4; } break; } } cp[len] = '\0'; this_state->last_tran->actargs = 1; this_state->last_tran->action = cp; } void store_newstate(void) { STATE *sp; TRAN_LIST *tlp; sp = find_state(tran_string,1); tlp = malloc(sizeof(TRAN_LIST)); tlp->link = sp->into; sp->into = tlp; tlp->ptr = this_state->last_tran; this_state->last_tran->next = sp; } void store_exitstate(void) { this_state->last_tran->next = NEXT_EXIT; } void store_failstate(void) { this_state->last_tran->next = NEXT_FAIL; } void next_newstate(void) { TRAN_LIST *tlp; if (next_state == 0) { next_state = malloc(sizeof(STATE)); next_state->defined = 0; next_state->name = 0; next_state->trans = next_state->last_tran = 0; next_state->into = 0; next_state->number = 0; } this_state->last_tran->next = next_state; tlp = malloc(sizeof(TRAN_LIST)); tlp->link = next_state->into; next_state->into = tlp; tlp->ptr = this_state->last_tran; }