diff options
-rw-r--r-- | Makefile | 44 | ||||
-rw-r--r-- | eval.c | 29 | ||||
-rw-r--r-- | food.c (renamed from main.c) | 41 | ||||
-rw-r--r-- | lib/include.rcp | 1 | ||||
-rw-r--r-- | lib/pasta-red-sauce.rcp | 2 | ||||
-rw-r--r-- | lib/simple_omelette.rcp | 2 | ||||
-rw-r--r-- | src/eval.c | 21 | ||||
-rw-r--r-- | src/eval.h (renamed from eval.h) | 0 | ||||
-rw-r--r-- | src/parser.c (renamed from parser.c) | 0 | ||||
-rw-r--r-- | src/parser.h (renamed from parser.h) | 3 | ||||
-rw-r--r-- | src/types.c (renamed from types.c) | 81 | ||||
-rw-r--r-- | src/types.h (renamed from types.h) | 22 | ||||
-rw-r--r-- | src/util.c (renamed from util.c) | 0 | ||||
-rw-r--r-- | src/util.h (renamed from util.h) | 0 |
14 files changed, 174 insertions, 72 deletions
@@ -1,33 +1,35 @@ -TARGET=food -SRC=*.c CC=gcc -CFLAGS=-D_GNU_SOURCE -std=c99 -pedantic -REL_FLAGS=-O3 -DBG_FLAGS=-Wall -g3 -make: $(SRC) - $(CC) $(REL_FLAGS) $(CFLAGS) -o $(TARGET) $^ $(LIBS) +CFLAGS=-D_GNU_SOURCE -std=c99 -pedantic -O3 +DBG_FLAGS=-Wall -g3 -D_FOOD_DEBUG -fsanitize=address -Og -debug: $(SRC) - $(CC) $(DBG_FLAGS) -D_FOOD_DEBUG -fsanitize=address $(CFLAGS) -o $(TARGET) $^ $(LIBS) +SRC=src/*.c -noasan: $(SRC) - $(CC) $(DBG_FLAGS) $(CFLAGS) -o $(TARGET) $^ $(LIBS) +.PHONY: all debug clean -tests: - $(MAKE) -C test +all: food #eval -clean-tests: - $(MAKE) clean -C test +food: $(SRC) food.c + $(CC) $(CFLAGS) -o food $^ $(LIBS) -.PHONY: clean +eval: $(SRC) eval.c + $(CC) $(CFLAGS) -o eval $^ $(LIBS) + +debug: CFLAGS += $(DBG_FLAGS) +debug: all clean: rm -f *.o - rm -f $(TARGET) + rm -f food eval + +# tests: +# $(MAKE) -C test + +# clean-tests: +# $(MAKE) clean -C test -install: $(TARGET) - @cp -v $(TARGET) /usr/local/bin/$(TARGET) +# install: $(TARGET) +# @cp -v $(TARGET) /usr/local/bin/$(TARGET) -uninstall: - @rm -v /usr/local/bin/$(TARGET) +# uninstall: +# @rm -v /usr/local/bin/$(TARGET) @@ -1,29 +0,0 @@ -#include "eval.h" -#include "util.h" - -static void -merge_items(recipe * dst, recipe * src) -{ - if (!dst || !src) return; - for (int i = 0; i < src->in; i++) { - new_item(dst); - dst->i[dst->in - 1]->name = strdup(src->i[i]->name); - dst->i[dst->in - 1]->qty = strdup(src->i[i]->qty); - } -} - -recipe * -eval(recipe * r) -{ - if (!r) return NULL; - recipe * eve = new_recipe(); - /* /\* Copy filename, title, etc *\/ */ - /* copy_metadata(eve, r); */ - /* attempt to merge items (adding qtys) */ - merge_items(eve, r); - /* /\* Resolve step type, variables, duration and step output (if any) *\/ */ - /* finalize_steps(eve, r); */ - - return r; -} - @@ -1,7 +1,8 @@ -#include "getopt.h" +#include <getopt.h> -#include "util.h" -#include "parser.h" +#include "src/util.h" +#include "src/parser.h" +#include "src/eval.h" recipe ** cookbook; @@ -10,12 +11,14 @@ static struct opts { int html; int rcp; char *query; + int list; int help; } opt = { .json = 0, .html = 0, .rcp = 0, .query = NULL, + .list = 0, .help = 0, }; @@ -28,6 +31,7 @@ print_help(char * argv0) { printf("-j json\n"); printf("-w html\n"); printf("-r rcp\n"); + printf("-l, --list-ingredients\n"); } int @@ -43,18 +47,19 @@ main(int argc, char * argv[]) /* <span class="roman">These options set a flag.</span> */ // {"verbose", no_argument, &verbose_flag, 1}, // {"brief", no_argument, &verbose_flag, 0}, - {"help", no_argument, 0, 'h'}, - {"to-json", no_argument, 0, 'j'}, - {"to-html", no_argument, 0, 'w'}, - {"to-rcp", no_argument, 0, 'r'}, - {"format", required_argument, 0, 'f'}, + {"help", no_argument, 0, 'h'}, + {"to-json", no_argument, 0, 'j'}, + {"to-html", no_argument, 0, 'w'}, + {"to-rcp", no_argument, 0, 'r'}, + {"format", required_argument, 0, 'f'}, + {"list-ingredients", no_argument, 0, 'l'}, // {"to-rcp", required_argument, 0, 'r'}, {0, 0, 0, 0} }; int option_index = 0; - c = getopt_long (argc, argv, "jhrwf:", + c = getopt_long (argc, argv, "jlhrwf:", long_options, &option_index); if (c == -1) @@ -88,6 +93,9 @@ main(int argc, char * argv[]) case 'r': opt.rcp = 1; break; + case 'l': + opt.list = 1; + break; case 'h': opt.help = 1; break; @@ -107,7 +115,14 @@ main(int argc, char * argv[]) if (optind < argc) { while (optind < argc) { recipe * r = parse(argv[optind++], NULL); - if (r) { + if (r && opt.list) { + /* recipe * r_merged = new_recipe(); */ + /* merge_items(r_merged, r); */ + recipe * r_merged = eval(r); + pprint_items(r_merged); + free_recipe(r_merged); + } + else if (r) { if (opt.json) tojson(r); if (opt.html) tohtml(r); if (opt.rcp) torcp(r); @@ -120,9 +135,3 @@ main(int argc, char * argv[]) return 0; } - - - - - - diff --git a/lib/include.rcp b/lib/include.rcp index b4b2814..e7c6954 100644 --- a/lib/include.rcp +++ b/lib/include.rcp @@ -2,3 +2,4 @@ poops = 5 crouches = 2 +#!simple_omelette.rcp
\ No newline at end of file diff --git a/lib/pasta-red-sauce.rcp b/lib/pasta-red-sauce.rcp index bef84c1..8b98626 100644 --- a/lib/pasta-red-sauce.rcp +++ b/lib/pasta-red-sauce.rcp @@ -1,6 +1,6 @@ @pasta with red sauce
-2!pa sta.rcp
+3!pasta.rcp
salt = *
sugar = 1 teaspoon
onion, garlic = 1
diff --git a/lib/simple_omelette.rcp b/lib/simple_omelette.rcp index c867e47..f278e1c 100644 --- a/lib/simple_omelette.rcp +++ b/lib/simple_omelette.rcp @@ -7,7 +7,7 @@ # 1b. local path # 2. default library path # !pasta.rcp = 3 -!~/code/food_compiler/lib/include.rcp +# !~/code/food_compiler/lib/include.rcp eggs = 3 milk = 2tbsp salt, pepper = * diff --git a/src/eval.c b/src/eval.c new file mode 100644 index 0000000..a26cc21 --- /dev/null +++ b/src/eval.c @@ -0,0 +1,21 @@ +#include "eval.h" +#include "util.h" + +recipe * +eval(recipe * r) +{ + if (!r) return NULL; + recipe * r1 = new_recipe(); + recipe * r2 = new_recipe(); + /* attempt to merge items (adding qtys) */ + merge_items(r1, r); + distinct_sum_items(r2, r1); + free_recipe(r1); + + copy_metadata(r2, r); + /* /\* Resolve step type, variables, duration and step output (if any) *\/ */ + /* finalize_steps(eve, r); */ + + return r2; +} + @@ -1,9 +1,6 @@ #ifndef __PARSER_H #define __PARSER_H -#include <stdio.h> -#include <stdlib.h> - #include "types.h" #define LINE_SIZE 4096 @@ -128,6 +128,15 @@ free_recipe(recipe * r) } void +pprint_items(recipe * r) +{ + printf("Ingredients for %s:\n", r->title); + for (int i = 0; i < r->in; i++) + printf("%s: %s\n", r->i[i]->name, r->i[i]->qty); + printf("\n"); +} + +void show(recipe * r) { printf("Filename\t%s\n", r->filename); @@ -208,7 +217,17 @@ torcp(recipe * r) } } -void copy_items(recipe * dst, recipe * src) +void +copy_metadata(recipe * dst, recipe * src) +{ + if (!dst || !src) return; + dst->filename = strdup(src->filename); + dst->path = strdup(src->path); + dst->title = strdup(src->title); +} + +void +copy_items(recipe * dst, recipe * src) { if (!dst || !src) return; for (int i = 0; i < src->in; i++) { @@ -218,3 +237,63 @@ void copy_items(recipe * dst, recipe * src) } } +static void +join_subrecipe_items(recipe * dst, recipe * src) +{ + if (!src || !dst) return; + for (int i = 0; i < src->rn; i++) { + join_subrecipe_items(dst, src->r[i]); + for (int j = 0; j < src->r[i]->in; j++) { + new_item(dst); + dst->i[dst->in - 1]->name = strdup(src->r[i]->i[j]->name); + if (src->r[i]->n > 1) { + char tmp[2048] = ""; + sprintf(tmp, "%d X ( %s )", src->r[i]->n, src->r[i]->i[j]->qty); + dst->i[dst->in - 1]->qty = strdup(tmp); + } + else { + dst->i[dst->in - 1]->qty = strdup(src->r[i]->i[j]->qty); + } + } + } +} + +void +merge_items(recipe * dst, recipe * src) +{ + /* Join all items in src's subrecipes to dst */ + join_subrecipe_items(dst, src); + /* Copy src items as well to dst */ + copy_items(dst, src); +} + +static int +item_exists(const char * name, const recipe * r) +{ + for (int i = 0; i < r->in; i++) + if (!strcmp(r->i[i]->name, name)) + return i; + return -1; +} + +void +distinct_sum_items(recipe * dst, recipe * src) +{ + if (!dst || !src) return; + for (int i = 0; i < src->in; i++) { + int n = item_exists(src->i[i]->name, dst); + if (n != -1) { + char tmp[2048] = ""; + strcat(tmp, dst->i[n]->qty); + strcat(tmp, " + "); + strcat(tmp, src->i[i]->qty); + free(dst->i[n]->qty); + dst->i[n]->qty = strdup(tmp); + } + else { + new_item(dst); + dst->i[dst->in - 1]->name = strdup(src->i[i]->name); + dst->i[dst->in - 1]->qty = strdup(src->i[i]->qty); + } + } +} @@ -41,11 +41,33 @@ void free_recipe(recipe * r); void free_item(item * i); void free_step(step * s); +void pprint_items(recipe * r); void show(recipe * r); void tojson(recipe * r); void tohtml(recipe * r); void torcp(recipe * r); +/* Operations */ + +/** + * Copy metadata from `src` to `dst` + */ +void copy_metadata(recipe * dst, recipe * src); + +/** + * Copy top level items from `src` to `dst` + */ void copy_items(recipe * dst, recipe * src); +/** + * Merge all items from `src` and add them to `dst` + */ +void merge_items(recipe * dst, recipe * src); + +/** + * Sum all top level item qtys in `src` and add them to `dst` + * making sure each item name exists only once. + */ +void distinct_sum_items(recipe * dst, recipe * src); + #endif /* __TYPES_H */ |