static function_t *ParseImmediateStatements (type_t *type) { int i; function_t *f; def_t *defs[MAX_PARMS]; def_t *scopeDef; def_t *searchDef; f = (function_t *) malloc(sizeof(function_t)); // Check for builtin function definition if (TK_CHECK(TK_COLON)) { if (pr_token_type != tt_immediate || pr_immediate_type != &type_float || pr_immediate._float != (int)pr_immediate._float) { PR_ParseError("bad builtin immediate"); } f->builtin = (int)pr_immediate._float; LX_Fetch(); return f; } f->builtin = 0; // Define the parms for (i = 0; i < type->num_parms; i++) { defs[i] = PR_GetDef(type->parm_types[i], pr_parm_names[i], pr_scope, true); f->parm_ofs[i] = defs[i]->ofs; if (i > 0 && f->parm_ofs[i] < f->parm_ofs[i-1]) { PR_ParseError("bad parm order"); } } f->code = numstatements; // Check for a state opcode if (TK_CHECK(TK_LBRACKET)) { ParseState(); } // Check for regular statements st_ReturnType = type->aux_type; st_ReturnParsed = false; if (TK_CHECK(TK_LBRACE)) { scopeDef = pr_scope; searchDef = pr.def_tail; while (pr_tokenclass != TK_RBRACE) { ST_ParseStatement(); } while ((searchDef = searchDef->next) != NULL) { if (searchDef->scope == scopeDef && searchDef->referenceCount == 0 && searchDef->parentVector == NULL) { PR_ParseWarning("unreferenced local variable '%s'", searchDef->name); } } if (type->aux_type->type != ev_void && st_ReturnParsed == false) { PR_ParseError("missing return"); } LX_Fetch(); } else if (type->aux_type->type != ev_void && st_ReturnParsed == false) { PR_ParseError("missing return"); } // Emit an end of statements opcode CO_GenCode(pr_opcodes, 0, 0); return f; }
void WriteData (int crc) { def_t *def; ddef_t *dd; dprograms_t progs; char tname[1024]; int h; unsigned int i; int size; for (def = pr.def_head.next ; def ; def = def->next) { if ((def->type->type == ev_field) && def->constant) { dd = &fields[numfielddefs]; numfielddefs++; dd->type = def->type->aux_type->type == ev_int ? ev_float : def->type->aux_type->type; if (def->save == 0) { strcpy(tname, def->name); strcat(tname, "__"); dd->s_name = CopyString(tname, 0); } else dd->s_name = CopyString (def->name, 0); dd->ofs = G_INT(def->ofs); } else if (pr_optimize_constant_names && def->constant && (def->type->type != ev_function)) { num_constant_names += strlen(def->name) + 1; num_constant_names += sizeof(ddef_t); continue; } else if (pr_optimize_unreferenced && pr_global_refs[def->ofs] <= 0) { if (!(def->type->type != ev_function)) { num_unreferenced += 1; continue; } } else if (pr_optimize_unreferenced && def->type->type == ev_vector) { if (pr_global_refs[def->ofs] + pr_global_refs[def->ofs + 1] + pr_global_refs[def->ofs +1] == 3) { num_unreferenced += 3; def = def->next; // def_x def = def->next; // def_y def = def->next; // def_z continue; } } dd = &globals[numglobaldefs]; dd->type = def->type->type == ev_int ? ev_float : def->type->type; if (def->save && ( dd->type != ev_field || def->constant != 1)) dd->type |= DEF_SAVEGLOBAL; if (def->name) { if (pr_optimize_locals && (def->scope || !(STRCMP(def->name, "IMMEDIATE")))) { num_locals_saved += strlen(def->name); dd->s_name = 0; } else dd->s_name = CopyString (def->name, 0); } dd->ofs = def->ofs; numglobaldefs++; } strofs = (strofs+3)&~3; if (strofs > INT_MAX) PR_ParseWarning(122, "strofs exceeds INT_MAX by %i", strofs - INT_MAX); if (numstatements > INT_MAX) PR_ParseWarning(123, "numstatements exceeds INT_MAX by %i", numstatements - INT_MAX); if (numfunctions > SHRT_MAX) PR_ParseWarning(124, "numfunctions exceeds SHRT_MAX by %i", numfunctions - SHRT_MAX); if (numglobaldefs > SHRT_MAX) PR_ParseWarning(125, "numglobaldefs exceeds SHRT_MAX by %i", numglobaldefs - SHRT_MAX); if (numfielddefs > SHRT_MAX) PR_ParseWarning(126, "numfielddefs exceeds SHRT_MAX by %i", numfielddefs - SHRT_MAX); if (numpr_globals > SHRT_MAX) PR_ParseWarning(127, "numpr_globals exceeds SHRT_MAX by %i", numpr_globals - SHRT_MAX); if (crc != NQ_PROGHEADER_CRC && crc != QW_PROGHEADER_CRC) PR_ParseWarning(208, "System defs do match internal crcs."); if (summary) { summary_print("----------- Summary -----------\n"); i = I_FloatTime() - StartTime; summary_print (" %02i:%02i elapsed time\n", (i / 60) % 59, i % 59); summary_print ("%6i strofs (MAX: %6i)\n", strofs, MAX_STRINGS ); summary_print ("%6i numstatements (MAX: %6i)\n", numstatements, MAX_STATEMENTS); summary_print ("%6i numfunctions (MAX: %6i)\n", numfunctions, SHRT_MAX); summary_print ("%6i numglobaldefs (MAX: %6i)\n", numglobaldefs, SHRT_MAX); summary_print ("%6i numfielddefs (MAX: %6i)\n", numfielddefs, SHRT_MAX); summary_print ("%6i numpr_globals (MAX: %6i)\n", numpr_globals, SHRT_MAX); } h = SafeOpenWrite (destfile); SafeWrite (h, &progs, sizeof(progs)); progs.ofs_strings = lseek (h, 0, SEEK_CUR); progs.numstrings = strofs; SafeWrite (h, strings, strofs); progs.ofs_statements = lseek (h, 0, SEEK_CUR); progs.numstatements = numstatements; for (i=0 ; i<numstatements ; i++) { statements[i].op = LittleShort(statements[i].op); statements[i].a = LittleShort(statements[i].a); statements[i].b = LittleShort(statements[i].b); statements[i].c = LittleShort(statements[i].c); } SafeWrite (h, statements, numstatements*sizeof(dstatement_t)); progs.ofs_functions = lseek (h, 0, SEEK_CUR); progs.numfunctions = numfunctions; for (i=0 ; i<numfunctions ; i++) { functions[i].first_statement = LittleLong (functions[i].first_statement); functions[i].parm_start = LittleLong (functions[i].parm_start); functions[i].s_name = LittleLong (functions[i].s_name < 0 || functions[i].s_name > strofs ? 0 : functions[i].s_name); functions[i].s_file = LittleLong (functions[i].s_file < 0 || functions[i].s_file > strofs ? 0 : functions[i].s_file); functions[i].numparms = LittleLong (functions[i].numparms > MAX_PARMS ? MAX_PARMS : functions[i].numparms); functions[i].locals = LittleLong (functions[i].locals); } SafeWrite (h, functions, numfunctions*sizeof(dfunction_t)); progs.ofs_globaldefs = lseek (h, 0, SEEK_CUR); progs.numglobaldefs = numglobaldefs; for (i=0 ; i<numglobaldefs ; i++) { globals[i].type = LittleShort (globals[i].type); globals[i].ofs = LittleShort (globals[i].ofs); globals[i].s_name = LittleLong (globals[i].s_name); } SafeWrite (h, globals, numglobaldefs*sizeof(ddef_t)); progs.ofs_fielddefs = lseek (h, 0, SEEK_CUR); progs.numfielddefs = numfielddefs; for (i=0 ; i<numfielddefs ; i++) { fields[i].type = LittleShort (fields[i].type); fields[i].ofs = LittleShort (fields[i].ofs); fields[i].s_name = LittleLong (fields[i].s_name < 0 || fields[i].s_name > strofs ? 0: fields[i].s_name); } SafeWrite (h, fields, numfielddefs*sizeof(ddef_t)); progs.ofs_globals = lseek (h, 0, SEEK_CUR); progs.numglobals = numpr_globals; for (i=0 ; i<numpr_globals ; i++) ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]); SafeWrite (h, pr_globals, numpr_globals*4); i = (int)lseek(h, 0, SEEK_CUR); if (summary) summary_print ("%6i TOTAL SIZE\n", i); size = (i+16)&(~15); progs.entityfields = pr.size_fields; progs.version = PROG_VERSION; progs.crc = crc; if (summary) { summary_print("%6i Progheader CRC ", crc); if (crc == NQ_PROGHEADER_CRC) summary_print("( Quake )\n"); else if (crc == QW_PROGHEADER_CRC) summary_print("(Quake World)\n"); else summary_print("( UNKNOWN )\n"); } // byte swap the header and write it out for (i=0 ; i<sizeof(progs)/4 ; i++) ((int *)&progs)[i] = LittleLong ( ((int *)&progs)[i] ); lseek (h, 0, SEEK_SET); SafeWrite (h, &progs, sizeof(progs)); // look for progs if ((def = PR_GetDef(&type_entity, "progs", NULL, false, 0, 0))) { lseek(h, progs.ofs_globals + 4 * def->ofs, SEEK_SET); i = - (size + 112); SafeWrite (h, &i, 4); } for (def = pr.def_head.next ; def ; def = def->next) { if (def->type->arraysize) { lseek(h, progs.ofs_globals + 4 * def->ofs, SEEK_SET); i = (-(size + 112)) + progs.ofs_globals + 4 * (def->arraystart); //printf("filled in %s with %i\n", def->name, def->arraystart); SafeWrite (h, &i, 4); } } if (summary) { summary_print ("%6i precache_sounds(MAX: %6i)\n", numsounds, MAX_SOUNDS); summary_print ("%6i precache_models(MAX: %6i)\n", nummodels, MAX_MODELS); } close (h); if (summary) { if (pr_optimize_eliminate_temps || pr_optimize_shorten_ifs || pr_optimize_nonvec_parms || pr_optimize_constant_names || pr_optimize_defs || pr_optimize_hash_strings || pr_optimize_locals || pr_optimize_function_names || pr_optimize_filenames || pr_optimize_unreferenced || pr_optimize_logicops || pr_optimize_recycle || pr_optimize_constant_arithmetic) { summary_print("----------- Optimization Summary -----------\n"); if (pr_optimize_eliminate_temps) summary_print("%d stores shortened\n", num_stores_shortened); if (pr_optimize_shorten_ifs) summary_print("%d ifs shortened\n", num_ifs_shortened); if (pr_optimize_nonvec_parms) summary_print("%d non-vector parms\n", num_nonvec_parms); if (pr_optimize_constant_names) summary_print("%d bytes of constant defs/names eliminated\n", num_constant_names); if (pr_optimize_defs) summary_print("%d duplicate defs eliminated\n", num_defs); if (pr_optimize_hash_strings) summary_print("%d bytes of duplicate strings eliminated\n", num_strings); if (pr_optimize_locals) summary_print("%d bytes of immediate and local names eliminated\n", num_locals_saved); if (pr_optimize_function_names) summary_print("%d bytes of function names eliminated\n", num_funcs_saved); if (pr_optimize_filenames) summary_print("%d bytes of filenames eliminated\n", num_files_saved); if (pr_optimize_unreferenced) summary_print("%d unreferenced global defs eliminated\n", num_unreferenced); if (pr_optimize_logicops) summary_print("%d logic jumps added\n", num_logic_jumps); if (pr_optimize_recycle) summary_print("%d temporary globals recycled\n", num_recycled); if (pr_optimize_constant_arithmetic) summary_print("%d constant arithmetic statements eliminated\n", num_constant_ops_saved); } } }