diff --git a/tools/qfcc/include/Makefile.am b/tools/qfcc/include/Makefile.am index 612e19c7b..a20d2a400 100644 --- a/tools/qfcc/include/Makefile.am +++ b/tools/qfcc/include/Makefile.am @@ -2,4 +2,4 @@ AUTOMAKE_OPTIONS= foreign EXTRA_DIST= class.h cmdlib.h cpp.h debug.h def.h expr.h function.h idstuff.h \ immediate.h linker.h method.h obj_file.h opcodes.h options.h \ - qfcc.h reloc.h struct.h switch.h type.h + qfcc.h reloc.h strpool.h struct.h switch.h type.h diff --git a/tools/qfcc/include/immediate.h b/tools/qfcc/include/immediate.h index 3e51b24f7..d77c298d3 100644 --- a/tools/qfcc/include/immediate.h +++ b/tools/qfcc/include/immediate.h @@ -35,7 +35,6 @@ struct expr_s; struct def_s *ReuseConstant (struct expr_s *expr, struct def_s *def); -int CopyString (const char *str); int ReuseString (const char *str); void clear_immediates (void); diff --git a/tools/qfcc/include/obj_file.h b/tools/qfcc/include/obj_file.h index 9692f5a88..d03456715 100644 --- a/tools/qfcc/include/obj_file.h +++ b/tools/qfcc/include/obj_file.h @@ -3,7 +3,7 @@ object file support - Copyright (C) 2001 Bill Currie + Copyright (C) 2002 Bill Currie Author: Bill Currie Date: 2002/6/16 @@ -123,7 +123,7 @@ typedef struct qfo_s { #define QFO_FLOAT(q, o) QFO_var (q, float, o) #define QFO_INT(q, o) QFO_var (q, integer, o) #define QFO_VECTOR(q, o) QFO_var (q, vector, o) -#define QFO_STRING(q, o) (pr.strings + QFO_var (q, string, o)) +#define QFO_STRING(q, o) G_GETSTR (QFO_var (q, string, o)) #define QFO_FUNCTION(q, o) QFO_var (q, func, o) #define QFO_POINTER(q, t,o) ((t *)((q)->data + o)) #define QFO_STRUCT(q, t,o) (*QFO_POINTER (q, t, o)) diff --git a/tools/qfcc/include/qfcc.h b/tools/qfcc/include/qfcc.h index db45bab21..7e103b432 100644 --- a/tools/qfcc/include/qfcc.h +++ b/tools/qfcc/include/qfcc.h @@ -48,9 +48,7 @@ typedef struct pr_info_s { struct type_s *types; struct ex_label_s *labels; - char *strings; - int strofs; - int strings_size; + struct strpool_s *strings; dstatement_t *statements; int *statement_linenums; @@ -80,11 +78,12 @@ extern char destfile[]; extern struct scope_s *current_scope; +#define G_GETSTR(s) (pr.strings->strings + (s)) #define G_var(t, o) (pr.near_data->data[o].t##_var) #define G_FLOAT(o) G_var (float, o) #define G_INT(o) G_var (integer, o) #define G_VECTOR(o) G_var (vector, o) -#define G_STRING(o) (pr.strings + G_var (string, o)) +#define G_STRING(o) G_GETSTR (G_var (string, o)) #define G_FUNCTION(o) G_var (func, o) #define G_POINTER(t,o) ((t *)(pr.near_data->data + o)) #define G_STRUCT(t,o) (*G_POINTER (t, o)) diff --git a/tools/qfcc/include/strpool.h b/tools/qfcc/include/strpool.h new file mode 100644 index 000000000..966dbf43a --- /dev/null +++ b/tools/qfcc/include/strpool.h @@ -0,0 +1,46 @@ +/* + strpool.h + + unique strings support + + Copyright (C) 2002 Bill Currie + + Author: Bill Currie + Date: 2002/7/5 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifndef __strpool_h +#define __strpool_h + +typedef struct strpool_s { + char *strings; + struct hashtab_s *str_tab; + int size, max_size; +} strpool_t; + +strpool_t *strpool_new (void); +strpool_t *strpool_build (const char *strings, int size); +void strpool_delete (strpool_t *strpool); +int strpool_addstr (strpool_t *strpool, const char *str); + +#endif//__strpool_h diff --git a/tools/qfcc/source/Makefile.am b/tools/qfcc/source/Makefile.am index 98adb16ed..c174063ee 100644 --- a/tools/qfcc/source/Makefile.am +++ b/tools/qfcc/source/Makefile.am @@ -40,7 +40,7 @@ bin_PROGRAMS= qfcc qfcc_SOURCES= \ class.c cmdlib.c cpp.c debug.c def.c emit.c expr.c function.c idstuff.c \ immediate.c linker.c method.c obj_file.c opcodes.c options.c qc-lex.l \ - qc-parse.y qfcc.c reloc.c struct.c switch.c type.c + qc-parse.y qfcc.c reloc.c strpool.c struct.c switch.c type.c qfcc_LDADD= $(QFCC_LIBS) qfcc_DEPENDENCIES= $(QFCC_DEPS) diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index caad2f0b8..f3eded796 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -3,7 +3,7 @@ QC function support code - Copyright (C) 2001 Bill Currie + Copyright (C) 2002 Bill Currie Author: Bill Currie Date: 2002/5/7 @@ -55,6 +55,7 @@ static const char rcsid[] = #include "method.h" #include "options.h" #include "reloc.h" +#include "strpool.h" #include "struct.h" #include "type.h" @@ -330,7 +331,7 @@ class_message_response (class_t *class, expr_t *sel) return 0; } selector = &G_STRUCT (pr_sel_t, sel->e.pointer.val); - sel_name = pr.strings + selector->sel_id; + sel_name = G_GETSTR (selector->sel_id); while (c) { if (c->methods) { for (m = c->methods->head; m; m = m->next) { diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index d9270498d..865331b81 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -37,6 +37,7 @@ static const char rcsid[] = #include "qfcc.h" #include "def.h" #include "expr.h" +#include "strpool.h" #include "struct.h" #include "type.h" @@ -365,7 +366,7 @@ free_tempdefs (void) *def = d->next; if (d->users < 0) - printf ("%s:%d: warning: %s %3d %3d %d\n", pr.strings + d->file, + printf ("%s:%d: warning: %s %3d %3d %d\n", G_GETSTR (d->file), d->line, pr_type_name[d->type->type], d->ofs, d->users, d->managed); size = type_size (d->type); @@ -394,7 +395,7 @@ reset_tempdefs (void) } for (d = temp_scope.next; d; d = d->next) - printf ("%s:%d: warning: %s %3d %3d %d\n", pr.strings + d->file, d->line, + printf ("%s:%d: warning: %s %3d %3d %d\n", G_GETSTR (d->file), d->line, pr_type_name[d->type->type], d->ofs, d->users, d->managed); temp_scope.next = 0; } diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index 0e0465002..be5097ed4 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -55,6 +55,7 @@ static const char rcsid[] = #include "immediate.h" #include "method.h" #include "options.h" +#include "strpool.h" #include "struct.h" #include "type.h" #include "qc-parse.h" @@ -232,7 +233,7 @@ error (expr_t *e, const char *fmt, ...) file = e->file; line = e->line; } - fprintf (stderr, "%s:%d: ", pr.strings + file, line); + fprintf (stderr, "%s:%d: ", G_GETSTR (file), line); vfprintf (stderr, fmt, args); fputs ("\n", stderr); va_end (args); @@ -260,7 +261,7 @@ _warning (expr_t *e, const char *fmt, va_list args) file = e->file; line = e->line; } - fprintf (stderr, "%s:%d: warning: ", pr.strings + file, line); + fprintf (stderr, "%s:%d: warning: ", G_GETSTR (file), line); vfprintf (stderr, fmt, args); fputs ("\n", stderr); } @@ -294,7 +295,7 @@ notice (expr_t *e, const char *fmt, ...) file = e->file; line = e->line; } - fprintf (stderr, "%s:%d: notice: ", pr.strings + file, line); + fprintf (stderr, "%s:%d: notice: ", G_GETSTR (file), line); vfprintf (stderr, fmt, args); fputs ("\n", stderr); } diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index b85d38ea6..3fb13e330 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -3,7 +3,7 @@ QC function support code - Copyright (C) 2001 Bill Currie + Copyright (C) 2002 Bill Currie Author: Bill Currie Date: 2002/5/7 diff --git a/tools/qfcc/source/idstuff.c b/tools/qfcc/source/idstuff.c index c90bed6e5..9495a1bf5 100644 --- a/tools/qfcc/source/idstuff.c +++ b/tools/qfcc/source/idstuff.c @@ -37,6 +37,7 @@ static const char rcsid[] = #include "qfcc.h" #include "expr.h" #include "options.h" +#include "strpool.h" #include "type.h" #define MAX_SOUNDS 1024 diff --git a/tools/qfcc/source/immediate.c b/tools/qfcc/source/immediate.c index e466f9214..a4b717f77 100644 --- a/tools/qfcc/source/immediate.c +++ b/tools/qfcc/source/immediate.c @@ -38,6 +38,7 @@ static const char rcsid[] = #include "def.h" #include "expr.h" #include "immediate.h" +#include "strpool.h" #include "type.h" static hashtab_t *string_imm_defs; @@ -49,7 +50,6 @@ static hashtab_t *func_imm_defs; static hashtab_t *pointer_imm_defs; static hashtab_t *quaternion_imm_defs; static hashtab_t *integer_imm_defs; -static hashtab_t *strings_tab; static const char * string_imm_get_key (void *_def, void *unused) @@ -95,45 +95,10 @@ int_imm_get_key (void *_def, void *_str) return va ("\001%s:%08X\001", str, G_INT (def->ofs)); } -static const char * -strings_get_key (void *_str, void *unsued) -{ - return pr.strings + (int) _str; -} - -int -CopyString (const char *str) -{ - int old; - int len = strlen (str) + 1; - - if (!strings_tab) { - strings_tab = Hash_NewTable (16381, strings_get_key, 0, 0); - } - if (pr.strofs + len >= pr.strings_size) { - pr.strings_size += (len + 16383) & ~16383; - pr.strings = realloc (pr.strings, pr.strings_size); - } - old = pr.strofs; - strcpy (pr.strings + pr.strofs, str); - pr.strofs += len; - Hash_Add (strings_tab, (void *)old); - return old; -} - int ReuseString (const char *str) { - int s; - - if (!str || !*str) - return 0; - if (!strings_tab) - return CopyString (str); - s = (long) Hash_Find (strings_tab, str); - if (s) - return s; - return CopyString (str); + return strpool_addstr (pr.strings, str); } def_t * diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index e76986331..4a81e7bcf 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -3,7 +3,7 @@ qc object file linking - Copyright (C) 2001 Bill Currie + Copyright (C) 2002 Bill Currie Author: Bill Currie Date: 2002/7/3 @@ -48,6 +48,7 @@ static const char rcsid[] = #include "immediate.h" #include "obj_file.h" #include "qfcc.h" +#include "strpool.h" static hashtab_t *extern_defs; static hashtab_t *defined_defs; @@ -57,7 +58,7 @@ defs_get_key (void *_def, void *unused) { qfo_def_t *def = (qfo_def_t *) _def; - return pr.strings + def->name; + return G_GETSTR (def->name); } void @@ -67,7 +68,7 @@ add_code (qfo_t *qfo) pr.num_statements += qfo->code_size; if (pr.num_statements >= pr.statements_size) { - pr.statements_size = (pr.num_statements + 16383) & ~16384; + pr.statements_size = (pr.num_statements + 16383) & ~16383; pr.statements = realloc (pr.statements, pr.statements_size * sizeof (dstatement_t)); } @@ -89,10 +90,10 @@ add_defs (qfo_t *qfo) Hash_Add (extern_defs, def); } else { if (def->flags & QFOD_GLOBAL) { - if ((d = Hash_Find (defined_defs, pr.strings + def->name))) { + if ((d = Hash_Find (defined_defs, G_GETSTR (def->name)))) { pr.source_file = def->file; pr.source_line = def->line; - error (0, "%s redefined", pr.strings + def->name); + error (0, "%s redefined", G_GETSTR (def->name)); } } if (def->basic_type == ev_string && def->ofs @@ -104,14 +105,14 @@ add_defs (qfo_t *qfo) if (def->ofs) def->ofs += pr.near_data->size; if (def->flags & QFOD_GLOBAL) { - while ((d = Hash_Find (extern_defs, pr.strings + def->name))) { - Hash_Del (extern_defs, pr.strings + d->name); + while ((d = Hash_Find (extern_defs, G_GETSTR (def->name)))) { + Hash_Del (extern_defs, G_GETSTR (d->name)); if (d->full_type != def->full_type) { pr.source_file = def->file; pr.source_line = def->line; error (0, "type mismatch %s %s", - pr.strings + def->full_type, - pr.strings + d->full_type); + G_GETSTR (def->full_type), + G_GETSTR (d->full_type)); } } Hash_Add (defined_defs, def); @@ -146,7 +147,7 @@ linker_begin (void) pr.statements_size = 16384; pr.statements = calloc (pr.statements_size, sizeof (dstatement_t)); pr.statement_linenums = calloc (pr.statements_size, sizeof (int)); - CopyString (""); + pr.strings = strpool_new (); pr.num_functions = 1; pr.near_data = new_defspace (); pr.near_data->data = calloc (65536, sizeof (pr_type_t)); @@ -177,6 +178,6 @@ linker_finish (void) for (def = undef_defs; *def; def++) { pr.source_file = (*def)->file; pr.source_line = (*def)->line; - error (0, "undefined symbol %s", pr.strings + (*def)->name); + error (0, "undefined symbol %s", G_GETSTR ((*def)->name)); } } diff --git a/tools/qfcc/source/method.c b/tools/qfcc/source/method.c index 4e6c744f9..db789e26c 100644 --- a/tools/qfcc/source/method.c +++ b/tools/qfcc/source/method.c @@ -3,7 +3,7 @@ QC method support code - Copyright (C) 2001 Bill Currie + Copyright (C) 2002 Bill Currie Author: Bill Currie Date: 2002/5/7 @@ -54,6 +54,7 @@ static const char rcsid[] = #include "immediate.h" #include "method.h" #include "reloc.h" +#include "strpool.h" #include "struct.h" #include "type.h" @@ -224,8 +225,8 @@ sel_def_get_hash (void *_sel_def, void *unused) sel_def_t *sel_def = (sel_def_t*)_sel_def; unsigned long hash; - hash = Hash_String (pr.strings + sel_def->sel_id) - ^ Hash_String (pr.strings + sel_def->sel_types); + hash = Hash_String (G_GETSTR (sel_def->sel_id)) + ^ Hash_String (G_GETSTR (sel_def->sel_types)); return hash; } @@ -236,10 +237,10 @@ sel_def_compare (void *_sd1, void *_sd2, void *unused) sel_def_t *sd2 = (sel_def_t*)_sd2; int cmp; - cmp = strcmp (pr.strings + sd1->sel_id, pr.strings + sd2->sel_id) == 0; + cmp = strcmp (G_GETSTR (sd1->sel_id), G_GETSTR (sd2->sel_id)) == 0; if (cmp) - cmp = strcmp (pr.strings + sd1->sel_types, - pr.strings + sd2->sel_types) == 0; + cmp = strcmp (G_GETSTR (sd1->sel_types), + G_GETSTR (sd2->sel_types)) == 0; return cmp; } diff --git a/tools/qfcc/source/obj_file.c b/tools/qfcc/source/obj_file.c index 0ea343000..d5f7c54f5 100644 --- a/tools/qfcc/source/obj_file.c +++ b/tools/qfcc/source/obj_file.c @@ -3,7 +3,7 @@ qfcc object file support - Copyright (C) 2001 Bill Currie + Copyright (C) 2002 Bill Currie Author: Bill Currie Date: 2002/6/21 @@ -50,8 +50,9 @@ static const char rcsid[] = #include "function.h" #include "immediate.h" #include "obj_file.h" -#include "reloc.h" #include "qfcc.h" +#include "reloc.h" +#include "strpool.h" #include "type.h" static qfo_def_t *defs; @@ -227,7 +228,7 @@ write_obj_file (const char *filename) file = Qopen (filename, "wbz9"); - pr.strofs = (pr.strofs + 3) & ~3; + pr.strings->size = (pr.strings->size + 3) & ~3; memset (&hdr, 0, sizeof (hdr)); @@ -238,7 +239,7 @@ write_obj_file (const char *filename) if (pr.far_data) { hdr.far_data_size = LittleLong (pr.far_data->size); } - hdr.strings_size = LittleLong (pr.strofs); + hdr.strings_size = LittleLong (pr.strings->size); hdr.num_relocs = LittleLong (num_relocs); hdr.num_defs = LittleLong (num_defs); hdr.num_functions = LittleLong (num_functions); @@ -254,8 +255,8 @@ write_obj_file (const char *filename) Qwrite (file, pr.far_data->data, pr.far_data->size * sizeof (pr_type_t)); } - if (pr.strofs) - Qwrite (file, pr.strings, pr.strofs); + if (pr.strings->size) + Qwrite (file, pr.strings->strings, pr.strings->size); if (num_relocs) Qwrite (file, relocs, num_relocs * sizeof (qfo_reloc_t)); if (num_defs) @@ -395,3 +396,92 @@ read_obj_file (const char *filename) return qfo; } + +defspace_t * +init_space (int size, pr_type_t *data) +{ + defspace_t *space = new_defspace (); + space->max_size = space->size = size; + if (size && data) { + space->data = malloc (size * sizeof (pr_type_t)); + memcpy (space->data, data, size * sizeof (pr_type_t)); + } + return space; +} + +int +qfo_to_progs (qfo_t *qfo, pr_info_t *pr) +{ + int i; + function_t *pf; + qfo_function_t *qf; + def_t *pd; + qfo_def_t *qd; + reloc_t *relocs; + + relocs = calloc (qfo->num_relocs, sizeof (reloc_t)); + for (i = 0; i < qfo->num_relocs; i++) { + if (i + 1 < qfo->num_relocs) + relocs[i].next = &relocs[i + 1]; + relocs[i].ofs = qfo->relocs[i].ofs; + relocs[i].type = qfo->relocs[i].type; + } + + pr->strings = strpool_build (qfo->strings, qfo->strings_size); + + pr->num_statements = pr->statements_size = qfo->code_size; + pr->statements = malloc (pr->statements_size * sizeof (dstatement_t)); + memcpy (pr->statements, qfo->code, + pr->statements_size * sizeof (dstatement_t)); + + pr->near_data = init_space (qfo->data_size, qfo->data); + pr->far_data = init_space (qfo->far_data_size, qfo->far_data); + pr->scope = new_scope (sc_global, pr->near_data, 0); + pr->scope->num_defs = qfo->num_defs; + pr->scope->head = calloc (pr->scope->num_defs, sizeof (def_t)); + for (i = 0, pd = pr->scope->head, qd = qfo->defs; + i < pr->scope->num_defs; i++) { + *pr->scope->tail = pd; + pr->scope->tail = &pd->def_next; + pd->type = 0; //XXX + pd->name = qfo->strings + qd->name; + pd->ofs = qd->ofs; + if (qd->num_relocs) { + pd->refs = relocs + qd->relocs; + pd->refs[qd->num_relocs - 1].next = 0; + } + pd->initialized = (qd->flags & QFOD_INITIALIZED) != 0; + pd->constant = (qd->flags & QFOD_CONSTANT) != 0; + pd->absolute = (qd->flags & QFOD_ABSOLUTE) != 0; + pd->global = (qd->flags & QFOD_GLOBAL) != 0; + pd->external = (qd->flags & QFOD_EXTERNAL) != 0; + pd->file = qd->file; + pd->line = qd->line; + } + + pr->num_functions = qfo->num_functions; + pr->func_head = calloc (pr->num_functions, sizeof (function_t)); + pr->func_tail = &pr->func_head; + for (i = 0, pf = pr->func_head, qf = qfo->functions; + i < pr->num_functions; i++) { + *pr->func_tail = pf; + pr->func_tail = &pf->next; + pf->aux = 0;//XXX + pf->builtin = qf->builtin; + pf->code = qf->code; + pf->function_num = i + 1; + pf->s_file = qf->file; + pf->file_line = qf->line; + pf->scope = new_scope (sc_params, init_space (qf->locals_size, 0), + pr->scope); + if (qf->num_local_defs) { + pf->scope->head = pr->scope->head + qf->local_defs; + pf->scope->tail = &pf->scope->head[qf->num_local_defs - 1].def_next; + } + if (qf->num_relocs) { + pf->refs = relocs + qf->relocs; + pf->refs[qf->num_relocs - 1].next = 0; + } + } + return 0; +} diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 55394dde2..5ff646bea 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -77,6 +77,7 @@ static const char rcsid[] = #include "opcodes.h" #include "options.h" #include "reloc.h" +#include "strpool.h" #include "struct.h" #include "type.h" @@ -127,6 +128,7 @@ InitData (void) if (pr.statements) { free (pr.statements); + strpool_delete (pr.strings); memset (&pr, 0, sizeof (pr)); } chain_initial_types (); @@ -136,8 +138,7 @@ InitData (void) pr.statements_size = 16384; pr.statements = calloc (pr.statements_size, sizeof (dstatement_t)); pr.statement_linenums = calloc (pr.statements_size, sizeof (int)); - pr.strofs = 0; - CopyString (""); + pr.strings = strpool_new (); pr.num_functions = 1; pr.near_data = new_defspace (); @@ -193,10 +194,10 @@ WriteData (int crc) dd->ofs = def->ofs; } - pr.strofs = (pr.strofs + 3) & ~3; + pr.strings->size = (pr.strings->size + 3) & ~3; if (options.verbosity >= 0) { - printf ("%6i strofs\n", pr.strofs); + printf ("%6i strofs\n", pr.strings->size); printf ("%6i statements\n", pr.num_statements); printf ("%6i functions\n", pr.num_functions); printf ("%6i global defs\n", numglobaldefs); @@ -210,8 +211,8 @@ WriteData (int crc) SafeWrite (h, &progs, sizeof (progs)); progs.ofs_strings = ftell (h); - progs.numstrings = pr.strofs; - SafeWrite (h, pr.strings, pr.strofs); + progs.numstrings = pr.strings->size; + SafeWrite (h, pr.strings->strings, pr.strings->size); progs.ofs_statements = ftell (h); progs.numstatements = pr.num_statements; diff --git a/tools/qfcc/source/strpool.c b/tools/qfcc/source/strpool.c new file mode 100644 index 000000000..0b61309f7 --- /dev/null +++ b/tools/qfcc/source/strpool.c @@ -0,0 +1,115 @@ +/* + strpool.c + + unique string support + + Copyright (C) 2002 Bill Currie + + Author: Bill Currie + Date: 2002/7/5 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +static const char rcsid[] = + "$Id$"; + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/hash.h" + +#include "strpool.h" + +static const char * +strpool_get_key (void *_str, void *_strpool) +{ + int str = (long) _str; + strpool_t *strpool = (strpool_t *) _strpool; + + return strpool->strings + str; +} + +strpool_t * +strpool_new (void) +{ + strpool_t *strpool = malloc (sizeof (strpool_t)); + + strpool->str_tab = Hash_NewTable (16381, strpool_get_key, 0, strpool); + strpool->size = 1; + strpool->max_size = 16384; + strpool->strings = malloc (strpool->max_size); + strpool->strings[0] = 0; + return strpool; +} + +strpool_t * +strpool_build (const char *strings, int size) +{ + int s; + + strpool_t *strpool = malloc (sizeof (strpool_t)); + strpool->str_tab = Hash_NewTable (16381, strpool_get_key, 0, strpool); + strpool->size = size; + strpool->max_size = (size + 16383) & ~16383; + strpool->strings = malloc (strpool->max_size); + memcpy (strpool->strings, strings, size); + for (s = 1; s < strpool->size; s += strlen (s) + 1) { + Hash_Add (strpool->str_tab, (void *) s); + } +} + +void +strpool_delete (strpool_t *strpool) +{ + Hash_DelTable (strpool->str_tab); + free (strpool->strings); + free (strpool); +} + +int +strpool_addstr (strpool_t *strpool, const char *str) +{ + int s; + int len; + + if (!str || !*str) + return 0; + s = (long) Hash_Find (strpool->str_tab, str); + if (s) + return s; + len = strlen (str) + 1; + if (strpool->size + len > strpool->max_size) { + strpool->max_size += (len + 16383) & ~16383; + strpool->strings = realloc (strpool->strings, strpool->max_size); + } + s = strpool->size; + strpool->size += len; + strcpy (strpool->strings + s, str); + Hash_Add (strpool->str_tab, (void *) s); + return s; +}