diff options
| author | peter <peter@pmikkelsen.com> | 2026-08-31 19:44:56 +0000 |
|---|---|---|
| committer | peter <peter@pmikkelsen.com> | 2026-08-31 19:44:56 +0000 |
| commit | 7f7a2fb4fb23433e7be3d6953725690c8ea958d2 (patch) | |
| tree | e73bc6f3bd9d5132a0262966cd99986027142144 | |
| parent | 729964bea692f9683860978b89848784a7fc2f46 (diff) | |
The objects returned to the user are now integer-based references,
not actual pointers. This means the aplwc internals can update those
pointers without the user noticing.
FossilOrigin-Name: 654c7d0ec85da295a7fb6ed381500410686b280f342fa81a30481f5e9a20c58a
| -rw-r--r-- | src/bin/main.c | 37 | ||||
| -rw-r--r-- | src/include/aplwc.h | 26 | ||||
| -rw-r--r-- | src/lib/aplwc_internal.h | 13 | ||||
| -rw-r--r-- | src/lib/main.c | 107 | ||||
| -rw-r--r-- | src/lib/memory.c | 83 | ||||
| -rw-r--r-- | tests/aplwc_errstr.c | 9 | ||||
| -rw-r--r-- | tests/aplwc_eval.c | 10 | ||||
| -rw-r--r-- | tests/aplwc_read.c | 6 | ||||
| -rw-r--r-- | tests/aplwc_utf8.c | 8 |
9 files changed, 226 insertions, 73 deletions
diff --git a/src/bin/main.c b/src/bin/main.c index 99149f6..42ab963 100644 --- a/src/bin/main.c +++ b/src/bin/main.c @@ -4,7 +4,8 @@ #include <errno.h> #include "aplwc_repl.h" -static void *my_alloc(size_t min, size_t max, size_t *actual) +static void * +my_alloc(size_t min, size_t max, size_t *actual) { UNUSED_PARAMETER(max); @@ -12,23 +13,29 @@ static void *my_alloc(size_t min, size_t max, size_t *actual) return malloc(min); } +static void +my_dealloc(void *p) +{ + free(p); +} + int main(int argc, char *argv[]) { struct aplwc_fns fns; struct aplwc *aplwc; - struct aplwc_line *line; - struct aplwc_value *value; + enum aplwc_rc ret; + AplwcLine line; + AplwcValue value; char *input, *src; - int ret, exit_code, line_number; + int exit_code, line_number; size_t input_size, src_size, i; int opt, xflag, input_file; long tmp; FILE *f; - input = NULL; - line = NULL; - value = NULL; + aplwc_clear_line(&line); + aplwc_clear_value(&value); xflag = 0; input_file = 0; exit_code = 0; @@ -36,6 +43,7 @@ main(int argc, char *argv[]) memset(&fns, 0, sizeof(fns)); fns.alloc = my_alloc; + fns.dealloc = my_dealloc; while((opt = getopt(argc, argv, "x")) != -1){ switch(opt){ @@ -61,7 +69,7 @@ usage: else goto usage; - ret = aplwc_new(&aplwc, fns); + aplwc = aplwc_new(fns, &ret); if(ret){ fprintf(stderr, "Couldn't create new aplwc instance: %s\n", aplwc_errstr_rc(ret)); return 1; @@ -117,19 +125,20 @@ file_size: for(;;){ if(input) free(input); - if(line) + if(aplwc_valid_line(line)) aplwc_free_line(line); - if(value) + if(aplwc_valid_value(value)) aplwc_free_value(value); input = NULL; if(getline(&input, &input_size, stdin) < 0){ free(input); + input = NULL; break; }else{ line_number++; line = aplwc_read(aplwc, input); - if(line == NULL){ + if(!aplwc_valid_line(line)){ line_error: fprintf(stderr, "error on line %d: %s: %s\n", line_number, aplwc_errstr(aplwc), input); if(input_file){ @@ -139,7 +148,7 @@ line_error: continue; } value = aplwc_eval(line); - if(value == NULL) + if(!aplwc_valid_value(value)) goto line_error; fprintf(stdout, "%s\n", aplwc_value_string(value)); } @@ -148,9 +157,9 @@ line_error: exit: if(input) free(input); - if(line) + if(aplwc_valid_line(line)) aplwc_free_line(line); - if(value) + if(aplwc_valid_value(value)) aplwc_free_value(value); aplwc_destroy(aplwc); diff --git a/src/include/aplwc.h b/src/include/aplwc.h index 843fe42..6ba2e35 100644 --- a/src/include/aplwc.h +++ b/src/include/aplwc.h @@ -15,24 +15,34 @@ enum aplwc_rc { }; struct aplwc; -struct aplwc_line; -struct aplwc_value; + +struct aplwc_ref { + struct aplwc *aplwc; + int id; +}; + +typedef struct { struct aplwc_ref ref; } AplwcLine; +typedef struct { struct aplwc_ref ref; } AplwcValue; struct aplwc_fns { void *(*alloc)(size_t, size_t, size_t *); void (*dealloc)(void *); }; -enum aplwc_rc aplwc_new(struct aplwc **, struct aplwc_fns); +struct aplwc *aplwc_new(struct aplwc_fns, enum aplwc_rc *); void aplwc_destroy(struct aplwc *); +void aplwc_clear_line(AplwcLine *); +void aplwc_clear_value(AplwcValue *); +int aplwc_valid_line(AplwcLine); +int aplwc_valid_value(AplwcValue); const char *aplwc_errstr_rc(enum aplwc_rc); const char *aplwc_errstr(struct aplwc *); enum aplwc_rc aplwc_last_error(struct aplwc *); -struct aplwc_line *aplwc_read(struct aplwc *, const char *); -void aplwc_free_line(struct aplwc_line *); -struct aplwc_value *aplwc_eval(struct aplwc_line *); -void aplwc_free_value(struct aplwc_value *); -const char *aplwc_value_string(struct aplwc_value *); +AplwcLine aplwc_read(struct aplwc *, const char *); +void aplwc_free_line(AplwcLine); +AplwcValue aplwc_eval(AplwcLine); +void aplwc_free_value(AplwcValue); +const char *aplwc_value_string(AplwcValue); enum aplwc_rc aplwc_load_module(struct aplwc *, const char *, const char *, int n); #endif /* APLWC_H */ diff --git a/src/lib/aplwc_internal.h b/src/lib/aplwc_internal.h index a7b7030..5320336 100644 --- a/src/lib/aplwc_internal.h +++ b/src/lib/aplwc_internal.h @@ -18,6 +18,7 @@ struct aplwc { uint8_t *unaligned_data; size_t size; struct memory_ptr_frame *memptrs; + struct root_ptr *rootptrs; }; struct memory_ptr_frame { @@ -26,6 +27,12 @@ struct memory_ptr_frame { size_t count; }; +struct root_ptr { + int id; + void *ptr; + struct root_ptr *link; +}; + struct aplwc_line { struct aplwc *aplwc; struct string *text; @@ -95,9 +102,13 @@ struct token_list *memory_alloc_token_list(struct aplwc *, size_t); struct aplwc_value *memory_alloc_aplwc_value(struct aplwc *); struct aplwc_module *memory_alloc_aplwc_module(struct aplwc *); struct module_imports *memory_alloc_module_imports(struct aplwc *, size_t); -void memory_free_root(struct aplwc *, void *); +struct aplwc_ref memory_root_new(struct aplwc *, void *); +void *memory_root_get(struct aplwc_ref); +void memory_root_free(struct aplwc_ref); void memptrs_add(struct aplwc *, struct memory_ptr_frame *, void ***, size_t); void memptrs_remove(struct aplwc *, struct memory_ptr_frame *); +void clear_ref(struct aplwc_ref *); +int valid_ref(struct aplwc_ref); #define MEMPTRS(aplwc, n) \ void **memptrs[n]; \ diff --git a/src/lib/main.c b/src/lib/main.c index 03c31a5..454ad1c 100644 --- a/src/lib/main.c +++ b/src/lib/main.c @@ -1,22 +1,34 @@ #include "aplwc_internal.h" #include "boot.h" -enum aplwc_rc -aplwc_new(struct aplwc **p, struct aplwc_fns fns) +struct aplwc * +aplwc_new(struct aplwc_fns fns, enum aplwc_rc *rcp) { + enum aplwc_rc rc; struct aplwc *aplwc; size_t size; - if(fns.alloc == NULL) - return APLWC_OUT_OF_MEMORY; + aplwc = NULL; + if(fns.alloc == NULL){ + rc = APLWC_OUT_OF_MEMORY; + goto end; + } aplwc = fns.alloc(sizeof(*aplwc), sizeof(*aplwc), &size); - if(aplwc == NULL) - return APLWC_OUT_OF_MEMORY; - *p = aplwc; + if(aplwc == NULL){ + rc = APLWC_OUT_OF_MEMORY; + goto end; + } aplwc->fns = fns; memory_init(aplwc); - return aplwc_load_module(aplwc, "Boot", (const char *)boot_src, boot_src_len); + + rc = aplwc_load_module(aplwc, "Boot", (const char *)boot_src, boot_src_len); +end: + if(rc != APLWC_OK) + aplwc_destroy(aplwc); + if(rcp) + *rcp = rc; + return aplwc; } void @@ -71,18 +83,19 @@ aplwc_last_error(struct aplwc *aplwc) return aplwc->last_error; } -struct aplwc_line * -aplwc_read(struct aplwc *aplwc, const char *line) +AplwcLine +aplwc_read(struct aplwc *aplwc, const char *linestr) { struct string *text; struct token_list *tokens; - struct aplwc_line *ret; + struct aplwc_line *line; + AplwcLine ret; MEMPTRS(aplwc, 2); - ret = NULL; + aplwc_clear_line(&ret); - if((text = chars_to_string(aplwc, line, -1)) == NULL) + if((text = chars_to_string(aplwc, linestr, -1)) == NULL) goto end; MEMPTR(0, text); @@ -93,45 +106,55 @@ aplwc_read(struct aplwc *aplwc, const char *line) if((aplwc->last_error = check_tokens(tokens)) != APLWC_OK) goto end; - if((ret = memory_alloc_aplwc_line(aplwc)) == NULL) + if((line = memory_alloc_aplwc_line(aplwc)) == NULL) goto end; - ret->aplwc = aplwc; - ret->text = text; - ret->tokens = tokens; + line->aplwc = aplwc; + line->text = text; + line->tokens = tokens; + ret.ref = memory_root_new(aplwc, line); end: MEMPTRS_EXIT(aplwc); return ret; } void -aplwc_free_line(struct aplwc_line *line) +aplwc_free_line(AplwcLine line) { - if(line) - memory_free_root(line->aplwc, line); + memory_root_free(line.ref); } -struct aplwc_value * -aplwc_eval(struct aplwc_line *line) +AplwcValue +aplwc_eval(AplwcLine line) { - line->aplwc->last_error = APLWC_OK; - return eval_line(line); + AplwcValue value; + struct aplwc_line *l; + struct aplwc_value *v; + + aplwc_clear_value(&value); + l = memory_root_get(line.ref); + l->aplwc->last_error = APLWC_OK; + v = eval_line(l); + if(v) + value.ref = memory_root_new(line.ref.aplwc, v); + return value; } void -aplwc_free_value(struct aplwc_value *value) +aplwc_free_value(AplwcValue value) { - if(value) - memory_free_root(value->aplwc, value); + memory_root_free(value.ref); } const char * -aplwc_value_string(struct aplwc_value *value) +aplwc_value_string(AplwcValue value) { - assert(value != NULL); + struct aplwc_value *v; + assert(aplwc_valid_value(value)); - switch(value->tag){ + v = memory_root_get(value.ref); + switch(v->tag){ default: return "???"; } @@ -162,3 +185,27 @@ end: MEMPTRS_EXIT(aplwc); return aplwc_last_error(aplwc); } + +void +aplwc_clear_value(AplwcValue *v) +{ + clear_ref(&v->ref); +} + +void +aplwc_clear_line(AplwcLine *l) +{ + clear_ref(&l->ref); +} + +int +aplwc_valid_value(AplwcValue v) +{ + return valid_ref(v.ref); +} + +int +aplwc_valid_line(AplwcLine l) +{ + return valid_ref(l.ref); +} diff --git a/src/lib/memory.c b/src/lib/memory.c index 8a91d2d..b6e044a 100644 --- a/src/lib/memory.c +++ b/src/lib/memory.c @@ -26,6 +26,7 @@ memory_init(struct aplwc *aplwc) aplwc->unaligned_data = NULL; aplwc->size = 0; aplwc->memptrs = NULL; + aplwc->rootptrs = NULL; } void @@ -49,6 +50,7 @@ fixrefs(struct aplwc *aplwc, uint8_t *new, uint8_t *old) struct chunk *c; struct memory_ptr_frame *frame; + struct root_ptr *root; size_t add, sub, i; if(new > old){ @@ -89,6 +91,10 @@ fixrefs(struct aplwc *aplwc, uint8_t *new, uint8_t *old) for(i = 0; i < frame->count; i++) if(frame->ptrs[i]) FIX(*frame->ptrs[i]); + + for(root = aplwc->rootptrs; root; root = root->link) + if(root->ptr) + FIX(root->ptr); #undef FIX #undef FIX_DATA @@ -198,13 +204,71 @@ retry: return new->data; } +struct aplwc_ref +memory_root_new(struct aplwc *aplwc, void *p) +{ + struct aplwc_ref ref; + struct root_ptr *root; + size_t size; + + clear_ref(&ref); + if(aplwc->fns.alloc == NULL){ + aplwc->last_error = APLWC_OUT_OF_MEMORY; + goto end; + } + + root = aplwc->fns.alloc(sizeof(*root), sizeof(*root), &size); + if(root == NULL){ + aplwc->last_error = APLWC_OUT_OF_MEMORY; + goto end; + } + + root->id = aplwc->rootptrs ? (aplwc->rootptrs->id+1) : 0; + root->ptr = p; + root->link = aplwc->rootptrs; + aplwc->rootptrs = root; + + ref.id = root->id; + ref.aplwc = aplwc; +end: + return ref; +} + +void * +memory_root_get(struct aplwc_ref ref) +{ + struct root_ptr *root; + + if(!valid_ref(ref)) + return NULL; + + for(root = ref.aplwc->rootptrs; root; root = root->link) + if(root->id == ref.id) + return root->ptr; + + return NULL; +} + void -memory_free_root(struct aplwc *aplwc, void *p) +memory_root_free(struct aplwc_ref ref) { - if(NEVER(p == NULL)) + struct aplwc *aplwc; + struct root_ptr **root, *tmp; + + if(!valid_ref(ref)) return; - UNUSED_PARAMETER(aplwc); + aplwc = ref.aplwc; + + for(root = &aplwc->rootptrs; (*root); root = &(*root)->link){ + if((*root)->id == ref.id){ + tmp = *root; + *root = tmp->link; + if(aplwc->fns.dealloc) + aplwc->fns.dealloc(tmp); + break; + } + } } void @@ -273,3 +337,16 @@ memory_alloc_aplwc_module(struct aplwc *aplwc) p = alloc(aplwc, sizeof(struct aplwc_module), CHUNK_TAG_APLWC_MODULE); return p; } + +void +clear_ref(struct aplwc_ref *ref) +{ + ref->id = -1; + ref->aplwc = NULL; +} + +int +valid_ref(struct aplwc_ref ref) +{ + return ref.id >= 0; +} diff --git a/tests/aplwc_errstr.c b/tests/aplwc_errstr.c index 1a5ebc4..fe9fa0e 100644 --- a/tests/aplwc_errstr.c +++ b/tests/aplwc_errstr.c @@ -20,19 +20,19 @@ my_dealloc(void *p) int main(void) { + enum aplwc_rc ret; struct aplwc_fns fns; struct aplwc *aplwc; - int ret, success; + int success; const char *err; success = 0; - aplwc = NULL; memset(&fns, 0, sizeof(fns)); fns.alloc = my_alloc; fns.dealloc = my_dealloc; - ret = aplwc_new(&aplwc, fns); + aplwc = aplwc_new(fns, &ret); if(ret) goto end; @@ -50,10 +50,9 @@ main(void) goto end; aplwc_destroy(aplwc); - aplwc = NULL; fns.alloc = NULL; - ret = aplwc_new(&aplwc, fns); + aplwc = aplwc_new(fns, &ret); if(ret == 0) goto end; err = aplwc_errstr_rc(ret); diff --git a/tests/aplwc_eval.c b/tests/aplwc_eval.c index 68ea4a8..3fd8c27 100644 --- a/tests/aplwc_eval.c +++ b/tests/aplwc_eval.c @@ -23,8 +23,8 @@ main(int argc, char *argv[]) { char *input; struct aplwc *aplwc; - struct aplwc_line *line; - struct aplwc_value *value; + AplwcLine line; + AplwcValue value; struct aplwc_fns fns; enum aplwc_rc ret; FILE *f; @@ -56,7 +56,7 @@ main(int argc, char *argv[]) fns.alloc = my_alloc; fns.dealloc = my_dealloc; - ret = aplwc_new(&aplwc, fns); + aplwc = aplwc_new(fns, &ret); if(ret) return 1; @@ -66,11 +66,11 @@ main(int argc, char *argv[]) input[i] = 0; line = aplwc_read(aplwc, &input[j]); - if(line == NULL) + if(!aplwc_valid_line(line)) return 1; value = aplwc_eval(line); - if((value == NULL) && (aplwc_last_error(aplwc) != APLWC_OUT_OF_MEMORY)) + if((!aplwc_valid_value(value)) && (aplwc_last_error(aplwc) != APLWC_OUT_OF_MEMORY)) return 1; aplwc_free_value(value); diff --git a/tests/aplwc_read.c b/tests/aplwc_read.c index 42a47c2..d090494 100644 --- a/tests/aplwc_read.c +++ b/tests/aplwc_read.c @@ -24,7 +24,7 @@ main(int argc, char *argv[]) struct aplwc_fns fns; char *input; struct aplwc *aplwc; - struct aplwc_line *line; + AplwcLine line; enum aplwc_rc ret; FILE *f; long input_size; @@ -53,12 +53,12 @@ main(int argc, char *argv[]) return 1; input[input_size] = 0; - ret = aplwc_new(&aplwc, fns); + aplwc = aplwc_new(fns, &ret); if(ret) return 1; line = aplwc_read(aplwc, input); - if((line == NULL) && (aplwc_last_error(aplwc) != APLWC_OUT_OF_MEMORY)) + if((!aplwc_valid_line(line)) && (aplwc_last_error(aplwc) != APLWC_OUT_OF_MEMORY)) return 1; aplwc_free_line(line); aplwc_destroy(aplwc); diff --git a/tests/aplwc_utf8.c b/tests/aplwc_utf8.c index 4f9f2a4..367db5d 100644 --- a/tests/aplwc_utf8.c +++ b/tests/aplwc_utf8.c @@ -35,7 +35,7 @@ int main(void) { struct aplwc *aplwc; - struct aplwc_line *line; + AplwcLine line; struct aplwc_fns fns; enum aplwc_rc ret; size_t i; @@ -62,13 +62,13 @@ main(void) fns.alloc = my_alloc; fns.dealloc = my_dealloc; - ret = aplwc_new(&aplwc, fns); + aplwc = aplwc_new(fns, &ret); if(ret) return 1; for(i = 0; i < (sizeof(bad_tests)/sizeof(*bad_tests)); i++){ line = aplwc_read(aplwc, (char *)bad_tests[i]); - if(line != NULL) + if(aplwc_valid_line(line)) return 1; if(aplwc_last_error(aplwc) != APLWC_INVALID_UTF8) return 1; @@ -77,7 +77,7 @@ main(void) for(i = 0; i < (sizeof(good_tests)/sizeof(*good_tests)); i++){ line = aplwc_read(aplwc, (char *)good_tests[i]); - if((line == NULL) && (aplwc_last_error(aplwc) == APLWC_INVALID_UTF8)) + if((!aplwc_valid_line(line)) && (aplwc_last_error(aplwc) == APLWC_INVALID_UTF8)) return 1; aplwc_free_line(line); } |