summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorpeter <peter@pmikkelsen.com>2026-08-31 19:44:56 +0000
committerpeter <peter@pmikkelsen.com>2026-08-31 19:44:56 +0000
commit7f7a2fb4fb23433e7be3d6953725690c8ea958d2 (patch)
treee73bc6f3bd9d5132a0262966cd99986027142144 /src
parent729964bea692f9683860978b89848784a7fc2f46 (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
Diffstat (limited to 'src')
-rw-r--r--src/bin/main.c37
-rw-r--r--src/include/aplwc.h26
-rw-r--r--src/lib/aplwc_internal.h13
-rw-r--r--src/lib/main.c107
-rw-r--r--src/lib/memory.c83
5 files changed, 210 insertions, 56 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;
+}