Commit 66560887 authored by Joel K. Pettersson's avatar Joel K. Pettersson
Browse files

Refactor parser. Rename 'test-builder' to 'test-scan'.

Preparation for further parser redesign:
Change parser node list type, begin moving
fields to new op ref type, simplify memory
management. No functional change.
 * Simplify memory handling by using the mempool
   for all parse data node allocation. Freeing
   becomes trivial. Also include the symtab in
   the produced parse (since it depends on the
   mempool), which may suit future needs.
 * Add new op ref type, op list wrapper type.
   Use instead of ptrlist in parser;
   the parseconv output is the same.
 * Move label from op data node to op ref node.
   Also fix bug in handling of deferred step,
   which caused crash now but didn't before.
 * Move link_type from op data node to op ref node.
   Also rearrange code to silence old warning about
   possible variable use before assignment.

Rename 'test-builder' to 'test-scan',
now built with `make tests`.

Minor correctness improvement in parseconv.

Return failure instead of success count in SAU_build().

Increase version to v0.3.4b.

Clean up .gitignore.

Change log:
 * 2019-11-11: Set version to v0.3.4-beta.
 * 2019-11-12: Change SAU_build() return value.
 * 2019-11-28: Rename 'test-builder' to 'test-scan',
       and remove old program names from .gitignore.
 * 2019-12-01: For parser, use new op ref type,
       op list wrapper type, instead of ptrlist.
 * 2019-12-02: Move label and link_type fields
       to op ref type, and refactoring.
       Set version to v0.3.4.
 * 2019-12-03: Use mempool in parser
       for all parse result allocation.
       Increase version suffix to 'b'.
parent 660add66
......@@ -2,10 +2,8 @@
.*.swp
*.o
mgensys
sgensys
saugns
test-builder
test-scan
*.[ch][-.]*
backup/
......@@ -31,7 +31,7 @@ OBJ=\
audiodev.o \
wavfile.o \
saugns.o
TEST_OBJ=\
TEST1_OBJ=\
common.o \
arrtype.o \
ptrlist.o \
......@@ -41,13 +41,13 @@ TEST_OBJ=\
builder/lexer.o \
builder/scriptconv.o \
mempool.o \
test-builder.o
test-scan.o
all: $(BIN)
test: test-builder
tests: test-scan
clean:
rm -f $(OBJ) $(BIN)
rm -f $(TEST_OBJ) test-builder
rm -f $(TEST1_OBJ) test-scan
install: $(BIN)
@if [ -d "$(DESTDIR)$(PREFIX)/man" ]; then \
MANDIR="man"; \
......@@ -91,8 +91,8 @@ $(BIN): $(OBJ)
$(CC) $(OBJ) $(LFLAGS) -o $(BIN); \
fi
test-builder: $(TEST_OBJ)
$(CC) $(TEST_OBJ) $(LFLAGS) -o test-builder
test-scan: $(TEST1_OBJ)
$(CC) $(TEST1_OBJ) $(LFLAGS) -o test-scan
arrtype.o: arrtype.c arrtype.h common.h
$(CC) -c $(CFLAGS) arrtype.c
......@@ -109,16 +109,16 @@ builder.o: builder.c saugns.h script.h ptrlist.h program.h ramp.h wave.h math.h
builder/file.o: builder/file.c builder/file.h common.h
$(CC) -c $(CFLAGS) builder/file.c -o builder/file.o
builder/lexer.o: builder/lexer.c builder/lexer.h builder/file.h builder/symtab.h builder/scanner.h math.h common.h
builder/lexer.o: builder/lexer.c builder/lexer.h builder/file.h builder/symtab.h mempool.h builder/scanner.h math.h common.h
$(CC) -c $(CFLAGS) builder/lexer.c -o builder/lexer.o
builder/parseconv.o: builder/parseconv.c builder/parser.h program.h ramp.h wave.h math.h script.h ptrlist.h common.h
$(CC) -c $(CFLAGS) builder/parseconv.c -o builder/parseconv.o
builder/parser.o: builder/parser.c builder/parser.h builder/scanner.h builder/file.h builder/symtab.h script.h ptrlist.h program.h ramp.h wave.h math.h common.h
builder/parser.o: builder/parser.c builder/parser.h builder/scanner.h builder/file.h builder/symtab.h mempool.h script.h ptrlist.h program.h ramp.h wave.h math.h common.h
$(CC) -c $(CFLAGS) builder/parser.c -o builder/parser.o
builder/scanner.o: builder/scanner.c builder/scanner.h builder/file.h builder/symtab.h math.h common.h
builder/scanner.o: builder/scanner.c builder/scanner.h builder/file.h builder/symtab.h mempool.h math.h common.h
$(CC) -c $(CFLAGS) builder/scanner.c -o builder/scanner.o
builder/scriptconv.o: builder/scriptconv.c program.h ramp.h wave.h math.h script.h ptrlist.h arrtype.h common.h
......@@ -151,8 +151,8 @@ renderer/osc.o: renderer/osc.c renderer/osc.h wave.h math.h common.h
saugns.o: saugns.c saugns.h ptrlist.h program.h ramp.h wave.h math.h common.h
$(CC) -c $(CFLAGS) saugns.c
test-builder.o: test-builder.c saugns.h builder/lexer.h builder/scanner.h builder/file.h builder/symtab.h ptrlist.h program.h ramp.h wave.h math.h common.h
$(CC) -c $(CFLAGS) test-builder.c
test-scan.o: test-scan.c saugns.h builder/lexer.h builder/scanner.h builder/file.h builder/symtab.h mempool.h ptrlist.h program.h ramp.h wave.h math.h common.h
$(CC) -c $(CFLAGS) test-scan.c
wave.o: wave.c wave.h math.h common.h
$(CC) -c $(CFLAGS_FAST) wave.c
......
......@@ -34,18 +34,19 @@ static SAU_Program *build_program(const char *restrict script_arg,
/**
* Build the listed scripts, adding each result (even if NULL)
* to the program list.
* to the program list. (NULL scripts are ignored.)
*
* \return number of programs successfully built
* \return number of failures for non-NULL scripts
*/
size_t SAU_build(const SAU_PtrList *restrict script_args, bool are_paths,
SAU_PtrList *restrict prg_objs) {
size_t built = 0;
size_t fails = 0;
const char **args = (const char**) SAU_PtrList_ITEMS(script_args);
for (size_t i = 0; i < script_args->count; ++i) {
if (!args[i]) continue;
SAU_Program *prg = build_program(args[i], are_paths);
if (prg != NULL) ++built;
if (!prg) ++fails;
SAU_PtrList_add(prg_objs, prg);
}
return built;
return fails;
}
......@@ -29,15 +29,13 @@
*/
static void group_events(SAU_ParseEvData *restrict to) {
SAU_ParseEvData *e, *e_after = to->next;
size_t i;
uint32_t wait = 0, waitcount = 0;
for (e = to->groupfrom; e != e_after; ) {
SAU_ParseOpData **ops;
ops = (SAU_ParseOpData**) SAU_PtrList_ITEMS(&e->operators);
for (i = 0; i < e->operators.count; ++i) {
SAU_ParseOpData *op = ops[i];
SAU_ParseOpRef *op_ref = e->op_list.refs;
for (; op_ref != NULL; op_ref = op_ref->next) {
SAU_ParseOpData *op = op_ref->data;
if (e->next == e_after &&
i == (e->operators.count - 1) && (op->op_flags & SAU_SDOP_TIME_DEFAULT) != 0) {
op_ref == e->op_list.last_ref && (op->op_flags & SAU_SDOP_TIME_DEFAULT) != 0) {
/* default for last node in group */
op->op_flags &= ~SAU_SDOP_TIME_DEFAULT;
}
......@@ -51,10 +49,9 @@ i == (e->operators.count - 1) && (op->op_flags & SAU_SDOP_TIME_DEFAULT) != 0) {
}
}
for (e = to->groupfrom; e != e_after; ) {
SAU_ParseOpData **ops;
ops = (SAU_ParseOpData**) SAU_PtrList_ITEMS(&e->operators);
for (i = 0; i < e->operators.count; ++i) {
SAU_ParseOpData *op = ops[i];
SAU_ParseOpRef *op_ref = e->op_list.refs;
for (; op_ref != NULL; op_ref = op_ref->next) {
SAU_ParseOpData *op = op_ref->data;
if ((op->op_flags & SAU_SDOP_TIME_DEFAULT) != 0) {
/* fill in sensible default time */
op->op_flags &= ~SAU_SDOP_TIME_DEFAULT;
......@@ -71,6 +68,12 @@ i == (e->operators.count - 1) && (op->op_flags & SAU_SDOP_TIME_DEFAULT) != 0) {
e_after->wait_ms += wait;
}
static void op_list_fornew(SAU_ParseOpList *restrict ol,
void (*on_op)(SAU_ParseOpData *restrict data)) {
SAU_ParseOpRef *op_ref = ol->new_refs;
for (; op_ref != NULL; op_ref = op_ref->next) on_op(op_ref->data);
}
static void time_operator(SAU_ParseOpData *restrict op) {
SAU_ParseEvData *e = op->event;
if (op->freq.time_ms == SAU_TIME_DEFAULT)
......@@ -92,20 +95,9 @@ static void time_operator(SAU_ParseOpData *restrict op) {
((SAU_ParseEvData*)e->next)->wait_ms += op->time_ms;
e->ev_flags &= ~SAU_SDEV_ADD_WAIT_DURATION;
}
size_t i;
SAU_ParseOpData **ops;
ops = (SAU_ParseOpData**) SAU_PtrList_ITEMS(&op->fmods);
for (i = op->fmods.old_count; i < op->fmods.count; ++i) {
time_operator(ops[i]);
}
ops = (SAU_ParseOpData**) SAU_PtrList_ITEMS(&op->pmods);
for (i = op->pmods.old_count; i < op->pmods.count; ++i) {
time_operator(ops[i]);
}
ops = (SAU_ParseOpData**) SAU_PtrList_ITEMS(&op->amods);
for (i = op->amods.old_count; i < op->amods.count; ++i) {
time_operator(ops[i]);
}
op_list_fornew(&op->fmod_list, time_operator);
op_list_fornew(&op->pmod_list, time_operator);
op_list_fornew(&op->amod_list, time_operator);
}
static void time_event(SAU_ParseEvData *restrict e) {
......@@ -115,19 +107,14 @@ static void time_event(SAU_ParseEvData *restrict e) {
*/
if (e->pan.time_ms == SAU_TIME_DEFAULT)
e->pan.time_ms = 1000; /* FIXME! */
size_t i;
SAU_ParseOpData **ops;
ops = (SAU_ParseOpData**) SAU_PtrList_ITEMS(&e->operators);
for (i = e->operators.old_count; i < e->operators.count; ++i) {
time_operator(ops[i]);
}
op_list_fornew(&e->op_list, time_operator);
/*
* Timing for composites - done before event list flattened.
*/
if (e->composite != NULL) {
SAU_ParseEvData *ce = e->composite;
SAU_ParseOpData *ce_op, *ce_op_prev, *e_op;
ce_op = (SAU_ParseOpData*) SAU_PtrList_GET(&ce->operators, 0);
ce_op = ce->op_list.refs->data;
ce_op_prev = ce_op->op_prev;
e_op = ce_op_prev;
if ((e_op->op_flags & SAU_SDOP_TIME_DEFAULT) != 0)
......@@ -151,8 +138,7 @@ static void time_event(SAU_ParseEvData *restrict e) {
ce_op_prev = ce_op;
ce = ce->next;
if (!ce) break;
ce_op = (SAU_ParseOpData*)
SAU_PtrList_GET(&ce->operators, 0);
ce_op = ce->op_list.refs->data;
}
}
}
......@@ -225,7 +211,8 @@ typedef struct ParseConv {
* adding it to the list to be used for the current program event.
*/
static bool ParseConv_add_opdata(ParseConv *restrict o,
SAU_ParseOpData *restrict pod) {
SAU_ParseOpRef *restrict pod_ref) {
SAU_ParseOpData *pod = pod_ref->data;
SAU_ScriptOpData *od = calloc(1, sizeof(SAU_ScriptOpData));
if (!od)
return false;
......@@ -233,13 +220,12 @@ static bool ParseConv_add_opdata(ParseConv *restrict o,
pod->op_conv = od;
od->event = e;
/* next_bound */
/* label */
od->op_flags = pod->op_flags;
od->op_params = pod->op_params;
od->time_ms = pod->time_ms;
od->silence_ms = pod->silence_ms;
od->wave = pod->wave;
if (pod->link_type == SAU_PDNL_GRAPH) {
if (pod_ref->link_type == SAU_PDNL_GRAPH) {
e->ev_flags |= SAU_SDEV_NEW_OPGRAPH;
od->op_flags |= SAU_SDOP_NEW_CARRIER;
}
......@@ -250,9 +236,9 @@ static bool ParseConv_add_opdata(ParseConv *restrict o,
od->phase = pod->phase;
if (pod->op_prev != NULL) od->op_prev = pod->op_prev->op_conv;
/* op_next */
/* fmods */
/* pmods */
/* amods */
/* fmod_list */
/* pmod_list */
/* amod_list */
if (!SAU_PtrList_add(&o->ev->op_all, od)) goto ERROR;
return true;
......@@ -266,17 +252,16 @@ ERROR:
* visiting new operator nodes as they branch out.
*/
static bool ParseConv_add_ops(ParseConv *restrict o,
const SAU_PtrList *restrict pod_list) {
SAU_ParseOpData **pods;
pods = (SAU_ParseOpData**) SAU_PtrList_ITEMS(pod_list);
for (size_t i = pod_list->old_count; i < pod_list->count; ++i) {
SAU_ParseOpData *pod = pods[i];
const SAU_ParseOpList *restrict pod_list) {
SAU_ParseOpRef *pod_ref = pod_list->new_refs;
for (; pod_ref != NULL; pod_ref = pod_ref->next) {
SAU_ParseOpData *pod = pod_ref->data;
// TODO: handle multiple operator nodes
//if (pod->op_flags & SAU_SDOP_MULTIPLE) continue;
if (!ParseConv_add_opdata(o, pod)) goto ERROR;
if (!ParseConv_add_ops(o, &pod->fmods)) goto ERROR;
if (!ParseConv_add_ops(o, &pod->pmods)) goto ERROR;
if (!ParseConv_add_ops(o, &pod->amods)) goto ERROR;
if (!ParseConv_add_opdata(o, pod_ref)) goto ERROR;
if (!ParseConv_add_ops(o, &pod->fmod_list)) goto ERROR;
if (!ParseConv_add_ops(o, &pod->pmod_list)) goto ERROR;
if (!ParseConv_add_ops(o, &pod->amod_list)) goto ERROR;
}
return true;
......@@ -290,11 +275,10 @@ ERROR:
*/
static bool ParseConv_link_ops(ParseConv *restrict o,
SAU_PtrList *restrict od_list,
const SAU_PtrList *restrict pod_list) {
SAU_ParseOpData **pods;
pods = (SAU_ParseOpData**) SAU_PtrList_ITEMS(pod_list);
for (size_t i = 0; i < pod_list->count; ++i) {
SAU_ParseOpData *pod = pods[i];
const SAU_ParseOpList *restrict pod_list) {
SAU_ParseOpRef *pod_ref = pod_list->refs;
for (; pod_ref != NULL; pod_ref = pod_ref->next) {
SAU_ParseOpData *pod = pod_ref->data;
// TODO: handle multiple operator nodes
//if (pod->op_flags & SAU_SDOP_MULTIPLE) continue;
SAU_ScriptOpData *od = pod->op_conv;
......@@ -302,17 +286,19 @@ static bool ParseConv_link_ops(ParseConv *restrict o,
SAU_ScriptEvData *e = od->event;
if (e->ev_flags & SAU_SDEV_NEW_OPGRAPH) {
// Handle linking for carriers separately
if (od->op_flags & SAU_SDOP_NEW_CARRIER)
SAU_PtrList_add(&e->op_graph, od);
if ((od->op_flags & SAU_SDOP_NEW_CARRIER) != 0
&& !SAU_PtrList_add(&e->op_graph, od))
goto ERROR;
}
if (od_list != NULL) SAU_PtrList_add(od_list, od);
if (od_list != NULL && !SAU_PtrList_add(od_list, od))
goto ERROR;
if (od->op_params & SAU_POPP_ADJCS) {
if (!ParseConv_link_ops(o,
&od->fmods, &pod->fmods)) goto ERROR;
if (!ParseConv_link_ops(o,
&od->pmods, &pod->pmods)) goto ERROR;
if (!ParseConv_link_ops(o,
&od->amods, &pod->amods)) goto ERROR;
if (!ParseConv_link_ops(o, &od->fmods,
&pod->fmod_list)) goto ERROR;
if (!ParseConv_link_ops(o, &od->pmods,
&pod->pmod_list)) goto ERROR;
if (!ParseConv_link_ops(o, &od->amods,
&pod->amod_list)) goto ERROR;
}
}
return true;
......@@ -349,8 +335,8 @@ static bool ParseConv_add_event(ParseConv *restrict o,
e->ev_flags |= SAU_SDEV_NEW_OPGRAPH;
}
e->pan = pe->pan;
if (!ParseConv_add_ops(o, &pe->operators)) goto ERROR;
if (!ParseConv_link_ops(o, NULL, &pe->operators)) goto ERROR;
if (!ParseConv_add_ops(o, &pe->op_list)) goto ERROR;
if (!ParseConv_link_ops(o, NULL, &pe->op_list)) goto ERROR;
return true;
ERROR:
......
......@@ -16,7 +16,6 @@
#include "parser.h"
#include "../math.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
/*
......@@ -451,32 +450,46 @@ typedef struct SAU_Parser {
ScanLookup sl;
SAU_Scanner *sc;
SAU_SymTab *st;
SAU_MemPool *mp;
uint32_t call_level;
/* node state */
SAU_ParseEvData *ev, *first_ev;
} SAU_Parser;
/*
* Finalize parser instance.
*/
static void fini_Parser(SAU_Parser *restrict o) {
SAU_destroy_Scanner(o->sc);
SAU_destroy_SymTab(o->st);
SAU_destroy_MemPool(o->mp);
}
/*
* Initialize parser instance.
*
* The same symbol table and script-set data will be used
* until the instance is finalized.
*
* \return true, or false on allocation failure
*/
static void init_Parser(SAU_Parser *restrict o) {
static bool init_Parser(SAU_Parser *restrict o) {
SAU_MemPool *mp = SAU_create_MemPool(0);
SAU_SymTab *st = SAU_create_SymTab(mp);
SAU_Scanner *sc = SAU_create_Scanner(st);
*o = (SAU_Parser){0};
o->st = SAU_create_SymTab();
init_ScanLookup(&o->sl, o->st);
o->sc = SAU_create_Scanner(o->st);
o->sc->filters['#'] = scan_filter_hashcommands;
o->sc->data = &o->sl;
}
o->sc = sc;
o->st = st;
o->mp = mp;
if (!sc || !st || !mp) goto ERROR;
if (!init_ScanLookup(&o->sl, st)) goto ERROR;
sc->filters['#'] = scan_filter_hashcommands;
sc->data = &o->sl;
return true;
/*
* Finalize parser instance.
*/
static void fini_Parser(SAU_Parser *restrict o) {
SAU_destroy_Scanner(o->sc);
SAU_destroy_SymTab(o->st);
ERROR:
fini_Parser(o);
return false;
}
/*
......@@ -518,8 +531,9 @@ typedef struct ParseLevel {
uint8_t location;
uint8_t scope;
SAU_ParseEvData *event, *last_event;
SAU_ParseOpData *operator, *first_operator, *last_operator;
SAU_ParseOpData *parent_op, *op_prev;
SAU_ParseOpRef *op_ref, *parent_op_ref;
SAU_ParseOpRef *prev_op_ref, *first_op_ref;
SAU_ParseOpData *last_op;
uint8_t last_link_type; /* FIXME: kludge */
const char *set_label; /* label assigned to next node */
/* timing/delay */
......@@ -533,7 +547,7 @@ static bool parse_waittime(ParseLevel *restrict pl) {
SAU_Scanner *sc = o->sc;
/* FIXME: ADD_WAIT_DURATION */
if (SAU_Scanner_tryc(sc, 't')) {
if (!pl->last_operator) {
if (!pl->last_op) {
SAU_Scanner_warning(sc, NULL,
"add wait for last duration before any parts given");
return false;
......@@ -553,49 +567,47 @@ static bool parse_waittime(ParseLevel *restrict pl) {
*/
/*
* Destroy the given operator data node.
* Clear list entries without freeing memory.
*
* The nodes and associated data remain in
* the mempool instance used to allocate them.
*/
static void destroy_operator(SAU_ParseOpData *restrict op) {
size_t i;
SAU_ParseOpData **ops;
ops = (SAU_ParseOpData**) SAU_PtrList_ITEMS(&op->fmods);
for (i = op->fmods.old_count; i < op->fmods.count; ++i) {
destroy_operator(ops[i]);
}
SAU_PtrList_clear(&op->fmods);
ops = (SAU_ParseOpData**) SAU_PtrList_ITEMS(&op->pmods);
for (i = op->pmods.old_count; i < op->pmods.count; ++i) {
destroy_operator(ops[i]);
}
SAU_PtrList_clear(&op->pmods);
ops = (SAU_ParseOpData**) SAU_PtrList_ITEMS(&op->amods);
for (i = op->amods.old_count; i < op->amods.count; ++i) {
destroy_operator(ops[i]);
}
SAU_PtrList_clear(&op->amods);
free(op);
static void clear_op_list(SAU_ParseOpList *restrict ol) {
ol->refs = NULL;
ol->new_refs = NULL;
ol->last_ref = NULL;
}
/*
* Destroy the given event data node and all associated operator data nodes.
*/
static void destroy_event_node(SAU_ParseEvData *restrict e) {
size_t i;
SAU_ParseOpData **ops;
ops = (SAU_ParseOpData**) SAU_PtrList_ITEMS(&e->operators);
for (i = e->operators.old_count; i < e->operators.count; ++i) {
destroy_operator(ops[i]);
}
SAU_PtrList_clear(&e->operators);
free(e);
static void copy_op_list(SAU_ParseOpList *restrict ol,
const SAU_ParseOpList *restrict src_ol) {
ol->refs = src_ol->refs;
ol->new_refs = NULL;
ol->last_ref = NULL;
}
static SAU_ParseOpRef *op_list_add(SAU_ParseOpList *restrict ol,
SAU_ParseOpData *restrict data,
SAU_MemPool *restrict memp) {
SAU_ParseOpRef *ref = SAU_MemPool_alloc(memp, sizeof(SAU_ParseOpRef));
if (!ref)
return NULL;
ref->data = data;
if (!ol->refs)
ol->refs = ref;
if (!ol->new_refs)
ol->new_refs = ref;
else
ol->last_ref->next = ref;
ol->last_ref = ref;
return ref;
}
static void end_operator(ParseLevel *restrict pl) {
if (!pl->op_ref)
return;
SAU_Parser *o = pl->o;
ScanLookup *sl = &o->sl;
SAU_ParseOpData *op = pl->operator;
if (!op)
return; /* nothing to do */
SAU_ParseOpData *op = pl->op_ref->data;
if (SAU_Ramp_ENABLED(&op->freq))
op->op_params |= SAU_POPP_FREQ;
if (SAU_Ramp_ENABLED(&op->freq2))
......@@ -632,8 +644,8 @@ static void end_operator(ParseLevel *restrict pl) {
op->op_params |= SAU_POPP_SILENCE;
/* SAU_PHASE set when phase set */
}
pl->operator = NULL;
pl->last_operator = op;
pl->op_ref = NULL;
pl->last_op = op;
}
static void end_event(ParseLevel *restrict pl) {
......@@ -654,20 +666,25 @@ static void end_event(ParseLevel *restrict pl) {
pl->event = NULL;
}
static void begin_event(ParseLevel *restrict pl, uint8_t link_type,
bool is_composite) {
static void begin_event(ParseLevel *restrict pl, bool is_composite) {
SAU_Parser *o = pl->o;
SAU_ParseEvData *e, *pve;
end_event(pl);
pl->event = calloc(1, sizeof(SAU_ParseEvData));
e = pl->event;
SAU_ParseEvData *e = SAU_MemPool_alloc(o->mp, sizeof(SAU_ParseEvData));
pl->event = e;
e->wait_ms = pl->next_wait_ms;
pl->next_wait_ms = 0;
SAU_Ramp_reset(&e->pan);
if (pl->op_prev != NULL) {
pve = pl->op_prev->event;
if (pl->prev_op_ref != NULL) {
SAU_ParseEvData *pve = pl->prev_op_ref->data->event;
pve->ev_flags |= SAU_SDEV_VOICE_LATER_USED;
if (pve->composite != NULL && !is_composite) {
if (is_composite) {
if (!pl->composite) {
pve->composite = e;
pl->composite = pve;
} else {
pve->next = e;
}
} else if (pve->composite != NULL) {
SAU_ParseEvData *last_ce = pve->composite;
while (last_ce->next != NULL)
last_ce = last_ce->next;
......@@ -683,14 +700,7 @@ static void begin_event(ParseLevel *restrict pl, uint8_t link_type,
}
if (!pl->group_from)
pl->group_from = e;
if (is_composite) {
if (!pl->composite) {
pve->composite = e;
pl->composite = pve;
} else {
pve->next = e;
}
} else {
if (!is_composite) {
if (!o->first_ev)
o->first_ev = e;
else
......@@ -705,26 +715,48 @@ static void begin_event(ParseLevel *restrict pl, uint8_t link_type,
* event or for a new event begun.
*/
static void begin_operator(ParseLevel *restrict pl,
SAU_ParseOpData *restrict previous,
SAU_ParseOpRef *restrict prev_op_ref,
uint8_t link_type, bool is_composite) {
SAU_Parser *o = pl->o;
ScanLookup *sl = &o->sl;
pl->op_prev = previous;
SAU_ParseOpData *pop = pl->op_prev;
pl->prev_op_ref = prev_op_ref;
if (!pl->event || /* not in event means previous implicitly ended */
pl->location != SDPL_IN_EVENT ||
pl->next_wait_ms ||
is_composite)
begin_event(pl, link_type, is_composite);
begin_event(pl, is_composite);
SAU_ParseEvData *e = pl->event;
end_operator(pl);
pl->operator = calloc(1, sizeof(SAU_ParseOpData));
SAU_ParseOpData *op = pl->operator;
if (!pl->first_operator)
pl->first_operator = op;
if (!is_composite && pl->last_operator != NULL)
pl->last_operator->next_bound = op;
op->link_type = link_type;
SAU_ParseOpData *op = SAU_MemPool_alloc(o->mp, sizeof(SAU_ParseOpData));
if (!is_composite && pl->last_op != NULL)
pl->last_op->next_bound = op;
/*
* Add new operator to parent(s), ie. either to the
* current event node, or to an operator node (ordinary or multiple)
* in the case of operator linking/nesting.
*/
SAU_ParseOpList *ol;
switch (link_type) {
case SAU_PDNL_FMODS:
ol = &pl->parent_op_ref->data->fmod_list;
break;
case SAU_PDNL_PMODS:
ol = &pl->parent_op_ref->data->pmod_list;
break;
case SAU_PDNL_AMODS:
ol = &pl->parent_op_ref->data->amod_list;
break;
default:
ol = &e->op_list;
break;
}
SAU_ParseOpRef *ref = op_list_add(ol, op, o->mp);
if (ol != &e->op_list)
pl->parent_op_ref->data->op_params |= SAU_POPP_ADJCS;
pl->op_ref = ref;
if (!pl->first_op_ref)
pl->first_op_ref = ref;
ref->link_type = link_type;
pl->last_link_type = link_type; /* FIXME: kludge */
/*
* Initialize node.
......@@ -733,7 +765,8 @@ static void begin_operator(ParseLevel *restrict pl,