summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/emit.c27
-rw-r--r--core/parser.c116
-rw-r--r--head/defconf/emit.h23
3 files changed, 165 insertions, 1 deletions
diff --git a/core/emit.c b/core/emit.c
new file mode 100644
index 0000000..ec00ed2
--- /dev/null
+++ b/core/emit.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2026, Apollo Telephone Laboratories.
+ * Provided under the BSD-3 clause.
+ */
+
+#include <stdio.h>
+#include "defconf/emit.h"
+
+int
+emit_data(const char *ident, struct data_value *v)
+{
+ if (ident == NULL || v == NULL) {
+ return -1;
+ }
+
+ switch (v->type) {
+ case DATA_TYPE_INT:
+ printf("-D%s=%zu\n", ident, v->v);
+ return 0;
+ case DATA_TYPE_STR:
+ printf("-D%s=\"%s\"\n", ident, v->s);
+ return 0;
+ }
+
+ printf("fatal: got bad data value during emission\n");
+ return -1;
+}
diff --git a/core/parser.c b/core/parser.c
index 727d5e1..e568504 100644
--- a/core/parser.c
+++ b/core/parser.c
@@ -6,6 +6,8 @@
#include "defconf/parser.h"
#include "defconf/lexer.h"
#include "defconf/token.h"
+#include "defconf/data.h"
+#include "defconf/emit.h"
/* Symbolic token */
#define SYMTOK(TOKSTR) \
@@ -31,17 +33,129 @@ static const char *toktab[_TT_MAX] = {
[TT_IDENT] = SYMTOK("ident")
};
+static int
+token_to_data(struct token *tok, struct data_value *result)
+{
+ if (tok == NULL || result == NULL) {
+ return -1;
+ }
+
+ switch (tok->type) {
+ case TT_TRUE:
+ result->v = 1;
+ result->type = DATA_TYPE_INT;
+ return 0;
+ case TT_FALSE:
+ result->v = 0;
+ result->type = DATA_TYPE_INT;
+ return 0;
+ default:
+ return -1;
+ }
+
+ return -1;
+}
+
+/*
+ * Assert that the next token is of a specific type
+ *
+ * @state: Defconf state
+ * @tok: Last token
+ * @exp: Expected token
+ */
+static int
+parse_expect(struct defconf_state *state, struct token *tok, tt_t exp)
+{
+ int error;
+
+ if (state == NULL || tok == NULL) {
+ return -1;
+ }
+
+ /* Try to grab the next token */
+ if ((error = lexer_scan(state, tok)) < 0) {
+ printf("fatal: expected '%s', got eof\n", TOKSTR(exp));
+ return error;
+ }
+
+ if (tok->type != exp) {
+ printf("fatal: expected '%s', got %s instead\n",
+ TOKSTR(exp), TOKSTR(tok->type));
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Parse a define directive
+ *
+ * @state: Defconf state
+ * @tok: Last token
+ *
+ * Returns zero on success
+ */
+static int
+parse_define(struct defconf_state *state, struct token *tok)
+{
+ struct data_value value;
+ char *ident;
+ int error;
+
+ if (state == NULL || tok == NULL) {
+ return -1;
+ }
+
+ /* Expect an identifier */
+ if ((error = parse_expect(state, tok, TT_IDENT)) < 0) {
+ return error;
+ }
+
+ /* Save the identifier */
+ ident = tok->s;
+
+ /* Scan the value */
+ if ((error = lexer_scan(state, tok)) < 0) {
+ printf("fatal: expected value, got eof\n");
+ return error;
+ }
+
+ /* Convert token to data */
+ if ((error = token_to_data(tok, &value)) < 0) {
+ printf("fatal: got bad data [%s]\n", TOKSTR(tok->type));
+ return error;
+ }
+
+ /* Emit the define */
+ if ((error = emit_data(ident, &value)) < 0) {
+ return error;
+ }
+
+ return 0;
+}
+
int
parse_begin(struct defconf_state *state)
{
struct token tok;
+ int error;
if (state == NULL) {
return -1;
}
while (lexer_scan(state, &tok) == 0) {
- printf("got %s\n", TOKSTR(tok.type));
+ switch (tok.type) {
+ case TT_DEFINE:
+ if ((error = parse_define(state, &tok)) < 0) {
+ return error;
+ }
+
+ break;
+ default:
+ printf("fatal: got unexpected token: %s\n", TOKSTR(tok.type));
+ return -1;
+ }
}
return 0;
diff --git a/head/defconf/emit.h b/head/defconf/emit.h
new file mode 100644
index 0000000..a116074
--- /dev/null
+++ b/head/defconf/emit.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2026, Apollo Telephone Laboratories.
+ * Provided under the BSD-3 clause.
+ */
+
+#ifndef DEFCONF_EMIT_H
+#define DEFCONF_EMIT_H 1
+
+#include <stdint.h>
+#include <stddef.h>
+#include "defconf/data.h"
+
+/*
+ * Emit a data value
+ *
+ * @ident: Identifier of data value to emit
+ * @v: Value to emit
+ *
+ * Returns zero on success
+ */
+int emit_data(const char *ident, struct data_value *v);
+
+#endif /* !DEFCONF_EMIT_H */