aboutsummaryrefslogtreecommitdiffstats
path: root/lcc/src/2html.c
diff options
context:
space:
mode:
Diffstat (limited to 'lcc/src/2html.c')
-rwxr-xr-xlcc/src/2html.c555
1 files changed, 555 insertions, 0 deletions
diff --git a/lcc/src/2html.c b/lcc/src/2html.c
new file mode 100755
index 0000000..3c9b146
--- /dev/null
+++ b/lcc/src/2html.c
@@ -0,0 +1,555 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "c.h"
+#include "rcc.h"
+#if WIN32
+#include <fcntl.h>
+#include <io.h>
+#endif
+
+
+static void do_int(int x) {
+ printf("%d", x);
+}
+
+static void do_scope(int x) {
+#define xx(c) if (x == c) { printf(#c); return; }
+ xx(CONSTANTS)
+ xx(LABELS)
+ xx(GLOBAL)
+ xx(PARAM)
+ xx(LOCAL)
+#undef xx
+ if (x > LOCAL)
+ printf("LOCAL+%d", x-LOCAL);
+ else
+ do_int(x);
+}
+
+static void do_sclass(int x) {
+#define xx(c) if (x == c) { printf(#c); return; }
+ xx(REGISTER)
+ xx(AUTO)
+ xx(EXTERN)
+ xx(STATIC)
+ xx(TYPEDEF)
+#undef xx
+ do_int(x);
+}
+
+static void do_flags(int x) {
+ char *bar = "";
+#define xx(f,n) if ((x>>n)&1) { printf("%s" #f, bar); bar = "|"; }
+ xx(structarg,0)
+ xx(addressed,1)
+ xx(computed,2)
+ xx(temporary,3)
+ xx(generated,4)
+#undef xx
+ if (*bar == '\0')
+ do_int(x);
+}
+
+static void do_seg(int x) {
+#define xx(s) if (x == s) { printf(#s); return; }
+ xx(CODE)
+ xx(BSS)
+ xx(DATA)
+ xx(LIT)
+#undef xx
+ do_int(x);
+}
+
+#define xx(ptr,field,type) do { printf("<li>" #field " = "); do_##type(ptr->field); printf("</li>\n"); } while (0)
+
+static void do_op(int x) {
+ static char *opnames[] = {
+ "",
+ "CNST",
+ "ARG",
+ "ASGN",
+ "INDIR",
+ "CVC",
+ "CVD",
+ "CVF",
+ "CVI",
+ "CVP",
+ "CVS",
+ "CVU",
+ "NEG",
+ "CALL",
+ "*LOAD*",
+ "RET",
+ "ADDRG",
+ "ADDRF",
+ "ADDRL",
+ "ADD",
+ "SUB",
+ "LSH",
+ "MOD",
+ "RSH",
+ "BAND",
+ "BCOM",
+ "BOR",
+ "BXOR",
+ "DIV",
+ "MUL",
+ "EQ",
+ "GE",
+ "GT",
+ "LE",
+ "LT",
+ "NE",
+ "JUMP",
+ "LABEL",
+ "AND",
+ "NOT",
+ "OR",
+ "COND",
+ "RIGHT",
+ "FIELD"
+ };
+ int op = opindex(x);
+ if (op < 1 || op >= sizeof opnames/sizeof opnames[0])
+ printf("%d", x);
+ else
+ printf("%s", opnames[op]);
+}
+
+static void do_define_uid(int x) {
+ printf("<strong id=uid%d>%d</strong>", x, x);
+}
+
+static void do_define_label(int x) {
+ printf("<strong id=ll%d>%d</strong>", x, x);
+}
+
+static void do_uid(int x) {
+ printf("<a href='#%d'>%d</a>", x, x, x);
+}
+
+static void do_label(int x) {
+ printf("<a href='#L%d'>%d</a>", x, x, x);
+}
+
+static int nextid;
+
+static void do_list(list_ty x, void do_one(void *), char *type, char *listhtml, char *separator) {
+ int count = Seq_length(x);
+
+ if (count == 0)
+ printf("<em>empty %s list</em>\n", type);
+ else {
+ int i;
+ printf("<em>%s list</em>", type);
+ if (listhtml != NULL)
+ printf("<%s>\n", listhtml);
+ for (i = 0; i < count; i++) {
+ if (listhtml != NULL)
+ printf("<li>");
+ printf(separator);
+ do_one(Seq_get(x, i));
+ if (listhtml != NULL)
+ printf("</li>\n");
+ }
+ if (listhtml != NULL)
+ printf("</%s>\n", listhtml);
+ }
+}
+
+static void do_uid_list(list_ty x) {
+ int i, count = Seq_length(x);
+
+ if (count == 0)
+ printf("<em>empty int list</em>\n");
+ else {
+ int i;
+ printf("<em>int list</em>");
+ for (i= 0; i < count; i++) {
+ printf(" ");
+ do_uid(*(int *)Seq_get(x, i));
+ }
+ }
+}
+
+static void do_identifier(const char *x) {
+ printf("%s", x);
+}
+
+static void do_real(rcc_real_ty x) {
+ double d;
+ unsigned *p = (unsigned *)&d;
+ static union { int x; char endian; } little = { 1 };
+
+ p[1-little.endian] = x->msb;
+ p[little.endian] = x->lsb;
+ printf("(%#X,%#X) = %g", x->msb, x->lsb, d);
+}
+
+static void do_suffix(int x) {
+ static char suffixes[] = "0F234IUPVB";
+
+ if (x < 0 || x >= (sizeof suffixes/sizeof suffixes[0]) - 1)
+ printf("%d", x);
+ else
+ printf("%c", suffixes[x]);
+}
+
+static void do_enum(void *x) {
+ rcc_enum__ty e = x;
+
+ do_identifier(e->id);
+ printf("=");
+ do_int(e->value);
+}
+
+static void do_enum_list(list_ty x) {
+ do_list(x, do_enum, "enum", NULL, " ");
+}
+
+static void do_field(void *x) {
+ rcc_field_ty f = x;
+
+ printf("<em>field</em><ul>\n");
+ xx(f,id,identifier);
+ xx(f,type,uid);
+ xx(f,offset,int);
+ xx(f,bitsize,int);
+ xx(f,lsb,int);
+ printf("</ul>\n");
+}
+
+static void do_field_list(list_ty x) {
+ do_list(x, do_field, "field", "ol", "");
+}
+
+static void do_symbol(rcc_symbol_ty x) {
+ printf("<em>symbol</em><ul>\n");
+ xx(x,id,identifier);
+ xx(x,type,uid);
+ xx(x,scope,scope);
+ xx(x,sclass,sclass);
+ xx(x,ref,int);
+ xx(x,flags,flags);
+ printf("</ul>\n");
+}
+
+#define caselabel(kind) case rcc_##kind##_enum: \
+ printf("<strong>" #kind "</strong> : <em>%s</em>", typename); \
+ printf("<ul>\n"); attributes
+#define yy(kind,field,type) xx((&x->v.rcc_##kind),field,type)
+
+static void do_type(rcc_type_ty x) {
+#define attributes xx(x,size,int); xx(x,align,int)
+ switch (x->kind) {
+ static char *typename = "type";
+ caselabel(INT); break;
+ caselabel(UNSIGNED); break;
+ caselabel(FLOAT); break;
+ caselabel(VOID); break;
+ caselabel(POINTER);
+ yy(POINTER,type,uid);
+ break;
+ caselabel(ENUM);
+ yy(ENUM,tag,identifier);
+ yy(ENUM,ids,enum_list);
+ break;
+ caselabel(STRUCT);
+ yy(STRUCT,tag,identifier);
+ yy(STRUCT,fields,field_list);
+ break;
+ caselabel(UNION);
+ yy(UNION,tag,identifier);
+ yy(UNION,fields,field_list);
+ break;
+ caselabel(ARRAY);
+ yy(ARRAY,type,uid);
+ break;
+ caselabel(FUNCTION);
+ yy(FUNCTION,type,uid);
+ yy(FUNCTION,formals,uid_list);
+ break;
+ caselabel(CONST);
+ yy(CONST,type,uid);
+ break;
+ caselabel(VOLATILE);
+ yy(VOLATILE,type,uid);
+ break;
+ default: assert(0);
+ }
+#undef attributes
+ printf("</ul>\n");
+}
+
+static void do_item(rcc_item_ty x) {
+ printf("<a name='%d'>", x->uid);
+#define attributes xx(x,uid,define_uid)
+ printf("</a>");
+ switch (x->kind) {
+ static char *typename = "item";
+ caselabel(Symbol);
+ yy(Symbol,symbol,symbol);
+ break;
+ caselabel(Type);
+ yy(Type,type,type);
+ break;
+ default: assert(0);
+ }
+#undef attributes
+ printf("</ul>\n");
+}
+
+static void do_item_list(list_ty x) {
+ int count = Seq_length(x);
+
+ if (count == 0)
+ printf("<em>empty item list</em>\n");
+ else {
+ int i;
+ printf("<em>item list</em>");
+ printf("<ol>\n");
+ for (i = 0; i < count; i++) {
+ rcc_item_ty item = Seq_get(x, i);
+ printf("<li value=%d>", item->uid);
+ do_item(item);
+ printf("</li>\n");
+ }
+ printf("</ol>\n");
+ }
+}
+
+static void do_string(string_ty x) {
+ printf("%d,<code>'%s'</code>", x.len, x.str);
+}
+
+static void do_generic_string(void *x) {
+ do_string(*(string_ty *)x);
+}
+
+static void do_string_list(list_ty x) {
+ do_list(x, do_generic_string, "string", "ol", "");
+}
+
+static void do_node(void *y) {
+ rcc_node_ty x = y;
+
+ if (x->kind == rcc_LABEL_enum)
+ printf("<a name='L%d'></a>", x->v.rcc_LABEL.label);
+#define attributes xx(x,suffix,suffix); xx(x,size,int)
+ switch (x->kind) {
+ static char *typename = "node";
+ caselabel(CNST);
+ yy(CNST,value,int);
+ break;
+ caselabel(CNSTF);
+ yy(CNSTF,value,real);
+ break;
+ caselabel(ARG);
+ yy(ARG,left,node);
+ yy(ARG,len,int);
+ yy(ARG,align,int);
+ break;
+ caselabel(ASGN);
+ yy(ASGN,left,node);
+ yy(ASGN,right,node);
+ yy(ASGN,len,int);
+ yy(ASGN,align,int);
+ break;
+ caselabel(CVT);
+ yy(CVT,op,op);
+ yy(CVT,left,node);
+ yy(CVT,fromsize,int);
+ break;
+ caselabel(CALL);
+ yy(CALL,left,node);
+ yy(CALL,type,uid);
+ break;
+ caselabel(CALLB);
+ yy(CALLB,left,node);
+ yy(CALLB,right,node);
+ yy(CALLB,type,uid);
+ break;
+ caselabel(RET); break;
+ caselabel(ADDRG);
+ yy(ADDRG,uid,uid);
+ break;
+ caselabel(ADDRL);
+ yy(ADDRL,uid,uid);
+ break;
+ caselabel(ADDRF);
+ yy(ADDRF,uid,uid);
+ break;
+ caselabel(Unary);
+ yy(Unary,op,op);
+ yy(Unary,left,node);
+ break;
+ caselabel(Binary);
+ yy(Binary,op,op);
+ yy(Binary,left,node);
+ yy(Binary,right,node);
+ break;
+ caselabel(Compare);
+ yy(Compare,op,op);
+ yy(Compare,left,node);
+ yy(Compare,right,node);
+ yy(Compare,label,label);
+ break;
+ caselabel(LABEL);
+ yy(LABEL,label,define_label);
+ break;
+ caselabel(BRANCH);
+ yy(BRANCH,label,label);
+ break;
+ caselabel(CSE);
+ yy(CSE,uid,uid);
+ yy(CSE,node,node);
+ break;
+ default: assert(0);
+ }
+#undef attributes
+ printf("</ul>");
+}
+
+static void do_node_list(list_ty x) {
+ do_list(x, do_node, "node", "ol", "");
+}
+
+static void do_interface(void *);
+
+static void do_interface_list(list_ty x) {
+ do_list(x, do_interface, "interface", "ol", "");
+}
+
+static void do_interface(void *y) {
+ rcc_interface_ty x = y;
+
+ if (x->kind == rcc_Address_enum)
+ printf("<a name='%d'></a>", x->v.rcc_Address.uid);
+ else if (x->kind == rcc_Local_enum)
+ printf("<a name='%d'></a>", x->v.rcc_Local.uid);
+#define attributes
+ switch (x->kind) {
+ static char *typename = "interface";
+ caselabel(Export);
+ yy(Export,p,uid);
+ break;
+ caselabel(Import);
+ yy(Import,p,uid);
+ break;
+ caselabel(Global);
+ yy(Global,p,uid);
+ yy(Global,seg,seg);
+ break;
+ caselabel(Local);
+ yy(Local,uid,define_uid);
+ yy(Local,p,symbol);
+ break;
+ caselabel(Address);
+ yy(Address,uid,define_uid);
+ yy(Address,q,symbol);
+ yy(Address,p,uid);
+ yy(Address,n,int);
+ break;
+ caselabel(Segment);
+ yy(Segment,seg,seg);
+ break;
+ caselabel(Defaddress);
+ yy(Defaddress,p,uid);
+ break;
+ caselabel(Deflabel);
+ yy(Deflabel,label,label);
+ break;
+ caselabel(Defconst);
+ yy(Defconst,suffix,suffix);
+ yy(Defconst,size,int);
+ yy(Defconst,value,int);
+ break;
+ caselabel(Defconstf);
+ yy(Defconstf,size,int);
+ yy(Defconstf,value,real);
+ break;
+ caselabel(Defstring);
+ yy(Defstring,s,string);
+ break;
+ caselabel(Space);
+ yy(Space,n,int);
+ break;
+ caselabel(Function);
+ yy(Function,f,uid);
+ yy(Function,caller,uid_list);
+ yy(Function,callee,uid_list);
+ yy(Function,ncalls,int);
+ yy(Function,codelist,interface_list);
+ break;
+ caselabel(Forest);
+ yy(Forest,nodes,node_list);
+ break;
+ case rcc_Blockbeg_enum: printf("<strong>Blockbeg</strong> : <em>%s</em>", typename); return;
+ case rcc_Blockend_enum: printf("<strong>Blockend</strong> : <em>%s</em>", typename); return;
+ default: assert(0);
+ }
+#undef attributes
+ printf("</ul>\n");
+}
+
+static void do_program(rcc_program_ty x) {
+ printf("<ul>\n");
+ xx(x,nuids,int);
+ xx(x,nlabels,int);
+ xx(x,items,item_list);
+ xx(x,interfaces,interface_list);
+ xx(x,argc,int);
+ xx(x,argv,string_list);
+ printf("</ul>\n");
+}
+
+int main(int argc, char *argv[]) {
+ int i, version;
+ float stamp = (assert(strstr(rcsid, ",v")), strtod(strstr(rcsid, ",v")+2, NULL))
+;
+ char *infile = NULL, *outfile = NULL;
+ rcc_program_ty pickle;
+
+ for (i = 1; i < argc; i++)
+ if (*argv[i] != '-' || strcmp(argv[i], "-") == 0) {
+ if (infile == NULL)
+ infile = argv[i];
+ else if (outfile == NULL)
+ outfile = argv[i];
+ }
+ if (infile != NULL && strcmp(infile, "-") != 0
+ && freopen(infile, "rb", stdin) == NULL) {
+ fprintf(stderr, "%s: can't read `%s'\n", argv[0], infile);
+ exit(EXIT_FAILURE);
+ }
+ if (infile == NULL || strcmp(infile, "-") == 0)
+ infile = "Standard Input";
+#if WIN32
+ else
+ _setmode(_fileno(stdin), _O_BINARY);
+#endif
+ if (outfile != NULL && strcmp(outfile, "-") != 0
+ && freopen(outfile, "w", stdout) == NULL) {
+ fprintf(stderr, "%s: can't write `%s'\n", argv[0], outfile);
+ exit(EXIT_FAILURE);
+ }
+ version = read_int(stdin);
+ assert(version/100 == (int)stamp);
+ pickle = rcc_read_program(stdin);
+ printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\"\n");
+ printf("<html><head><title>%s</title>\n"
+ "<link rev=made href=\"mailto:drh@microsoft.com\">\n"
+ "</head><body>\n<h1>%s</h1>\n", infile, infile);
+ printf("<p>version = %d.%d</p>", version/100, version%100);
+ do_program(pickle);
+ {
+ time_t t;
+ time(&t);
+ printf("<hr><address>%s</address>\n", ctime(&t));
+ }
+ printf("</body></html>\n");
+ return EXIT_SUCCESS;
+}