char *PR_VarString (progfuncs_t *progfuncs, int first) { int i; static char out[1024]; char *s; out[0] = 0; for (i=first ; i<pr_argc ; i++) { if (G_STRING(OFS_PARM0+i*3)) { s=G_STRING((OFS_PARM0+i*3)) + progfuncs->stringtable; if (strlen(out) + strlen(s) + 1 >= sizeof(out)) return out; strcat (out, s); } } return out; }
void PrecacheFile (def_t *e, int ch) { char *n; int i; if (!e->ofs) return; n = G_STRING(e->ofs); for (i=0 ; i<numfiles ; i++) if (!strcmp(n, precache_files[i])) return; if (numfiles == MAX_FILES) Error ("PrecacheFile: numfiles == MAX_FILES"); strcpy (precache_files[i], n); if (ch >= '1' && ch <= '9') precache_files_block[i] = ch - '0'; else precache_files_block[i] = 1; numfiles++; }
void PrecacheModel (def_t *e, int ch) { char *n; int i; if (!e->ofs) return; n = G_STRING(e->ofs); for (i=0 ; i<nummodels ; i++) if (!strcmp(n, precache_models[i])) return; if (numsounds == MAX_SOUNDS) Error ("PrecacheModels: numsounds == MAX_SOUNDS"); strcpy (precache_models[i], n); if (ch >= '1' && ch <= '9') precache_models_block[i] = ch - '0'; else precache_models_block[i] = 1; nummodels++; }
def_t *CO_ParseImmediate (void) { def_t *cn = NULL; int idx = 0; struct hash_element *cell = NULL; if (pr_immediate_type == &type_string) { idx = COM_Hash(pr_immediate_string); } else if (pr_immediate_type == &type_float) { char tmpchar[40]; sprintf(tmpchar, "%.4f", pr_immediate._float); idx = COM_Hash(tmpchar); } else if (pr_immediate_type == &type_vector) { char tmpchar[80]; sprintf(tmpchar, "%.4f,%.4f,%.4f", pr_immediate.vector[0], pr_immediate.vector[1], pr_immediate.vector[2]); idx = COM_Hash(tmpchar); } else { PR_ParseError("weird immediate type"); } for (cell = HashTable[idx]; cell != NULL; cell = cell->next) { cn = cell->def; if (!cn->initialized || (cn->type != pr_immediate_type)) { continue; } if (pr_immediate_type == &type_string) { if (!STRCMP(G_STRING(cn->ofs), pr_immediate_string)) { return cn; } } else if (pr_immediate_type == &type_float) { if (G_FLOAT(cn->ofs) == pr_immediate._float) { return cn; } } else if (pr_immediate_type == &type_vector) { if ((G_FLOAT(cn->ofs) == pr_immediate.vector[0]) && (G_FLOAT(cn->ofs+1) == pr_immediate.vector[1]) && (G_FLOAT(cn->ofs+2) == pr_immediate.vector[2])) { return cn; } } else { PR_ParseError("weird immediate type"); } } if (hcc_OptimizeImmediates) { // Check for a constant with the same value for (cn = pr.def_head.next; cn; cn = cn->next) { if (!cn->initialized || (cn->type != pr_immediate_type)) { continue; } if (pr_immediate_type == &type_string) { if (!STRCMP(G_STRING(cn->ofs), pr_immediate_string)) { cell = (struct hash_element *) malloc(sizeof(struct hash_element)); cell->next = HashTable[idx]; cell->def = cn; HashTable[idx] = cell; return cn; } } else if (pr_immediate_type == &type_float) { if (G_FLOAT(cn->ofs) == pr_immediate._float) { cell = (struct hash_element *) malloc(sizeof(struct hash_element)); cell->next = HashTable[idx]; cell->def = cn; HashTable[idx] = cell; return cn; } } else if (pr_immediate_type == &type_vector) { if ((G_FLOAT(cn->ofs) == pr_immediate.vector[0]) && ( G_FLOAT(cn->ofs+1) == pr_immediate.vector[1]) && ( G_FLOAT(cn->ofs+2) == pr_immediate.vector[2])) { cell = (struct hash_element *) malloc(sizeof(struct hash_element)); cell->next = HashTable[idx]; cell->def = cn; HashTable[idx] = cell; return cn; } } else { PR_ParseError("weird immediate type"); } } } // Allocate a new one cn = (def_t *) malloc(sizeof(def_t)); memset(cn, 0, sizeof(*cn)); cn->next = NULL; pr.def_tail->next = cn; pr.def_tail = cn; cell = (struct hash_element *) malloc(sizeof(struct hash_element)); cell->next = HashTable[idx]; cell->def = cn; HashTable[idx] = cell; cn->type = pr_immediate_type; //cn->name = "IMMEDIATE"; cn->name = "I+"; cn->initialized = 1; cn->scope = NULL; // Always share immediates // Copy the immediate to the global area cn->ofs = numpr_globals; pr_global_defs[cn->ofs] = cn; numpr_globals += type_size[pr_immediate_type->type]; if (pr_immediate_type == &type_string) { pr_immediate.string = CopyString(pr_immediate_string); } memcpy(pr_globals+cn->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]); return cn; }
/* ============ PR_ParseImmediate Looks for a preexisting constant ============ */ def_t *PR_ParseImmediate (void) { def_t *cn; // check for a constant with the same value for (cn=pr.def_head.next ; cn ; cn=cn->next) { if (!cn->initialized) continue; if (cn->type != pr_immediate_type) continue; if (pr_immediate_type == &type_string) { if (!strcmp(G_STRING(cn->ofs), pr_immediate_string) ) { PR_Lex (); return cn; } } else if (pr_immediate_type == &type_float) { if ( G_FLOAT(cn->ofs) == pr_immediate._float ) { PR_Lex (); return cn; } } else if (pr_immediate_type == &type_vector) { if ( ( G_FLOAT(cn->ofs) == pr_immediate.vector[0] ) && ( G_FLOAT(cn->ofs+1) == pr_immediate.vector[1] ) && ( G_FLOAT(cn->ofs+2) == pr_immediate.vector[2] ) ) { PR_Lex (); return cn; } } else PR_ParseError ("weird immediate type"); } // allocate a new one cn = malloc (sizeof(def_t)); cn->next = NULL; pr.def_tail->next = cn; pr.def_tail = cn; cn->search_next = pr.search; pr.search = cn; cn->type = pr_immediate_type; cn->name = "IMMEDIATE"; cn->initialized = 1; cn->scope = NULL; // always share immediates // copy the immediate to the global area cn->ofs = numpr_globals; pr_global_defs[cn->ofs] = cn; numpr_globals += type_size[pr_immediate_type->type]; if (pr_immediate_type == &type_string) pr_immediate.string = CopyString (pr_immediate_string); memcpy (pr_globals + cn->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]); PR_Lex (); return cn; }
/* ============ PR_GetImmediate Return a preexisting constant if possible, or allocate a new def ============ */ def_t *PR_GetImmediate (type_t *type, eval_t val, char *string = NULL /* for ev_string only */) { def_t *def; assert (type == &type_const_string || type == &type_const_float || type == &type_const_vector); char *name = "IMMEDIATE"; int hash = Com_HashKey (name); if (opt_mergeconstants) { // check for any constant with the same value for (def=pr.def_head.next ; def ; def=def->next) { if (def->type != type || !def->initialized) continue; if (type == &type_const_string) { if (!strcmp(G_STRING(def->ofs), string) ) return def; } else if (type == &type_const_float) { if ( G_FLOAT(def->ofs) == val._float ) return def; } else /*if (type == &type_const_vector)*/ { if ( ( G_FLOAT(def->ofs) == val.vector[0] ) && ( G_FLOAT(def->ofs+1) == val.vector[1] ) && ( G_FLOAT(def->ofs+2) == val.vector[2] ) ) { return def; } } } } else { // check for an immediate with the same value for (def = pr.def_hash_head[hash].hash_next ; def ; def=def->hash_next) { if (def->type != type || !def->initialized) continue; if (strcmp(def->name, name)) // is it indeed an immediate? continue; if (type == &type_const_string) { if (!strcmp(G_STRING(def->ofs), string) ) return def; } else if (type == &type_const_float) { if ( G_FLOAT(def->ofs) == val._float ) return def; } else /*if (type == &type_const_vector)*/ { if ( ( G_FLOAT(def->ofs) == val.vector[0] ) && ( G_FLOAT(def->ofs+1) == val.vector[1] ) && ( G_FLOAT(def->ofs+2) == val.vector[2] ) ) { return def; } } } } // allocate a new def def = PR_NewDef(hash); def->name = name; def->type = type; def->initialized = 1; def->scope = def->visscope = NULL; // always share immediates // copy the immediate to the global area if (numpr_globals + type_size[type->type] > MAX_REGS) Error ("numpr_globals > MAX_REGS"); def->ofs = numpr_globals; pr_global_defs[def->ofs] = def; numpr_globals += type_size[type->type]; if (type == &type_const_string) val.string = CopyString (string); memcpy (pr_globals + def->ofs, &val, 4*type_size[type->type]); return def; }