# HG changeset patch # User William Astle # Date 1379792034 21600 # Node ID 670ea8f902126c0f0f8b9cb8b05ea23ec46ecbdc # Parent 9e342c4e4b66a944c657500a2e74b9cd0d44975e Converted preproc logic to library and moved some utility stuff to lwlib The strbuf and strpool stuff is generally useful so move it to lwlib where other such things live. Also, package the preprocessor logic into a library for easy use in multiple places. diff -r 9e342c4e4b66 -r 670ea8f90212 Makefile --- a/Makefile Sat Sep 21 12:27:48 2013 -0600 +++ b/Makefile Sat Sep 21 13:33:54 2013 -0600 @@ -69,7 +69,8 @@ lwar_srcs := $(addprefix lwar/,$(lwar_srcs)) lwlib_srcs := lw_alloc.c lw_realloc.c lw_free.c lw_error.c lw_expr.c \ - lw_stack.c lw_string.c lw_stringlist.c lw_cmdline.c + lw_stack.c lw_string.c lw_stringlist.c lw_cmdline.c lw_strbuf.c \ + lw_strpool.c lwlib_srcs := $(addprefix lwlib/,$(lwlib_srcs)) lwlink_srcs := main.c lwlink.c readfiles.c expr.c script.c link.c output.c map.c @@ -101,12 +102,17 @@ lwcc_driver_objs := $(lwcc_driver_srcs:.c=.o) lwcc_driver_deps := $(lwcc_driver_srcs:.c=.d) -lwcc_cpp_srcs := cpp-main.c cpp.c lex.c strbuf.c token.c preproc.c symbol.c strpool.c +lwcc_cpp_srcs := cpp-main.c lwcc_cpp_srcs := $(addprefix lwcc/,$(lwcc_cpp_srcs)) lwcc_cpp_objs := $(lwcc_cpp_srcs:.c=.o) lwcc_cpp_deps := $(lwcc_cpp_srcs:.c=.d) -lwcc_deps := $(lwcc_cpp_deps) $(lwcc_driver_deps) +lwcc_cpplib_srcs := cpp.c lex.c token.c preproc.c symbol.c +lwcc_cpplib_srcs := $(addprefix lwcc/,$(lwcc_cpplib_srcs)) +lwcc_cpplib_objs := $(lwcc_cpplib_srcs:.c=.o) +lwcc_cpplib_deps := $(lwcc_cpplib_srcs:.c=.d) + +lwcc_deps := $(lwcc_cpp_deps) $(lwcc_driver_deps) $(lwcc_cpplib_deps) .PHONY: lwlink lwasm lwar lwobjdump lwcc lwlink: lwlink/lwlink$(PROGSUFFIX) @@ -115,6 +121,7 @@ lwobjdump: lwlink/lwobjdump$(PROGSUFFIX) lwcc: lwcc/lwcc$(PROGSUFFIX) lwcc-cpp: lwcc/lwcc-cpp$(PROGSUFFIX) +lwcc-cpplib: lwcc/libcpp.a lwasm/lwasm$(PROGSUFFIX): $(lwasm_objs) lwlib @echo Linking $@ @@ -136,9 +143,16 @@ @echo Linking $@ @$(CC) -o $@ $(lwcc_driver_objs) $(LDFLAGS) -lwcc/lwcc-cpp$(PROGSUFFIX): $(lwcc_cpp_objs) lwlib +lwcc/lwcc-cpp$(PROGSUFFIX): $(lwcc_cpp_objs) lwlib lwcc-cpplib @echo Linking $@ - @$(CC) -o $@ $(lwcc_cpp_objs) $(LDFLAGS) + @$(CC) -o $@ $(lwcc_cpp_objs) lwcc/libcpp.a $(LDFLAGS) + +.INTERMEDIATE: lwcc-cpplib +lwcc-cpplib: lwcc/libcpp.a +lwcc/libcpp.a: $(lwcc_cpplib_objs) + @echo Linking $@ + @$(AR) rc $@ $(lwcc_cpplib_objs) + @$(RANLIB) $@ #.PHONY: lwlib .INTERMEDIATE: lwlib @@ -170,8 +184,8 @@ clean: $(cleantargs) @echo "Cleaning up" @rm -f lwlib/liblw.a lwasm/lwasm$(PROGSUFFIX) lwlink/lwlink$(PROGSUFFIX) lwlink/lwobjdump$(PROGSUFFIX) lwar/lwar$(PROGSUFFIX) - @rm -f lwcc/lwcc$(PROGSUFFIX) lwcc/lwcc-cpp$(PROGSUFFIX) - @rm -f $(lwcc_driver_ojbs) $(lwcc_cpp_objs) + @rm -f lwcc/lwcc$(PROGSUFFIX) lwcc/lwcc-cpp$(PROGSUFFIX) lwcc/libcpp.a + @rm -f $(lwcc_driver_objs) $(lwcc_cpp_objs) $(lwcc_cpplib_objs) @rm -f $(lwasm_objs) $(lwlink_objs) $(lwar_objs) $(lwlib_objs) $(lwobjdump_objs) @rm -f $(extra_clean) @rm -f */*.exe @@ -180,7 +194,7 @@ realclean: clean $(realcleantargs) @echo "Cleaning up even more" @rm -f $(lwasm_deps) $(lwlink_deps) $(lwar_deps) $(lwlib_deps) $(lwobjdump_deps) - @rm -f $(lwcc_driver_deps) $(lwcc_cpp_deps) + @rm -f $(lwcc_driver_deps) $(lwcc_cpp_deps) $(lwcc_cpplib_deps) @rm -f docs/manual/*.html docs/manual/*.pdf print-%: diff -r 9e342c4e4b66 -r 670ea8f90212 lwcc/cpp.c --- a/lwcc/cpp.c Sat Sep 21 12:27:48 2013 -0600 +++ b/lwcc/cpp.c Sat Sep 21 13:33:54 2013 -0600 @@ -27,9 +27,9 @@ #include #include #include - +#include #include "cpp.h" -#include "strpool.h" + struct token *preproc_lex_next_token(struct preproc_info *); @@ -51,8 +51,8 @@ pp = lw_alloc(sizeof(struct preproc_info)); memset(pp, 0, sizeof(struct preproc_info)); - pp -> strpool = strpool_create(); - pp -> fn = strpool_strdup(pp -> strpool, fn); + pp -> strpool = lw_strpool_create(); + pp -> fn = lw_strpool_strdup(pp -> strpool, fn); pp -> fp = fp; pp -> ra = CPP_NOUNG; pp -> unget = CPP_NOUNG; @@ -138,7 +138,7 @@ preproc_next_token(pp); token_free(pp -> curtok); } - strpool_free(pp -> strpool); + lw_strpool_free(pp -> strpool); lw_free(pp); } diff -r 9e342c4e4b66 -r 670ea8f90212 lwcc/cpp.h --- a/lwcc/cpp.h Sat Sep 21 12:27:48 2013 -0600 +++ b/lwcc/cpp.h Sat Sep 21 13:33:54 2013 -0600 @@ -69,7 +69,7 @@ int lexstrloc; // ditto struct preproc_info *n; // next in file stack struct preproc_info *filestack; // stack of saved files during include - struct strpool *strpool; + struct lw_strpool *strpool; lw_stringlist_t quotelist; lw_stringlist_t inclist; }; diff -r 9e342c4e4b66 -r 670ea8f90212 lwcc/lex.c --- a/lwcc/lex.c Sat Sep 21 12:27:48 2013 -0600 +++ b/lwcc/lex.c Sat Sep 21 13:33:54 2013 -0600 @@ -23,9 +23,9 @@ #include #include +#include #include "cpp.h" -#include "strbuf.h" #include "token.h" /* fetch a raw input byte from the current file. Will return CPP_EOF if @@ -360,7 +360,7 @@ int ttype = TOK_NONE; int c, c2; int cl; - struct strbuf *strbuf; + struct lw_strbuf *strbuf; struct token *t = NULL; struct preproc_info *fs; @@ -616,7 +616,7 @@ /* character constant - turns into a uint */ chrlit: cl = 0; - strbuf = strbuf_new(); + strbuf = lw_strbuf_new(); for (;;) { c = preproc_lex_fetch_byte(pp); @@ -625,23 +625,23 @@ cl++; if (c == '\\') { - strbuf_add(strbuf, '\\'); + lw_strbuf_add(strbuf, '\\'); c = preproc_lex_fetch_byte(pp); if (c == CPP_EOF || c == CPP_EOL) { if (!pp -> lexstr) preproc_throw_error(pp, "Invalid character constant"); ttype = TOK_ERROR; - strval = strbuf_end(strbuf); + strval = lw_strbuf_end(strbuf); goto out; } cl++; - strbuf_add(strbuf, c); + lw_strbuf_add(strbuf, c); continue; } - strbuf_add(strbuf, c); + lw_strbuf_add(strbuf, c); } - strval = strbuf_end(strbuf); + strval = lw_strbuf_end(strbuf); if (cl == 0) { ttype = TOK_ERROR; @@ -655,15 +655,15 @@ case '"': strlit: /* string literal */ - strbuf = strbuf_new(); - strbuf_add(strbuf, '"'); + strbuf = lw_strbuf_new(); + lw_strbuf_add(strbuf, '"'); for (;;) { c = preproc_lex_fetch_byte(pp); if (c == CPP_EOF || c == CPP_EOL) { ttype = TOK_ERROR; - strval = strbuf_end(strbuf); + strval = lw_strbuf_end(strbuf); if (!pp -> lexstr) preproc_throw_error(pp, "Invalid string constant"); goto out; @@ -672,24 +672,24 @@ break; if (c == '\\') { - strbuf_add(strbuf, '\\'); + lw_strbuf_add(strbuf, '\\'); c = preproc_lex_fetch_byte(pp); if (c == CPP_EOF || c == CPP_EOL) { ttype = TOK_ERROR; if (!pp -> lexstr) preproc_throw_error(pp, "Invalid string constant"); - strval = strbuf_end(strbuf); + strval = lw_strbuf_end(strbuf); goto out; } cl++; - strbuf_add(strbuf, c); + lw_strbuf_add(strbuf, c); continue; } - strbuf_add(strbuf, c); + lw_strbuf_add(strbuf, c); } - strbuf_add(strbuf, '"'); - strval = strbuf_end(strbuf); + lw_strbuf_add(strbuf, '"'); + strval = lw_strbuf_end(strbuf); ttype = TOK_STR_LIT; goto out; @@ -718,20 +718,20 @@ case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': /* we have an identifier here */ - strbuf = strbuf_new(); - strbuf_add(strbuf, c); + strbuf = lw_strbuf_new(); + lw_strbuf_add(strbuf, c); for (;;) { c = preproc_lex_fetch_byte(pp); if ((c == '_') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { - strbuf_add(strbuf, c); + lw_strbuf_add(strbuf, c); continue; } else { - strbuf_add(strbuf, 0); - strval = strbuf_end(strbuf); + lw_strbuf_add(strbuf, 0); + strval = lw_strbuf_end(strbuf); break; } } @@ -743,8 +743,8 @@ c = preproc_lex_fetch_byte(pp); if (c >= '0' && c <= '9') { - strbuf = strbuf_new(); - strbuf_add(strbuf, '.'); + strbuf = lw_strbuf_new(); + lw_strbuf_add(strbuf, '.'); goto numlit; } else if (c == '.') @@ -763,28 +763,28 @@ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - strbuf = strbuf_new(); + strbuf = lw_strbuf_new(); numlit: ttype = TOK_NUMBER; - strbuf_add(strbuf, c); + lw_strbuf_add(strbuf, c); for (;;) { c = preproc_lex_fetch_byte(pp); if (!((c == '_') || (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) break; - strbuf_add(strbuf, c); + lw_strbuf_add(strbuf, c); if (c == 'e' || c == 'E' || c == 'p' || c == 'P') { c = preproc_lex_fetch_byte(pp); if (c == '+' || c == '-') { - strbuf_add(strbuf, c); + lw_strbuf_add(strbuf, c); continue; } preproc_lex_unfetch_byte(pp, c); } } - strval = strbuf_end(strbuf); + strval = lw_strbuf_end(strbuf); preproc_lex_unfetch_byte(pp, c); goto out; diff -r 9e342c4e4b66 -r 670ea8f90212 lwcc/preproc.c --- a/lwcc/preproc.c Sat Sep 21 12:27:48 2013 -0600 +++ b/lwcc/preproc.c Sat Sep 21 13:33:54 2013 -0600 @@ -27,10 +27,10 @@ #include #include +#include +#include #include "cpp.h" -#include "strbuf.h" -#include "strpool.h" #include "symbol.h" #include "token.h" @@ -38,6 +38,8 @@ static void process_directive(struct preproc_info *); static long eval_expr(struct preproc_info *); extern struct token *preproc_lex_next_token(struct preproc_info *); +static long preproc_numval(struct preproc_info *, struct token *); +static int eval_escape(char **); struct token *preproc_next_processed_token(struct preproc_info *pp) @@ -424,11 +426,11 @@ char *streol(struct preproc_info *pp) { - struct strbuf *s; + struct lw_strbuf *s; struct token *ct; int i; - s = strbuf_new(); + s = lw_strbuf_new(); do { ct = preproc_next_token(pp); @@ -437,10 +439,10 @@ while (ct -> ttype != TOK_EOL) { for (i = 0; ct -> strval[i]; i++) - strbuf_add(s, ct -> strval[i]); + lw_strbuf_add(s, ct -> strval[i]); ct = preproc_next_token(pp); } - return strbuf_end(s); + return lw_strbuf_end(s); } static void dir_error(struct preproc_info *pp) @@ -544,7 +546,7 @@ struct token *ct; int sys = 0; char *fn; - struct strbuf *strbuf; + struct lw_strbuf *strbuf; int i; struct preproc_info *fs; @@ -561,7 +563,7 @@ } else if (ct -> ttype == TOK_LT) { - strbuf = strbuf_new(); + strbuf = lw_strbuf_new(); for (;;) { int c; @@ -570,23 +572,23 @@ { preproc_lex_unfetch_byte(pp, c); preproc_throw_error(pp, "Bad #include"); - lw_free(strbuf_end(strbuf)); + lw_free(lw_strbuf_end(strbuf)); break; } if (c == '>') break; - strbuf_add(strbuf, c); + lw_strbuf_add(strbuf, c); } ct = preproc_next_token_nws(pp); if (ct -> ttype != TOK_EOL) { preproc_throw_error(pp, "Bad #include"); skip_eol(pp); - lw_free(strbuf_end(strbuf)); + lw_free(lw_strbuf_end(strbuf)); return; } sys = 1; - fn = strbuf_end(strbuf); + fn = lw_strbuf_end(strbuf); goto doinc; } else @@ -598,7 +600,7 @@ goto usrinc; else if (ct -> ttype == TOK_LT) { - strbuf = strbuf_new(); + strbuf = lw_strbuf_new(); for (;;) { ct = preproc_next_processed_token(pp); @@ -607,12 +609,12 @@ if (ct -> ttype == TOK_EOL) { preproc_throw_error(pp, "Bad #include"); - lw_free(strbuf_end(strbuf)); + lw_free(lw_strbuf_end(strbuf)); return; } for (i = 0; ct -> strval[i]; ct++) { - strbuf_add(strbuf, ct -> strval[i]); + lw_strbuf_add(strbuf, ct -> strval[i]); } } ct = preproc_next_processed_token_nws(pp); @@ -620,11 +622,11 @@ { preproc_throw_error(pp, "Bad #include"); skip_eol(pp); - lw_free(strbuf_end(strbuf)); + lw_free(lw_strbuf_end(strbuf)); return; } sys = 1; - fn = strbuf_end(strbuf); + fn = lw_strbuf_end(strbuf); goto doinc; } else @@ -653,7 +655,7 @@ fs -> n = pp -> filestack; pp -> curtok = NULL; pp -> filestack = fs; - pp -> fn = strpool_strdup(pp -> strpool, fn); + pp -> fn = lw_strpool_strdup(pp -> strpool, fn); lw_free(fn); pp -> fp = fp; pp -> ra = CPP_NOUNG; @@ -770,6 +772,36 @@ if (ct -> ttype == TOK_EOL) return; + if (ct -> ttype == TOK_NUMBER) + { + // this is probably a file marker from a previous run of the preprocessor + char *fn; + struct lw_strbuf *sb; + + i = preproc_numval(pp, ct); + ct = preproc_next_token_nws(pp); + if (ct -> ttype != TOK_STR_LIT) + goto baddir; + pp -> lineno = i; + sb = lw_strbuf_new(); + for (fn = ct -> strval; *fn && *fn != '"'; ) + { + if (*fn == '\\') + { + lw_strbuf_add(sb, eval_escape(&fn)); + } + else + { + lw_strbuf_add(sb, *fn++); + } + } + fn = lw_strbuf_end(sb); + pp -> fn = lw_strpool_strdup(pp -> strpool, fn); + lw_free(fn); + skip_eol(pp); + return; + } + if (ct -> ttype != TOK_IDENT) goto baddir; @@ -800,7 +832,6 @@ } static long eval_expr_real(struct preproc_info *, int); -static long preproc_numval(struct preproc_info *, struct token *); static long eval_term_real(struct preproc_info *pp) { @@ -1165,12 +1196,12 @@ */ static char *stringify(struct token_list *tli) { - struct strbuf *s; + struct lw_strbuf *s; int ws = 0; struct token *tl = tli -> head; - s = strbuf_new(); - strbuf_add(s, '"'); + s = lw_strbuf_new(); + lw_strbuf_add(s, '"'); while (tl && tl -> ttype == TOK_WSPACE) tl = tl -> next; @@ -1184,21 +1215,21 @@ } if (ws) { - strbuf_add(s, ' '); + lw_strbuf_add(s, ' '); } for (ws = 0; tl -> strval[ws]; ws++) { if (tl -> ttype == TOK_STR_LIT || tl -> ttype == TOK_CHR_LIT) { if (tl -> strval[ws] == '"' || tl -> strval[ws] == '\\') - strbuf_add(s, '\\'); + lw_strbuf_add(s, '\\'); } } ws = 0; } - strbuf_add(s, '"'); - return strbuf_end(s); + lw_strbuf_add(s, '"'); + return lw_strbuf_end(s); } static int macro_arg(struct symtab_e *s, char *str) @@ -1339,26 +1370,26 @@ // check for built in macros if (strcmp(mname, "__FILE__") == 0) { - struct strbuf *sb; + struct lw_strbuf *sb; - sb = strbuf_new(); - strbuf_add(sb, '"'); + sb = lw_strbuf_new(); + lw_strbuf_add(sb, '"'); for (tstr = (char *)(pp -> fn); *tstr; tstr++) { if (*tstr == 32 || (*tstr > 34 && *tstr < 127)) { - strbuf_add(sb, *tstr); + lw_strbuf_add(sb, *tstr); } else { - strbuf_add(sb, '\\'); - strbuf_add(sb, (*tstr >> 6) + '0'); - strbuf_add(sb, ((*tstr >> 3) & 7) + '0'); - strbuf_add(sb, (*tstr & 7) + '0'); + lw_strbuf_add(sb, '\\'); + lw_strbuf_add(sb, (*tstr >> 6) + '0'); + lw_strbuf_add(sb, ((*tstr >> 3) & 7) + '0'); + lw_strbuf_add(sb, (*tstr & 7) + '0'); } } - strbuf_add(sb, '"'); - tstr = strbuf_end(sb); + lw_strbuf_add(sb, '"'); + tstr = lw_strbuf_end(sb); preproc_unget_token(pp, token_create(TOK_STR_LIT, tstr, pp -> lineno, pp -> column, pp -> fn)); lw_free(tstr); return 1; diff -r 9e342c4e4b66 -r 670ea8f90212 lwcc/strbuf.c --- a/lwcc/strbuf.c Sat Sep 21 12:27:48 2013 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* -lwcc/strbuf.c - -Copyright © 2013 William Astle - -This file is part of LWTOOLS. - -LWTOOLS 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 3 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, see . -*/ - -#include - -#include - -#include "strbuf.h" - -struct strbuf *strbuf_new(void) -{ - struct strbuf *strbuf; - - strbuf = lw_alloc(sizeof(struct strbuf)); - strbuf -> str = NULL; - strbuf -> bo = 0; - strbuf -> bl = 0; - return strbuf; -} - -void strbuf_add(struct strbuf *strbuf, int c) -{ - if (strbuf -> bo >= strbuf -> bl) - { - strbuf -> bl += 100; - strbuf -> str = lw_realloc(strbuf -> str, strbuf -> bl); - } - strbuf -> str[strbuf -> bo++] = c; -} - -char *strbuf_end(struct strbuf *strbuf) -{ - char *rv; - - strbuf_add(strbuf, 0); - rv = strbuf -> str; - lw_free(strbuf); - return rv; -} diff -r 9e342c4e4b66 -r 670ea8f90212 lwcc/strbuf.h --- a/lwcc/strbuf.h Sat Sep 21 12:27:48 2013 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* -lwcc/strbuf.h - -Copyright © 2013 William Astle - -This file is part of LWTOOLS. - -LWTOOLS 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 3 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, see . -*/ - -#ifndef strbuf_h_seen___ -#define strbuf_h_seen___ - -struct strbuf -{ - char *str; - int bl; - int bo; -}; - -extern struct strbuf *strbuf_new(void); -extern void strbuf_add(struct strbuf *, int); -extern char *strbuf_end(struct strbuf *); - -#endif // strbufh_seen___ diff -r 9e342c4e4b66 -r 670ea8f90212 lwcc/strpool.c --- a/lwcc/strpool.c Sat Sep 21 12:27:48 2013 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* -lwcc/strpool.c - -Copyright © 2013 William Astle - -This file is part of LWTOOLS. - -LWTOOLS 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 3 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, see . -*/ - -#include -#include - -#include -#include - -#include "strpool.h" - -struct strpool *strpool_create(void) -{ - struct strpool *sp; - - sp = lw_alloc(sizeof(struct strpool)); - sp -> nstrs = 0; - sp -> strs = NULL; - return sp; -} - -extern void strpool_free(struct strpool *sp) -{ - int i; - - for (i = 0; i < sp -> nstrs; i++) - lw_free(sp -> strs[i]); - lw_free(sp -> strs); - lw_free(sp); -} - -char *strpool_strdup(struct strpool *sp, const char *s) -{ - int i; - - if (!s) - return NULL; - - /* first do a fast scan for a pointer match */ - for (i = 0; i < sp -> nstrs; i++) - if (sp -> strs[i] == s) - return sp -> strs[i]; - - /* no match - do a slow scan for a string match */ - for (i = 0; i < sp -> nstrs; i++) - if (strcmp(sp -> strs[i], s) == 0) - return sp -> strs[i]; - - /* no match - create a new string entry */ - sp -> strs = lw_realloc(sp -> strs, sizeof(char *) * (sp -> nstrs + 1)); - sp -> strs[sp -> nstrs] = lw_strdup(s); - sp -> nstrs++; - return sp -> strs[sp -> nstrs - 1]; -} diff -r 9e342c4e4b66 -r 670ea8f90212 lwcc/strpool.h --- a/lwcc/strpool.h Sat Sep 21 12:27:48 2013 -0600 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* -lwcc/strpool.h - -Copyright © 2013 William Astle - -This file is part of LWTOOLS. - -LWTOOLS 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 3 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, see . -*/ - -#ifndef strpool_h_seen___ -#define strpool_h_seen___ - -struct strpool -{ - int nstrs; - char **strs; -}; - -extern struct strpool *strpool_create(void); -extern void strpool_free(struct strpool *); -extern char *strpool_strdup(struct strpool *, const char *); - -#endif // strpool.h_seen___ diff -r 9e342c4e4b66 -r 670ea8f90212 lwlib/lw_strbuf.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwlib/lw_strbuf.c Sat Sep 21 13:33:54 2013 -0600 @@ -0,0 +1,56 @@ +/* +lwlib/lw_strbuf.c + +Copyright © 2013 William Astle + +This file is part of LWTOOLS. + +LWTOOLS 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 3 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, see . +*/ + +#include + +#include "lw_alloc.h" +#include "lw_strbuf.h" + +struct lw_strbuf *lw_strbuf_new(void) +{ + struct lw_strbuf *lw_strbuf; + + lw_strbuf = lw_alloc(sizeof(struct lw_strbuf)); + lw_strbuf -> str = NULL; + lw_strbuf -> bo = 0; + lw_strbuf -> bl = 0; + return lw_strbuf; +} + +void lw_strbuf_add(struct lw_strbuf *lw_strbuf, int c) +{ + if (lw_strbuf -> bo >= lw_strbuf -> bl) + { + lw_strbuf -> bl += 100; + lw_strbuf -> str = lw_realloc(lw_strbuf -> str, lw_strbuf -> bl); + } + lw_strbuf -> str[lw_strbuf -> bo++] = c; +} + +char *lw_strbuf_end(struct lw_strbuf *lw_strbuf) +{ + char *rv; + + lw_strbuf_add(lw_strbuf, 0); + rv = lw_strbuf -> str; + lw_free(lw_strbuf); + return rv; +} diff -r 9e342c4e4b66 -r 670ea8f90212 lwlib/lw_strbuf.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwlib/lw_strbuf.h Sat Sep 21 13:33:54 2013 -0600 @@ -0,0 +1,36 @@ +/* +lwlib/lw_strbuf.h + +Copyright © 2013 William Astle + +This file is part of LWTOOLS. + +LWTOOLS 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 3 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, see . +*/ + +#ifndef ___lw_strbuf_h_seen___ +#define ___lw_strbuf_h_seen___ + +struct lw_strbuf +{ + char *str; + int bl; + int bo; +}; + +extern struct lw_strbuf *lw_strbuf_new(void); +extern void lw_strbuf_add(struct lw_strbuf *, int); +extern char *lw_strbuf_end(struct lw_strbuf *); + +#endif // ___lw_strbuf_h_seen___ diff -r 9e342c4e4b66 -r 670ea8f90212 lwlib/lw_strpool.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwlib/lw_strpool.c Sat Sep 21 13:33:54 2013 -0600 @@ -0,0 +1,71 @@ +/* +lwlib/lw_strpool.c + +Copyright © 2013 William Astle + +This file is part of LWTOOLS. + +LWTOOLS 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 3 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, see . +*/ + +#include +#include + +#include "lw_alloc.h" +#include "lw_string.h" +#include "lw_strpool.h" + +struct lw_strpool *lw_strpool_create(void) +{ + struct lw_strpool *sp; + + sp = lw_alloc(sizeof(struct lw_strpool)); + sp -> nstrs = 0; + sp -> strs = NULL; + return sp; +} + +extern void lw_strpool_free(struct lw_strpool *sp) +{ + int i; + + for (i = 0; i < sp -> nstrs; i++) + lw_free(sp -> strs[i]); + lw_free(sp -> strs); + lw_free(sp); +} + +char *lw_strpool_strdup(struct lw_strpool *sp, const char *s) +{ + int i; + + if (!s) + return NULL; + + /* first do a fast scan for a pointer match */ + for (i = 0; i < sp -> nstrs; i++) + if (sp -> strs[i] == s) + return sp -> strs[i]; + + /* no match - do a slow scan for a string match */ + for (i = 0; i < sp -> nstrs; i++) + if (strcmp(sp -> strs[i], s) == 0) + return sp -> strs[i]; + + /* no match - create a new string entry */ + sp -> strs = lw_realloc(sp -> strs, sizeof(char *) * (sp -> nstrs + 1)); + sp -> strs[sp -> nstrs] = lw_strdup(s); + sp -> nstrs++; + return sp -> strs[sp -> nstrs - 1]; +} diff -r 9e342c4e4b66 -r 670ea8f90212 lwlib/lw_strpool.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwlib/lw_strpool.h Sat Sep 21 13:33:54 2013 -0600 @@ -0,0 +1,35 @@ +/* +lwlib/lw_strpool.h + +Copyright © 2013 William Astle + +This file is part of LWTOOLS. + +LWTOOLS 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 3 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, see . +*/ + +#ifndef ___lw_strpool_h_seen___ +#define ___lw_strpool_h_seen___ + +struct lw_strpool +{ + int nstrs; + char **strs; +}; + +extern struct lw_strpool *lw_strpool_create(void); +extern void lw_strpool_free(struct lw_strpool *); +extern char *lw_strpool_strdup(struct lw_strpool *, const char *); + +#endif // ___lw_strpool_h_seen____