Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

2html.c (11130B)


      1 #include <assert.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <time.h>
      6 #include "c.h"
      7 #include "rcc.h"
      8 #if WIN32
      9 #include <fcntl.h>
     10 #include <io.h>
     11 #endif
     12 
     13 
     14 static void do_int(int x) {
     15 	printf("%d", x);
     16 }
     17 
     18 static void do_scope(int x) {
     19 #define xx(c) if (x == c) { printf(#c); return; }
     20 	xx(CONSTANTS)
     21 	xx(LABELS)
     22 	xx(GLOBAL)
     23 	xx(PARAM)
     24 	xx(LOCAL)
     25 #undef xx
     26 	if (x > LOCAL)
     27 		printf("LOCAL+%d", x-LOCAL);
     28 	else
     29 		do_int(x);
     30 }
     31 
     32 static void do_sclass(int x) {
     33 #define xx(c) if (x == c) { printf(#c); return; }
     34 	xx(REGISTER)
     35 	xx(AUTO)
     36 	xx(EXTERN)
     37 	xx(STATIC)
     38 	xx(TYPEDEF)
     39 #undef xx
     40 	do_int(x);
     41 }
     42 
     43 static void do_flags(int x) {
     44 	char *bar = "";
     45 #define xx(f,n) if ((x>>n)&1) { printf("%s" #f, bar); bar = "|"; }
     46 	xx(structarg,0)
     47 	xx(addressed,1)
     48 	xx(computed,2)
     49 	xx(temporary,3)
     50 	xx(generated,4)
     51 #undef xx
     52 	if (*bar == '\0')
     53 		do_int(x);
     54 }
     55 
     56 static void do_seg(int x) {
     57 #define xx(s) if (x == s) { printf(#s); return; }
     58 	xx(CODE)
     59 	xx(BSS)
     60 	xx(DATA)
     61 	xx(LIT)
     62 #undef xx
     63 	do_int(x);
     64 }
     65 
     66 #define xx(ptr,field,type) do { printf("<li>" #field " = "); do_##type(ptr->field); printf("</li>\n"); } while (0)
     67 
     68 static void do_op(int x) {
     69 	static char *opnames[] = {
     70 		"",
     71 		"CNST",
     72 		"ARG",
     73 		"ASGN",
     74 		"INDIR",
     75 		"CVC",
     76 		"CVD",
     77 		"CVF",
     78 		"CVI",
     79 		"CVP",
     80 		"CVS",
     81 		"CVU",
     82 		"NEG",
     83 		"CALL",
     84 		"*LOAD*",
     85 		"RET",
     86 		"ADDRG",
     87 		"ADDRF",
     88 		"ADDRL",
     89 		"ADD",
     90 		"SUB",
     91 		"LSH",
     92 		"MOD",
     93 		"RSH",
     94 		"BAND",
     95 		"BCOM",
     96 		"BOR",
     97 		"BXOR",
     98 		"DIV",
     99 		"MUL",
    100 		"EQ",
    101 		"GE",
    102 		"GT",
    103 		"LE",
    104 		"LT",
    105 		"NE",
    106 		"JUMP",
    107 		"LABEL",
    108 		"AND",
    109 		"NOT",
    110 		"OR",
    111 		"COND",
    112 		"RIGHT",
    113 		"FIELD"
    114 	};
    115 	int op = opindex(x);
    116 	if (op < 1 || op >= sizeof opnames/sizeof opnames[0])
    117 		printf("%d", x);
    118 	else
    119 		printf("%s", opnames[op]);
    120 }
    121 
    122 static void do_define_uid(int x) {
    123 	printf("<strong id=uid%d>%d</strong>", x, x);
    124 }
    125 
    126 static void do_define_label(int x) {
    127 	printf("<strong id=ll%d>%d</strong>", x, x);
    128 }
    129 
    130 static void do_uid(int x) {
    131 	printf("<a href='#%d'>%d</a>", x, x, x);
    132 }
    133 
    134 static void do_label(int x) {
    135 	printf("<a href='#L%d'>%d</a>", x, x, x);
    136 }
    137 
    138 static int nextid;
    139 
    140 static void do_list(list_ty x, void do_one(void *), char *type, char *listhtml, char *separator) {
    141 	int count = Seq_length(x);
    142 
    143 	if (count == 0)
    144 		printf("<em>empty %s list</em>\n", type);
    145 	else {
    146 		int i;
    147 		printf("<em>%s list</em>", type);
    148 		if (listhtml != NULL)
    149 			printf("<%s>\n", listhtml);
    150 		for (i = 0; i < count; i++) {
    151 			if (listhtml != NULL)
    152 				printf("<li>");
    153 			printf(separator);
    154 			do_one(Seq_get(x, i));
    155 			if (listhtml != NULL)
    156 				printf("</li>\n");
    157 		}
    158 		if (listhtml != NULL)
    159 			printf("</%s>\n", listhtml);
    160 	}
    161 }
    162 
    163 static void do_uid_list(list_ty x) {
    164 	int i, count = Seq_length(x);
    165 
    166 	if (count == 0)
    167 		printf("<em>empty int list</em>\n");
    168 	else {
    169 		int i;
    170 		printf("<em>int list</em>");
    171 		for (i= 0; i < count; i++) {
    172 			printf(" ");
    173 			do_uid(*(int *)Seq_get(x, i));
    174 		}
    175 	}
    176 }
    177 
    178 static void do_identifier(const char *x) {
    179 	printf("%s", x);
    180 }
    181 
    182 static void do_real(rcc_real_ty x) {
    183 	double d;
    184 	unsigned *p = (unsigned *)&d;
    185 	static union { int x; char endian; } little = { 1 };
    186 
    187 	p[1-little.endian] = x->msb;
    188 	p[little.endian] = x->lsb;
    189 	printf("(%#X,%#X) = %g", x->msb, x->lsb, d);
    190 }
    191 
    192 static void do_suffix(int x) {
    193 	static char suffixes[] = "0F234IUPVB";
    194 
    195 	if (x < 0 || x >= (sizeof suffixes/sizeof suffixes[0]) - 1)
    196 		printf("%d", x);
    197 	else
    198 		printf("%c", suffixes[x]);
    199 }
    200 
    201 static void do_enum(void *x) {
    202 	rcc_enum__ty e = x;
    203 
    204 	do_identifier(e->id);
    205 	printf("=");
    206 	do_int(e->value);
    207 }
    208 
    209 static void do_enum_list(list_ty x) {
    210 	do_list(x, do_enum, "enum", NULL, " ");
    211 }
    212 
    213 static void do_field(void *x) {
    214 	rcc_field_ty f = x;
    215 
    216 	printf("<em>field</em><ul>\n");
    217 	xx(f,id,identifier);
    218 	xx(f,type,uid);
    219 	xx(f,offset,int);
    220 	xx(f,bitsize,int);
    221 	xx(f,lsb,int);
    222 	printf("</ul>\n");
    223 }
    224 
    225 static void do_field_list(list_ty x) {
    226 	do_list(x, do_field, "field", "ol", "");
    227 }
    228 
    229 static void do_symbol(rcc_symbol_ty x) {
    230 	printf("<em>symbol</em><ul>\n");
    231 	xx(x,id,identifier);
    232 	xx(x,type,uid);
    233 	xx(x,scope,scope);
    234 	xx(x,sclass,sclass);
    235 	xx(x,ref,int);
    236 	xx(x,flags,flags);
    237 	printf("</ul>\n");
    238 }
    239 
    240 #define caselabel(kind) case rcc_##kind##_enum: \
    241 	printf("<strong>" #kind "</strong> : <em>%s</em>", typename); \
    242 	printf("<ul>\n"); attributes
    243 #define yy(kind,field,type) xx((&x->v.rcc_##kind),field,type)
    244 
    245 static void do_type(rcc_type_ty x) {
    246 #define attributes xx(x,size,int); xx(x,align,int)
    247 	switch (x->kind) {
    248 	static char *typename = "type";
    249 	caselabel(INT); break;
    250 	caselabel(UNSIGNED); break;
    251 	caselabel(FLOAT); break;
    252 	caselabel(VOID); break;
    253 	caselabel(POINTER);
    254 		yy(POINTER,type,uid);
    255 		break;
    256 	caselabel(ENUM);
    257 		yy(ENUM,tag,identifier);
    258 		yy(ENUM,ids,enum_list);
    259 		break;
    260 	caselabel(STRUCT);
    261 		yy(STRUCT,tag,identifier);
    262 		yy(STRUCT,fields,field_list);
    263 		break;
    264 	caselabel(UNION);
    265 		yy(UNION,tag,identifier);
    266 		yy(UNION,fields,field_list);
    267 		break;
    268 	caselabel(ARRAY);
    269 		yy(ARRAY,type,uid);
    270 		break;
    271 	caselabel(FUNCTION);
    272 		yy(FUNCTION,type,uid);
    273 		yy(FUNCTION,formals,uid_list);
    274 		break;
    275 	caselabel(CONST);
    276 		yy(CONST,type,uid);
    277 		break;
    278 	caselabel(VOLATILE);
    279 		yy(VOLATILE,type,uid);
    280 		break;
    281 	default: assert(0);
    282 	}
    283 #undef attributes
    284 	printf("</ul>\n");
    285 }
    286 
    287 static void do_item(rcc_item_ty x) {
    288 	printf("<a name='%d'>", x->uid);
    289 #define attributes xx(x,uid,define_uid)
    290 	printf("</a>");
    291 	switch (x->kind) {
    292 	static char *typename = "item";
    293 	caselabel(Symbol);
    294 		yy(Symbol,symbol,symbol);
    295 		break;
    296 	caselabel(Type);
    297 		yy(Type,type,type);
    298 		break;
    299 	default: assert(0);
    300 	}
    301 #undef attributes
    302 	printf("</ul>\n");
    303 }
    304 
    305 static void do_item_list(list_ty x) {
    306 	int count = Seq_length(x);
    307 
    308 	if (count == 0)
    309 		printf("<em>empty item list</em>\n");
    310 	else {
    311 		int i;
    312 		printf("<em>item list</em>");
    313 		printf("<ol>\n");
    314 		for (i = 0; i < count; i++) {
    315 			rcc_item_ty item = Seq_get(x, i);
    316 			printf("<li value=%d>", item->uid);
    317 			do_item(item);
    318 			printf("</li>\n");
    319 		}
    320 		printf("</ol>\n");
    321 	}
    322 }
    323 
    324 static void do_string(string_ty x) {
    325 	printf("%d,<code>'%s'</code>", x.len, x.str);
    326 }
    327 
    328 static void do_generic_string(void *x) {
    329 	do_string(*(string_ty *)x);
    330 }
    331 
    332 static void do_string_list(list_ty x) {
    333 	do_list(x, do_generic_string, "string", "ol", "");
    334 }
    335 
    336 static void do_node(void *y) {
    337 	rcc_node_ty x = y;
    338 
    339 	if (x->kind == rcc_LABEL_enum)
    340 		printf("<a name='L%d'></a>", x->v.rcc_LABEL.label);
    341 #define attributes xx(x,suffix,suffix); xx(x,size,int)
    342 	switch (x->kind) {
    343 	static char *typename = "node";
    344 	caselabel(CNST);
    345 		yy(CNST,value,int);
    346 		break;
    347 	caselabel(CNSTF);
    348 		yy(CNSTF,value,real);
    349 		break;
    350 	caselabel(ARG);
    351 		yy(ARG,left,node);
    352 		yy(ARG,len,int);
    353 		yy(ARG,align,int);
    354 		break;
    355 	caselabel(ASGN);
    356 		yy(ASGN,left,node);
    357 		yy(ASGN,right,node);
    358 		yy(ASGN,len,int);
    359 		yy(ASGN,align,int);
    360 		break;
    361 	caselabel(CVT);
    362 		yy(CVT,op,op);
    363 		yy(CVT,left,node);
    364 		yy(CVT,fromsize,int);
    365 		break;
    366 	caselabel(CALL);
    367 		yy(CALL,left,node);
    368 		yy(CALL,type,uid);
    369 		break;
    370 	caselabel(CALLB);
    371 		yy(CALLB,left,node);
    372 		yy(CALLB,right,node);
    373 		yy(CALLB,type,uid);
    374 		break;
    375 	caselabel(RET);	break;
    376 	caselabel(ADDRG);
    377 		yy(ADDRG,uid,uid);
    378 		break;
    379 	caselabel(ADDRL);
    380 		yy(ADDRL,uid,uid);
    381 		break;
    382 	caselabel(ADDRF);
    383 		yy(ADDRF,uid,uid);
    384 		break;
    385 	caselabel(Unary);
    386 		yy(Unary,op,op);
    387 		yy(Unary,left,node);
    388 		break;
    389 	caselabel(Binary);
    390 		yy(Binary,op,op);
    391 		yy(Binary,left,node);
    392 		yy(Binary,right,node);
    393 		break;
    394 	caselabel(Compare);
    395 		yy(Compare,op,op);
    396 		yy(Compare,left,node);
    397 		yy(Compare,right,node);
    398 		yy(Compare,label,label);
    399 		break;
    400 	caselabel(LABEL);
    401 		yy(LABEL,label,define_label);
    402 		break;
    403 	caselabel(BRANCH);
    404 		yy(BRANCH,label,label);
    405 		break;
    406 	caselabel(CSE);
    407 		yy(CSE,uid,uid);
    408 		yy(CSE,node,node);
    409 		break;
    410 	default: assert(0);
    411 	}
    412 #undef attributes
    413 	printf("</ul>");
    414 }
    415 
    416 static void do_node_list(list_ty x) {
    417 	do_list(x, do_node, "node", "ol", "");
    418 }
    419 
    420 static void do_interface(void *);
    421 
    422 static void do_interface_list(list_ty x) {
    423 	do_list(x, do_interface, "interface", "ol", "");
    424 }
    425 
    426 static void do_interface(void *y) {
    427 	rcc_interface_ty x = y;
    428 
    429 	if (x->kind == rcc_Address_enum)
    430 		printf("<a name='%d'></a>", x->v.rcc_Address.uid);
    431 	else if (x->kind == rcc_Local_enum)
    432 		printf("<a name='%d'></a>", x->v.rcc_Local.uid);
    433 #define attributes
    434 	switch (x->kind) {
    435 	static char *typename = "interface";
    436 	caselabel(Export);
    437 		yy(Export,p,uid);
    438 		break;
    439 	caselabel(Import);
    440 		yy(Import,p,uid);
    441 		break;
    442 	caselabel(Global);
    443 		yy(Global,p,uid);
    444 		yy(Global,seg,seg);
    445 		break;
    446 	caselabel(Local);
    447 		yy(Local,uid,define_uid);
    448 		yy(Local,p,symbol);
    449 		break;
    450 	caselabel(Address);
    451 		yy(Address,uid,define_uid);
    452 		yy(Address,q,symbol);
    453 		yy(Address,p,uid);
    454 		yy(Address,n,int);
    455 		break;
    456 	caselabel(Segment);
    457 		yy(Segment,seg,seg);
    458 		break;
    459 	caselabel(Defaddress);
    460 		yy(Defaddress,p,uid);
    461 		break;
    462 	caselabel(Deflabel);
    463 		yy(Deflabel,label,label);
    464 		break;
    465 	caselabel(Defconst);
    466 		yy(Defconst,suffix,suffix);
    467 		yy(Defconst,size,int);
    468 		yy(Defconst,value,int);
    469 		break;
    470 	caselabel(Defconstf);
    471 		yy(Defconstf,size,int);
    472 		yy(Defconstf,value,real);
    473 		break;
    474 	caselabel(Defstring);
    475 		yy(Defstring,s,string);
    476 		break;
    477 	caselabel(Space);
    478 		yy(Space,n,int);
    479 		break;
    480 	caselabel(Function);
    481 		yy(Function,f,uid);
    482 		yy(Function,caller,uid_list);
    483 		yy(Function,callee,uid_list);
    484 		yy(Function,ncalls,int);
    485 		yy(Function,codelist,interface_list);
    486 		break;
    487 	caselabel(Forest);
    488 		yy(Forest,nodes,node_list);
    489 		break;
    490 	case rcc_Blockbeg_enum: printf("<strong>Blockbeg</strong> : <em>%s</em>", typename); return;
    491 	case rcc_Blockend_enum: printf("<strong>Blockend</strong> : <em>%s</em>", typename); return;
    492 	default: assert(0);
    493 	}
    494 #undef attributes
    495 	printf("</ul>\n");
    496 }
    497 
    498 static void do_program(rcc_program_ty x) {
    499 	printf("<ul>\n");
    500 	xx(x,nuids,int);
    501 	xx(x,nlabels,int);
    502 	xx(x,items,item_list);
    503 	xx(x,interfaces,interface_list);
    504 	xx(x,argc,int);
    505 	xx(x,argv,string_list);
    506 	printf("</ul>\n");
    507 }
    508 
    509 int main(int argc, char *argv[]) {
    510 	int i, version;
    511 	float stamp = (assert(strstr(rcsid, ",v")), strtod(strstr(rcsid, ",v")+2, NULL))
    512 ;
    513 	char *infile = NULL, *outfile = NULL;
    514 	rcc_program_ty pickle;
    515 
    516 	for (i = 1; i < argc; i++)
    517 		if (*argv[i] != '-' || strcmp(argv[i], "-") == 0) {
    518 			if (infile == NULL)
    519 				infile = argv[i];
    520 			else if (outfile == NULL)
    521 				outfile = argv[i];
    522 		}
    523 	if (infile != NULL && strcmp(infile, "-") != 0
    524 	&& freopen(infile, "rb", stdin) == NULL) {
    525 		fprintf(stderr, "%s: can't read `%s'\n", argv[0], infile);
    526 		exit(EXIT_FAILURE);
    527 	}
    528 	if (infile == NULL || strcmp(infile, "-") == 0)
    529 		infile = "Standard Input";
    530 #if WIN32
    531 	else
    532 		_setmode(_fileno(stdin), _O_BINARY);
    533 #endif
    534 	if (outfile != NULL && strcmp(outfile, "-") != 0
    535 	&& freopen(outfile, "w", stdout) == NULL) {
    536 		fprintf(stderr, "%s: can't write `%s'\n", argv[0], outfile);
    537 		exit(EXIT_FAILURE);
    538 	}
    539 	version = read_int(stdin);
    540 	assert(version/100 == (int)stamp);
    541 	pickle = rcc_read_program(stdin);
    542 	printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\"\n");
    543 	printf("<html><head><title>%s</title>\n"
    544 	"<link rev=made href=\"mailto:drh@microsoft.com\">\n"
    545 	"</head><body>\n<h1>%s</h1>\n",	infile, infile);
    546 	printf("<p>version = %d.%d</p>", version/100, version%100);
    547 	do_program(pickle);
    548 	{
    549 		time_t t;
    550 		time(&t);
    551 		printf("<hr><address>%s</address>\n", ctime(&t));
    552 	}
    553 	printf("</body></html>\n");
    554 	return EXIT_SUCCESS;
    555 }