1f06ca4afSHartmut Brandt /*
2f06ca4afSHartmut Brandt * Copyright (c) 2001-2003
3f06ca4afSHartmut Brandt * Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4f06ca4afSHartmut Brandt * All rights reserved.
5f06ca4afSHartmut Brandt *
68e9b3e70SHartmut Brandt * Copyright (c) 2004-2006,2018
7896052c1SHartmut Brandt * Hartmut Brandt.
8896052c1SHartmut Brandt * All rights reserved.
9896052c1SHartmut Brandt *
10f06ca4afSHartmut Brandt * Author: Harti Brandt <harti@freebsd.org>
11f06ca4afSHartmut Brandt *
12896052c1SHartmut Brandt * Redistribution and use in source and binary forms, with or without
13896052c1SHartmut Brandt * modification, are permitted provided that the following conditions
14896052c1SHartmut Brandt * are met:
15896052c1SHartmut Brandt * 1. Redistributions of source code must retain the above copyright
16896052c1SHartmut Brandt * notice, this list of conditions and the following disclaimer.
17f06ca4afSHartmut Brandt * 2. Redistributions in binary form must reproduce the above copyright
18f06ca4afSHartmut Brandt * notice, this list of conditions and the following disclaimer in the
19f06ca4afSHartmut Brandt * documentation and/or other materials provided with the distribution.
20f06ca4afSHartmut Brandt *
21896052c1SHartmut Brandt * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22896052c1SHartmut Brandt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23896052c1SHartmut Brandt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24896052c1SHartmut Brandt * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
25896052c1SHartmut Brandt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26896052c1SHartmut Brandt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27896052c1SHartmut Brandt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28896052c1SHartmut Brandt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29896052c1SHartmut Brandt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30896052c1SHartmut Brandt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31896052c1SHartmut Brandt * SUCH DAMAGE.
32f06ca4afSHartmut Brandt *
336f557cf7SHartmut Brandt * $Begemot: gensnmptree.c 383 2006-05-30 07:40:49Z brandt_h $
34f06ca4afSHartmut Brandt *
35f06ca4afSHartmut Brandt * Generate OID table from table description.
36f06ca4afSHartmut Brandt *
37f06ca4afSHartmut Brandt * Syntax is:
38f06ca4afSHartmut Brandt * ---------
396f557cf7SHartmut Brandt * file := top | top file
406f557cf7SHartmut Brandt *
416f557cf7SHartmut Brandt * top := tree | typedef | include
42896052c1SHartmut Brandt *
43f06ca4afSHartmut Brandt * tree := head elements ')'
44f06ca4afSHartmut Brandt *
45f06ca4afSHartmut Brandt * entry := head ':' index STRING elements ')'
46f06ca4afSHartmut Brandt *
476f557cf7SHartmut Brandt * leaf := head type STRING ACCESS ')'
48f06ca4afSHartmut Brandt *
496f557cf7SHartmut Brandt * column := head type ACCESS ')'
506f557cf7SHartmut Brandt *
516f557cf7SHartmut Brandt * type := BASETYPE | BASETYPE '|' subtype | enum | bits
526f557cf7SHartmut Brandt *
536f557cf7SHartmut Brandt * subtype := STRING
546f557cf7SHartmut Brandt *
556f557cf7SHartmut Brandt * enum := ENUM '(' value ')'
566f557cf7SHartmut Brandt *
576f557cf7SHartmut Brandt * bits := BITS '(' value ')'
586f557cf7SHartmut Brandt *
596f557cf7SHartmut Brandt * value := optminus INT STRING | optminus INT STRING value
606f557cf7SHartmut Brandt *
616f557cf7SHartmut Brandt * optminus := '-' | EMPTY
62f06ca4afSHartmut Brandt *
63f06ca4afSHartmut Brandt * head := '(' INT STRING
64f06ca4afSHartmut Brandt *
65f06ca4afSHartmut Brandt * elements := EMPTY | elements element
66f06ca4afSHartmut Brandt *
6794caccb3SHartmut Brandt * element := tree | leaf | column
68f06ca4afSHartmut Brandt *
696f557cf7SHartmut Brandt * index := type | index type
70f06ca4afSHartmut Brandt *
716f557cf7SHartmut Brandt * typedef := 'typedef' STRING type
726f557cf7SHartmut Brandt *
736f557cf7SHartmut Brandt * include := 'include' filespec
746f557cf7SHartmut Brandt *
756f557cf7SHartmut Brandt * filespec := '"' STRING '"' | '<' STRING '>'
76f06ca4afSHartmut Brandt */
77f06ca4afSHartmut Brandt #include <sys/types.h>
78f06ca4afSHartmut Brandt #include <sys/param.h>
79f06ca4afSHartmut Brandt #include <stdio.h>
80f06ca4afSHartmut Brandt #include <stdlib.h>
81f06ca4afSHartmut Brandt #include <stdarg.h>
82f06ca4afSHartmut Brandt #include <unistd.h>
83f06ca4afSHartmut Brandt #include <string.h>
84f06ca4afSHartmut Brandt #include <ctype.h>
850a9d66caSHartmut Brandt #include <inttypes.h>
86896052c1SHartmut Brandt #include <errno.h>
87896052c1SHartmut Brandt #ifdef HAVE_ERR_H
88f06ca4afSHartmut Brandt #include <err.h>
89896052c1SHartmut Brandt #endif
90f06ca4afSHartmut Brandt #include <sys/queue.h>
91896052c1SHartmut Brandt #include "support.h"
92f06ca4afSHartmut Brandt #include "asn1.h"
93f06ca4afSHartmut Brandt #include "snmp.h"
94f06ca4afSHartmut Brandt #include "snmpagent.h"
95f06ca4afSHartmut Brandt
96f06ca4afSHartmut Brandt /*
97f06ca4afSHartmut Brandt * Constant prefix for all OIDs
98f06ca4afSHartmut Brandt */
99f06ca4afSHartmut Brandt static const asn_subid_t prefix[] = { 1, 3, 6 };
100f06ca4afSHartmut Brandt #define PREFIX_LEN (sizeof(prefix) / sizeof(prefix[0]))
101f06ca4afSHartmut Brandt
102f06ca4afSHartmut Brandt u_int tree_size;
103f06ca4afSHartmut Brandt static const char *file_prefix = "";
104f06ca4afSHartmut Brandt
105f06ca4afSHartmut Brandt /* if true generate local include paths */
106f06ca4afSHartmut Brandt static int localincs = 0;
107f06ca4afSHartmut Brandt
1086f557cf7SHartmut Brandt /* if true print tokens */
1096f557cf7SHartmut Brandt static int debug;
1106f557cf7SHartmut Brandt
111f06ca4afSHartmut Brandt static const char usgtxt[] = "\
1126f557cf7SHartmut Brandt Generate SNMP tables.\n\
1138e9b3e70SHartmut Brandt usage: gensnmptree [-dEeFfhlt] [-I directory] [-i infile] [-p prefix]\n\
1146f557cf7SHartmut Brandt [name]...\n\
115f06ca4afSHartmut Brandt options:\n\
1166f557cf7SHartmut Brandt -d debug mode\n\
1178e9b3e70SHartmut Brandt -E extract the named or all enums and bits only\n\
1186f557cf7SHartmut Brandt -e extract the named oids or enums\n\
1198e9b3e70SHartmut Brandt -F generate functions for -E into a .c file\n\
1208e9b3e70SHartmut Brandt -f generate functions for -E into the header\n\
121f06ca4afSHartmut Brandt -h print this info\n\
1226f557cf7SHartmut Brandt -I directory add directory to include path\n\
1236f557cf7SHartmut Brandt -i ifile read from the named file instead of stdin\n\
124f06ca4afSHartmut Brandt -l generate local include directives\n\
125f06ca4afSHartmut Brandt -p prefix prepend prefix to file and variable names\n\
1268e9b3e70SHartmut Brandt -t generate a .def file\n\
127f06ca4afSHartmut Brandt ";
128f06ca4afSHartmut Brandt
129*04d17814SAndrey V. Elsukov /**
130*04d17814SAndrey V. Elsukov * Program operation.
131*04d17814SAndrey V. Elsukov */
132*04d17814SAndrey V. Elsukov enum op {
133*04d17814SAndrey V. Elsukov /** generate the tree */
134*04d17814SAndrey V. Elsukov OP_GEN,
135*04d17814SAndrey V. Elsukov
136*04d17814SAndrey V. Elsukov /** extract OIDs */
137*04d17814SAndrey V. Elsukov OP_EXTRACT,
138*04d17814SAndrey V. Elsukov
139*04d17814SAndrey V. Elsukov /** print the parsed tree */
140*04d17814SAndrey V. Elsukov OP_TREE,
141*04d17814SAndrey V. Elsukov
142*04d17814SAndrey V. Elsukov /** extract enums */
143*04d17814SAndrey V. Elsukov OP_ENUMS,
144*04d17814SAndrey V. Elsukov };
145*04d17814SAndrey V. Elsukov
146*04d17814SAndrey V. Elsukov /**
147*04d17814SAndrey V. Elsukov * Which functions to create.
148*04d17814SAndrey V. Elsukov */
149*04d17814SAndrey V. Elsukov enum gen_funcs {
150*04d17814SAndrey V. Elsukov /** none */
151*04d17814SAndrey V. Elsukov GEN_FUNCS_NONE,
152*04d17814SAndrey V. Elsukov
153*04d17814SAndrey V. Elsukov /** functions for header files */
154*04d17814SAndrey V. Elsukov GEN_FUNCS_H,
155*04d17814SAndrey V. Elsukov
156*04d17814SAndrey V. Elsukov /** functions for C files */
157*04d17814SAndrey V. Elsukov GEN_FUNCS_C,
158*04d17814SAndrey V. Elsukov };
159*04d17814SAndrey V. Elsukov
160f06ca4afSHartmut Brandt /*
161f06ca4afSHartmut Brandt * A node in the OID tree
162f06ca4afSHartmut Brandt */
163f06ca4afSHartmut Brandt enum ntype {
164f06ca4afSHartmut Brandt NODE_LEAF = 1,
165f06ca4afSHartmut Brandt NODE_TREE,
166f06ca4afSHartmut Brandt NODE_ENTRY,
167f06ca4afSHartmut Brandt NODE_COLUMN
168f06ca4afSHartmut Brandt };
169f06ca4afSHartmut Brandt
170f06ca4afSHartmut Brandt enum {
171f06ca4afSHartmut Brandt FL_GET = 0x01,
172f06ca4afSHartmut Brandt FL_SET = 0x02,
173f06ca4afSHartmut Brandt };
174f06ca4afSHartmut Brandt
175f06ca4afSHartmut Brandt struct node;
176f06ca4afSHartmut Brandt TAILQ_HEAD(node_list, node);
177f06ca4afSHartmut Brandt
178f06ca4afSHartmut Brandt struct node {
179f06ca4afSHartmut Brandt enum ntype type;
180f06ca4afSHartmut Brandt asn_subid_t id; /* last element of OID */
181f06ca4afSHartmut Brandt char *name; /* name of node */
182f06ca4afSHartmut Brandt TAILQ_ENTRY(node) link;
183f06ca4afSHartmut Brandt u_int lno; /* starting line number */
184f06ca4afSHartmut Brandt u_int flags; /* allowed operations */
185f06ca4afSHartmut Brandt
186f06ca4afSHartmut Brandt union {
187f06ca4afSHartmut Brandt struct tree {
188f06ca4afSHartmut Brandt struct node_list subs;
189f06ca4afSHartmut Brandt } tree;
190f06ca4afSHartmut Brandt
191f06ca4afSHartmut Brandt struct entry {
192896052c1SHartmut Brandt uint32_t index; /* index for table entry */
193f06ca4afSHartmut Brandt char *func; /* function for tables */
194f06ca4afSHartmut Brandt struct node_list subs;
195*04d17814SAndrey V. Elsukov char *subtypes[SNMP_INDEXES_MAX];
196f06ca4afSHartmut Brandt } entry;
197f06ca4afSHartmut Brandt
198f06ca4afSHartmut Brandt struct leaf {
199f06ca4afSHartmut Brandt enum snmp_syntax syntax; /* syntax for this leaf */
200f06ca4afSHartmut Brandt char *func; /* function name */
201*04d17814SAndrey V. Elsukov char *subtype; /* subtype */
202f06ca4afSHartmut Brandt } leaf;
203f06ca4afSHartmut Brandt
204f06ca4afSHartmut Brandt struct column {
205f06ca4afSHartmut Brandt enum snmp_syntax syntax; /* syntax for this column */
206*04d17814SAndrey V. Elsukov char *subtype; /* subtype */
207f06ca4afSHartmut Brandt } column;
208f06ca4afSHartmut Brandt } u;
209f06ca4afSHartmut Brandt };
210f06ca4afSHartmut Brandt
211f06ca4afSHartmut Brandt struct func {
212f06ca4afSHartmut Brandt const char *name;
213f06ca4afSHartmut Brandt LIST_ENTRY(func) link;
214f06ca4afSHartmut Brandt };
215f06ca4afSHartmut Brandt
216f06ca4afSHartmut Brandt static LIST_HEAD(, func) funcs = LIST_HEAD_INITIALIZER(funcs);
217f06ca4afSHartmut Brandt
2186f557cf7SHartmut Brandt struct enums {
2196f557cf7SHartmut Brandt const char *name;
2206f557cf7SHartmut Brandt long value;
2216f557cf7SHartmut Brandt TAILQ_ENTRY(enums) link;
2226f557cf7SHartmut Brandt };
2236f557cf7SHartmut Brandt
2246f557cf7SHartmut Brandt struct type {
2256f557cf7SHartmut Brandt const char *name;
2266f557cf7SHartmut Brandt const char *from_fname;
2276f557cf7SHartmut Brandt u_int from_lno;
2286f557cf7SHartmut Brandt u_int syntax;
2296f557cf7SHartmut Brandt int is_enum;
2306f557cf7SHartmut Brandt int is_bits;
2316f557cf7SHartmut Brandt TAILQ_HEAD(, enums) enums;
2326f557cf7SHartmut Brandt LIST_ENTRY(type) link;
2336f557cf7SHartmut Brandt };
2346f557cf7SHartmut Brandt
2356f557cf7SHartmut Brandt static LIST_HEAD(, type) types = LIST_HEAD_INITIALIZER(types);
2366f557cf7SHartmut Brandt
2376f557cf7SHartmut Brandt static void report(const char *, ...) __dead2 __printflike(1, 2);
2386f557cf7SHartmut Brandt static void report_node(const struct node *, const char *, ...)
2396f557cf7SHartmut Brandt __dead2 __printflike(2, 3);
2406f557cf7SHartmut Brandt
241f06ca4afSHartmut Brandt /************************************************************
242f06ca4afSHartmut Brandt *
243f06ca4afSHartmut Brandt * Allocate memory and panic just in the case...
244f06ca4afSHartmut Brandt */
245f06ca4afSHartmut Brandt static void *
xalloc(size_t size)246f06ca4afSHartmut Brandt xalloc(size_t size)
247f06ca4afSHartmut Brandt {
248f06ca4afSHartmut Brandt void *ptr;
249f06ca4afSHartmut Brandt
250*04d17814SAndrey V. Elsukov if ((ptr = calloc(1, size)) == NULL)
251d7eb6b47SHartmut Brandt err(1, "allocing %zu bytes", size);
252f06ca4afSHartmut Brandt
253f06ca4afSHartmut Brandt return (ptr);
254f06ca4afSHartmut Brandt }
255f06ca4afSHartmut Brandt
2566f557cf7SHartmut Brandt static char *
savestr(const char * s)2576f557cf7SHartmut Brandt savestr(const char *s)
2586f557cf7SHartmut Brandt {
2596f557cf7SHartmut Brandt
2606f557cf7SHartmut Brandt if (s == NULL)
2616f557cf7SHartmut Brandt return (NULL);
2626f557cf7SHartmut Brandt return (strcpy(xalloc(strlen(s) + 1), s));
2636f557cf7SHartmut Brandt }
2646f557cf7SHartmut Brandt
2656f557cf7SHartmut Brandt /************************************************************
2666f557cf7SHartmut Brandt *
2676f557cf7SHartmut Brandt * Input stack
2686f557cf7SHartmut Brandt */
2696f557cf7SHartmut Brandt struct input {
2706f557cf7SHartmut Brandt FILE *fp;
2716f557cf7SHartmut Brandt u_int lno;
2726f557cf7SHartmut Brandt char *fname;
2736f557cf7SHartmut Brandt char *path;
2746f557cf7SHartmut Brandt LIST_ENTRY(input) link;
2756f557cf7SHartmut Brandt };
2766f557cf7SHartmut Brandt static LIST_HEAD(, input) inputs = LIST_HEAD_INITIALIZER(inputs);
2776f557cf7SHartmut Brandt static struct input *input = NULL;
2786f557cf7SHartmut Brandt
2796f557cf7SHartmut Brandt #define MAX_PATHS 100
2806f557cf7SHartmut Brandt static u_int npaths = 2;
2816f557cf7SHartmut Brandt static u_int stdpaths = 2;
2826f557cf7SHartmut Brandt static const char *paths[MAX_PATHS + 1] = {
2836f557cf7SHartmut Brandt "/usr/share/snmp/defs",
2846f557cf7SHartmut Brandt "/usr/local/share/snmp/defs",
2856f557cf7SHartmut Brandt NULL
2866f557cf7SHartmut Brandt };
2876f557cf7SHartmut Brandt
2886f557cf7SHartmut Brandt static int pbchar = -1;
2896f557cf7SHartmut Brandt
2906f557cf7SHartmut Brandt static void
path_new(const char * path)2916f557cf7SHartmut Brandt path_new(const char *path)
2926f557cf7SHartmut Brandt {
2936f557cf7SHartmut Brandt if (npaths >= MAX_PATHS)
2946f557cf7SHartmut Brandt report("too many -I directives");
2956f557cf7SHartmut Brandt memmove(&paths[npaths - stdpaths + 1], &paths[npaths - stdpaths],
2966f557cf7SHartmut Brandt sizeof(path[0]) * stdpaths);
2976f557cf7SHartmut Brandt paths[npaths - stdpaths] = savestr(path);
2986f557cf7SHartmut Brandt npaths++;
2996f557cf7SHartmut Brandt }
3006f557cf7SHartmut Brandt
3016f557cf7SHartmut Brandt static void
input_new(FILE * fp,const char * path,const char * fname)3026f557cf7SHartmut Brandt input_new(FILE *fp, const char *path, const char *fname)
3036f557cf7SHartmut Brandt {
3046f557cf7SHartmut Brandt struct input *ip;
3056f557cf7SHartmut Brandt
3066f557cf7SHartmut Brandt ip = xalloc(sizeof(*ip));
3076f557cf7SHartmut Brandt ip->fp = fp;
3086f557cf7SHartmut Brandt ip->lno = 1;
3096f557cf7SHartmut Brandt ip->fname = savestr(fname);
3106f557cf7SHartmut Brandt ip->path = savestr(path);
3116f557cf7SHartmut Brandt LIST_INSERT_HEAD(&inputs, ip, link);
3126f557cf7SHartmut Brandt
3136f557cf7SHartmut Brandt input = ip;
3146f557cf7SHartmut Brandt }
3156f557cf7SHartmut Brandt
3166f557cf7SHartmut Brandt static void
input_close(void)3176f557cf7SHartmut Brandt input_close(void)
3186f557cf7SHartmut Brandt {
3196f557cf7SHartmut Brandt
3206f557cf7SHartmut Brandt if (input == NULL)
3216f557cf7SHartmut Brandt return;
3226f557cf7SHartmut Brandt fclose(input->fp);
3236f557cf7SHartmut Brandt free(input->fname);
3246f557cf7SHartmut Brandt free(input->path);
3256f557cf7SHartmut Brandt LIST_REMOVE(input, link);
3266f557cf7SHartmut Brandt free(input);
3276f557cf7SHartmut Brandt
3286f557cf7SHartmut Brandt input = LIST_FIRST(&inputs);
3296f557cf7SHartmut Brandt }
3306f557cf7SHartmut Brandt
3316f557cf7SHartmut Brandt static FILE *
tryopen(const char * path,const char * fname)3326f557cf7SHartmut Brandt tryopen(const char *path, const char *fname)
3336f557cf7SHartmut Brandt {
3346f557cf7SHartmut Brandt char *fn;
3356f557cf7SHartmut Brandt FILE *fp;
3366f557cf7SHartmut Brandt
3376f557cf7SHartmut Brandt if (path == NULL)
3386f557cf7SHartmut Brandt fn = savestr(fname);
3396f557cf7SHartmut Brandt else {
3406f557cf7SHartmut Brandt fn = xalloc(strlen(path) + strlen(fname) + 2);
3416f557cf7SHartmut Brandt sprintf(fn, "%s/%s", path, fname);
3426f557cf7SHartmut Brandt }
3436f557cf7SHartmut Brandt fp = fopen(fn, "r");
3446f557cf7SHartmut Brandt free(fn);
3456f557cf7SHartmut Brandt return (fp);
3466f557cf7SHartmut Brandt }
3476f557cf7SHartmut Brandt
3486f557cf7SHartmut Brandt static void
input_fopen(const char * fname,int loc)3496f557cf7SHartmut Brandt input_fopen(const char *fname, int loc)
3506f557cf7SHartmut Brandt {
3516f557cf7SHartmut Brandt FILE *fp;
3526f557cf7SHartmut Brandt char *path;
3536f557cf7SHartmut Brandt u_int p;
3546f557cf7SHartmut Brandt
3556f557cf7SHartmut Brandt if (fname[0] == '/') {
3566f557cf7SHartmut Brandt if ((fp = tryopen(NULL, fname)) != NULL) {
3576f557cf7SHartmut Brandt input_new(fp, NULL, fname);
3586f557cf7SHartmut Brandt return;
3596f557cf7SHartmut Brandt }
3606f557cf7SHartmut Brandt
3616f557cf7SHartmut Brandt } else {
3626f557cf7SHartmut Brandt if (loc) {
3636f557cf7SHartmut Brandt if (input == NULL)
3646f557cf7SHartmut Brandt path = NULL;
3656f557cf7SHartmut Brandt else
3666f557cf7SHartmut Brandt path = input->path;
3676f557cf7SHartmut Brandt
3686f557cf7SHartmut Brandt if ((fp = tryopen(path, fname)) != NULL) {
3696f557cf7SHartmut Brandt input_new(fp, NULL, fname);
3706f557cf7SHartmut Brandt return;
3716f557cf7SHartmut Brandt }
3726f557cf7SHartmut Brandt }
3736f557cf7SHartmut Brandt
3746f557cf7SHartmut Brandt for (p = 0; paths[p] != NULL; p++)
3756f557cf7SHartmut Brandt if ((fp = tryopen(paths[p], fname)) != NULL) {
3766f557cf7SHartmut Brandt input_new(fp, paths[p], fname);
3776f557cf7SHartmut Brandt return;
3786f557cf7SHartmut Brandt }
3796f557cf7SHartmut Brandt }
3806f557cf7SHartmut Brandt report("cannot open '%s'", fname);
3816f557cf7SHartmut Brandt }
3826f557cf7SHartmut Brandt
3836f557cf7SHartmut Brandt static int
tgetc(void)3846f557cf7SHartmut Brandt tgetc(void)
3856f557cf7SHartmut Brandt {
3866f557cf7SHartmut Brandt int c;
3876f557cf7SHartmut Brandt
3886f557cf7SHartmut Brandt if (pbchar != -1) {
3896f557cf7SHartmut Brandt c = pbchar;
3906f557cf7SHartmut Brandt pbchar = -1;
3916f557cf7SHartmut Brandt return (c);
3926f557cf7SHartmut Brandt }
3936f557cf7SHartmut Brandt
3946f557cf7SHartmut Brandt for (;;) {
3956f557cf7SHartmut Brandt if (input == NULL)
3966f557cf7SHartmut Brandt return (EOF);
3976f557cf7SHartmut Brandt
3986f557cf7SHartmut Brandt if ((c = getc(input->fp)) != EOF)
3996f557cf7SHartmut Brandt return (c);
4006f557cf7SHartmut Brandt
4016f557cf7SHartmut Brandt input_close();
4026f557cf7SHartmut Brandt }
4036f557cf7SHartmut Brandt }
4046f557cf7SHartmut Brandt
4056f557cf7SHartmut Brandt static void
tungetc(int c)4066f557cf7SHartmut Brandt tungetc(int c)
4076f557cf7SHartmut Brandt {
4086f557cf7SHartmut Brandt
4096f557cf7SHartmut Brandt if (pbchar != -1)
4106f557cf7SHartmut Brandt abort();
4116f557cf7SHartmut Brandt pbchar = c;
4126f557cf7SHartmut Brandt }
4136f557cf7SHartmut Brandt
414f06ca4afSHartmut Brandt /************************************************************
415f06ca4afSHartmut Brandt *
416f06ca4afSHartmut Brandt * Parsing input
417f06ca4afSHartmut Brandt */
418f06ca4afSHartmut Brandt enum tok {
419f06ca4afSHartmut Brandt TOK_EOF = 0200, /* end-of-file seen */
420f06ca4afSHartmut Brandt TOK_NUM, /* number */
421f06ca4afSHartmut Brandt TOK_STR, /* string */
422f06ca4afSHartmut Brandt TOK_ACCESS, /* access operator */
423f06ca4afSHartmut Brandt TOK_TYPE, /* type operator */
4246f557cf7SHartmut Brandt TOK_ENUM, /* enum token (kind of a type) */
4256f557cf7SHartmut Brandt TOK_TYPEDEF, /* typedef directive */
4266f557cf7SHartmut Brandt TOK_DEFTYPE, /* defined type */
4276f557cf7SHartmut Brandt TOK_INCLUDE, /* include directive */
4286f557cf7SHartmut Brandt TOK_FILENAME, /* filename ("foo.bar" or <foo.bar>) */
4296f557cf7SHartmut Brandt TOK_BITS, /* bits token (kind of a type) */
430f06ca4afSHartmut Brandt };
431f06ca4afSHartmut Brandt
432f06ca4afSHartmut Brandt static const struct {
433f06ca4afSHartmut Brandt const char *str;
434f06ca4afSHartmut Brandt enum tok tok;
435f06ca4afSHartmut Brandt u_int val;
436f06ca4afSHartmut Brandt } keywords[] = {
437f06ca4afSHartmut Brandt { "GET", TOK_ACCESS, FL_GET },
438f06ca4afSHartmut Brandt { "SET", TOK_ACCESS, FL_SET },
439f06ca4afSHartmut Brandt { "NULL", TOK_TYPE, SNMP_SYNTAX_NULL },
440f06ca4afSHartmut Brandt { "INTEGER", TOK_TYPE, SNMP_SYNTAX_INTEGER },
441f06ca4afSHartmut Brandt { "INTEGER32", TOK_TYPE, SNMP_SYNTAX_INTEGER },
442f06ca4afSHartmut Brandt { "UNSIGNED32", TOK_TYPE, SNMP_SYNTAX_GAUGE },
443f06ca4afSHartmut Brandt { "OCTETSTRING", TOK_TYPE, SNMP_SYNTAX_OCTETSTRING },
444f06ca4afSHartmut Brandt { "IPADDRESS", TOK_TYPE, SNMP_SYNTAX_IPADDRESS },
445f06ca4afSHartmut Brandt { "OID", TOK_TYPE, SNMP_SYNTAX_OID },
446f06ca4afSHartmut Brandt { "TIMETICKS", TOK_TYPE, SNMP_SYNTAX_TIMETICKS },
447f06ca4afSHartmut Brandt { "COUNTER", TOK_TYPE, SNMP_SYNTAX_COUNTER },
448f06ca4afSHartmut Brandt { "GAUGE", TOK_TYPE, SNMP_SYNTAX_GAUGE },
449f06ca4afSHartmut Brandt { "COUNTER64", TOK_TYPE, SNMP_SYNTAX_COUNTER64 },
4506f557cf7SHartmut Brandt { "ENUM", TOK_ENUM, SNMP_SYNTAX_INTEGER },
4516f557cf7SHartmut Brandt { "BITS", TOK_BITS, SNMP_SYNTAX_OCTETSTRING },
4526f557cf7SHartmut Brandt { "typedef", TOK_TYPEDEF, 0 },
4536f557cf7SHartmut Brandt { "include", TOK_INCLUDE, 0 },
454f06ca4afSHartmut Brandt { NULL, 0, 0 }
455f06ca4afSHartmut Brandt };
456f06ca4afSHartmut Brandt
457f06ca4afSHartmut Brandt /* arbitrary upper limit on node names and function names */
458f06ca4afSHartmut Brandt #define MAXSTR 1000
4598e9b3e70SHartmut Brandt static char str[MAXSTR];
4608e9b3e70SHartmut Brandt static u_long val; /* integer values */
4618e9b3e70SHartmut Brandt static int saved_token = -1;
462f06ca4afSHartmut Brandt
463f06ca4afSHartmut Brandt /*
464f06ca4afSHartmut Brandt * Report an error and exit.
465f06ca4afSHartmut Brandt */
466f06ca4afSHartmut Brandt static void
report(const char * fmt,...)467f06ca4afSHartmut Brandt report(const char *fmt, ...)
468f06ca4afSHartmut Brandt {
469f06ca4afSHartmut Brandt va_list ap;
470f06ca4afSHartmut Brandt int c;
471f06ca4afSHartmut Brandt
472f06ca4afSHartmut Brandt va_start(ap, fmt);
4736f557cf7SHartmut Brandt fprintf(stderr, "line %u: ", input->lno);
474f06ca4afSHartmut Brandt vfprintf(stderr, fmt, ap);
475f06ca4afSHartmut Brandt fprintf(stderr, "\n");
476f06ca4afSHartmut Brandt fprintf(stderr, "context: \"");
4776f557cf7SHartmut Brandt while ((c = tgetc()) != EOF && c != '\n')
478f06ca4afSHartmut Brandt fprintf(stderr, "%c", c);
479f06ca4afSHartmut Brandt fprintf(stderr, "\n");
480f06ca4afSHartmut Brandt va_end(ap);
481f06ca4afSHartmut Brandt exit(1);
482f06ca4afSHartmut Brandt }
483f06ca4afSHartmut Brandt static void
report_node(const struct node * np,const char * fmt,...)484f06ca4afSHartmut Brandt report_node(const struct node *np, const char *fmt, ...)
485f06ca4afSHartmut Brandt {
486f06ca4afSHartmut Brandt va_list ap;
487f06ca4afSHartmut Brandt
488f06ca4afSHartmut Brandt va_start(ap, fmt);
489f06ca4afSHartmut Brandt fprintf(stderr, "line %u, node %s: ", np->lno, np->name);
490f06ca4afSHartmut Brandt vfprintf(stderr, fmt, ap);
491f06ca4afSHartmut Brandt fprintf(stderr, "\n");
492f06ca4afSHartmut Brandt va_end(ap);
493f06ca4afSHartmut Brandt exit(1);
494f06ca4afSHartmut Brandt }
495f06ca4afSHartmut Brandt
496f06ca4afSHartmut Brandt /*
497f06ca4afSHartmut Brandt * Return a fresh copy of the string constituting the current token.
498f06ca4afSHartmut Brandt */
499f06ca4afSHartmut Brandt static char *
savetok(void)500f06ca4afSHartmut Brandt savetok(void)
501f06ca4afSHartmut Brandt {
5026f557cf7SHartmut Brandt return (savestr(str));
503f06ca4afSHartmut Brandt }
504f06ca4afSHartmut Brandt
505f06ca4afSHartmut Brandt /*
506f06ca4afSHartmut Brandt * Get the next token from input.
507f06ca4afSHartmut Brandt */
508f06ca4afSHartmut Brandt static int
gettoken_internal(void)5096f557cf7SHartmut Brandt gettoken_internal(void)
510f06ca4afSHartmut Brandt {
511f06ca4afSHartmut Brandt int c;
5126f557cf7SHartmut Brandt struct type *t;
5136f557cf7SHartmut Brandt
5146f557cf7SHartmut Brandt if (saved_token != -1) {
5156f557cf7SHartmut Brandt c = saved_token;
5166f557cf7SHartmut Brandt saved_token = -1;
5176f557cf7SHartmut Brandt return (c);
5186f557cf7SHartmut Brandt }
519f06ca4afSHartmut Brandt
520f06ca4afSHartmut Brandt again:
521f06ca4afSHartmut Brandt /*
522f06ca4afSHartmut Brandt * Skip any whitespace before the next token
523f06ca4afSHartmut Brandt */
5246f557cf7SHartmut Brandt while ((c = tgetc()) != EOF) {
525f06ca4afSHartmut Brandt if (c == '\n')
5266f557cf7SHartmut Brandt input->lno++;
527f06ca4afSHartmut Brandt if (!isspace(c))
528f06ca4afSHartmut Brandt break;
529f06ca4afSHartmut Brandt }
530f06ca4afSHartmut Brandt if (c == EOF)
531f06ca4afSHartmut Brandt return (TOK_EOF);
532f06ca4afSHartmut Brandt if (!isascii(c))
533f06ca4afSHartmut Brandt report("unexpected character %#2x", (u_int)c);
534f06ca4afSHartmut Brandt
535f06ca4afSHartmut Brandt /*
536f06ca4afSHartmut Brandt * Skip comments
537f06ca4afSHartmut Brandt */
538f06ca4afSHartmut Brandt if (c == '#') {
5396f557cf7SHartmut Brandt while ((c = tgetc()) != EOF) {
540f06ca4afSHartmut Brandt if (c == '\n') {
5416f557cf7SHartmut Brandt input->lno++;
542f06ca4afSHartmut Brandt goto again;
543f06ca4afSHartmut Brandt }
544f06ca4afSHartmut Brandt }
545f06ca4afSHartmut Brandt report("unexpected EOF in comment");
546f06ca4afSHartmut Brandt }
547f06ca4afSHartmut Brandt
548f06ca4afSHartmut Brandt /*
549f06ca4afSHartmut Brandt * Single character tokens
550f06ca4afSHartmut Brandt */
5516f557cf7SHartmut Brandt if (strchr("():|-", c) != NULL)
552f06ca4afSHartmut Brandt return (c);
553f06ca4afSHartmut Brandt
5546f557cf7SHartmut Brandt if (c == '"' || c == '<') {
5556f557cf7SHartmut Brandt int end = c;
5566f557cf7SHartmut Brandt size_t n = 0;
5576f557cf7SHartmut Brandt
5586f557cf7SHartmut Brandt val = 1;
5596f557cf7SHartmut Brandt if (c == '<') {
5606f557cf7SHartmut Brandt val = 0;
5616f557cf7SHartmut Brandt end = '>';
5626f557cf7SHartmut Brandt }
5636f557cf7SHartmut Brandt
5646f557cf7SHartmut Brandt while ((c = tgetc()) != EOF) {
5656f557cf7SHartmut Brandt if (c == end)
5666f557cf7SHartmut Brandt break;
5676f557cf7SHartmut Brandt if (n == sizeof(str) - 1) {
5686f557cf7SHartmut Brandt str[n++] = '\0';
5696f557cf7SHartmut Brandt report("filename too long '%s...'", str);
5706f557cf7SHartmut Brandt }
5716f557cf7SHartmut Brandt str[n++] = c;
5726f557cf7SHartmut Brandt }
5736f557cf7SHartmut Brandt str[n++] = '\0';
5746f557cf7SHartmut Brandt return (TOK_FILENAME);
5756f557cf7SHartmut Brandt }
5766f557cf7SHartmut Brandt
577f06ca4afSHartmut Brandt /*
578f06ca4afSHartmut Brandt * Sort out numbers
579f06ca4afSHartmut Brandt */
580f06ca4afSHartmut Brandt if (isdigit(c)) {
5816f557cf7SHartmut Brandt size_t n = 0;
5826f557cf7SHartmut Brandt str[n++] = c;
5836f557cf7SHartmut Brandt while ((c = tgetc()) != EOF) {
5846f557cf7SHartmut Brandt if (!isdigit(c)) {
5856f557cf7SHartmut Brandt tungetc(c);
5866f557cf7SHartmut Brandt break;
5876f557cf7SHartmut Brandt }
5886f557cf7SHartmut Brandt if (n == sizeof(str) - 1) {
5896f557cf7SHartmut Brandt str[n++] = '\0';
5906f557cf7SHartmut Brandt report("number too long '%s...'", str);
5916f557cf7SHartmut Brandt }
5926f557cf7SHartmut Brandt str[n++] = c;
5936f557cf7SHartmut Brandt }
5946f557cf7SHartmut Brandt str[n++] = '\0';
5956f557cf7SHartmut Brandt sscanf(str, "%lu", &val);
596f06ca4afSHartmut Brandt return (TOK_NUM);
597f06ca4afSHartmut Brandt }
598f06ca4afSHartmut Brandt
599f06ca4afSHartmut Brandt /*
600f06ca4afSHartmut Brandt * So that has to be a string.
601f06ca4afSHartmut Brandt */
602f06ca4afSHartmut Brandt if (isalpha(c) || c == '_') {
603f06ca4afSHartmut Brandt size_t n = 0;
604f06ca4afSHartmut Brandt str[n++] = c;
6056f557cf7SHartmut Brandt while ((c = tgetc()) != EOF) {
6066f557cf7SHartmut Brandt if (!isalnum(c) && c != '_' && c != '-') {
6076f557cf7SHartmut Brandt tungetc(c);
608f06ca4afSHartmut Brandt break;
609f06ca4afSHartmut Brandt }
610f06ca4afSHartmut Brandt if (n == sizeof(str) - 1) {
611f06ca4afSHartmut Brandt str[n++] = '\0';
612f06ca4afSHartmut Brandt report("string too long '%s...'", str);
613f06ca4afSHartmut Brandt }
614f06ca4afSHartmut Brandt str[n++] = c;
615f06ca4afSHartmut Brandt }
616f06ca4afSHartmut Brandt str[n++] = '\0';
617f06ca4afSHartmut Brandt
618f06ca4afSHartmut Brandt /*
619f06ca4afSHartmut Brandt * Keywords
620f06ca4afSHartmut Brandt */
621f06ca4afSHartmut Brandt for (c = 0; keywords[c].str != NULL; c++)
622f06ca4afSHartmut Brandt if (strcmp(keywords[c].str, str) == 0) {
623f06ca4afSHartmut Brandt val = keywords[c].val;
624f06ca4afSHartmut Brandt return (keywords[c].tok);
625f06ca4afSHartmut Brandt }
626f06ca4afSHartmut Brandt
6276f557cf7SHartmut Brandt LIST_FOREACH(t, &types, link) {
6286f557cf7SHartmut Brandt if (strcmp(t->name, str) == 0) {
6296f557cf7SHartmut Brandt val = t->syntax;
6306f557cf7SHartmut Brandt return (TOK_DEFTYPE);
6316f557cf7SHartmut Brandt }
6326f557cf7SHartmut Brandt }
633f06ca4afSHartmut Brandt return (TOK_STR);
634f06ca4afSHartmut Brandt }
635f06ca4afSHartmut Brandt if (isprint(c))
6366f557cf7SHartmut Brandt errx(1, "%u: unexpected character '%c'", input->lno, c);
637f06ca4afSHartmut Brandt else
6386f557cf7SHartmut Brandt errx(1, "%u: unexpected character 0x%02x", input->lno,
6396f557cf7SHartmut Brandt (u_int)c);
6406f557cf7SHartmut Brandt }
6416f557cf7SHartmut Brandt static int
gettoken(void)6426f557cf7SHartmut Brandt gettoken(void)
6436f557cf7SHartmut Brandt {
6446f557cf7SHartmut Brandt int tok = gettoken_internal();
6456f557cf7SHartmut Brandt
6466f557cf7SHartmut Brandt if (debug) {
6476f557cf7SHartmut Brandt switch (tok) {
6486f557cf7SHartmut Brandt
6496f557cf7SHartmut Brandt case TOK_EOF:
6506f557cf7SHartmut Brandt fprintf(stderr, "EOF ");
6516f557cf7SHartmut Brandt break;
6526f557cf7SHartmut Brandt
6536f557cf7SHartmut Brandt case TOK_NUM:
6546f557cf7SHartmut Brandt fprintf(stderr, "NUM(%lu) ", val);
6556f557cf7SHartmut Brandt break;
6566f557cf7SHartmut Brandt
6576f557cf7SHartmut Brandt case TOK_STR:
6586f557cf7SHartmut Brandt fprintf(stderr, "STR(%s) ", str);
6596f557cf7SHartmut Brandt break;
6606f557cf7SHartmut Brandt
6616f557cf7SHartmut Brandt case TOK_ACCESS:
6626f557cf7SHartmut Brandt fprintf(stderr, "ACCESS(%lu) ", val);
6636f557cf7SHartmut Brandt break;
6646f557cf7SHartmut Brandt
6656f557cf7SHartmut Brandt case TOK_TYPE:
6666f557cf7SHartmut Brandt fprintf(stderr, "TYPE(%lu) ", val);
6676f557cf7SHartmut Brandt break;
6686f557cf7SHartmut Brandt
6696f557cf7SHartmut Brandt case TOK_ENUM:
6706f557cf7SHartmut Brandt fprintf(stderr, "ENUM ");
6716f557cf7SHartmut Brandt break;
6726f557cf7SHartmut Brandt
6736f557cf7SHartmut Brandt case TOK_BITS:
6746f557cf7SHartmut Brandt fprintf(stderr, "BITS ");
6756f557cf7SHartmut Brandt break;
6766f557cf7SHartmut Brandt
6776f557cf7SHartmut Brandt case TOK_TYPEDEF:
6786f557cf7SHartmut Brandt fprintf(stderr, "TYPEDEF ");
6796f557cf7SHartmut Brandt break;
6806f557cf7SHartmut Brandt
6816f557cf7SHartmut Brandt case TOK_DEFTYPE:
6826f557cf7SHartmut Brandt fprintf(stderr, "DEFTYPE(%s,%lu) ", str, val);
6836f557cf7SHartmut Brandt break;
6846f557cf7SHartmut Brandt
6856f557cf7SHartmut Brandt case TOK_INCLUDE:
6866f557cf7SHartmut Brandt fprintf(stderr, "INCLUDE ");
6876f557cf7SHartmut Brandt break;
6886f557cf7SHartmut Brandt
6896f557cf7SHartmut Brandt case TOK_FILENAME:
6906f557cf7SHartmut Brandt fprintf(stderr, "FILENAME ");
6916f557cf7SHartmut Brandt break;
6926f557cf7SHartmut Brandt
6936f557cf7SHartmut Brandt default:
6946f557cf7SHartmut Brandt if (tok < TOK_EOF) {
6956f557cf7SHartmut Brandt if (isprint(tok))
6966f557cf7SHartmut Brandt fprintf(stderr, "'%c' ", tok);
6976f557cf7SHartmut Brandt else if (tok == '\n')
6986f557cf7SHartmut Brandt fprintf(stderr, "\n");
6996f557cf7SHartmut Brandt else
7006f557cf7SHartmut Brandt fprintf(stderr, "%02x ", tok);
7016f557cf7SHartmut Brandt } else
7026f557cf7SHartmut Brandt abort();
7036f557cf7SHartmut Brandt break;
7046f557cf7SHartmut Brandt }
7056f557cf7SHartmut Brandt }
7066f557cf7SHartmut Brandt return (tok);
7076f557cf7SHartmut Brandt }
7086f557cf7SHartmut Brandt
7096f557cf7SHartmut Brandt /**
7106f557cf7SHartmut Brandt * Pushback a token
7116f557cf7SHartmut Brandt */
7126f557cf7SHartmut Brandt static void
pushback(enum tok tok)7136f557cf7SHartmut Brandt pushback(enum tok tok)
7146f557cf7SHartmut Brandt {
7156f557cf7SHartmut Brandt
7166f557cf7SHartmut Brandt if (saved_token != -1)
7176f557cf7SHartmut Brandt abort();
7186f557cf7SHartmut Brandt saved_token = tok;
7196f557cf7SHartmut Brandt }
7206f557cf7SHartmut Brandt
7216f557cf7SHartmut Brandt /*
7226f557cf7SHartmut Brandt * Create a new type
7236f557cf7SHartmut Brandt */
7246f557cf7SHartmut Brandt static struct type *
make_type(const char * s)7256f557cf7SHartmut Brandt make_type(const char *s)
7266f557cf7SHartmut Brandt {
7276f557cf7SHartmut Brandt struct type *t;
7286f557cf7SHartmut Brandt
7296f557cf7SHartmut Brandt t = xalloc(sizeof(*t));
7306f557cf7SHartmut Brandt t->name = savestr(s);
7316f557cf7SHartmut Brandt t->is_enum = 0;
7326f557cf7SHartmut Brandt t->syntax = SNMP_SYNTAX_NULL;
7336f557cf7SHartmut Brandt t->from_fname = savestr(input->fname);
7346f557cf7SHartmut Brandt t->from_lno = input->lno;
7356f557cf7SHartmut Brandt TAILQ_INIT(&t->enums);
7366f557cf7SHartmut Brandt LIST_INSERT_HEAD(&types, t, link);
7376f557cf7SHartmut Brandt
7386f557cf7SHartmut Brandt return (t);
7396f557cf7SHartmut Brandt }
7406f557cf7SHartmut Brandt
7416f557cf7SHartmut Brandt /*
7426f557cf7SHartmut Brandt * Parse a type. We've seen the ENUM or type keyword already. Leave next
7436f557cf7SHartmut Brandt * token.
7446f557cf7SHartmut Brandt */
7456f557cf7SHartmut Brandt static u_int
parse_type(enum tok * tok,struct type * t,const char * vname,char ** subtype)746*04d17814SAndrey V. Elsukov parse_type(enum tok *tok, struct type *t, const char *vname, char **subtype)
7476f557cf7SHartmut Brandt {
7486f557cf7SHartmut Brandt u_int syntax;
7496f557cf7SHartmut Brandt struct enums *e;
7506f557cf7SHartmut Brandt
7516f557cf7SHartmut Brandt syntax = val;
752*04d17814SAndrey V. Elsukov if (subtype != NULL)
753*04d17814SAndrey V. Elsukov *subtype = NULL;
7546f557cf7SHartmut Brandt
7556f557cf7SHartmut Brandt if (*tok == TOK_ENUM || *tok == TOK_BITS) {
7566f557cf7SHartmut Brandt if (t == NULL && vname != NULL) {
7576f557cf7SHartmut Brandt t = make_type(vname);
7586f557cf7SHartmut Brandt t->is_enum = (*tok == TOK_ENUM);
7596f557cf7SHartmut Brandt t->is_bits = (*tok == TOK_BITS);
7606f557cf7SHartmut Brandt t->syntax = syntax;
7616f557cf7SHartmut Brandt }
7626f557cf7SHartmut Brandt if (gettoken() != '(')
7636f557cf7SHartmut Brandt report("'(' expected after ENUM");
7646f557cf7SHartmut Brandt
7656f557cf7SHartmut Brandt if ((*tok = gettoken()) == TOK_EOF)
7666f557cf7SHartmut Brandt report("unexpected EOF in ENUM");
7676f557cf7SHartmut Brandt do {
7686f557cf7SHartmut Brandt e = NULL;
7696f557cf7SHartmut Brandt if (t != NULL) {
7706f557cf7SHartmut Brandt e = xalloc(sizeof(*e));
7716f557cf7SHartmut Brandt }
7726f557cf7SHartmut Brandt if (*tok == '-') {
7736f557cf7SHartmut Brandt if ((*tok = gettoken()) == TOK_EOF)
7746f557cf7SHartmut Brandt report("unexpected EOF in ENUM");
7756f557cf7SHartmut Brandt e->value = -(long)val;
7766f557cf7SHartmut Brandt } else
7776f557cf7SHartmut Brandt e->value = val;
7786f557cf7SHartmut Brandt
7796f557cf7SHartmut Brandt if (*tok != TOK_NUM)
7806f557cf7SHartmut Brandt report("need value for ENUM/BITS");
7816f557cf7SHartmut Brandt if (gettoken() != TOK_STR)
7826f557cf7SHartmut Brandt report("need string in ENUM/BITS");
7836f557cf7SHartmut Brandt e->name = savetok();
7846f557cf7SHartmut Brandt TAILQ_INSERT_TAIL(&t->enums, e, link);
7856f557cf7SHartmut Brandt if ((*tok = gettoken()) == TOK_EOF)
7866f557cf7SHartmut Brandt report("unexpected EOF in ENUM/BITS");
7876f557cf7SHartmut Brandt } while (*tok != ')');
7886f557cf7SHartmut Brandt *tok = gettoken();
7896f557cf7SHartmut Brandt
7906f557cf7SHartmut Brandt } else if (*tok == TOK_DEFTYPE) {
7916f557cf7SHartmut Brandt *tok = gettoken();
7926f557cf7SHartmut Brandt
7936f557cf7SHartmut Brandt } else {
7946f557cf7SHartmut Brandt if ((*tok = gettoken()) == '|') {
7956f557cf7SHartmut Brandt if (gettoken() != TOK_STR)
7966f557cf7SHartmut Brandt report("subtype expected after '|'");
797*04d17814SAndrey V. Elsukov if (subtype != NULL)
798*04d17814SAndrey V. Elsukov *subtype = savetok();
7996f557cf7SHartmut Brandt *tok = gettoken();
8006f557cf7SHartmut Brandt }
8016f557cf7SHartmut Brandt }
8026f557cf7SHartmut Brandt
8036f557cf7SHartmut Brandt return (syntax);
804f06ca4afSHartmut Brandt }
805f06ca4afSHartmut Brandt
806f06ca4afSHartmut Brandt /*
807f06ca4afSHartmut Brandt * Parse the next node (complete with all subnodes)
808f06ca4afSHartmut Brandt */
809f06ca4afSHartmut Brandt static struct node *
parse(enum tok tok)810f06ca4afSHartmut Brandt parse(enum tok tok)
811f06ca4afSHartmut Brandt {
812f06ca4afSHartmut Brandt struct node *node;
813f06ca4afSHartmut Brandt struct node *sub;
814f06ca4afSHartmut Brandt u_int index_count;
815f06ca4afSHartmut Brandt
816f06ca4afSHartmut Brandt node = xalloc(sizeof(struct node));
8176f557cf7SHartmut Brandt node->lno = input->lno;
8182a9284a7SHartmut Brandt node->flags = 0;
819f06ca4afSHartmut Brandt
820f06ca4afSHartmut Brandt if (tok != '(')
821f06ca4afSHartmut Brandt report("'(' expected at begin of node");
822f06ca4afSHartmut Brandt if (gettoken() != TOK_NUM)
823f06ca4afSHartmut Brandt report("node id expected after opening '('");
824f06ca4afSHartmut Brandt if (val > ASN_MAXID)
825f06ca4afSHartmut Brandt report("subid too large '%lu'", val);
826f06ca4afSHartmut Brandt node->id = (asn_subid_t)val;
827f06ca4afSHartmut Brandt if (gettoken() != TOK_STR)
828f06ca4afSHartmut Brandt report("node name expected after '(' ID");
829f06ca4afSHartmut Brandt node->name = savetok();
830f06ca4afSHartmut Brandt
8316f557cf7SHartmut Brandt if ((tok = gettoken()) == TOK_TYPE || tok == TOK_DEFTYPE ||
8326f557cf7SHartmut Brandt tok == TOK_ENUM || tok == TOK_BITS) {
833f06ca4afSHartmut Brandt /* LEAF or COLUM */
834*04d17814SAndrey V. Elsukov char *subtype;
835*04d17814SAndrey V. Elsukov u_int syntax = parse_type(&tok, NULL, node->name, &subtype);
836f06ca4afSHartmut Brandt
8376f557cf7SHartmut Brandt if (tok == TOK_STR) {
838f06ca4afSHartmut Brandt /* LEAF */
839f06ca4afSHartmut Brandt node->type = NODE_LEAF;
840f06ca4afSHartmut Brandt node->u.leaf.func = savetok();
841f06ca4afSHartmut Brandt node->u.leaf.syntax = syntax;
842*04d17814SAndrey V. Elsukov node->u.leaf.subtype = subtype;
843f06ca4afSHartmut Brandt tok = gettoken();
844f06ca4afSHartmut Brandt } else {
845f06ca4afSHartmut Brandt /* COLUMN */
846f06ca4afSHartmut Brandt node->type = NODE_COLUMN;
847f06ca4afSHartmut Brandt node->u.column.syntax = syntax;
848*04d17814SAndrey V. Elsukov node->u.column.subtype = subtype;
849f06ca4afSHartmut Brandt }
850f06ca4afSHartmut Brandt
851f06ca4afSHartmut Brandt while (tok != ')') {
852f06ca4afSHartmut Brandt if (tok != TOK_ACCESS)
853f06ca4afSHartmut Brandt report("access keyword or ')' expected");
854f06ca4afSHartmut Brandt node->flags |= (u_int)val;
855f06ca4afSHartmut Brandt tok = gettoken();
856f06ca4afSHartmut Brandt }
857f06ca4afSHartmut Brandt
858f06ca4afSHartmut Brandt } else if (tok == ':') {
859f06ca4afSHartmut Brandt /* ENTRY */
860f06ca4afSHartmut Brandt node->type = NODE_ENTRY;
861f06ca4afSHartmut Brandt TAILQ_INIT(&node->u.entry.subs);
862f06ca4afSHartmut Brandt
863f06ca4afSHartmut Brandt index_count = 0;
864f06ca4afSHartmut Brandt node->u.entry.index = 0;
8656f557cf7SHartmut Brandt tok = gettoken();
8666f557cf7SHartmut Brandt while (tok == TOK_TYPE || tok == TOK_DEFTYPE ||
8676f557cf7SHartmut Brandt tok == TOK_ENUM || tok == TOK_BITS) {
868*04d17814SAndrey V. Elsukov char *subtype;
869*04d17814SAndrey V. Elsukov u_int syntax = parse_type(&tok, NULL, node->name,
870*04d17814SAndrey V. Elsukov &subtype);
871*04d17814SAndrey V. Elsukov if (index_count == SNMP_INDEXES_MAX)
872f06ca4afSHartmut Brandt report("too many table indexes");
873*04d17814SAndrey V. Elsukov node->u.entry.subtypes[index_count++] = subtype;
874f06ca4afSHartmut Brandt node->u.entry.index |=
8756f557cf7SHartmut Brandt syntax << (SNMP_INDEX_SHIFT * index_count);
876f06ca4afSHartmut Brandt }
877f06ca4afSHartmut Brandt node->u.entry.index |= index_count;
878f06ca4afSHartmut Brandt if (index_count == 0)
879f06ca4afSHartmut Brandt report("need at least one index");
880f06ca4afSHartmut Brandt if (tok != TOK_STR)
881f06ca4afSHartmut Brandt report("function name expected");
882f06ca4afSHartmut Brandt
883f06ca4afSHartmut Brandt node->u.entry.func = savetok();
884f06ca4afSHartmut Brandt
885f06ca4afSHartmut Brandt tok = gettoken();
886f06ca4afSHartmut Brandt
887f06ca4afSHartmut Brandt while (tok != ')') {
888f06ca4afSHartmut Brandt sub = parse(tok);
889f06ca4afSHartmut Brandt TAILQ_INSERT_TAIL(&node->u.entry.subs, sub, link);
890f06ca4afSHartmut Brandt tok = gettoken();
891f06ca4afSHartmut Brandt }
892f06ca4afSHartmut Brandt
893f06ca4afSHartmut Brandt } else {
894f06ca4afSHartmut Brandt /* subtree */
895f06ca4afSHartmut Brandt node->type = NODE_TREE;
896f06ca4afSHartmut Brandt TAILQ_INIT(&node->u.tree.subs);
897f06ca4afSHartmut Brandt
898f06ca4afSHartmut Brandt while (tok != ')') {
899f06ca4afSHartmut Brandt sub = parse(tok);
900f06ca4afSHartmut Brandt TAILQ_INSERT_TAIL(&node->u.tree.subs, sub, link);
901f06ca4afSHartmut Brandt tok = gettoken();
902f06ca4afSHartmut Brandt }
903f06ca4afSHartmut Brandt }
904f06ca4afSHartmut Brandt return (node);
905f06ca4afSHartmut Brandt }
906f06ca4afSHartmut Brandt
907f06ca4afSHartmut Brandt /*
9086f557cf7SHartmut Brandt * Parse a top level element. Return the tree if it was a tree, NULL
9096f557cf7SHartmut Brandt * otherwise.
9106f557cf7SHartmut Brandt */
9116f557cf7SHartmut Brandt static struct node *
parse_top(enum tok tok)9126f557cf7SHartmut Brandt parse_top(enum tok tok)
9136f557cf7SHartmut Brandt {
9146f557cf7SHartmut Brandt struct type *t;
9156f557cf7SHartmut Brandt
9166f557cf7SHartmut Brandt if (tok == '(')
9176f557cf7SHartmut Brandt return (parse(tok));
9186f557cf7SHartmut Brandt
9196f557cf7SHartmut Brandt if (tok == TOK_TYPEDEF) {
9206f557cf7SHartmut Brandt if (gettoken() != TOK_STR)
9216f557cf7SHartmut Brandt report("type name expected after typedef");
9226f557cf7SHartmut Brandt
9236f557cf7SHartmut Brandt t = make_type(str);
9246f557cf7SHartmut Brandt
9256f557cf7SHartmut Brandt tok = gettoken();
9266f557cf7SHartmut Brandt t->is_enum = (tok == TOK_ENUM);
9276f557cf7SHartmut Brandt t->is_bits = (tok == TOK_BITS);
928*04d17814SAndrey V. Elsukov
929*04d17814SAndrey V. Elsukov t->syntax = parse_type(&tok, t, NULL, NULL);
9306f557cf7SHartmut Brandt pushback(tok);
9316f557cf7SHartmut Brandt
9326f557cf7SHartmut Brandt return (NULL);
9336f557cf7SHartmut Brandt }
9346f557cf7SHartmut Brandt
9356f557cf7SHartmut Brandt if (tok == TOK_INCLUDE) {
9366f557cf7SHartmut Brandt if (gettoken() != TOK_FILENAME)
9376f557cf7SHartmut Brandt report("filename expected in include directive");
9386f557cf7SHartmut Brandt
9396f557cf7SHartmut Brandt input_fopen(str, val);
9406f557cf7SHartmut Brandt return (NULL);
9416f557cf7SHartmut Brandt }
9426f557cf7SHartmut Brandt
9436f557cf7SHartmut Brandt report("'(' or 'typedef' expected");
9446f557cf7SHartmut Brandt }
9456f557cf7SHartmut Brandt
9466f557cf7SHartmut Brandt /*
947f06ca4afSHartmut Brandt * Generate the C-code table part for one node.
948f06ca4afSHartmut Brandt */
949f06ca4afSHartmut Brandt static void
gen_node(FILE * fp,const struct node * np,struct asn_oid * oid,u_int idx,const char * func)950*04d17814SAndrey V. Elsukov gen_node(FILE *fp, const struct node *np, struct asn_oid *oid, u_int idx,
9516f557cf7SHartmut Brandt const char *func)
952f06ca4afSHartmut Brandt {
953f06ca4afSHartmut Brandt u_int n;
954f06ca4afSHartmut Brandt struct node *sub;
955f06ca4afSHartmut Brandt u_int syntax;
956f06ca4afSHartmut Brandt
957f06ca4afSHartmut Brandt if (oid->len == ASN_MAXOIDLEN)
958f06ca4afSHartmut Brandt report_node(np, "OID too long");
959f06ca4afSHartmut Brandt oid->subs[oid->len++] = np->id;
960f06ca4afSHartmut Brandt
961f06ca4afSHartmut Brandt if (np->type == NODE_TREE) {
962f06ca4afSHartmut Brandt TAILQ_FOREACH(sub, &np->u.tree.subs, link)
9636f557cf7SHartmut Brandt gen_node(fp, sub, oid, 0, NULL);
964f06ca4afSHartmut Brandt oid->len--;
965f06ca4afSHartmut Brandt return;
966f06ca4afSHartmut Brandt }
967f06ca4afSHartmut Brandt if (np->type == NODE_ENTRY) {
968f06ca4afSHartmut Brandt TAILQ_FOREACH(sub, &np->u.entry.subs, link)
9696f557cf7SHartmut Brandt gen_node(fp, sub, oid, np->u.entry.index,
9706f557cf7SHartmut Brandt np->u.entry.func);
971f06ca4afSHartmut Brandt oid->len--;
972f06ca4afSHartmut Brandt return;
973f06ca4afSHartmut Brandt }
974f06ca4afSHartmut Brandt
975f06ca4afSHartmut Brandt /* leaf or column */
976f06ca4afSHartmut Brandt if ((np->flags & (FL_GET|FL_SET)) == 0) {
977f06ca4afSHartmut Brandt oid->len--;
978f06ca4afSHartmut Brandt return;
979f06ca4afSHartmut Brandt }
980f06ca4afSHartmut Brandt
981f06ca4afSHartmut Brandt fprintf(fp, " {{ %u, {", oid->len);
982f06ca4afSHartmut Brandt for (n = 0; n < oid->len; n++)
983f06ca4afSHartmut Brandt fprintf(fp, " %u,", oid->subs[n]);
984f06ca4afSHartmut Brandt fprintf(fp, " }}, \"%s\", ", np->name);
985f06ca4afSHartmut Brandt
986f06ca4afSHartmut Brandt if (np->type == NODE_COLUMN) {
987f06ca4afSHartmut Brandt syntax = np->u.column.syntax;
988f06ca4afSHartmut Brandt fprintf(fp, "SNMP_NODE_COLUMN, ");
989f06ca4afSHartmut Brandt } else {
990f06ca4afSHartmut Brandt syntax = np->u.leaf.syntax;
991f06ca4afSHartmut Brandt fprintf(fp, "SNMP_NODE_LEAF, ");
992f06ca4afSHartmut Brandt }
993f06ca4afSHartmut Brandt
994f06ca4afSHartmut Brandt switch (syntax) {
995f06ca4afSHartmut Brandt
996f06ca4afSHartmut Brandt case SNMP_SYNTAX_NULL:
997f06ca4afSHartmut Brandt fprintf(fp, "SNMP_SYNTAX_NULL, ");
998f06ca4afSHartmut Brandt break;
999f06ca4afSHartmut Brandt
1000f06ca4afSHartmut Brandt case SNMP_SYNTAX_INTEGER:
1001f06ca4afSHartmut Brandt fprintf(fp, "SNMP_SYNTAX_INTEGER, ");
1002f06ca4afSHartmut Brandt break;
1003f06ca4afSHartmut Brandt
1004f06ca4afSHartmut Brandt case SNMP_SYNTAX_OCTETSTRING:
1005f06ca4afSHartmut Brandt fprintf(fp, "SNMP_SYNTAX_OCTETSTRING, ");
1006f06ca4afSHartmut Brandt break;
1007f06ca4afSHartmut Brandt
1008f06ca4afSHartmut Brandt case SNMP_SYNTAX_IPADDRESS:
1009f06ca4afSHartmut Brandt fprintf(fp, "SNMP_SYNTAX_IPADDRESS, ");
1010f06ca4afSHartmut Brandt break;
1011f06ca4afSHartmut Brandt
1012f06ca4afSHartmut Brandt case SNMP_SYNTAX_OID:
1013f06ca4afSHartmut Brandt fprintf(fp, "SNMP_SYNTAX_OID, ");
1014f06ca4afSHartmut Brandt break;
1015f06ca4afSHartmut Brandt
1016f06ca4afSHartmut Brandt case SNMP_SYNTAX_TIMETICKS:
1017f06ca4afSHartmut Brandt fprintf(fp, "SNMP_SYNTAX_TIMETICKS, ");
1018f06ca4afSHartmut Brandt break;
1019f06ca4afSHartmut Brandt
1020f06ca4afSHartmut Brandt case SNMP_SYNTAX_COUNTER:
1021f06ca4afSHartmut Brandt fprintf(fp, "SNMP_SYNTAX_COUNTER, ");
1022f06ca4afSHartmut Brandt break;
1023f06ca4afSHartmut Brandt
1024f06ca4afSHartmut Brandt case SNMP_SYNTAX_GAUGE:
1025f06ca4afSHartmut Brandt fprintf(fp, "SNMP_SYNTAX_GAUGE, ");
1026f06ca4afSHartmut Brandt break;
1027f06ca4afSHartmut Brandt
1028f06ca4afSHartmut Brandt case SNMP_SYNTAX_COUNTER64:
1029f06ca4afSHartmut Brandt fprintf(fp, "SNMP_SYNTAX_COUNTER64, ");
1030f06ca4afSHartmut Brandt break;
1031f06ca4afSHartmut Brandt
1032f06ca4afSHartmut Brandt case SNMP_SYNTAX_NOSUCHOBJECT:
1033f06ca4afSHartmut Brandt case SNMP_SYNTAX_NOSUCHINSTANCE:
1034f06ca4afSHartmut Brandt case SNMP_SYNTAX_ENDOFMIBVIEW:
1035f06ca4afSHartmut Brandt abort();
1036f06ca4afSHartmut Brandt }
1037f06ca4afSHartmut Brandt
1038f06ca4afSHartmut Brandt if (np->type == NODE_COLUMN)
1039f06ca4afSHartmut Brandt fprintf(fp, "%s, ", func);
1040f06ca4afSHartmut Brandt else
1041f06ca4afSHartmut Brandt fprintf(fp, "%s, ", np->u.leaf.func);
1042f06ca4afSHartmut Brandt
1043f06ca4afSHartmut Brandt fprintf(fp, "0");
1044f06ca4afSHartmut Brandt if (np->flags & FL_SET)
1045f06ca4afSHartmut Brandt fprintf(fp, "|SNMP_NODE_CANSET");
10468eecd77aSHartmut Brandt fprintf(fp, ", %#x, NULL, NULL },\n", idx);
1047f06ca4afSHartmut Brandt oid->len--;
1048f06ca4afSHartmut Brandt return;
1049f06ca4afSHartmut Brandt }
1050f06ca4afSHartmut Brandt
1051f06ca4afSHartmut Brandt /*
1052f06ca4afSHartmut Brandt * Generate the header file with the function declarations.
1053f06ca4afSHartmut Brandt */
1054f06ca4afSHartmut Brandt static void
gen_header(FILE * fp,const struct node * np,u_int oidlen,const char * func)1055*04d17814SAndrey V. Elsukov gen_header(FILE *fp, const struct node *np, u_int oidlen, const char *func)
1056f06ca4afSHartmut Brandt {
1057f06ca4afSHartmut Brandt char f[MAXSTR + 4];
1058f06ca4afSHartmut Brandt struct node *sub;
1059f06ca4afSHartmut Brandt struct func *ptr;
1060f06ca4afSHartmut Brandt
1061f06ca4afSHartmut Brandt oidlen++;
1062f06ca4afSHartmut Brandt if (np->type == NODE_TREE) {
1063f06ca4afSHartmut Brandt TAILQ_FOREACH(sub, &np->u.tree.subs, link)
10646f557cf7SHartmut Brandt gen_header(fp, sub, oidlen, NULL);
1065f06ca4afSHartmut Brandt return;
1066f06ca4afSHartmut Brandt }
1067f06ca4afSHartmut Brandt if (np->type == NODE_ENTRY) {
1068f06ca4afSHartmut Brandt TAILQ_FOREACH(sub, &np->u.entry.subs, link)
10696f557cf7SHartmut Brandt gen_header(fp, sub, oidlen, np->u.entry.func);
1070f06ca4afSHartmut Brandt return;
1071f06ca4afSHartmut Brandt }
1072f06ca4afSHartmut Brandt
1073f06ca4afSHartmut Brandt if((np->flags & (FL_GET|FL_SET)) == 0)
1074f06ca4afSHartmut Brandt return;
1075f06ca4afSHartmut Brandt
107694caccb3SHartmut Brandt if (np->type == NODE_COLUMN) {
107794caccb3SHartmut Brandt if (func == NULL)
107894caccb3SHartmut Brandt errx(1, "column without function (%s) - probably "
107994caccb3SHartmut Brandt "outside of a table", np->name);
1080f06ca4afSHartmut Brandt sprintf(f, "%s", func);
108194caccb3SHartmut Brandt } else
1082f06ca4afSHartmut Brandt sprintf(f, "%s", np->u.leaf.func);
1083f06ca4afSHartmut Brandt
1084f06ca4afSHartmut Brandt LIST_FOREACH(ptr, &funcs, link)
1085f06ca4afSHartmut Brandt if (strcmp(ptr->name, f) == 0)
1086f06ca4afSHartmut Brandt break;
1087f06ca4afSHartmut Brandt
1088f06ca4afSHartmut Brandt if (ptr == NULL) {
1089f06ca4afSHartmut Brandt ptr = xalloc(sizeof(*ptr));
10906f557cf7SHartmut Brandt ptr->name = savestr(f);
1091f06ca4afSHartmut Brandt LIST_INSERT_HEAD(&funcs, ptr, link);
1092f06ca4afSHartmut Brandt
1093f06ca4afSHartmut Brandt fprintf(fp, "int %s(struct snmp_context *, "
1094f06ca4afSHartmut Brandt "struct snmp_value *, u_int, u_int, "
1095f06ca4afSHartmut Brandt "enum snmp_op);\n", f);
1096f06ca4afSHartmut Brandt }
1097f06ca4afSHartmut Brandt
1098f06ca4afSHartmut Brandt fprintf(fp, "# define LEAF_%s %u\n", np->name, np->id);
1099f06ca4afSHartmut Brandt }
1100f06ca4afSHartmut Brandt
1101f06ca4afSHartmut Brandt /*
1102f06ca4afSHartmut Brandt * Generate the OID table.
1103f06ca4afSHartmut Brandt */
1104f06ca4afSHartmut Brandt static void
gen_table(FILE * fp,const struct node * node)1105*04d17814SAndrey V. Elsukov gen_table(FILE *fp, const struct node *node)
1106f06ca4afSHartmut Brandt {
1107f06ca4afSHartmut Brandt struct asn_oid oid;
1108f06ca4afSHartmut Brandt
1109f06ca4afSHartmut Brandt fprintf(fp, "#include <sys/types.h>\n");
1110f06ca4afSHartmut Brandt fprintf(fp, "#include <stdio.h>\n");
1111165c5d31SHartmut Brandt #ifdef HAVE_STDINT_H
1112896052c1SHartmut Brandt fprintf(fp, "#include <stdint.h>\n");
1113165c5d31SHartmut Brandt #endif
1114f06ca4afSHartmut Brandt if (localincs) {
1115f06ca4afSHartmut Brandt fprintf(fp, "#include \"asn1.h\"\n");
1116f06ca4afSHartmut Brandt fprintf(fp, "#include \"snmp.h\"\n");
1117f06ca4afSHartmut Brandt fprintf(fp, "#include \"snmpagent.h\"\n");
1118f06ca4afSHartmut Brandt } else {
1119f06ca4afSHartmut Brandt fprintf(fp, "#include <bsnmp/asn1.h>\n");
1120f06ca4afSHartmut Brandt fprintf(fp, "#include <bsnmp/snmp.h>\n");
1121f06ca4afSHartmut Brandt fprintf(fp, "#include <bsnmp/snmpagent.h>\n");
1122f06ca4afSHartmut Brandt }
1123f06ca4afSHartmut Brandt fprintf(fp, "#include \"%stree.h\"\n", file_prefix);
1124f06ca4afSHartmut Brandt fprintf(fp, "\n");
1125f06ca4afSHartmut Brandt
1126f06ca4afSHartmut Brandt fprintf(fp, "const struct snmp_node %sctree[] = {\n", file_prefix);
1127f06ca4afSHartmut Brandt
1128f06ca4afSHartmut Brandt oid.len = PREFIX_LEN;
1129f06ca4afSHartmut Brandt memcpy(oid.subs, prefix, sizeof(prefix));
11306f557cf7SHartmut Brandt gen_node(fp, node, &oid, 0, NULL);
1131f06ca4afSHartmut Brandt
1132f06ca4afSHartmut Brandt fprintf(fp, "};\n\n");
1133f06ca4afSHartmut Brandt }
1134f06ca4afSHartmut Brandt
1135896052c1SHartmut Brandt static void
print_syntax(u_int syntax)1136896052c1SHartmut Brandt print_syntax(u_int syntax)
1137896052c1SHartmut Brandt {
1138896052c1SHartmut Brandt u_int i;
1139896052c1SHartmut Brandt
1140896052c1SHartmut Brandt for (i = 0; keywords[i].str != NULL; i++)
1141896052c1SHartmut Brandt if (keywords[i].tok == TOK_TYPE &&
1142896052c1SHartmut Brandt keywords[i].val == syntax) {
1143896052c1SHartmut Brandt printf(" %s", keywords[i].str);
1144896052c1SHartmut Brandt return;
1145896052c1SHartmut Brandt }
1146896052c1SHartmut Brandt abort();
1147896052c1SHartmut Brandt }
1148896052c1SHartmut Brandt
1149896052c1SHartmut Brandt /*
1150896052c1SHartmut Brandt * Generate a tree definition file
1151896052c1SHartmut Brandt */
1152896052c1SHartmut Brandt static void
gen_tree(const struct node * np,int level)1153896052c1SHartmut Brandt gen_tree(const struct node *np, int level)
1154896052c1SHartmut Brandt {
1155896052c1SHartmut Brandt const struct node *sp;
1156896052c1SHartmut Brandt u_int i;
1157896052c1SHartmut Brandt
1158896052c1SHartmut Brandt printf("%*s(%u %s", 2 * level, "", np->id, np->name);
1159896052c1SHartmut Brandt
1160896052c1SHartmut Brandt switch (np->type) {
1161896052c1SHartmut Brandt
1162896052c1SHartmut Brandt case NODE_LEAF:
1163896052c1SHartmut Brandt print_syntax(np->u.leaf.syntax);
1164*04d17814SAndrey V. Elsukov if (np->u.leaf.subtype != NULL)
1165*04d17814SAndrey V. Elsukov printf(" | %s", np->u.leaf.subtype);
1166896052c1SHartmut Brandt printf(" %s%s%s)\n", np->u.leaf.func,
1167896052c1SHartmut Brandt (np->flags & FL_GET) ? " GET" : "",
1168896052c1SHartmut Brandt (np->flags & FL_SET) ? " SET" : "");
1169896052c1SHartmut Brandt break;
1170896052c1SHartmut Brandt
1171896052c1SHartmut Brandt case NODE_TREE:
1172896052c1SHartmut Brandt if (TAILQ_EMPTY(&np->u.tree.subs)) {
1173896052c1SHartmut Brandt printf(")\n");
1174896052c1SHartmut Brandt } else {
1175896052c1SHartmut Brandt printf("\n");
1176896052c1SHartmut Brandt TAILQ_FOREACH(sp, &np->u.tree.subs, link)
1177896052c1SHartmut Brandt gen_tree(sp, level + 1);
1178896052c1SHartmut Brandt printf("%*s)\n", 2 * level, "");
1179896052c1SHartmut Brandt }
1180896052c1SHartmut Brandt break;
1181896052c1SHartmut Brandt
1182896052c1SHartmut Brandt case NODE_ENTRY:
1183896052c1SHartmut Brandt printf(" :");
1184896052c1SHartmut Brandt
1185*04d17814SAndrey V. Elsukov for (i = 0; i < SNMP_INDEX_COUNT(np->u.entry.index); i++) {
1186896052c1SHartmut Brandt print_syntax(SNMP_INDEX(np->u.entry.index, i));
1187*04d17814SAndrey V. Elsukov if (np->u.entry.subtypes[i] != NULL)
1188*04d17814SAndrey V. Elsukov printf(" | %s", np->u.entry.subtypes[i]);
1189*04d17814SAndrey V. Elsukov }
1190896052c1SHartmut Brandt printf(" %s\n", np->u.entry.func);
1191896052c1SHartmut Brandt TAILQ_FOREACH(sp, &np->u.entry.subs, link)
1192896052c1SHartmut Brandt gen_tree(sp, level + 1);
1193896052c1SHartmut Brandt printf("%*s)\n", 2 * level, "");
1194896052c1SHartmut Brandt break;
1195896052c1SHartmut Brandt
1196896052c1SHartmut Brandt case NODE_COLUMN:
1197896052c1SHartmut Brandt print_syntax(np->u.column.syntax);
1198*04d17814SAndrey V. Elsukov if (np->u.column.subtype != NULL)
1199*04d17814SAndrey V. Elsukov printf(" | %s", np->u.column.subtype);
1200896052c1SHartmut Brandt printf("%s%s)\n", (np->flags & FL_GET) ? " GET" : "",
1201896052c1SHartmut Brandt (np->flags & FL_SET) ? " SET" : "");
1202896052c1SHartmut Brandt break;
1203896052c1SHartmut Brandt }
1204896052c1SHartmut Brandt }
1205896052c1SHartmut Brandt
1206f06ca4afSHartmut Brandt static int
extract(FILE * fp,const struct node * np,struct asn_oid * oid,const char * obj,const struct asn_oid * idx,const char * iname)12076f557cf7SHartmut Brandt extract(FILE *fp, const struct node *np, struct asn_oid *oid, const char *obj,
1208896052c1SHartmut Brandt const struct asn_oid *idx, const char *iname)
1209f06ca4afSHartmut Brandt {
1210f06ca4afSHartmut Brandt struct node *sub;
1211f06ca4afSHartmut Brandt u_long n;
1212f06ca4afSHartmut Brandt
1213f06ca4afSHartmut Brandt if (oid->len == ASN_MAXOIDLEN)
1214f06ca4afSHartmut Brandt report_node(np, "OID too long");
1215f06ca4afSHartmut Brandt oid->subs[oid->len++] = np->id;
1216f06ca4afSHartmut Brandt
1217f06ca4afSHartmut Brandt if (strcmp(obj, np->name) == 0) {
1218896052c1SHartmut Brandt if (oid->len + idx->len >= ASN_MAXOIDLEN)
1219896052c1SHartmut Brandt report_node(np, "OID too long");
1220896052c1SHartmut Brandt fprintf(fp, "#define OID_%s%s\t%u\n", np->name,
1221896052c1SHartmut Brandt iname ? iname : "", np->id);
1222896052c1SHartmut Brandt fprintf(fp, "#define OIDLEN_%s%s\t%u\n", np->name,
1223896052c1SHartmut Brandt iname ? iname : "", oid->len + idx->len);
1224896052c1SHartmut Brandt fprintf(fp, "#define OIDX_%s%s\t{ %u, {", np->name,
1225896052c1SHartmut Brandt iname ? iname : "", oid->len + idx->len);
1226f06ca4afSHartmut Brandt for (n = 0; n < oid->len; n++)
1227f06ca4afSHartmut Brandt fprintf(fp, " %u,", oid->subs[n]);
1228896052c1SHartmut Brandt for (n = 0; n < idx->len; n++)
1229896052c1SHartmut Brandt fprintf(fp, " %u,", idx->subs[n]);
1230f06ca4afSHartmut Brandt fprintf(fp, " } }\n");
1231f06ca4afSHartmut Brandt return (0);
1232f06ca4afSHartmut Brandt }
1233f06ca4afSHartmut Brandt
1234f06ca4afSHartmut Brandt if (np->type == NODE_TREE) {
1235f06ca4afSHartmut Brandt TAILQ_FOREACH(sub, &np->u.tree.subs, link)
12366f557cf7SHartmut Brandt if (!extract(fp, sub, oid, obj, idx, iname))
1237f06ca4afSHartmut Brandt return (0);
1238f06ca4afSHartmut Brandt } else if (np->type == NODE_ENTRY) {
1239f06ca4afSHartmut Brandt TAILQ_FOREACH(sub, &np->u.entry.subs, link)
12406f557cf7SHartmut Brandt if (!extract(fp, sub, oid, obj, idx, iname))
1241f06ca4afSHartmut Brandt return (0);
1242f06ca4afSHartmut Brandt }
1243f06ca4afSHartmut Brandt oid->len--;
1244f06ca4afSHartmut Brandt return (1);
1245f06ca4afSHartmut Brandt }
1246f06ca4afSHartmut Brandt
1247f06ca4afSHartmut Brandt static int
gen_extract(FILE * fp,const struct node * root,char * object)12486f557cf7SHartmut Brandt gen_extract(FILE *fp, const struct node *root, char *object)
1249f06ca4afSHartmut Brandt {
1250f06ca4afSHartmut Brandt struct asn_oid oid;
1251896052c1SHartmut Brandt struct asn_oid idx;
1252896052c1SHartmut Brandt char *s, *e, *end, *iname;
1253896052c1SHartmut Brandt u_long ul;
1254896052c1SHartmut Brandt int ret;
1255896052c1SHartmut Brandt
1256896052c1SHartmut Brandt /* look whether the object to extract has an index part */
1257896052c1SHartmut Brandt idx.len = 0;
1258896052c1SHartmut Brandt iname = NULL;
1259896052c1SHartmut Brandt s = strchr(object, '.');
1260896052c1SHartmut Brandt if (s != NULL) {
1261896052c1SHartmut Brandt iname = malloc(strlen(s) + 1);
1262896052c1SHartmut Brandt if (iname == NULL)
1263896052c1SHartmut Brandt err(1, "cannot allocated index");
1264896052c1SHartmut Brandt
1265896052c1SHartmut Brandt strcpy(iname, s);
1266896052c1SHartmut Brandt for (e = iname; *e != '\0'; e++)
1267896052c1SHartmut Brandt if (*e == '.')
1268896052c1SHartmut Brandt *e = '_';
1269896052c1SHartmut Brandt
1270896052c1SHartmut Brandt *s++ = '\0';
1271896052c1SHartmut Brandt while (s != NULL) {
1272896052c1SHartmut Brandt if (*s == '\0')
1273896052c1SHartmut Brandt errx(1, "bad index syntax");
1274896052c1SHartmut Brandt if ((e = strchr(s, '.')) != NULL)
1275896052c1SHartmut Brandt *e++ = '\0';
1276896052c1SHartmut Brandt
1277896052c1SHartmut Brandt errno = 0;
1278896052c1SHartmut Brandt ul = strtoul(s, &end, 0);
1279896052c1SHartmut Brandt if (*end != '\0')
1280896052c1SHartmut Brandt errx(1, "bad index syntax '%s'", end);
1281896052c1SHartmut Brandt if (errno != 0)
1282896052c1SHartmut Brandt err(1, "bad index syntax");
1283896052c1SHartmut Brandt
1284896052c1SHartmut Brandt if (idx.len == ASN_MAXOIDLEN)
1285896052c1SHartmut Brandt errx(1, "index oid too large");
1286896052c1SHartmut Brandt idx.subs[idx.len++] = ul;
1287896052c1SHartmut Brandt
1288896052c1SHartmut Brandt s = e;
1289896052c1SHartmut Brandt }
1290896052c1SHartmut Brandt }
1291f06ca4afSHartmut Brandt
1292f06ca4afSHartmut Brandt oid.len = PREFIX_LEN;
1293f06ca4afSHartmut Brandt memcpy(oid.subs, prefix, sizeof(prefix));
12946f557cf7SHartmut Brandt ret = extract(fp, root, &oid, object, &idx, iname);
1295896052c1SHartmut Brandt if (iname != NULL)
1296896052c1SHartmut Brandt free(iname);
1297896052c1SHartmut Brandt
1298896052c1SHartmut Brandt return (ret);
1299f06ca4afSHartmut Brandt }
1300f06ca4afSHartmut Brandt
1301f06ca4afSHartmut Brandt
1302f06ca4afSHartmut Brandt static void
check_sub_order(const struct node * np,const struct node_list * subs)1303f06ca4afSHartmut Brandt check_sub_order(const struct node *np, const struct node_list *subs)
1304f06ca4afSHartmut Brandt {
1305f06ca4afSHartmut Brandt int first;
1306f06ca4afSHartmut Brandt const struct node *sub;
1307f06ca4afSHartmut Brandt asn_subid_t maxid = 0;
1308f06ca4afSHartmut Brandt
1309f06ca4afSHartmut Brandt /* ensure, that subids are ordered */
1310f06ca4afSHartmut Brandt first = 1;
1311f06ca4afSHartmut Brandt TAILQ_FOREACH(sub, subs, link) {
1312f06ca4afSHartmut Brandt if (!first && sub->id <= maxid)
1313f06ca4afSHartmut Brandt report_node(np, "subids not ordered at %s", sub->name);
1314f06ca4afSHartmut Brandt maxid = sub->id;
1315f06ca4afSHartmut Brandt first = 0;
1316f06ca4afSHartmut Brandt }
1317f06ca4afSHartmut Brandt }
1318f06ca4afSHartmut Brandt
1319f06ca4afSHartmut Brandt /*
1320f06ca4afSHartmut Brandt * Do some sanity checks on the tree definition and do some computations.
1321f06ca4afSHartmut Brandt */
1322f06ca4afSHartmut Brandt static void
check_tree(struct node * np)1323f06ca4afSHartmut Brandt check_tree(struct node *np)
1324f06ca4afSHartmut Brandt {
1325f06ca4afSHartmut Brandt struct node *sub;
1326f06ca4afSHartmut Brandt
1327f06ca4afSHartmut Brandt if (np->type == NODE_LEAF || np->type == NODE_COLUMN) {
1328f06ca4afSHartmut Brandt if ((np->flags & (FL_GET|FL_SET)) != 0)
1329f06ca4afSHartmut Brandt tree_size++;
1330f06ca4afSHartmut Brandt return;
1331f06ca4afSHartmut Brandt }
1332f06ca4afSHartmut Brandt
1333f06ca4afSHartmut Brandt if (np->type == NODE_ENTRY) {
1334f06ca4afSHartmut Brandt check_sub_order(np, &np->u.entry.subs);
1335f06ca4afSHartmut Brandt
1336f06ca4afSHartmut Brandt /* ensure all subnodes are columns */
1337f06ca4afSHartmut Brandt TAILQ_FOREACH(sub, &np->u.entry.subs, link) {
1338f06ca4afSHartmut Brandt if (sub->type != NODE_COLUMN)
1339f06ca4afSHartmut Brandt report_node(np, "entry subnode '%s' is not "
1340f06ca4afSHartmut Brandt "a column", sub->name);
1341f06ca4afSHartmut Brandt check_tree(sub);
1342f06ca4afSHartmut Brandt }
1343f06ca4afSHartmut Brandt } else {
1344f06ca4afSHartmut Brandt check_sub_order(np, &np->u.tree.subs);
1345f06ca4afSHartmut Brandt
1346f06ca4afSHartmut Brandt TAILQ_FOREACH(sub, &np->u.tree.subs, link)
1347f06ca4afSHartmut Brandt check_tree(sub);
1348f06ca4afSHartmut Brandt }
1349f06ca4afSHartmut Brandt }
1350f06ca4afSHartmut Brandt
1351896052c1SHartmut Brandt static void
merge_subs(struct node_list * s1,struct node_list * s2)1352896052c1SHartmut Brandt merge_subs(struct node_list *s1, struct node_list *s2)
1353896052c1SHartmut Brandt {
1354896052c1SHartmut Brandt struct node *n1, *n2;
1355896052c1SHartmut Brandt
1356896052c1SHartmut Brandt while (!TAILQ_EMPTY(s2)) {
1357896052c1SHartmut Brandt n2 = TAILQ_FIRST(s2);
1358896052c1SHartmut Brandt TAILQ_REMOVE(s2, n2, link);
1359896052c1SHartmut Brandt
1360896052c1SHartmut Brandt TAILQ_FOREACH(n1, s1, link)
1361896052c1SHartmut Brandt if (n1->id >= n2->id)
1362896052c1SHartmut Brandt break;
1363896052c1SHartmut Brandt if (n1 == NULL)
1364896052c1SHartmut Brandt TAILQ_INSERT_TAIL(s1, n2, link);
1365896052c1SHartmut Brandt else if (n1->id > n2->id)
1366896052c1SHartmut Brandt TAILQ_INSERT_BEFORE(n1, n2, link);
1367896052c1SHartmut Brandt else {
1368896052c1SHartmut Brandt if (n1->type == NODE_TREE && n2->type == NODE_TREE) {
1369896052c1SHartmut Brandt if (strcmp(n1->name, n2->name) != 0)
1370896052c1SHartmut Brandt errx(1, "trees to merge must have "
1371896052c1SHartmut Brandt "same name '%s' '%s'", n1->name,
1372896052c1SHartmut Brandt n2->name);
1373896052c1SHartmut Brandt merge_subs(&n1->u.tree.subs, &n2->u.tree.subs);
1374896052c1SHartmut Brandt free(n2);
1375896052c1SHartmut Brandt } else if (n1->type == NODE_ENTRY &&
1376896052c1SHartmut Brandt n2->type == NODE_ENTRY) {
1377896052c1SHartmut Brandt if (strcmp(n1->name, n2->name) != 0)
1378896052c1SHartmut Brandt errx(1, "entries to merge must have "
1379896052c1SHartmut Brandt "same name '%s' '%s'", n1->name,
1380896052c1SHartmut Brandt n2->name);
1381896052c1SHartmut Brandt if (n1->u.entry.index != n2->u.entry.index)
1382896052c1SHartmut Brandt errx(1, "entries to merge must have "
1383896052c1SHartmut Brandt "same index '%s'", n1->name);
1384896052c1SHartmut Brandt if (strcmp(n1->u.entry.func,
1385896052c1SHartmut Brandt n2->u.entry.func) != 0)
1386896052c1SHartmut Brandt errx(1, "entries to merge must have "
1387896052c1SHartmut Brandt "same op '%s'", n1->name);
1388896052c1SHartmut Brandt merge_subs(&n1->u.entry.subs,
1389896052c1SHartmut Brandt &n2->u.entry.subs);
1390896052c1SHartmut Brandt free(n2);
1391896052c1SHartmut Brandt } else
1392896052c1SHartmut Brandt errx(1, "entities to merge must be both "
1393896052c1SHartmut Brandt "trees or both entries: %s, %s",
1394896052c1SHartmut Brandt n1->name, n2->name);
1395896052c1SHartmut Brandt }
1396896052c1SHartmut Brandt }
1397896052c1SHartmut Brandt }
1398896052c1SHartmut Brandt
1399896052c1SHartmut Brandt static void
merge(struct node ** root,struct node * t)14006f557cf7SHartmut Brandt merge(struct node **root, struct node *t)
1401896052c1SHartmut Brandt {
1402896052c1SHartmut Brandt
14036f557cf7SHartmut Brandt if (*root == NULL) {
14046f557cf7SHartmut Brandt *root = t;
14056f557cf7SHartmut Brandt return;
14066f557cf7SHartmut Brandt }
14076f557cf7SHartmut Brandt if (t == NULL)
14086f557cf7SHartmut Brandt return;
14096f557cf7SHartmut Brandt
1410896052c1SHartmut Brandt /* both must be trees */
14116f557cf7SHartmut Brandt if ((*root)->type != NODE_TREE)
1412896052c1SHartmut Brandt errx(1, "root is not a tree");
1413896052c1SHartmut Brandt if (t->type != NODE_TREE)
1414896052c1SHartmut Brandt errx(1, "can merge only with tree");
14156f557cf7SHartmut Brandt if ((*root)->id != t->id)
1416896052c1SHartmut Brandt errx(1, "trees to merge must have same id");
1417896052c1SHartmut Brandt
14186f557cf7SHartmut Brandt merge_subs(&(*root)->u.tree.subs, &t->u.tree.subs);
14196f557cf7SHartmut Brandt }
14206f557cf7SHartmut Brandt
14216f557cf7SHartmut Brandt static void
unminus(FILE * fp,const char * s)14226f557cf7SHartmut Brandt unminus(FILE *fp, const char *s)
14236f557cf7SHartmut Brandt {
14246f557cf7SHartmut Brandt
14256f557cf7SHartmut Brandt while (*s != '\0') {
14266f557cf7SHartmut Brandt if (*s == '-')
14276f557cf7SHartmut Brandt fprintf(fp, "_");
14286f557cf7SHartmut Brandt else
14296f557cf7SHartmut Brandt fprintf(fp, "%c", *s);
14306f557cf7SHartmut Brandt s++;
14316f557cf7SHartmut Brandt }
14326f557cf7SHartmut Brandt }
14336f557cf7SHartmut Brandt
14348e9b3e70SHartmut Brandt /**
14358e9b3e70SHartmut Brandt * Generate helper functions for an enum.
14368e9b3e70SHartmut Brandt *
14378e9b3e70SHartmut Brandt * We always generate a switch statement for the isok function. The compiler
14388e9b3e70SHartmut Brandt * optimizes this into range checks if possible.
14398e9b3e70SHartmut Brandt *
14408e9b3e70SHartmut Brandt * \param fp file to write to
14418e9b3e70SHartmut Brandt * \param t type
14428e9b3e70SHartmut Brandt * \param ccode generate externally visible non-inline functions
14438e9b3e70SHartmut Brandt */
14446f557cf7SHartmut Brandt static void
gen_enum_funcs(FILE * fp,const struct type * t,int ccode)14458e9b3e70SHartmut Brandt gen_enum_funcs(FILE *fp, const struct type *t, int ccode)
14468e9b3e70SHartmut Brandt {
14478e9b3e70SHartmut Brandt fprintf(fp, "\n");
14488e9b3e70SHartmut Brandt
14498e9b3e70SHartmut Brandt if (!ccode)
14508e9b3e70SHartmut Brandt fprintf(fp, "static inline ");
14518e9b3e70SHartmut Brandt fprintf(fp, "int\n");
14528e9b3e70SHartmut Brandt fprintf(fp, "isok_%s(enum %s s)\n", t->name, t->name);
14538e9b3e70SHartmut Brandt fprintf(fp, "{\n");
14548e9b3e70SHartmut Brandt fprintf(fp, " switch (s) {\n");
14558e9b3e70SHartmut Brandt
14568e9b3e70SHartmut Brandt const struct enums *e;
14578e9b3e70SHartmut Brandt TAILQ_FOREACH(e, &t->enums, link) {
14588e9b3e70SHartmut Brandt fprintf(fp, "\t case %s_", t->name);
14598e9b3e70SHartmut Brandt unminus(fp, e->name);
14608e9b3e70SHartmut Brandt fprintf(fp, ":\n");
14618e9b3e70SHartmut Brandt }
14628e9b3e70SHartmut Brandt
14638e9b3e70SHartmut Brandt fprintf(fp, " return (1);\n");
14648e9b3e70SHartmut Brandt fprintf(fp, " }\n");
14658e9b3e70SHartmut Brandt fprintf(fp, " return (0);\n");
14668e9b3e70SHartmut Brandt fprintf(fp, "}\n\n");
14678e9b3e70SHartmut Brandt
14688e9b3e70SHartmut Brandt if (!ccode)
14698e9b3e70SHartmut Brandt fprintf(fp, "static inline ");
14708e9b3e70SHartmut Brandt fprintf(fp, "const char *\n");
14718e9b3e70SHartmut Brandt fprintf(fp, "tostr_%s(enum %s s)\n", t->name, t->name);
14728e9b3e70SHartmut Brandt fprintf(fp, "{\n");
14738e9b3e70SHartmut Brandt fprintf(fp, " static const char *vals[] = { STRING_%s };\n", t->name);
14748e9b3e70SHartmut Brandt fprintf(fp, "\n");
14758e9b3e70SHartmut Brandt fprintf(fp, " if (isok_%s(s))\n", t->name);
14768e9b3e70SHartmut Brandt fprintf(fp, " return (vals[(int)s - STROFF_%s]);\n", t->name);
14778e9b3e70SHartmut Brandt fprintf(fp, " return (\"%s???\");\n", t->name);
14788e9b3e70SHartmut Brandt fprintf(fp, "}\n\n");
14798e9b3e70SHartmut Brandt
14808e9b3e70SHartmut Brandt if (!ccode)
14818e9b3e70SHartmut Brandt fprintf(fp, "static inline ");
14828e9b3e70SHartmut Brandt fprintf(fp, "int\n");
14838e9b3e70SHartmut Brandt fprintf(fp, "fromstr_%s(const char *str, enum %s *s)\n",
14848e9b3e70SHartmut Brandt t->name, t->name);
14858e9b3e70SHartmut Brandt fprintf(fp, "{\n");
14868e9b3e70SHartmut Brandt fprintf(fp, " static const char *vals[] = { STRING_%s };\n", t->name);
14878e9b3e70SHartmut Brandt fprintf(fp, "\n");
14888e9b3e70SHartmut Brandt fprintf(fp, " for (size_t i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) {\n");
14898e9b3e70SHartmut Brandt fprintf(fp, " if (vals[i] != NULL && strcmp(vals[i], str) == 0) {\n");
14908e9b3e70SHartmut Brandt fprintf(fp, " *s = i + STROFF_%s;\n", t->name);
14918e9b3e70SHartmut Brandt fprintf(fp, " return (1);\n");
14928e9b3e70SHartmut Brandt fprintf(fp, " }\n");
14938e9b3e70SHartmut Brandt fprintf(fp, " }\n");
14948e9b3e70SHartmut Brandt fprintf(fp, " return (0);\n");
14958e9b3e70SHartmut Brandt fprintf(fp, "}\n");
14968e9b3e70SHartmut Brandt }
14978e9b3e70SHartmut Brandt
14988e9b3e70SHartmut Brandt /**
1499*04d17814SAndrey V. Elsukov * Generate a definition for the enum packed into a guard against multiple
1500*04d17814SAndrey V. Elsukov * definitions.
1501*04d17814SAndrey V. Elsukov *
1502*04d17814SAndrey V. Elsukov * \param fp file to write definition to
1503*04d17814SAndrey V. Elsukov * \param t type
1504*04d17814SAndrey V. Elsukov * \param dof generate functions too
1505*04d17814SAndrey V. Elsukov */
1506*04d17814SAndrey V. Elsukov static void
gen_enum(FILE * fp,const struct type * t,int dof)1507*04d17814SAndrey V. Elsukov gen_enum(FILE *fp, const struct type *t, int dof)
1508*04d17814SAndrey V. Elsukov {
1509*04d17814SAndrey V. Elsukov const struct enums *e;
1510*04d17814SAndrey V. Elsukov long min = LONG_MAX;
1511*04d17814SAndrey V. Elsukov
1512*04d17814SAndrey V. Elsukov fprintf(fp, "\n");
1513*04d17814SAndrey V. Elsukov fprintf(fp, "#ifndef %s_defined__\n", t->name);
1514*04d17814SAndrey V. Elsukov fprintf(fp, "#define %s_defined__\n", t->name);
1515*04d17814SAndrey V. Elsukov fprintf(fp, "/*\n");
1516*04d17814SAndrey V. Elsukov fprintf(fp, " * From %s:%u\n", t->from_fname, t->from_lno);
1517*04d17814SAndrey V. Elsukov fprintf(fp, " */\n");
1518*04d17814SAndrey V. Elsukov fprintf(fp, "enum %s {\n", t->name);
1519*04d17814SAndrey V. Elsukov TAILQ_FOREACH(e, &t->enums, link) {
1520*04d17814SAndrey V. Elsukov fprintf(fp, "\t%s_", t->name);
1521*04d17814SAndrey V. Elsukov unminus(fp, e->name);
1522*04d17814SAndrey V. Elsukov fprintf(fp, " = %ld,\n", e->value);
1523*04d17814SAndrey V. Elsukov if (e->value < min)
1524*04d17814SAndrey V. Elsukov min = e->value;
1525*04d17814SAndrey V. Elsukov }
1526*04d17814SAndrey V. Elsukov fprintf(fp, "};\n");
1527*04d17814SAndrey V. Elsukov fprintf(fp, "#define STROFF_%s %ld\n", t->name, min);
1528*04d17814SAndrey V. Elsukov fprintf(fp, "#define STRING_%s \\\n", t->name);
1529*04d17814SAndrey V. Elsukov TAILQ_FOREACH(e, &t->enums, link) {
1530*04d17814SAndrey V. Elsukov fprintf(fp, "\t[%ld] = \"%s_", e->value - min, t->name);
1531*04d17814SAndrey V. Elsukov unminus(fp, e->name);
1532*04d17814SAndrey V. Elsukov fprintf(fp, "\",\\\n");
1533*04d17814SAndrey V. Elsukov }
1534*04d17814SAndrey V. Elsukov fprintf(fp, "\n");
1535*04d17814SAndrey V. Elsukov if (dof) {
1536*04d17814SAndrey V. Elsukov fprintf(fp, "#ifdef SNMPENUM_FUNCS\n");
1537*04d17814SAndrey V. Elsukov fprintf(fp, "\n");
1538*04d17814SAndrey V. Elsukov gen_enum_funcs(fp, t, 0);
1539*04d17814SAndrey V. Elsukov fprintf(fp, "\n");
1540*04d17814SAndrey V. Elsukov fprintf(fp, "#endif\n");
1541*04d17814SAndrey V. Elsukov fprintf(fp, "\n");
1542*04d17814SAndrey V. Elsukov }
1543*04d17814SAndrey V. Elsukov fprintf(fp, "#endif /* %s_defined__ */\n", t->name);
1544*04d17814SAndrey V. Elsukov }
1545*04d17814SAndrey V. Elsukov
1546*04d17814SAndrey V. Elsukov /**
15478e9b3e70SHartmut Brandt * Generate helper functions for an enum. This generates code for a c file.
15488e9b3e70SHartmut Brandt *
15498e9b3e70SHartmut Brandt * \param fp file to write to
15508e9b3e70SHartmut Brandt * \param name enum name
15518e9b3e70SHartmut Brandt */
15528e9b3e70SHartmut Brandt static int
gen_enum_funcs_str(FILE * fp,const char * name)15538e9b3e70SHartmut Brandt gen_enum_funcs_str(FILE *fp, const char *name)
15548e9b3e70SHartmut Brandt {
15558e9b3e70SHartmut Brandt const struct type *t;
15568e9b3e70SHartmut Brandt
15578e9b3e70SHartmut Brandt LIST_FOREACH(t, &types, link)
15588e9b3e70SHartmut Brandt if ((t->is_enum || t->is_bits) && strcmp(t->name, name) == 0) {
15598e9b3e70SHartmut Brandt gen_enum_funcs(fp, t, 1);
15608e9b3e70SHartmut Brandt return (0);
15618e9b3e70SHartmut Brandt }
15628e9b3e70SHartmut Brandt
15638e9b3e70SHartmut Brandt return (-1);
15648e9b3e70SHartmut Brandt }
15658e9b3e70SHartmut Brandt
15668e9b3e70SHartmut Brandt /**
15678e9b3e70SHartmut Brandt * Generate helper functions for all enums.
15688e9b3e70SHartmut Brandt *
15698e9b3e70SHartmut Brandt * \param fp file to write to
15708e9b3e70SHartmut Brandt * \param ccode generate externally visible non-inline functions
15718e9b3e70SHartmut Brandt */
15728e9b3e70SHartmut Brandt static void
gen_all_enum_funcs(FILE * fp,int ccode)15738e9b3e70SHartmut Brandt gen_all_enum_funcs(FILE *fp, int ccode)
15746f557cf7SHartmut Brandt {
15756f557cf7SHartmut Brandt const struct type *t;
15766f557cf7SHartmut Brandt
15776f557cf7SHartmut Brandt LIST_FOREACH(t, &types, link)
15786f557cf7SHartmut Brandt if (t->is_enum || t->is_bits)
15798e9b3e70SHartmut Brandt gen_enum_funcs(fp, t, ccode);
15806f557cf7SHartmut Brandt }
15816f557cf7SHartmut Brandt
1582*04d17814SAndrey V. Elsukov static void
gen_enums(FILE * fp,int dof)1583*04d17814SAndrey V. Elsukov gen_enums(FILE *fp, int dof)
1584*04d17814SAndrey V. Elsukov {
1585*04d17814SAndrey V. Elsukov const struct type *t;
1586*04d17814SAndrey V. Elsukov
1587*04d17814SAndrey V. Elsukov LIST_FOREACH(t, &types, link)
1588*04d17814SAndrey V. Elsukov if (t->is_enum || t->is_bits)
1589*04d17814SAndrey V. Elsukov gen_enum(fp, t, dof);
1590*04d17814SAndrey V. Elsukov }
1591*04d17814SAndrey V. Elsukov
15928e9b3e70SHartmut Brandt /**
15938e9b3e70SHartmut Brandt * Extract a given enum to the specified file and optionally generate static
15948e9b3e70SHartmut Brandt * inline helper functions for them.
15958e9b3e70SHartmut Brandt *
15968e9b3e70SHartmut Brandt * \param fp file to print on
15978e9b3e70SHartmut Brandt * \param name name of the enum
15988e9b3e70SHartmut Brandt * \param gen_funcs generate the functions too
15998e9b3e70SHartmut Brandt *
16008e9b3e70SHartmut Brandt * \return 0 if found, -1 otherwise
16018e9b3e70SHartmut Brandt */
16026f557cf7SHartmut Brandt static int
extract_enum(FILE * fp,const char * name,int gen_funcs)16038e9b3e70SHartmut Brandt extract_enum(FILE *fp, const char *name, int gen_funcs)
16046f557cf7SHartmut Brandt {
16056f557cf7SHartmut Brandt const struct type *t;
16066f557cf7SHartmut Brandt
16076f557cf7SHartmut Brandt LIST_FOREACH(t, &types, link)
16086f557cf7SHartmut Brandt if ((t->is_enum || t->is_bits) && strcmp(t->name, name) == 0) {
1609*04d17814SAndrey V. Elsukov gen_enum(fp, t, gen_funcs);
16106f557cf7SHartmut Brandt return (0);
16116f557cf7SHartmut Brandt }
16126f557cf7SHartmut Brandt return (-1);
1613896052c1SHartmut Brandt }
1614896052c1SHartmut Brandt
16158e9b3e70SHartmut Brandt /**
16168e9b3e70SHartmut Brandt * Extract all enums to the given file and optionally generate static inline
16178e9b3e70SHartmut Brandt * helper functions for them.
16188e9b3e70SHartmut Brandt *
16198e9b3e70SHartmut Brandt * \param fp file to print on
16208e9b3e70SHartmut Brandt * \param gen_funcs generate the functions too
16218e9b3e70SHartmut Brandt */
16228e9b3e70SHartmut Brandt static void
extract_all_enums(FILE * fp,int gen_funcs)16238e9b3e70SHartmut Brandt extract_all_enums(FILE *fp, int gen_funcs)
16248e9b3e70SHartmut Brandt {
16258e9b3e70SHartmut Brandt const struct type *t;
16268e9b3e70SHartmut Brandt
16278e9b3e70SHartmut Brandt LIST_FOREACH(t, &types, link)
1628*04d17814SAndrey V. Elsukov if (t->is_enum || t->is_bits)
1629*04d17814SAndrey V. Elsukov gen_enum(fp, t, gen_funcs);
16308e9b3e70SHartmut Brandt }
16318e9b3e70SHartmut Brandt
16328e9b3e70SHartmut Brandt /**
16338e9b3e70SHartmut Brandt * Extract enums and optionally generate some helper functions for them.
16348e9b3e70SHartmut Brandt *
16358e9b3e70SHartmut Brandt * \param argc number of arguments
16368e9b3e70SHartmut Brandt * \param argv arguments (enum names)
1637*04d17814SAndrey V. Elsukov * \param gen_funcs which functions to generate
16388e9b3e70SHartmut Brandt */
16398e9b3e70SHartmut Brandt static void
make_enums(int argc,char * argv[],enum gen_funcs gen_funcs)1640*04d17814SAndrey V. Elsukov make_enums(int argc, char *argv[], enum gen_funcs gen_funcs)
16418e9b3e70SHartmut Brandt {
1642*04d17814SAndrey V. Elsukov if (gen_funcs == GEN_FUNCS_C) {
16438e9b3e70SHartmut Brandt if (argc == 0)
16448e9b3e70SHartmut Brandt gen_all_enum_funcs(stdout, 1);
16458e9b3e70SHartmut Brandt else {
16468e9b3e70SHartmut Brandt for (int i = 0; i < argc; i++)
16478e9b3e70SHartmut Brandt if (gen_enum_funcs_str(stdout, argv[i]))
16488e9b3e70SHartmut Brandt errx(1, "enum not found: %s", argv[i]);
16498e9b3e70SHartmut Brandt }
16508e9b3e70SHartmut Brandt } else {
16518e9b3e70SHartmut Brandt if (argc == 0)
1652*04d17814SAndrey V. Elsukov extract_all_enums(stdout, gen_funcs == GEN_FUNCS_H);
16538e9b3e70SHartmut Brandt else {
16548e9b3e70SHartmut Brandt for (int i = 0; i < argc; i++)
1655*04d17814SAndrey V. Elsukov if (extract_enum(stdout, argv[i],
1656*04d17814SAndrey V. Elsukov gen_funcs == GEN_FUNCS_H))
16578e9b3e70SHartmut Brandt errx(1, "enum not found: %s", argv[i]);
16588e9b3e70SHartmut Brandt }
16598e9b3e70SHartmut Brandt }
16608e9b3e70SHartmut Brandt }
16618e9b3e70SHartmut Brandt
1662*04d17814SAndrey V. Elsukov /**
1663*04d17814SAndrey V. Elsukov * Produce the operation tables for the daemon or a module.
1664*04d17814SAndrey V. Elsukov *
1665*04d17814SAndrey V. Elsukov * \param root tree root
1666*04d17814SAndrey V. Elsukov * \param gen_funcs generate enum funcs
1667*04d17814SAndrey V. Elsukov */
1668*04d17814SAndrey V. Elsukov static void
make_table(const struct node * root,int gen_funcs)1669*04d17814SAndrey V. Elsukov make_table(const struct node *root, int gen_funcs)
1670*04d17814SAndrey V. Elsukov {
1671*04d17814SAndrey V. Elsukov FILE *fp;
1672*04d17814SAndrey V. Elsukov
1673*04d17814SAndrey V. Elsukov char fname[MAXPATHLEN + 1];
1674*04d17814SAndrey V. Elsukov sprintf(fname, "%stree.h", file_prefix);
1675*04d17814SAndrey V. Elsukov if ((fp = fopen(fname, "w")) == NULL)
1676*04d17814SAndrey V. Elsukov err(1, "%s: ", fname);
1677*04d17814SAndrey V. Elsukov gen_header(fp, root, PREFIX_LEN, NULL);
1678*04d17814SAndrey V. Elsukov
1679*04d17814SAndrey V. Elsukov fprintf(fp, "\n#ifdef SNMPTREE_TYPES\n");
1680*04d17814SAndrey V. Elsukov gen_enums(fp, gen_funcs);
1681*04d17814SAndrey V. Elsukov fprintf(fp, "\n#endif /* SNMPTREE_TYPES */\n\n");
1682*04d17814SAndrey V. Elsukov
1683*04d17814SAndrey V. Elsukov fprintf(fp, "#define %sCTREE_SIZE %u\n", file_prefix, tree_size);
1684*04d17814SAndrey V. Elsukov fprintf(fp, "extern const struct snmp_node %sctree[];\n", file_prefix);
1685*04d17814SAndrey V. Elsukov
1686*04d17814SAndrey V. Elsukov fclose(fp);
1687*04d17814SAndrey V. Elsukov
1688*04d17814SAndrey V. Elsukov sprintf(fname, "%stree.c", file_prefix);
1689*04d17814SAndrey V. Elsukov if ((fp = fopen(fname, "w")) == NULL)
1690*04d17814SAndrey V. Elsukov err(1, "%s: ", fname);
1691*04d17814SAndrey V. Elsukov gen_table(fp, root);
1692*04d17814SAndrey V. Elsukov fclose(fp);
1693*04d17814SAndrey V. Elsukov }
1694*04d17814SAndrey V. Elsukov
1695f06ca4afSHartmut Brandt int
main(int argc,char * argv[])1696f06ca4afSHartmut Brandt main(int argc, char *argv[])
1697f06ca4afSHartmut Brandt {
1698*04d17814SAndrey V. Elsukov enum op op = OP_GEN;
1699*04d17814SAndrey V. Elsukov enum gen_funcs gen_funcs = GEN_FUNCS_NONE;
1700*04d17814SAndrey V. Elsukov
17016f557cf7SHartmut Brandt char *infile = NULL;
1702f06ca4afSHartmut Brandt
1703*04d17814SAndrey V. Elsukov int opt;
17048e9b3e70SHartmut Brandt while ((opt = getopt(argc, argv, "dEeFfhI:i:lp:t")) != EOF)
1705f06ca4afSHartmut Brandt switch (opt) {
1706f06ca4afSHartmut Brandt
17076f557cf7SHartmut Brandt case 'd':
17086f557cf7SHartmut Brandt debug = 1;
17096f557cf7SHartmut Brandt break;
17106f557cf7SHartmut Brandt
17116f557cf7SHartmut Brandt case 'E':
1712*04d17814SAndrey V. Elsukov if (op != OP_GEN && op != OP_ENUMS)
1713*04d17814SAndrey V. Elsukov errx(1, "-E conflicts with earlier options");
1714*04d17814SAndrey V. Elsukov op = OP_ENUMS;
17156f557cf7SHartmut Brandt break;
17166f557cf7SHartmut Brandt
1717f06ca4afSHartmut Brandt case 'e':
1718*04d17814SAndrey V. Elsukov if (op != OP_GEN && op != OP_EXTRACT)
1719*04d17814SAndrey V. Elsukov errx(1, "-e conflicts with earlier options");
1720*04d17814SAndrey V. Elsukov op = OP_EXTRACT;
1721f06ca4afSHartmut Brandt break;
1722f06ca4afSHartmut Brandt
17238e9b3e70SHartmut Brandt case 'F':
1724*04d17814SAndrey V. Elsukov if (gen_funcs != GEN_FUNCS_NONE &&
1725*04d17814SAndrey V. Elsukov gen_funcs != GEN_FUNCS_C)
1726*04d17814SAndrey V. Elsukov errx(1, "-F conflicts with -f");
1727*04d17814SAndrey V. Elsukov gen_funcs = GEN_FUNCS_C;
17288e9b3e70SHartmut Brandt break;
17298e9b3e70SHartmut Brandt
17308e9b3e70SHartmut Brandt case 'f':
1731*04d17814SAndrey V. Elsukov if (gen_funcs != GEN_FUNCS_NONE &&
1732*04d17814SAndrey V. Elsukov gen_funcs != GEN_FUNCS_H)
1733*04d17814SAndrey V. Elsukov errx(1, "-f conflicts with -F");
1734*04d17814SAndrey V. Elsukov gen_funcs = GEN_FUNCS_H;
17358e9b3e70SHartmut Brandt break;
17368e9b3e70SHartmut Brandt
17378e9b3e70SHartmut Brandt case 'h':
17388e9b3e70SHartmut Brandt fprintf(stderr, "%s", usgtxt);
17398e9b3e70SHartmut Brandt exit(0);
17408e9b3e70SHartmut Brandt
17416f557cf7SHartmut Brandt case 'I':
17426f557cf7SHartmut Brandt path_new(optarg);
17436f557cf7SHartmut Brandt break;
17446f557cf7SHartmut Brandt
17456f557cf7SHartmut Brandt case 'i':
17466f557cf7SHartmut Brandt infile = optarg;
17476f557cf7SHartmut Brandt break;
17486f557cf7SHartmut Brandt
1749f06ca4afSHartmut Brandt case 'l':
1750f06ca4afSHartmut Brandt localincs = 1;
1751f06ca4afSHartmut Brandt break;
1752f06ca4afSHartmut Brandt
1753f06ca4afSHartmut Brandt case 'p':
1754f06ca4afSHartmut Brandt file_prefix = optarg;
1755f06ca4afSHartmut Brandt if (strlen(file_prefix) + strlen("tree.c") >
1756f06ca4afSHartmut Brandt MAXPATHLEN)
1757f06ca4afSHartmut Brandt errx(1, "prefix too long");
1758f06ca4afSHartmut Brandt break;
1759896052c1SHartmut Brandt
1760896052c1SHartmut Brandt case 't':
1761*04d17814SAndrey V. Elsukov if (op != OP_GEN && op != OP_TREE)
1762*04d17814SAndrey V. Elsukov errx(1, "-t conflicts with earlier options");
1763*04d17814SAndrey V. Elsukov op = OP_TREE;
1764896052c1SHartmut Brandt break;
1765f06ca4afSHartmut Brandt }
1766f06ca4afSHartmut Brandt
1767*04d17814SAndrey V. Elsukov argc -= optind;
1768*04d17814SAndrey V. Elsukov argv += optind;
1769f06ca4afSHartmut Brandt
1770*04d17814SAndrey V. Elsukov /* open input */
17716f557cf7SHartmut Brandt if (infile == NULL) {
17726f557cf7SHartmut Brandt input_new(stdin, NULL, "<stdin>");
17736f557cf7SHartmut Brandt } else {
1774*04d17814SAndrey V. Elsukov FILE *fp;
17756f557cf7SHartmut Brandt if ((fp = fopen(infile, "r")) == NULL)
17766f557cf7SHartmut Brandt err(1, "%s", infile);
17776f557cf7SHartmut Brandt input_new(fp, NULL, infile);
17786f557cf7SHartmut Brandt }
17796f557cf7SHartmut Brandt
1780*04d17814SAndrey V. Elsukov /* parse and check input */
1781*04d17814SAndrey V. Elsukov struct node *root = parse_top(gettoken());
1782*04d17814SAndrey V. Elsukov
1783*04d17814SAndrey V. Elsukov int tok;
1784896052c1SHartmut Brandt while ((tok = gettoken()) != TOK_EOF)
17856f557cf7SHartmut Brandt merge(&root, parse_top(tok));
1786f06ca4afSHartmut Brandt
17878e9b3e70SHartmut Brandt if (root)
1788f06ca4afSHartmut Brandt check_tree(root);
1789f06ca4afSHartmut Brandt
1790*04d17814SAndrey V. Elsukov /* do what the user has requested */
1791*04d17814SAndrey V. Elsukov switch (op) {
1792*04d17814SAndrey V. Elsukov
1793*04d17814SAndrey V. Elsukov case OP_EXTRACT:
1794*04d17814SAndrey V. Elsukov if (argc == 0)
1795*04d17814SAndrey V. Elsukov errx(1, "-e requires arguments");
1796*04d17814SAndrey V. Elsukov
1797*04d17814SAndrey V. Elsukov for (int i = 0; i < argc; i++)
1798*04d17814SAndrey V. Elsukov if (gen_extract(stdout, root, argv[i]))
1799*04d17814SAndrey V. Elsukov errx(1, "object not found: %s", argv[i]);
18006f557cf7SHartmut Brandt return (0);
1801*04d17814SAndrey V. Elsukov
1802*04d17814SAndrey V. Elsukov case OP_ENUMS:
1803*04d17814SAndrey V. Elsukov make_enums(argc, argv, gen_funcs);
1804f06ca4afSHartmut Brandt return (0);
1805*04d17814SAndrey V. Elsukov
1806*04d17814SAndrey V. Elsukov case OP_TREE:
1807*04d17814SAndrey V. Elsukov if (argc != 0)
1808*04d17814SAndrey V. Elsukov errx(1, "-t allows no arguments");
1809896052c1SHartmut Brandt gen_tree(root, 0);
1810896052c1SHartmut Brandt return (0);
18116f557cf7SHartmut Brandt
1812*04d17814SAndrey V. Elsukov case OP_GEN:
1813*04d17814SAndrey V. Elsukov if (argc != 0)
1814*04d17814SAndrey V. Elsukov errx(1, "tree generation allows no arguments");
1815*04d17814SAndrey V. Elsukov make_table(root, gen_funcs == GEN_FUNCS_H);
1816f06ca4afSHartmut Brandt return (0);
1817f06ca4afSHartmut Brandt }
1818*04d17814SAndrey V. Elsukov }
1819