2021-01-12 21:04:43 -08:00
|
|
|
//
|
2021-01-15 19:35:39 -08:00
|
|
|
// definitions.c - Code for defining named pattern rules
|
2021-01-12 21:04:43 -08:00
|
|
|
//
|
2020-09-11 01:28:06 -07:00
|
|
|
|
2021-01-26 17:54:23 -08:00
|
|
|
#include <err.h>
|
2020-12-14 22:13:47 -08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2021-01-15 19:35:39 -08:00
|
|
|
#include "definitions.h"
|
2021-01-15 19:44:16 -08:00
|
|
|
#include "files.h"
|
|
|
|
#include "pattern.h"
|
2020-09-11 01:28:06 -07:00
|
|
|
#include "utils.h"
|
|
|
|
|
2021-01-12 21:04:43 -08:00
|
|
|
//
|
|
|
|
// Return a new list of definitions with one added to the front
|
|
|
|
//
|
2021-01-17 13:33:10 -08:00
|
|
|
def_t *with_def(def_t *defs, size_t namelen, const char *name, pat_t *pat)
|
2020-09-11 01:28:06 -07:00
|
|
|
{
|
2021-01-10 00:12:09 -08:00
|
|
|
def_t *def = new(def_t);
|
2021-01-10 01:45:40 -08:00
|
|
|
def->next = defs;
|
2021-01-13 18:56:22 -08:00
|
|
|
def->namelen = namelen;
|
2021-01-10 00:12:09 -08:00
|
|
|
def->name = name;
|
2021-01-15 19:21:41 -08:00
|
|
|
def->pat = pat;
|
2021-01-10 01:45:40 -08:00
|
|
|
return def;
|
2020-09-11 01:28:06 -07:00
|
|
|
}
|
|
|
|
|
2021-01-12 21:04:43 -08:00
|
|
|
//
|
|
|
|
// Load the given grammar (semicolon-separated definitions)
|
|
|
|
// and return the first rule defined.
|
|
|
|
//
|
2021-01-10 01:45:40 -08:00
|
|
|
def_t *load_grammar(def_t *defs, file_t *f)
|
2020-09-11 01:28:06 -07:00
|
|
|
{
|
2021-05-20 18:31:28 -07:00
|
|
|
const char *src = f->start;
|
2020-09-16 22:36:38 -07:00
|
|
|
src = after_spaces(src);
|
2021-01-10 01:45:40 -08:00
|
|
|
while (src < f->end) {
|
2020-09-11 01:28:06 -07:00
|
|
|
const char *name = src;
|
2021-01-10 00:39:34 -08:00
|
|
|
src = after_name(name);
|
2021-01-26 17:58:46 -08:00
|
|
|
if (src <= name)
|
|
|
|
file_err(f, name, src, "Invalid name for definition: %s", name);
|
2021-01-13 18:56:22 -08:00
|
|
|
size_t namelen = (size_t)(src - name);
|
2021-01-26 17:54:23 -08:00
|
|
|
if (!matchchar(&src, ':'))
|
|
|
|
errx(EXIT_FAILURE, "Expected ':' in definition");
|
2021-01-15 19:21:41 -08:00
|
|
|
pat_t *pat = bp_pattern(f, src);
|
|
|
|
if (pat == NULL) break;
|
2021-01-17 13:33:10 -08:00
|
|
|
defs = with_def(defs, namelen, name, pat);
|
2021-01-15 19:21:41 -08:00
|
|
|
src = pat->end;
|
2020-09-16 22:36:38 -07:00
|
|
|
src = after_spaces(src);
|
2021-01-10 00:39:34 -08:00
|
|
|
if (matchchar(&src, ';'))
|
2020-09-16 22:36:38 -07:00
|
|
|
src = after_spaces(src);
|
|
|
|
}
|
2021-01-26 17:58:46 -08:00
|
|
|
if (src < f->end)
|
|
|
|
file_err(f, src, NULL, "Invalid BP pattern");
|
2021-01-10 01:45:40 -08:00
|
|
|
return defs;
|
2020-09-11 01:28:06 -07:00
|
|
|
}
|
|
|
|
|
2021-01-12 21:04:43 -08:00
|
|
|
//
|
|
|
|
// Look up a backreference or grammar definition by name
|
|
|
|
//
|
2021-01-17 23:28:19 -08:00
|
|
|
def_t *lookup(def_t *defs, size_t namelen, const char *name)
|
2020-09-11 01:28:06 -07:00
|
|
|
{
|
2021-01-10 01:45:40 -08:00
|
|
|
for ( ; defs; defs = defs->next) {
|
2021-01-17 23:28:19 -08:00
|
|
|
if (namelen == defs->namelen && strncmp(defs->name, name, namelen) == 0)
|
2021-01-13 18:56:22 -08:00
|
|
|
return defs;
|
2020-09-11 02:55:15 -07:00
|
|
|
}
|
|
|
|
return NULL;
|
2020-09-11 01:28:06 -07:00
|
|
|
}
|
2020-09-12 18:20:13 -07:00
|
|
|
|
2021-01-13 01:48:36 -08:00
|
|
|
//
|
|
|
|
// Free all the given definitions up till (but not including) `stop`
|
|
|
|
//
|
|
|
|
void free_defs(def_t **defs, def_t *stop)
|
|
|
|
{
|
|
|
|
while (*defs != stop && *defs != NULL) {
|
|
|
|
def_t *next = (*defs)->next;
|
|
|
|
(*defs)->next = NULL;
|
|
|
|
free(*defs);
|
|
|
|
(*defs) = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-17 19:49:56 -08:00
|
|
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
|