xref: /onnv-gate/usr/src/cmd/agents/snmp/parser/parse.c (revision 3857:21b9b714e4ab)
1 /*
2  * Copyright 1999 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 #pragma ident	"%Z%%M%	%I%	%E% SMI"
6 
7 /******************************************************************
8 	Copyright 1989, 1991, 1992 by Carnegie Mellon University
9 
10                       All Rights Reserved
11 
12 Permission to use, copy, modify, and distribute this software and its
13 documentation for any purpose and without fee is hereby granted,
14 provided that the above copyright notice appear in all copies and that
15 both that copyright notice and this permission notice appear in
16 supporting documentation, and that the name of CMU not be
17 used in advertising or publicity pertaining to distribution of the
18 software without specific, written prior permission.
19 
20 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
21 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
22 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
23 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
24 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26 SOFTWARE.
27 ******************************************************************/
28 /*
29  * parse.c
30  */
31 
32 /* HISTORY
33  * Jerry Yeung	6-6-96
34  * Jerry Yeung	1-9-97	fix 4019317
35  */
36 
37 #include <stdio.h>
38 #include <ctype.h>
39 #include <stdlib.h>
40 #include <sys/types.h>
41 #include "parse.h"
42 
43 struct trap_item *trap_list = NULL;
44 
45 /* A quoted string value-- too long for a general "token" */
46 char *quoted_string_buffer;
47 
48 /*
49  * This is one element of an object identifier with either an integer
50  * subidentifier, or a textual string label, or both.
51  * The subid is -1 if not present, and label is NULL if not present.
52  */
53 struct subid {
54     int subid;
55     char *label;
56 };
57 
58 #define MAXTC	128
59 struct tc {	/* textual conventions */
60     int type;
61     char descriptor[MAXTOKEN];
62     struct enum_list *enums;
63 } tclist[MAXTC];
64 
65 
66 
67 int Line = 1;
68 
69 #define SYNTAX_MASK	0x80
70 /* types of tokens
71  Tokens wiht the SYNTAX_MASK bit set are syntax tokens */
72 #define	CONTINUE    -1
73 #define ENDOFFILE   0
74 #define LABEL	    1
75 #define SUBTREE	    2
76 #define SYNTAX	    3
77 #define PARSE_OBJID	    (4 | SYNTAX_MASK)
78 #define OCTETSTR    (5 | SYNTAX_MASK)
79 #define PARSE_INTEGER	    (6 | SYNTAX_MASK)
80 #define NETADDR	    (7 | SYNTAX_MASK)
81 #define	IPADDR	    (8 | SYNTAX_MASK)
82 #define PARSE_COUNTER	    (9 | SYNTAX_MASK)
83 #define PARSE_GUAGE	    (10 | SYNTAX_MASK)
84 #define PARSE_TIMETICKS   (11 | SYNTAX_MASK)
85 #define PARSE_OPAQUE	    (12 | SYNTAX_MASK)
86 #define NUL	    (13 | SYNTAX_MASK)
87 #define SEQUENCE    14
88 #define OF	    15	/* SEQUENCE OF */
89 #define OBJTYPE	    16
90 #define ACCESS	    17
91 #define READONLY    18
92 #define READWRITE   19
93 #define	WRITEONLY   20
94 #define NOACCESS    21
95 #define STATUS	    22
96 #define MANDATORY   23
97 #define OPTIONAL    24
98 #define OBSOLETE    25
99 /* #define RECOMMENDED 26 */
100 #define PUNCT	    27
101 #define EQUALS	    28
102 #define NUMBER	    29
103 #define LEFTBRACKET 30
104 #define RIGHTBRACKET 31
105 #define	LEFTPAREN   32
106 #define RIGHTPAREN  33
107 #define COMMA	    34
108 #define DESCRIPTION 35
109 #define QUOTESTRING 36
110 #define INDEX       37
111 #define DEFVAL      38
112 #define DEPRECATED  39
113 #define SIZE        40
114 #define BITSTRING   (41 | SYNTAX_MASK)
115 #define NSAPADDRESS (42 | SYNTAX_MASK)
116 #define PARSE_COUNTER64   (43 | SYNTAX_MASK)
117 #define OBJGROUP    44
118 #define NOTIFTYPE   45
119 #define AUGMENTS    46
120 #define COMPLIANCE  47
121 #define READCREATE  48
122 #define UNITS       49
123 #define REFERENCE   50
124 #define NUM_ENTRIES 51
125 #define MODULEIDENTITY 52
126 #define LASTUPDATED 53
127 #define ORGANIZATION 54
128 #define CONTACTINFO 55
129 #define UINTEGER32 (56 | SYNTAX_MASK)
130 #define CURRENT	    57
131 #define DEFINITIONS 58
132 #define END         59
133 #define SEMI        60
134 
135 /*
136 -- Olivier Reisacher 95/2/14
137 */
138 #define PSEUDO_TOKEN_TABLE        61
139 #define PSEUDO_TOKEN_ENTRY        62
140 
141 /* Jerry Yeung 6-6-96 (trap-support) */
142 #define TRAPTYPE 63
143 #define ENTERPRISE 64
144 #define VARIABLES 65
145 
146 struct tok {
147 	char *name;			/* token name */
148 	int len;			/* length not counting nul */
149 	int token;			/* value */
150 	int hash;			/* hash of name */
151 	struct tok *next;		/* pointer to next in hash table */
152 };
153 
154 
155 struct tok tokens[] = {
156 	{ "obsolete", sizeof ("obsolete")-1, OBSOLETE },
157 	{ "Opaque", sizeof ("Opaque")-1, PARSE_OPAQUE },
158 /*	{ "recommended", sizeof("recommended")-1, RECOMMENDED },  */
159 	{ "optional", sizeof ("optional")-1, OPTIONAL },
160 	{ "LAST-UPDATED", sizeof ("LAST-UPDATED")-1, LASTUPDATED },
161 	{ "ORGANIZATION", sizeof ("ORGANIZATION")-1, ORGANIZATION },
162 	{ "CONTACT-INFO", sizeof ("CONTACT-INFO")-1, CONTACTINFO },
163 	{ "MODULE-IDENTITY", sizeof ("MODULE-IDENTITY")-1, MODULEIDENTITY },
164 	{ "MODULE-COMPLIANCE", sizeof ("MODULE-COMPLIANCE")-1, COMPLIANCE },
165         { "DEFINITIONS", sizeof("DEFINITIONS")-1, DEFINITIONS},
166         { "END", sizeof("END")-1, END},
167         { ";", sizeof(";")-1, SEMI},
168 	{ "AUGMENTS", sizeof ("AUGMENTS")-1, AUGMENTS },
169 	{ "not-accessible", sizeof ("not-accessible")-1, NOACCESS },
170 	{ "write-only", sizeof ("write-only")-1, WRITEONLY },
171 	{ "NsapAddress", sizeof("NsapAddress")-1, NSAPADDRESS},
172 	{ "UNITS", sizeof("Units")-1, UNITS},
173 	{ "REFERENCE", sizeof("REFERENCE")-1, REFERENCE},
174 	{ "NUM-ENTRIES", sizeof("NUM-ENTRIES")-1, NUM_ENTRIES},
175 	{ "BITSTRING", sizeof("BitString")-1, BITSTRING},
176 	{ "BIT", sizeof("BIT")-1, CONTINUE},
177 	{ "Counter64", sizeof("Counter64")-1, PARSE_COUNTER64},
178 	{ "TimeTicks", sizeof ("TimeTicks")-1, PARSE_TIMETICKS },
179 	{ "NOTIFICATION-TYPE", sizeof ("NOTIFICATION-TYPE")-1, NOTIFTYPE },
180 	{ "OBJECT-GROUP", sizeof ("OBJECT-GROUP")-1, OBJGROUP },
181 	{ "OBJECTIDENTIFIER", sizeof ("OBJECTIDENTIFIER")-1, PARSE_OBJID },
182 	/*
183 	 * This CONTINUE appends the next word onto OBJECT,
184 	 * hopefully matching OBJECTIDENTIFIER above.
185 	 */
186 	{ "OBJECT", sizeof ("OBJECT")-1, CONTINUE },
187 	{ "NetworkAddress", sizeof ("NetworkAddress")-1, NETADDR },
188 	{ "Gauge", sizeof ("Gauge")-1, PARSE_GUAGE },
189 	{ "read-write", sizeof ("read-write")-1, READWRITE },
190 	{ "read-create", sizeof ("read-create")-1, READCREATE },
191 	{ "OCTETSTRING", sizeof ("OCTETSTRING")-1, OCTETSTR },
192 	{ "OCTET", sizeof ("OCTET")-1, -1 },
193 	{ "OF", sizeof ("OF")-1, OF },
194 	{ "SEQUENCE", sizeof ("SEQUENCE")-1, SEQUENCE },
195 	{ "NULL", sizeof ("NULL")-1, NUL },
196 	{ "IpAddress", sizeof ("IpAddress")-1, IPADDR },
197 	{ "UInteger32", sizeof ("UInteger32")-1, UINTEGER32 },
198 	{ "INTEGER", sizeof ("INTEGER")-1, PARSE_INTEGER },
199 	{ "Counter", sizeof ("Counter")-1, PARSE_COUNTER },
200 	{ "read-only", sizeof ("read-only")-1, READONLY },
201         { "DESCRIPTION", sizeof ("DESCRIPTION")-1, DESCRIPTION },
202         { "INDEX", sizeof ("INDEX")-1, INDEX },
203         { "DEFVAL", sizeof ("DEFVAL")-1, DEFVAL },
204         { "deprecated", sizeof ("deprecated")-1, DEPRECATED },
205         { "SIZE", sizeof ("SIZE")-1, SIZE },
206 	{ "MAX-ACCESS", sizeof ("MAX-ACCESS")-1, ACCESS },
207 	{ "ACCESS", sizeof ("ACCESS")-1, ACCESS },
208 	{ "mandatory", sizeof ("mandatory")-1, MANDATORY },
209 	{ "current", sizeof ("current")-1, CURRENT },
210 	{ "STATUS", sizeof ("STATUS")-1, STATUS },
211 	{ "SYNTAX", sizeof ("SYNTAX")-1, SYNTAX },
212 	{ "OBJECT-TYPE", sizeof ("OBJECT-TYPE")-1, OBJTYPE },
213 	{ "{", sizeof ("{")-1, LEFTBRACKET },
214 	{ "}", sizeof ("}")-1, RIGHTBRACKET },
215 	{ "::=", sizeof ("::=")-1, EQUALS },
216 	{ "(", sizeof ("(")-1, LEFTPAREN },
217 	{ ")", sizeof (")")-1, RIGHTPAREN },
218 	{ ",", sizeof (",")-1, COMMA },
219 	{ "TRAP-TYPE", sizeof ("TRAP-TYPE")-1, TRAPTYPE },
220 	{ "ENTERPRISE", sizeof ("ENTERPRISE")-1, ENTERPRISE },
221 	{ "VARIABLES", sizeof ("VARIABLES")-1, VARIABLES },
222 	{ NULL }
223 };
224 
225 #define	HASHSIZE	32
226 #define	BUCKET(x)	(x & 0x01F)
227 
228 struct tok	*buckets[HASHSIZE];
229 static void
230 do_subtree(struct tree *root, struct node **nodes);
231 static int
232 get_token(register FILE *fp, register char *token);
233 static int
234 parseQuoteString(register FILE *fp, register char *token);
235 static int
236 tossObjectIdentifier(register FILE *fp);
237 
238 int number_value;
239 
240 static void
hash_init()241 hash_init()
242 {
243 	register struct tok	*tp;
244 	register char	*cp;
245 	register int	h;
246 	register int	b;
247 
248 /*
249 -- Olivier Reisacher 95/2/14
250 	bzero((char *)buckets, sizeof(buckets));
251 */
252 	memset((void *) buckets, 0, sizeof(buckets));
253 
254 	for (tp = tokens; tp->name; tp++) {
255 		for (h = 0, cp = tp->name; *cp; cp++)
256 			h += *cp;
257 		tp->hash = h;
258 		b = BUCKET(h);
259 		if (buckets[b])
260 		    tp->next = buckets[b]; /* BUG ??? */
261 		buckets[b] = tp;
262 	}
263 }
264 
265 #define NHASHSIZE    128
266 #define NBUCKET(x)   (x & 0x7F)
267 struct node *nbuckets[NHASHSIZE];
268 
init_node_hash(nodes)269 void init_node_hash(nodes)
270      struct node *nodes;
271 {
272      register struct node *np, *nextp;
273      register char *cp;
274      register int hash;
275 
276 /*
277 -- Olivier Reisacher 95/2/14
278      bzero((char *)nbuckets,sizeof(nbuckets));
279 */
280      memset((void *) nbuckets, 0, sizeof(nbuckets));
281 
282      for(np = nodes; np;){
283          nextp = np->next;
284          hash = 0;
285 	 for(cp = np->parent; *cp; cp++)
286 	     hash += *cp;
287 	 np->next = nbuckets[NBUCKET(hash)];
288 	 nbuckets[NBUCKET(hash)] = np;
289 	 np = nextp;
290      }
291 }
292 
293 static char *
Malloc(num)294 Malloc(num)
295     unsigned num;
296 {
297     char     *buf;
298 
299     /* this is to fix (what seems to be) a problem with the IBM RT C
300 library malloc */
301     if (num < 16)
302 	num = 16;
303     buf = (char *)malloc (num);
304     if (buf == NULL) {
305       fprintf(stderr, "malloc failed.  Exiting\n");
306       exit(1);
307     }
308     return (char *)buf;
309 }
310 
311 static void
print_error(string,token,type)312 print_error(string, token, type)
313     char *string;
314     char *token;
315     int type;
316 {
317     if (type == ENDOFFILE)
318 	fprintf(stderr, "%s(EOF): On or around line %d\n", string, Line);
319     else if (token)
320 	fprintf(stderr, "%s(%s): On or around line %d\n", string, token, Line);
321     else
322 	fprintf(stderr, "%s: On or around line %d\n", string, Line);
323 }
324 
325 /*
326 -- Olivier Reisacher 95/2/14
327 #ifdef TEST
328 print_subtree(tree, count)
329 */
print_subtree(tree,count)330 void print_subtree(tree, count)
331     struct tree *tree;
332     int count;
333 {
334     struct tree *tp;
335     int i;
336 
337     for(i = 0; i < count; i++)
338 	printf("  ");
339     printf("Children of %s:\n", tree->label);
340     count++;
341     for(tp = tree->child_list; tp; tp = tp->next_peer){
342 	for(i = 0; i < count; i++)
343 	    printf("  ");
344 	printf("%s\n", tp->label);
345     }
346     for(tp = tree->child_list; tp; tp = tp->next_peer){
347 	print_subtree(tp, count);
348     }
349 }
350 /*
351 -- Olivier Reisacher 95/2/14
352 #endif
353 */
354 
355 int translation_table[256];
356 
build_translation_table()357 void build_translation_table(){
358     int count;
359 
360     for(count = 0; count < 256; count++){
361 	switch(count){
362 	    case PARSE_OBJID:
363 		translation_table[count] = TYPE_OBJID;
364 		break;
365 	    case OCTETSTR:
366 		translation_table[count] = TYPE_OCTETSTR;
367 		break;
368 	    case PARSE_INTEGER:
369 		translation_table[count] = TYPE_INTEGER;
370 		break;
371 	    case NETADDR:
372 		translation_table[count] = TYPE_IPADDR;
373 		break;
374 	    case IPADDR:
375 		translation_table[count] = TYPE_IPADDR;
376 		break;
377 	    case PARSE_COUNTER:
378 		translation_table[count] = TYPE_COUNTER;
379 		break;
380 	    case PARSE_GUAGE:
381 		translation_table[count] = TYPE_GAUGE;
382 		break;
383 	    case PARSE_TIMETICKS:
384 		translation_table[count] = TYPE_TIMETICKS;
385 		break;
386 	    case PARSE_OPAQUE:
387 		translation_table[count] = TYPE_OPAQUE;
388 		break;
389 	    case NUL:
390 		translation_table[count] = TYPE_NULL;
391 		break;
392 	    case PARSE_COUNTER64:
393 		translation_table[count] = TYPE_COUNTER64;
394 		break;
395 	    case BITSTRING:
396 		translation_table[count] = TYPE_BITSTRING;
397 		break;
398 	    case NSAPADDRESS:
399 		translation_table[count] = TYPE_NSAPADDRESS;
400 		break;
401 	    case UINTEGER32:
402 		translation_table[count] = TYPE_UINTEGER;
403 		break;
404 
405 /*
406 -- Olivier Reisacher 95/2/14
407 */
408 		case PSEUDO_TOKEN_TABLE:
409 			translation_table[count] = TYPE_TABLE;
410 			break;
411 		case PSEUDO_TOKEN_ENTRY:
412 			translation_table[count] = TYPE_ENTRY;
413 			break;
414 
415 	    default:
416 		translation_table[count] = TYPE_OTHER;
417 		break;
418 	}
419     }
420 }
421 
422 /*
423 -- Olivier Reisacher 95/2/14
424 static struct tree *
425 */
426 struct tree *
build_tree(nodes)427 build_tree(nodes)
428     struct node *nodes;
429 {
430     struct node *np;
431     struct tree *tp;
432     int bucket, nodes_left = 0;
433 
434     build_translation_table();
435     /* grow tree from this root node */
436     init_node_hash(nodes);
437 
438 /*
439 -- Olivier Reisacher 95/2/14
440      build root node
441     tp = (struct tree *)Malloc(sizeof(struct tree));
442     tp->parent = NULL;
443     tp->next_peer = NULL;
444     tp->child_list = NULL;
445     tp->enums = NULL;
446     strcpy(tp->label, "joint-iso-ccitt");
447     tp->subid = 2;
448     tp->type = 0;
449     tp->description = 0;
450      XXX nodes isn't needed in do_subtree() ???
451     do_subtree(tp, &nodes);
452     lasttp = tp;
453 
454      build root node
455     tp = (struct tree *)Malloc(sizeof(struct tree));
456     tp->parent = NULL;
457     tp->next_peer = lasttp;
458     tp->child_list = NULL;
459     tp->enums = NULL;
460     strcpy(tp->label, "ccitt");
461     tp->subid = 0;
462     tp->type = 0;
463     tp->description = 0;
464      XXX nodes isn't needed in do_subtree() ???
465     do_subtree(tp, &nodes);
466     lasttp = tp;
467 */
468 
469     /* build root node */
470     tp = (struct tree *)Malloc(sizeof(struct tree));
471     tp->parent = NULL;
472 /*
473 -- Olivier Reisacher 95/2/14
474     tp->next_peer = lasttp;
475 */
476     tp->next_peer = NULL;
477     tp->child_list = NULL;
478     tp->enums = NULL;
479     strcpy(tp->label, "iso");
480     tp->subid = 1;
481     tp->type = 0;
482     tp->description = 0;
483     /* XXX nodes isn't needed in do_subtree() ??? */
484     do_subtree(tp, &nodes);
485 /*
486 -- Olivier Reisacher 95/2/14
487 */
488 	tp->access = 0;
489 	tp->indexs = NULL;
490 	tp->n_indexs = 0;
491 
492 
493 #ifdef TEST
494     print_subtree(tp, 0);
495 #endif /* TEST */
496     /* If any nodes are left, the tree is probably inconsistent */
497     for(bucket = 0; bucket < NHASHSIZE; bucket++){
498         if (nbuckets[bucket]){
499 	    nodes_left = 1;
500 	    break;
501 	}
502     }
503     if (nodes_left){
504 	fprintf(stderr, "The mib description doesn't seem to be consistent.\n");
505 	fprintf(stderr, "Some nodes couldn't be linked under the \"iso\" tree.\n");
506 	fprintf(stderr, "these nodes are left:\n");
507 	for(bucket = 0; bucket < NHASHSIZE; bucket++){
508 	    for(np = nbuckets[bucket]; np; np = np->next)
509 	        fprintf(stderr, "%s ::= { %s %d } (%d)\n", np->label,
510 			np->parent, np->subid, np->type);
511 	}
512     }
513     return tp;
514 }
515 
516 /*
517  * Find all the children of root in the list of nodes.  Link them into the
518  * tree and out of the nodes list.
519  */
520 static void
do_subtree(root,nodes)521 do_subtree(root, nodes)
522     struct tree *root;
523     struct node **nodes;
524 {
525     register struct tree *tp;
526     register struct node *np, **headp;
527     struct node *oldnp = NULL, *child_list = NULL, *childp = NULL;
528     char *cp;
529     int hash;
530 
531     tp = root;
532     hash = 0;
533     for(cp = tp->label; *cp; cp++)
534         hash += *cp;
535     headp = &nbuckets[NBUCKET(hash)];
536     /*
537      * Search each of the nodes for one whose parent is root, and
538      * move each into a separate list.
539      */
540     for(np = *headp; np; np = np->next){
541 	if ((*tp->label != *np->parent) || strcmp(tp->label, np->parent)){
542 	    if ((*tp->label == *np->label) && !strcmp(tp->label, np->label)){
543 		/* if there is another node with the same label, assume that
544 		 * any children after this point in the list belong to the other node.
545 		 * This adds some scoping to the table and allows vendors to
546 		 * reuse names such as "ip".
547 		 */
548 		break;
549 	    }
550 	    oldnp = np;
551 	} else {
552 	    if (child_list == NULL){
553 		child_list = childp = np;   /* first entry in child list */
554 	    } else {
555 		childp->next = np;
556 		childp = np;
557 	    }
558 	    /* take this node out of the node list */
559 	    if (oldnp == NULL){
560 		*headp = np->next;  /* fix root of node list */
561 	    } else {
562 		oldnp->next = np->next;	/* link around this node */
563 	    }
564 	}
565     }
566     if (childp)
567 	childp->next = 0;	/* re-terminate list */
568     /*
569      * Take each element in the child list and place it into the tree.
570      */
571     for(np = child_list; np; np = np->next){
572 	tp = (struct tree *)Malloc(sizeof(struct tree));
573 	tp->parent = root;
574 	tp->next_peer = NULL;
575 	tp->child_list = NULL;
576 	strcpy(tp->label, np->label);
577 	tp->subid = np->subid;
578 	tp->type = translation_table[np->type];
579         tp->oct_str_len = np->oct_str_len;
580 	tp->enums = np->enums;
581 	np->enums = NULL;	/* so we don't free them later */
582 	tp->description = np->description; /* steals memory from np */
583 	np->description = NULL; /* so we don't free it later */
584 /*
585 -- Olivier Reisacher 95/2/14
586 */
587 	tp->access = np->access;
588 	tp->indexs = np->indexs;
589 	np->indexs = NULL;
590 	tp->n_indexs = np->n_indexs;
591 /*
592 -- Olivier Reisacher 95/2/14
593 -- The goal of this modification is to order the
594 -- tree according to the subid
595 
596 	if (root->child_list == NULL){
597 	    root->child_list = tp;
598 	} else {
599 	    peer->next_peer = tp;
600 	}
601 	peer = tp;
602 */
603 	if(root->child_list == NULL)
604 	{
605 		root->child_list = tp;
606 	}
607 	else
608 	{
609 		struct tree *t = root->child_list;
610 		struct tree *l = NULL;
611 
612 		while(t)
613 		{
614 			if(tp->subid < t->subid)
615 			{
616 				break;
617 			}
618 			l = t;
619 			t = t->next_peer;
620 		}
621 		if(l == NULL)
622 		{
623 			tp->next_peer = root->child_list;
624 			root->child_list = tp;
625 		}
626 		else
627 		{
628 			tp->next_peer = l->next_peer;
629 			l->next_peer = tp;
630 		}
631 	}
632 
633 /*	if (tp->type == TYPE_OTHER) */
634 	    do_subtree(tp, nodes);	/* recurse on this child if it isn't
635 					   an end node */
636     }
637     /* free all nodes that were copied into tree */
638     oldnp = NULL;
639     for(np = child_list; np; np = np->next){
640 	if (oldnp)
641 	    free(oldnp);
642 	oldnp = np;
643     }
644     if (oldnp)
645 	free(oldnp);
646 }
647 
648 
649 /*
650  * Takes a list of the form:
651  * { iso org(3) dod(6) 1 }
652  * and creates several nodes, one for each parent-child pair.
653  * Returns NULL on error.
654  */
655 static int
getoid(fp,oid,length)656 getoid(fp, oid,  length)
657     register FILE *fp;
658     register struct subid *oid;	/* an array of subids */
659     int length;	    /* the length of the array */
660 {
661     register int count;
662     int type;
663     char token[MAXTOKEN];
664     register char *cp;
665 
666 #ifdef TRACE_PROC
667 printf("getoid() invoked\n");
668 #endif
669 
670     if ((type = get_token(fp, token)) != LEFTBRACKET){
671 	print_error("Expected \"{\"", token, type);
672 	return NULL;
673     }
674     type = get_token(fp, token);
675     for(count = 0; count < length; count++, oid++){
676 	oid->label = 0;
677 	oid->subid = -1;
678 	if (type == RIGHTBRACKET){
679 	    return count;
680 	} else if (type != LABEL && type != NUMBER){
681 	    print_error("Not valid for object identifier", token, type);
682 	    return NULL;
683 	}
684 	if (type == LABEL){
685 	    /* this entry has a label */
686 	    cp = (char *)Malloc((unsigned)strlen(token) + 1);
687 	    strcpy(cp, token);
688 	    oid->label = cp;
689 	    type = get_token(fp, token);
690 	    if (type == LEFTPAREN){
691 		type = get_token(fp, token);
692 		if (type == NUMBER){
693 		    oid->subid = atoi(token);
694 		    if ((type = get_token(fp, token)) != RIGHTPAREN){
695 			print_error("Unexpected a closing parenthesis", token, type);
696 			return NULL;
697 		    }
698 		} else {
699 		    print_error("Expected a number", token, type);
700 		    return NULL;
701 		}
702 	    } else {
703 		continue;
704 	    }
705 	} else {
706 	    /* this entry  has just an integer sub-identifier */
707 	    oid->subid = atoi(token);
708 	}
709 	type = get_token(fp, token);
710     }
711     return count;
712 
713 
714 }
715 
716 static void
free_node(np)717 free_node(np)
718     struct node *np;
719 {
720     struct enum_list *ep, *tep;
721 /*
722 -- Olivier Reisacher 95/2/14
723 */
724 	struct index_list *ip, *tip;
725 
726 	ip = np->indexs;
727 	while(ip)
728 	{
729 		tip = ip;
730 		ip = ip->next;
731 		free((char *)tip);
732 	}
733 
734 
735     ep = np->enums;
736     while(ep){
737 	tep = ep;
738 	ep = ep->next;
739 	free((char *)tep);
740     }
741     free((char *)np);
742 }
743 
parse_traptype(fp,name)744 int parse_traptype(fp,name)
745 FILE *fp;
746 char *name;
747 {
748    int type;
749    char token[MAXTOKEN];
750    struct trap_item *ti;
751    struct index_list *ip;
752    static struct trap_item *last_trap_item=NULL;
753 
754 #ifdef TRACE_PROC
755 printf("parse_traptype() invoked\n");
756 #endif
757 
758    type = get_token(fp,token);
759    if( type == ENTERPRISE){
760      if( (type = get_token(fp,token)) == LABEL){
761 	/* create a trap item */
762         ti = (struct trap_item*)calloc(1, sizeof(struct trap_item));
763         if(ti==NULL){
764 	 fprintf(stderr,"calloc failed\n");
765 	 return 0;
766         }
767 	strcpy(ti->label,name);
768 	strcpy(ti->enterprise_label,token);
769 	ti->enterprise_subids[0] = (u_long)-1;
770 
771 	type = get_token(fp,token);
772 	while(type != EQUALS){
773 	  switch(type){
774 	    case VARIABLES:
775 		type = get_token(fp,token);
776 		if(type != LEFTBRACKET){
777 		  print_error("{ expected in VARIABLES clause",token,type);
778 		  free(ti);
779 		  return 0;
780 		}
781 		type = get_token(fp,token);
782 		while(type != RIGHTBRACKET)
783 		{
784 			if(type != LABEL)
785 			{
786 				print_error("LABEL expected in VARIABLES1 clause",token,type);
787 				free(ti);
788 				return 0;
789 			}
790 
791 
792 			(ti->n_variables)++;
793 		    	if(ti->var_list == NULL)
794 			{
795 				ip = ti->var_list = (struct index_list *)
796 					Malloc(sizeof(struct index_list));
797 			}
798 			else
799 			{
800 				ip->next = (struct index_list *)
801 					Malloc(sizeof(struct enum_list));
802 				ip = ip->next;
803 			}
804 			ip->next = 0;
805 			ip->tp = NULL;
806 
807 			ip->label =
808 				(char *)Malloc((unsigned)strlen(token) + 1);
809 			strcpy(ip->label, token);
810 
811 			type = get_token(fp, token);
812 
813 			switch(type)
814 			{
815 				case COMMA:
816 					type = get_token(fp, token);
817 					break;
818 
819 				case RIGHTBRACKET:
820 					break;
821 
822 				default:
823 					print_error(", or } expected in VARIABLES clause",token,type);
824 					free(ti);
825 					return 0;
826 
827 			}
828 		}
829 		break;
830 
831 	    case DESCRIPTION:
832 		type = get_token(fp,token);
833 		if(type != QUOTESTRING){
834 		  print_error("Bad DESCRIPTION",token,type);
835 		  free(ti);
836 		  return 0;
837 		}
838 		ti->description = quoted_string_buffer;
839 		quoted_string_buffer = (char*)malloc(MAXQUOTESTR);
840 		if(quoted_string_buffer==NULL){
841 		  fprintf(stderr,"malloc failed\n");
842 		  return 0;
843 		}
844 		break;
845 	    case REFERENCE:
846 		type = get_token(fp,token);
847 		if(type != QUOTESTRING){
848 		  print_error("Bad DESCRIPTION",token,type);
849 		  free(ti);
850 		  return 0;
851 		}
852 		break;
853 	    default:
854 		/* NOTHING*/
855 		break;
856 	  }
857 	  type = get_token(fp,token);
858 	}
859 	/* get the integer */
860 	if( (type = get_token(fp,token)) == NUMBER){
861 		ti->value = atoi(token);
862 		/* attach the item to list */
863 
864 
865 
866 	}else{
867         	print_error("Expected a number",token,type);
868 		free(ti);
869 		return 0;
870 	}
871      }else{
872         print_error("Expected \"enterprise name\"",token,type);
873         return 0;
874      }
875    }else{
876      print_error("Expected \"ENTERPRISE\"",token,type);
877      return 0;
878    }
879    if(trap_list == NULL){
880 	last_trap_item = trap_list = ti;
881    }else{
882 	last_trap_item->next = ti;
883 	last_trap_item = ti;
884    }
885    return 1;
886 }
887 
888 /*
889  * Parse an entry of the form:
890  * label OBJECT IDENTIFIER ::= { parent 2 }
891  * The "label OBJECT IDENTIFIER" portion has already been parsed.
892  * Returns 0 on error.
893  */
894 static struct node *
parse_objectid(fp,name)895 parse_objectid(fp, name)
896     FILE *fp;
897     char *name;
898 {
899     int type;
900     char token[MAXTOKEN];
901     register int count;
902     register struct subid *op, *nop;
903     int length;
904     struct subid oid[32];
905     struct node *np, *root, *oldnp = NULL;
906 
907     type = get_token(fp, token);
908     if (type != EQUALS){
909 	print_error("Bad format", token, type);
910 	return 0;
911     }
912     if ((length = getoid(fp, oid, 32)) != 0){
913 	np = root = (struct node *)Malloc(sizeof(struct node));
914 
915 /*
916 -- Olivier Reisacher 95/2/14
917 	bzero((char *)np, sizeof(struct node));
918 */
919 	memset((void *) np, 0, sizeof(struct node));
920 
921 	/*
922 	 * For each parent-child subid pair in the subid array,
923 	 * create a node and link it into the node list.
924 	 */
925 	for(count = 0, op = oid, nop=oid+1; count < (length - 2); count++,
926 	    op++, nop++){
927 	    /* every node must have parent's name and child's name or number */
928 	    if (op->label && (nop->label || (nop->subid != -1))){
929 		strcpy(np->parent, op->label);
930 		if (nop->label)
931 		    strcpy(np->label, nop->label);
932 		if (nop->subid != -1)
933 		    np->subid = nop->subid;
934 		np->type = 0;
935 		np->enums = 0;
936 /*
937 -- Olivier Reisacher 95/2/14
938 */
939 		np->access = 0;
940 		np->n_indexs = 0;
941 		np->indexs = NULL;
942 
943 		/* set up next entry */
944 		np->next = (struct node *)Malloc(sizeof(*np->next));
945 
946 /*
947 -- Olivier Reisacher 95/2/14
948 		bzero((char *)np->next, sizeof(struct node));
949 */
950 		memset((void *) np->next, 0, sizeof(struct node));
951 
952 		oldnp = np;
953 		np = np->next;
954 	    }
955 	}
956 	np->next = (struct node *)NULL;
957 	/*
958 	 * The above loop took care of all but the last pair.  This pair is taken
959 	 * care of here.  The name for this node is taken from the label for this
960 	 * entry.
961 	 * np still points to an unused entry.
962 	 */
963 	if (count == (length - 2)){
964 	    if (op->label){
965 		strcpy(np->parent, op->label);
966 		strcpy(np->label, name);
967 		if (nop->subid != -1)
968 		    np->subid = nop->subid;
969 		else
970 		    print_error("Warning: This entry is pretty silly",
971 				np->label, type);
972 	    } else {
973 		free_node(np);
974 		if (oldnp)
975 		    oldnp->next = NULL;
976 		else
977 		    return NULL;
978 	    }
979 	} else {
980 	    print_error("Missing end of oid", (char *)NULL, type);
981 	    free_node(np);   /* the last node allocated wasn't used */
982 	    if (oldnp)
983 		oldnp->next = NULL;
984 	    return NULL;
985 	}
986 	/* free the oid array */
987 	for(count = 0, op = oid; count < length; count++, op++){
988 	    if (op->label)
989 		free(op->label);
990 	    op->label = 0;
991 	}
992 	return root;
993     } else {
994 	print_error("Bad object identifier", (char *)NULL, type);
995 	return 0;
996     }
997 }
998 
999 static int
get_tc(descriptor,ep)1000 get_tc(descriptor, ep)
1001     char *descriptor;
1002     struct enum_list **ep;
1003 {
1004     int i;
1005 
1006     for(i = 0; i < MAXTC; i++){
1007 	if (tclist[i].type == 0)
1008 	    break;
1009 	if (!strcmp(descriptor, tclist[i].descriptor)){
1010 	    *ep = tclist[i].enums;
1011 	    return tclist[i].type;
1012 	}
1013     }
1014     return LABEL;
1015 }
1016 
1017 /*
1018  * Parses an asn type.  Structures are ignored by this parser.
1019  * Returns NULL on error.
1020  */
1021 static int
parse_asntype(fp,name,ntype,ntoken)1022 parse_asntype(fp, name, ntype, ntoken)
1023     FILE *fp;
1024     char *name;
1025     int *ntype;
1026     char *ntoken;
1027 {
1028     int type, i;
1029     char token[MAXTOKEN];
1030     struct enum_list *ep;
1031     struct tc *tcp;
1032     int level;
1033 
1034 #ifdef TRACE_PROC
1035 printf("parse_asntype() invoked\n");
1036 #endif
1037 
1038     type = get_token(fp, token);
1039     if (type == SEQUENCE){
1040 	while((type = get_token(fp, token)) != ENDOFFILE){
1041 	    if (type == RIGHTBRACKET){
1042 		*ntype = get_token(fp, ntoken);
1043 		return 1;
1044 	    }
1045 	}
1046 	print_error("Expected \"}\"", token, type);
1047 	return 0;
1048     } else {
1049 	if (!strcmp(token, "TEXTUAL-CONVENTION")){
1050 	    while (type != SYNTAX)
1051 		type = get_token(fp, token);
1052 	    type = get_token(fp, token);
1053 	}
1054 	/* textual convention */
1055 	for(i = 0; i < MAXTC; i++){
1056 	    if (tclist[i].type == 0)
1057 		break;
1058 	}
1059 	if (i == MAXTC){
1060 	    print_error("No more textual conventions possible.", token, type);
1061 	    return 0;
1062 	}
1063 	tcp = &tclist[i];
1064 	strcpy(tcp->descriptor, name);
1065 	if (!(type & SYNTAX_MASK)){
1066 
1067 /*
1068 -- Olivier Reisacher 95/2/14
1069 	    print_error("Textual convention doesn't map to real type.", token,
1070 			type);
1071 	    return 0;
1072 	}
1073 */
1074 		int w;
1075 
1076 		w = get_tc(token, &ep);
1077 		if(!(w & SYNTAX_MASK))
1078 		{
1079 	    		print_error("Textual convention doesn't map to real type.", token, type);
1080 	    		return 0;
1081 		}
1082 		type = w;
1083 	}
1084 
1085 	tcp->type = type;
1086 	*ntype = get_token(fp, ntoken);
1087 	if (*ntype == LEFTPAREN){
1088 	    level = 1;
1089 	    /* don't record any constraints for now */
1090 	    while(level > 0){
1091 		*ntype = get_token(fp, ntoken);
1092 		if (*ntype == LEFTPAREN)
1093 		    level++;
1094 		if (*ntype == RIGHTPAREN)
1095 		    level--;
1096 	    }
1097 	    *ntype = get_token(fp, ntoken);
1098 	} else if (*ntype == LEFTBRACKET) {
1099 	    /* if there is an enumeration list, parse it */
1100 	    while((type = get_token(fp, token)) != ENDOFFILE){
1101 		if (type == RIGHTBRACKET)
1102 		    break;
1103 		if (type == LABEL){
1104 		    /* this is an enumerated label */
1105 		    if (tcp->enums == 0){
1106 			ep = tcp->enums = (struct enum_list *)
1107 			    Malloc(sizeof(struct enum_list));
1108 		    } else {
1109 			ep->next = (struct enum_list *)
1110 			    Malloc(sizeof(struct enum_list));
1111 			ep = ep->next;
1112 		    }
1113 		    ep->next = 0;
1114 		    /* a reasonable approximation for the length */
1115 		    ep->label =
1116 			(char *)Malloc((unsigned)strlen(token) + 1);
1117 		    strcpy(ep->label, token);
1118 		    type = get_token(fp, token);
1119 		    if (type != LEFTPAREN){
1120 			print_error("Expected \"(\"", token, type);
1121 			/* free_node(np); */
1122 			return 0;
1123 		    }
1124 		    type = get_token(fp, token);
1125 		    if (type != NUMBER){
1126 			print_error("Expected integer", token, type);
1127 			/* free_node(np); */
1128 			return 0;
1129 		    }
1130 		    ep->value = atoi(token);
1131 		    type = get_token(fp, token);
1132 		    if (type != RIGHTPAREN){
1133 			print_error("Expected \")\"", token, type);
1134 			/* free_node(np); */
1135 			return 0;
1136 		    }
1137 		}
1138 	    }
1139 	    if (type == ENDOFFILE){
1140 		print_error("Expected \"}\"", token, type);
1141 		/* free_node(np); */
1142 		return 0;
1143 	    }
1144 	    *ntype = get_token(fp, ntoken);
1145 	}
1146 	return 1;
1147     }
1148 }
1149 
1150 
1151 /*
1152  * Parses an OBJECT TYPE macro.
1153  * Returns 0 on error.
1154  */
1155 static struct node *
parse_objecttype(fp,name)1156 parse_objecttype(fp, name)
1157     register FILE *fp;
1158     char *name;
1159 {
1160     register int type;
1161     char token[MAXTOKEN];
1162     int count, length;
1163     struct subid oid[32];
1164     char syntax[MAXTOKEN];
1165     int nexttype, tctype;
1166     char nexttoken[MAXTOKEN];
1167     register struct node *np;
1168     register struct enum_list *ep;
1169 /*
1170 -- Olivier Reisacher 95/2/14
1171 */
1172 	struct index_list *ip;
1173 
1174     type = get_token(fp, token);
1175     if (type != SYNTAX){
1176 	print_error("Bad format for OBJECT TYPE", token, type);
1177 	return 0;
1178     }
1179     np = (struct node *)Malloc(sizeof(struct node));
1180     np->next = 0;
1181     np->enums = 0;
1182     np->description = NULL;        /* default to an empty description */
1183 /*
1184 -- Olivier Reisacher 95/2/14
1185 */
1186 	np->access = 0;
1187 	np->n_indexs = 0;
1188 	np->indexs = 0;
1189 
1190     type = get_token(fp, token);
1191     if (type == LABEL){
1192 	tctype = get_tc(token, &(np->enums));
1193 #if 0
1194 	if (tctype == LABEL){
1195 	    print_error("No known translation for type", token, type);
1196 	    return 0;
1197 	}
1198 #endif
1199 	type = tctype;
1200     }
1201     np->type = type;
1202     np->oct_str_len = 0;
1203     nexttype = get_token(fp, nexttoken);
1204     switch(type){
1205 	case SEQUENCE:
1206 	    strcpy(syntax, token);
1207 	    if (nexttype == OF){
1208 		strcat(syntax, " ");
1209 		strcat(syntax, nexttoken);
1210 		nexttype = get_token(fp, nexttoken);
1211 		strcat(syntax, " ");
1212 		strcat(syntax, nexttoken);
1213 		nexttype = get_token(fp, nexttoken);
1214 
1215 /*
1216 -- Olivier Reisacher 95/2/14
1217 */
1218 		np->type = PSEUDO_TOKEN_TABLE;
1219 	    }
1220 
1221 	    break;
1222 	case PARSE_INTEGER:
1223 	case UINTEGER32:
1224 	    strcpy(syntax, token);
1225 	    if (nexttype == LEFTBRACKET) {
1226 		/* if there is an enumeration list, parse it */
1227 		while((type = get_token(fp, token)) != ENDOFFILE){
1228 		    if (type == RIGHTBRACKET)
1229 			break;
1230 		    if (type == LABEL){
1231 			/* this is an enumerated label */
1232 			if (np->enums == 0){
1233 			    ep = np->enums = (struct enum_list *)
1234 					Malloc(sizeof(struct enum_list));
1235 			} else {
1236 			    ep->next = (struct enum_list *)
1237 					Malloc(sizeof(struct enum_list));
1238 			    ep = ep->next;
1239 			}
1240 			ep->next = 0;
1241 			/* a reasonable approximation for the length */
1242 			ep->label =
1243 			    (char *)Malloc((unsigned)strlen(token) + 1);
1244 			strcpy(ep->label, token);
1245 			type = get_token(fp, token);
1246 			if (type != LEFTPAREN){
1247 			    print_error("Expected \"(\"", token, type);
1248 			    free_node(np);
1249 			    return 0;
1250 			}
1251 			type = get_token(fp, token);
1252 			if (type != NUMBER){
1253 			    print_error("Expected integer", token, type);
1254 			    free_node(np);
1255 			    return 0;
1256 			}
1257 			ep->value = atoi(token);
1258 			type = get_token(fp, token);
1259 			if (type != RIGHTPAREN){
1260 			    print_error("Expected \")\"", token, type);
1261 			    free_node(np);
1262 			    return 0;
1263 			}
1264 		    }
1265 		}
1266 		if (type == ENDOFFILE){
1267 		    print_error("Expected \"}\"", token, type);
1268 		    free_node(np);
1269 		    return 0;
1270 		}
1271 		nexttype = get_token(fp, nexttoken);
1272 	    } else if (nexttype == LEFTPAREN){
1273 		/* ignore the "constrained integer" for now */
1274 		nexttype = get_token(fp, nexttoken);
1275 		nexttype = get_token(fp, nexttoken);
1276 		nexttype = get_token(fp, nexttoken);
1277 	    }
1278 	    break;
1279 	case BITSTRING:
1280 	    strcpy(syntax, token);
1281 	    if (nexttype == LEFTBRACKET) {
1282 		/* if there is an enumeration list, parse it */
1283 		while((type = get_token(fp, token)) != ENDOFFILE){
1284 		    if (type == RIGHTBRACKET)
1285 			break;
1286 		    if (type == LABEL){
1287 			/* this is an enumerated label */
1288 			if (np->enums == 0){
1289 			    ep = np->enums = (struct enum_list *)
1290 					Malloc(sizeof(struct enum_list));
1291 			} else {
1292 			    ep->next = (struct enum_list *)
1293 					Malloc(sizeof(struct enum_list));
1294 			    ep = ep->next;
1295 			}
1296 			ep->next = 0;
1297 			/* a reasonable approximation for the length */
1298 			ep->label =
1299 			    (char *)Malloc((unsigned)strlen(token) + 1);
1300 			strcpy(ep->label, token);
1301 			type = get_token(fp, token);
1302 			if (type != LEFTPAREN){
1303 			    print_error("Expected \"(\"", token, type);
1304 			    free_node(np);
1305 			    return 0;
1306 			}
1307 			type = get_token(fp, token);
1308 			if (type != NUMBER){
1309 			    print_error("Expected integer", token, type);
1310 			    free_node(np);
1311 			    return 0;
1312 			}
1313 			ep->value = atoi(token);
1314 			type = get_token(fp, token);
1315 			if (type != RIGHTPAREN){
1316 			    print_error("Expected \")\"", token, type);
1317 			    free_node(np);
1318 			    return 0;
1319 			}
1320 		    }
1321 		}
1322 		if (type == ENDOFFILE){
1323 		    print_error("Expected \"}\"", token, type);
1324 		    free_node(np);
1325 		    return 0;
1326 		}
1327 		nexttype = get_token(fp, nexttoken);
1328 	    } else if (nexttype == LEFTPAREN){
1329 		/* ignore the "constrained integer" for now */
1330 		nexttype = get_token(fp, nexttoken);
1331 		nexttype = get_token(fp, nexttoken);
1332 		nexttype = get_token(fp, nexttoken);
1333 	    }
1334 	    break;
1335 	case OCTETSTR:
1336 	    strcpy(syntax, token);
1337             /* ignore the "constrained octet string" for now */
1338             if (nexttype == LEFTPAREN) {
1339                 nexttype = get_token(fp, nexttoken);
1340                 if (nexttype == SIZE) {
1341                     nexttype = get_token(fp, nexttoken);
1342                     if (nexttype == LEFTPAREN) {
1343                         nexttype = get_token(fp, nexttoken); /* 0..255 */
1344                         np->oct_str_len = number_value;
1345                         number_value = 0;
1346                         nexttype = get_token(fp, nexttoken); /* ) */
1347                         nexttype = get_token(fp, nexttoken); /* ) */
1348                         if (nexttype == RIGHTPAREN)
1349                         {
1350                             nexttype = get_token(fp, nexttoken);
1351                             break;
1352                         }
1353                     }
1354                 }
1355                 print_error("Bad syntax", token, type);
1356                 free_node(np);
1357                 return 0;
1358             }
1359 	    break;
1360 	case PARSE_OBJID:
1361 	case NETADDR:
1362 	case IPADDR:
1363 	case PARSE_COUNTER:
1364 	case PARSE_GUAGE:
1365 	case PARSE_TIMETICKS:
1366 	case PARSE_OPAQUE:
1367 	case NUL:
1368 	case LABEL:
1369 	case NSAPADDRESS:
1370 	case PARSE_COUNTER64:
1371 	    strcpy(syntax, token);
1372 	    break;
1373 	default:
1374 	    print_error("Bad syntax", token, type);
1375 	    free_node(np);
1376 	    return 0;
1377     }
1378     if (nexttype == UNITS){
1379 	type = get_token(fp, token);
1380 	if (type != QUOTESTRING) {
1381 	    print_error("Bad DESCRIPTION", token, type);
1382 	    free_node(np);
1383 	    return 0;
1384 	}
1385 	nexttype = get_token(fp, nexttoken);
1386     }
1387     if (nexttype != ACCESS){
1388 	print_error("Should be ACCESS", nexttoken, nexttype);
1389 	free_node(np);
1390 	return 0;
1391     }
1392     type = get_token(fp, token);
1393     if (type != READONLY && type != READWRITE && type != WRITEONLY
1394 	&& type != NOACCESS && type != READCREATE){
1395 	print_error("Bad access type", nexttoken, nexttype);
1396 	free_node(np);
1397 	return 0;
1398     }
1399 
1400 /*
1401 -- Olivier Reisacher 95/2/14
1402 */
1403 	switch(type)
1404 	{
1405 		case READONLY:
1406 			np->access = READ_FLAG;
1407 			break;
1408 
1409 		case READWRITE:
1410 			np->access = READ_FLAG | WRITE_FLAG;
1411 			break;
1412 
1413 		case WRITEONLY:
1414 			np->access = WRITE_FLAG;
1415 			break;
1416 
1417 		case NOACCESS:
1418 			np->access = 0;
1419 			break;
1420 
1421 		case READCREATE:
1422 			np->access = READ_FLAG | CREATE_FLAG;
1423 			break;
1424 	}
1425 
1426     type = get_token(fp, token);
1427     if (type != STATUS){
1428 	print_error("Should be STATUS", token, nexttype);
1429 	free_node(np);
1430 	return 0;
1431     }
1432     type = get_token(fp, token);
1433     if (type != MANDATORY && type != CURRENT && type != OPTIONAL && type != OBSOLETE && type != DEPRECATED){
1434 	print_error("Bad status", token, type);
1435 	free_node(np);
1436 	return 0;
1437     }
1438     /*
1439      * Optional parts of the OBJECT-TYPE macro
1440      */
1441     type = get_token(fp, token);
1442     while (type != EQUALS) {
1443       switch (type) {
1444         case DESCRIPTION:
1445           type = get_token(fp, token);
1446           if (type != QUOTESTRING) {
1447               print_error("Bad DESCRIPTION", token, type);
1448               free_node(np);
1449               return 0;
1450           }
1451 #ifdef TEST
1452 printf("Description== \"%.50s\"\n", quoted_string_buffer);
1453 #endif
1454 	  np->description = quoted_string_buffer;
1455 	  quoted_string_buffer = (char *)malloc(MAXQUOTESTR);
1456 	  if (!quoted_string_buffer){
1457 	    fprintf(stderr, "malloc failed.  Exiting\n");
1458 	    exit(1);
1459 	  }
1460           break;
1461 
1462 	case REFERENCE:
1463 	  type = get_token(fp, token);
1464 	  if (type != QUOTESTRING) {
1465 	      print_error("Bad DESCRIPTION", token, type);
1466 	      free_node(np);
1467 	      return 0;
1468 	  }
1469 	  break;
1470 /*
1471 -- Olivier Reisacher 95/2/14
1472 */
1473        	case INDEX:
1474 		np->type = PSEUDO_TOKEN_ENTRY;
1475 
1476 		type = get_token(fp, token);
1477 		if(type != LEFTBRACKET)
1478 		{
1479 			print_error("{ expected in INDEX clause",token,type);
1480 			free_node(np);
1481 			return 0;
1482 		}
1483 		type = get_token(fp, token);
1484 		while(type != RIGHTBRACKET)
1485 		{
1486 			if(type != LABEL)
1487 			{
1488 				print_error("LABEL expected in INDEX clause",token,type);
1489 				free_node(np);
1490 				return 0;
1491 			}
1492 
1493 
1494 			(np->n_indexs)++;
1495 		    	if(np->indexs == NULL)
1496 			{
1497 				ip = np->indexs = (struct index_list *)
1498 					Malloc(sizeof(struct index_list));
1499 			}
1500 			else
1501 			{
1502 				ip->next = (struct index_list *)
1503 					Malloc(sizeof(struct enum_list));
1504 				ip = ip->next;
1505 			}
1506 			ip->next = 0;
1507 			ip->tp = NULL;
1508 
1509 			ip->label =
1510 				(char *)Malloc((unsigned)strlen(token) + 1);
1511 			strcpy(ip->label, token);
1512 
1513 			type = get_token(fp, token);
1514 
1515 			switch(type)
1516 			{
1517 				case COMMA:
1518 					type = get_token(fp, token);
1519 					break;
1520 
1521 				case RIGHTBRACKET:
1522 					break;
1523 
1524 				default:
1525 					print_error(", or } expected in INDEX clause",token,type);
1526 					free_node(np);
1527 					return 0;
1528 
1529 			}
1530 		}
1531 		break;
1532 
1533         case DEFVAL:
1534 	case AUGMENTS:
1535 	case NUM_ENTRIES:
1536           if (tossObjectIdentifier(fp) != PARSE_OBJID) {
1537               print_error("Bad Object Identifier", token, type);
1538               free_node(np);
1539               return 0;
1540           }
1541           break;
1542 
1543         default:
1544           print_error("Bad format of optional clauses", token,type);
1545           free_node(np);
1546           return 0;
1547 
1548       }
1549       type = get_token(fp, token);
1550     }
1551     if (type != EQUALS){
1552 	print_error("Bad format", token, type);
1553 	free_node(np);
1554 	return 0;
1555     }
1556     length = getoid(fp, oid, 32);
1557     if (length > 1 && length <= 32){
1558 	/* just take the last pair in the oid list */
1559 	if (oid[length - 2].label)
1560 	    strncpy(np->parent, oid[length - 2].label, MAXLABEL);
1561 	strcpy(np->label, name);
1562 	if (oid[length - 1].subid != -1)
1563 	    np->subid = oid[length - 1].subid;
1564 	else
1565 	    print_error("Warning: This entry is pretty silly", np->label, type);
1566     } else {
1567 	print_error("No end to oid", (char *)NULL, type);
1568 	free_node(np);
1569 	np = 0;
1570     }
1571     /* free oid array */
1572     for(count = 0; count < length; count++){
1573 	if (oid[count].label)
1574 	    free(oid[count].label);
1575 	oid[count].label = 0;
1576     }
1577     return np;
1578 }
1579 
1580 
1581 /*
1582  * Parses an OBJECT GROUP macro.
1583  * Returns 0 on error.
1584  */
1585 static struct node *
parse_objectgroup(fp,name)1586 parse_objectgroup(fp, name)
1587     register FILE *fp;
1588     char *name;
1589 {
1590     register int type;
1591     char token[MAXTOKEN];
1592     int count, length;
1593     struct subid oid[32];
1594     register struct node *np;
1595 
1596     np = (struct node *)Malloc(sizeof(struct node));
1597     np->type = 0;
1598     np->next = 0;
1599     np->enums = 0;
1600     np->description = NULL;        /* default to an empty description */
1601 
1602 /*
1603 -- Olivier Reisacher 95/2/14
1604 */
1605 	np->access = 0;
1606 	np->n_indexs = 0;
1607 	np->indexs = 0;
1608 
1609     type = get_token(fp, token);
1610     while (type != EQUALS) {
1611       switch (type) {
1612         case DESCRIPTION:
1613           type = get_token(fp, token);
1614           if (type != QUOTESTRING) {
1615               print_error("Bad DESCRIPTION", token, type);
1616               free_node(np);
1617               return 0;
1618           }
1619 #ifdef TEST
1620 printf("Description== \"%.50s\"\n", quoted_string_buffer);
1621 #endif
1622 	  np->description = quoted_string_buffer;
1623 	  quoted_string_buffer = (char *)malloc(MAXQUOTESTR);
1624 	  if (!quoted_string_buffer){
1625 	    fprintf(stderr, "malloc failed.  Exiting\n");
1626 	    exit(1);
1627 	  }
1628           break;
1629 
1630         default:
1631 	  /* NOTHING */
1632 	  break;
1633       }
1634       type = get_token(fp, token);
1635     }
1636     length = getoid(fp, oid, 32);
1637     if (length > 1 && length <= 32){
1638 	/* just take the last pair in the oid list */
1639 	if (oid[length - 2].label)
1640 	    strncpy(np->parent, oid[length - 2].label, MAXLABEL);
1641 	strcpy(np->label, name);
1642 	if (oid[length - 1].subid != -1)
1643 	    np->subid = oid[length - 1].subid;
1644 	else
1645 	    print_error("Warning: This entry is pretty silly", np->label, type);
1646     } else {
1647 	print_error("No end to oid", (char *)NULL, type);
1648 	free_node(np);
1649 	np = 0;
1650     }
1651     /* free oid array */
1652     for(count = 0; count < length; count++){
1653 	if (oid[count].label)
1654 	    free(oid[count].label);
1655 	oid[count].label = 0;
1656     }
1657     return np;
1658 }
1659 
1660 /*
1661  * Parses a NOTIFICATION-TYPE macro.
1662  * Returns 0 on error.
1663  */
1664 static struct node *
parse_notificationDefinition(fp,name)1665 parse_notificationDefinition(fp, name)
1666     register FILE *fp;
1667     char *name;
1668 {
1669     register int type;
1670     char token[MAXTOKEN];
1671     int count, length;
1672     struct subid oid[32];
1673     register struct node *np;
1674 
1675     np = (struct node *)Malloc(sizeof(struct node));
1676     np->type = 0;
1677     np->next = 0;
1678     np->enums = 0;
1679     np->description = NULL;        /* default to an empty description */
1680 /*
1681 -- Olivier Reisacher 95/2/14
1682 */
1683 	np->access = 0;
1684 	np->n_indexs = 0;
1685 	np->indexs = 0;
1686 
1687     type = get_token(fp, token);
1688     while (type != EQUALS) {
1689       switch (type) {
1690         case DESCRIPTION:
1691           type = get_token(fp, token);
1692           if (type != QUOTESTRING) {
1693               print_error("Bad DESCRIPTION", token, type);
1694               free_node(np);
1695               return 0;
1696           }
1697 #ifdef TEST
1698 printf("Description== \"%.50s\"\n", quoted_string_buffer);
1699 #endif
1700 	  np->description = quoted_string_buffer;
1701 	  quoted_string_buffer = (char *)malloc(MAXQUOTESTR);
1702 	  if (!quoted_string_buffer){
1703 	    fprintf(stderr, "malloc failed.  Exiting\n");
1704 	    exit(1);
1705 	  }
1706           break;
1707 
1708         default:
1709 	  /* NOTHING */
1710 	  break;
1711       }
1712       type = get_token(fp, token);
1713     }
1714     length = getoid(fp, oid, 32);
1715     if (length > 1 && length <= 32){
1716 	/* just take the last pair in the oid list */
1717 	if (oid[length - 2].label)
1718 	    strncpy(np->parent, oid[length - 2].label, MAXLABEL);
1719 	strcpy(np->label, name);
1720 	if (oid[length - 1].subid != -1)
1721 	    np->subid = oid[length - 1].subid;
1722 	else
1723 	    print_error("Warning: This entry is pretty silly", np->label, type);
1724     } else {
1725 	print_error("No end to oid", (char *)NULL, type);
1726 	free_node(np);
1727 	np = 0;
1728     }
1729     /* free oid array */
1730     for(count = 0; count < length; count++){
1731 	if (oid[count].label)
1732 	    free(oid[count].label);
1733 	oid[count].label = 0;
1734     }
1735     return np;
1736 }
1737 
1738 /*
1739  * Parses a compliance macro
1740  * Returns 0 on error.
1741  */
1742 static struct node *
parse_compliance(fp,name)1743 parse_compliance(fp, name)
1744     register FILE *fp;
1745     char *name;
1746 {
1747     register int type;
1748     char token[MAXTOKEN];
1749     int count, length;
1750     struct subid oid[32];
1751     register struct node *np;
1752 
1753     np = (struct node *)Malloc(sizeof(struct node));
1754     np->type = 0;
1755     np->next = 0;
1756     np->enums = 0;
1757     np->description = NULL;        /* default to an empty description */
1758 /*
1759 -- Olivier Reisacher 95/2/14
1760 */
1761 	np->access = 0;
1762 	np->n_indexs = 0;
1763 	np->indexs = 0;
1764 
1765     type = get_token(fp, token);
1766     while (type != EQUALS) {
1767 	type = get_token(fp, token);
1768     }
1769     length = getoid(fp, oid, 32);
1770     if (length > 1 && length <= 32){
1771 	/* just take the last pair in the oid list */
1772 	if (oid[length - 2].label)
1773 	    strncpy(np->parent, oid[length - 2].label, MAXLABEL);
1774 	strcpy(np->label, name);
1775 	if (oid[length - 1].subid != -1)
1776 	    np->subid = oid[length - 1].subid;
1777 	else
1778 	    print_error("Warning: This entry is pretty silly", np->label, type);
1779     } else {
1780 	print_error("No end to oid", (char *)NULL, type);
1781 	free_node(np);
1782 	np = 0;
1783     }
1784     /* free oid array */
1785     for(count = 0; count < length; count++){
1786 	if (oid[count].label)
1787 	    free(oid[count].label);
1788 	oid[count].label = 0;
1789     }
1790     return np;
1791 }
1792 
1793 
1794 
1795 /*
1796  * Parses a module identity macro
1797  * Returns 0 on error.
1798  */
1799 static struct node *
parse_moduleIdentity(fp,name)1800 parse_moduleIdentity(fp, name)
1801     register FILE *fp;
1802     char *name;
1803 {
1804     register int type;
1805     char token[MAXTOKEN];
1806     int count, length;
1807     struct subid oid[32];
1808     register struct node *np;
1809 
1810     np = (struct node *)Malloc(sizeof(struct node));
1811     np->type = 0;
1812     np->next = 0;
1813     np->enums = 0;
1814     np->description = NULL;        /* default to an empty description */
1815 /*
1816 -- Olivier Reisacher 95/2/14
1817 */
1818 	np->n_indexs = 0;
1819 	np->indexs = 0;
1820 	np->access = 0;
1821 
1822     type = get_token(fp, token);
1823     while (type != EQUALS) {
1824 	type = get_token(fp, token);
1825     }
1826     length = getoid(fp, oid, 32);
1827     if (length > 1 && length <= 32){
1828 	/* just take the last pair in the oid list */
1829 	if (oid[length - 2].label)
1830 	    strncpy(np->parent, oid[length - 2].label, MAXLABEL);
1831 	strcpy(np->label, name);
1832 	if (oid[length - 1].subid != -1)
1833 	    np->subid = oid[length - 1].subid;
1834 	else
1835 	    print_error("Warning: This entry is pretty silly", np->label, type);
1836     } else {
1837 	print_error("No end to oid", (char *)NULL, type);
1838 	free_node(np);
1839 	np = 0;
1840     }
1841     /* free oid array */
1842     for(count = 0; count < length; count++){
1843 	if (oid[count].label)
1844 	    free(oid[count].label);
1845 	oid[count].label = 0;
1846     }
1847     return np;
1848 }
1849 
parse_mib_header(fp,name)1850 int parse_mib_header(fp, name)
1851     register FILE *fp;
1852     char *name;
1853 {
1854     int type = DEFINITIONS;
1855     char token[MAXTOKEN];
1856 
1857 #ifdef TRACE_PROC
1858 printf("parse_mib_header() invoked\n");
1859 #endif
1860 
1861     /* This probably isn't good enough.  If there is no
1862        imports clause we can't go around waiting (forever) for a semicolon.
1863        We need to check for semi following an EXPORTS clause or an IMPORTS
1864        clause of both.  Look for BEGIN; in my initial MIBs to see those
1865        that I needed to hack to get to parse because they didn't have
1866        an IMPORTS or and EXPORTS clause.
1867        */
1868     while(type != SEMI){
1869 	type = get_token(fp, token);
1870     }
1871     return 1;
1872 }
1873 
1874 
1875 /*
1876 -- Olivier Reisacher 95/2/14
1877 */
parse_init()1878 void parse_init()
1879 {
1880 	hash_init();
1881 	memset((void *) tclist, 0, 64 * sizeof(struct tc));
1882 }
1883 
1884 
1885 /*
1886  * Parses a mib file and returns a linked list of nodes found in the file.
1887  * Returns NULL on error.
1888  */
1889 /*
1890 -- Olivier Reisacher 95/2/14
1891 static struct node *
1892 */
1893 struct node *
parse(fp)1894 parse(fp)
1895     FILE *fp;
1896 {
1897     char token[MAXTOKEN];
1898     char name[MAXTOKEN];
1899     int	type = 1;
1900 #define BETWEEN_MIBS  	      1
1901 #define IN_MIB                2
1902     int state = BETWEEN_MIBS;
1903     struct node *np, *root = NULL;
1904 
1905 #ifdef TRACE_PROC
1906 printf("parse() invoked\n");
1907 #endif
1908 
1909 /*
1910 -- Olivier Reisacher 95/2/14
1911     hash_init();
1912 */
1913     Line = 1;
1914 
1915     quoted_string_buffer = (char *)malloc(MAXQUOTESTR);  /* free this later */
1916     if (!quoted_string_buffer){
1917       fprintf(stderr, "malloc failed.  Exiting\n");
1918       exit(1);
1919     }
1920 
1921 /*
1922 -- Olivier Reisacher 95/2/14
1923     bzero(tclist, 64 * sizeof(struct tc));
1924 */
1925 
1926     while(type != ENDOFFILE){
1927 	type = get_token(fp, token);
1928 skipget:
1929 	if (type == END){
1930 	    if (state != IN_MIB){
1931 		print_error("Error, end before start of MIB.", (char *)NULL, type);
1932 		return NULL;
1933 	    }
1934 	    state = BETWEEN_MIBS;
1935 	    continue;
1936 	} else if (type != LABEL){
1937 	    if (type == ENDOFFILE){
1938 		return root;
1939 	    }
1940 	    print_error(token, "is a reserved word", type);
1941 	    return NULL;
1942 	}
1943 	strncpy(name, token, MAXTOKEN);
1944 	type = get_token(fp, token);
1945 	if (type == DEFINITIONS){
1946 	    if (state != BETWEEN_MIBS){
1947 		print_error("Error, nested MIBS.", (char *)NULL, type);
1948 		return NULL;
1949 	    }
1950 	    state = IN_MIB;
1951 	    if (!parse_mib_header(fp, name)){
1952 		print_error("Bad parse of module header", (char *)NULL, type);
1953 		return NULL;
1954 	    }
1955        } else if (type == OBJTYPE){
1956 	    if (root == NULL){
1957 		/* first link in chain */
1958 		np = root = parse_objecttype(fp, name);
1959 		if (np == NULL){
1960 		    print_error("Bad parse of object type", (char *)NULL,
1961 				type);
1962 		    return NULL;
1963 		}
1964 	    } else {
1965 		np->next = parse_objecttype(fp, name);
1966 		if (np->next == NULL){
1967 		    print_error("Bad parse of objecttype", (char *)NULL,
1968 				type);
1969 		    return NULL;
1970 		}
1971 	    }
1972 	    /* now find end of chain */
1973 	    while(np->next)
1974 		np = np->next;
1975 	} else if (type == OBJGROUP){
1976 	    if (root == NULL){
1977 		/* first link in chain */
1978 		np = root = parse_objectgroup(fp, name);
1979 		if (np == NULL){
1980 		    print_error("Bad parse of object group", (char *)NULL,
1981 				type);
1982 		    return NULL;
1983 		}
1984 	    } else {
1985 		np->next = parse_objectgroup(fp, name);
1986 		if (np->next == NULL){
1987 		    print_error("Bad parse of objectgroup", (char *)NULL,
1988 				type);
1989 		    return NULL;
1990 		}
1991 	    }
1992 	    /* now find end of chain */
1993 	    while(np->next)
1994 		np = np->next;
1995 	} else if (type == NOTIFTYPE){
1996 	    if (root == NULL){
1997 		/* first link in chain */
1998 		np = root = parse_notificationDefinition(fp, name);
1999 		if (np == NULL){
2000 		    print_error("Bad parse of notification definition",
2001 				(char *)NULL, type);
2002 		    return NULL;
2003 		}
2004 	    } else {
2005 		np->next = parse_notificationDefinition(fp, name);
2006 		if (np->next == NULL){
2007 		    print_error("Bad parse of notification definition",
2008 				(char *)NULL, type);
2009 		    return NULL;
2010 		}
2011 	    }
2012 	    /* now find end of chain */
2013 	    while(np->next)
2014 		np = np->next;
2015 	} else if (type == COMPLIANCE){
2016 	    if (root == NULL){
2017 		/* first link in chain */
2018 		np = root = parse_compliance(fp, name);
2019 		if (np == NULL){
2020 		    print_error("Bad parse of module compliance", (char *)NULL,
2021 				type);
2022 		    return NULL;
2023 		}
2024 	    } else {
2025 		np->next = parse_compliance(fp, name);
2026 		if (np->next == NULL){
2027 		    print_error("Bad parse of module compliance", (char *)NULL,
2028 				type);
2029 		    return NULL;
2030 		}
2031 	    }
2032 	    /* now find end of chain */
2033 	    while(np->next)
2034 		np = np->next;
2035 	} else if (type == MODULEIDENTITY){
2036 	    if (root == NULL){
2037 		/* first link in chain */
2038 		np = root = parse_moduleIdentity(fp, name);
2039 		if (np == NULL){
2040 		    print_error("Bad parse of module identity", (char *)NULL,
2041 				type);
2042 		    return NULL;
2043 		}
2044 	    } else {
2045 		np->next = parse_moduleIdentity(fp, name);
2046 		if (np->next == NULL){
2047 		    print_error("Bad parse of module identity", (char *)NULL,
2048 				type);
2049 		    return NULL;
2050 		}
2051 	    }
2052 	    /* now find end of chain */
2053 	    while(np->next)
2054 		np = np->next;
2055 	} else if (type == PARSE_OBJID){
2056 	    if (root == NULL){
2057 		/* first link in chain */
2058 		np = root = parse_objectid(fp, name);
2059 		if (np == NULL){
2060 		    print_error("Bad parse of object id", (char *)NULL, type);
2061 		    return NULL;
2062 		}
2063 	    } else {
2064 		np->next = parse_objectid(fp, name);
2065 		if (np->next == NULL){
2066 		    print_error("Bad parse of object type", (char *)NULL,
2067 				type);
2068 		    return NULL;
2069 		}
2070 	    }
2071 	    /* now find end of chain */
2072 	    while(np->next)
2073 		np = np->next;
2074 	} else if (type == EQUALS){
2075 	    if (!parse_asntype(fp, name, &type, token)){
2076 		print_error("Bad parse of ASN type definition.", (char*)NULL, EQUALS);
2077 		return NULL;
2078 	    }
2079 	    goto skipget;
2080 	} else if (type == TRAPTYPE){ /* Jerry Yeung 6-6-96 */
2081 	    if(!parse_traptype(fp,name)){
2082 		 print_error("Bad parse of TRAP type",(char*)NULL,type);
2083 		 return NULL;
2084 	    }
2085 	} else if (type == ENDOFFILE){
2086 	    break;
2087 	} else {
2088 	    print_error("Bad operator", (char *)NULL, type);
2089 	    return NULL;
2090 	}
2091     }
2092 #ifdef TEST
2093 {
2094     struct enum_list *ep;
2095 
2096     for(np = root; np; np = np->next){
2097 	printf("%s ::= { %s %d } (%d)\n", np->label, np->parent, np->subid,
2098 		np->type);
2099 	if (np->enums){
2100 	    printf("Enums: \n");
2101 	    for(ep = np->enums; ep; ep = ep->next){
2102 		printf("%s(%d)\n", ep->label, ep->value);
2103 	    }
2104 	}
2105     }
2106 }
2107 #endif /* TEST */
2108     return root;
2109 }
2110 
2111 /*
2112  * Parses a token from the file.  The type of the token parsed is returned,
2113  * and the text is placed in the string pointed to by token.
2114  */
2115 static int
get_token(fp,token)2116 get_token(fp, token)
2117     register FILE *fp;
2118     register char *token;
2119 {
2120     static char last = ' ';
2121     register int ch;
2122     register char *cp = token;
2123     register int hash = 0;
2124     register struct tok *tp;
2125 
2126     *cp = 0;
2127     ch = last;
2128     /* skip all white space */
2129     while(isspace(ch) && ch != -1){
2130 	ch = getc(fp);
2131 	if (ch == '\n')
2132 	    Line++;
2133     }
2134     if (ch == -1) {
2135 #ifdef TRACE_GET_TOKEN
2136 print_error("TRACE", token, ENDOFFILE);
2137 #endif
2138 	return ENDOFFILE;
2139     } else if (ch == '"') {
2140 	return parseQuoteString(fp, token);
2141     }
2142 
2143     /*
2144      * Accumulate characters until end of token is found.  Then attempt to
2145      * match this token as a reserved word.  If a match is found, return the
2146      * type.  Else it is a label.
2147      */
2148     do {
2149 	if (ch == '\n')
2150 	    Line++;
2151 	if (isspace(ch) || ch == '(' || ch == ')' || ch == '{' || ch == '}' ||
2152 	    ch == ',' || ch == ';'){
2153 	    if (!isspace(ch) && *token == 0){
2154 		hash += ch;
2155 		*cp++ = ch;
2156 		last = ' ';
2157 	    } else {
2158 		last = ch;
2159 	    }
2160 	    *cp = '\0';
2161 
2162 	    for (tp = buckets[BUCKET(hash)]; tp; tp = tp->next) {
2163 		if ((tp->hash == hash) && (strcmp(tp->name, token) == 0))
2164 			break;
2165 	    }
2166 	    if (tp){
2167 		if (tp->token == CONTINUE)
2168 		    continue;
2169 #ifdef TRACE_GET_TOKEN
2170 print_error("TRACE", token, tp->token);
2171 #endif
2172 		return (tp->token);
2173 	    }
2174 
2175 	    if (token[0] == '-' && token[1] == '-'){
2176 		/* strip comment */
2177 		if (ch != '\n'){
2178 		    while ((ch = getc(fp)) != -1)
2179 			if (ch == '\n'){
2180 			    Line++;
2181 			    break;
2182 			}
2183 		}
2184 		if (ch == -1)
2185 {
2186 #ifdef TRACE_GET_TOKEN
2187 print_error("TRACE", token, ENDOFFILE);
2188 #endif
2189 		    return ENDOFFILE;
2190 }
2191 		last = ch;
2192 		return get_token(fp, token);
2193 	    }
2194 	    for(cp = token; *cp; cp++)
2195 		if (!isdigit(*cp))
2196 {
2197 #ifdef TRACE_GET_TOKEN
2198 print_error("TRACE", token, LABEL);
2199 #endif
2200 		    return LABEL;
2201 }
2202 #ifdef TRACE_GET_TOKEN
2203 print_error("TRACE", token, NUMBER);
2204 #endif
2205             number_value = atoi(token);   /* octet string size */
2206 	    return NUMBER;
2207 	} else {
2208 	    hash += ch;
2209 	    *cp++ = ch;
2210 	    if (ch == '\n')
2211 		Line++;
2212 	}
2213 
2214     } while ((ch = getc(fp)) != -1);
2215 #ifdef TRACE_GET_TOKEN
2216 print_error("TRACE", token, ENDOFFILE);
2217 #endif
2218     return ENDOFFILE;
2219 }
2220 
2221 struct tree *
read_mib(filename)2222 read_mib(filename)
2223     char *filename;
2224 {
2225     FILE *fp;
2226     struct node *nodes;
2227     struct tree *tree;
2228 
2229     fp = fopen(filename, "r");
2230     if (fp == NULL)
2231 	return NULL;
2232     nodes = parse(fp);
2233     if (!nodes){
2234 	fprintf(stderr, "Mib table is bad.  Exiting\n");
2235 	exit(1);
2236     }
2237     tree = build_tree(nodes);
2238     fclose(fp);
2239     return tree;
2240 }
2241 
2242 
2243 #ifdef TEST
main(argc,argv)2244 main(argc, argv)
2245     int argc;
2246     char *argv[];
2247 {
2248     FILE *fp;
2249     struct node *nodes;
2250     struct tree *tp;
2251 
2252     fp = fopen("mib.txt", "r");
2253     if (fp == NULL){
2254 	fprintf(stderr, "open failed\n");
2255 	return 1;
2256     }
2257     nodes = parse(fp);
2258     if (!nodes){
2259       fprintf(stderr, "Mib table is bad. \n");
2260       return (1);
2261     }
2262     tp = build_tree(nodes);
2263     print_subtree(tp, 0);
2264     fclose(fp);
2265 }
2266 
2267 #endif /* TEST */
2268 
2269 static int
parseQuoteString(fp,token)2270 parseQuoteString(fp, token)
2271     register FILE *fp;
2272     register char *token;
2273 {
2274     register int ch;
2275     register char *ptr, *ptr1;
2276     register int len = 0;
2277 
2278     ch = ' ';
2279     *token = '\0';                      /* make the token empty */
2280 
2281     ptr = quoted_string_buffer;
2282     if (ptr)
2283 	*ptr = 0;
2284 
2285 
2286     while(ch != -1) {
2287         ch = getc(fp);
2288 	if (ch != '"') {
2289 		if (ptr) {
2290 			* ptr ++ = ch;
2291 			len ++;
2292 			if (len % MAXQUOTESTR == 0) {
2293 				ptr1 = (char *) malloc (len + MAXQUOTESTR);
2294 				if (!ptr1){
2295 				  fprintf(stderr, "malloc failed.  Exiting\n");
2296 				  exit(1);
2297 				}
2298 				memcpy (ptr1, quoted_string_buffer, len);
2299 				free (quoted_string_buffer);
2300 				quoted_string_buffer = ptr1;
2301 				ptr = ptr1 + len;
2302 			}
2303 		}
2304 	} else {
2305 		if (ptr)
2306 			* ptr = 0;
2307 	}
2308 	if (ch == '\n')
2309 	    Line++;
2310 	else if (ch == '"') {
2311 #ifdef TRACE_GET_TOKEN
2312 print_error("TRACE", token, QUOTESTRING);
2313 #endif
2314             return QUOTESTRING;
2315         }
2316 
2317     }
2318 
2319 #ifdef TRACE_GET_TOKEN
2320 print_error("TRACE", token, NULL);
2321 #endif
2322     return NULL;
2323 }
2324 
2325 /*
2326  * This routine parses a string like  { blah blah blah } and returns PARSE_OBJID if
2327  * it is well formed, and NULL if not.
2328  */
2329 static int
tossObjectIdentifier(fp)2330 tossObjectIdentifier(fp)
2331     register FILE *fp;
2332 {
2333     register int ch;
2334 
2335         ch = getc(fp);
2336 /*    ch = last; = ' '? */
2337     /* skip all white space */
2338     while(isspace(ch) && ch != -1){
2339         ch = getc(fp);
2340         if (ch == '\n')
2341             Line++;
2342     }
2343     if (ch != '{')
2344         return NULL;
2345 
2346     while(ch != -1) {
2347         ch = getc(fp);
2348 
2349         if (ch == '\n')
2350             Line++;
2351         else if (ch == '}')
2352             return PARSE_OBJID;
2353     }
2354 
2355 /*    last = ch;*/
2356     return NULL;
2357 }
2358