summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile44
-rw-r--r--eval.c29
-rw-r--r--food.c (renamed from main.c)41
-rw-r--r--lib/include.rcp1
-rw-r--r--lib/pasta-red-sauce.rcp2
-rw-r--r--lib/simple_omelette.rcp2
-rw-r--r--src/eval.c21
-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
diff --git a/Makefile b/Makefile
index 82c9da1..3b011df 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/eval.c b/eval.c
deleted file mode 100644
index 12fe45c..0000000
--- a/eval.c
+++ /dev/null
@@ -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;
-}
-
diff --git a/main.c b/food.c
index 68de644..90ce489 100644
--- a/main.c
+++ b/food.c
@@ -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;
+}
+
diff --git a/eval.h b/src/eval.h
index 2d4f6a1..2d4f6a1 100644
--- a/eval.h
+++ b/src/eval.h
diff --git a/parser.c b/src/parser.c
index df8d80b..df8d80b 100644
--- a/parser.c
+++ b/src/parser.c
diff --git a/parser.h b/src/parser.h
index 3d704c3..2680da5 100644
--- a/parser.h
+++ b/src/parser.h
@@ -1,9 +1,6 @@
#ifndef __PARSER_H
#define __PARSER_H
-#include <stdio.h>
-#include <stdlib.h>
-
#include "types.h"
#define LINE_SIZE 4096
diff --git a/types.c b/src/types.c
index 091ff8d..d9253af 100644
--- a/types.c
+++ b/src/types.c
@@ -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);
+ }
+ }
+}
diff --git a/types.h b/src/types.h
index ea8fa47..0d870cf 100644
--- a/types.h
+++ b/src/types.h
@@ -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 */
diff --git a/util.c b/src/util.c
index 6eda622..6eda622 100644
--- a/util.c
+++ b/src/util.c
diff --git a/util.h b/src/util.h
index fe09145..fe09145 100644
--- a/util.h
+++ b/src/util.h