ref: f4f19cdf1a8f0d2aa5f9fce10c896201528b5347
dir: /sys/src/cmd/spin/reprosrc.c/
/***** spin: reprosrc.c *****/ /* * This file is part of the public release of Spin. It is subject to the * terms in the LICENSE file that is included in this source directory. * Tool documentation is available at http://spinroot.com */ #include <stdio.h> #include <assert.h> #include "spin.h" #include "y.tab.h" static int indent = 1; extern YYSTYPE yylval; extern ProcList *rdy; static void repro_seq(Sequence *); void doindent(void) { int i; for (i = 0; i < indent; i++) printf(" "); } void repro_sub(Element *e) { doindent(); switch (e->n->ntyp) { case D_STEP: printf("d_step {\n"); break; case ATOMIC: printf("atomic {\n"); break; case NON_ATOMIC: printf(" {\n"); break; } indent++; repro_seq(e->n->sl->this); indent--; doindent(); printf(" };\n"); } static void repro_seq(Sequence *s) { Element *e; Symbol *v; SeqList *h; for (e = s->frst; e; e = e->nxt) { v = has_lab(e, 0); if (v) printf("%s:\n", v->name); if (e->n->ntyp == UNLESS) { printf("/* normal */ {\n"); repro_seq(e->n->sl->this); doindent(); printf("} unless {\n"); repro_seq(e->n->sl->nxt->this); doindent(); printf("}; /* end unless */\n"); } else if (e->sub) { switch (e->n->ntyp) { case DO: doindent(); printf("do\n"); indent++; break; case IF: doindent(); printf("if\n"); indent++; break; } for (h = e->sub; h; h = h->nxt) { indent--; doindent(); indent++; printf("::\n"); repro_seq(h->this); printf("\n"); } switch (e->n->ntyp) { case DO: indent--; doindent(); printf("od;\n"); break; case IF: indent--; doindent(); printf("fi;\n"); break; } } else { if (e->n->ntyp == ATOMIC || e->n->ntyp == D_STEP || e->n->ntyp == NON_ATOMIC) repro_sub(e); else if (e->n->ntyp != '.' && e->n->ntyp != '@' && e->n->ntyp != BREAK) { doindent(); if (e->n->ntyp == C_CODE) { printf("c_code "); plunk_inline(stdout, e->n->sym->name, 1, 1); } else if (e->n->ntyp == 'c' && e->n->lft->ntyp == C_EXPR) { printf("c_expr { "); plunk_expr(stdout, e->n->lft->sym->name); printf("} ->\n"); } else { comment(stdout, e->n, 0); printf(";\n"); } } } if (e == s->last) break; } } void repro_proc(ProcList *p) { if (!p) return; if (p->nxt) repro_proc(p->nxt); if (p->det) printf("D"); /* deterministic */ printf("proctype %s()", p->n->name); if (p->prov) { printf(" provided "); comment(stdout, p->prov, 0); } printf("\n{\n"); repro_seq(p->s); printf("}\n"); } void repro_src(void) { repro_proc(rdy); } static int in_decl; static int in_c_decl; static int in_c_code; void blip(int n, char *b) { char mtxt[1024]; strcpy(mtxt, ""); switch (n) { default: if (n > 0 && n < 256) sprintf(mtxt, "%c", n); else sprintf(mtxt, "<%d?>", n); break; case '(': strcpy(mtxt, "("); in_decl++; break; case ')': strcpy(mtxt, ")"); in_decl--; break; case '{': strcpy(mtxt, "{"); break; case '}': strcpy(mtxt, "}"); break; case '\t': sprintf(mtxt, "\\t"); break; case '\f': sprintf(mtxt, "\\f"); break; case '\n': sprintf(mtxt, "\\n"); break; case '\r': sprintf(mtxt, "\\r"); break; case 'c': sprintf(mtxt, "condition"); break; case 's': sprintf(mtxt, "send"); break; case 'r': sprintf(mtxt, "recv"); break; case 'R': sprintf(mtxt, "recv poll"); break; case '@': sprintf(mtxt, "@"); break; case '?': sprintf(mtxt, "(x->y:z)"); break; case NEXT: sprintf(mtxt, "X"); break; case ALWAYS: sprintf(mtxt, "[]"); break; case EVENTUALLY: sprintf(mtxt, "<>"); break; case IMPLIES: sprintf(mtxt, "->"); break; case EQUIV: sprintf(mtxt, "<->"); break; case UNTIL: sprintf(mtxt, "U"); break; case WEAK_UNTIL: sprintf(mtxt, "W"); break; case IN: sprintf(mtxt, "in"); break; case ACTIVE: sprintf(mtxt, "active"); break; case AND: sprintf(mtxt, "&&"); break; case ARROW: sprintf(mtxt, "->"); break; case ASGN: sprintf(mtxt, "="); break; case ASSERT: sprintf(mtxt, "assert"); break; case ATOMIC: sprintf(mtxt, "atomic"); break; case BREAK: sprintf(mtxt, "break"); break; case C_CODE: sprintf(mtxt, "c_code"); in_c_code++; break; case C_DECL: sprintf(mtxt, "c_decl"); in_c_decl++; break; case C_EXPR: sprintf(mtxt, "c_expr"); break; case C_STATE: sprintf(mtxt, "c_state"); break; case C_TRACK: sprintf(mtxt, "c_track"); break; case CLAIM: sprintf(mtxt, "never"); break; case CONST: sprintf(mtxt, "%d", yylval->val); break; case DECR: sprintf(mtxt, "--"); break; case D_STEP: sprintf(mtxt, "d_step"); break; case D_PROCTYPE: sprintf(mtxt, "d_proctype"); break; case DO: sprintf(mtxt, "do"); break; case DOT: sprintf(mtxt, "."); break; case ELSE: sprintf(mtxt, "else"); break; case EMPTY: sprintf(mtxt, "empty"); break; case ENABLED: sprintf(mtxt, "enabled"); break; case EQ: sprintf(mtxt, "=="); break; case EVAL: sprintf(mtxt, "eval"); break; case FI: sprintf(mtxt, "fi"); break; case FULL: sprintf(mtxt, "full"); break; case GE: sprintf(mtxt, ">="); break; case GET_P: sprintf(mtxt, "get_priority"); break; case GOTO: sprintf(mtxt, "goto"); break; case GT: sprintf(mtxt, ">"); break; case HIDDEN: sprintf(mtxt, "hidden"); break; case IF: sprintf(mtxt, "if"); break; case INCR: sprintf(mtxt, "++"); break; case INLINE: sprintf(mtxt, "inline"); break; case INIT: sprintf(mtxt, "init"); break; case ISLOCAL: sprintf(mtxt, "local"); break; case LABEL: sprintf(mtxt, "<label-name>"); break; case LE: sprintf(mtxt, "<="); break; case LEN: sprintf(mtxt, "len"); break; case LSHIFT: sprintf(mtxt, "<<"); break; case LT: sprintf(mtxt, "<"); break; case LTL: sprintf(mtxt, "ltl"); break; case NAME: sprintf(mtxt, "%s", yylval->sym->name); break; case XU: switch (yylval->val) { case XR: sprintf(mtxt, "xr"); break; case XS: sprintf(mtxt, "xs"); break; default: sprintf(mtxt, "<?>"); break; } break; case TYPE: switch (yylval->val) { case BIT: sprintf(mtxt, "bit"); break; case BYTE: sprintf(mtxt, "byte"); break; case CHAN: sprintf(mtxt, "chan"); in_decl++; break; case INT: sprintf(mtxt, "int"); break; case MTYPE: sprintf(mtxt, "mtype"); break; case SHORT: sprintf(mtxt, "short"); break; case UNSIGNED: sprintf(mtxt, "unsigned"); break; default: sprintf(mtxt, "<unknown type>"); break; } break; case NE: sprintf(mtxt, "!="); break; case NEG: sprintf(mtxt, "!"); break; case NEMPTY: sprintf(mtxt, "nempty"); break; case NFULL: sprintf(mtxt, "nfull"); break; case NON_ATOMIC: sprintf(mtxt, "<sub-sequence>"); break; case NONPROGRESS: sprintf(mtxt, "np_"); break; case OD: sprintf(mtxt, "od"); break; case OF: sprintf(mtxt, "of"); break; case OR: sprintf(mtxt, "||"); break; case O_SND: sprintf(mtxt, "!!"); break; case PC_VAL: sprintf(mtxt, "pc_value"); break; case PRINT: sprintf(mtxt, "printf"); break; case PRINTM: sprintf(mtxt, "printm"); break; case PRIORITY: sprintf(mtxt, "priority"); break; case PROCTYPE: sprintf(mtxt, "proctype"); break; case PROVIDED: sprintf(mtxt, "provided"); break; case RCV: sprintf(mtxt, "?"); break; case R_RCV: sprintf(mtxt, "??"); break; case RSHIFT: sprintf(mtxt, ">>"); break; case RUN: sprintf(mtxt, "run"); break; case SEP: sprintf(mtxt, "::"); break; case SEMI: sprintf(mtxt, ";"); break; case SET_P: sprintf(mtxt, "set_priority"); break; case SHOW: sprintf(mtxt, "show"); break; case SND: sprintf(mtxt, "!"); break; case INAME: case UNAME: case PNAME: case STRING: sprintf(mtxt, "%s", yylval->sym->name); break; case TRACE: sprintf(mtxt, "trace"); break; case TIMEOUT: sprintf(mtxt, "timeout"); break; case TYPEDEF: sprintf(mtxt, "typedef"); break; case UMIN: sprintf(mtxt, "-"); break; case UNLESS: sprintf(mtxt, "unless"); break; } strcat(b, mtxt); } void purge(char *b) { if (strlen(b) == 0) return; if (b[strlen(b)-1] != ':') /* label? */ { if (b[0] == ':' && b[1] == ':') { indent--; doindent(); indent++; } else { doindent(); } } printf("%s\n", b); strcpy(b, ""); in_decl = 0; in_c_code = 0; in_c_decl = 0; } int pp_mode; extern int lex(void); void pretty_print(void) { int c, lastc = 0; char buf[1024]; pp_mode = 1; indent = 0; strcpy(buf, ""); while ((c = lex()) != EOF) { if ((lastc == IF || lastc == DO) && c != SEP) { indent--; /* c_code if */ } if (c == C_DECL || c == C_STATE || c == C_TRACK || c == SEP || c == DO || c == IF || (c == TYPE && !in_decl)) { purge(buf); /* start on new line */ } if (c == '{' && lastc != OF && lastc != IN && lastc != ATOMIC && lastc != D_STEP && lastc != C_CODE && lastc != C_DECL && lastc != C_EXPR) { purge(buf); } if (c == PREPROC) { int oi = indent; purge(buf); assert(strlen(yylval->sym->name) < sizeof(buf)); strcpy(buf, yylval->sym->name); indent = 0; purge(buf); indent = oi; continue; } if (c != ':' && c != SEMI && c != ',' && c != '(' && c != '#' && lastc != '#' && c != ARROW && lastc != ARROW && c != '.' && lastc != '.' && c != '!' && lastc != '!' && c != SND && lastc != SND && c != RCV && lastc != RCV && c != O_SND && lastc != O_SND && c != R_RCV && lastc != R_RCV && (c != ']' || lastc != '[') && (c != '>' || lastc != '<') && (c != GT || lastc != LT) && c != '@' && lastc != '@' && c != DO && c != OD && c != IF && c != FI && c != SEP && strlen(buf) > 0) strcat(buf, " "); if (c == '}' || c == OD || c == FI) { purge(buf); indent--; } blip(c, buf); if (c == '{' || c == DO || c == IF) { purge(buf); indent++; } if (c == '}' || c == BREAK || c == SEMI || (c == ':' && lastc == NAME)) { purge(buf); } lastc = c; } purge(buf); }