summaryrefslogtreecommitdiff
path: root/src/skeletons.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/skeletons.c')
-rw-r--r--src/skeletons.c255
1 files changed, 255 insertions, 0 deletions
diff --git a/src/skeletons.c b/src/skeletons.c
new file mode 100644
index 0000000..84e3a4f
--- /dev/null
+++ b/src/skeletons.c
@@ -0,0 +1,255 @@
+/* flex - tool to generate fast lexical analyzers */
+
+/* Copyright (c) 1990 The Regents of the University of California. */
+/* All rights reserved. */
+
+/* This code is derived from software contributed to Berkeley by */
+/* Vern Paxson. */
+
+/* The United States Government has rights in this work pursuant */
+/* to contract no. DE-AC03-76SF00098 between the United States */
+/* Department of Energy and the University of California. */
+
+/* This file is part of flex. */
+
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following conditions */
+/* are met: */
+
+/* 1. Redistributions of source code must retain the above copyright */
+/* notice, this list of conditions and the following disclaimer. */
+/* 2. Redistributions in binary form must reproduce the above copyright */
+/* notice, this list of conditions and the following disclaimer in the */
+/* documentation and/or other materials provided with the distribution. */
+
+/* Neither the name of the University nor the names of its contributors */
+/* may be used to endorse or promote products derived from this software */
+/* without specific prior written permission. */
+
+/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
+/* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
+/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
+/* PURPOSE. */
+
+
+#include "flexdef.h"
+#include "tables.h"
+
+/* START digested skeletons */
+
+const char *cpp_skel[] = {
+#include "cpp-flex.h"
+ 0,
+};
+
+const char *c99_skel[] = {
+#include "c99-flex.h"
+ 0,
+};
+
+const char *go_skel[] = {
+#include "go-flex.h"
+ 0,
+};
+
+/* END digested skeletons */
+
+/* Method table describing a language-specific back end.
+ * Even if this never gets a member other than the skel
+ * array, it prevents us from getting lost in a maze of
+ * twisty array reference levels, all different.
+ */
+struct flex_backend_t {
+ const char **skel; // Digested skeleton file
+};
+
+static struct flex_backend_t backends[] = {
+ {.skel=cpp_skel},
+ {.skel=c99_skel},
+ {.skel=go_skel},
+ {NULL}
+};
+
+static struct flex_backend_t *backend = &backends[0];
+
+/* Functions for querying skeleton properties. */
+
+bool is_default_backend(void)
+{
+ return backend == &backends[0];
+}
+
+/* Search for a string in the skeleton prolog, where macros are defined.
+ */
+static bool boneseeker(const char *bone)
+{
+ int i;
+
+ for (i = 0; backend->skel[i] != NULL; i++) {
+ const char *line = backend->skel[i];
+ if (strstr(line, bone) != NULL)
+ return true;
+ else if (strncmp(line, "%%", 2) == 0)
+ break;
+ }
+ return false;
+}
+
+void backend_by_name(const char *name)
+{
+ const char *prefix_property;
+ if (name != NULL) {
+ if (strcmp(name, "nr") == 0) {
+ backend = &backends[0];
+ ctrl.reentrant = false;
+ goto backend_ok;
+ }
+ if (strcmp(name, "r") == 0) {
+ backend = &backends[0];
+ ctrl.reentrant = true;
+ goto backend_ok;
+ }
+ for (backend = &backends[0]; backend->skel != NULL; backend++) {
+ if (strcasecmp(skel_property("M4_PROPERTY_BACKEND_NAME"), name) == 0)
+ goto backend_ok;
+ }
+ flexerror(_("no such back end"));
+ }
+ backend_ok:
+ ctrl.rewrite = !is_default_backend();
+ ctrl.backend_name = xstrdup(skel_property("M4_PROPERTY_BACKEND_NAME"));
+ ctrl.traceline_re = xstrdup(skel_property("M4_PROPERTY_TRACE_LINE_REGEXP"));
+ ctrl.traceline_template = xstrdup(skel_property("M4_PROPERTY_TRACE_LINE_TEMPLATE"));
+ ctrl.have_state_entry_format = boneseeker("m4_define([[M4_HOOK_STATE_ENTRY_FORMAT]]");
+ prefix_property = skel_property("M4_PROPERTY_PREFIX");
+ if (prefix_property != NULL)
+ ctrl.prefix = xstrdup(prefix_property);
+ flex_init_regex(ctrl.traceline_re);
+}
+
+const char *suffix (void)
+{
+ const char *suffix;
+
+ if (is_default_backend()) {
+ if (ctrl.C_plus_plus)
+ suffix = "cc";
+ else
+ suffix = "c";
+ } else {
+ suffix = skel_property("M4_PROPERTY_SOURCE_SUFFIX");
+ }
+
+ return suffix;
+}
+
+/* Search for a m4 define of the property key, retrieve the value. The
+ * definition must be single-line. Don't call this a second time before
+ * stashing away the previous return, we cheat with static buffers.
+ */
+const char *skel_property(const char *propname)
+{
+ int i;
+ static char name[256], value[256], *np, *vp;;
+ const char *cp;
+
+ for (i = 0; backend->skel[i] != NULL; i++) {
+ const char *line = backend->skel[i];
+ if (line[0] == '\0')
+ continue;
+ /* only scan before first skell breakpoint */
+ if (strncmp(line, "%%", 2) == 0)
+ break;
+ /* ignore anything that's not a definition */
+ if (strncmp(line, "m4_define(", 10) != 0)
+ continue;
+ /* skip space and quotes before macro name */
+ for (cp = line + 10; isspace(*cp) || *cp == '['; *cp++)
+ continue;
+ /* copy up to following ] into the name buffer */
+ np = name;
+ while (*cp != ']' && *cp != '\0' && (np < name + sizeof(name)-1)) {
+ *np++ = *cp++;
+ }
+ *np = '\0';
+ /* check for valid and matching name */
+ if (*cp == ']') {
+ if (strcmp(name, propname) != 0)
+ continue; /* try next line */
+ } else {
+ flexerror(_("unterminated or too long property name"));
+ continue;
+ }
+ /* skip to the property value */
+ while (*cp != '\0' && (*cp == ']' || isspace(*cp) || *cp == ','))
+ cp++;
+ while (*cp == '[')
+ cp++;
+ if (*cp == '\0')
+ flexerror(_("garbled property line"));
+ /* extract the value */
+ vp = value;
+ while (*cp != '\0' && vp < value + sizeof(value) - 1 && (cp[0] != ']' || cp[1] != ']'))
+ *vp++ = *cp++;
+ if (*cp == ']') {
+ *vp = '\0';
+ return value;
+ } else {
+ flexerror(_("unterminated or too long property value"));
+ }
+ }
+ return NULL;
+}
+
+/* skelout - write out one section of the skeleton file
+ *
+ * Description
+ * Copies skelfile or skel array to stdout until a line beginning with
+ * "%%" or EOF is found.
+ */
+void skelout (bool announce)
+{
+ char buf_storage[MAXLINE];
+ char *buf = buf_storage;
+ bool do_copy = true;
+
+ /* Loop pulling lines either from the skelfile, if we're using
+ * one, or from the selected back end's skel[] array.
+ */
+ while (env.skelfile != NULL ?
+ (fgets (buf, MAXLINE, env.skelfile) != NULL) :
+ ((buf = (char *) backend->skel[skel_ind++]) != 0)) {
+
+ if (env.skelfile != NULL)
+ chomp (buf);
+
+ /* copy from skel array */
+ if (buf[0] == '%') { /* control line */
+ /* print the control line as a comment. */
+ if (ctrl.ddebug && buf[1] != '#') {
+ comment(buf);
+ outc ('\n');
+ }
+ if (buf[1] == '#') {
+ /* %# indicates comment line to be ignored */
+ }
+ else if (buf[1] == '%') {
+ /* %% is a break point for skelout() */
+ if (announce) {
+ comment(buf);
+ outc ('\n');
+ }
+ return;
+ }
+ else {
+ flexfatal (_("bad line in skeleton file"));
+ }
+ }
+
+ else if (do_copy)
+ outn (buf);
+ } /* end while */
+}
+
+
+/* end */