summaryrefslogtreecommitdiffstats
path: root/contrib/bsnmp/gensnmptree/gensnmptree.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bsnmp/gensnmptree/gensnmptree.c')
-rw-r--r--contrib/bsnmp/gensnmptree/gensnmptree.c719
1 files changed, 649 insertions, 70 deletions
diff --git a/contrib/bsnmp/gensnmptree/gensnmptree.c b/contrib/bsnmp/gensnmptree/gensnmptree.c
index 990844a..b69d739 100644
--- a/contrib/bsnmp/gensnmptree/gensnmptree.c
+++ b/contrib/bsnmp/gensnmptree/gensnmptree.c
@@ -3,7 +3,7 @@
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
* All rights reserved.
*
- * Copyright (c) 2004
+ * Copyright (c) 2004-2006
* Hartmut Brandt.
* All rights reserved.
*
@@ -30,21 +30,35 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Begemot: bsnmp/gensnmptree/gensnmptree.c,v 1.44 2006/02/14 09:04:17 brandt_h Exp $
+ * $Begemot: gensnmptree.c 383 2006-05-30 07:40:49Z brandt_h $
*
* Generate OID table from table description.
*
* Syntax is:
* ---------
- * file := tree | tree file
+ * file := top | top file
+ *
+ * top := tree | typedef | include
*
* tree := head elements ')'
*
* entry := head ':' index STRING elements ')'
*
- * leaf := head TYPE STRING ACCESS ')'
+ * leaf := head type STRING ACCESS ')'
+ *
+ * column := head type ACCESS ')'
+ *
+ * type := BASETYPE | BASETYPE '|' subtype | enum | bits
+ *
+ * subtype := STRING
*
- * column := head TYPE ACCESS ')'
+ * enum := ENUM '(' value ')'
+ *
+ * bits := BITS '(' value ')'
+ *
+ * value := optminus INT STRING | optminus INT STRING value
+ *
+ * optminus := '-' | EMPTY
*
* head := '(' INT STRING
*
@@ -52,8 +66,13 @@
*
* element := tree | leaf | column
*
- * index := TYPE | index TYPE
+ * index := type | index type
+ *
+ * typedef := 'typedef' STRING type
*
+ * include := 'include' filespec
+ *
+ * filespec := '"' STRING '"' | '<' STRING '>'
*/
#include <sys/types.h>
#include <sys/param.h>
@@ -82,20 +101,27 @@ static const asn_subid_t prefix[] = { 1, 3, 6 };
u_int tree_size;
static const char *file_prefix = "";
-static FILE *fp;
/* if true generate local include paths */
static int localincs = 0;
+/* if true print tokens */
+static int debug;
+
static const char usgtxt[] = "\
-Generate SNMP tables. Copyright (c) 2001-2002 Fraunhofer Institute for\n\
-Open Communication Systems (FhG Fokus). All rights reserved.\n\
-usage: gensnmptree [-hel] [-p prefix] [name]...\n\
+Generate SNMP tables.\n\
+usage: gensnmptree [-dEehlt] [-I directory] [-i infile] [-p prefix]\n\
+ [name]...\n\
options:\n\
+ -d debug mode\n\
+ -E extract the named enums and bits only\n\
+ -e extract the named oids or enums\n\
-h print this info\n\
- -e extrace the named oids\n\
+ -I directory add directory to include path\n\
+ -i ifile read from the named file instead of stdin\n\
-l generate local include directives\n\
-p prefix prepend prefix to file and variable names\n\
+ -t generated a .def file\n\
";
/*
@@ -153,6 +179,29 @@ struct func {
static LIST_HEAD(, func) funcs = LIST_HEAD_INITIALIZER(funcs);
+struct enums {
+ const char *name;
+ long value;
+ TAILQ_ENTRY(enums) link;
+};
+
+struct type {
+ const char *name;
+ const char *from_fname;
+ u_int from_lno;
+ u_int syntax;
+ int is_enum;
+ int is_bits;
+ TAILQ_HEAD(, enums) enums;
+ LIST_ENTRY(type) link;
+};
+
+static LIST_HEAD(, type) types = LIST_HEAD_INITIALIZER(types);
+
+static void report(const char *, ...) __dead2 __printflike(1, 2);
+static void report_node(const struct node *, const char *, ...)
+ __dead2 __printflike(2, 3);
+
/************************************************************
*
* Allocate memory and panic just in the case...
@@ -168,6 +217,164 @@ xalloc(size_t size)
return (ptr);
}
+static char *
+savestr(const char *s)
+{
+
+ if (s == NULL)
+ return (NULL);
+ return (strcpy(xalloc(strlen(s) + 1), s));
+}
+
+/************************************************************
+ *
+ * Input stack
+ */
+struct input {
+ FILE *fp;
+ u_int lno;
+ char *fname;
+ char *path;
+ LIST_ENTRY(input) link;
+};
+static LIST_HEAD(, input) inputs = LIST_HEAD_INITIALIZER(inputs);
+static struct input *input = NULL;
+
+#define MAX_PATHS 100
+static u_int npaths = 2;
+static u_int stdpaths = 2;
+static const char *paths[MAX_PATHS + 1] = {
+ "/usr/share/snmp/defs",
+ "/usr/local/share/snmp/defs",
+ NULL
+};
+
+static int pbchar = -1;
+
+static void
+path_new(const char *path)
+{
+ if (npaths >= MAX_PATHS)
+ report("too many -I directives");
+ memmove(&paths[npaths - stdpaths + 1], &paths[npaths - stdpaths],
+ sizeof(path[0]) * stdpaths);
+ paths[npaths - stdpaths] = savestr(path);
+ npaths++;
+}
+
+static void
+input_new(FILE *fp, const char *path, const char *fname)
+{
+ struct input *ip;
+
+ ip = xalloc(sizeof(*ip));
+ ip->fp = fp;
+ ip->lno = 1;
+ ip->fname = savestr(fname);
+ ip->path = savestr(path);
+ LIST_INSERT_HEAD(&inputs, ip, link);
+
+ input = ip;
+}
+
+static void
+input_close(void)
+{
+
+ if (input == NULL)
+ return;
+ fclose(input->fp);
+ free(input->fname);
+ free(input->path);
+ LIST_REMOVE(input, link);
+ free(input);
+
+ input = LIST_FIRST(&inputs);
+}
+
+static FILE *
+tryopen(const char *path, const char *fname)
+{
+ char *fn;
+ FILE *fp;
+
+ if (path == NULL)
+ fn = savestr(fname);
+ else {
+ fn = xalloc(strlen(path) + strlen(fname) + 2);
+ sprintf(fn, "%s/%s", path, fname);
+ }
+ fp = fopen(fn, "r");
+ free(fn);
+ return (fp);
+}
+
+static void
+input_fopen(const char *fname, int loc)
+{
+ FILE *fp;
+ char *path;
+ u_int p;
+
+ if (fname[0] == '/') {
+ if ((fp = tryopen(NULL, fname)) != NULL) {
+ input_new(fp, NULL, fname);
+ return;
+ }
+
+ } else {
+ if (loc) {
+ if (input == NULL)
+ path = NULL;
+ else
+ path = input->path;
+
+ if ((fp = tryopen(path, fname)) != NULL) {
+ input_new(fp, NULL, fname);
+ return;
+ }
+ }
+
+ for (p = 0; paths[p] != NULL; p++)
+ if ((fp = tryopen(paths[p], fname)) != NULL) {
+ input_new(fp, paths[p], fname);
+ return;
+ }
+ }
+ report("cannot open '%s'", fname);
+}
+
+static int
+tgetc(void)
+{
+ int c;
+
+ if (pbchar != -1) {
+ c = pbchar;
+ pbchar = -1;
+ return (c);
+ }
+
+ for (;;) {
+ if (input == NULL)
+ return (EOF);
+
+ if ((c = getc(input->fp)) != EOF)
+ return (c);
+
+ input_close();
+ }
+}
+
+static void
+tungetc(int c)
+{
+
+ if (pbchar != -1)
+ abort();
+ pbchar = c;
+}
+
/************************************************************
*
* Parsing input
@@ -178,6 +385,12 @@ enum tok {
TOK_STR, /* string */
TOK_ACCESS, /* access operator */
TOK_TYPE, /* type operator */
+ TOK_ENUM, /* enum token (kind of a type) */
+ TOK_TYPEDEF, /* typedef directive */
+ TOK_DEFTYPE, /* defined type */
+ TOK_INCLUDE, /* include directive */
+ TOK_FILENAME, /* filename ("foo.bar" or <foo.bar>) */
+ TOK_BITS, /* bits token (kind of a type) */
};
static const struct {
@@ -198,6 +411,10 @@ static const struct {
{ "COUNTER", TOK_TYPE, SNMP_SYNTAX_COUNTER },
{ "GAUGE", TOK_TYPE, SNMP_SYNTAX_GAUGE },
{ "COUNTER64", TOK_TYPE, SNMP_SYNTAX_COUNTER64 },
+ { "ENUM", TOK_ENUM, SNMP_SYNTAX_INTEGER },
+ { "BITS", TOK_BITS, SNMP_SYNTAX_OCTETSTRING },
+ { "typedef", TOK_TYPEDEF, 0 },
+ { "include", TOK_INCLUDE, 0 },
{ NULL, 0, 0 }
};
@@ -205,12 +422,8 @@ static const struct {
#define MAXSTR 1000
char str[MAXSTR];
u_long val; /* integer values */
-u_int lno = 1; /* current line number */
int all_cond; /* all conditions are true */
-
-static void report(const char *, ...) __dead2 __printflike(1, 2);
-static void report_node(const struct node *, const char *, ...)
- __dead2 __printflike(2, 3);
+int saved_token = -1;
/*
* Report an error and exit.
@@ -222,11 +435,11 @@ report(const char *fmt, ...)
int c;
va_start(ap, fmt);
- fprintf(stderr, "line %u: ", lno);
+ fprintf(stderr, "line %u: ", input->lno);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
fprintf(stderr, "context: \"");
- while ((c = getchar()) != EOF && c != '\n')
+ while ((c = tgetc()) != EOF && c != '\n')
fprintf(stderr, "%c", c);
fprintf(stderr, "\n");
va_end(ap);
@@ -251,24 +464,31 @@ report_node(const struct node *np, const char *fmt, ...)
static char *
savetok(void)
{
- return (strcpy(xalloc(strlen(str)+1), str));
+ return (savestr(str));
}
/*
* Get the next token from input.
*/
static int
-gettoken(void)
+gettoken_internal(void)
{
int c;
+ struct type *t;
+
+ if (saved_token != -1) {
+ c = saved_token;
+ saved_token = -1;
+ return (c);
+ }
again:
/*
* Skip any whitespace before the next token
*/
- while ((c = getchar()) != EOF) {
+ while ((c = tgetc()) != EOF) {
if (c == '\n')
- lno++;
+ input->lno++;
if (!isspace(c))
break;
}
@@ -281,9 +501,9 @@ gettoken(void)
* Skip comments
*/
if (c == '#') {
- while ((c = getchar()) != EOF) {
+ while ((c = tgetc()) != EOF) {
if (c == '\n') {
- lno++;
+ input->lno++;
goto again;
}
}
@@ -293,15 +513,51 @@ gettoken(void)
/*
* Single character tokens
*/
- if (c == ')' || c == '(' || c == ':')
+ if (strchr("():|-", c) != NULL)
return (c);
+ if (c == '"' || c == '<') {
+ int end = c;
+ size_t n = 0;
+
+ val = 1;
+ if (c == '<') {
+ val = 0;
+ end = '>';
+ }
+
+ while ((c = tgetc()) != EOF) {
+ if (c == end)
+ break;
+ if (n == sizeof(str) - 1) {
+ str[n++] = '\0';
+ report("filename too long '%s...'", str);
+ }
+ str[n++] = c;
+ }
+ str[n++] = '\0';
+ return (TOK_FILENAME);
+ }
+
/*
* Sort out numbers
*/
if (isdigit(c)) {
- ungetc(c, stdin);
- scanf("%lu", &val);
+ size_t n = 0;
+ str[n++] = c;
+ while ((c = tgetc()) != EOF) {
+ if (!isdigit(c)) {
+ tungetc(c);
+ break;
+ }
+ if (n == sizeof(str) - 1) {
+ str[n++] = '\0';
+ report("number too long '%s...'", str);
+ }
+ str[n++] = c;
+ }
+ str[n++] = '\0';
+ sscanf(str, "%lu", &val);
return (TOK_NUM);
}
@@ -311,9 +567,9 @@ gettoken(void)
if (isalpha(c) || c == '_') {
size_t n = 0;
str[n++] = c;
- while ((c = getchar()) != EOF) {
- if (!isalnum(c) && c != '_') {
- ungetc(c, stdin);
+ while ((c = tgetc()) != EOF) {
+ if (!isalnum(c) && c != '_' && c != '-') {
+ tungetc(c);
break;
}
if (n == sizeof(str) - 1) {
@@ -333,12 +589,181 @@ gettoken(void)
return (keywords[c].tok);
}
+ LIST_FOREACH(t, &types, link) {
+ if (strcmp(t->name, str) == 0) {
+ val = t->syntax;
+ return (TOK_DEFTYPE);
+ }
+ }
return (TOK_STR);
}
if (isprint(c))
- errx(1, "%u: unexpected character '%c'", lno, c);
+ errx(1, "%u: unexpected character '%c'", input->lno, c);
else
- errx(1, "%u: unexpected character 0x%02x", lno, (u_int)c);
+ errx(1, "%u: unexpected character 0x%02x", input->lno,
+ (u_int)c);
+}
+static int
+gettoken(void)
+{
+ int tok = gettoken_internal();
+
+ if (debug) {
+ switch (tok) {
+
+ case TOK_EOF:
+ fprintf(stderr, "EOF ");
+ break;
+
+ case TOK_NUM:
+ fprintf(stderr, "NUM(%lu) ", val);
+ break;
+
+ case TOK_STR:
+ fprintf(stderr, "STR(%s) ", str);
+ break;
+
+ case TOK_ACCESS:
+ fprintf(stderr, "ACCESS(%lu) ", val);
+ break;
+
+ case TOK_TYPE:
+ fprintf(stderr, "TYPE(%lu) ", val);
+ break;
+
+ case TOK_ENUM:
+ fprintf(stderr, "ENUM ");
+ break;
+
+ case TOK_BITS:
+ fprintf(stderr, "BITS ");
+ break;
+
+ case TOK_TYPEDEF:
+ fprintf(stderr, "TYPEDEF ");
+ break;
+
+ case TOK_DEFTYPE:
+ fprintf(stderr, "DEFTYPE(%s,%lu) ", str, val);
+ break;
+
+ case TOK_INCLUDE:
+ fprintf(stderr, "INCLUDE ");
+ break;
+
+ case TOK_FILENAME:
+ fprintf(stderr, "FILENAME ");
+ break;
+
+ default:
+ if (tok < TOK_EOF) {
+ if (isprint(tok))
+ fprintf(stderr, "'%c' ", tok);
+ else if (tok == '\n')
+ fprintf(stderr, "\n");
+ else
+ fprintf(stderr, "%02x ", tok);
+ } else
+ abort();
+ break;
+ }
+ }
+ return (tok);
+}
+
+/**
+ * Pushback a token
+ */
+static void
+pushback(enum tok tok)
+{
+
+ if (saved_token != -1)
+ abort();
+ saved_token = tok;
+}
+
+/*
+ * Create a new type
+ */
+static struct type *
+make_type(const char *s)
+{
+ struct type *t;
+
+ t = xalloc(sizeof(*t));
+ t->name = savestr(s);
+ t->is_enum = 0;
+ t->syntax = SNMP_SYNTAX_NULL;
+ t->from_fname = savestr(input->fname);
+ t->from_lno = input->lno;
+ TAILQ_INIT(&t->enums);
+ LIST_INSERT_HEAD(&types, t, link);
+
+ return (t);
+}
+
+/*
+ * Parse a type. We've seen the ENUM or type keyword already. Leave next
+ * token.
+ */
+static u_int
+parse_type(enum tok *tok, struct type *t, const char *vname)
+{
+ u_int syntax;
+ struct enums *e;
+
+ syntax = val;
+
+ if (*tok == TOK_ENUM || *tok == TOK_BITS) {
+ if (t == NULL && vname != NULL) {
+ t = make_type(vname);
+ t->is_enum = (*tok == TOK_ENUM);
+ t->is_bits = (*tok == TOK_BITS);
+ t->syntax = syntax;
+ }
+ if (gettoken() != '(')
+ report("'(' expected after ENUM");
+
+ if ((*tok = gettoken()) == TOK_EOF)
+ report("unexpected EOF in ENUM");
+ do {
+ e = NULL;
+ if (t != NULL) {
+ e = xalloc(sizeof(*e));
+ }
+ if (*tok == '-') {
+ if ((*tok = gettoken()) == TOK_EOF)
+ report("unexpected EOF in ENUM");
+ e->value = -(long)val;
+ } else
+ e->value = val;
+
+ if (*tok != TOK_NUM)
+ report("need value for ENUM/BITS");
+ if (gettoken() != TOK_STR)
+ report("need string in ENUM/BITS");
+ if (e != NULL) {
+ e->name = savetok();
+ TAILQ_INSERT_TAIL(&t->enums, e, link);
+ }
+ if ((*tok = gettoken()) == TOK_EOF)
+ report("unexpected EOF in ENUM/BITS");
+ } while (*tok != ')');
+ *tok = gettoken();
+
+ } else if (*tok == TOK_DEFTYPE) {
+ *tok = gettoken();
+
+ } else {
+ if ((*tok = gettoken()) == '|') {
+ if (gettoken() != TOK_STR)
+ report("subtype expected after '|'");
+ *tok = gettoken();
+ }
+ }
+
+ return (syntax);
}
/*
@@ -352,7 +777,7 @@ parse(enum tok tok)
u_int index_count;
node = xalloc(sizeof(struct node));
- node->lno = lno;
+ node->lno = input->lno;
node->flags = 0;
if (tok != '(')
@@ -366,11 +791,12 @@ parse(enum tok tok)
report("node name expected after '(' ID");
node->name = savetok();
- if ((tok = gettoken()) == TOK_TYPE) {
+ if ((tok = gettoken()) == TOK_TYPE || tok == TOK_DEFTYPE ||
+ tok == TOK_ENUM || tok == TOK_BITS) {
/* LEAF or COLUM */
- u_int syntax = val;
+ u_int syntax = parse_type(&tok, NULL, node->name);
- if ((tok = gettoken()) == TOK_STR) {
+ if (tok == TOK_STR) {
/* LEAF */
node->type = NODE_LEAF;
node->u.leaf.func = savetok();
@@ -396,16 +822,18 @@ parse(enum tok tok)
index_count = 0;
node->u.entry.index = 0;
- while ((tok = gettoken()) == TOK_TYPE) {
+ tok = gettoken();
+ while (tok == TOK_TYPE || tok == TOK_DEFTYPE ||
+ tok == TOK_ENUM || tok == TOK_BITS) {
+ u_int syntax = parse_type(&tok, NULL, node->name);
if (index_count++ == SNMP_INDEXES_MAX)
report("too many table indexes");
node->u.entry.index |=
- val << (SNMP_INDEX_SHIFT * index_count);
+ syntax << (SNMP_INDEX_SHIFT * index_count);
}
node->u.entry.index |= index_count;
if (index_count == 0)
report("need at least one index");
-
if (tok != TOK_STR)
report("function name expected");
@@ -434,10 +862,49 @@ parse(enum tok tok)
}
/*
+ * Parse a top level element. Return the tree if it was a tree, NULL
+ * otherwise.
+ */
+static struct node *
+parse_top(enum tok tok)
+{
+ struct type *t;
+
+ if (tok == '(')
+ return (parse(tok));
+
+ if (tok == TOK_TYPEDEF) {
+ if (gettoken() != TOK_STR)
+ report("type name expected after typedef");
+
+ t = make_type(str);
+
+ tok = gettoken();
+ t->is_enum = (tok == TOK_ENUM);
+ t->is_bits = (tok == TOK_BITS);
+ t->syntax = parse_type(&tok, t, NULL);
+ pushback(tok);
+
+ return (NULL);
+ }
+
+ if (tok == TOK_INCLUDE) {
+ if (gettoken() != TOK_FILENAME)
+ report("filename expected in include directive");
+
+ input_fopen(str, val);
+ return (NULL);
+ }
+
+ report("'(' or 'typedef' expected");
+}
+
+/*
* Generate the C-code table part for one node.
*/
static void
-gen_node(struct node *np, struct asn_oid *oid, u_int idx, const char *func)
+gen_node(FILE *fp, struct node *np, struct asn_oid *oid, u_int idx,
+ const char *func)
{
u_int n;
struct node *sub;
@@ -449,13 +916,14 @@ gen_node(struct node *np, struct asn_oid *oid, u_int idx, const char *func)
if (np->type == NODE_TREE) {
TAILQ_FOREACH(sub, &np->u.tree.subs, link)
- gen_node(sub, oid, 0, NULL);
+ gen_node(fp, sub, oid, 0, NULL);
oid->len--;
return;
}
if (np->type == NODE_ENTRY) {
TAILQ_FOREACH(sub, &np->u.entry.subs, link)
- gen_node(sub, oid, np->u.entry.index, np->u.entry.func);
+ gen_node(fp, sub, oid, np->u.entry.index,
+ np->u.entry.func);
oid->len--;
return;
}
@@ -540,7 +1008,7 @@ gen_node(struct node *np, struct asn_oid *oid, u_int idx, const char *func)
* Generate the header file with the function declarations.
*/
static void
-gen_header(struct node *np, u_int oidlen, const char *func)
+gen_header(FILE *fp, struct node *np, u_int oidlen, const char *func)
{
char f[MAXSTR + 4];
struct node *sub;
@@ -549,12 +1017,12 @@ gen_header(struct node *np, u_int oidlen, const char *func)
oidlen++;
if (np->type == NODE_TREE) {
TAILQ_FOREACH(sub, &np->u.tree.subs, link)
- gen_header(sub, oidlen, NULL);
+ gen_header(fp, sub, oidlen, NULL);
return;
}
if (np->type == NODE_ENTRY) {
TAILQ_FOREACH(sub, &np->u.entry.subs, link)
- gen_header(sub, oidlen, np->u.entry.func);
+ gen_header(fp, sub, oidlen, np->u.entry.func);
return;
}
@@ -575,7 +1043,7 @@ gen_header(struct node *np, u_int oidlen, const char *func)
if (ptr == NULL) {
ptr = xalloc(sizeof(*ptr));
- ptr->name = strcpy(xalloc(strlen(f)+1), f);
+ ptr->name = savestr(f);
LIST_INSERT_HEAD(&funcs, ptr, link);
fprintf(fp, "int %s(struct snmp_context *, "
@@ -590,7 +1058,7 @@ gen_header(struct node *np, u_int oidlen, const char *func)
* Generate the OID table.
*/
static void
-gen_table(struct node *node)
+gen_table(FILE *fp, struct node *node)
{
struct asn_oid oid;
@@ -615,7 +1083,7 @@ gen_table(struct node *node)
oid.len = PREFIX_LEN;
memcpy(oid.subs, prefix, sizeof(prefix));
- gen_node(node, &oid, 0, NULL);
+ gen_node(fp, node, &oid, 0, NULL);
fprintf(fp, "};\n\n");
}
@@ -681,12 +1149,11 @@ gen_tree(const struct node *np, int level)
printf("%s%s)\n", (np->flags & FL_GET) ? " GET" : "",
(np->flags & FL_SET) ? " SET" : "");
break;
-
}
}
static int
-extract(const struct node *np, struct asn_oid *oid, const char *obj,
+extract(FILE *fp, const struct node *np, struct asn_oid *oid, const char *obj,
const struct asn_oid *idx, const char *iname)
{
struct node *sub;
@@ -715,11 +1182,11 @@ extract(const struct node *np, struct asn_oid *oid, const char *obj,
if (np->type == NODE_TREE) {
TAILQ_FOREACH(sub, &np->u.tree.subs, link)
- if (!extract(sub, oid, obj, idx, iname))
+ if (!extract(fp, sub, oid, obj, idx, iname))
return (0);
} else if (np->type == NODE_ENTRY) {
TAILQ_FOREACH(sub, &np->u.entry.subs, link)
- if (!extract(sub, oid, obj, idx, iname))
+ if (!extract(fp, sub, oid, obj, idx, iname))
return (0);
}
oid->len--;
@@ -727,7 +1194,7 @@ extract(const struct node *np, struct asn_oid *oid, const char *obj,
}
static int
-gen_extract(const struct node *root, char *object)
+gen_extract(FILE *fp, const struct node *root, char *object)
{
struct asn_oid oid;
struct asn_oid idx;
@@ -773,7 +1240,7 @@ gen_extract(const struct node *root, char *object)
oid.len = PREFIX_LEN;
memcpy(oid.subs, prefix, sizeof(prefix));
- ret = extract(root, &oid, object, &idx, iname);
+ ret = extract(fp, root, &oid, object, &idx, iname);
if (iname != NULL)
free(iname);
@@ -879,18 +1346,93 @@ merge_subs(struct node_list *s1, struct node_list *s2)
}
static void
-merge(struct node *root, struct node *t)
+merge(struct node **root, struct node *t)
{
+ if (*root == NULL) {
+ *root = t;
+ return;
+ }
+ if (t == NULL)
+ return;
+
/* both must be trees */
- if (root->type != NODE_TREE)
+ if ((*root)->type != NODE_TREE)
errx(1, "root is not a tree");
if (t->type != NODE_TREE)
errx(1, "can merge only with tree");
- if (root->id != t->id)
+ if ((*root)->id != t->id)
errx(1, "trees to merge must have same id");
- merge_subs(&root->u.tree.subs, &t->u.tree.subs);
+ merge_subs(&(*root)->u.tree.subs, &t->u.tree.subs);
+}
+
+static void
+unminus(FILE *fp, const char *s)
+{
+
+ while (*s != '\0') {
+ if (*s == '-')
+ fprintf(fp, "_");
+ else
+ fprintf(fp, "%c", *s);
+ s++;
+ }
+}
+
+static void
+gen_enum(FILE *fp, const struct type *t)
+{
+ const struct enums *e;
+ long min = LONG_MAX;
+
+ fprintf(fp, "\n");
+ fprintf(fp, "#ifndef %s_defined__\n", t->name);
+ fprintf(fp, "#define %s_defined__\n", t->name);
+ fprintf(fp, "/*\n");
+ fprintf(fp, " * From %s:%u\n", t->from_fname, t->from_lno);
+ fprintf(fp, " */\n");
+ fprintf(fp, "enum %s {\n", t->name);
+ TAILQ_FOREACH(e, &t->enums, link) {
+ fprintf(fp, "\t%s_", t->name);
+ unminus(fp, e->name);
+ fprintf(fp, " = %ld,\n", e->value);
+ if (e->value < min)
+ min = e->value;
+ }
+ fprintf(fp, "};\n");
+ fprintf(fp, "#define STROFF_%s %ld\n", t->name, min);
+ fprintf(fp, "#define STRING_%s \\\n", t->name);
+ TAILQ_FOREACH(e, &t->enums, link) {
+ fprintf(fp, "\t[%ld] \"%s_", e->value - min, t->name);
+ unminus(fp, e->name);
+ fprintf(fp, "\",\\\n");
+ }
+ fprintf(fp, "\n");
+ fprintf(fp, "#endif /* %s_defined__ */\n", t->name);
+}
+
+static void
+gen_enums(FILE *fp)
+{
+ const struct type *t;
+
+ LIST_FOREACH(t, &types, link)
+ if (t->is_enum || t->is_bits)
+ gen_enum(fp, t);
+}
+
+static int
+extract_enum(FILE *fp, const char *name)
+{
+ const struct type *t;
+
+ LIST_FOREACH(t, &types, link)
+ if ((t->is_enum || t->is_bits) && strcmp(t->name, name) == 0) {
+ gen_enum(fp, t);
+ return (0);
+ }
+ return (-1);
}
int
@@ -898,22 +1440,41 @@ main(int argc, char *argv[])
{
int do_extract = 0;
int do_tree = 0;
+ int do_enums = 0;
int opt;
struct node *root;
char fname[MAXPATHLEN + 1];
int tok;
+ FILE *fp;
+ char *infile = NULL;
- while ((opt = getopt(argc, argv, "help:t")) != EOF)
+ while ((opt = getopt(argc, argv, "dEehI:i:lp:t")) != EOF)
switch (opt) {
+ case 'd':
+ debug = 1;
+ break;
+
case 'h':
fprintf(stderr, "%s", usgtxt);
exit(0);
+ case 'E':
+ do_enums = 1;
+ break;
+
case 'e':
do_extract = 1;
break;
+ case 'I':
+ path_new(optarg);
+ break;
+
+ case 'i':
+ infile = optarg;
+ break;
+
case 'l':
localincs = 1;
break;
@@ -930,27 +1491,41 @@ main(int argc, char *argv[])
break;
}
- if (do_extract && do_tree)
- errx(1, "conflicting options -e and -t");
- if (!do_extract && argc != optind)
+ if (do_extract + do_tree + do_enums > 1)
+ errx(1, "conflicting options -e/-t/-E");
+ if (!do_extract && !do_enums && argc != optind)
errx(1, "no arguments allowed");
- if (do_extract && argc == optind)
+ if ((do_extract || do_enums) && argc == optind)
errx(1, "no objects specified");
- root = parse(gettoken());
+ if (infile == NULL) {
+ input_new(stdin, NULL, "<stdin>");
+ } else {
+ if ((fp = fopen(infile, "r")) == NULL)
+ err(1, "%s", infile);
+ input_new(fp, NULL, infile);
+ }
+
+ root = parse_top(gettoken());
while ((tok = gettoken()) != TOK_EOF)
- merge(root, parse(tok));
+ merge(&root, parse_top(tok));
check_tree(root);
if (do_extract) {
- fp = stdout;
while (optind < argc) {
- if (gen_extract(root, argv[optind]))
+ if (gen_extract(stdout, root, argv[optind]))
errx(1, "object not found: %s", argv[optind]);
optind++;
}
-
+ return (0);
+ }
+ if (do_enums) {
+ while (optind < argc) {
+ if (extract_enum(stdout, argv[optind]))
+ errx(1, "enum not found: %s", argv[optind]);
+ optind++;
+ }
return (0);
}
if (do_tree) {
@@ -960,7 +1535,11 @@ main(int argc, char *argv[])
sprintf(fname, "%stree.h", file_prefix);
if ((fp = fopen(fname, "w")) == NULL)
err(1, "%s: ", fname);
- gen_header(root, PREFIX_LEN, NULL);
+ gen_header(fp, root, PREFIX_LEN, NULL);
+
+ fprintf(fp, "\n#ifdef SNMPTREE_TYPES\n");
+ gen_enums(fp);
+ fprintf(fp, "\n#endif /* SNMPTREE_TYPES */\n\n");
fprintf(fp, "#define %sCTREE_SIZE %u\n", file_prefix, tree_size);
fprintf(fp, "extern const struct snmp_node %sctree[];\n", file_prefix);
@@ -970,7 +1549,7 @@ main(int argc, char *argv[])
sprintf(fname, "%stree.c", file_prefix);
if ((fp = fopen(fname, "w")) == NULL)
err(1, "%s: ", fname);
- gen_table(root);
+ gen_table(fp, root);
fclose(fp);
return (0);
OpenPOWER on IntegriCloud