diff --git a/implementations/C/Makefile b/implementations/C/Makefile index 6f3a6fc..5525702 100644 --- a/implementations/C/Makefile +++ b/implementations/C/Makefile @@ -1,24 +1,28 @@ OBJS=joy.o keywords.o + +# On FreeBSD gc and gmp are installed in /usr/local/: STATIC_GCLIB=/usr/local/lib/libgc.a /usr/local/lib/libgmp.a -CFLAGS = -ansi -Wall -Wextra -Werror -pedantic -Wstrict-overflow -fno-strict-aliasing -pedantic-errors -I/usr/local/include +# Hold my hand, in fact, hold both of them, and pat my head too please. +CFLAGS = -ansi -Wall -Wextra -Werror -pedantic -Wstrict-overflow -fno-strict-aliasing -pedantic-errors -#COPTS=-I/usr/local/include -# $(STATIC_GCLIB) +CFLAGS += -I/usr/local/include -GPERF_OPTS = --readonly-tables --enum --includes +# TODO: move these to KEYWORDS.txt. +GPERF_OPTS = --readonly-tables --enum --includes --hash-function-name=keyword_hash #--global-table joy: ${OBJS} $(STATIC_GCLIB) -# Gperf doesn't add anything to '{""}' unused entries in the worlist. +# Gperf doesn't add anything to '{""}' unused entries in the wordlist. # This causes "warning: missing field 'func' initializer [-Wmissing-field-initializers]" -# But we can turn off that warning for this here: +# which is promoted to an error and holds up the show. +# But we can turn off that warning for the keyword code like so: keywords.o: CFLAGS+=-Wno-missing-field-initializers keywords.c: KEYWORDS.txt - gperf --output-file=$@ --hash-function-name=keyword_hash $(GPERF_OPTS) KEYWORDS.txt + gperf --output-file=$@ $(GPERF_OPTS) $< clean: - rm -vf *.o + rm -vf *.o joy diff --git a/implementations/C/keywords.c b/implementations/C/keywords.c index af621da..9e887aa 100644 --- a/implementations/C/keywords.c +++ b/implementations/C/keywords.c @@ -1,5 +1,5 @@ /* ANSI-C code produced by gperf version 3.1 */ -/* Command-line: gperf --output-file=keywords.c --hash-function-name=keyword_hash --readonly-tables --enum --includes KEYWORDS.txt */ +/* Command-line: gperf --output-file=keywords.c --readonly-tables --enum --includes --hash-function-name=keyword_hash KEYWORDS.txt */ /* Computed positions: -k'1-2' */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ diff --git a/implementations/C/notes b/implementations/C/notes index 7b8cfb9..580c61d 100644 --- a/implementations/C/notes +++ b/implementations/C/notes @@ -1,208 +1,3 @@ - -// Example S-exprs -// https://www.hboehm.info/gc/04tutorial.pdf -/**/ -/*typedef union se*/ -/*{*/ -/* struct cons * cp;*/ -/* mpz_t i;*/ -/*} sexpr;*/ -/**/ -/*struct cons*/ -/*{*/ -/* union se head;*/ -/* union se tail;*/ -/*};*/ -/**/ -/*#define car(s) (s).cp->head*/ -/*#define cdr(s) (s).cp->tail*/ -/*#define from_i(z) ({sexpr tmp; tmp.i=z; tmp;})*/ -/*#define to_i(s) (s).i*/ -/**/ -/*sexpr cons(sexpr a, sexpr b) {*/ -/* sexpr tmp = {GC_MALLOC(sizeof(struct cons))};*/ -/* car(tmp) = a; cdr(tmp) = b;*/ -/* return (tmp);*/ -/*};*/ - - - -/*sexpr new_int(void) {*/ -/* sexpr node = {GC_MALLOC(sizeof(struct cons))};*/ -/* mpz_init(node.i);*/ -/* GC_register_finalizer(node.i, my_callback, NULL, NULL, NULL);*/ -/* return (node);*/ -/*}*/ - - -typedef struct list_node* JoyList; - - - - /*sexpr i = new_int();*/ - /*mpz_add(i.i, pi, pi);*/ - /*gmp_printf ("%Zd\n", i.i);*/ - /*return to_i(car(cons(from_i(0),from_i(1))));*/ - - /*gmp_printf("%Zd = %Zx\n", pi, pi);*/ - /*mpz_mul(pi, pi, pi);*/ - /*gmp_printf("%Zd = %Zx\n", pi, pi);*/ -' - - - - - - - - -/*=======================================================*/ -struct list_node* -text_to_expression(char *text) -{ - char *rest; - ptrdiff_t diff; - struct list_node *thing; - struct list_node *result; - struct list_node *tail = NULL; - struct list_node *stack[128]; - int s = 0; /* stack pointer */ - - /* NULL string input? */ - if (NULL == text) { - return EMPTY_LIST; - } - - text = trim_leading_blanks(text); - - /* All blanks? */ - if (NULL == text) { - return EMPTY_LIST; - } - - /* Look for blanks or brackets. */ - rest = strpbrk(text, " []"); - /* - rest now points to a space or '[' or ']' after a term, - -or- it is NULL if the rest of the string is a single term - with no spaces nor brackets. If that's the case then we're - done, and we can just return a list with one symbol in it. - */ - if (NULL == rest) { - return make_symbol_node(text, strlen(text)); - } - - /* How many chars have we got? */ - diff = rest - text; - - if (diff) { - thing = make_symbol_node(text, diff); - if (tail) { - tail->tail = thing; - } else { - /* There is no head now, so this must be the first - result, the head that we will eventually return. */ - result = thing; - } - tail = thing; - - } else if ('[' == rest[0]) { - rest++; - /* We need to parse a sub-list. */ - if (tail) { - /* We have already parsed some terms, set them aside. */ - stack[s++] = tail; - stack[s++] = result; - tail = (struct list_node *)NULL; - } else { - /* - This is going to be our first term when we're done parsing it. - Do nothing, empty stack will signal it. - */ - - } - } else if (']' == rest[0]) { - rest++; - if (s) { - /* We have a tail on the stack. */ - thing = result; - result = stack[--s]; - tail = stack[--s]; - tail->tail = thing; - } else { - /* This list must have been the first thing in the expr. */ - printf("wtf"); - exit(1); - } - } else { - - } - - result = make_symbol_node(text, diff); - - /* - This is the head of the list we are eventually going to return, - so we assign it to the result - We are going to be adding things to the tail of this list, so - we'll need to keep track of that - */ - tail = result; - - /* - Now we want to - */ - while (NULL != rest) { - - - if (head) { - head->tail = current_list_node; - } else { - /* There is no head now, so this must be the first - result, the head that we will eventually return. */ - result = current_list_node; - } - head = current_list_node; - } - - /* The next char is a space or '[' or ']'. */ - if ('[' == rest[0]) { - if (head) { - stack[s++] = head; - head = (struct list_node *)NULL; - } - /*printf("%c\n", rest[0]);*/ - } - - if (']' == rest[0]) { - current_list_node = make_list_node(stack[s--]); - if (head) { - head->tail = current_list_node; - } else { - /* There is no head now, so this must be the first - result, the head that we will eventually return. */ - result = current_list_node; - } - head = current_list_node; - /*printf("%c\n", rest[0]);*/ - } - - text = trim_leading_blanks(++rest); - - /* calling strpbrk on NULL caused segfault! */ - rest = (NULL != text) ? strpbrk(text, " []") : text; - } - if (text) { - current_list_node = make_symbol_node(text, strlen(text)); - if (head) { - head->tail = current_list_node; - } else { - result = current_list_node; - } - } - return result; -} -' - /*mpz_t pi;*/ /*char *text = (char *)TEXT;*/ /*mpz_init_set_str(pi, "3141592653589793238462643383279502884", 10);*/ @@ -214,8 +9,3 @@ text_to_expression(char *text) /*el = text_to_expression(text);*/ /*print_list(el);*/ /*printf("\n");*/ - - - /*const char *TEXT = " 23 [dup *] i hi there fr [[] ie]nd [] 23 ";*/ -/*const char *TEXT = " 23 33 [] ";*/ -const char *TEXT = "ok [wow] [23 45][1[2]3]simple terms already work eh? ";