1 /*
2  * parser-smi.y --
3  *
4  *      Syntax rules for parsing the SMIv1/v2 MIB module language.
5  *
6  * Copyright (c) 1999 Frank Strauss, Technical University of Braunschweig.
7  *
8  * See the file "COPYING" for information on usage and redistribution
9  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
10  *
11  * @(#) $Id: parser-smi.y 8090 2008-04-18 12:56:29Z strauss $
12  */
13 
14 %{
15 
16 #include <config.h>
17 
18 #ifdef BACKEND_SMI
19 
20 #include <stdio.h>
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <ctype.h>
25 #include <time.h>
26 #include <limits.h>
27 
28 #if defined(_MSC_VER)
29 #include <malloc.h>
30 #endif
31 
32 #include "smi.h"
33 #include "error.h"
34 #include "parser-smi.h"
35 #include "scanner-smi.h"
36 #include "data.h"
37 #include "check.h"
38 #include "util.h"
39 
40 #ifdef HAVE_DMALLOC_H
41 #include <dmalloc.h>
42 #endif
43 
44 
45 
46 /*
47  * These arguments are passed to yyparse() and yylex().
48  */
49 #define YYPARSE_PARAM parserPtr
50 #define YYLEX_PARAM   parserPtr
51 
52 
53 
54 #define thisParserPtr      ((Parser *)parserPtr)
55 #define thisModulePtr     (((Parser *)parserPtr)->modulePtr)
56 
57 
58 
59 /*
60  * NOTE: The argument lvalp is not really a void pointer. Unfortunately,
61  * we don't know it better at this point. bison generated C code declares
62  * YYSTYPE just a few lines below based on the `%union' declaration.
63  */
64 extern int yylex(void *lvalp, Parser *parserPtr);
65 
66 
67 
68 static int	   impliedFlag;
69 static SmiNodekind variationkind;
70 static SmiBasetype defaultBasetype;
71 static int	   indexFlag;
72 
73 /*
74  * Values for the indexFlag variable
75  */
76 #define INDEXFLAG_NONE     0
77 #define INDEXFLAG_PIBINDEX 1
78 #define INDEXFLAG_AUGMENTS 2
79 #define INDEXFLAG_EXTENDS  3
80 
81 
82 #define SMI_EPOCH	631152000	/* 01 Jan 1990 00:00:00 */
83 
84 
85 
86 static char *convertImportv2[] = {
87     "RFC1155-SMI", "internet",	    "SNMPv2-SMI", "internet",
88     "RFC1155-SMI", "directory",	    "SNMPv2-SMI", "directory",
89     "RFC1155-SMI", "mgmt",	    "SNMPv2-SMI", "mgmt",
90     "RFC1155-SMI", "experimental",  "SNMPv2-SMI", "experimental",
91     "RFC1155-SMI", "private",	    "SNMPv2-SMI", "private",
92     "RFC1155-SMI", "enterprises",   "SNMPv2-SMI", "enterprises",
93     "RFC1155-SMI", "IpAddress",     "SNMPv2-SMI", "IpAddress",
94     "RFC1155-SMI", "Counter",       "SNMPv2-SMI", "Counter32",
95     "RFC1155-SMI", "Gauge",         "SNMPv2-SMI", "Gauge32",
96     "RFC1155-SMI", "TimeTicks",     "SNMPv2-SMI", "TimeTicks",
97     "RFC1155-SMI", "Opaque",        "SNMPv2-SMI", "Opaque",
98     "RFC1065-SMI", "internet",	    "SNMPv2-SMI", "internet",
99     "RFC1065-SMI", "directory",	    "SNMPv2-SMI", "directory",
100     "RFC1065-SMI", "mgmt",	    "SNMPv2-SMI", "mgmt",
101     "RFC1065-SMI", "experimental",  "SNMPv2-SMI", "experimental",
102     "RFC1065-SMI", "private",	    "SNMPv2-SMI", "private",
103     "RFC1065-SMI", "enterprises",   "SNMPv2-SMI", "enterprises",
104     "RFC1065-SMI", "IpAddress",     "SNMPv2-SMI", "IpAddress",
105     "RFC1065-SMI", "Counter",       "SNMPv2-SMI", "Counter32",
106     "RFC1065-SMI", "Gauge",         "SNMPv2-SMI", "Gauge32",
107     "RFC1065-SMI", "TimeTicks",     "SNMPv2-SMI", "TimeTicks",
108     "RFC1065-SMI", "Opaque",        "SNMPv2-SMI", "Opaque",
109     "RFC1213-MIB", "mib-2",         "SNMPv2-SMI", "mib-2",
110     "RFC1213-MIB", "DisplayString", "SNMPv2-TC",  "DisplayString",
111     NULL, NULL, NULL, NULL
112 };
113 
114 
115 
116 static void
checkDescr(Parser * parser,char * descr)117 checkDescr(Parser *parser, char *descr)
118 {
119     if (descr) {
120 	if (descr[0] == 0) {
121 	    smiPrintError(parser, ERR_EMPTY_DESCRIPTION);
122 	}
123 	/* we might want to add more checks since I have recently
124 	   seen things like DESCRIPTION "." to cirumvent warnings */
125     }
126 }
127 
128 
129 
130 static void
checkNameLen(Parser * parser,char * name,int error_32,int error_64)131 checkNameLen(Parser *parser, char *name, int error_32, int error_64)
132 {
133     int len = strlen(name);
134 
135     if (len > 64) {
136 	smiPrintError(parser, error_64, name);
137     } else if (len > 32) {
138 	smiPrintError(parser, error_32, name);
139     }
140 }
141 
142 
143 
144 static void
checkModuleName(Parser * parserPtr,Module * modulePtr)145 checkModuleName(Parser *parserPtr, Module *modulePtr)
146 {
147      static char *mib_ignore[] = {
148 	 "SNMPv2-SMI", "SNMPv2-TC", "SNMPv2-CONF", NULL
149      };
150 
151      static char *pib_ignore[] = {
152 	 "COPS-PR-SPPI", "COPS-PR-SPPI-TC",
153 	 "SNMPv2-SMI", "SNMPv2-TC", "SNMPv2-CONF", NULL
154      };
155 
156      const char *name = thisModulePtr->export.name;
157      const int len = strlen(name);
158      int i;
159 
160      switch (modulePtr->export.language) {
161      case SMI_LANGUAGE_SMIV1:
162      case SMI_LANGUAGE_SMIV2:
163      case SMI_LANGUAGE_SMING:
164 	 for (i = 0; mib_ignore[i]; i++) {
165 	     if (strcmp(mib_ignore[i], name) == 0) {
166 		 return;
167 	     }
168 	 }
169 	 if (len > 3 && (strcmp(name + len - 4, "-MIB") != 0)) {
170 	     smiPrintError(parserPtr, ERR_MIB_MODULENAME_SUFFIX, name);
171 	     return;
172 	 }
173 	 break;
174      case SMI_LANGUAGE_SPPI:
175 	 for (i = 0; pib_ignore[i]; i++) {
176 	     if (strcmp(pib_ignore[i], name) == 0) {
177 		 return;
178 	     }
179 	 }
180 	 if (len > 3 && (strcmp(name + len - 4, "-PIB") != 0)) {
181 	     smiPrintError(parserPtr, ERR_PIB_MODULENAME_SUFFIX, name);
182 	 }
183 	 break;
184      case SMI_LANGUAGE_UNKNOWN:
185 	 break;
186      }
187 }
188 
189 
190 
191 static void
checkModuleIdentity(Parser * parserPtr,Module * modulePtr)192 checkModuleIdentity(Parser *parserPtr, Module *modulePtr)
193 {
194     if ((modulePtr->export.language == SMI_LANGUAGE_SMIV2)
195 	&& (modulePtr->numModuleIdentities < 1)
196 	&& strcmp(modulePtr->export.name, "SNMPv2-SMI")
197 	&& strcmp(modulePtr->export.name, "SNMPv2-CONF")
198 	&& strcmp(modulePtr->export.name, "SNMPv2-TC")
199         && strcmp(modulePtr->export.name, "COPS-PR-SPPI")) {
200 	smiPrintError(parserPtr, ERR_NO_MODULE_IDENTITY);
201     }
202 }
203 
204 
205 
206 static void
checkObjects(Parser * parserPtr,Module * modulePtr)207 checkObjects(Parser *parserPtr, Module *modulePtr)
208 {
209     Object *objectPtr;
210     Node *nodePtr;
211     int i;
212     Type *counterTypePtr, *counter32TypePtr, *counter64TypePtr;
213 
214     counterTypePtr = findTypeByName("Counter");
215     counter32TypePtr = findTypeByModulenameAndName("SNMPv2-SMI", "Counter32");
216     counter64TypePtr = findTypeByModulenameAndName("SNMPv2-SMI", "Counter64");
217 
218     for (objectPtr = modulePtr->firstObjectPtr;
219 	 objectPtr; objectPtr = objectPtr->nextPtr) {
220 
221 	Object *parentPtr;
222 
223 	if ((objectPtr->export.decl != SMI_DECL_UNKNOWN) &&
224 	    objectPtr->nodePtr->parentPtr &&
225 	    objectPtr->nodePtr->parentPtr->lastObjectPtr) {
226 	    parentPtr = objectPtr->nodePtr->parentPtr->lastObjectPtr;
227 	} else {
228 	    parentPtr = NULL;
229 	}
230 
231 	/*
232 	 * Set nodekinds of all newly defined objects.
233 	 */
234 
235 	if (objectPtr->export.decl == SMI_DECL_MODULEIDENTITY) {
236 	    objectPtr->export.nodekind = SMI_NODEKIND_NODE;
237 	} else if ((objectPtr->export.decl == SMI_DECL_VALUEASSIGNMENT) ||
238 		   (objectPtr->export.decl == SMI_DECL_OBJECTIDENTITY)) {
239 	    objectPtr->export.nodekind = SMI_NODEKIND_NODE;
240 	} else if ((objectPtr->export.decl == SMI_DECL_OBJECTTYPE) &&
241 		   (objectPtr->typePtr) &&
242 		   (objectPtr->typePtr->export.decl == SMI_DECL_IMPL_SEQUENCEOF)) {
243 	    objectPtr->export.nodekind = SMI_NODEKIND_TABLE;
244 	} else if ((objectPtr->export.decl == SMI_DECL_OBJECTTYPE) &&
245 		   (objectPtr->export.indexkind != SMI_INDEX_UNKNOWN)) {
246 	    objectPtr->export.nodekind = SMI_NODEKIND_ROW;
247 	} else if ((objectPtr->export.decl == SMI_DECL_NOTIFICATIONTYPE) ||
248 		   (objectPtr->export.decl == SMI_DECL_TRAPTYPE)) {
249 	    objectPtr->export.nodekind = SMI_NODEKIND_NOTIFICATION;
250 	} else if ((objectPtr->export.decl == SMI_DECL_OBJECTGROUP) ||
251 		   (objectPtr->export.decl == SMI_DECL_NOTIFICATIONGROUP)) {
252 	    objectPtr->export.nodekind = SMI_NODEKIND_GROUP;
253 	} else if (objectPtr->export.decl == SMI_DECL_MODULECOMPLIANCE) {
254 	    objectPtr->export.nodekind = SMI_NODEKIND_COMPLIANCE;
255 	} else if (objectPtr->export.decl == SMI_DECL_AGENTCAPABILITIES) {
256 	    objectPtr->export.nodekind = SMI_NODEKIND_CAPABILITIES;
257 	} else if ((objectPtr->export.decl == SMI_DECL_OBJECTTYPE) &&
258 		   (parentPtr) &&
259 		   (parentPtr->export.indexkind != SMI_INDEX_UNKNOWN)) {
260 	    objectPtr->export.nodekind = SMI_NODEKIND_COLUMN;
261 	} else if ((objectPtr->export.decl == SMI_DECL_OBJECTTYPE) &&
262 		   (parentPtr) &&
263 		   (parentPtr->export.indexkind == SMI_INDEX_UNKNOWN)) {
264 	    objectPtr->export.nodekind = SMI_NODEKIND_SCALAR;
265 	}
266     }
267 
268     for (objectPtr = modulePtr->firstObjectPtr;
269 	 objectPtr; objectPtr = objectPtr->nextPtr) {
270 
271 	Object *parentPtr;
272 
273 	if (objectPtr->nodePtr->parentPtr &&
274 	    objectPtr->nodePtr->parentPtr->lastObjectPtr) {
275 	    parentPtr = objectPtr->nodePtr->parentPtr->lastObjectPtr;
276 	} else {
277 	    parentPtr = NULL;
278 	}
279 
280 	/*
281 	 * Check whether the associated type resolves to a known base type.
282 	 */
283 
284 	if (objectPtr->typePtr
285 	    && (objectPtr->export.nodekind == SMI_NODEKIND_COLUMN
286 		|| objectPtr->export.nodekind == SMI_NODEKIND_SCALAR)
287 	    && objectPtr->typePtr->export.basetype == SMI_BASETYPE_UNKNOWN) {
288 	    smiPrintErrorAtLine(parserPtr, ERR_BASETYPE_UNKNOWN,
289 				objectPtr->line,
290 				objectPtr->typePtr->export.name ?
291 				objectPtr->typePtr->export.name : "[unknown]",
292 				objectPtr->export.name);
293 	    if (objectPtr->nodePtr->parentPtr->firstObjectPtr->export.nodekind
294 		== SMI_NODEKIND_TABLE) {
295 		/* the parent node is a table node, so assume this is
296 		 *  a row node. this adjusts missing INDEXs in RFC 1158.
297 		 */
298 		objectPtr->export.nodekind = SMI_NODEKIND_ROW;
299 	    }
300 	}
301 
302 	/*
303 	 * Mark types that are referenced in this module.
304 	 */
305 
306 	if (objectPtr->typePtr
307 	    && (objectPtr->export.nodekind == SMI_NODEKIND_COLUMN
308 		|| objectPtr->export.nodekind == SMI_NODEKIND_SCALAR)
309 	    && (objectPtr->typePtr->export.decl == SMI_DECL_TYPEDEF
310 		|| objectPtr->typePtr->export.decl == SMI_DECL_TEXTUALCONVENTION
311 		|| objectPtr->typePtr->export.decl == SMI_DECL_IMPLICIT_TYPE)) {
312 	    addTypeFlags(objectPtr->typePtr, FLAG_INSYNTAX);
313 	    if (objectPtr->typePtr->export.decl == SMI_DECL_IMPLICIT_TYPE) {
314 		addTypeFlags(objectPtr->typePtr->parentPtr, FLAG_INSYNTAX);
315 	    }
316 	}
317 
318 	/*
319 	 * Check whether the status of the associated type matches the
320 	 * status of the object.
321 	 */
322 
323 	if (objectPtr->typePtr
324 	    && (objectPtr->export.nodekind == SMI_NODEKIND_COLUMN
325 		|| objectPtr->export.nodekind == SMI_NODEKIND_SCALAR)
326 	    && (objectPtr->export.status < objectPtr->typePtr->export.status)) {
327 	    if (objectPtr->typePtr->export.status == SMI_STATUS_DEPRECATED) {
328 		smiPrintErrorAtLine(parserPtr, ERR_TYPE_STATUS_DEPRECATED,
329 				    objectPtr->line,
330 				    objectPtr->typePtr->export.name,
331 				    objectPtr->export.name);
332 	    }
333 	    if (objectPtr->typePtr->export.status == SMI_STATUS_OBSOLETE) {
334 		smiPrintErrorAtLine(parserPtr, ERR_TYPE_STATUS_OBSOLETE,
335 				    objectPtr->line,
336 				    objectPtr->typePtr->export.name,
337 				    objectPtr->export.name);
338 	    }
339 	}
340 
341 	/*
342 	 * Check the nodekind of the parent node.
343 	 */
344 
345 	if (parentPtr) {
346 	    switch (objectPtr->export.nodekind) {
347 	    case SMI_NODEKIND_COLUMN:
348 		if (parentPtr->export.nodekind != SMI_NODEKIND_ROW) {
349 		    smiPrintErrorAtLine(parserPtr, ERR_COLUMN_PARENT_TYPE,
350 					objectPtr->line, objectPtr->export.name);
351 		}
352 		break;
353 	    case SMI_NODEKIND_ROW:
354 		if (parentPtr->export.nodekind != SMI_NODEKIND_TABLE) {
355 		    smiPrintErrorAtLine(parserPtr, ERR_ROW_PARENT_TYPE,
356 					objectPtr->line, objectPtr->export.name);
357 		}
358 		if (parentPtr->typePtr && parentPtr->typePtr->parentPtr &&
359 		    strcmp(parentPtr->typePtr->parentPtr->export.name,
360 			   objectPtr->typePtr->export.name)) {
361 		    smiPrintErrorAtLine(parserPtr, ERR_TABLE_ROW_TYPE_MISMATCH,
362 					objectPtr->line,
363 					objectPtr->export.name);
364 		}
365 		break;
366 	    case SMI_NODEKIND_TABLE:
367 		if ((parentPtr->export.nodekind != SMI_NODEKIND_UNKNOWN) &&
368 		    (parentPtr->export.nodekind != SMI_NODEKIND_NODE)) {
369 		    smiPrintErrorAtLine(parserPtr, ERR_TABLE_PARENT_TYPE,
370 					objectPtr->line, objectPtr->export.name);
371 		}
372 		break;
373 	    case SMI_NODEKIND_SCALAR:
374 		if ((parentPtr->export.nodekind != SMI_NODEKIND_UNKNOWN) &&
375 		    (parentPtr->export.nodekind != SMI_NODEKIND_NODE)) {
376 		    smiPrintErrorAtLine(parserPtr, ERR_SCALAR_PARENT_TYPE,
377 					objectPtr->line, objectPtr->export.name);
378 		}
379 		break;
380 	    case SMI_NODEKIND_NOTIFICATION:
381 		if ((parentPtr->export.nodekind != SMI_NODEKIND_NODE) &&
382 		    (parentPtr->export.nodekind != SMI_NODEKIND_UNKNOWN)) {
383 		    smiPrintErrorAtLine(parserPtr, ERR_NOTIFICATION_PARENT_TYPE,
384 					objectPtr->line, objectPtr->export.name);
385 		}
386 		if (parserPtr && parentPtr->nodePtr->parentPtr &&
387 		    parentPtr->nodePtr->parentPtr->lastObjectPtr) {
388 		    Object *parent2Ptr = parentPtr->nodePtr->parentPtr->lastObjectPtr;
389 		    if ((parent2Ptr->export.nodekind != SMI_NODEKIND_NODE) &&
390 			(parent2Ptr->export.nodekind != SMI_NODEKIND_UNKNOWN)) {
391 			smiPrintErrorAtLine(parserPtr,
392 					    ERR_NOTIFICATION_PARENT_TYPE,
393 					    objectPtr->line,
394 					    objectPtr->export.name);
395 		    }
396 		}
397 		break;
398 	    case SMI_NODEKIND_NODE:
399 		/* Node defined by OBJECT IDENTIFIER assignments can have
400 		   arbitrary parent node. */
401 		if ((parentPtr->export.nodekind != SMI_NODEKIND_UNKNOWN) &&
402 		    (parentPtr->export.nodekind != SMI_NODEKIND_NODE) &&
403 		    (objectPtr->export.decl != SMI_DECL_VALUEASSIGNMENT)) {
404 		    smiPrintErrorAtLine(parserPtr, ERR_NODE_PARENT_TYPE,
405 					objectPtr->line, objectPtr->export.name);
406 		}
407 		break;
408 	    case SMI_NODEKIND_GROUP:
409 		if ((parentPtr->export.nodekind != SMI_NODEKIND_UNKNOWN) &&
410 		    (parentPtr->export.nodekind != SMI_NODEKIND_NODE)) {
411 		    smiPrintErrorAtLine(parserPtr, ERR_GROUP_PARENT_TYPE,
412 					objectPtr->line, objectPtr->export.name);
413 		}
414 		break;
415 	    case SMI_NODEKIND_COMPLIANCE:
416 		if ((parentPtr->export.nodekind != SMI_NODEKIND_UNKNOWN) &&
417 		    (parentPtr->export.nodekind != SMI_NODEKIND_NODE)) {
418 		    smiPrintErrorAtLine(parserPtr, ERR_COMPLIANCE_PARENT_TYPE,
419 					objectPtr->line, objectPtr->export.name);
420 		}
421 		break;
422 	    case SMI_NODEKIND_CAPABILITIES:
423 		if ((parentPtr->export.nodekind != SMI_NODEKIND_UNKNOWN) &&
424 		    (parentPtr->export.nodekind != SMI_NODEKIND_NODE)) {
425 		    smiPrintErrorAtLine(parserPtr, ERR_CAPABILITIES_PARENT_TYPE,
426 					objectPtr->line, objectPtr->export.name);
427 		}
428 		break;
429 	    }
430 	}
431 
432 	/*
433 	 * Check whether groups only contain scalars, columns and
434 	 * notifications.
435 	 */
436 
437 	if (objectPtr->export.nodekind == SMI_NODEKIND_GROUP) {
438 	    smiCheckGroupMembers(parserPtr, objectPtr);
439 	}
440 
441 	/*
442 	 * Check whether compliance statements contain out of date
443 	 * groups or objects.
444 	 */
445 
446 	if (objectPtr->export.nodekind == SMI_NODEKIND_COMPLIANCE) {
447 	    smiCheckComplianceStatus(parserPtr, objectPtr);
448 	}
449 
450 	/*
451 	 * Check whether notification statements contain useful
452 	 * objects.
453 	 */
454 
455 	if (objectPtr->export.nodekind == SMI_NODEKIND_NOTIFICATION) {
456 	    smiCheckNotificationOid(parserPtr, modulePtr, objectPtr);
457 	    smiCheckNotificationMembers(parserPtr, objectPtr);
458 	}
459 
460         if (modulePtr->export.language != SMI_LANGUAGE_SPPI) {
461 	    /*
462 	     * Check whether tables and rows are not accessible
463 	     * (RFC 2578 7.1.12).
464 	     */
465 
466 	    if (objectPtr->export.nodekind == SMI_NODEKIND_TABLE
467 	        && objectPtr->export.access != SMI_ACCESS_NOT_ACCESSIBLE) {
468 	        smiPrintErrorAtLine(parserPtr, ERR_TABLE_ACCESS,
469 				    objectPtr->line, objectPtr->export.name);
470 	    }
471 
472 	    if (objectPtr->export.nodekind == SMI_NODEKIND_ROW
473 	        && objectPtr->export.access != SMI_ACCESS_NOT_ACCESSIBLE) {
474 	        smiPrintErrorAtLine(parserPtr, ERR_ROW_ACCESS,
475 				    objectPtr->line, objectPtr->export.name);
476 	    }
477 
478 	    /*
479 	     * Check whether counter objects are read-only or
480 	     * accessible-for-notify (RFC 2578, 7.1.6).
481 	     */
482 	    if (((objectPtr->export.nodekind == SMI_NODEKIND_SCALAR) ||
483 		 (objectPtr->export.nodekind == SMI_NODEKIND_COLUMN)) &&
484 	        (objectPtr->export.access != SMI_ACCESS_NOTIFY) &&
485 		(objectPtr->export.access != SMI_ACCESS_READ_ONLY) &&
486 		(smiTypeDerivedFrom(objectPtr->typePtr, counterTypePtr) ||
487 		 smiTypeDerivedFrom(objectPtr->typePtr, counter32TypePtr) ||
488 		 smiTypeDerivedFrom(objectPtr->typePtr, counter64TypePtr))) {
489 	        smiPrintErrorAtLine(parserPtr, ERR_COUNTER_ACCESS,
490 				    objectPtr->line, objectPtr->export.name);
491 	    }
492         }
493 
494 	/*
495 	 * Check whether a row's subid is 1, see RFC 2578 7.10 (1).
496 	 */
497 
498 	if (objectPtr->export.nodekind == SMI_NODEKIND_ROW) {
499 	    int len;
500 
501 	    if (objectPtr->nodePtr->subid != 1) {
502 		smiPrintErrorAtLine(parserPtr, ERR_ROW_SUBID_ONE,
503 				    objectPtr->line, objectPtr->export.name);
504 	    }
505 
506 	    len = strlen(objectPtr->export.name);
507 	    if (len < 6 || strcmp(objectPtr->export.name+len-5, "Entry")) {
508 		smiPrintErrorAtLine(parserPtr, ERR_ROWNAME_ENTRY,
509 				    objectPtr->line, objectPtr->export.name);
510 	    } else {
511 
512 		/*
513 		 * This misreports some cases where the table name
514 		 * does not have the "*Table" suffix.  This is trying
515 		 * to allow Entry names of either fooTableEntry or
516 		 * fooEntry.
517 		 */
518 		if (parentPtr &&
519 		    !(((int)strlen(parentPtr->export.name) == len ||
520 		       (int)strlen(parentPtr->export.name) == len - 5) &&
521 		      !strncmp(objectPtr->export.name, parentPtr->export.name,
522 			len - 5))) {
523 		    smiPrintErrorAtLine(parserPtr, ERR_ROWNAME_TABLENAME,
524 					objectPtr->line,
525 					objectPtr->export.name,
526 					parentPtr->export.name);
527 		}
528 	    }
529 	}
530 
531 	/*
532 	 * Check whether a row's SEQUENCE contains exactly the list
533 	 * of child nodes (columns).  An unknown SEQUENCE type
534 	 * is handled later.
535 	 */
536 
537 	if (objectPtr->export.nodekind == SMI_NODEKIND_ROW &&
538 	    ((objectPtr->typePtr->flags & FLAG_INCOMPLETE) == 0)) {
539 	    List *p;
540 	    Node *seqNodePtr, *childNodePtr;
541 	    Object *colPtr;
542 	    int i;
543 
544 	    /*
545 	     * Walk through the SEQUENCE elements and find those
546 	     * that are misordered or have no matching columnar object.
547 	     */
548 	    for (p = objectPtr->typePtr->listPtr, i = 1,
549 		     childNodePtr = objectPtr->nodePtr->firstChildPtr;
550 		 p && childNodePtr;
551 		 p = p->nextPtr, childNodePtr = childNodePtr->nextPtr, i++) {
552 		seqNodePtr = ((Object *)p->ptr)->nodePtr;
553 
554 		if (seqNodePtr->parentPtr != childNodePtr->parentPtr) {
555 		    smiPrintErrorAtLine(parserPtr, ERR_SEQUENCE_NO_COLUMN,
556 					objectPtr->typePtr->line,
557 					i,
558 					((Object *)p->ptr)->export.name,
559 					objectPtr->export.name);
560 		    continue;
561 		}
562 
563 		if (seqNodePtr != childNodePtr) {
564 		    smiPrintErrorAtLine(parserPtr, ERR_SEQUENCE_ORDER,
565 					objectPtr->typePtr->line,
566 					i,
567 					((Object *)p->ptr)->export.name,
568 					objectPtr->export.name);
569 		    break;
570 		}
571 	    }
572 	    if ((p != NULL) && (childNodePtr == NULL)) {
573 		smiPrintErrorAtLine(parserPtr, ERR_SEQUENCE_NO_COLUMN,
574 				    objectPtr->typePtr->line,
575 				    i,
576 				    ((Object *)p->ptr)->export.name,
577 				    objectPtr->export.name);
578 	    }
579 
580 	    /*
581 	     * Walk through all child objects and find those
582 	     * that were missing in the SEQUENCE.
583 	     */
584 	    for (childNodePtr = objectPtr->nodePtr->firstChildPtr;
585 		 childNodePtr; childNodePtr = childNodePtr->nextPtr) {
586 		colPtr = findObjectByModuleAndNode(modulePtr, childNodePtr);
587 		if (!colPtr) continue;
588 		for (p = objectPtr->typePtr->listPtr; p; p = p->nextPtr) {
589 		    if (((Object *)p->ptr)->nodePtr == colPtr->nodePtr)
590 			break;
591 		}
592 		if (!p) {
593 		    if (colPtr->export.name) {
594 			/*
595 			 * Don't complain, if it's an implcitly defined
596 			 * unnamed node (could happen for parent node of
597 			 * TRAP-TYPE definitions).
598 			 */
599 			smiPrintErrorAtLine(parserPtr,
600 					    ERR_SEQUENCE_MISSING_COLUMN,
601 					    objectPtr->typePtr->line,
602 					    objectPtr->typePtr->export.name,
603 					    colPtr->export.name);
604 		    }
605 		}
606 	    }
607 
608 	}
609 
610 	if (objectPtr->export.nodekind == SMI_NODEKIND_TABLE) {
611 	    int len;
612 
613 	    len = strlen(objectPtr->export.name);
614 	    if (len < 6 || strcmp(objectPtr->export.name+len-5, "Table")) {
615 		smiPrintErrorAtLine(parserPtr, ERR_TABLENAME_TABLE,
616 				    objectPtr->line, objectPtr->export.name);
617 	    }
618 	}
619 
620 	/*
621 	 * TODO: check whether the row is the only node below the
622          * table node
623 	 */
624 
625 	/*
626 	 * Check references to unknown identifiers.
627 	 */
628 
629 	if ((objectPtr->flags & FLAG_INCOMPLETE) &&
630 	    (objectPtr->export.decl != SMI_DECL_IMPL_OBJECT)) {
631 	    if (objectPtr->export.name) {
632 		smiPrintErrorAtLine(parserPtr, ERR_UNKNOWN_OIDLABEL,
633 				    objectPtr->line, objectPtr->export.name);
634 	    } else {
635 		smiPrintErrorAtLine(parserPtr, ERR_IMPLICIT_NODE,
636 				    objectPtr->line);
637 	    }
638 	}
639 
640 	/*
641 	 * Adjust the status of implicit type definitions.
642 	 */
643 
644 	if (objectPtr->typePtr
645 	    && (objectPtr->typePtr->export.decl == SMI_DECL_IMPLICIT_TYPE)
646 	    && (objectPtr->typePtr->export.status == SMI_STATUS_UNKNOWN)) {
647 	    objectPtr->typePtr->export.status = objectPtr->export.status;
648 	}
649 
650 	/*
651 	 * Link implicit type definition from refinements into
652 	 * the type derivation tree. Adjust the status of implicit
653 	 * type definitions in refinements.
654 	 */
655 
656 	if (objectPtr->export.nodekind == SMI_NODEKIND_COMPLIANCE) {
657 
658 	    List *listPtr;
659 
660 	    for (listPtr = objectPtr->refinementlistPtr;
661 		 listPtr;
662 		 listPtr = listPtr->nextPtr) {
663 
664 		Refinement *refinementPtr;
665 		Type *typePtr;
666 
667 		refinementPtr = ((Refinement *)(listPtr->ptr));
668 		typePtr = refinementPtr->typePtr;
669 		if (typePtr) {
670 		    if (typePtr->export.status == SMI_STATUS_UNKNOWN) {
671 			typePtr->export.status = objectPtr->export.status;
672 		    }
673 		}
674 
675 		typePtr = refinementPtr->writetypePtr;
676 		if (typePtr) {
677 		    if (typePtr->export.status == SMI_STATUS_UNKNOWN) {
678 			typePtr->export.status = objectPtr->export.status;
679 		    }
680 		}
681 
682 	    }
683 	    /* relocate the refinement type into the type tree */
684 	    /* relocate the write refinement type into the type tree */
685 	}
686 
687 	/*
688 	 * Set the oidlen/oid values that are not yet correct.
689 	 */
690 
691 	if (objectPtr->export.oidlen == 0) {
692 	    if (objectPtr->nodePtr->oidlen == 0) {
693 		for (nodePtr = objectPtr->nodePtr, i = 1;
694 		     nodePtr->parentPtr != thisParserPtr->pendingNodePtr &&
695 			 nodePtr->parentPtr != smiHandle->rootNodePtr &&
696 			 nodePtr != nodePtr->parentPtr &&
697 			 i <= 128;
698 		     nodePtr = nodePtr->parentPtr, i++);
699 		if ((objectPtr->export.name) &&
700 		    ((i > 128) || (nodePtr == nodePtr->parentPtr))) {
701 		    smiPrintErrorAtLine(parserPtr, ERR_OID_RECURSIVE,
702 					objectPtr->line,
703 					objectPtr->export.name);
704 		}
705 		objectPtr->nodePtr->oid = smiMalloc(i * sizeof(SmiSubid));
706 		objectPtr->nodePtr->oidlen = i;
707 		for (nodePtr = objectPtr->nodePtr; i > 0; i--) {
708 		    objectPtr->nodePtr->oid[i-1] = nodePtr->subid;
709 		    nodePtr = nodePtr->parentPtr;
710 		}
711 	    }
712 	    objectPtr->export.oidlen = objectPtr->nodePtr->oidlen;
713 	    objectPtr->export.oid = objectPtr->nodePtr->oid;
714 	}
715 
716 	if ((objectPtr->export.decl != SMI_DECL_UNKNOWN)
717 	    && (objectPtr->export.nodekind != SMI_NODEKIND_NODE)
718 	    && objectPtr->export.name
719 	    && objectPtr->export.oid[objectPtr->export.oidlen-1] == 0
720 	    && objectPtr->export.oidlen != 2 && objectPtr->export.oid[0] != 0) {
721 	    smiPrintErrorAtLine(parserPtr, ERR_OID_ADMIN_ZERO,
722 				objectPtr->line,
723 				objectPtr->export.name);
724 	}
725 
726 	/*
727 	 * Check whether the module identity is registered in a well
728 	 * known controlled location.
729 	 */
730 
731 	if (objectPtr->export.decl == SMI_DECL_MODULEIDENTITY) {
732 	    smiCheckModuleIdentityRegistration(parserPtr, objectPtr);
733 	}
734 
735 	/*
736 	 * Check table linkage constraints for row objects.
737 	 */
738 
739 	if (objectPtr->export.nodekind == SMI_NODEKIND_ROW) {
740 	    switch (objectPtr->export.indexkind) {
741 	    case SMI_INDEX_INDEX:
742 		smiCheckIndex(parserPtr, objectPtr);
743 		break;
744 	    case SMI_INDEX_AUGMENT:
745             case SMI_INDEX_SPARSE:
746 		smiCheckAugment(parserPtr, objectPtr);
747 		break;
748 	    default:
749 		break;
750 	    }
751 	}
752 
753 	/*
754 	 * Determine the longest common OID prefix of all nodes.
755 	 */
756 
757 	if (!modulePtr->prefixNodePtr) {
758 	    modulePtr->prefixNodePtr = objectPtr->nodePtr;
759 	} else {
760 	    if (objectPtr->nodePtr->oidlen < modulePtr->prefixNodePtr->oidlen) {
761 		Node *nodePtr = findNodeByOid(objectPtr->nodePtr->oidlen,
762 					      modulePtr->prefixNodePtr->oid);
763 		if (nodePtr)
764 		    modulePtr->prefixNodePtr = nodePtr;
765 		else
766 		    smiPrintError(parserPtr, ERR_OTHER_ERROR,
767 				  "Failed to create complete object tree - "
768 				  "expect incorrect output");
769 	    }
770 	    for (i = 0; i < modulePtr->prefixNodePtr->oidlen; i++) {
771 		if (modulePtr->prefixNodePtr->oid[i] !=
772 		    objectPtr->nodePtr->oid[i]) {
773 		    modulePtr->prefixNodePtr =
774 			findNodeByOid(i, modulePtr->prefixNodePtr->oid);
775 		    break;
776 		}
777 	    }
778 	}
779     }
780 
781     if (modulePtr->export.language == SMI_LANGUAGE_SMIV2) {
782 	for (objectPtr = modulePtr->firstObjectPtr;
783 	     objectPtr; objectPtr = objectPtr->nextPtr) {
784 
785 	    /*
786 	     * Check whether all objects and notifications are contained in at
787 	     * least one conformance group (RFC 2580 3.3 and 4.1).
788 	     */
789 
790 	    smiCheckGroupMembership(parserPtr, objectPtr);
791 	}
792     }
793 
794     if (modulePtr->export.language == SMI_LANGUAGE_SPPI) {
795         Object *parentPtr;
796 
797         for (objectPtr = modulePtr->firstObjectPtr;
798              objectPtr; objectPtr = objectPtr->nextPtr) {
799             /*
800              * All checks for SPPI constructs
801              */
802             if (objectPtr->nodePtr->parentPtr)
803                 parentPtr = objectPtr->nodePtr->parentPtr->lastObjectPtr;
804             else
805                 parentPtr = NULL;
806 
807             /*
808              * Do all rows contain a PIB-INDEX/AUGMENTS/EXTENDS ?
809              * See RFC 3159 7.5, 7.7, 7.8
810              */
811             if (parentPtr  &&
812                 (parentPtr->export.nodekind == SMI_NODEKIND_TABLE) &&
813                 (objectPtr->export.indexkind != SMI_INDEX_INDEX) &&
814                 (objectPtr->export.indexkind != SMI_INDEX_AUGMENT) &&
815                 (objectPtr->export.indexkind != SMI_INDEX_SPARSE))
816                 smiPrintErrorAtLine(parserPtr, ERR_ROW_LACKS_PIB_INDEX,
817                                     objectPtr->line);
818 
819             /*
820              * Does any non row contain a PIB-INDEX/AUGMENTS/EXTENDS ?
821              * See RFC 3159 7.5, 7.7, 7.8
822              */
823             if ((objectPtr->export.nodekind != SMI_NODEKIND_ROW) &&
824                 (objectPtr->export.indexkind != SMI_INDEX_UNKNOWN))
825                 smiPrintErrorAtLine(parserPtr, ERR_PIB_INDEX_FOR_NON_ROW_TYPE,
826                                     objectPtr->line);
827 
828             /*
829              * Check the PIB-INDEX and other indices
830              */
831             if ((objectPtr->export.nodekind == SMI_NODEKIND_ROW) &&
832                 (objectPtr->export.indexkind == SMI_INDEX_INDEX)) {
833 
834                 /*
835                  * Only the first element (PIB-INDEX) has to be an InstanceId.
836                  * See RFC 3159 7.5
837                  */
838                 if (objectPtr->listPtr && objectPtr->listPtr->ptr) {
839                     Object *pibindex = (Object *)objectPtr->listPtr->ptr;
840                     if (pibindex->typePtr && pibindex->typePtr->export.name &&
841                         strcmp(pibindex->typePtr->export.name, "InstanceId"))
842                         smiPrintErrorAtLine(thisParserPtr, ERR_PIB_INDEX_NOT_INSTANCEID,
843                                             pibindex->line, pibindex->export.name);
844                 }
845             }
846 
847             /*
848              * Do all tables contain a PIB-ACCESS clause?
849              * See RFC 3159 7.3
850              */
851             if ((objectPtr->export.nodekind == SMI_NODEKIND_TABLE) &&
852                 (objectPtr->export.access == SMI_ACCESS_UNKNOWN))
853                 smiPrintErrorAtLine(parserPtr, ERR_TABLE_LACKS_PIB_ACCESS,
854                                     objectPtr->line);
855 
856             /*
857              * Does any non table types contain a PIB-ACCESS clause?
858              * See RFC 3159 7.3
859              */
860             if (((objectPtr->export.nodekind == SMI_NODEKIND_NODE) ||
861                  (objectPtr->export.nodekind == SMI_NODEKIND_ROW) ||
862                  (objectPtr->export.nodekind == SMI_NODEKIND_SCALAR)) &&
863                 (objectPtr->export.access != SMI_ACCESS_UNKNOWN))
864                 smiPrintErrorAtLine(parserPtr, ERR_PIB_ACCESS_FOR_NON_TABLE,
865                                     objectPtr->line);
866 
867             /*
868              * Check the UNIQUENESS clause and its entries
869              * See RFC 3159 7.9
870              */
871             if (objectPtr->uniquenessPtr) {
872                 if (objectPtr->export.nodekind != SMI_NODEKIND_ROW)
873                     smiPrintErrorAtLine(parserPtr, ERR_UNIQUENESS_FOR_NON_ROW,
874                                         objectPtr->line);
875                 else
876                     smiCheckUniqueness(parserPtr, objectPtr);
877             }
878 
879             /*
880              * Does the PIB-REFERENCES object point to a PRC (table)?
881              * See RFC 3159 7.10
882              */
883             if (objectPtr->typePtr && objectPtr->typePtr->export.name &&
884                 !strcmp(objectPtr->typePtr->export.name, "ReferenceId") &&
885                 objectPtr->relatedPtr &&
886                 (objectPtr->relatedPtr->export.nodekind != SMI_NODEKIND_ROW))
887                 smiPrintErrorAtLine(parserPtr, ERR_PIB_REFERENCES_NOT_ROW,
888                                     objectPtr->line);
889 
890             /*
891              * Do all PIB-TAGs point to objects with a SYNTAX of TagId?
892              * See RFC 3159 7.12
893              */
894             if (objectPtr->typePtr && objectPtr->typePtr->export.name &&
895                 !strcmp(objectPtr->typePtr->export.name, "TagReferenceId") &&
896                 objectPtr->relatedPtr && objectPtr->relatedPtr->typePtr &&
897                 objectPtr->relatedPtr->typePtr->export.name &&
898                 strcmp(objectPtr->relatedPtr->typePtr->export.name, "TagId"))
899                 smiPrintErrorAtLine(parserPtr, ERR_PIB_TAG_TYPE, objectPtr->line);
900 
901             /*
902              * Is the attribute member of at least one compliance group?
903              * See RFC 3159 9.1
904              */
905             if (objectPtr->export.nodekind & SMI_NODEKIND_COLUMN) {
906                 Object *group;
907                 int found = 0;
908 
909                 for (group = modulePtr->firstObjectPtr; group;
910                      group = group->nextPtr) {
911                     if ((group->export.nodekind == SMI_NODEKIND_GROUP) &&
912                         group->listPtr) {
913                         List *l;
914 
915                         for (l = group->listPtr; l; l = l->nextPtr)
916                             if (((Object *)l->ptr)->export.name &&
917                                 !strcmp(((Object *)l->ptr)->export.name,
918                                         objectPtr->export.name)) {
919                                 found = 1;
920                                 break;
921                             }
922                     }
923                     if (found)
924                         break;
925                 }
926                 if (!found)
927                     smiPrintErrorAtLine(parserPtr, ERR_ATTRIBUTE_NOT_IN_GROUP,
928                                         objectPtr->line, objectPtr->export.name);
929             }
930         }
931     }
932 }
933 
934 
935 
936 static void
checkTypes(Parser * parserPtr,Module * modulePtr)937 checkTypes(Parser *parserPtr, Module *modulePtr)
938 {
939     Type *typePtr;
940 
941     for (typePtr = modulePtr->firstTypePtr;
942 	typePtr; typePtr = typePtr->nextPtr) {
943 
944 	/*
945 	 * Check references to unknown types.
946 	 */
947 
948 	if ((typePtr->flags & FLAG_INCOMPLETE)
949 	    && typePtr->export.name
950 	    && (typePtr->export.decl == SMI_DECL_UNKNOWN)) {
951 	    smiPrintErrorAtLine(parserPtr, ERR_UNKNOWN_TYPE,
952 				typePtr->line, typePtr->export.name);
953 	}
954 
955 	/*
956 	 * Use TCs instead of type assignments in SMIv2.
957 	 */
958 
959 	if (thisModulePtr->export.language == SMI_LANGUAGE_SMIV2
960 	    && typePtr->export.decl == SMI_DECL_TYPEASSIGNMENT
961 	    && typePtr->export.basetype != SMI_BASETYPE_UNKNOWN
962 	    && strcmp(thisModulePtr->export.name, "SNMPv2-SMI")) {
963 	    smiPrintErrorAtLine(parserPtr, ERR_SMIV2_TYPE_ASSIGNEMENT,
964 				typePtr->line, typePtr->export.name);
965 	}
966 
967 	/*
968 	 * Check whether we have types that are not used in this
969 	 * module.
970 	 */
971 
972 	if ((typePtr->export.decl == SMI_DECL_TYPEDEF
973 	     || typePtr->export.decl == SMI_DECL_TEXTUALCONVENTION)
974 	    && ! (typePtr->flags & FLAG_INSYNTAX)) {
975 	    static char *status[] = { "Unknown", "current", "deprecated",
976 				      "mandatory", "optional", "obsolete" };
977 	    smiPrintErrorAtLine(parserPtr, ERR_TYPE_UNREF,
978 				typePtr->line,
979 				status[typePtr->export.status],
980 				typePtr->export.name);
981 	}
982 
983 	/*
984 	 * Complain about TCs derived from other TCs (RFC 2579 3.5).
985 	 */
986 
987 	if (typePtr->parentPtr
988 	    && typePtr->export.decl == SMI_DECL_TEXTUALCONVENTION
989 	    && typePtr->export.decl == typePtr->parentPtr->export.decl) {
990 	    smiPrintErrorAtLine(parserPtr, ERR_SMIV2_NESTED_TEXTUAL_CONVENTION,
991 				typePtr->line,
992 				typePtr->export.name,
993 				typePtr->parentPtr->export.name);
994 
995 	    if (typePtr->export.status < typePtr->parentPtr->export.status) {
996 		if (typePtr->parentPtr->export.status == SMI_STATUS_DEPRECATED) {
997 		    smiPrintErrorAtLine(parserPtr, ERR_TYPE_STATUS_DEPRECATED,
998 					typePtr->line,
999 					typePtr->parentPtr->export.name,
1000 					typePtr->export.name);
1001 		}
1002 		if (typePtr->parentPtr->export.status == SMI_STATUS_OBSOLETE) {
1003 		    smiPrintErrorAtLine(parserPtr, ERR_TYPE_STATUS_OBSOLETE,
1004 					typePtr->line,
1005 					typePtr->parentPtr->export.name,
1006 					typePtr->export.name);
1007 		}
1008 	    }
1009 	}
1010 
1011 	smiCheckTypeFormat(parserPtr, typePtr);
1012 	smiCheckNamedNumberRedefinition(parserPtr, typePtr);
1013 	smiCheckNamedNumberSubtyping(parserPtr, typePtr);
1014     }
1015 }
1016 
1017 
1018 
1019 static void
adjustDefval(Parser * parserPtr,SmiValue * valuePtr,Type * typePtr,int line)1020 adjustDefval(Parser *parserPtr, SmiValue *valuePtr, Type *typePtr, int line)
1021 {
1022     Object *object2Ptr;
1023     List *bitsListPtr, *valueListPtr, *p, *pp, *nextPtr, *listPtr;
1024     Import *importPtr;
1025     int nBits, bit;
1026 
1027     if (valuePtr->basetype == SMI_BASETYPE_UNKNOWN)
1028 	return;
1029 
1030     if (valuePtr->basetype == SMI_BASETYPE_OBJECTIDENTIFIER) {
1031 	/* a len of -1 indicates an unresolved label in ptr */
1032 	if (valuePtr->len == -1) {
1033 	    object2Ptr = findObjectByModuleAndName(parserPtr->modulePtr,
1034 						  (char *)valuePtr->value.ptr);
1035 	    if (!object2Ptr) {
1036 		importPtr = findImportByName(
1037 		    (char *)valuePtr->value.ptr, parserPtr->modulePtr);
1038 		if (importPtr) {		/* imported object */
1039 		    importPtr->use++;
1040 		    object2Ptr = findObjectByModulenameAndName(
1041 			importPtr->export.module,
1042 			importPtr->export.name);
1043 		}
1044 	    }
1045 	    if (!object2Ptr) {
1046 		smiPrintErrorAtLine(parserPtr, ERR_UNKNOWN_OIDLABEL,
1047 				    line,
1048 				    (char *)valuePtr->value.ptr);
1049 		smiFree(valuePtr->value.ptr);
1050 		valuePtr->value.ptr = NULL;
1051 		valuePtr->basetype = SMI_BASETYPE_UNKNOWN;
1052 	    } else {
1053 		smiFree(valuePtr->value.ptr);
1054 		valuePtr->len = object2Ptr->export.oidlen;
1055 		valuePtr->value.ptr = smiMalloc(object2Ptr->export.oidlen *
1056 						sizeof(SmiSubid));
1057 		memcpy(valuePtr->value.ptr,
1058 		       object2Ptr->export.oid,
1059 		       object2Ptr->export.oidlen * sizeof(SmiSubid));
1060 	    }
1061 	}
1062     } else if (valuePtr->basetype == SMI_BASETYPE_BITS) {
1063 	bitsListPtr = typePtr->listPtr;
1064 	valueListPtr = (void *)valuePtr->value.ptr;
1065 	for (nBits = 0, p = bitsListPtr; p; p = p->nextPtr) {
1066 	    if (nBits < 1+((NamedNumber *)(p->ptr))->export.value.value.integer32) {
1067 		nBits = 1+((NamedNumber *)(p->ptr))->export.value.value.integer32;
1068 	    }
1069 	}
1070 	valuePtr->value.ptr = smiMalloc((nBits+7)/8);
1071 	memset(valuePtr->value.ptr, 0, (nBits+7)/8);
1072 	valuePtr->len = (nBits+7)/8;
1073 	for (p = valueListPtr; p;) {
1074 	    for (pp = bitsListPtr; pp; pp = pp->nextPtr) {
1075 		if (!strcmp(p->ptr,
1076 			    ((NamedNumber *)(pp->ptr))->export.name)) {
1077 		    bit = ((NamedNumber *)(pp->ptr))->export.value.value.integer32;
1078 		    valuePtr->value.ptr[bit/8] |=
1079 			1 << (7-(bit%8));
1080 		}
1081 	    }
1082 	    smiFree(p->ptr);
1083 	    nextPtr = p->nextPtr;
1084 	    smiFree(p);
1085 	    p = nextPtr;
1086 	}
1087     } else if (valuePtr->basetype == SMI_BASETYPE_ENUM) {
1088 	/* a len of -1 indicates an unresolved enum label in ptr */
1089 	if (valuePtr->len == -1) {
1090 	    for (listPtr = typePtr->listPtr; listPtr;
1091 		 listPtr = listPtr->nextPtr) {
1092 		if (!strcmp(((NamedNumber *)(listPtr->ptr))->export.name,
1093 			    (char *)valuePtr->value.ptr)) {
1094 		    smiFree(valuePtr->value.ptr);
1095 		    valuePtr->value.integer32 =
1096 			((NamedNumber *)(listPtr->ptr))->
1097 			export.value.value.integer32;
1098 		    valuePtr->len = 1;
1099 		    break;
1100 		}
1101 	    }
1102 	}
1103     }
1104 }
1105 
1106 
1107 
1108 static void
checkDefvals(Parser * parserPtr,Module * modulePtr)1109 checkDefvals(Parser *parserPtr, Module *modulePtr)
1110 {
1111     Object *objectPtr;
1112 
1113     /*
1114      * Check unknown identifiers in OID DEFVALs.
1115      */
1116 
1117     for(objectPtr = modulePtr->firstObjectPtr;
1118 	objectPtr; objectPtr = objectPtr->nextPtr) {
1119 
1120 	adjustDefval(parserPtr, &objectPtr->export.value,
1121 		     objectPtr->typePtr, objectPtr->line);
1122 
1123 	if (objectPtr->export.value.len == -1) {
1124 	    smiPrintErrorAtLine(parserPtr,
1125 				ERR_DEFVAL_SYNTAX, objectPtr->line);
1126 	}
1127 
1128 	smiCheckDefault(parserPtr, objectPtr);
1129     }
1130 }
1131 
1132 
1133 
1134 static void
checkImportsUsage(Parser * parserPtr,Module * modulePtr)1135 checkImportsUsage(Parser *parserPtr, Module *modulePtr)
1136 {
1137     Import *importPtr;
1138 
1139     /*
1140      * Check usage of all imported identifiers.
1141      */
1142 
1143     if (strcmp(modulePtr->export.name, "SNMPv2-TC") &&
1144 	strcmp(modulePtr->export.name, "SNMPv2-CONF") &&
1145 	strcmp(modulePtr->export.name, "RFC-1212") &&
1146 	strcmp(modulePtr->export.name, "RFC-1215")) {
1147 	for(importPtr = modulePtr->firstImportPtr;
1148 	    importPtr; importPtr = importPtr->nextPtr) {
1149 	    if (! strcmp(importPtr->export.module, "SNMPv2-SMI")) {
1150 		if (! strcmp(importPtr->export.name, "ExtUTCTime")
1151 		    || !strcmp(importPtr->export.name, "ObjectName")
1152 		    || !strcmp(importPtr->export.name, "NotificationName")) {
1153 		    smiPrintErrorAtLine(parserPtr, ERR_ILLEGAL_IMPORT,
1154 					importPtr->line,
1155 					importPtr->export.name,
1156 					importPtr->export.module);
1157 		}
1158 	    }
1159 	    /* checkImports() handles KIND_NOTFOUND */
1160 	    if (importPtr->use == 0 && importPtr->kind != KIND_NOTFOUND) {
1161 		smiPrintErrorAtLine(parserPtr, ERR_UNUSED_IMPORT,
1162 				    importPtr->line,
1163 				    importPtr->export.name,
1164 				    importPtr->export.module);
1165 	    }
1166 
1167 	    if (modulePtr->export.language == SMI_LANGUAGE_SMIV2) {
1168 		int j;
1169 		for (j = 0; convertImportv2[j]; j += 4) {
1170 		    if ((strcmp(convertImportv2[j],
1171 				importPtr->export.module) == 0)
1172 			&& (strcmp(convertImportv2[j+1],
1173 				   importPtr->export.name) == 0)) {
1174 			smiPrintErrorAtLine(parserPtr,
1175 					    ERR_OBSOLETE_IMPORT,
1176 					    importPtr->line,
1177 					    importPtr->export.name,
1178 					    convertImportv2[j+2],
1179 					    importPtr->export.module);
1180 		    }
1181 		}
1182 	    }
1183 	}
1184     }
1185 }
1186 
1187 
1188 
1189 static time_t
checkDate(Parser * parserPtr,char * date)1190 checkDate(Parser *parserPtr, char *date)
1191 {
1192     struct tm	tm;
1193     time_t	anytime;
1194     int		i, len;
1195     char	*p;
1196 
1197     memset(&tm, 0, sizeof(tm));
1198     anytime = 0;
1199 
1200     len = strlen(date);
1201     if (len == 11 || len == 13) {
1202 	for (i = 0; i < len; i++) {
1203 	    if ( (i < len-1 && ! isdigit((int) date[i]))
1204 		 || (i == len-1 && date[len-1] != 'Z')) {
1205 		smiPrintError(parserPtr, ERR_DATE_CHARACTER, date);
1206 		anytime = (time_t) -1;
1207 		break;
1208 	    }
1209 	}
1210     } else {
1211 	smiPrintError(parserPtr, ERR_DATE_LENGTH, date);
1212 	anytime = (time_t) -1;
1213     }
1214 
1215     if (anytime == 0) {
1216 	for (i = 0, p = date, tm.tm_year = 0;
1217 	     i < ((len == 11) ? 2 : 4); i++, p++) {
1218 	    tm.tm_year = tm.tm_year * 10 + (*p - '0');
1219 	}
1220 	if (len == 11) {
1221 	    tm.tm_year += 1900;
1222 	    if (tm.tm_year < 1990)
1223 		smiPrintError(parserPtr, ERR_DATE_YEAR_2DIGITS,
1224 			      date, tm.tm_year);
1225 	}
1226 	tm.tm_mon  = (p[0]-'0') * 10 + (p[1]-'0');
1227 	p += 2;
1228 	tm.tm_mday = (p[0]-'0') * 10 + (p[1]-'0');
1229 	p += 2;
1230 	tm.tm_hour = (p[0]-'0') * 10 + (p[1]-'0');
1231 	p += 2;
1232 	tm.tm_min  = (p[0]-'0') * 10 + (p[1]-'0');
1233 
1234 	if (tm.tm_mon < 1 || tm.tm_mon > 12) {
1235 	    smiPrintError(parserPtr, ERR_DATE_MONTH, date);
1236 	}
1237 	if (tm.tm_mday < 1 || tm.tm_mday > 31) {
1238 	    smiPrintError(parserPtr, ERR_DATE_DAY, date);
1239 	}
1240 	if (tm.tm_hour < 0 || tm.tm_hour > 23) {
1241 	    smiPrintError(parserPtr, ERR_DATE_HOUR, date);
1242 	}
1243 	if (tm.tm_min < 0 || tm.tm_min > 59) {
1244 	    smiPrintError(parserPtr, ERR_DATE_MINUTES, date);
1245 	}
1246 
1247 	tm.tm_year -= 1900;
1248 	tm.tm_mon -= 1;
1249 	tm.tm_isdst = 0;
1250 
1251 	anytime = timegm(&tm);
1252 
1253 	if (anytime == (time_t) -1) {
1254 	    smiPrintError(parserPtr, ERR_DATE_VALUE, date);
1255 	} else {
1256 	    if (anytime < SMI_EPOCH) {
1257 		smiPrintError(parserPtr, ERR_DATE_IN_PAST, date);
1258 	    }
1259 	    if (anytime > time(NULL)) {
1260 		smiPrintError(parserPtr, ERR_DATE_IN_FUTURE, date);
1261 	    }
1262 	}
1263     }
1264 
1265     return (anytime == (time_t) -1) ? 0 : anytime;
1266 }
1267 
1268 %}
1269 
1270 /*
1271  * The grammars start symbol.
1272  */
1273 %start mibFile
1274 
1275 
1276 
1277 /*
1278  * We call the parser from within the parser when IMPORTing modules,
1279  * hence we need reentrant parser code. This is a bison feature.
1280  */
1281 %pure_parser
1282 
1283 
1284 
1285 /*
1286  * The attributes.
1287  */
1288 %union {
1289     char           *text;	  		/* scanned quoted text       */
1290     char           *id;				/* identifier name           */
1291     int            err;				/* actually just a dummy     */
1292     time_t	   date;			/* a date value              */
1293     Object         *objectPtr;			/* object identifier         */
1294     SmiStatus      status;			/* a STATUS value            */
1295     SmiAccess      access;			/* an ACCESS value           */
1296     Type           *typePtr;
1297     List           *listPtr;			/* SEQUENCE and INDEX lists  */
1298     NamedNumber    *namedNumberPtr;		/* BITS or enum item         */
1299     Range          *rangePtr;			/* type restricting range    */
1300     SmiValue	   *valuePtr;
1301     SmiUnsigned32  unsigned32;			/*                           */
1302     SmiInteger32   integer32;			/*                           */
1303     SmiUnsigned64  unsigned64;			/*                           */
1304     SmiInteger64   integer64;			/*                           */
1305     struct Compl   compl;
1306     struct Index   index;
1307     Module	   *modulePtr;
1308     SubjectCategories *subjectCategoriesPtr;
1309 }
1310 
1311 
1312 
1313 /*
1314  * Tokens and their attributes.
1315  */
1316 %token DOT_DOT
1317 %token COLON_COLON_EQUAL
1318 
1319 %token <id>UPPERCASE_IDENTIFIER
1320 %token <id>LOWERCASE_IDENTIFIER
1321 %token <unsigned32>NUMBER
1322 %token <integer32>NEGATIVENUMBER
1323 %token <unsigned64>NUMBER64
1324 %token <integer64>NEGATIVENUMBER64
1325 %token <text>BIN_STRING
1326 %token <text>HEX_STRING
1327 %token <text>QUOTED_STRING
1328 
1329 %token <id>ACCESS
1330 %token <id>AGENT_CAPABILITIES
1331 %token <id>APPLICATION
1332 %token <id>AUGMENTS
1333 %token <id>BEGIN_
1334 %token <id>BITS
1335 %token <id>CHOICE
1336 %token <id>CONTACT_INFO
1337 %token <id>CREATION_REQUIRES
1338 %token <id>COUNTER32
1339 %token <id>COUNTER64
1340 %token <id>DEFINITIONS
1341 %token <id>DEFVAL
1342 %token <id>DESCRIPTION
1343 %token <id>DISPLAY_HINT
1344 %token <id>END
1345 %token <id>ENTERPRISE
1346 %token <id>EXPORTS
1347 %token <id>EXTENDS
1348 %token <id>FROM
1349 %token <id>GROUP
1350 %token <id>GAUGE32
1351 %token <id>IDENTIFIER
1352 %token <id>IMPLICIT
1353 %token <id>IMPLIED
1354 %token <id>IMPORTS
1355 %token <id>INCLUDES
1356 %token <id>INDEX
1357 %token <id>INSTALL_ERRORS
1358 %token <id>INTEGER
1359 %token <id>INTEGER32
1360 %token <id>INTEGER64
1361 %token <id>IPADDRESS
1362 %token <id>LAST_UPDATED
1363 %token <id>MACRO
1364 %token <id>MANDATORY_GROUPS
1365 %token <id>MAX_ACCESS
1366 %token <id>MIN_ACCESS
1367 %token <id>MODULE
1368 %token <id>MODULE_COMPLIANCE
1369 %token <id>MODULE_IDENTITY
1370 %token <id>NOT_ACCESSIBLE
1371 %token <id>NOTIFICATIONS
1372 %token <id>NOTIFICATION_GROUP
1373 %token <id>NOTIFICATION_TYPE
1374 %token <id>OBJECT
1375 %token <id>OBJECT_GROUP
1376 %token <id>OBJECT_IDENTITY
1377 %token <id>OBJECT_TYPE
1378 %token <id>OBJECTS
1379 %token <id>OCTET
1380 %token <id>OF
1381 %token <id>ORGANIZATION
1382 %token <id>OPAQUE
1383 %token <id>PIB_ACCESS
1384 %token <id>PIB_DEFINITIONS
1385 %token <id>PIB_INDEX
1386 %token <id>PIB_MIN_ACCESS
1387 %token <id>PIB_REFERENCES
1388 %token <id>PIB_TAG
1389 %token <id>POLICY_ACCESS
1390 %token <id>PRODUCT_RELEASE
1391 %token <id>REFERENCE
1392 %token <id>REVISION
1393 %token <id>SEQUENCE
1394 %token <id>SIZE
1395 %token <id>STATUS
1396 %token <id>STRING
1397 %token <id>SUBJECT_CATEGORIES
1398 %token <id>SUPPORTS
1399 %token <id>SYNTAX
1400 %token <id>TEXTUAL_CONVENTION
1401 %token <id>TIMETICKS
1402 %token <id>TRAP_TYPE
1403 %token <id>UNIQUENESS
1404 %token <id>UNITS
1405 %token <id>UNIVERSAL
1406 %token <id>UNSIGNED32
1407 %token <id>UNSIGNED64
1408 %token <id>VALUE
1409 %token <id>VARIABLES
1410 %token <id>VARIATION
1411 %token <id>WRITE_SYNTAX
1412 
1413 
1414 
1415 /*
1416  * Types of non-terminal symbols.
1417  */
1418 %type  <err>mibFile
1419 %type  <err>modules
1420 %type  <err>module
1421 %type  <err>moduleOid
1422 %type  <id>moduleName
1423 %type  <id>importIdentifier
1424 %type  <err>importIdentifiers
1425 %type  <id>importedKeyword
1426 %type  <id>importedSMIKeyword
1427 %type  <id>importedSPPIKeyword
1428 %type  <err>linkagePart
1429 %type  <err>linkageClause
1430 %type  <err>importPart
1431 %type  <err>imports
1432 %type  <err>declarationPart
1433 %type  <err>declarations
1434 %type  <err>declaration
1435 %type  <err>exportsClause
1436 %type  <err>macroClause
1437 %type  <id>macroName
1438 %type  <typePtr>choiceClause
1439 %type  <id>typeName
1440 %type  <id>typeSMI
1441 %type  <id>typeSMIonly
1442 %type  <id>typeSMIandSPPI
1443 %type  <id>typeSPPIonly
1444 %type  <err>typeTag
1445 %type  <id>fuzzy_lowercase_identifier
1446 %type  <err>valueDeclaration
1447 %type  <typePtr>conceptualTable
1448 %type  <typePtr>row
1449 %type  <typePtr>entryType
1450 %type  <listPtr>sequenceItems
1451 %type  <objectPtr>sequenceItem
1452 %type  <typePtr>Syntax
1453 %type  <typePtr>sequenceSyntax
1454 %type  <listPtr>NamedBits
1455 %type  <namedNumberPtr>NamedBit
1456 %type  <err>objectIdentityClause
1457 %type  <err>objectTypeClause
1458 %type  <err>trapTypeClause
1459 %type  <text>descriptionClause
1460 %type  <listPtr>VarPart
1461 %type  <listPtr>VarTypes
1462 %type  <objectPtr>VarType
1463 %type  <text>DescrPart
1464 %type  <access>MaxAccessPart
1465 %type  <access>MaxOrPIBAccessPart
1466 %type  <access>PibAccessPart
1467 %type  <err>notificationTypeClause
1468 %type  <err>moduleIdentityClause
1469 %type  <err>typeDeclaration
1470 %type  <typePtr>typeDeclarationRHS
1471 %type  <typePtr>ObjectSyntax
1472 %type  <typePtr>sequenceObjectSyntax
1473 %type  <valuePtr>valueofObjectSyntax
1474 %type  <typePtr>SimpleSyntax
1475 %type  <valuePtr>valueofSimpleSyntax
1476 %type  <typePtr>sequenceSimpleSyntax
1477 %type  <typePtr>ApplicationSyntax
1478 %type  <typePtr>sequenceApplicationSyntax
1479 %type  <listPtr>anySubType
1480 %type  <listPtr>integerSubType
1481 %type  <listPtr>octetStringSubType
1482 %type  <listPtr>ranges
1483 %type  <rangePtr>range
1484 %type  <valuePtr>value
1485 %type  <listPtr>enumSpec
1486 %type  <listPtr>enumItems
1487 %type  <namedNumberPtr>enumItem
1488 %type  <valuePtr>enumNumber
1489 %type  <status>Status
1490 %type  <status>Status_Capabilities
1491 %type  <text>DisplayPart
1492 %type  <text>UnitsPart
1493 %type  <access>Access
1494 %type  <index>IndexPart
1495 %type  <index>MibIndex
1496 %type  <listPtr>IndexTypes
1497 %type  <objectPtr>IndexType
1498 %type  <objectPtr>Index
1499 %type  <objectPtr>Entry
1500 %type  <valuePtr>DefValPart
1501 %type  <valuePtr>Value
1502 %type  <listPtr>BitsValue
1503 %type  <listPtr>BitNames
1504 %type  <objectPtr>ObjectName
1505 %type  <objectPtr>NotificationName
1506 %type  <text>ReferPart
1507 %type  <err>RevisionPart
1508 %type  <err>Revisions
1509 %type  <err>Revision
1510 %type  <listPtr>NotificationObjectsPart
1511 %type  <listPtr>ObjectGroupObjectsPart
1512 %type  <listPtr>Objects
1513 %type  <objectPtr>Object
1514 %type  <listPtr>NotificationsPart
1515 %type  <listPtr>Notifications
1516 %type  <objectPtr>Notification
1517 %type  <text>Text
1518 %type  <date>ExtUTCTime
1519 %type  <objectPtr>objectIdentifier
1520 %type  <objectPtr>subidentifiers
1521 %type  <objectPtr>subidentifier
1522 %type  <text>objectIdentifier_defval
1523 %type  <err>subidentifiers_defval
1524 %type  <err>subidentifier_defval
1525 %type  <err>objectGroupClause
1526 %type  <err>notificationGroupClause
1527 %type  <err>moduleComplianceClause
1528 %type  <compl>ComplianceModulePart
1529 %type  <compl>ComplianceModules
1530 %type  <compl>ComplianceModule
1531 %type  <modulePtr>ComplianceModuleName
1532 %type  <listPtr>MandatoryPart
1533 %type  <listPtr>MandatoryGroups
1534 %type  <objectPtr>MandatoryGroup
1535 %type  <compl>CompliancePart
1536 %type  <compl>Compliances
1537 %type  <compl>Compliance
1538 %type  <listPtr>ComplianceGroup
1539 %type  <listPtr>ComplianceObject
1540 %type  <typePtr>SyntaxPart
1541 %type  <typePtr>WriteSyntaxPart
1542 %type  <typePtr>WriteSyntax
1543 %type  <access>AccessPart
1544 %type  <err>agentCapabilitiesClause
1545 %type  <err>ModulePart_Capabilities
1546 %type  <err>Modules_Capabilities
1547 %type  <err>Module_Capabilities
1548 %type  <modulePtr>ModuleName_Capabilities
1549 %type  <listPtr>CapabilitiesGroups
1550 %type  <listPtr>CapabilitiesGroup
1551 %type  <err>VariationPart
1552 %type  <err>Variations
1553 %type  <err>Variation
1554 %type  <access>VariationAccessPart
1555 %type  <access>VariationAccess
1556 %type  <err>CreationPart
1557 %type  <err>Cells
1558 %type  <err>Cell
1559 %type  <objectPtr>SPPIPibReferencesPart
1560 %type  <objectPtr>SPPIPibTagPart
1561 %type  <subjectCategoriesPtr>SubjectCategoriesPart
1562 %type  <subjectCategoriesPtr>SubjectCategories
1563 %type  <listPtr>CategoryIDs
1564 %type  <objectPtr>CategoryID
1565 %type  <objectPtr>UniqueType
1566 %type  <listPtr>UniqueTypes
1567 %type  <listPtr>UniqueTypesPart
1568 %type  <listPtr>SPPIUniquePart
1569 %type  <objectPtr>Error
1570 %type  <listPtr>Errors
1571 %type  <listPtr>SPPIErrorsPart
1572 
1573 %%
1574 
1575 /*
1576  * Yacc rules.
1577  *
1578  */
1579 
1580 
1581 /*
1582  * One mibFile may contain multiple MIB modules.
1583  * It's also possible that there's no module in a file.
1584  */
1585 mibFile:
1586     modules
1587     {
1588         $$ = 0;
1589     }
1590 | /* empty */
1591     {
1592 	$$ = 0;
1593     }
1594 ;
1595 
1596 modules:		module
1597 			{ $$ = 0; }
1598 	|		modules module
1599 			{ $$ = 0; }
1600 	;
1601 
1602 /*
1603  * The general structure of a module is described at REF:RFC1902,3. .
1604  * An example is given at REF:RFC1902,5.7. .
1605  */
1606 module:			moduleName
1607 			{
1608 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
1609 			    thisParserPtr->currentDecl = SMI_DECL_MODULE;
1610 
1611 			    thisParserPtr->modulePtr = findModuleByName($1);
1612 			    if (!thisParserPtr->modulePtr) {
1613 				thisParserPtr->modulePtr =
1614 				    addModule($1,
1615 					      smiStrdup(thisParserPtr->path),
1616 					      0,
1617 					      thisParserPtr);
1618 				thisParserPtr->modulePtr->
1619 				    numImportedIdentifiers = 0;
1620 				thisParserPtr->modulePtr->
1621 				    numStatements = 0;
1622 				thisParserPtr->modulePtr->
1623 				    numModuleIdentities = 0;
1624 				if (!strcmp($1, "SNMPv2-SMI")) {
1625 			            /*
1626 				     * SNMPv2-SMI is an SMIv2 module
1627 				     * that cannot be identified by
1628 				     * importing from SNMPv2-SMI.
1629 				     */
1630 				    thisModulePtr->export.language =
1631 					SMI_LANGUAGE_SMIV2;
1632 				}
1633 			    } else {
1634 			        smiPrintError(thisParserPtr,
1635 					      ERR_MODULE_ALREADY_LOADED,
1636 					      $1);
1637 				/*
1638 				 * this aborts parsing the whole file,
1639 				 * not only the current module.
1640 				 */
1641 				YYABORT;
1642 			    }
1643 			}
1644 			moduleOid
1645 			definitions
1646                         COLON_COLON_EQUAL BEGIN_
1647 			exportsClause
1648 			linkagePart
1649 			declarationPart
1650 			END
1651 			{
1652 			    if (thisModulePtr->export.language == SMI_LANGUAGE_UNKNOWN)
1653 				thisModulePtr->export.language = SMI_LANGUAGE_SMIV1;
1654 			    checkModuleName(thisParserPtr, thisModulePtr);
1655 			    checkModuleIdentity(thisParserPtr, thisModulePtr);
1656 			    checkObjects(thisParserPtr, thisModulePtr);
1657 			    checkTypes(thisParserPtr, thisModulePtr);
1658 			    checkDefvals(thisParserPtr, thisModulePtr);
1659 			    checkImportsUsage(thisParserPtr, thisModulePtr);
1660 			    smiCheckTypeUsage(thisParserPtr, thisModulePtr);
1661 
1662 			    thisParserPtr->capabilitiesModulePtr = NULL;
1663 
1664                             $$ = 0;
1665 			}
1666 	;
1667 
1668 moduleOid:		'{' objectIdentifier '}'
1669 			{ $$ = 0; }
1670 	|		/* empty */
1671 			{ $$ = 0; }
1672 	;
1673 
1674 definitions:            DEFINITIONS
1675                         { }
1676         |               PIB_DEFINITIONS
1677                         {
1678                             thisModulePtr->export.language = SMI_LANGUAGE_SPPI;
1679                         }
1680         ;
1681 
1682 /*
1683  * REF:RFC1902,3.2.
1684  */
1685 linkagePart:		linkageClause
1686 			{ $$ = 0; }
1687 	|		/* empty */
1688 			{ $$ = 0; }
1689 	;
1690 
1691 linkageClause:		IMPORTS importPart ';'
1692 			{
1693 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
1694 			    thisParserPtr->currentDecl = SMI_DECL_MODULE;
1695 
1696 			    if ((thisModulePtr->export.language != SMI_LANGUAGE_SMIV2) &&
1697                                 (thisModulePtr->export.language != SMI_LANGUAGE_SPPI))
1698 				thisModulePtr->export.language = SMI_LANGUAGE_SMIV1;
1699 
1700 			    $$ = 0;
1701 			}
1702 
1703         ;
1704 
1705 exportsClause:		/* empty */
1706 			{ $$ = 0; }
1707 	|		EXPORTS
1708 			{
1709                             if (thisParserPtr->modulePtr->export.language ==
1710                                  SMI_LANGUAGE_SPPI)
1711                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "EXPORTS");
1712 
1713 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
1714 			    thisParserPtr->currentDecl = SMI_DECL_MODULE;
1715 
1716 			    if (strcmp(thisParserPtr->modulePtr->export.name,
1717 				       "RFC1155-SMI") &&
1718 				strcmp(thisParserPtr->modulePtr->export.name,
1719 				       "RFC1065-SMI")) {
1720 			        smiPrintError(thisParserPtr, ERR_EXPORTS);
1721 			    }
1722 			}
1723 			/* the scanner skips until... */
1724 			';'
1725 			{ $$ = 0; }
1726 	;
1727 
1728 importPart:		imports
1729 			{ $$ = 0; }
1730 	|		/* empty */
1731 			{ $$ = 0; }
1732 			/* TODO: ``IMPORTS ;'' allowed? refer ASN.1! */
1733 	;
1734 
1735 imports:		import
1736 			{ $$ = 0; }
1737 	|		imports import
1738 			{ $$ = 0; }
1739 	;
1740 
1741 import:			importIdentifiers FROM moduleName
1742 			/* TODO: multiple clauses with same moduleName
1743 			 * allowed? I guess so. refer ASN.1! */
1744 			{
1745 			    Import      *importPtr;
1746 			    Module      *modulePtr;
1747 
1748 			    /*
1749 			     * Recursively call the parser to suffer
1750 			     * the IMPORTS, if the module is not yet
1751 			     * loaded.
1752 			     */
1753 			    modulePtr = findModuleByName($3);
1754 			    if (!modulePtr) {
1755 				modulePtr = loadModule($3, thisParserPtr);
1756 			    }
1757 			    checkImports(modulePtr, thisParserPtr);
1758 
1759 			    if (modulePtr && !strcmp($3, "SNMPv2-SMI")) {
1760 			        /*
1761 				 * A module that imports a macro or
1762 				 * type definition from SNMPv2-SMI
1763 				 * seems to be SMIv2 style - but only if
1764                                  * it is not SPPI yet.
1765 				 */
1766                                 if (thisModulePtr->export.language != SMI_LANGUAGE_SPPI) {
1767 				    for (importPtr =
1768 					     thisModulePtr->firstImportPtr;
1769 				         importPtr;
1770 				         importPtr = importPtr->nextPtr) {
1771 				        if ((!strcmp(importPtr->export.module,
1772 						     $3)) &&
1773 					    ((importPtr->kind == KIND_MACRO) ||
1774 					     (importPtr->kind == KIND_TYPE))) {
1775 					    thisModulePtr->export.language =
1776 					        SMI_LANGUAGE_SMIV2;
1777 				        }
1778 				    }
1779                                 }
1780 			    }
1781 
1782 			    smiFree($3);
1783 			}
1784 	;
1785 
1786 importIdentifiers:	importIdentifier
1787 			{ $$ = 0; }
1788 	|		importIdentifiers ',' importIdentifier
1789 			/* TODO: might this list list be empty? */
1790 			{ $$ = 0; }
1791 	;
1792 
1793 /*
1794  * Note that some named types must not be imported, REF:RFC1902,590 .
1795  */
1796 importIdentifier:	LOWERCASE_IDENTIFIER
1797 			{
1798 			    addImport($1, thisParserPtr);
1799 			    thisParserPtr->modulePtr->numImportedIdentifiers++;
1800 			    $$ = 0;
1801 			}
1802 	|		UPPERCASE_IDENTIFIER
1803 			{
1804 			    addImport($1, thisParserPtr);
1805 			    thisParserPtr->modulePtr->numImportedIdentifiers++;
1806 			    $$ = 0;
1807 			}
1808 	|		importedKeyword
1809 			{
1810 			    addImport(smiStrdup($1), thisParserPtr);
1811 			    thisParserPtr->modulePtr->numImportedIdentifiers++;
1812 			    $$ = 0;
1813 			}
1814 	;
1815 
1816 /*
1817  * These keywords are no real keywords. They have to be imported
1818  * from the SMI, TC, CONF MIBs.
1819  */
1820 /*
1821  * TODO: Think! Shall we really leave these words as keywords or should
1822  * we prefer the symbol table appropriately??
1823  */
1824 importedKeyword:	importedSMIKeyword
1825                         {
1826                             /*
1827                              * There are PIBs that import e.g. Counter64 - so
1828                              * don't complain here about SMI keywords.
1829                              */
1830                            /* if (thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI)
1831                               smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, $1);*/
1832                             $$ = $1;
1833                         }
1834         |               importedSPPIKeyword
1835                         {
1836                             if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)
1837 				smiPrintError(thisParserPtr, ERR_SPPI_TYPE_IN_MIB, $1);
1838                             $$ = $1;
1839                         }
1840         |               BITS
1841 	|		INTEGER32
1842 	|		IPADDRESS
1843 	|		MANDATORY_GROUPS
1844 	|		MODULE_COMPLIANCE
1845 	|		MODULE_IDENTITY
1846 	|		OBJECT_GROUP
1847 	|		OBJECT_IDENTITY
1848 	|		OBJECT_TYPE
1849 	|		OPAQUE
1850 	|		TEXTUAL_CONVENTION
1851 	|		TIMETICKS
1852 	|		UNSIGNED32
1853         ;
1854 
1855 importedSMIKeyword:     AGENT_CAPABILITIES
1856 	|		COUNTER32
1857 	|		COUNTER64
1858 	|		GAUGE32
1859 	|		NOTIFICATION_GROUP
1860 	|		NOTIFICATION_TYPE
1861 	|		TRAP_TYPE
1862 	;
1863 
1864 importedSPPIKeyword:	INTEGER64
1865 	|		UNSIGNED64
1866 	;
1867 
1868 moduleName:		UPPERCASE_IDENTIFIER
1869 			{
1870 			    checkNameLen(thisParserPtr, $1,
1871 					 ERR_MODULENAME_32, ERR_MODULENAME_64);
1872 			    $$ = $1;
1873 			}
1874 	;
1875 
1876 /*
1877  * The paragraph at REF:RFC1902,490 lists roughly what's allowed
1878  * in the body of an information module.
1879  */
1880 declarationPart:	declarations
1881 			{ $$ = 0; }
1882 	|		/* empty */
1883 			{ $$ = 0; }
1884 			/* TODO: might this list really be emtpy? */
1885 	;
1886 
1887 declarations:		declaration
1888 			{ $$ = 0; }
1889 	|		declarations declaration
1890 			{ $$ = 0; }
1891 	;
1892 
1893 declaration:		typeDeclaration
1894 			{
1895 			    thisParserPtr->modulePtr->numStatements++;
1896 			    $$ = 0;
1897 			}
1898 	|		valueDeclaration
1899 			{
1900 			    thisParserPtr->modulePtr->numStatements++;
1901 			    $$ = 0;
1902 			}
1903 	|		objectIdentityClause
1904 			{
1905 			    thisParserPtr->modulePtr->numStatements++;
1906 			    $$ = 0;
1907 			}
1908 	|		objectTypeClause
1909 			{
1910 			    thisParserPtr->modulePtr->numStatements++;
1911 			    $$ = 0;
1912 			}
1913 	|		trapTypeClause
1914 			{
1915 			    thisParserPtr->modulePtr->numStatements++;
1916 			    $$ = 0;
1917 			}
1918 	|		notificationTypeClause
1919 			{
1920 			    thisParserPtr->modulePtr->numStatements++;
1921 			    $$ = 0;
1922 			}
1923 	|		moduleIdentityClause
1924 			{
1925 			    thisParserPtr->modulePtr->numStatements++;
1926 			    $$ = 0;
1927 			}
1928 	|		moduleComplianceClause
1929 			{
1930 			    thisParserPtr->modulePtr->numStatements++;
1931 			    $$ = 0;
1932 			}
1933 	|		objectGroupClause
1934 			{
1935 			    thisParserPtr->modulePtr->numStatements++;
1936 			    $$ = 0;
1937 			}
1938 	|		notificationGroupClause
1939 			{
1940 			    thisParserPtr->modulePtr->numStatements++;
1941 			    $$ = 0;
1942 			}
1943 	|		agentCapabilitiesClause
1944 			{
1945 			    thisParserPtr->modulePtr->numStatements++;
1946 			    $$ = 0;
1947 			}
1948 	|		macroClause
1949 			{
1950 			    thisParserPtr->modulePtr->numStatements++;
1951 			    $$ = 0;
1952 			}
1953 	|		error '}'
1954 			{
1955 			    smiPrintError(thisParserPtr,
1956 					  ERR_FLUSH_DECLARATION);
1957 			    yyerrok;
1958 			    $$ = 1;
1959 			}
1960 	;
1961 
1962 /*
1963  * Macro clauses. Its contents are not really parsed, but skipped by
1964  * the scanner until 'END' is read. This is just to make the SMI
1965  * documents readable.
1966  */
1967 macroClause:		macroName
1968 			{
1969 			    Macro *macroPtr;
1970 
1971 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
1972 			    thisParserPtr->currentDecl = SMI_DECL_MACRO;
1973 
1974 			    macroPtr = addMacro(smiStrdup($1),
1975 						0, thisParserPtr);
1976 			    setMacroLine(macroPtr, thisParserPtr->firstStatementLine,
1977 					 thisParserPtr);
1978 			}
1979 			MACRO
1980 			{
1981 			    /*
1982 			     * ASN.1 macros are known to be in these
1983 			     * modules.
1984 			     */
1985 			    if (strcmp(thisParserPtr->modulePtr->export.name,
1986 				       "SNMPv2-SMI") &&
1987 			        strcmp(thisParserPtr->modulePtr->export.name,
1988 				       "SNMPv2-TC") &&
1989 				strcmp(thisParserPtr->modulePtr->export.name,
1990 				       "SNMPv2-CONF") &&
1991 				strcmp(thisParserPtr->modulePtr->export.name,
1992 				       "RFC-1212") &&
1993 				strcmp(thisParserPtr->modulePtr->export.name,
1994 				       "RFC-1215") &&
1995 				strcmp(thisParserPtr->modulePtr->export.name,
1996 				       "RFC1065-SMI") &&
1997 				strcmp(thisParserPtr->modulePtr->export.name,
1998 				       "RFC1155-SMI") &&
1999                                 strcmp(thisParserPtr->modulePtr->export.name,
2000                                        "COPS-PR-SPPI") &&
2001                                 strcmp(thisParserPtr->modulePtr->export.name,
2002                                        "COPS-PR-SPPI-TC")) {
2003 			        smiPrintError(thisParserPtr, ERR_MACRO);
2004 			    }
2005 			}
2006 			/* the scanner skips until... */
2007 			END
2008 			{
2009 			    $$ = 0;
2010                         }
2011 	;
2012 
2013 macroName:		MODULE_IDENTITY     { $$ = $1; }
2014 	|		OBJECT_TYPE	    { $$ = $1; }
2015 	|		TRAP_TYPE	    { $$ = $1; }
2016 	|		NOTIFICATION_TYPE   { $$ = $1; }
2017 	|		OBJECT_IDENTITY	    { $$ = $1; }
2018 	|		TEXTUAL_CONVENTION  { $$ = $1; }
2019 	|		OBJECT_GROUP	    { $$ = $1; }
2020 	|		NOTIFICATION_GROUP  { $$ = $1; }
2021 	|		MODULE_COMPLIANCE   { $$ = $1; }
2022 	|		AGENT_CAPABILITIES  { $$ = $1; }
2023 	;
2024 
2025 choiceClause:		CHOICE
2026 			{
2027 			    if (strcmp(thisParserPtr->modulePtr->export.name,
2028 				       "SNMPv2-SMI") &&
2029 			        strcmp(thisParserPtr->modulePtr->export.name,
2030 				       "SNMPv2-TC") &&
2031 				strcmp(thisParserPtr->modulePtr->export.name,
2032 				       "SNMPv2-CONF") &&
2033 				strcmp(thisParserPtr->modulePtr->export.name,
2034 				       "RFC-1212") &&
2035 				strcmp(thisParserPtr->modulePtr->export.name,
2036 				       "RFC1065-SMI") &&
2037 				strcmp(thisParserPtr->modulePtr->export.name,
2038 				       "RFC1155-SMI") &&
2039                                 strcmp(thisParserPtr->modulePtr->export.name,
2040                                        "COPS-PR-SPPI")) {
2041 			        smiPrintError(thisParserPtr, ERR_CHOICE);
2042 			    }
2043 			}
2044 			/* the scanner skips until... */
2045 			'}'
2046 			{
2047 			    $$ = addType(NULL, SMI_BASETYPE_UNKNOWN, 0,
2048 					 thisParserPtr);
2049 			}
2050 	;
2051 
2052 /*
2053  * The only ASN.1 value declarations are for OIDs, REF:RFC1902,491 .
2054  */
2055 fuzzy_lowercase_identifier:	LOWERCASE_IDENTIFIER
2056 			{
2057 			  $$ = $1;
2058 			}
2059 	|
2060 			UPPERCASE_IDENTIFIER
2061 			{
2062 			    smiPrintError (thisParserPtr,
2063 					   ERR_BAD_LOWER_IDENTIFIER_CASE,
2064 					   $1);
2065 			    /* xxx
2066 			    if ((thisParserPtr->flags & SMI_FLAG_BE_LAX) == 0) {
2067 			        YYERROR;
2068 			    }
2069 			    */
2070 			  $$ = $1;
2071 			}
2072 	;
2073 
2074 /* valueDeclaration:	LOWERCASE_IDENTIFIER */
2075 valueDeclaration:	fuzzy_lowercase_identifier
2076 			{
2077 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
2078 			    thisParserPtr->currentDecl = SMI_DECL_VALUEASSIGNMENT;
2079 
2080 			    checkNameLen(thisParserPtr, $1,
2081 					 ERR_OIDNAME_32, ERR_OIDNAME_64);
2082 			    smiCheckObjectName(thisParserPtr,
2083 					       thisModulePtr, $1);
2084 			    if (thisModulePtr->export.language == SMI_LANGUAGE_SMIV2)
2085 			    {
2086 			        if (strchr($1, '-') &&
2087 				    (strcmp($1, "mib-2") ||
2088 				  strcmp(thisModulePtr->export.name, "SNMPv2-SMI"))) {
2089 				    smiPrintError(thisParserPtr,
2090 						  ERR_OIDNAME_INCLUDES_HYPHEN,
2091 						  $1);
2092 				}
2093 			    }
2094 			}
2095 			OBJECT IDENTIFIER
2096 			COLON_COLON_EQUAL '{' objectIdentifier '}'
2097 			{
2098 			    Object *objectPtr;
2099 
2100 			    objectPtr = $7;
2101 			    smiCheckObjectReuse(thisParserPtr, $1, &objectPtr);
2102 			    objectPtr = setObjectName(objectPtr, $1, thisParserPtr);
2103 			    deleteObjectFlags(objectPtr, FLAG_INCOMPLETE);
2104 			    setObjectLine(objectPtr, thisParserPtr->firstStatementLine,
2105 					  thisParserPtr);
2106 			    setObjectDecl(objectPtr,
2107 					  SMI_DECL_VALUEASSIGNMENT);
2108 			    $$ = 0;
2109 			}
2110 	;
2111 
2112 /*
2113  * This is for simple ASN.1 style type assignments and textual conventions.
2114  */
2115 typeDeclaration:	typeName
2116 			{
2117 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
2118 			    thisParserPtr->currentDecl = SMI_DECL_TYPEASSIGNMENT;
2119 
2120 			    checkNameLen(thisParserPtr, $1,
2121 					 ERR_TYPENAME_32, ERR_TYPENAME_64);
2122 			}
2123 			COLON_COLON_EQUAL typeDeclarationRHS
2124 			{
2125 			    Type *typePtr;
2126 
2127 			    if (strlen($1)) {
2128 				if ($4->export.basetype != SMI_BASETYPE_UNKNOWN) {
2129 				    smiCheckTypeName(thisParserPtr,
2130 						     thisModulePtr, $1,
2131 						     thisParserPtr->firstStatementLine);
2132 				}
2133 				setTypeLine($4, thisParserPtr->firstStatementLine,
2134 					    thisParserPtr);
2135 				setTypeName($4, $1);
2136 				$$ = 0;
2137 			    } else {
2138 				$$ = 0;
2139 			    }
2140 
2141 			    /*
2142 			     * If we are in an SMI module, some type
2143 			     * definitions derived from ASN.1 `INTEGER'
2144 			     * must be modified to libsmi basetypes.
2145 			     */
2146 			    if (thisModulePtr &&
2147 				(!strcmp(thisModulePtr->export.name, "SNMPv2-SMI"))) {
2148 				if (!strcmp($1, "Counter32")) {
2149 				    $4->export.basetype = SMI_BASETYPE_UNSIGNED32;
2150 				    setTypeParent($4, smiHandle->typeUnsigned32Ptr);
2151 				    if ($4->listPtr) {
2152 					((Range *)$4->listPtr->ptr)->export.minValue.basetype = SMI_BASETYPE_UNSIGNED32;
2153 					((Range *)$4->listPtr->ptr)->export.minValue.value.unsigned32 = 0;
2154 					((Range *)$4->listPtr->ptr)->export.maxValue.basetype = SMI_BASETYPE_UNSIGNED32;
2155 					((Range *)$4->listPtr->ptr)->export.maxValue.value.unsigned32 = 4294967295U;
2156 				    }
2157 				} else if (!strcmp($1, "Gauge32")) {
2158 				    $4->export.basetype = SMI_BASETYPE_UNSIGNED32;
2159 				    setTypeParent($4, smiHandle->typeUnsigned32Ptr);
2160 				    if ($4->listPtr) {
2161 					((Range *)$4->listPtr->ptr)->export.minValue.basetype = SMI_BASETYPE_UNSIGNED32;
2162 					((Range *)$4->listPtr->ptr)->export.minValue.value.unsigned32 = 0;
2163 					((Range *)$4->listPtr->ptr)->export.maxValue.basetype = SMI_BASETYPE_UNSIGNED32;
2164 					((Range *)$4->listPtr->ptr)->export.maxValue.value.unsigned32 = 4294967295U;
2165 				    }
2166 				} else if (!strcmp($1, "Unsigned32")) {
2167 				    $4->export.basetype = SMI_BASETYPE_UNSIGNED32;
2168 				    setTypeParent($4, smiHandle->typeUnsigned32Ptr);
2169 				    if ($4->listPtr) {
2170 					((Range *)$4->listPtr->ptr)->export.minValue.basetype = SMI_BASETYPE_UNSIGNED32;
2171 					((Range *)$4->listPtr->ptr)->export.minValue.value.unsigned32 = 0;
2172 					((Range *)$4->listPtr->ptr)->export.maxValue.basetype = SMI_BASETYPE_UNSIGNED32;
2173 					((Range *)$4->listPtr->ptr)->export.maxValue.value.unsigned32 = 4294967295U;
2174 				    }
2175 				} else if (!strcmp($1, "TimeTicks")) {
2176 				    $4->export.basetype = SMI_BASETYPE_UNSIGNED32;
2177 				    setTypeParent($4, smiHandle->typeUnsigned32Ptr);
2178 				    if ($4->listPtr) {
2179 					((Range *)$4->listPtr->ptr)->export.minValue.basetype = SMI_BASETYPE_UNSIGNED32;
2180 					((Range *)$4->listPtr->ptr)->export.minValue.value.unsigned32 = 0;
2181 					((Range *)$4->listPtr->ptr)->export.maxValue.basetype = SMI_BASETYPE_UNSIGNED32;
2182 					((Range *)$4->listPtr->ptr)->export.maxValue.value.unsigned32 = 4294967295U;
2183 				    }
2184 				} else if (!strcmp($1, "Counter64")) {
2185 				    $4->export.basetype = SMI_BASETYPE_UNSIGNED64;
2186 				    if ($4->listPtr) {
2187 					((Range *)$4->listPtr->ptr)->export.minValue.basetype = SMI_BASETYPE_UNSIGNED64;
2188 					((Range *)$4->listPtr->ptr)->export.minValue.value.unsigned64 = 0;
2189 					((Range *)$4->listPtr->ptr)->export.maxValue.basetype = SMI_BASETYPE_UNSIGNED64;
2190 					((Range *)$4->listPtr->ptr)->export.maxValue.value.unsigned64 = SMI_BASETYPE_UNSIGNED64_MAX;
2191 				    }
2192 				    setTypeParent($4, smiHandle->typeUnsigned64Ptr);
2193 				}
2194 			    }
2195 			    if (thisModulePtr &&
2196 				(!strcmp(thisModulePtr->export.name, "RFC1155-SMI") ||
2197 				 !strcmp(thisModulePtr->export.name, "RFC1065-SMI"))) {
2198 				if (!strcmp($1, "Counter")) {
2199 				    $4->export.basetype = SMI_BASETYPE_UNSIGNED32;
2200 				    setTypeParent($4, smiHandle->typeUnsigned32Ptr);
2201 				    if ($4->listPtr) {
2202 					((Range *)$4->listPtr->ptr)->export.minValue.basetype = SMI_BASETYPE_UNSIGNED32;
2203 					((Range *)$4->listPtr->ptr)->export.minValue.value.unsigned32 = 0;
2204 					((Range *)$4->listPtr->ptr)->export.maxValue.basetype = SMI_BASETYPE_UNSIGNED32;
2205 					((Range *)$4->listPtr->ptr)->export.maxValue.value.unsigned32 = 4294967295U;
2206 				    }
2207 				} else if (!strcmp($1, "Gauge")) {
2208 				    $4->export.basetype = SMI_BASETYPE_UNSIGNED32;
2209 				    setTypeParent($4, smiHandle->typeUnsigned32Ptr);
2210 				    if ($4->listPtr) {
2211 					((Range *)$4->listPtr->ptr)->export.minValue.basetype = SMI_BASETYPE_UNSIGNED32;
2212 					((Range *)$4->listPtr->ptr)->export.minValue.value.unsigned32 = 0;
2213 					((Range *)$4->listPtr->ptr)->export.maxValue.basetype = SMI_BASETYPE_UNSIGNED32;
2214 					((Range *)$4->listPtr->ptr)->export.maxValue.value.unsigned32 = 4294967295U;
2215 				    }
2216 				} else if (!strcmp($1, "TimeTicks")) {
2217 				    $4->export.basetype = SMI_BASETYPE_UNSIGNED32;
2218 				    setTypeParent($4, smiHandle->typeUnsigned32Ptr);
2219 				    if ($4->listPtr) {
2220 					((Range *)$4->listPtr->ptr)->export.minValue.basetype = SMI_BASETYPE_UNSIGNED32;
2221 					((Range *)$4->listPtr->ptr)->export.minValue.value.unsigned32 = 0;
2222 					((Range *)$4->listPtr->ptr)->export.maxValue.basetype = SMI_BASETYPE_UNSIGNED32;
2223 					((Range *)$4->listPtr->ptr)->export.maxValue.value.unsigned32 = 4294967295U;
2224 				    }
2225 				} else if (!strcmp($1, "NetworkAddress")) {
2226 				    setTypeName($4, smiStrdup("NetworkAddress"));
2227 				    $4->export.basetype = SMI_BASETYPE_OCTETSTRING;
2228 				    setTypeParent($4, findTypeByModuleAndName(
2229 					                   thisModulePtr,
2230 						           "IpAddress"));
2231 				} else if (!strcmp($1, "IpAddress")) {
2232 				    typePtr = findTypeByModuleAndName(
2233 					thisModulePtr, "NetworkAddress");
2234 				    if (typePtr)
2235 					setTypeParent(typePtr, $4);
2236 				}
2237 			    }
2238 			    if (thisModulePtr &&
2239 				(!strcmp(thisModulePtr->export.name, "COPS-PR-SPPI"))) {
2240 				if (!strcmp($1, "Unsigned32")) {
2241 				    $4->export.basetype = SMI_BASETYPE_UNSIGNED32;
2242 				    setTypeParent($4, smiHandle->typeUnsigned32Ptr);
2243 				    if ($4->listPtr) {
2244 					((Range *)$4->listPtr->ptr)->export.minValue.basetype = SMI_BASETYPE_UNSIGNED32;
2245 					((Range *)$4->listPtr->ptr)->export.minValue.value.unsigned32 = 0;
2246 					((Range *)$4->listPtr->ptr)->export.maxValue.basetype = SMI_BASETYPE_UNSIGNED32;
2247 					((Range *)$4->listPtr->ptr)->export.maxValue.value.unsigned32 = 4294967295U;
2248 				    }
2249 				} else if (!strcmp($1, "TimeTicks")) {
2250 				    $4->export.basetype = SMI_BASETYPE_UNSIGNED32;
2251 				    setTypeParent($4, smiHandle->typeUnsigned32Ptr);
2252 				    if ($4->listPtr) {
2253 					((Range *)$4->listPtr->ptr)->export.minValue.basetype = SMI_BASETYPE_UNSIGNED32;
2254 					((Range *)$4->listPtr->ptr)->export.minValue.value.unsigned32 = 0;
2255 					((Range *)$4->listPtr->ptr)->export.maxValue.basetype = SMI_BASETYPE_UNSIGNED32;
2256 					((Range *)$4->listPtr->ptr)->export.maxValue.value.unsigned32 = 4294967295U;
2257 				    }
2258 				} else if (!strcmp($1, "Unsigned64")) {
2259 				    $4->export.basetype = SMI_BASETYPE_UNSIGNED64;
2260 				    if ($4->listPtr) {
2261 					((Range *)$4->listPtr->ptr)->export.minValue.basetype = SMI_BASETYPE_UNSIGNED64;
2262 					((Range *)$4->listPtr->ptr)->export.minValue.value.unsigned64 = 0;
2263 					((Range *)$4->listPtr->ptr)->export.maxValue.basetype = SMI_BASETYPE_UNSIGNED64;
2264 					((Range *)$4->listPtr->ptr)->export.maxValue.value.unsigned64 = SMI_BASETYPE_UNSIGNED64_MAX;
2265 				    }
2266 				    setTypeParent($4, smiHandle->typeUnsigned64Ptr);
2267 				} else if (!strcmp($1, "Integer64")) {
2268 				    $4->export.basetype = SMI_BASETYPE_INTEGER64;
2269 				    if ($4->listPtr) {
2270 					((Range *)$4->listPtr->ptr)->export.minValue.basetype = SMI_BASETYPE_INTEGER64;
2271 					((Range *)$4->listPtr->ptr)->export.minValue.value.integer64 = SMI_BASETYPE_INTEGER64_MIN;
2272 					((Range *)$4->listPtr->ptr)->export.maxValue.basetype = SMI_BASETYPE_INTEGER64;
2273 					((Range *)$4->listPtr->ptr)->export.maxValue.value.integer64 = SMI_BASETYPE_INTEGER64_MAX;
2274 				    }
2275 				    setTypeParent($4, smiHandle->typeInteger64Ptr);
2276 				}
2277 			    }
2278 			}
2279 	;
2280 
2281 typeName:		UPPERCASE_IDENTIFIER
2282 			{
2283 			    $$ = $1;
2284 			}
2285 	|		typeSMI
2286 			{
2287 			    $$ = smiStrdup($1);
2288 			    /*
2289 			     * well known types (keywords in this grammar)
2290 			     * are known to be defined in these modules.
2291 			     */
2292 			    if (strcmp(thisParserPtr->modulePtr->export.name,
2293 				       "SNMPv2-SMI") &&
2294 			        strcmp(thisParserPtr->modulePtr->export.name,
2295 				       "SNMPv2-TC") &&
2296 				strcmp(thisParserPtr->modulePtr->export.name,
2297 				       "SNMPv2-CONF") &&
2298 				strcmp(thisParserPtr->modulePtr->export.name,
2299 				       "RFC-1212") &&
2300 				strcmp(thisParserPtr->modulePtr->export.name,
2301 				       "RFC1065-SMI") &&
2302 				strcmp(thisParserPtr->modulePtr->export.name,
2303 				       "RFC1155-SMI") &&
2304 				strcmp(thisParserPtr->modulePtr->export.name,
2305 				       "COPS-PR-SPPI")) {
2306 			        smiPrintError(thisParserPtr, ERR_TYPE_SMI_OR_SPPI, $1);
2307 			    }
2308 			}
2309         |               typeSPPIonly
2310                         {
2311 			    $$ = smiStrdup($1);
2312 			    /*
2313 			     * well known types (keywords in this grammar)
2314 			     * are known to be defined in these modules.
2315 			     */
2316 			    if ((strcmp(thisParserPtr->modulePtr->export.name,
2317 					"COPS-PR-SPPI")) &&
2318 				(thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI))
2319 			        smiPrintError(thisParserPtr, ERR_TYPE_SPPI, $1);
2320                         }
2321 	;
2322 
2323 typeSMI:                typeSMIandSPPI
2324         |               typeSMIonly
2325                         {
2326                             if ((thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI) &&
2327                                 !findImportByName($1, thisParserPtr->modulePtr))
2328                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, $1);
2329                             $$ = $1;
2330                         }
2331         ;
2332 
2333 typeSMIandSPPI:		IPADDRESS
2334 	|		TIMETICKS
2335 	|		OPAQUE
2336 	|		INTEGER32
2337 	|		UNSIGNED32
2338         ;
2339 
2340 typeSMIonly:		COUNTER32
2341 	|		GAUGE32
2342 	|		COUNTER64
2343 	;
2344 
2345 typeSPPIonly:           INTEGER64
2346         |               UNSIGNED64
2347         ;
2348 
2349 typeDeclarationRHS:	Syntax
2350 			{
2351 			    if ($1->export.name) {
2352 				/*
2353 				 * If we found an already defined type,
2354 				 * we have to inherit a new type structure.
2355 				 * (Otherwise the `Syntax' rule created
2356 				 * a new type for us.)
2357 				 */
2358 				$$ = duplicateType($1, 0, thisParserPtr);
2359 				setTypeDecl($$, SMI_DECL_TYPEASSIGNMENT);
2360 			    } else {
2361 				$$ = $1;
2362 				setTypeDecl($$, SMI_DECL_TYPEASSIGNMENT);
2363 			    }
2364 			}
2365 	|		TEXTUAL_CONVENTION
2366 			{
2367 			    Import *importPtr;
2368 
2369 			    thisParserPtr->currentDecl = SMI_DECL_TEXTUALCONVENTION;
2370 
2371 			    if (thisModulePtr->export.language == SMI_LANGUAGE_UNKNOWN)
2372 				thisModulePtr->export.language = SMI_LANGUAGE_SMIV2;
2373 
2374 			    if (strcmp(thisModulePtr->export.name, "SNMPv2-TC")) {
2375 				importPtr =
2376 				    findImportByName("TEXTUAL-CONVENTION",
2377 						     thisModulePtr);
2378 				if (importPtr) {
2379 				    importPtr->use++;
2380 				} else {
2381                                     if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)
2382 				        smiPrintError(thisParserPtr,
2383 						      ERR_MACRO_NOT_IMPORTED,
2384 						      "TEXTUAL-CONVENTION",
2385 						      "SNMPv2-TC");
2386                                     else
2387 				        smiPrintError(thisParserPtr,
2388 						      ERR_MACRO_NOT_IMPORTED,
2389 						      "TEXTUAL-CONVENTION",
2390 						      "COPS-PR-SPPI");
2391 				}
2392 			    }
2393 			}
2394 			DisplayPart
2395 			STATUS Status
2396 			DESCRIPTION Text
2397 			{
2398 			    checkDescr(thisParserPtr, $7);
2399 			}
2400 			ReferPart
2401 			SYNTAX Syntax
2402 			{
2403 			    if (($11) && !($11->export.name)) {
2404 				/*
2405 				 * If the Type we found has just been
2406 				 * defined, we don't have to allocate
2407 				 * a new one.
2408 				 */
2409 				$$ = $11;
2410 			    } else {
2411 				if (!($11))
2412 				    smiPrintError(thisParserPtr, ERR_INTERNAL);
2413 				/*
2414 				 * Otherwise, we have to allocate a
2415 				 * new Type struct, inherited from $10.
2416 				 */
2417 				$$ = duplicateType($11, 0, thisParserPtr);
2418 			    }
2419 			    setTypeDescription($$, $7, thisParserPtr);
2420 			    if ($9) {
2421 				setTypeReference($$, $9, thisParserPtr);
2422 			    }
2423 			    setTypeStatus($$, $5);
2424 			    if ($3) {
2425 				if (smiCheckFormat(thisParserPtr,
2426 						   $$->export.basetype, $3,
2427 						   thisParserPtr->firstStatementLine)) {
2428 				    setTypeFormat($$, $3);
2429 				}
2430 			    }
2431 			    setTypeDecl($$, SMI_DECL_TEXTUALCONVENTION);
2432 			}
2433 	|		choiceClause
2434 			{
2435 			    $$ = $1;
2436 			    setTypeDecl($$, SMI_DECL_TYPEASSIGNMENT);
2437 			}
2438 	;
2439 
2440 /* REF:RFC1902,7.1.12. */
2441 conceptualTable:	SEQUENCE OF row
2442 			{
2443 			    if ($3) {
2444 				$$ = addType(NULL,
2445 					     SMI_BASETYPE_UNKNOWN, 0,
2446 					     thisParserPtr);
2447 				setTypeDecl($$, SMI_DECL_IMPL_SEQUENCEOF);
2448 				setTypeParent($$, $3);
2449 			    } else {
2450 				$$ = NULL;
2451 			    }
2452 			}
2453 	;
2454 
2455 row:			UPPERCASE_IDENTIFIER
2456 			/*
2457 			 * In this case, we do NOT allow `Module.Type'.
2458 			 * The identifier must be defined in the local
2459 			 * module.
2460 			 */
2461 			{
2462 			    Type *typePtr;
2463 			    Import *importPtr;
2464 
2465 			    $$ = findTypeByModulenameAndName(
2466 				thisParserPtr->modulePtr->export.name, $1);
2467 			    if (! $$) {
2468 				importPtr = findImportByName($1,
2469 							     thisModulePtr);
2470 				if (!importPtr ||
2471 				    (importPtr->kind == KIND_NOTFOUND)) {
2472 				    /*
2473 				     * forward referenced type. create it,
2474 				     * marked with FLAG_INCOMPLETE.
2475 				     */
2476 				    typePtr = addType($1,
2477 						      SMI_BASETYPE_UNKNOWN,
2478 						      FLAG_INCOMPLETE,
2479 						      thisParserPtr);
2480 				    $$ = typePtr;
2481 				} else {
2482 				    /*
2483 				     * imported type.
2484 				     * TODO: is this allowed in a SEQUENCE?
2485 				     */
2486 				    importPtr->use++;
2487 				    $$ = findTypeByModulenameAndName(
2488 					importPtr->export.module,
2489 					importPtr->export.name);
2490 				    smiFree($1);
2491 				}
2492 			    } else {
2493 				smiFree($1);
2494 			    }
2495 			}
2496 		        /* TODO: this must be an entryType */
2497 	;
2498 
2499 /* REF:RFC1902,7.1.12. */
2500 entryType:		SEQUENCE '{' sequenceItems '}'
2501 			{
2502 			    $$ = addType(NULL, SMI_BASETYPE_UNKNOWN, 0,
2503 					 thisParserPtr);
2504 			    setTypeList($$, $3);
2505 			}
2506 ;
2507 
2508 sequenceItems:		sequenceItem
2509 			{
2510 			    $$ = smiMalloc(sizeof(List));
2511 			    $$->ptr = $1;
2512 			    $$->nextPtr = NULL;
2513 			}
2514 	|		sequenceItems ',' sequenceItem
2515 			/* TODO: might this list be emtpy? */
2516 			{
2517 			    List *p, *pp;
2518 
2519 			    p = smiMalloc(sizeof(List));
2520 			    p->ptr = (void *)$3;
2521 			    p->nextPtr = NULL;
2522 			    for (pp = $1; pp->nextPtr; pp = pp->nextPtr);
2523 			    pp->nextPtr = p;
2524 			    $$ = $1;
2525 			}
2526 	;
2527 
2528 /*
2529  * In a SEQUENCE { ... } there are no sub-types, enumerations or
2530  * named bits. REF: draft, p.29
2531  * NOTE: REF:RFC1902,7.1.12. was less clear, it said:
2532  * `normally omitting the sub-typing information'
2533  */
2534 sequenceItem:		LOWERCASE_IDENTIFIER sequenceSyntax
2535 			{
2536 			    Object *objectPtr;
2537 			    Import *importPtr;
2538 			    Type *typePtr;
2539 
2540 			    objectPtr =
2541 			        findObjectByModuleAndName(thisParserPtr->modulePtr,
2542 							  $1);
2543 
2544 			    if (!objectPtr) {
2545 				importPtr = findImportByName($1,
2546 							     thisModulePtr);
2547 				if (!importPtr ||
2548 				    (importPtr->kind == KIND_NOTFOUND)) {
2549 				    objectPtr = addObject($1, thisParserPtr->pendingNodePtr,
2550 					                  0,
2551 					                  FLAG_INCOMPLETE |
2552 							  FLAG_SEQTYPE,
2553 						          thisParserPtr);
2554 				    setObjectType(objectPtr, $2);
2555 				} else {
2556 				    /*
2557 				     * imported object.
2558 				     */
2559 				    importPtr->use++;
2560 				    objectPtr = findObjectByModulenameAndName(
2561 					importPtr->export.module, $1);
2562 				    smiFree($1);
2563 
2564 				    if (objectPtr->typePtr->export.name) {
2565 					typePtr = objectPtr->typePtr;
2566 				    } else {
2567 					typePtr = objectPtr->typePtr->parentPtr;
2568 				    }
2569 				    if (($2 != typePtr) &&
2570 					(($2->export.basetype !=
2571 					  SMI_BASETYPE_INTEGER32) ||
2572 					 (typePtr->export.basetype !=
2573 					  SMI_BASETYPE_ENUM)) &&
2574 					(($2->export.basetype !=
2575 					  SMI_BASETYPE_OCTETSTRING) ||
2576 					 (typePtr->export.basetype !=
2577 					  SMI_BASETYPE_BITS))) {
2578 					smiPrintError(thisParserPtr,
2579 						      ERR_SEQUENCE_TYPE_MISMATCH,
2580 						      objectPtr->export.name);
2581 				    }
2582 				}
2583 			    } else {
2584 				smiFree($1);
2585 				if (objectPtr->typePtr) {
2586 
2587 				    if (objectPtr->typePtr->export.name) {
2588 					typePtr = objectPtr->typePtr;
2589 				    } else {
2590 					typePtr = objectPtr->typePtr->parentPtr;
2591 				    }
2592 				    if (($2 != typePtr) &&
2593 					(($2->export.basetype !=
2594 					  SMI_BASETYPE_INTEGER32) ||
2595 					 (typePtr->export.basetype !=
2596 					  SMI_BASETYPE_ENUM)) &&
2597 					(($2->export.basetype !=
2598 					  SMI_BASETYPE_OCTETSTRING) ||
2599 					 (typePtr->export.basetype !=
2600 					  SMI_BASETYPE_BITS))) {
2601 					smiPrintError(thisParserPtr,
2602 						      ERR_SEQUENCE_TYPE_MISMATCH,
2603 						      objectPtr->export.name);
2604 				    }
2605 
2606 				} else {
2607 				    setObjectType(objectPtr, $2);
2608 				    addObjectFlags(objectPtr,
2609 						   FLAG_SEQTYPE);
2610 				}
2611 			    }
2612 
2613 			    $$ = objectPtr;
2614 			}
2615 	;
2616 
2617 Syntax:			ObjectSyntax
2618 			{
2619 			    $$ = $1;
2620 			    if ($$)
2621 				defaultBasetype = $$->export.basetype;
2622 			}
2623 	|		BITS '{' NamedBits '}'
2624 			/* TODO: standalone `BITS' ok? seen in RMON2-MIB */
2625 			/* -> no, it's only allowed in a SEQUENCE {...} */
2626 			{
2627 			    Type *typePtr;
2628 			    List *p;
2629 
2630 			    defaultBasetype = SMI_BASETYPE_BITS;
2631 			    typePtr = addType(NULL, SMI_BASETYPE_BITS,
2632 					      FLAG_INCOMPLETE,
2633 					      thisParserPtr);
2634 			    setTypeDecl(typePtr, SMI_DECL_IMPLICIT_TYPE);
2635 			    setTypeParent(typePtr, smiHandle->typeBitsPtr);
2636 			    setTypeList(typePtr, $3);
2637 			    for (p = $3; p; p = p->nextPtr)
2638 				((NamedNumber *)p->ptr)->typePtr = typePtr;
2639 			    smiCheckNamedNumbersOrder(parserPtr, typePtr);
2640 			    $$ = typePtr;
2641 			}
2642 	;
2643 
2644 sequenceSyntax:		/* ObjectSyntax */
2645 			sequenceObjectSyntax
2646 			{
2647 			    $$ = $1;
2648 			}
2649 	|		BITS
2650 			{
2651 			    /* TODO: */
2652 			    $$ = smiHandle->typeOctetStringPtr;
2653 			}
2654 	|		UPPERCASE_IDENTIFIER anySubType
2655 			{
2656 			    Type *typePtr;
2657 			    Import *importPtr;
2658 
2659 			    $$ = findTypeByModulenameAndName(
2660 				thisParserPtr->modulePtr->export.name, $1);
2661 			    if (! $$) {
2662 				importPtr = findImportByName($1,
2663 							     thisModulePtr);
2664 				if (!importPtr ||
2665 				    (importPtr->kind == KIND_NOTFOUND)) {
2666 				    /*
2667 				     * forward referenced type. create it,
2668 				     * marked with FLAG_INCOMPLETE.
2669 				     */
2670 				    typePtr = addType($1, SMI_BASETYPE_UNKNOWN,
2671 						      FLAG_INCOMPLETE,
2672 						      thisParserPtr);
2673 				    $$ = typePtr;
2674 				} else {
2675 				    importPtr->use++;
2676 				    $$ = findTypeByModulenameAndName(
2677 					importPtr->export.module,
2678 					importPtr->export.name);
2679 				    smiFree($1);
2680 				}
2681 			    } else {
2682 				smiFree($1);
2683 			    }
2684 			}
2685 	;
2686 
2687 NamedBits:		NamedBit
2688 			{
2689 			    $$ = smiMalloc(sizeof(List));
2690 			    $$->ptr = $1;
2691 			    $$->nextPtr = NULL;
2692 			}
2693 	|		NamedBits ',' NamedBit
2694 			{
2695 			    List *p, *pp;
2696 
2697 			    p = smiMalloc(sizeof(List));
2698 			    p->ptr = (void *)$3;
2699 			    p->nextPtr = NULL;
2700 			    for (pp = $1; pp->nextPtr; pp = pp->nextPtr);
2701 			    pp->nextPtr = p;
2702 			    $$ = $1;
2703 			}
2704 	;
2705 
2706 NamedBit:		LOWERCASE_IDENTIFIER
2707 			{
2708 			    checkNameLen(thisParserPtr, $1,
2709 					 ERR_BITNAME_32, ERR_BITNAME_64);
2710 			    if (thisModulePtr->export.language == SMI_LANGUAGE_SMIV2)
2711 			    {
2712 				if (strchr($1, '-')) {
2713 				    smiPrintError(thisParserPtr,
2714 						  ERR_NAMEDBIT_INCLUDES_HYPHEN,
2715 						  $1);
2716 				}
2717 			    }
2718 			}
2719 			'(' NUMBER ')'
2720 			{
2721 			    $$ = smiMalloc(sizeof(NamedNumber));
2722 			    $$->export.name = $1;
2723 			    $$->export.value.basetype =
2724 				                       SMI_BASETYPE_UNSIGNED32;
2725 			    $$->export.value.value.unsigned32 = $4;
2726 			    /* RFC 2578 7.1.4 */
2727 			    if ($4 >= 65535*8) {
2728 				smiPrintError(thisParserPtr,
2729 					      ERR_BITS_NUMBER_TOO_LARGE,
2730 					      $1, $4);
2731 			    } else {
2732 				if ($4 >= 128) {
2733 				    smiPrintError(thisParserPtr,
2734 						  ERR_BITS_NUMBER_LARGE,
2735 						  $1, $4);
2736 				}
2737 			    }
2738 			}
2739 	;
2740 
2741 objectIdentityClause:	LOWERCASE_IDENTIFIER
2742 			{
2743 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
2744 			    thisParserPtr->currentDecl = SMI_DECL_OBJECTIDENTITY;
2745 
2746 			    checkNameLen(thisParserPtr, $1,
2747 					 ERR_OIDNAME_32, ERR_OIDNAME_64);
2748 			    smiCheckObjectName(thisParserPtr,
2749 					       thisModulePtr, $1);
2750 			}
2751 			OBJECT_IDENTITY
2752 			{
2753 			    Import *importPtr;
2754 
2755 			    if (strcmp(thisModulePtr->export.name, "SNMPv2-SMI") &&
2756                                 strcmp(thisModulePtr->export.name, "COPS-PR-SPPI")) {
2757 				importPtr = findImportByName("OBJECT-IDENTITY",
2758 							     thisModulePtr);
2759 				if (importPtr) {
2760 				    importPtr->use++;
2761 				} else {
2762                                     if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)
2763 				        smiPrintError(thisParserPtr,
2764 						      ERR_MACRO_NOT_IMPORTED,
2765 						      "OBJECT-IDENTITY",
2766 						      "SNMPv2-SMI");
2767                                     else
2768 				        smiPrintError(thisParserPtr,
2769 						      ERR_MACRO_NOT_IMPORTED,
2770 						      "OBJECT-IDENTITY",
2771 						      "COPS-PR-SPPI");
2772 				}
2773 			    }
2774 			}
2775 			STATUS Status
2776 			DESCRIPTION Text
2777 			{
2778 			    checkDescr(thisParserPtr, $8);
2779 			}
2780 			ReferPart
2781 			COLON_COLON_EQUAL
2782 			'{' objectIdentifier '}'
2783 			{
2784 			    Object *objectPtr;
2785 
2786 			    objectPtr = $13;
2787 			    smiCheckObjectReuse(thisParserPtr, $1, &objectPtr);
2788 
2789 			    objectPtr = setObjectName(objectPtr, $1, thisParserPtr);
2790 			    setObjectDecl(objectPtr, SMI_DECL_OBJECTIDENTITY);
2791 			    setObjectLine(objectPtr, thisParserPtr->firstStatementLine,
2792 					  thisParserPtr);
2793 			    setObjectStatus(objectPtr, $6);
2794 			    setObjectDescription(objectPtr, $8, thisParserPtr);
2795 			    if ($10) {
2796 				setObjectReference(objectPtr, $10, thisParserPtr);
2797 			    }
2798 			    addObjectFlags(objectPtr, FLAG_REGISTERED);
2799 			    deleteObjectFlags(objectPtr, FLAG_INCOMPLETE);
2800 			    $$ = 0;
2801 			}
2802 	;
2803 
2804 objectTypeClause:	LOWERCASE_IDENTIFIER
2805 			{
2806 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
2807 			    thisParserPtr->currentDecl = SMI_DECL_OBJECTTYPE;
2808 
2809 			    checkNameLen(thisParserPtr, $1,
2810 					 ERR_OIDNAME_32, ERR_OIDNAME_64);
2811 			    smiCheckObjectName(thisParserPtr,
2812 					       thisModulePtr, $1);
2813 			}
2814 			OBJECT_TYPE
2815 			{
2816 			    Import *importPtr;
2817 
2818 			    importPtr = findImportByName("OBJECT-TYPE",
2819 							 thisModulePtr);
2820 			    if (importPtr) {
2821 				importPtr->use++;
2822 			    } else {
2823 				if (thisModulePtr->export.language ==
2824 				    SMI_LANGUAGE_SMIV2) {
2825 				    smiPrintError(thisParserPtr,
2826 						  ERR_MACRO_NOT_IMPORTED,
2827 						  "OBJECT-TYPE", "SNMPv2-SMI");
2828 				} else if (thisModulePtr->export.language ==
2829                                     SMI_LANGUAGE_SPPI) {
2830                                     smiPrintError(thisParserPtr,
2831                                                   ERR_MACRO_NOT_IMPORTED,
2832                                                   "OBJECT-TYPE", "COPS-PR-SPPI");
2833                                 } else {
2834 				    smiPrintError(thisParserPtr,
2835 						  ERR_MACRO_NOT_IMPORTED,
2836 						  "OBJECT-TYPE", "RFC-1212");
2837 				}
2838 			    }
2839                             indexFlag = 0;
2840 			}
2841 			SYNTAX Syntax                /* old $6, new $6 */
2842 		        UnitsPart                    /* old $7, new $7 */
2843                         MaxOrPIBAccessPart           /* old $8, new $8 */
2844                         SPPIPibReferencesPart        /* SPPI only, $9 */
2845                         SPPIPibTagPart               /* SPPI only, $10 */
2846 			STATUS Status                /* old $9 $10, new $11 $12 */
2847 			descriptionClause            /* old $11, new $13 */
2848                         SPPIErrorsPart               /* SPPI only, $14 */
2849 			ReferPart                    /* old $12, new $15 */
2850 			IndexPart                    /* modified, old $13, new $16 */
2851                         MibIndex                     /* new, $17 */
2852                         SPPIUniquePart               /* SPPI only, $18 */
2853 			DefValPart                   /* old $14, new $19 */
2854 			COLON_COLON_EQUAL '{' ObjectName '}' /* old $17, new $22 */
2855 			{
2856 			    Object *objectPtr, *parentPtr;
2857 			    Type *typePtr = NULL;
2858 
2859 			    objectPtr = $22;
2860 
2861 			    smiCheckObjectReuse(thisParserPtr, $1, &objectPtr);
2862 
2863 			    objectPtr = setObjectName(objectPtr, $1, thisParserPtr);
2864 			    setObjectDecl(objectPtr, SMI_DECL_OBJECTTYPE);
2865 			    setObjectLine(objectPtr, thisParserPtr->firstStatementLine,
2866 					  thisParserPtr);
2867 			    if (checkObjectFlags(objectPtr, FLAG_SEQTYPE)) {
2868 				deleteObjectFlags(objectPtr, FLAG_SEQTYPE);
2869 				if ($6) {
2870 				    if ($6->export.name) {
2871 					typePtr = $6;
2872                                         /*
2873                                          * According to RFC 3159 7.1.3. Opaque must not be used
2874                                          * in a SYNTAX clause.
2875                                          */
2876                                         if ((thisModulePtr->export.language == SMI_LANGUAGE_SPPI) &&
2877                                             !strcmp(typePtr->export.name, "Opaque"))
2878                                             smiPrintError(thisParserPtr, ERR_OPAQUE_IN_SYNTAX);
2879                                         /*
2880                                          * According to RFC 3159 7.1.4. IpAddress must not be used
2881                                          * in a SYNTAX clause.
2882                                          */
2883                                         if ((thisModulePtr->export.language == SMI_LANGUAGE_SPPI) &&
2884                                             !strcmp(typePtr->export.name, "IpAddress"))
2885                                             smiPrintError(thisParserPtr, ERR_IPADDRESS_IN_SYNTAX);
2886 				    } else {
2887 					typePtr = $6->parentPtr;
2888 				    }
2889 				    if ((objectPtr->typePtr != typePtr) &&
2890 					((objectPtr->typePtr->export.basetype !=
2891 					  SMI_BASETYPE_INTEGER32) ||
2892 					 (typePtr->export.basetype !=
2893 					  SMI_BASETYPE_ENUM)) &&
2894 					((objectPtr->typePtr->export.basetype !=
2895 					  SMI_BASETYPE_OCTETSTRING) ||
2896 					 (typePtr->export.basetype !=
2897 					  SMI_BASETYPE_BITS))) {
2898 					smiPrintError(thisParserPtr,
2899 						      ERR_SEQUENCE_TYPE_MISMATCH,
2900 						      objectPtr->export.name);
2901 				    }
2902 				}
2903 			    }
2904 			    setObjectType(objectPtr, $6);
2905 			    if (!($6->export.name)) {
2906 				/*
2907 				 * An inlined type.
2908 				 */
2909 #if 0 /* export implicitly defined types by the node's lowercase name */
2910 				setTypeName($6, $1);
2911 #endif
2912 			    }
2913 			    setObjectUnits(objectPtr, $7);
2914 			    setObjectAccess(objectPtr, $8);
2915 			    if (thisParserPtr->flags & FLAG_CREATABLE) {
2916 				thisParserPtr->flags &= ~FLAG_CREATABLE;
2917 				parentPtr =
2918 				  objectPtr->nodePtr->parentPtr->lastObjectPtr;
2919 				if (parentPtr &&
2920 				    parentPtr->export.indexkind !=
2921 				       SMI_INDEX_UNKNOWN) {
2922 				    /*
2923 				     * add objectPtr to the parent object's
2924 				     * listPtr, which is the list of columns
2925 				     * needed for row creation.
2926 				     *
2927 				     * Note, that this would clash, if the
2928 				     * parent row object-type is not yet
2929 				     * defined.
2930 				     */
2931 				    /*
2932 				    newlistPtr = smiMalloc(sizeof(List));
2933 				    newlistPtr->nextPtr = NULL;
2934 				    newlistPtr->ptr = objectPtr;
2935 				    */
2936 				    /*
2937 				     * Look up the parent object-type.
2938 				     */
2939 				    /*
2940 				    if (parentPtr->listPtr) {
2941 					for(listPtr = parentPtr->listPtr;
2942 					    listPtr->nextPtr;
2943 					    listPtr = listPtr->nextPtr);
2944 					listPtr->nextPtr = newlistPtr;
2945 				    } else {
2946 					parentPtr->listPtr = newlistPtr;
2947 				    }
2948 				    */
2949 				    addObjectFlags(parentPtr, FLAG_CREATABLE);
2950 				    setObjectCreate(parentPtr, 1);
2951 				} else {
2952 				    smiPrintError(thisParserPtr,
2953 						  ERR_SCALAR_READCREATE);
2954 				}
2955 			    }
2956 			    setObjectStatus(objectPtr, $12);
2957 			    addObjectFlags(objectPtr, FLAG_REGISTERED);
2958 			    deleteObjectFlags(objectPtr, FLAG_INCOMPLETE);
2959 			    if ($13) {
2960 				setObjectDescription(objectPtr, $13, thisParserPtr);
2961 			    }
2962 			    if ($15) {
2963 				setObjectReference(objectPtr, $15, thisParserPtr);
2964 			    }
2965                             if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI) {
2966                                 /*
2967                                  * For SMI documents either $16 (IndexPart) or $17 (MibIndex)
2968                                  * are used, but not both. This is signalled via the indexFlag
2969                                  * which is 1 if IndexPart has been used.
2970                                  */
2971                                 if (indexFlag == INDEXFLAG_AUGMENTS) { /* IndexPart was used */
2972 			            if ($16.indexkind != SMI_INDEX_UNKNOWN) {
2973 				        setObjectList(objectPtr, $16.listPtr);
2974 				        setObjectImplied(objectPtr, $16.implied);
2975 				        setObjectIndexkind(objectPtr, $16.indexkind);
2976 				        setObjectRelated(objectPtr, $16.rowPtr);
2977 			            }
2978                                 } else {
2979 			            if ($17.indexkind != SMI_INDEX_UNKNOWN) {
2980 				        setObjectList(objectPtr, $17.listPtr);
2981 				        setObjectImplied(objectPtr, $17.implied);
2982 				        setObjectIndexkind(objectPtr, $17.indexkind);
2983 				        setObjectRelated(objectPtr, $17.rowPtr);
2984 			            }
2985                                 }
2986                             } else {
2987                                 /*
2988                                  * PIBs contain either PIB-INDEX or AUGMENTS or EXTENDS -
2989                                  * but only with one Index entry. A PIB-INDEX may be
2990                                  * followed by a full INDEX. We get the indexkind
2991                                  * from the first.
2992                                  * Note that PIB-INDEX/AUGMENTS/EXTENS is always
2993                                  * the first element in objectPtr->listPtr.
2994                                  * If an optional INDEX exists then it is
2995                                  * appended to this list.
2996                                  */
2997 			        if ($16.indexkind != SMI_INDEX_UNKNOWN) {
2998                                     setObjectList(objectPtr, $16.listPtr);
2999 				    setObjectIndexkind(objectPtr, $16.indexkind);
3000 				    setObjectRelated(objectPtr, $16.rowPtr);
3001 			        }
3002 			        if ($17.indexkind != SMI_INDEX_UNKNOWN) {
3003                                     if (objectPtr->listPtr) {
3004                                         List *p;
3005                                         for (p = objectPtr->listPtr; p->nextPtr;
3006                                              p = p->nextPtr);
3007                                         p->nextPtr = $17.listPtr;
3008                                     }
3009 				    setObjectImplied(objectPtr, $17.implied);
3010 			        }
3011                             }
3012                             if ($18) {
3013                                 setObjectUniqueness(objectPtr, $18);
3014                             }
3015 			    if ($19) {
3016 				if (objectPtr->typePtr
3017 				    && (((objectPtr->typePtr->export.basetype == SMI_BASETYPE_OCTETSTRING) &&
3018 					 ($19->basetype != SMI_BASETYPE_OCTETSTRING))
3019 					|| ((objectPtr->typePtr->export.basetype == SMI_BASETYPE_OBJECTIDENTIFIER) &&
3020 					    ($19->basetype != SMI_BASETYPE_OBJECTIDENTIFIER)))) {
3021 				    smiPrintError(thisParserPtr,
3022 						  ERR_DEFVAL_SYNTAX);
3023 				    if ($19->basetype == SMI_BASETYPE_OBJECTIDENTIFIER) {
3024 					smiFree($19->value.oid);
3025 				    }
3026 				    if (($19->basetype == SMI_BASETYPE_BITS) ||
3027 					($19->basetype == SMI_BASETYPE_OCTETSTRING)) {
3028 					smiFree($19->value.ptr);
3029 				    }
3030 				    smiFree($19);
3031 				} else {
3032 				    setObjectValue(objectPtr, $19);
3033 				}
3034 			    }
3035                             if ($9) {
3036                                 if (objectPtr->relatedPtr)
3037                                     smiPrintError(thisParserPtr, ERR_OBJECTPTR_ELEMENT_IN_USE,
3038                                                   "relatedPtr", "PIB-REFERENCES");
3039                                 /*
3040                                  * PIB-REFERENCES clauses are only allowed for
3041                                  * objects with a SYNTAX of 'ReferenceId'.
3042                                  * See RFC 3159 7.10
3043                                  */
3044                                 if (objectPtr->typePtr && objectPtr->typePtr->export.name &&
3045                                     strcmp(objectPtr->typePtr->export.name, "ReferenceId"))
3046                                     smiPrintErrorAtLine(parserPtr, ERR_PIB_REFERENCES_WRONG_TYPE,
3047                                                         objectPtr->line);
3048                                 else
3049                                     setObjectRelated(objectPtr, $9);
3050                             } else {
3051                                /*
3052                                 * Does this object have a SYNTAX of 'ReferenceId'
3053                                 * and a PIB-REFERENCES clause?
3054                                 * See RFC 3159 7.10
3055                                 */
3056                                if ((thisModulePtr->export.language == SMI_LANGUAGE_SPPI) &&
3057                                    objectPtr->typePtr && objectPtr->typePtr->export.name &&
3058                                    !strcmp(objectPtr->typePtr->export.name, "ReferenceId"))
3059                                    smiPrintErrorAtLine(parserPtr, ERR_LACKING_PIB_REFERENCES,
3060                                                        objectPtr->line);
3061                             }
3062                             if ($10) {
3063                                 if (objectPtr->relatedPtr)
3064                                     smiPrintError(thisParserPtr, ERR_OBJECTPTR_ELEMENT_IN_USE,
3065                                                   "relatedPtr", "PIB-TAG");
3066                                 /*
3067                                  * PIB-TAG clauses are only allowed for
3068                                  * objects with a SYNTAX of 'TagReferenceId'.
3069                                  * See RFC 3159 7.11
3070                                  */
3071                                 if (objectPtr->typePtr && objectPtr->typePtr->export.name &&
3072                                     strcmp(objectPtr->typePtr->export.name, "TagReferenceId"))
3073                                     smiPrintErrorAtLine(parserPtr, ERR_PIB_TAG_WRONG_TYPE,
3074                                                         objectPtr->line);
3075                                 else
3076                                     setObjectRelated(objectPtr, $10);
3077                             } else {
3078                                 /*
3079                                  * Does this object have a SYNTAX of 'TagReferenceId'
3080                                  * and a PIB-TAG clause?
3081                                  * See RFC 3159 7.11
3082                                  */
3083                                 if ((thisModulePtr->export.language == SMI_LANGUAGE_SPPI) &&
3084                                     objectPtr->typePtr && objectPtr->typePtr->export.name &&
3085                                     !strcmp(objectPtr->typePtr->export.name, "TagReferenceId"))
3086                                     smiPrintErrorAtLine(parserPtr, ERR_LACKING_PIB_TAG,
3087                                                         objectPtr->line);
3088 
3089                             }
3090                             if ($14) {
3091                                 if (objectPtr->listPtr)
3092                                     smiPrintError(thisParserPtr, ERR_OBJECTPTR_ELEMENT_IN_USE,
3093                                                   "listPtr", "INSTALL-ERRORS");
3094                                 /*
3095                                  * Are INSTALL-ERRORS only used with tables?
3096                                  * See RFC 3159 7.4
3097                                  */
3098                                 if (!((objectPtr->export.decl == SMI_DECL_OBJECTTYPE) &&
3099                                     (objectPtr->typePtr) &&
3100                                     (objectPtr->typePtr->export.decl == SMI_DECL_IMPL_SEQUENCEOF)))
3101                                     smiPrintErrorAtLine(parserPtr, ERR_INSTALL_ERRORS_FOR_NON_TABLE,
3102                                                         objectPtr->line);
3103                                 else
3104                                     setObjectList(objectPtr, $14);
3105                             }
3106 			    $$ = 0;
3107 			}
3108 	;
3109 
3110 descriptionClause:	/* empty */
3111 			{
3112 			    if ((thisModulePtr->export.language == SMI_LANGUAGE_SMIV2) ||
3113                                 (thisModulePtr->export.language == SMI_LANGUAGE_SPPI))
3114 			    {
3115 				smiPrintError(thisParserPtr,
3116 					      ERR_MISSING_DESCRIPTION);
3117 			    }
3118 			    $$ = NULL;
3119 			}
3120 	|		DESCRIPTION Text
3121 			{
3122 			    $$ = $2;
3123 			    checkDescr(thisParserPtr, $2);
3124 			}
3125 	;
3126 
3127 trapTypeClause:		fuzzy_lowercase_identifier
3128 			{
3129 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
3130 			    thisParserPtr->currentDecl = SMI_DECL_TRAPTYPE;
3131 
3132 			    checkNameLen(thisParserPtr, $1,
3133 					 ERR_OIDNAME_32, ERR_OIDNAME_64);
3134 			    smiCheckObjectName(thisParserPtr,
3135 					       thisModulePtr, $1);
3136 			}
3137 			TRAP_TYPE
3138 			{
3139 			    Import *importPtr;
3140                             if (thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI)
3141                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "TRAP-TYPE");
3142 
3143 			    if (thisModulePtr->export.language == SMI_LANGUAGE_SMIV2)
3144 			    {
3145 			        smiPrintError(thisParserPtr, ERR_TRAP_TYPE);
3146 			    }
3147 
3148 			    importPtr = findImportByName("TRAP-TYPE",
3149 							 thisModulePtr);
3150 			    if (importPtr) {
3151 				importPtr->use++;
3152 			    } else {
3153 				smiPrintError(thisParserPtr,
3154 					      ERR_MACRO_NOT_IMPORTED,
3155 					      "TRAP-TYPE", "RFC-1215");
3156 			    }
3157 			}
3158 			ENTERPRISE objectIdentifier
3159 			VarPart
3160 			DescrPart
3161 			ReferPart
3162 			COLON_COLON_EQUAL NUMBER
3163 			/* TODO: range of number? */
3164 			{
3165 			    Object *objectPtr;
3166 			    Node *nodePtr;
3167 
3168 			    objectPtr = $6;
3169 			    nodePtr = findNodeByParentAndSubid(
3170 				objectPtr->nodePtr, 0);
3171 			    if (nodePtr && nodePtr->lastObjectPtr &&
3172 	       		        (nodePtr->lastObjectPtr->modulePtr == thisModulePtr)) {
3173 				/*
3174 				 * hopefully, the last defined Object for
3175 				 * this Node is the one we expect.
3176 				 */
3177 				objectPtr = nodePtr->lastObjectPtr;
3178 			    } else {
3179 				objectPtr = addObject(NULL,
3180 						      objectPtr->nodePtr,
3181 						      0,
3182 						      FLAG_INCOMPLETE,
3183 						      thisParserPtr);
3184 			    }
3185 			    objectPtr = addObject(NULL,
3186 						  objectPtr->nodePtr,
3187 						  $11,
3188 						  FLAG_INCOMPLETE,
3189 						  thisParserPtr);
3190 
3191 			    smiCheckObjectReuse(thisParserPtr, $1, &objectPtr);
3192 
3193 			    objectPtr = setObjectName(objectPtr, $1, thisParserPtr);
3194 			    setObjectDecl(objectPtr,
3195 					  SMI_DECL_TRAPTYPE);
3196 			    setObjectLine(objectPtr, thisParserPtr->firstStatementLine,
3197 					  thisParserPtr);
3198 			    addObjectFlags(objectPtr, FLAG_REGISTERED);
3199 			    deleteObjectFlags(objectPtr, FLAG_INCOMPLETE);
3200 			    setObjectList(objectPtr, $7);
3201 			    setObjectStatus(objectPtr, SMI_STATUS_CURRENT);
3202 			    setObjectDescription(objectPtr, $8, thisParserPtr);
3203 			    if ($9) {
3204 				setObjectReference(objectPtr, $9, thisParserPtr);
3205 			    }
3206 			    $$ = 0;
3207 			}
3208 	;
3209 
3210 VarPart:		VARIABLES '{' VarTypes '}'
3211 			{
3212 			    $$ = $3;
3213 			}
3214 	|		/* empty */
3215 			{
3216 			    $$ = NULL;
3217 			}
3218 	;
3219 
3220 VarTypes:		VarType
3221 			{
3222 			    if ($1) {
3223 				$$ = smiMalloc(sizeof(List));
3224 				$$->ptr = $1;
3225 				$$->nextPtr = NULL;
3226 			    } else {
3227 				$$ = NULL;
3228 			    }
3229 			}
3230 	|		VarTypes ',' VarType
3231 			{
3232 			    List *p, *pp;
3233 
3234 			    if ($3) {
3235 				p = smiMalloc(sizeof(List));
3236 				p->ptr = $3;
3237 				p->nextPtr = NULL;
3238 				if ($1) {
3239 				    for (pp = $1; pp->nextPtr;
3240 					 pp = pp->nextPtr);
3241 				    pp->nextPtr = p;
3242 				    $$ = $1;
3243 				} else {
3244 				    $$ = p;
3245 				}
3246 			    } else {
3247 				$$ = $1;
3248 			    }
3249 			}
3250 	;
3251 
3252 VarType:		ObjectName
3253 			{
3254 			    $$ = $1;
3255 			}
3256 	;
3257 
3258 DescrPart:		DESCRIPTION Text
3259 			{
3260 			    $$ = $2;
3261 			    checkDescr(thisParserPtr, $2);
3262 			}
3263 	|		/* empty */
3264 			{ $$ = NULL; }
3265 	;
3266 
3267 MaxOrPIBAccessPart:     MaxAccessPart
3268                         {
3269                             $$ = $1;
3270                         }
3271         |               PibAccessPart
3272                         {
3273                             if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)
3274                                 smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "MAX-ACCESS");
3275                             if ($1 == SMI_ACCESS_NOT_ACCESSIBLE)
3276                                 smiPrintError(thisParserPtr, ERR_NOT_ACCESSIBLE_IN_PIB_ACCESS);
3277                             $$ = $1;
3278                         }
3279         |               /* empty */
3280                         { $$ = 0;  }
3281         ;
3282 
3283 PibAccessPart:          PibAccess Access
3284                         { $$ = $2; }
3285         ;
3286 
3287 PibAccess:              POLICY_ACCESS
3288                         {
3289                             smiPrintError(thisParserPtr, ERR_POLICY_ACCESS_IN_PIB);
3290                         }
3291         |               PIB_ACCESS
3292                         { }
3293         ;
3294 
3295 SPPIPibReferencesPart:  PIB_REFERENCES
3296                         {
3297                             if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)
3298                                 smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "PIB-REFERENCES");
3299                         }
3300                         '{' Entry '}'
3301                         { $$ = $4; }
3302         |               /* empty */
3303                         { $$ = 0; }
3304         ;
3305 
3306 SPPIPibTagPart:         PIB_TAG
3307                         {
3308                             if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)
3309                                 smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "PIB-TAG");
3310                         }
3311                         '{' ObjectName '}'
3312                         { $$ = $4; }
3313         |               /* empty */
3314                         { $$ = 0; }
3315         ;
3316 
3317 
3318 SPPIUniquePart:         UNIQUENESS
3319                         {
3320                             if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)
3321                                 smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "UNIQUENESS");
3322                         }
3323                         '{' UniqueTypesPart '}'
3324                         { $$ = $4; }
3325         |               /* empty */
3326                         { $$ = NULL; }
3327         ;
3328 
3329 UniqueTypesPart:        UniqueTypes
3330                         { $$ = $1; }
3331         |               /* empty */
3332                         { $$ = NULL; }
3333         ;
3334 
3335 UniqueTypes:            UniqueType
3336                         {
3337 			    $$ = smiMalloc(sizeof(List));
3338 			    $$->ptr = $1;
3339 			    $$->nextPtr = NULL;
3340 			}
3341         |               UniqueTypes ',' UniqueType
3342 			/* TODO: might this list be emtpy? */
3343 			{
3344 			    List *p, *pp;
3345 
3346 			    p = smiMalloc(sizeof(List));
3347 			    p->ptr = $3;
3348 			    p->nextPtr = NULL;
3349 			    for (pp = $1; pp->nextPtr; pp = pp->nextPtr);
3350 			    pp->nextPtr = p;
3351 			    $$ = $1;
3352                         }
3353         ;
3354 
3355 UniqueType:             ObjectName
3356                         { $$ = $1; }
3357         ;
3358 
3359 SPPIErrorsPart:         INSTALL_ERRORS
3360                         {
3361                             if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)
3362                                 smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "INSTALL-ERRORS");
3363                         }
3364                         '{' Errors '}'
3365                         { $$ = $4; }
3366         |               /* empty */
3367                         { $$ = NULL; }
3368         ;
3369 
3370 Errors:                 Error
3371                         {
3372 			    $$ = smiMalloc(sizeof(List));
3373 			    $$->ptr = $1;
3374 			    $$->nextPtr = NULL;
3375 			}
3376         |               Errors ',' Error
3377 			/* TODO: might this list be emtpy? */
3378 			{
3379 			    List *p, *pp;
3380 
3381 			    p = smiMalloc(sizeof(List));
3382 			    p->ptr = $3;
3383 			    p->nextPtr = NULL;
3384 			    for (pp = $1; pp->nextPtr; pp = pp->nextPtr);
3385 			    pp->nextPtr = p;
3386 			    $$ = $1;
3387                         }
3388         ;
3389 
3390 Error:                  LOWERCASE_IDENTIFIER '(' NUMBER ')'
3391 			{
3392 			    Object *objectPtr;
3393 
3394                             if (($3 < 1) || ($3 > 65536))
3395                                 smiPrintError(thisParserPtr, ERR_ERROR_NUMBER_RANGE, $3);
3396                             /*
3397                              * This is not a regular object that will be added vid
3398                              * 'addObject' as error identifier have no other
3399                              * meaning in PIBs. They are just used for
3400                              * a direct mapping to the actual protocol fields.
3401                              */
3402                             objectPtr = smiMalloc(sizeof(Object));
3403                             objectPtr->export.name = $1;
3404                             objectPtr->export.oidlen = 1;
3405                             objectPtr->export.oid = (void *)$3;
3406 			    $$ = objectPtr;
3407 			}
3408         ;
3409 
3410 
3411 MaxAccessPart:		MAX_ACCESS
3412 			{
3413 			    if (thisModulePtr->export.language == SMI_LANGUAGE_SMIV1)
3414 			    {
3415 			        smiPrintError(thisParserPtr,
3416 					      ERR_MAX_ACCESS_IN_SMIV1);
3417 			    } else if (thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI)
3418                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "MAX-ACCESS");
3419 			}
3420 			Access
3421 			{ $$ = $3; }
3422 	|		ACCESS
3423 			{
3424 			    if (thisModulePtr->export.language == SMI_LANGUAGE_SMIV2)
3425 			    {
3426 			        smiPrintError(thisParserPtr, ERR_ACCESS_IN_SMIV2);
3427 			    } else if (thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI)
3428                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "ACCESS");
3429 			}
3430 			Access
3431 			/* TODO: limited values in v1 */
3432 			{ $$ = $3; }
3433 	;
3434 
3435 notificationTypeClause:	LOWERCASE_IDENTIFIER
3436 			{
3437 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
3438 			    thisParserPtr->currentDecl = SMI_DECL_NOTIFICATIONTYPE;
3439 
3440 			    checkNameLen(thisParserPtr, $1,
3441 					 ERR_OIDNAME_32, ERR_OIDNAME_64);
3442 			    smiCheckObjectName(thisParserPtr,
3443 					       thisModulePtr, $1);
3444 			}
3445 			NOTIFICATION_TYPE
3446 			{
3447 			    Import *importPtr;
3448 
3449                             if (thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI)
3450                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "NOTIFICATION-TYPE");
3451 
3452 			    importPtr = findImportByName("NOTIFICATION-TYPE",
3453 							 thisModulePtr);
3454 			    if (importPtr) {
3455 				importPtr->use++;
3456 			    } else {
3457 				smiPrintError(thisParserPtr,
3458 					      ERR_MACRO_NOT_IMPORTED,
3459 					      "NOTIFICATION-TYPE",
3460 					      "SNMPv2-SMI");
3461 			    }
3462 			}
3463 			NotificationObjectsPart
3464 			STATUS Status
3465 			DESCRIPTION Text
3466 			{
3467 			    checkDescr(thisParserPtr, $9);
3468 			}
3469 			ReferPart
3470 			COLON_COLON_EQUAL
3471 			'{' NotificationName '}'
3472 			{
3473 			    Object *objectPtr;
3474 
3475 			    objectPtr = $14;
3476 
3477 			    smiCheckObjectReuse(thisParserPtr, $1, &objectPtr);
3478 
3479 			    objectPtr = setObjectName(objectPtr, $1, thisParserPtr);
3480 			    setObjectDecl(objectPtr,
3481 					  SMI_DECL_NOTIFICATIONTYPE);
3482 			    setObjectLine(objectPtr, thisParserPtr->firstStatementLine,
3483 					  thisParserPtr);
3484 			    addObjectFlags(objectPtr, FLAG_REGISTERED);
3485 			    deleteObjectFlags(objectPtr, FLAG_INCOMPLETE);
3486 			    setObjectList(objectPtr, $5);
3487 			    setObjectStatus(objectPtr, $7);
3488 			    setObjectDescription(objectPtr, $9, thisParserPtr);
3489 			    if ($11) {
3490 				setObjectReference(objectPtr, $11, thisParserPtr);
3491 			    }
3492 			    $$ = 0;
3493 			}
3494 	;
3495 
3496 moduleIdentityClause:	LOWERCASE_IDENTIFIER
3497 			{
3498 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
3499 			    thisParserPtr->currentDecl = SMI_DECL_MODULEIDENTITY;
3500 
3501 			    checkNameLen(thisParserPtr, $1,
3502 					 ERR_OIDNAME_32, ERR_OIDNAME_64);
3503 			    smiCheckObjectName(thisParserPtr,
3504 					       thisModulePtr, $1);
3505 			}
3506 			MODULE_IDENTITY
3507 			{
3508 			    Import *importPtr;
3509 
3510 			    importPtr = findImportByName("MODULE-IDENTITY",
3511 							 thisModulePtr);
3512 			    if (importPtr) {
3513 				importPtr->use++;
3514 			    } else {
3515 				smiPrintError(thisParserPtr,
3516 					      ERR_MACRO_NOT_IMPORTED,
3517 					      "MODULE-IDENTITY",
3518 					      "SNMPv2-SMI");
3519 			    }
3520 
3521 			    if (thisParserPtr->modulePtr->numModuleIdentities > 0)
3522 			    {
3523 			        smiPrintError(thisParserPtr,
3524 					      ERR_TOO_MANY_MODULE_IDENTITIES);
3525 			    }
3526 			    if (thisParserPtr->modulePtr->numStatements > 0) {
3527 			        smiPrintError(thisParserPtr,
3528 					      ERR_MODULE_IDENTITY_NOT_FIRST);
3529 			    }
3530 			}
3531                         SubjectCategoriesPart        /* SPPI only */
3532                         {
3533                           /* do nothing at the moment */
3534                         }
3535 			LAST_UPDATED ExtUTCTime
3536 			{
3537 			    setModuleLastUpdated(thisParserPtr->modulePtr, $8);
3538 			}
3539 			ORGANIZATION Text
3540 			{
3541 			    if ($11 && !strlen($11)) {
3542 				smiPrintError(thisParserPtr,
3543 					      ERR_EMPTY_ORGANIZATION);
3544 			    }
3545 			}
3546 			CONTACT_INFO Text
3547 			{
3548 			    if ($14 && !strlen($14)) {
3549 				smiPrintError(thisParserPtr,
3550 					      ERR_EMPTY_CONTACT);
3551 			    }
3552 			}
3553 			DESCRIPTION Text
3554 			{
3555 			    checkDescr(thisParserPtr, $17);
3556 			}
3557 			RevisionPart
3558                         {
3559 			    if ((!thisModulePtr->firstRevisionPtr) ||
3560 				(thisModulePtr->firstRevisionPtr->export.date !=
3561 				 thisModulePtr->lastUpdated)) {
3562 				smiPrintError(thisParserPtr,
3563 					      ERR_REVISION_MISSING);
3564 				addRevision(thisModulePtr->lastUpdated,
3565 					    smiStrdup(
3566 						"[Revision added by libsmi due to a LAST-UPDATED clause.]"),
3567 					    thisParserPtr);
3568 			    }
3569 			}
3570 			COLON_COLON_EQUAL
3571 			'{' objectIdentifier '}'
3572 			{
3573 			    Object *objectPtr;
3574 
3575 			    objectPtr = $23;
3576 			    smiCheckObjectReuse(thisParserPtr, $1, &objectPtr);
3577 
3578 			    thisParserPtr->modulePtr->numModuleIdentities++;
3579 
3580 			    objectPtr = setObjectName(objectPtr, $1, thisParserPtr);
3581 			    setObjectDecl(objectPtr, SMI_DECL_MODULEIDENTITY);
3582 			    setObjectLine(objectPtr, thisParserPtr->firstStatementLine,
3583 					  thisParserPtr);
3584 			    setObjectStatus(objectPtr, SMI_STATUS_CURRENT);
3585 			    addObjectFlags(objectPtr, FLAG_REGISTERED);
3586 			    deleteObjectFlags(objectPtr, FLAG_INCOMPLETE);
3587 			    setModuleIdentityObject(thisParserPtr->modulePtr,
3588 						    objectPtr);
3589 			    setModuleOrganization(thisParserPtr->modulePtr,
3590 						  $11);
3591 			    setModuleContactInfo(thisParserPtr->modulePtr,
3592 						 $14);
3593 			    setModuleDescription(thisParserPtr->modulePtr,
3594 						 $17, thisParserPtr);
3595                             if ($5 != NULL) {
3596                                 setObjectList(objectPtr, $5->categories);
3597                                 smiFree($5);
3598                             }
3599 			    /* setObjectDescription(objectPtr, $15); */
3600 			    $$ = 0;
3601 			}
3602         ;
3603 
3604 SubjectCategoriesPart:  SUBJECT_CATEGORIES '{' SubjectCategories '}'
3605                         {
3606                             if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)
3607                                 smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "SUBJECT-CATEGORIES");
3608                             $$ = $3;
3609                         }
3610         |               /* empty */
3611                         {
3612                             if (thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI)
3613                                 smiPrintError(thisParserPtr, ERR_SUBJECT_CATEGORIES_MISSING);
3614                             $$ = NULL;
3615                         }
3616         ;
3617 
3618 SubjectCategories:      CategoryIDs
3619                         {
3620                             $$ = smiMalloc(sizeof(SubjectCategories));
3621                             $$->categories    = $1;
3622                         }
3623         ;
3624 
3625 CategoryIDs:            CategoryID
3626 			{
3627 			    $$ = smiMalloc(sizeof(List));
3628 			    $$->ptr = $1;
3629 			    $$->nextPtr = NULL;
3630 			}
3631         |               CategoryIDs ',' CategoryID
3632 			{
3633 			    List *p, *pp;
3634 
3635                             if ($1->ptr == NULL)
3636                                 smiPrintError(thisParserPtr, ERR_SUBJECT_CATEGORIES_ALL);
3637 			    p = smiMalloc(sizeof(List));
3638 			    p->ptr = (void *)$3;
3639 			    p->nextPtr = NULL;
3640 			    for (pp = $1; pp->nextPtr; pp = pp->nextPtr);
3641 			    pp->nextPtr = p;
3642 			    $$ = $1;
3643 			}
3644         ;
3645 
3646 CategoryID:		LOWERCASE_IDENTIFIER
3647                         {
3648                             Object *objectPtr;
3649 
3650                             if (strcmp($1, "all"))
3651                                 smiPrintError(thisParserPtr, ERR_SUBJECT_CATEGORIES_MISSING_SUBID);
3652                             else {
3653                                 /*
3654                                  * This is not a regular object that will be added via
3655                                  * 'addObject' as subject category dentifier have no
3656                                  * other meaning in PIBs. They are just used for
3657                                  * a direct mapping to the actual protocol fields.
3658                                  */
3659                                 objectPtr = smiMalloc(sizeof(Object));
3660                                 objectPtr->export.name = "all";
3661                                 objectPtr->export.oidlen = 0;
3662                                 objectPtr->export.oid = 0;
3663                                 $$ = objectPtr;
3664                             }
3665                             smiFree($1);
3666                         }
3667         |               LOWERCASE_IDENTIFIER '(' NUMBER ')'
3668 			{
3669 			    Object *objectPtr;
3670 
3671                             if (!strcmp($1, "all")) {
3672                                 smiPrintError(thisParserPtr, ERR_SUBJECT_CATEGORIES_ALL_WITH_SUBID);
3673                                 $$ = NULL;
3674                             } else {
3675                                 /*
3676                                  * This is not a regular object that will be added via
3677                                  * 'addObject' as subject category dentifier have no
3678                                  * other meaning in PIBs. They are just used for
3679                                  * a direct mapping to the actual protocol fields.
3680                                  */
3681                                 objectPtr = smiMalloc(sizeof(Object));
3682                                 objectPtr->export.name = $1;
3683                                 objectPtr->export.oidlen = 1;
3684                                 objectPtr->export.oid = (void *)$3;
3685                                 $$ = objectPtr;
3686                             }
3687 			}
3688         ;
3689 
3690 ObjectSyntax:		SimpleSyntax
3691 			{
3692 			    $$ = $1;
3693 			}
3694 	|		typeTag SimpleSyntax
3695 			{
3696 			    if (strcmp(thisParserPtr->modulePtr->export.name,
3697 				       "SNMPv2-SMI") &&
3698 			        strcmp(thisParserPtr->modulePtr->export.name,
3699 				       "SNMPv2-TC") &&
3700 				strcmp(thisParserPtr->modulePtr->export.name,
3701 				       "SNMPv2-CONF") &&
3702 				strcmp(thisParserPtr->modulePtr->export.name,
3703 				       "RFC-1212") &&
3704 				strcmp(thisParserPtr->modulePtr->export.name,
3705 				       "RFC1065-SMI") &&
3706 				strcmp(thisParserPtr->modulePtr->export.name,
3707 				       "RFC1155-SMI") &&
3708                                 strcmp(thisParserPtr->modulePtr->export.name,
3709                                        "COPS-PR-SPPI")) {
3710 			        smiPrintError(thisParserPtr, ERR_TYPE_TAG, $1);
3711 			    }
3712 			    $$ = $2;
3713 			}
3714 	|		conceptualTable	     /* TODO: possible? row? entry? */
3715 			{
3716 			    /* TODO */
3717 			    $$ = $1;
3718 			}
3719 	|		row		     /* the uppercase name of a row  */
3720 			{
3721 			    /* TODO */
3722 			    $$ = $1;
3723 			}
3724 	|		entryType	     /* SEQUENCE { ... } phrase */
3725 			{
3726 			    /* TODO */
3727 			    $$ = $1;
3728 			}
3729 	|		ApplicationSyntax
3730 			{
3731 			    Import *importPtr;
3732 
3733 			    if ($1 && $1->export.name) {
3734 				importPtr = findImportByName($1->export.name,
3735 							     thisModulePtr);
3736 				if (importPtr) {
3737 				    importPtr->use++;
3738 				}
3739 			    }
3740 
3741 			    /* TODO */
3742 			    $$ = $1;
3743 			}
3744         ;
3745 
3746 typeTag:		'[' APPLICATION NUMBER ']' IMPLICIT
3747 			{ $$ = 0; /* TODO: check range */ }
3748 	|		'[' UNIVERSAL NUMBER ']' IMPLICIT
3749 			{ $$ = 0; /* TODO: check range */ }
3750 	;
3751 
3752 /*
3753  * In a SEQUENCE { ... } there are no sub-types, enumerations or
3754  * named bits. REF: draft, p.29
3755  */
3756 sequenceObjectSyntax:	sequenceSimpleSyntax
3757 			{ $$ = $1; }
3758 /*	|		conceptualTable	     /* TODO: possible? row? entry? */
3759 /*	|		row		     /* the uppercase name of a row  */
3760 /*	|		entryType	     /* it's SEQUENCE { ... } phrase */
3761 	|		sequenceApplicationSyntax
3762 			{
3763 			    Import *importPtr;
3764 
3765 			    if ($1 && $1->export.name) {
3766 				importPtr = findImportByName($1->export.name,
3767 							     thisModulePtr);
3768 				if (importPtr) {
3769 				    importPtr->use++;
3770 				}
3771 			    }
3772 
3773 			    /* TODO */
3774 			    $$ = $1;
3775 			}
3776         ;
3777 
3778 valueofObjectSyntax:	valueofSimpleSyntax
3779 			{ $$ = $1; }
3780 			/* conceptualTables and rows do not have DEFVALs
3781 			 */
3782 			/* valueofApplicationSyntax would not introduce any
3783 			 * further syntax of ObjectSyntax values.
3784 			 */
3785 	;
3786 
3787 SimpleSyntax:		INTEGER			/* (-2147483648..2147483647) */
3788 			{
3789 			    if ((thisModulePtr->export.language == SMI_LANGUAGE_SMIV2)
3790 				&&
3791 				(strcmp(thisModulePtr->export.name, "SNMPv2-SMI") &&
3792 				 strcmp(thisModulePtr->export.name, "SNMPv2-TC") &&
3793                                  strcmp(thisModulePtr->export.name, "COPS-PR-SPPI")))
3794 				smiPrintError(thisParserPtr,
3795 					      ERR_INTEGER_IN_SMIV2);
3796 
3797 			    defaultBasetype = SMI_BASETYPE_INTEGER32;
3798 			    $$ = smiHandle->typeInteger32Ptr;
3799 			}
3800 	|		INTEGER
3801 			{
3802 			    defaultBasetype = SMI_BASETYPE_INTEGER32;
3803 			}
3804 			integerSubType
3805 			{
3806 			    if ((thisModulePtr->export.language == SMI_LANGUAGE_SMIV2)
3807 				&&
3808 				(strcmp(thisModulePtr->export.name, "SNMPv2-SMI") &&
3809 				 strcmp(thisModulePtr->export.name, "SNMPv2-TC") &&
3810                                  strcmp(thisModulePtr->export.name, "COPS-PR-SPPI")))
3811 				smiPrintError(thisParserPtr,
3812 					      ERR_INTEGER_IN_SMIV2);
3813 
3814 			    $$ = duplicateType(smiHandle->typeInteger32Ptr, 0,
3815 					       thisParserPtr);
3816 			    setTypeList($$, $3);
3817 			    smiCheckTypeRanges(thisParserPtr, $$);
3818 			}
3819 	|		INTEGER
3820 			{
3821 			    defaultBasetype = SMI_BASETYPE_ENUM;
3822 			}
3823 			enumSpec
3824 			{
3825 			    List *p;
3826 
3827 			    $$ = duplicateType(smiHandle->typeEnumPtr, 0,
3828 					       thisParserPtr);
3829 			    setTypeList($$, $3);
3830 			    for (p = $3; p; p = p->nextPtr)
3831 				((NamedNumber *)p->ptr)->typePtr = $$;
3832 			    smiCheckNamedNumbersOrder(parserPtr, $$);
3833 			}
3834 	|		INTEGER32		/* (-2147483648..2147483647) */
3835 			{
3836 			    Import *importPtr;
3837 
3838 			    defaultBasetype = SMI_BASETYPE_INTEGER32;
3839 			    importPtr = findImportByName("Integer32",
3840 							 thisModulePtr);
3841 			    if (importPtr) {
3842 				importPtr->use++;
3843 			    } else {
3844 				if (thisModulePtr->export.language ==
3845 				    SMI_LANGUAGE_SMIV2) {
3846 				    smiPrintError(thisParserPtr,
3847 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
3848 						  "Integer32");
3849 				} else if (thisModulePtr->export.language ==
3850 					   SMI_LANGUAGE_SPPI) {
3851 				    smiPrintError(thisParserPtr,
3852 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
3853 						  "Integer32");
3854 				}
3855 			    }
3856 
3857 			    /* TODO: any need to distinguish from INTEGER? */
3858 			    $$ = smiHandle->typeInteger32Ptr;
3859 			}
3860         |		INTEGER32
3861 			{
3862 			    defaultBasetype = SMI_BASETYPE_INTEGER32;
3863 			}
3864 			integerSubType
3865 			{
3866 			    Import *importPtr;
3867 
3868 			    importPtr = findImportByName("Integer32",
3869 							 thisModulePtr);
3870 			    if (importPtr) {
3871 				importPtr->use++;
3872 			    } else {
3873 				if (thisModulePtr->export.language ==
3874 				    SMI_LANGUAGE_SMIV2) {
3875 				    smiPrintError(thisParserPtr,
3876 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
3877 						  "Integer32");
3878 				} else if (thisModulePtr->export.language ==
3879 					   SMI_LANGUAGE_SPPI) {
3880 				    smiPrintError(thisParserPtr,
3881 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
3882 						  "Integer32");
3883 				}
3884 			    }
3885 
3886 			    $$ = duplicateType(smiHandle->typeInteger32Ptr, 0,
3887 					       thisParserPtr);
3888 			    setTypeList($$, $3);
3889 			    smiCheckTypeRanges(thisParserPtr, $$);
3890 			}
3891 	|		UPPERCASE_IDENTIFIER
3892 			{
3893 			    defaultBasetype = SMI_BASETYPE_ENUM;
3894 			}
3895 			enumSpec
3896 			{
3897 			    Type *parentPtr;
3898 			    Import *importPtr;
3899 			    List *p;
3900 
3901 			    parentPtr = findTypeByModuleAndName(
3902 			        thisParserPtr->modulePtr, $1);
3903 			    if (!parentPtr) {
3904 			        importPtr = findImportByName($1,
3905 							     thisModulePtr);
3906 				if (importPtr &&
3907 				    importPtr->kind == KIND_TYPE) {
3908 				    importPtr->use++;
3909 				    parentPtr = findTypeByModulenameAndName(
3910 					importPtr->export.module, $1);
3911 				}
3912 			    }
3913 			    if (parentPtr) {
3914 				if ((parentPtr->export.basetype !=
3915 				     SMI_BASETYPE_ENUM) &&
3916 				    (parentPtr->export.basetype !=
3917 				     SMI_BASETYPE_BITS)) {
3918 				    smiPrintError(thisParserPtr,
3919 						  ERR_ILLEGAL_ENUM_FOR_PARENT_TYPE,
3920 						  $1);
3921 				    $$ = duplicateType(smiHandle->typeEnumPtr, 0,
3922 						       thisParserPtr);
3923 				} else {
3924 				    $$ = duplicateType(parentPtr, 0,
3925 						       thisParserPtr);
3926 				}
3927 				smiFree($1);
3928 			    } else {
3929 				/*
3930 				 * forward referenced type. create it,
3931 				 * marked with FLAG_INCOMPLETE.
3932 				 */
3933 				parentPtr = addType($1,
3934 						    SMI_BASETYPE_UNKNOWN,
3935 						    FLAG_INCOMPLETE,
3936 						    thisParserPtr);
3937 				$$ = duplicateType(parentPtr, 0,
3938 						   thisParserPtr);
3939 			    }
3940 			    setTypeList($$, $3);
3941 			    for (p = $3; p; p = p->nextPtr)
3942 				((NamedNumber *)p->ptr)->typePtr = $$;
3943 			    smiCheckNamedNumbersOrder(parserPtr, $$);
3944 			}
3945 	|		moduleName '.' UPPERCASE_IDENTIFIER enumSpec
3946 			/* TODO: UPPERCASE_IDENTIFIER must be an INTEGER */
3947 			{
3948 			    Type *parentPtr;
3949 			    Import *importPtr;
3950 			    List *p;
3951 
3952                             defaultBasetype = SMI_BASETYPE_ENUM;
3953                             parentPtr = findTypeByModulenameAndName($1, $3);
3954 			    if (!parentPtr) {
3955 				importPtr =
3956 				    findImportByModulenameAndName($1,
3957 							  $3, thisModulePtr);
3958 				if (importPtr &&
3959 				    importPtr->kind == KIND_TYPE) {
3960 				    importPtr->use++;
3961 				    parentPtr =
3962 					findTypeByModulenameAndName($1, $3);
3963 				}
3964 			    }
3965 			    if (parentPtr) {
3966 				if ((parentPtr->export.basetype !=
3967 				     SMI_BASETYPE_ENUM) &&
3968 				    (parentPtr->export.basetype !=
3969 				     SMI_BASETYPE_BITS)) {
3970 				    smiPrintError(thisParserPtr,
3971 						  ERR_ILLEGAL_ENUM_FOR_PARENT_TYPE,
3972 						  $3);
3973 				    $$ = duplicateType(smiHandle->typeEnumPtr, 0,
3974 						       thisParserPtr);
3975 				} else {
3976 				    $$ = duplicateType(parentPtr, 0,
3977 						       thisParserPtr);
3978 				}
3979 			    } else {
3980 				smiPrintError(thisParserPtr,
3981 					      ERR_UNKNOWN_TYPE, $3);
3982 				$$ = duplicateType(smiHandle->typeEnumPtr, 0,
3983 						   thisParserPtr);
3984 			    }
3985 			    setTypeList($$, $4);
3986 			    for (p = $4; p; p = p->nextPtr)
3987 				((NamedNumber *)p->ptr)->typePtr = $$;
3988 			    smiCheckNamedNumbersOrder(parserPtr, $$);
3989 			    smiFree($1);
3990 			    smiFree($3);
3991 			}
3992 	|		UPPERCASE_IDENTIFIER integerSubType
3993 			{
3994 			    Type *parentPtr;
3995 			    Import *importPtr;
3996 
3997 			    parentPtr = findTypeByModuleAndName(
3998 				thisParserPtr->modulePtr, $1);
3999 			    if (!parentPtr) {
4000 				importPtr = findImportByName($1,
4001 							     thisModulePtr);
4002 				if (importPtr &&
4003 				    importPtr->kind == KIND_TYPE) {
4004 				    importPtr->use++;
4005 				    parentPtr = findTypeByModulenameAndName(
4006 					importPtr->export.module, $1);
4007 				}
4008 			    }
4009 			    if (parentPtr) {
4010 				if ((parentPtr->export.basetype !=
4011 				    SMI_BASETYPE_INTEGER32) &&
4012 				    (parentPtr->export.basetype !=
4013 				     SMI_BASETYPE_INTEGER64) &&
4014 				    (parentPtr->export.basetype !=
4015 				     SMI_BASETYPE_UNSIGNED32) &&
4016 				    (parentPtr->export.basetype !=
4017 				     SMI_BASETYPE_UNSIGNED64)) {
4018 				    smiPrintError(thisParserPtr,
4019 					     ERR_ILLEGAL_RANGE_FOR_PARENT_TYPE,
4020 						  $1);
4021 				    $$ = duplicateType(smiHandle->typeInteger32Ptr, 0,
4022 						       thisParserPtr);
4023 				    defaultBasetype = SMI_BASETYPE_INTEGER32;
4024 				} else {
4025 				    defaultBasetype =
4026 					parentPtr->export.basetype;
4027 				    $$ = duplicateType(parentPtr, 0,
4028 						       thisParserPtr);
4029 				}
4030 				smiFree($1);
4031 			    } else {
4032 				/*
4033 				 * forward referenced type. create it,
4034 				 * marked with FLAG_INCOMPLETE.
4035 				 */
4036 				parentPtr = addType($1,
4037 						    SMI_BASETYPE_UNKNOWN,
4038 						    FLAG_INCOMPLETE,
4039 						    thisParserPtr);
4040 				$$ = duplicateType(parentPtr, 0,
4041 						   thisParserPtr);
4042 				defaultBasetype = SMI_BASETYPE_INTEGER32;
4043 			    }
4044 			    setTypeList($$, $2);
4045 			    smiCheckTypeRanges(thisParserPtr, $$);
4046 			}
4047 	|		moduleName '.' UPPERCASE_IDENTIFIER integerSubType
4048 			/* TODO: UPPERCASE_IDENTIFIER must be an INT/Int32. */
4049 			{
4050 			    Type *parentPtr;
4051 			    Import *importPtr;
4052 
4053 			    parentPtr = findTypeByModulenameAndName($1, $3);
4054 			    if (!parentPtr) {
4055 				importPtr = findImportByModulenameAndName($1,
4056 							  $3, thisModulePtr);
4057 				if (importPtr &&
4058 				    importPtr->kind == KIND_TYPE) {
4059 				    importPtr->use++;
4060 				    parentPtr = findTypeByModulenameAndName(
4061 					$1, $3);
4062 				}
4063 			    }
4064 			    if (parentPtr) {
4065 				if ((parentPtr->export.basetype !=
4066 				    SMI_BASETYPE_INTEGER32) &&
4067 				    (parentPtr->export.basetype !=
4068 				     SMI_BASETYPE_INTEGER64) &&
4069 				    (parentPtr->export.basetype !=
4070 				     SMI_BASETYPE_UNSIGNED32) &&
4071 				    (parentPtr->export.basetype !=
4072 				     SMI_BASETYPE_UNSIGNED64)) {
4073 				    smiPrintError(thisParserPtr,
4074 					     ERR_ILLEGAL_RANGE_FOR_PARENT_TYPE,
4075 						  $3);
4076 				    $$ = duplicateType(smiHandle->typeInteger32Ptr, 0,
4077 						       thisParserPtr);
4078 				    defaultBasetype = SMI_BASETYPE_INTEGER32;
4079 				} else {
4080 				    defaultBasetype =
4081 					parentPtr->export.basetype;
4082 				    $$ = duplicateType(parentPtr, 0,
4083 						       thisParserPtr);
4084 				}
4085 			    } else {
4086 				smiPrintError(thisParserPtr,
4087 					      ERR_UNKNOWN_TYPE, $3);
4088 				$$ = duplicateType(smiHandle->typeInteger32Ptr, 0,
4089 						   thisParserPtr);
4090 				defaultBasetype = SMI_BASETYPE_INTEGER32;
4091 			    }
4092 			    setTypeList($$, $4);
4093 			    smiCheckTypeRanges(thisParserPtr, $$);
4094 			    smiFree($1);
4095 			    smiFree($3);
4096 			}
4097 	|		OCTET STRING		/* (SIZE (0..65535))	     */
4098 			{
4099 			    defaultBasetype = SMI_BASETYPE_OCTETSTRING;
4100 			    $$ = smiHandle->typeOctetStringPtr;
4101 			}
4102 	|		OCTET STRING
4103 			{
4104 			    defaultBasetype = SMI_BASETYPE_OCTETSTRING;
4105 			}
4106 			octetStringSubType
4107 			{
4108 
4109 			    $$ = duplicateType(smiHandle->typeOctetStringPtr, 0,
4110 					       thisParserPtr);
4111 			    setTypeList($$, $4);
4112 			    smiCheckTypeRanges(thisParserPtr, $$);
4113 			}
4114 	|		UPPERCASE_IDENTIFIER octetStringSubType
4115 			{
4116 			    Type *parentPtr;
4117 			    Import *importPtr;
4118 
4119 			    defaultBasetype = SMI_BASETYPE_OCTETSTRING;
4120 			    parentPtr = findTypeByModuleAndName(
4121 				thisParserPtr->modulePtr, $1);
4122 			    if (!parentPtr) {
4123 				importPtr = findImportByName($1,
4124 							     thisModulePtr);
4125 				if (importPtr &&
4126 				    importPtr->kind == KIND_TYPE) {
4127 				    importPtr->use++;
4128 				    parentPtr = findTypeByModulenameAndName(
4129 					importPtr->export.module, $1);
4130 				}
4131 			    }
4132 			    if (parentPtr) {
4133 				if (parentPtr->export.basetype !=
4134 				    SMI_BASETYPE_OCTETSTRING) {
4135 				    smiPrintError(thisParserPtr,
4136 					      ERR_ILLEGAL_SIZE_FOR_PARENT_TYPE,
4137 						  $1);
4138 				    $$ = duplicateType(smiHandle->typeOctetStringPtr, 0,
4139 						       thisParserPtr);
4140 				} else {
4141 				    $$ = duplicateType(parentPtr, 0,
4142 						       thisParserPtr);
4143 				}
4144 				smiFree($1);
4145 			    } else {
4146 				/*
4147 				 * forward referenced type. create it,
4148 				 * marked with FLAG_INCOMPLETE.
4149 				 */
4150 				parentPtr = addType($1,
4151 						    SMI_BASETYPE_UNKNOWN,
4152 						    FLAG_INCOMPLETE,
4153 						    thisParserPtr);
4154 				$$ = duplicateType(parentPtr, 0,
4155 						   thisParserPtr);
4156 			    }
4157 			    setTypeList($$, $2);
4158 			    smiCheckTypeRanges(thisParserPtr, $$);
4159 			}
4160 	|		moduleName '.' UPPERCASE_IDENTIFIER octetStringSubType
4161 			/* TODO: UPPERCASE_IDENTIFIER must be an OCTET STR. */
4162 			{
4163 			    Type *parentPtr;
4164 			    Import *importPtr;
4165 
4166 			    defaultBasetype = SMI_BASETYPE_OCTETSTRING;
4167 			    parentPtr = findTypeByModulenameAndName($1, $3);
4168 			    if (!parentPtr) {
4169 				importPtr = findImportByModulenameAndName($1,
4170 							  $3, thisModulePtr);
4171 				if (importPtr &&
4172 				    importPtr->kind == KIND_TYPE) {
4173 				    importPtr->use++;
4174 				    parentPtr = findTypeByModulenameAndName(
4175 					$1, $3);
4176 				}
4177 			    }
4178 			    if (parentPtr) {
4179 				if (parentPtr->export.basetype !=
4180 				    SMI_BASETYPE_OCTETSTRING) {
4181 				    smiPrintError(thisParserPtr,
4182 					      ERR_ILLEGAL_SIZE_FOR_PARENT_TYPE,
4183 						  $3);
4184 				    $$ = duplicateType(smiHandle->typeOctetStringPtr, 0,
4185 						       thisParserPtr);
4186 				} else {
4187 				    $$ = duplicateType(parentPtr, 0,
4188 						       thisParserPtr);
4189 				}
4190 			    } else {
4191 				smiPrintError(thisParserPtr,
4192 					      ERR_UNKNOWN_TYPE, $3);
4193 				$$ = duplicateType(smiHandle->typeOctetStringPtr, 0,
4194 						   thisParserPtr);
4195 			    }
4196 			    setTypeList($$, $4);
4197 			    smiCheckTypeRanges(thisParserPtr, $$);
4198 			    smiFree($1);
4199 			    smiFree($3);
4200 			}
4201 	|		OBJECT IDENTIFIER anySubType
4202 			{
4203 			    defaultBasetype = SMI_BASETYPE_OBJECTIDENTIFIER;
4204 			    $$ = smiHandle->typeObjectIdentifierPtr;
4205 			}
4206         ;
4207 
4208 valueofSimpleSyntax:	NUMBER			/* 0..2147483647 */
4209 			/* NOTE: Counter64 must not have a DEFVAL */
4210 			{
4211 			    $$ = smiMalloc(sizeof(SmiValue));
4212 			    $$->basetype = SMI_BASETYPE_UNSIGNED32;
4213 			    $$->value.unsigned32 = $1;
4214 			}
4215 	|		NEGATIVENUMBER		/* -2147483648..0 */
4216 			{
4217 			    $$ = smiMalloc(sizeof(SmiValue));
4218 			    $$->basetype = SMI_BASETYPE_INTEGER32;
4219 			    $$->value.integer32 = $1;
4220 			}
4221         |               NUMBER64		/* 0..18446744073709551615 */
4222 			{
4223                             /* The scanner already checks for the language */
4224 			    $$ = smiMalloc(sizeof(SmiValue));
4225 			    $$->basetype = SMI_BASETYPE_UNSIGNED64;
4226 			    $$->value.unsigned64 = $1;
4227 			}
4228 	|		NEGATIVENUMBER64	/* -9223372036854775807..0 */
4229 			{
4230                             /* The scanner already checks for the language */
4231 			    $$ = smiMalloc(sizeof(SmiValue));
4232 			    $$->basetype = SMI_BASETYPE_INTEGER64;
4233 			    $$->value.integer64 = $1;
4234 			}
4235 	|		BIN_STRING		/* number or OCTET STRING */
4236 			{
4237 			    char s[9];
4238 			    int i, len, j;
4239 
4240 			    $$ = smiMalloc(sizeof(SmiValue));
4241 			    if (defaultBasetype == SMI_BASETYPE_OCTETSTRING) {
4242 				$$->basetype = SMI_BASETYPE_OCTETSTRING;
4243 				len = strlen($1);
4244 				$$->value.ptr =
4245 				    smiMalloc((len+7)/8+1);
4246 				for (i = 0; i < len; i += 8) {
4247 				    strncpy(s, &$1[i], 8);
4248 				    for (j = 1; j < 8; j++) {
4249 					if (!s[j]) s[j] = '0';
4250 				    }
4251 				    s[8] = 0;
4252 				    $$->value.ptr[i/8] =
4253 					(unsigned char)strtol(s, 0, 2);
4254 				}
4255 				$$->len = (len+7)/8;
4256 			    } else {
4257 				$$->basetype = SMI_BASETYPE_UNSIGNED32;
4258 				$$->value.unsigned32 = strtoul($1, NULL, 2);
4259 			    }
4260 			}
4261 	|		HEX_STRING		/* number or OCTET STRING */
4262 			{
4263 			    char s[3];
4264 			    int i, len;
4265 
4266 			    $$ = smiMalloc(sizeof(SmiValue));
4267 			    if (defaultBasetype == SMI_BASETYPE_OCTETSTRING) {
4268 				$$->basetype = SMI_BASETYPE_OCTETSTRING;
4269 				len = strlen($1);
4270 				$$->value.ptr = smiMalloc((len+1)/2+1);
4271 				for (i = 0; i < len; i += 2) {
4272 				    strncpy(s, &$1[i], 2);
4273 				    if (!s[1]) s[1] = '0';
4274 				    s[2] = 0;
4275 				    $$->value.ptr[i/2] =
4276 					(unsigned char)strtol(s, 0, 16);
4277 				}
4278 				$$->len = (len+1)/2;
4279 			    } else {
4280 				$$->basetype = SMI_BASETYPE_UNSIGNED32;
4281 				$$->value.unsigned32 = strtoul($1, NULL, 16);
4282 			    }
4283 			}
4284 	|		LOWERCASE_IDENTIFIER	/* enumeration or named oid */
4285 			{
4286 			    $$ = smiMalloc(sizeof(SmiValue));
4287 			    if ((defaultBasetype != SMI_BASETYPE_ENUM) &&
4288 				(defaultBasetype != SMI_BASETYPE_OBJECTIDENTIFIER)) {
4289 				smiPrintError(thisParserPtr, ERR_DEFVAL_SYNTAX);
4290 				$$->basetype = defaultBasetype;
4291 				if (defaultBasetype == SMI_BASETYPE_ENUM) {
4292 				    $$->len = 1;
4293 				    $$->value.unsigned32 = 0;
4294 				} else {
4295 				    $$->len = 0;
4296 				    $$->value.ptr = NULL;
4297 				}
4298 			    } else {
4299 				$$->basetype = defaultBasetype;
4300 				$$->len = -1;  /* indicates unresolved ptr */
4301 				$$->value.ptr = $1; /* JS: needs strdup? */
4302 			    }
4303 			}
4304 	|		QUOTED_STRING		/* an OCTET STRING */
4305 			{
4306 			    $$ = smiMalloc(sizeof(SmiValue));
4307 			    $$->basetype = SMI_BASETYPE_OCTETSTRING;
4308 			    $$->value.ptr = smiStrdup($1);
4309 			    $$->len = strlen($1);
4310 			}
4311 			/* NOTE: If the value is an OBJECT IDENTIFIER, then
4312 			 *       it must be expressed as a single ASN.1
4313 			 *	 identifier, and not as a collection of
4314 			 *	 of sub-identifiers.
4315 			 *	 REF: draft,p.34
4316 			 *	 Anyway, we try to accept it. But it's only
4317 			 *	 possible for numbered sub-identifiers, since
4318 			 *	 other identifiers would make something like
4319 			 *	 { gaga } indistiguishable from a BitsValue.
4320 			 */
4321 	|		'{' objectIdentifier_defval '}'
4322 			/*
4323 			 * This is only for some MIBs with invalid numerical
4324 			 * OID notation for DEFVALs. We DO NOT parse them
4325 			 * correctly. We just don't want to produce a
4326 			 * parser error.
4327 			 */
4328 			{
4329 			    /*
4330 			     * SMIv1 allows something like { 0 0 } !
4331 			     * SMIv2 does not!
4332 			     */
4333 			    /* TODO: make it work correctly for SMIv1 */
4334 			    if (thisModulePtr->export.language == SMI_LANGUAGE_SMIV2) {
4335 				smiPrintError(thisParserPtr,
4336 					      ERR_OID_DEFVAL_TOO_LONG_SMIV2);
4337 			    } else {
4338 				smiPrintError(thisParserPtr,
4339 					      ERR_OID_DEFVAL_TOO_LONG_SMIV1);
4340 			    }
4341 			    $$ = smiMalloc(sizeof(SmiValue));
4342 			    $$->basetype = SMI_BASETYPE_OBJECTIDENTIFIER;
4343 			    $$->len = 2;
4344 			    $$->value.oid = smiMalloc(2 * sizeof(SmiSubid));
4345 			    $$->value.oid[0] = 0;
4346 			    $$->value.oid[1] = 0;
4347 			}
4348 	;
4349 
4350 /*
4351  * In a SEQUENCE { ... } there are no sub-types, enumerations or
4352  * named bits. REF: draft, p.29
4353  */
4354 sequenceSimpleSyntax:	INTEGER	anySubType
4355 			{
4356 			    $$ = smiHandle->typeInteger32Ptr;
4357 			}
4358         |		INTEGER32 anySubType
4359 			{
4360 			    Import *importPtr;
4361 
4362 			    /* TODO: any need to distinguish from INTEGER? */
4363 			    $$ = smiHandle->typeInteger32Ptr;
4364 
4365 			    importPtr = findImportByName("Integer32",
4366 							 thisModulePtr);
4367 			    if (importPtr) {
4368 				importPtr->use++;
4369 			    } else {
4370 				if (thisModulePtr->export.language ==
4371 				    SMI_LANGUAGE_SMIV2) {
4372 				    smiPrintError(thisParserPtr,
4373 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4374 						  "Integer32");
4375 				} else if (thisModulePtr->export.language ==
4376 					   SMI_LANGUAGE_SPPI) {
4377 				    smiPrintError(thisParserPtr,
4378 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
4379 						  "Integer32");
4380 				}
4381 			    }
4382 			}
4383 	|		OCTET STRING anySubType
4384 			{
4385 			    $$ = smiHandle->typeOctetStringPtr;
4386 			}
4387 	|		OBJECT IDENTIFIER anySubType
4388 			{
4389 			    $$ = smiHandle->typeObjectIdentifierPtr;
4390 			}
4391 	;
4392 
4393 ApplicationSyntax:	IPADDRESS anySubType
4394 			{
4395 			    Import *importPtr;
4396 
4397 			    $$ = findTypeByName("IpAddress");
4398 			    if (! $$) {
4399 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4400 					      "IpAddress");
4401 			    }
4402 
4403 			    importPtr = findImportByName("IpAddress",
4404 							 thisModulePtr);
4405 			    if (importPtr) {
4406 				importPtr->use++;
4407 			    } else {
4408 				if (thisModulePtr->export.language ==
4409 				    SMI_LANGUAGE_SMIV2) {
4410 				    smiPrintError(thisParserPtr,
4411 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4412 						  "IpAddress");
4413 				} else if (thisModulePtr->export.language ==
4414 					   SMI_LANGUAGE_SPPI) {
4415 				    smiPrintError(thisParserPtr,
4416 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
4417 						  "IpAddress");
4418 				}
4419 			    }
4420 			}
4421 	|		COUNTER32 anySubType  /* (0..4294967295)	     */
4422 			{
4423 			    Import *importPtr;
4424 
4425                             if ((thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI) &&
4426                                 !findImportByName("Counter32", thisParserPtr->modulePtr))
4427                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "COUNTER32");
4428 			    $$ = findTypeByName("Counter32");
4429 			    if (! $$) {
4430 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4431 					      "Counter32");
4432 			    }
4433 
4434 			    importPtr = findImportByName("Counter32",
4435 							 thisModulePtr);
4436 			    if (importPtr) {
4437 				importPtr->use++;
4438 			    } else {
4439 				if (thisModulePtr->export.language ==
4440 				    SMI_LANGUAGE_SMIV2) {
4441 				    smiPrintError(thisParserPtr,
4442 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4443 						  "Counter32");
4444 				}
4445 			    }
4446 			}
4447 	|		COUNTER32 integerSubType
4448 			{
4449 			    Import *importPtr;
4450 			    List *listPtr, *nextListPtr;
4451 
4452 			    smiPrintError(thisParserPtr,
4453 					  ERR_ILLEGAL_RANGE_FOR_COUNTER,
4454 					  "Counter32");
4455 			    for (listPtr = $2; listPtr;
4456 				 listPtr = nextListPtr) {
4457 				nextListPtr = listPtr->nextPtr;
4458 				smiFree((Range *)listPtr->ptr);
4459 				smiFree(listPtr);
4460 			    }
4461 
4462                             if ((thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI) &&
4463                                 !findImportByName("Counter32", thisParserPtr->modulePtr))
4464                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "Counter32");
4465 			    $$ = findTypeByName("Counter32");
4466 			    if (! $$) {
4467 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4468 					      "Counter32");
4469 			    }
4470 
4471 			    importPtr = findImportByName("Counter32",
4472 							 thisModulePtr);
4473 			    if (importPtr) {
4474 				importPtr->use++;
4475 			    } else {
4476 				if (thisModulePtr->export.language ==
4477 				    SMI_LANGUAGE_SMIV2) {
4478 				    smiPrintError(thisParserPtr,
4479 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4480 						  "Counter32");
4481 				}
4482 			    }
4483 			}
4484 	|		GAUGE32			/* (0..4294967295)	     */
4485 			{
4486 			    Import *importPtr;
4487 
4488                             if ((thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI) &&
4489                                 !findImportByName("Gauge32", thisParserPtr->modulePtr))
4490                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "Gauge32");
4491 			    $$ = findTypeByName("Gauge32");
4492 			    if (! $$) {
4493 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4494 					      "Gauge32");
4495 			    }
4496 
4497 			    importPtr = findImportByName("Gauge32",
4498 							 thisModulePtr);
4499 			    if (importPtr) {
4500 				importPtr->use++;
4501 			    } else {
4502 				if (thisModulePtr->export.language ==
4503 				    SMI_LANGUAGE_SMIV2) {
4504 				    smiPrintError(thisParserPtr,
4505 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4506 						  "Gauge32");
4507 				}
4508 			    }
4509 			}
4510 	|		GAUGE32 integerSubType
4511 			{
4512 			    Type *parentPtr;
4513 			    Import *importPtr;
4514 
4515                             if ((thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI) &&
4516                                 !findImportByName("Gauge32", thisParserPtr->modulePtr))
4517                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "Gauge32");
4518 			    parentPtr = findTypeByName("Gauge32");
4519 			    if (! parentPtr) {
4520 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4521 					      "Gauge32");
4522 				$$ = NULL;
4523 			    } else {
4524 				$$ = duplicateType(parentPtr, 0,
4525 						   thisParserPtr);
4526 				setTypeList($$, $2);
4527 				smiCheckTypeRanges(thisParserPtr, $$);
4528 			    }
4529 
4530 			    importPtr = findImportByName("Gauge32",
4531 							 thisModulePtr);
4532 			    if (importPtr) {
4533 				importPtr->use++;
4534 			    } else {
4535 				if (thisModulePtr->export.language ==
4536 				    SMI_LANGUAGE_SMIV2) {
4537 				    smiPrintError(thisParserPtr,
4538 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4539 						  "Gauge32");
4540 				}
4541 			    }
4542 			}
4543 	|		UNSIGNED32		/* (0..4294967295)	     */
4544 			{
4545 			    Import *importPtr;
4546 
4547 			    $$ = smiHandle->typeUnsigned32Ptr;
4548 
4549 			    importPtr = findImportByName("Unsigned32",
4550 							 thisModulePtr);
4551 			    if (importPtr) {
4552 				importPtr->use++;
4553 			    } else {
4554 				if (thisModulePtr->export.language ==
4555 				    SMI_LANGUAGE_SMIV2) {
4556 				    smiPrintError(thisParserPtr,
4557 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4558 						  "Unsigned32");
4559 				} else if (thisModulePtr->export.language ==
4560 					   SMI_LANGUAGE_SPPI) {
4561 				    smiPrintError(thisParserPtr,
4562 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
4563 						  "Unsigned32");
4564 				}
4565 			    }
4566 			}
4567 	|		UNSIGNED32 integerSubType
4568 			{
4569 			    Import *importPtr;
4570 
4571 			    $$ = duplicateType(smiHandle->typeUnsigned32Ptr, 0,
4572 					       thisParserPtr);
4573 			    setTypeList($$, $2);
4574 			    smiCheckTypeRanges(thisParserPtr, $$);
4575 
4576 			    importPtr = findImportByName("Unsigned32",
4577 							 thisModulePtr);
4578 			    if (importPtr) {
4579 				importPtr->use++;
4580 			    } else {
4581 				if (thisModulePtr->export.language ==
4582 				    SMI_LANGUAGE_SMIV2) {
4583 				    smiPrintError(thisParserPtr,
4584 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4585 						  "Unsigned32");
4586 				} else if (thisModulePtr->export.language ==
4587 					   SMI_LANGUAGE_SPPI) {
4588 				    smiPrintError(thisParserPtr,
4589 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
4590 						  "Unsigned32");
4591 				}
4592 			    }
4593 			}
4594 	|		TIMETICKS anySubType
4595 			{
4596 			    Import *importPtr;
4597 
4598 			    $$ = findTypeByName("TimeTicks");
4599 			    if (! $$) {
4600 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4601 					      "TimeTicks");
4602 			    }
4603 
4604 			    importPtr = findImportByName("TimeTicks",
4605 							 thisModulePtr);
4606 			    if (importPtr) {
4607 				importPtr->use++;
4608 			    } else {
4609 				if (thisModulePtr->export.language ==
4610 				    SMI_LANGUAGE_SMIV2) {
4611 				    smiPrintError(thisParserPtr,
4612 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4613 						  "TimeTicks");
4614 				} else if (thisModulePtr->export.language ==
4615 					   SMI_LANGUAGE_SPPI) {
4616 				    smiPrintError(thisParserPtr,
4617 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
4618 						  "TimeTicks");
4619 				}
4620 			    }
4621 			}
4622 	|		OPAQUE			/* IMPLICIT OCTET STRING     */
4623 			{
4624 			    Import *importPtr;
4625 
4626 			    $$ = findTypeByName("Opaque");
4627 			    if (! $$) {
4628 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4629 					      "Opaque");
4630 			    } else {
4631 				if (thisModulePtr->export.language ==
4632 				    SMI_LANGUAGE_SMIV2) {
4633 				    smiPrintError(thisParserPtr,
4634 						  ERR_SMIV2_OPAQUE_OBSOLETE);
4635 				} else if (thisModulePtr->export.language ==
4636 					   SMI_LANGUAGE_SPPI) {
4637 				    smiPrintError(thisParserPtr,
4638 						  ERR_SPPI_OPAQUE_OBSOLETE);
4639 				}
4640 			    }
4641 
4642 			    importPtr = findImportByName("Opaque",
4643 							 thisModulePtr);
4644 			    if (importPtr) {
4645 				importPtr->use++;
4646 			    } else {
4647 				if (thisModulePtr->export.language ==
4648 				    SMI_LANGUAGE_SMIV2) {
4649 				    smiPrintError(thisParserPtr,
4650 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4651 						  "Opaque");
4652 				} else if (thisModulePtr->export.language ==
4653 					   SMI_LANGUAGE_SPPI) {
4654 				    smiPrintError(thisParserPtr,
4655 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
4656 						  "Opaque");
4657 				}
4658 			    }
4659 			}
4660 	|		OPAQUE octetStringSubType
4661 			{
4662 			    Type *parentPtr;
4663 			    Import *importPtr;
4664 
4665 			    parentPtr = findTypeByName("Opaque");
4666 			    if (! parentPtr) {
4667 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4668 					      "Opaque");
4669 				$$ = NULL;
4670 			    } else {
4671 				if (thisModulePtr->export.language ==
4672 				    SMI_LANGUAGE_SMIV2) {
4673 				    smiPrintError(thisParserPtr,
4674 						  ERR_SMIV2_OPAQUE_OBSOLETE,
4675 						  "Opaque");
4676 				} else if (thisModulePtr->export.language ==
4677 					   SMI_LANGUAGE_SPPI) {
4678 				    smiPrintError(thisParserPtr,
4679 						  ERR_SPPI_OPAQUE_OBSOLETE,
4680 						  "Opaque");
4681 				}
4682 				$$ = duplicateType(parentPtr, 0,
4683 						   thisParserPtr);
4684 				setTypeList($$, $2);
4685 				smiCheckTypeRanges(thisParserPtr, $$);
4686 			    }
4687 
4688 			    importPtr = findImportByName("Opaque",
4689 							 thisModulePtr);
4690 			    if (importPtr) {
4691 				importPtr->use++;
4692 			    } else {
4693 				if (thisModulePtr->export.language ==
4694 				    SMI_LANGUAGE_SMIV2) {
4695 				    smiPrintError(thisParserPtr,
4696 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4697 						  "Opaque");
4698 				} else if (thisModulePtr->export.language ==
4699 					   SMI_LANGUAGE_SPPI) {
4700 				    smiPrintError(thisParserPtr,
4701 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
4702 						  "Opaque");
4703 				}
4704 			    }
4705 			}
4706 	|		COUNTER64 anySubType   /* (0..18446744073709551615) */
4707 			{
4708 			    Import *importPtr;
4709 
4710                             if ((thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI) &&
4711                                 !findImportByName("Counter64", thisParserPtr->modulePtr))
4712                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "Counter64");
4713 			    $$ = findTypeByName("Counter64");
4714 			    if (! $$) {
4715 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4716 					      "Counter64");
4717 			    }
4718 
4719 			    importPtr = findImportByName("Counter64",
4720 							 thisModulePtr);
4721 			    if (importPtr) {
4722 				importPtr->use++;
4723 			    } else {
4724 				if (thisModulePtr->export.language ==
4725 				    SMI_LANGUAGE_SMIV2) {
4726 				    smiPrintError(thisParserPtr,
4727 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4728 						  "Counter64");
4729 				}
4730 			    }
4731 			}
4732 	|		COUNTER64 integerSubType
4733 			{
4734 			    Import *importPtr;
4735 			    List *listPtr, *nextListPtr;
4736 
4737 			    smiPrintError(thisParserPtr,
4738 					  ERR_ILLEGAL_RANGE_FOR_COUNTER,
4739 					  "Counter64");
4740 			    for (listPtr = $2; listPtr;
4741 				 listPtr = nextListPtr) {
4742 				nextListPtr = listPtr->nextPtr;
4743 				smiFree((Range *)listPtr->ptr);
4744 				smiFree(listPtr);
4745 			    }
4746 
4747                             if ((thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI) &&
4748                                 !findImportByName("Counter64", thisParserPtr->modulePtr))
4749                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "Counter64");
4750 			    $$ = findTypeByName("Counter64");
4751 			    if (! $$) {
4752 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4753 					      "Counter64");
4754 			    }
4755 
4756 			    importPtr = findImportByName("Counter64",
4757 							 thisModulePtr);
4758 			    if (importPtr) {
4759 				importPtr->use++;
4760 			    } else {
4761 				if (thisModulePtr->export.language ==
4762 				    SMI_LANGUAGE_SMIV2) {
4763 				    smiPrintError(thisParserPtr,
4764 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4765 						  "Counter64");
4766 				}
4767 			    }
4768 			}
4769 	|		INTEGER64               /* (-9223372036854775807..9223372036854775807) */
4770 			{
4771 			    Import *importPtr;
4772 
4773 			    $$ = findTypeByModulenameAndName(
4774 				thisParserPtr->modulePtr->export.name, "Integer64");
4775 			    if (! $$) {
4776 				importPtr = findImportByName("Integer64",
4777 							     thisModulePtr);
4778 				if (!importPtr) {
4779 				    $$ = findTypeByName("Integer64");
4780 				    if ((thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)) {
4781 					smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "Integer64");
4782 				    } else {
4783 					smiPrintError(thisParserPtr,
4784 						      ERR_SPPI_BASETYPE_NOT_IMPORTED,
4785 						      "Integer64");
4786 				    }
4787 				} else {
4788 				    importPtr->use++;
4789 				    $$ = findTypeByModulenameAndName(
4790 					importPtr->export.module,
4791 					importPtr->export.name);
4792 				}
4793 			    }
4794 			}
4795 	|		INTEGER64 integerSubType
4796 			{
4797 			    Type *parentPtr;
4798 			    Import *importPtr;
4799 
4800 			    parentPtr = findTypeByModulenameAndName(
4801 				thisParserPtr->modulePtr->export.name, "Integer64");
4802 			    if (! parentPtr) {
4803 				importPtr = findImportByName("Integer64",
4804 							     thisModulePtr);
4805 				if (!importPtr) {
4806 				    parentPtr = findTypeByName("Integer64");
4807 				    if ((thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)) {
4808 					smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "Integer64");
4809 				    } else {
4810 					smiPrintError(thisParserPtr,
4811 						      ERR_SPPI_BASETYPE_NOT_IMPORTED,
4812 						      "Integer64");
4813 				    }
4814 				} else {
4815 				    importPtr->use++;
4816 				    parentPtr = findTypeByModulenameAndName(
4817 					importPtr->export.module,
4818 					importPtr->export.name);
4819 				}
4820 			    }
4821 			    if (! parentPtr) {
4822 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4823 					      "Integer64");
4824 				$$ = NULL;
4825 			    } else {
4826 				$$ = duplicateType(parentPtr, 0,
4827 						   thisParserPtr);
4828 				setTypeList($$, $2);
4829 				smiCheckTypeRanges(thisParserPtr, $$);
4830 			    }
4831 			}
4832 	|		UNSIGNED64	        /* (0..18446744073709551615) */
4833 			{
4834 			    Import *importPtr;
4835 
4836 			    $$ = findTypeByModulenameAndName(
4837 				thisParserPtr->modulePtr->export.name, "Unsigned64");
4838 			    if (! $$) {
4839 				importPtr = findImportByName("Unsigned64",
4840 							     thisModulePtr);
4841 				if (!importPtr) {
4842 				    $$ = findTypeByName("Unsigned64");
4843 				    if ((thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)) {
4844 					smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "Unsigned64");
4845 				    } else {
4846 					smiPrintError(thisParserPtr,
4847 						      ERR_SPPI_BASETYPE_NOT_IMPORTED,
4848 						      "Unsigned64");
4849 				    }
4850 				} else {
4851 				    importPtr->use++;
4852 				    $$ = findTypeByModulenameAndName(
4853 					importPtr->export.module,
4854 					importPtr->export.name);
4855 				}
4856 			    }
4857 			}
4858 	|		UNSIGNED64 integerSubType
4859 			{
4860 			    Type *parentPtr;
4861 			    Import *importPtr;
4862 
4863 			    parentPtr = findTypeByModulenameAndName(
4864 				thisParserPtr->modulePtr->export.name, "Unsigned64");
4865 			    if (! parentPtr) {
4866 				importPtr = findImportByName("Unsigned64",
4867 							     thisModulePtr);
4868 				if (!importPtr) {
4869 				    parentPtr = findTypeByName("Unsigned64");
4870 				    if ((thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)) {
4871 					smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "Unsigned64");
4872 				    } else {
4873 					smiPrintError(thisParserPtr,
4874 						      ERR_SPPI_BASETYPE_NOT_IMPORTED,
4875 						      "Unsigned64");
4876 				    }
4877 				} else {
4878 				    importPtr->use++;
4879 				    parentPtr = findTypeByModulenameAndName(
4880 					importPtr->export.module,
4881 					importPtr->export.name);
4882 				}
4883 			    }
4884 			    if (! parentPtr) {
4885 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4886 					      "Unsigned64");
4887 				$$ = NULL;
4888 			    } else {
4889 				$$ = duplicateType(parentPtr, 0,
4890 						   thisParserPtr);
4891 				setTypeList($$, $2);
4892 				smiCheckTypeRanges(thisParserPtr, $$);
4893 			    }
4894 			}
4895 	;
4896 
4897 /*
4898  * In a SEQUENCE { ... } there are no sub-types, enumerations or
4899  * named bits. REF: draft, p.29
4900  */
4901 sequenceApplicationSyntax: IPADDRESS anySubType
4902 			{
4903 			    Import *importPtr;
4904 
4905 			    $$ = findTypeByName("IpAddress");
4906 			    if (! $$) {
4907 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4908 					      "IpAddress");
4909 			    }
4910 
4911 			    importPtr = findImportByName("IpAddress",
4912 							 thisModulePtr);
4913 			    if (importPtr) {
4914 				importPtr->use++;
4915 			    } else {
4916 				if (thisModulePtr->export.language ==
4917 				    SMI_LANGUAGE_SMIV2) {
4918 				    smiPrintError(thisParserPtr,
4919 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4920 						  "IpAddress");
4921 				} else if (thisModulePtr->export.language ==
4922 					   SMI_LANGUAGE_SPPI) {
4923 				    smiPrintError(thisParserPtr,
4924 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
4925 						  "IpAddress");
4926 				}
4927 			    }
4928 			}
4929 	|		COUNTER32 anySubType
4930 			{
4931 			    Import *importPtr;
4932 
4933                             if ((thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI) &&
4934                                 !findImportByName("Counter32", thisParserPtr->modulePtr))
4935                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "Counter32");
4936 			    $$ = findTypeByName("Counter32");
4937 			    if (! $$) {
4938 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4939 					      "Counter32");
4940 			    }
4941 
4942 			    importPtr = findImportByName("Counter32",
4943 							 thisModulePtr);
4944 			    if (importPtr) {
4945 				importPtr->use++;
4946 			    } else {
4947 				if (thisModulePtr->export.language ==
4948 				    SMI_LANGUAGE_SMIV2) {
4949 				    smiPrintError(thisParserPtr,
4950 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4951 						  "Counter32");
4952 				}
4953 			    }
4954 			}
4955 	|		GAUGE32	anySubType	/* (0..4294967295)	     */
4956 			{
4957 			    Import *importPtr;
4958 
4959                             if ((thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI) &&
4960                                 !findImportByName("Gauge32", thisParserPtr->modulePtr))
4961                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "Gauge32");
4962 			    $$ = findTypeByName("Gauge32");
4963 			    if (! $$) {
4964 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
4965 					      "Gauge32");
4966 			    }
4967 
4968 			    importPtr = findImportByName("Gauge32",
4969 							 thisModulePtr);
4970 			    if (importPtr) {
4971 				importPtr->use++;
4972 			    } else {
4973 				if (thisModulePtr->export.language ==
4974 				    SMI_LANGUAGE_SMIV2) {
4975 				    smiPrintError(thisParserPtr,
4976 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4977 						  "Gauge32");
4978 				}
4979 			    }
4980 			}
4981 	|		UNSIGNED32 anySubType /* (0..4294967295)	     */
4982 			{
4983 			    Import *importPtr;
4984 
4985 			    $$ = smiHandle->typeUnsigned32Ptr;
4986 
4987 			    importPtr = findImportByName("Unsigned32",
4988 							 thisModulePtr);
4989 			    if (importPtr) {
4990 				importPtr->use++;
4991 			    } else {
4992 				if (thisModulePtr->export.language ==
4993 				    SMI_LANGUAGE_SMIV2) {
4994 				    smiPrintError(thisParserPtr,
4995 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
4996 						  "Unsigned32");
4997 				} else if (thisModulePtr->export.language ==
4998 					   SMI_LANGUAGE_SPPI) {
4999 				    smiPrintError(thisParserPtr,
5000 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
5001 						  "Unsigned32");
5002 				}
5003 			    }
5004 			}
5005 	|		TIMETICKS anySubType	/* (0..4294967295)	     */
5006 			{
5007 			    Import *importPtr;
5008 
5009 			    $$ = findTypeByName("TimeTicks");
5010 			    if (! $$) {
5011 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
5012 					      "TimeTicks");
5013 			    }
5014 
5015 			    importPtr = findImportByName("TimeTicks",
5016 							 thisModulePtr);
5017 			    if (importPtr) {
5018 				importPtr->use++;
5019 			    } else {
5020 				if (thisModulePtr->export.language ==
5021 				    SMI_LANGUAGE_SMIV2) {
5022 				    smiPrintError(thisParserPtr,
5023 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
5024 						  "TimeTicks");
5025 				} else if (thisModulePtr->export.language ==
5026 					   SMI_LANGUAGE_SPPI) {
5027 				    smiPrintError(thisParserPtr,
5028 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
5029 						  "TimeTicks");
5030 				}
5031 			    }
5032 			}
5033 	|		OPAQUE			/* IMPLICIT OCTET STRING     */
5034 			{
5035 			    Import *importPtr;
5036 
5037 			    $$ = findTypeByName("Opaque");
5038 			    if (! $$) {
5039 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
5040 					      "Opaque");
5041 			    } else {
5042 				if (thisModulePtr->export.language ==
5043 				    SMI_LANGUAGE_SMIV2) {
5044 				    smiPrintError(thisParserPtr,
5045 						  ERR_SMIV2_OPAQUE_OBSOLETE,
5046 						  "Opaque");
5047 				} else if (thisModulePtr->export.language ==
5048 					   SMI_LANGUAGE_SPPI) {
5049 				    smiPrintError(thisParserPtr,
5050 						  ERR_SPPI_OPAQUE_OBSOLETE,
5051 						  "Opaque");
5052 				}
5053 			    }
5054 
5055 			    importPtr = findImportByName("Opaque",
5056 							 thisModulePtr);
5057 			    if (importPtr) {
5058 				importPtr->use++;
5059 			    } else {
5060 				if (thisModulePtr->export.language ==
5061 				    SMI_LANGUAGE_SMIV2) {
5062 				    smiPrintError(thisParserPtr,
5063 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
5064 						  "Opaque");
5065 				} else if (thisModulePtr->export.language ==
5066 					   SMI_LANGUAGE_SPPI) {
5067 				    smiPrintError(thisParserPtr,
5068 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
5069 						  "Opaque");
5070 				}
5071 			    }
5072 			}
5073 	|		COUNTER64 anySubType    /* (0..18446744073709551615) */
5074 			{
5075 			    Import *importPtr;
5076 
5077                             if ((thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI) &&
5078                                 !findImportByName("Counter64", thisModulePtr))
5079                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "Counter64");
5080 			    $$ = findTypeByName("Counter64");
5081 			    if (! $$) {
5082 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
5083 					      "Counter64");
5084 			    }
5085 
5086 			    importPtr = findImportByName("Counter64",
5087 							 thisModulePtr);
5088 			    if (importPtr) {
5089 				importPtr->use++;
5090 			    } else {
5091 				if (thisModulePtr->export.language ==
5092 				    SMI_LANGUAGE_SMIV2) {
5093 				    smiPrintError(thisParserPtr,
5094 						  ERR_SMIV2_BASETYPE_NOT_IMPORTED,
5095 						  "Counter64");
5096 				}
5097 			    }
5098 			}
5099 	|		INTEGER64	        /* (-9223372036854775807..9223372036854775807) */
5100 			{
5101 			    Import *importPtr;
5102 
5103                             if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)
5104                                 smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "Integer64");
5105 			    $$ = findTypeByName("Integer64");
5106 			    if (! $$) {
5107 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
5108 					      "Integer64");
5109 			    }
5110 
5111 			    importPtr = findImportByName("Integer64",
5112 							 thisModulePtr);
5113 			    if (importPtr) {
5114 				importPtr->use++;
5115 			    } else {
5116 				if (thisModulePtr->export.language ==
5117 					   SMI_LANGUAGE_SPPI) {
5118 				    smiPrintError(thisParserPtr,
5119 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
5120 						  "Integer64");
5121 				}
5122 			    }
5123 			}
5124 	|		UNSIGNED64	        /* (0..18446744073709551615) */
5125 			{
5126 			    Import *importPtr;
5127 
5128 			    importPtr = findImportByName("Unsigned64",
5129 							 thisModulePtr);
5130                             if ((thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI) && (!importPtr))
5131                                 smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "Unsigned64");
5132 			    $$ = findTypeByName("Unsigned64");
5133 			    if (! $$) {
5134 				smiPrintError(thisParserPtr, ERR_UNKNOWN_TYPE,
5135 					      "Unsigned64");
5136 			    }
5137 
5138 			    if (importPtr) {
5139 				importPtr->use++;
5140 			    } else {
5141 				if (thisModulePtr->export.language ==
5142 					   SMI_LANGUAGE_SPPI) {
5143 				    smiPrintError(thisParserPtr,
5144 						  ERR_SPPI_BASETYPE_NOT_IMPORTED,
5145 						  "Unsigned64");
5146 				}
5147 			    }
5148 			}
5149 	;
5150 
5151 anySubType:		integerSubType
5152 			{
5153 			    List *listPtr, *nextListPtr;
5154 
5155 			    if (thisModulePtr->export.language == SMI_LANGUAGE_SMIV2)
5156 				smiPrintError(thisParserPtr,
5157 					      ERR_UNEXPECTED_TYPE_RESTRICTION);
5158 
5159 			    for (listPtr = $1; listPtr;
5160 				 listPtr = nextListPtr) {
5161 				nextListPtr = listPtr->nextPtr;
5162 				smiFree((Range *)(listPtr->ptr));
5163 				smiFree(listPtr);
5164 			    }
5165 
5166 			    $$ = NULL;
5167 			}
5168 	|	        octetStringSubType
5169 			{
5170 			    List *listPtr, *nextListPtr;
5171 
5172 			    if (thisModulePtr->export.language == SMI_LANGUAGE_SMIV2)
5173 				smiPrintError(thisParserPtr,
5174 					      ERR_UNEXPECTED_TYPE_RESTRICTION);
5175 
5176 			    for (listPtr = $1; listPtr;
5177 				 listPtr = nextListPtr) {
5178 				nextListPtr = listPtr->nextPtr;
5179 				smiFree((Range *)(listPtr->ptr));
5180 				smiFree(listPtr);
5181 			    }
5182 
5183 			    $$ = NULL;
5184 			}
5185 	|		enumSpec
5186 			{
5187 			    List *listPtr, *nextListPtr;
5188 
5189 			    if (thisModulePtr->export.language == SMI_LANGUAGE_SMIV2)
5190 				smiPrintError(thisParserPtr,
5191 					      ERR_UNEXPECTED_TYPE_RESTRICTION);
5192 
5193 			    for (listPtr = $1; listPtr;
5194 				 listPtr = nextListPtr) {
5195 				nextListPtr = listPtr->nextPtr;
5196 				smiFree(((NamedNumber *)(listPtr->ptr))->export.name);
5197 				smiFree((NamedNumber *)(listPtr->ptr));
5198 				smiFree(listPtr);
5199 			    }
5200 
5201 			    $$ = NULL;
5202 			}
5203 	|		/* empty */
5204 			{
5205 			    $$ = NULL;
5206 			}
5207         ;
5208 
5209 
5210 /* REF: draft,p.46 */
5211 integerSubType:		'(' ranges ')'		/* at least one range        */
5212 			/*
5213 			 * the specification mentions an alternative of an
5214 			 * empty RHS here. this would lead to reduce/reduce
5215 			 * conflicts. instead, we differentiate the parent
5216 			 * rule(s) (SimpleSyntax).
5217 			 */
5218 			{ $$ = $2; }
5219 	;
5220 
5221 octetStringSubType:	'(' SIZE '(' ranges ')' ')'
5222 			/*
5223 			 * the specification mentions an alternative of an
5224 			 * empty RHS here. this would lead to reduce/reduce
5225 			 * conflicts. instead, we differentiate the parent
5226 			 * rule(s) (SimpleSyntax).
5227 			 */
5228 			{
5229 			    $$ = $4;
5230 			}
5231 	;
5232 
5233 ranges:			range
5234 			{
5235 			    $$ = smiMalloc(sizeof(List));
5236 			    $$->ptr = $1;
5237 			    $$->nextPtr = NULL;
5238 			}
5239 	|		ranges '|' range
5240 			{
5241 			    List *p, *pp;
5242 
5243 			    p = smiMalloc(sizeof(List));
5244 			    p->ptr = (void *)$3;
5245 			    p->nextPtr = NULL;
5246 			    for (pp = $1; pp->nextPtr; pp = pp->nextPtr);
5247 			    pp->nextPtr = p;
5248 
5249 			    $$ = $1;
5250 			}
5251 	;
5252 
5253 range:			value
5254 			{
5255 			    $$ = smiMalloc(sizeof(Range));
5256 			    $$->export.minValue = *$1;
5257 			    $$->export.maxValue = *$1;
5258 			    smiFree($1);
5259 			}
5260 	|		value DOT_DOT value
5261 			{
5262 			    $$ = smiMalloc(sizeof(Range));
5263 			    $$->export.minValue = *$1;
5264 			    $$->export.maxValue = *$3;
5265 			    smiFree($1);
5266 			    smiFree($3);
5267 			}
5268 	;
5269 
5270 value:			NEGATIVENUMBER
5271 			{
5272 			    $$ = smiMalloc(sizeof(SmiValue));
5273 			    $$->basetype = SMI_BASETYPE_INTEGER32;
5274 			    $$->value.integer32 = $1;
5275 			}
5276 	|		NUMBER
5277 			{
5278 			    $$ = smiMalloc(sizeof(SmiValue));
5279 			    $$->basetype = SMI_BASETYPE_UNSIGNED32;
5280 			    $$->value.unsigned32 = $1;
5281 			}
5282 	|		NEGATIVENUMBER64
5283 			{
5284 			    $$ = smiMalloc(sizeof(SmiValue));
5285 			    $$->basetype = SMI_BASETYPE_INTEGER64;
5286 			    $$->value.integer64 = $1;
5287 			}
5288 	|		NUMBER64
5289 			{
5290 			    $$ = smiMalloc(sizeof(SmiValue));
5291 			    $$->basetype = SMI_BASETYPE_UNSIGNED64;
5292 			    $$->value.unsigned64 = $1;
5293 			}
5294 	|		HEX_STRING
5295 			{
5296 			    char s[3];
5297 			    int i, len;
5298 
5299 			    $$ = smiMalloc(sizeof(SmiValue));
5300 			    if (defaultBasetype == SMI_BASETYPE_OCTETSTRING) {
5301 				$$->basetype = SMI_BASETYPE_OCTETSTRING;
5302 				len = strlen($1);
5303 				$$->value.ptr = smiMalloc((len+1)/2+1);
5304 				for (i = 0; i < len; i += 2) {
5305 				    strncpy(s, &$1[i], 2);
5306 				    if (!s[1]) s[1] = '0';
5307 				    s[2] = 0;
5308 				    $$->value.ptr[i/2] =
5309 					(unsigned char)strtol(s, 0, 16);
5310 				}
5311 				$$->len = (len+1)/2;
5312 			    } else {
5313 				$$->basetype = SMI_BASETYPE_UNSIGNED32;
5314 				$$->value.unsigned32 = strtoul($1, NULL, 16);
5315 			    }
5316 			}
5317 	|		BIN_STRING
5318 			{
5319 			    char s[9];
5320 			    int i, len, j;
5321 
5322 			    $$ = smiMalloc(sizeof(SmiValue));
5323 			    if (defaultBasetype == SMI_BASETYPE_OCTETSTRING) {
5324 				$$->basetype = SMI_BASETYPE_OCTETSTRING;
5325 				len = strlen($1);
5326 				$$->value.ptr = smiMalloc((len+7)/8+1);
5327 				for (i = 0; i < len; i += 8) {
5328 				    strncpy(s, &$1[i], 8);
5329 				    for (j = 1; j < 8; j++) {
5330 					if (!s[j]) s[j] = '0';
5331 				    }
5332 				    s[8] = 0;
5333 				    $$->value.ptr[i/8] =
5334 					(unsigned char)strtol(s, 0, 2);
5335 				}
5336 				$$->len = (len+7)/8;
5337 			    } else {
5338 				$$->basetype = SMI_BASETYPE_UNSIGNED32;
5339 				$$->value.unsigned32 = strtoul($1, NULL, 2);
5340 			    }
5341 			}
5342 	;
5343 
5344 enumSpec:		'{' enumItems '}'
5345 			{
5346 			    $$ = $2;
5347 			}
5348 	;
5349 
5350 enumItems:		enumItem
5351 			{
5352 			    $$ = smiMalloc(sizeof(List));
5353 			    $$->ptr = $1;
5354 			    $$->nextPtr = NULL;
5355 			}
5356 	|		enumItems ',' enumItem
5357 			{
5358 			    List *p, *pp;
5359 
5360 			    p = smiMalloc(sizeof(List));
5361 			    p->ptr = (void *)$3;
5362 			    p->nextPtr = NULL;
5363 			    for (pp = $1; pp->nextPtr; pp = pp->nextPtr);
5364 			    pp->nextPtr = p;
5365 			    $$ = $1;
5366 			}
5367 	;
5368 
5369 enumItem:		LOWERCASE_IDENTIFIER
5370 			{
5371 			    checkNameLen(thisParserPtr, $1,
5372 					 ERR_ENUMNAME_32, ERR_ENUMNAME_64);
5373 			    if (thisModulePtr->export.language == SMI_LANGUAGE_SMIV2)
5374 			    {
5375 				if (strchr($1, '-')) {
5376 				    smiPrintError(thisParserPtr,
5377 					  ERR_NAMEDNUMBER_INCLUDES_HYPHEN,
5378 						  $1);
5379 				}
5380 			    }
5381 			}
5382 			'(' enumNumber ')'
5383 			{
5384 			    $$ = smiMalloc(sizeof(NamedNumber));
5385 			    $$->export.name = $1;
5386 			    $$->export.value = *$4;
5387 			    smiFree($4);
5388 			}
5389 	;
5390 
5391 enumNumber:		NUMBER
5392 			{
5393 			    if ($1 > SMI_BASETYPE_INTEGER32_MAX) {
5394 				smiPrintError(thisParserPtr,
5395 					      ERR_INTEGER32_TOO_LARGE, $1);
5396 			    }
5397 			    if ((thisModulePtr->export.language == SMI_LANGUAGE_SMIV1) &&
5398 				($1 == 0)) {
5399 				smiPrintError(thisParserPtr,
5400 					      ERR_ENUM_ZERO);
5401 			    }
5402 			    $$ = smiMalloc(sizeof(SmiValue));
5403 			    $$->basetype = SMI_BASETYPE_INTEGER32;
5404 			    $$->value.integer32 = $1;
5405 			}
5406 	|		NEGATIVENUMBER
5407 			{
5408 			    $$ = smiMalloc(sizeof(SmiValue));
5409 			    $$->basetype = SMI_BASETYPE_INTEGER32;
5410 			    $$->value.integer32 = $1;
5411 			    /* TODO: non-negative is suggested */
5412 			}
5413 	;
5414 
5415 Status:			LOWERCASE_IDENTIFIER
5416 			{
5417 			    if (thisModulePtr->export.language == SMI_LANGUAGE_SMIV2)
5418 			    {
5419 			        if (!strcmp($1, "current")) {
5420 				    $$ = SMI_STATUS_CURRENT;
5421 			        } else if (!strcmp($1, "deprecated")) {
5422 				    $$ = SMI_STATUS_DEPRECATED;
5423 			        } else if (!strcmp($1, "obsolete")) {
5424 				    $$ = SMI_STATUS_OBSOLETE;
5425 			        } else {
5426 				    smiPrintError(thisParserPtr,
5427 					          ERR_INVALID_SMIV2_STATUS,
5428 					          $1);
5429 				    if (!strcmp($1, "mandatory")
5430 				        || !strcmp($1, "optional")) {
5431 				        /* best guess */
5432 				        $$ = SMI_STATUS_CURRENT;
5433 				    } else {
5434 				        $$ = SMI_STATUS_UNKNOWN;
5435 				    }
5436 			        }
5437 			    } else if (thisModulePtr->export.language != SMI_LANGUAGE_SPPI) {
5438 			        if (!strcmp($1, "mandatory")) {
5439 				    $$ = SMI_STATUS_MANDATORY;
5440 			        } else if (!strcmp($1, "optional")) {
5441 				    $$ = SMI_STATUS_OPTIONAL;
5442 			        } else if (!strcmp($1, "obsolete")) {
5443 				    $$ = SMI_STATUS_OBSOLETE;
5444 			        } else if (!strcmp($1, "deprecated")) {
5445 				    $$ = SMI_STATUS_OBSOLETE;
5446 			        } else {
5447 				    smiPrintError(thisParserPtr,
5448 					          ERR_INVALID_SMIV1_STATUS,
5449 					          $1);
5450 				    if (!strcmp($1, "current")) {
5451 				        /* best guess */
5452 				        $$ = SMI_STATUS_MANDATORY;
5453 				    } else {
5454 				        $$ = SMI_STATUS_UNKNOWN;
5455 				    }
5456 			        }
5457 			    } else { /* it is SPPI */
5458 			        if (!strcmp($1, "current")) {
5459 				    $$ = SMI_STATUS_CURRENT;
5460 			        } else if (!strcmp($1, "obsolete")) {
5461 				    $$ = SMI_STATUS_OBSOLETE;
5462 			        } else if (!strcmp($1, "deprecated")) {
5463 				    $$ = SMI_STATUS_OBSOLETE;
5464                                 } else {
5465                                     smiPrintError(thisParserPtr,
5466                                                   ERR_INVALID_SPPI_STATUS, $1);
5467                                     $$ = SMI_STATUS_UNKNOWN;
5468                                 }
5469                             }
5470 			    smiFree($1);
5471 			}
5472         ;
5473 
5474 Status_Capabilities:	LOWERCASE_IDENTIFIER
5475 			{
5476 			    if (!strcmp($1, "current")) {
5477 				$$ = SMI_STATUS_CURRENT;
5478 			    } else if (!strcmp($1, "obsolete")) {
5479 				$$ = SMI_STATUS_OBSOLETE;
5480 			    } else {
5481 				smiPrintError(thisParserPtr,
5482 					      ERR_INVALID_CAPABILITIES_STATUS,
5483 					      $1);
5484 				$$ = SMI_STATUS_UNKNOWN;
5485 			    }
5486 			    smiFree($1);
5487 			}
5488         ;
5489 
5490 DisplayPart:		DISPLAY_HINT Text
5491 			{
5492 			    $$ = $2;
5493 
5494 			    if ($2 && !strlen($2)) {
5495 				smiPrintError(thisParserPtr,
5496 					      ERR_EMPTY_FORMAT);
5497 			    }
5498 			}
5499         |		/* empty */
5500 			{
5501 			    $$ = NULL;
5502 			}
5503         ;
5504 
5505 UnitsPart:		UNITS Text
5506 			{
5507 			    $$ = $2;
5508 
5509 			    if ($2 && !strlen($2)) {
5510 				smiPrintError(thisParserPtr,
5511 					      ERR_EMPTY_UNITS);
5512 			    }
5513 			}
5514         |		/* empty */
5515 			{
5516 			    $$ = NULL;
5517 			}
5518         ;
5519 
5520 Access:			LOWERCASE_IDENTIFIER
5521 			{
5522 			    if (thisModulePtr->export.language == SMI_LANGUAGE_SMIV2)
5523 			    {
5524 				if (!strcmp($1, "not-accessible")) {
5525 				    $$ = SMI_ACCESS_NOT_ACCESSIBLE;
5526 				} else if (!strcmp($1,
5527 						   "accessible-for-notify")) {
5528 				    $$ = SMI_ACCESS_NOTIFY;
5529 				} else if (!strcmp($1, "read-only")) {
5530 				    $$ = SMI_ACCESS_READ_ONLY;
5531 				} else if (!strcmp($1, "read-write")) {
5532 				    $$ = SMI_ACCESS_READ_WRITE;
5533 				} else if (!strcmp($1, "read-create")) {
5534 				    $$ = SMI_ACCESS_READ_WRITE;
5535 				    thisParserPtr->flags |= FLAG_CREATABLE;
5536 				    /* TODO:remember it's really read-create */
5537 				} else if (!strcmp($1, "write-only")) {
5538 				    smiPrintError(thisParserPtr,
5539 						  ERR_SMIV2_WRITE_ONLY);
5540 				    $$ = SMI_ACCESS_READ_WRITE;
5541 				} else {
5542 				    smiPrintError(thisParserPtr,
5543 						  ERR_INVALID_SMIV2_ACCESS,
5544 						  $1);
5545 				    $$ = SMI_ACCESS_UNKNOWN;
5546 				}
5547 			    } else if (thisModulePtr->export.language != SMI_LANGUAGE_SPPI) {
5548 				if (!strcmp($1, "not-accessible")) {
5549 				    $$ = SMI_ACCESS_NOT_ACCESSIBLE;
5550 				} else if (!strcmp($1, "read-only")) {
5551 				    $$ = SMI_ACCESS_READ_ONLY;
5552 				} else if (!strcmp($1, "read-write")) {
5553 				    $$ = SMI_ACCESS_READ_WRITE;
5554 				} else if (!strcmp($1, "write-only")) {
5555 				    smiPrintError(thisParserPtr,
5556 						  ERR_SMIV1_WRITE_ONLY);
5557 				    $$ = SMI_ACCESS_READ_WRITE;
5558 				} else {
5559 				    smiPrintError(thisParserPtr,
5560 						  ERR_INVALID_SMIV1_ACCESS,
5561 						  $1);
5562 				    $$ = SMI_ACCESS_UNKNOWN;
5563 				}
5564 			    } else {
5565 			        if (!strcmp($1, "install")) {
5566 				    $$ = SMI_ACCESS_INSTALL;
5567 			        } else if (!strcmp($1, "install-notify")) {
5568 				    $$ = SMI_ACCESS_INSTALL_NOTIFY;
5569 			        } else if (!strcmp($1, "notify")) {
5570 				    $$ = SMI_ACCESS_NOTIFY;
5571 			        } else if (!strcmp($1, "report-only")) {
5572 				    $$ = SMI_ACCESS_REPORT_ONLY;
5573 			        } else if (!strcmp($1, "not-accessible")) {
5574 				    $$ = SMI_ACCESS_NOT_ACCESSIBLE;
5575                                 } else {
5576 				    smiPrintError(thisParserPtr,
5577 					          ERR_INVALID_SPPI_ACCESS,
5578 					          $1);
5579 				    $$ = SMI_ACCESS_UNKNOWN;
5580 			        }
5581                             }
5582 			    smiFree($1);
5583 			}
5584         ;
5585 
5586 IndexPart:              PIB_INDEX
5587                         {
5588                             if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)
5589                                 smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "PIB-INDEX");
5590                         }
5591                         '{' Entry '}'
5592                         {
5593                             List *p = smiMalloc(sizeof(List));
5594 
5595                             p->ptr       = $4;
5596                             p->nextPtr   = NULL;
5597 
5598 			    $$.indexkind = SMI_INDEX_INDEX;
5599 			    $$.implied   = impliedFlag;
5600 			    $$.listPtr   = p;
5601 			    $$.rowPtr    = NULL;
5602                             indexFlag    = INDEXFLAG_PIBINDEX;
5603 			}
5604         |		AUGMENTS '{' Entry '}'
5605 			/* TODO: no AUGMENTS clause in v1 */
5606 			/* TODO: how to differ INDEX and AUGMENTS ? */
5607 			{
5608 			    $$.indexkind    = SMI_INDEX_AUGMENT;
5609 			    $$.implied      = 0;
5610 			    $$.listPtr      = NULL;
5611 			    $$.rowPtr       = $3;
5612                             indexFlag       = INDEXFLAG_AUGMENTS;
5613 			}
5614         |		EXTENDS
5615                         {
5616                             if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)
5617                                 smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "EXTENDS");
5618                         }
5619                         '{' Entry '}'
5620 			{
5621 			    $$.indexkind    = SMI_INDEX_SPARSE;
5622 			    $$.implied      = 0;
5623 			    $$.listPtr      = NULL;
5624 			    $$.rowPtr       = $4;
5625                             indexFlag       = INDEXFLAG_EXTENDS;
5626 			}
5627         |		/* empty */
5628 			{
5629 			    $$.indexkind = SMI_INDEX_UNKNOWN;
5630 			}
5631 	;
5632 
5633 MibIndex:		INDEX
5634                         {
5635                             /*
5636                              * To avoid ambiguity caused by merging
5637                              * the SMI and SPPI parser we use a flag.
5638                              */
5639                             if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI) {
5640                                 /*
5641                                  * Only INDEX or AUGMENTS are allowed for SMI
5642                                  */
5643                                 if (indexFlag != INDEXFLAG_NONE)
5644                                     smiPrintError(thisParserPtr, ERR_INDEX_AND_AUGMENTS_USED);
5645                             } else {
5646                                 /*
5647                                  * INDEX may only be used if PIB_INDEX was used
5648                                  */
5649                                 if (indexFlag != INDEXFLAG_PIBINDEX)
5650                                     smiPrintError(thisParserPtr, ERR_INDEX_WITHOUT_PIB_INDEX);
5651                             }
5652 
5653 			    /*
5654 			     * Use a global variable to fetch and remember
5655 			     * whether we have seen an IMPLIED keyword.
5656 			     */
5657 			    impliedFlag = 0;
5658 			}
5659 			'{' IndexTypes '}'
5660 			{
5661 			    $$.indexkind = SMI_INDEX_INDEX;
5662 			    $$.implied   = impliedFlag;
5663 			    $$.listPtr   = $4;
5664 			    $$.rowPtr    = NULL;
5665                         }
5666         |               /* empty */
5667 			{
5668 			    $$.indexkind = SMI_INDEX_UNKNOWN;
5669 			}
5670         ;
5671 
5672 IndexTypes:		IndexType
5673 			{
5674 			    $$ = smiMalloc(sizeof(List));
5675 			    $$->ptr = $1;
5676 			    $$->nextPtr = NULL;
5677 			}
5678         |		IndexTypes ',' IndexType
5679 			/* TODO: might this list be emtpy? */
5680 			{
5681 			    List *p, *pp;
5682 
5683 			    p = smiMalloc(sizeof(List));
5684 			    p->ptr = $3;
5685 			    p->nextPtr = NULL;
5686 			    for (pp = $1; pp->nextPtr; pp = pp->nextPtr);
5687 			    pp->nextPtr = p;
5688 			    $$ = $1;
5689 			}
5690 	;
5691 
5692 IndexType:		IMPLIED Index
5693 			{
5694 			    impliedFlag = 1;
5695 			    $$ = $2;
5696 			}
5697 	|		Index
5698 			{
5699 			    $$ = $1;
5700 			}
5701 	;
5702 
5703 Index:			ObjectName
5704 			/*
5705 			 * TODO: use the SYNTAX value of the correspondent
5706 			 *       OBJECT-TYPE invocation
5707 			 */
5708 			{
5709 			    $$ = $1;
5710 			}
5711         ;
5712 
5713 Entry:			ObjectName
5714 			{
5715 			    $$ = $1;
5716 			}
5717         ;
5718 
5719 DefValPart:		DEFVAL '{' Value '}'
5720 			{
5721 			    $$ = $3;
5722 			    if ((defaultBasetype == SMI_BASETYPE_BITS) &&
5723 				($$->basetype != SMI_BASETYPE_BITS)) {
5724 				smiPrintError(thisParserPtr,
5725 					      ERR_DEFVAL_SYNTAX);
5726 				if ($$->basetype == SMI_BASETYPE_OCTETSTRING) {
5727 				    smiFree($$->value.ptr);
5728 				}
5729 				smiFree($$);
5730 				$$ = NULL;
5731 			    }
5732 			}
5733 	|		/* empty */
5734 			{ $$ = NULL; }
5735 			/* TODO: different for DefValPart in AgentCaps ? */
5736 	;
5737 
5738 Value:			valueofObjectSyntax
5739 			{ $$ = $1; }
5740 	|		'{' BitsValue '}'
5741 			{
5742 			    $$ = smiMalloc(sizeof(SmiValue));
5743 			    $$->basetype = SMI_BASETYPE_BITS;
5744 			    $$->value.ptr = (void *)$2;
5745 			}
5746 	;
5747 
5748 BitsValue:		BitNames
5749 			{ $$ = $1; }
5750 	|		/* empty */
5751 			{ $$ = NULL; }
5752 	;
5753 
5754 BitNames:		LOWERCASE_IDENTIFIER
5755 			{
5756 			    $$ = smiMalloc(sizeof(List));
5757 			    $$->ptr = $1;
5758 			    $$->nextPtr = NULL;
5759 			}
5760 	|		BitNames ',' LOWERCASE_IDENTIFIER
5761 			{
5762 			    List *p, *pp;
5763 
5764 			    p = smiMalloc(sizeof(List));
5765 			    p->ptr = $3;
5766 			    p->nextPtr = NULL;
5767 			    for (pp = $1; pp->nextPtr; pp = pp->nextPtr);
5768 			    pp->nextPtr = p;
5769 			    $$ = $1;
5770 			}
5771 	;
5772 
5773 ObjectName:		objectIdentifier
5774 			{
5775 			    $$ = $1;
5776 			}
5777 	;
5778 
5779 NotificationName:	objectIdentifier
5780 			{
5781 			    $$ = $1;
5782 			}
5783 	;
5784 
5785 ReferPart:		REFERENCE Text
5786 			{
5787 			    $$ = $2;
5788 
5789 			    if ($2 && !strlen($2)) {
5790 				smiPrintError(thisParserPtr,
5791 					      ERR_EMPTY_REFERENCE);
5792 			    }
5793 			}
5794 	|		/* empty */
5795 			{ $$ = NULL; }
5796 	;
5797 
5798 RevisionPart:		Revisions
5799 			{ $$ = 0; }
5800 	|		/* empty */
5801 			{ $$ = 0; }
5802 	;
5803 
5804 Revisions:		Revision
5805 			{ $$ = 0; }
5806 	|		Revisions Revision
5807 			{ $$ = 0; }
5808 	;
5809 
5810 Revision:		REVISION ExtUTCTime
5811 			{
5812 			    thisParserPtr->firstRevisionLine = thisParserPtr->line;
5813 
5814 			    if (thisParserPtr->modulePtr->lastRevisionPtr &&
5815 				($2 >= thisParserPtr->modulePtr->lastRevisionPtr->export.date)) {
5816 				smiPrintError(thisParserPtr,
5817 					      ERR_REVISION_NOT_DESCENDING);
5818 			    }
5819 
5820 			    if ($2 > thisParserPtr->modulePtr->lastUpdated) {
5821 				smiPrintError(thisParserPtr,
5822 					      ERR_REVISION_AFTER_LAST_UPDATE);
5823 			    }
5824 			}
5825 			DESCRIPTION Text
5826 			{
5827 			    Revision *revisionPtr;
5828 
5829 			    checkDescr(thisParserPtr, $5);
5830 
5831 			    revisionPtr = addRevision($2, $5, thisParserPtr);
5832 			    if (revisionPtr) {
5833 				setRevisionLine(revisionPtr,
5834 						thisParserPtr->firstRevisionLine,
5835 						thisParserPtr);
5836 			    }
5837 			    $$ = revisionPtr ? 0 : -1;
5838 			}
5839 	;
5840 
5841 NotificationObjectsPart: OBJECTS '{' Objects '}'
5842 			{
5843 			    $$ = $3;
5844 			}
5845 	|		/* empty */
5846 			{
5847 			    $$ = NULL;
5848 			}
5849 	;
5850 
5851 ObjectGroupObjectsPart:	OBJECTS '{' Objects '}'
5852 			{
5853 			    $$ = $3;
5854 			}
5855 	;
5856 
5857 Objects:		Object
5858 			{
5859 			    $$ = smiMalloc(sizeof(List));
5860 			    $$->ptr = $1;
5861 			    $$->nextPtr = NULL;
5862 			}
5863 	|		Objects ',' Object
5864 			{
5865 			    List *p, *pp;
5866 
5867 			    p = smiMalloc(sizeof(List));
5868 			    p->ptr = $3;
5869 			    p->nextPtr = NULL;
5870 			    for (pp = $1; pp->nextPtr; pp = pp->nextPtr);
5871 			    pp->nextPtr = p;
5872 			    $$ = $1;
5873 			}
5874 	;
5875 
5876 Object:			ObjectName
5877 			{
5878 			    $$ = $1;
5879 			    if ((thisParserPtr->currentDecl == SMI_DECL_OBJECTGROUP) &&
5880 				$$->modulePtr != thisParserPtr->modulePtr) {
5881                                 smiPrintError(thisParserPtr,
5882 					      ERR_COMPLIANCE_MEMBER_NOT_LOCAL,
5883 					      $$->export.name);
5884 			    }
5885 			}
5886 	;
5887 
5888 NotificationsPart:	NOTIFICATIONS '{' Notifications '}'
5889 			{
5890 			    $$ = $3;
5891 			}
5892 	;
5893 
5894 Notifications:		Notification
5895 			{
5896 			    $$ = smiMalloc(sizeof(List));
5897 			    $$->ptr = $1;
5898 			    $$->nextPtr = NULL;
5899 			}
5900 	|		Notifications ',' Notification
5901 			{
5902 			    List *p, *pp;
5903 
5904 			    p = smiMalloc(sizeof(List));
5905 			    p->ptr = $3;
5906 			    p->nextPtr = NULL;
5907 			    for (pp = $1; pp->nextPtr; pp = pp->nextPtr);
5908 			    pp->nextPtr = p;
5909 			    $$ = $1;
5910 			}
5911 	;
5912 
5913 Notification:		NotificationName
5914 			{
5915 			    $$ = $1;
5916 			    if ($$->modulePtr != thisParserPtr->modulePtr) {
5917                                 smiPrintError(thisParserPtr,
5918 					      ERR_COMPLIANCE_MEMBER_NOT_LOCAL,
5919 					      $$->export.name);
5920 			    }
5921 			}
5922 	;
5923 
5924 Text:			QUOTED_STRING
5925 			{
5926 			    int len;
5927 			    $$ = smiStrdup($1);
5928 			    len = strlen($$);
5929 			    while (len > 0 && $$[len-1] == '\n') {
5930 				$$[--len] = 0;
5931 			    }
5932 			}
5933 	;
5934 
5935 ExtUTCTime:		QUOTED_STRING
5936 			{
5937 			    $$ = checkDate(thisParserPtr, $1);
5938 			}
5939 	;
5940 
5941 objectIdentifier:	{
5942 			    thisParserPtr->parentNodePtr = smiHandle->rootNodePtr;
5943 			}
5944 			subidentifiers
5945 			{
5946 			    $$ = $2;
5947 			    if ($$) {
5948 				thisParserPtr->parentNodePtr = $2->nodePtr;
5949 			    } else {
5950 				thisParserPtr->parentNodePtr = NULL;
5951 			    }
5952 			}
5953 	;
5954 
5955 subidentifiers:
5956 			subidentifier
5957 			{
5958 			    $$ = $1;
5959 			}
5960 	|		subidentifiers
5961 			subidentifier
5962 			{
5963 			    $$ = $2;
5964 			}
5965         ;
5966 
5967 subidentifier:
5968 			/* LOWERCASE_IDENTIFIER */
5969 			fuzzy_lowercase_identifier
5970 			{
5971 			    Object *objectPtr;
5972 			    Import *importPtr;
5973 
5974 			    if (thisParserPtr->parentNodePtr != smiHandle->rootNodePtr) {
5975 				smiPrintError(thisParserPtr,
5976 					      ERR_OIDLABEL_NOT_FIRST, $1);
5977 			    }
5978 			    objectPtr = findObjectByModuleAndName(
5979 				thisParserPtr->modulePtr, $1);
5980 			    if (objectPtr) {
5981 				$$ = objectPtr;
5982 				smiFree($1);
5983 			    } else {
5984 				importPtr = findImportByName($1,
5985 							     thisModulePtr);
5986 				if (!importPtr ||
5987 				    (importPtr->kind == KIND_NOTFOUND)) {
5988 				    /*
5989 				     * If we are in a MODULE-COMPLIANCE
5990 				     * statement with a given MODULE...
5991 				     */
5992 				    if (thisParserPtr->complianceModulePtr) {
5993 					objectPtr =
5994 					    findObjectByModuleAndName(
5995 						thisParserPtr->complianceModulePtr, $1);
5996 					if (objectPtr) {
5997 					    importPtr = addImport(
5998 						$1,
5999 						thisParserPtr);
6000 					    setImportModulename(importPtr,
6001 								thisParserPtr->complianceModulePtr->export.name);
6002 					    addImportFlags(importPtr,
6003 							   FLAG_INCOMPLIANCE);
6004 					    importPtr->use++;
6005 					} else {
6006 					    objectPtr = addObject($1,
6007 								  thisParserPtr->pendingNodePtr, 0,
6008 								  FLAG_INCOMPLETE,
6009 								  thisParserPtr);
6010 					    smiPrintError(thisParserPtr,
6011 							  ERR_IDENTIFIER_NOT_IN_MODULE, $1,
6012 							  thisParserPtr->complianceModulePtr->export.name);
6013 					}
6014 				    } else if (thisParserPtr->capabilitiesModulePtr) {
6015 					objectPtr =
6016 					    findObjectByModuleAndName(
6017 						thisParserPtr->capabilitiesModulePtr, $1);
6018 					if (objectPtr) {
6019 					    importPtr = addImport(
6020 						$1,
6021 						thisParserPtr);
6022 					    setImportModulename(importPtr,
6023 								thisParserPtr->capabilitiesModulePtr->
6024 								export.name);
6025 					    addImportFlags(importPtr,
6026 							   FLAG_INCOMPLIANCE);
6027 					    importPtr->use++;
6028 					} else {
6029 					    objectPtr = addObject($1,
6030 								  thisParserPtr->pendingNodePtr, 0,
6031 								  FLAG_INCOMPLETE,
6032 								  thisParserPtr);
6033 					    smiPrintError(thisParserPtr,
6034 							  ERR_IDENTIFIER_NOT_IN_MODULE, $1,
6035 							  thisParserPtr->capabilitiesModulePtr->export.name);
6036 					}
6037 				    } else {
6038 					/*
6039 					 * forward referenced node.
6040 					 * create it,
6041 					 * marked with FLAG_INCOMPLETE.
6042 					 */
6043 					objectPtr = addObject($1,
6044 							      thisParserPtr->pendingNodePtr,
6045 							      0,
6046 							      FLAG_INCOMPLETE,
6047 							      thisParserPtr);
6048 				    }
6049 				    $$ = objectPtr;
6050 				} else {
6051 				    /*
6052 				     * imported object.
6053 				     */
6054 				    importPtr->use++;
6055 				    $$ = findObjectByModulenameAndName(
6056 					importPtr->export.module, $1);
6057 				    smiFree($1);
6058 				}
6059 			    }
6060 			    if ($$)
6061 				thisParserPtr->parentNodePtr = $$->nodePtr;
6062 			}
6063 	|		moduleName '.' LOWERCASE_IDENTIFIER
6064 			{
6065 			    Object *objectPtr;
6066 			    Import *importPtr;
6067 			    char *md;
6068 
6069 			    if (thisParserPtr->parentNodePtr != smiHandle->rootNodePtr) {
6070 				md = smiMalloc(sizeof(char) *
6071 					       (strlen($1) + strlen($3) + 2));
6072 				sprintf(md, "%s.%s", $1, $3);
6073 				smiPrintError(thisParserPtr,
6074 					      ERR_OIDLABEL_NOT_FIRST, md);
6075 				smiFree(md);
6076 			    } else {
6077 				objectPtr = findObjectByModulenameAndName(
6078 				    $1, $3);
6079 				if (objectPtr) {
6080 				    $$ = objectPtr;
6081 				    smiFree($1);
6082 				    smiFree($3);
6083 				} else {
6084 				    importPtr = findImportByModulenameAndName(
6085 					$1, $3, thisModulePtr);
6086 				    if (!importPtr ||
6087 					(importPtr->kind == KIND_NOTFOUND)) {
6088 					/* TODO: check: $1 == thisModule ? */
6089 					/*
6090 					 * If we are in a MODULE-COMPLIANCE
6091 					 * statement with a given MODULE...
6092 					 */
6093 					if (thisParserPtr->complianceModulePtr) {
6094 					    objectPtr =
6095 						findObjectByModuleAndName(
6096 						    thisParserPtr->complianceModulePtr, $1);
6097 					    if (objectPtr) {
6098 						importPtr = addImport(
6099 						    $1,
6100 						    thisParserPtr);
6101 						setImportModulename(importPtr,
6102 						    thisParserPtr->complianceModulePtr->export.name);
6103 						addImportFlags(importPtr,
6104 							       FLAG_INCOMPLIANCE);
6105 						importPtr->use++;
6106 					    } else {
6107 						objectPtr = addObject($1,
6108 						    thisParserPtr->pendingNodePtr, 0,
6109 						    FLAG_INCOMPLETE,
6110 						    thisParserPtr);
6111 						smiPrintError(thisParserPtr,
6112 					      ERR_IDENTIFIER_NOT_IN_MODULE, $1,
6113 					     thisParserPtr->complianceModulePtr->export.name);
6114 					    }
6115 					} else if (thisParserPtr->capabilitiesModulePtr) {
6116 					    objectPtr =
6117 						findObjectByModuleAndName(
6118 						    thisParserPtr->capabilitiesModulePtr, $1);
6119 					    if (objectPtr) {
6120 						importPtr = addImport(
6121 						    $1,
6122 						    thisParserPtr);
6123 						setImportModulename(importPtr,
6124 						        thisParserPtr->capabilitiesModulePtr->
6125 								  export.name);
6126 						addImportFlags(importPtr,
6127 							       FLAG_INCOMPLIANCE);
6128 						importPtr->use++;
6129 					    } else {
6130 						objectPtr = addObject($1,
6131 						    thisParserPtr->pendingNodePtr, 0,
6132 						    FLAG_INCOMPLETE,
6133 						    thisParserPtr);
6134 						smiPrintError(thisParserPtr,
6135 					      ERR_IDENTIFIER_NOT_IN_MODULE, $1,
6136 					   thisParserPtr->capabilitiesModulePtr->export.name);
6137 					    }
6138 					} else {
6139 					    /*
6140 					     * forward referenced node.
6141 					     * create it,
6142 					     * marked with FLAG_INCOMPLETE.
6143 					     */
6144 					    objectPtr = addObject($3,
6145 							    thisParserPtr->pendingNodePtr,
6146 							      0,
6147 							      FLAG_INCOMPLETE,
6148 							      thisParserPtr);
6149 					    smiFree($1);
6150 					}
6151 					$$ = objectPtr;
6152 				    } else {
6153 					/*
6154 					 * imported object.
6155 					 */
6156 					importPtr->use++;
6157 					$$ = findObjectByModulenameAndName(
6158 					    importPtr->export.module, $3);
6159 					smiFree($1);
6160 					smiFree($3);
6161 				    }
6162 				}
6163 				if ($$)
6164 				    thisParserPtr->parentNodePtr = $$->nodePtr;
6165 			    }
6166 			}
6167 	|		NUMBER
6168 			{
6169 			    Node *nodePtr;
6170 			    Object *objectPtr;
6171 
6172 			    nodePtr = findNodeByParentAndSubid(thisParserPtr->parentNodePtr,
6173 							       $1);
6174 			    if (nodePtr && nodePtr->lastObjectPtr &&
6175 	       		(nodePtr->lastObjectPtr->modulePtr == thisModulePtr)) {
6176 				/*
6177 				 * hopefully, the last defined Object for
6178 				 * this Node is the one we expect.
6179 				 */
6180 				$$ = nodePtr->lastObjectPtr;
6181 			    } else {
6182 				objectPtr = addObject(NULL,
6183 						      thisParserPtr->parentNodePtr,
6184 						      $1,
6185 						      FLAG_INCOMPLETE,
6186 						      thisParserPtr);
6187 				$$ = objectPtr;
6188 			    }
6189 			    thisParserPtr->parentNodePtr = $$->nodePtr;
6190 			}
6191 	|		LOWERCASE_IDENTIFIER '(' NUMBER ')'
6192 			{
6193 			    Object *objectPtr = NULL;
6194 			    Object *oldObjectPtr = NULL;
6195 			    Node *oldNodePtr = NULL;
6196 
6197 			    /* TODO: search in local module and
6198 			     *       in imported modules
6199 			     */
6200 
6201 			    oldNodePtr = findNodeByParentAndSubid(
6202 				thisParserPtr->parentNodePtr, $3);
6203 			    oldObjectPtr = findObjectByModuleAndName(
6204                                 thisParserPtr->modulePtr, $1);
6205 
6206 			    if (oldObjectPtr &&
6207 				((oldObjectPtr->nodePtr->subid != $3) ||
6208 				 (oldObjectPtr->nodePtr->parentPtr != thisParserPtr->parentNodePtr))) {
6209 				smiPrintError(thisParserPtr,
6210 					      ERR_IDENTIFIER_OID_CHANGED,
6211 					      $1);
6212 				smiPrintErrorAtLine(thisParserPtr,
6213 						    ERR_PREVIOUS_DEFINITION,
6214 						    oldObjectPtr->line,
6215 						    oldObjectPtr->export.name);
6216 				objectPtr = addObject($1,
6217 						      thisParserPtr->parentNodePtr,
6218 						      $3, 0, thisParserPtr);
6219 				setObjectDecl(objectPtr,
6220 					      SMI_DECL_IMPL_OBJECT);
6221 				$$ = objectPtr;
6222 				thisParserPtr->parentNodePtr = $$->nodePtr;
6223 			    } else if (oldNodePtr &&
6224 				       oldNodePtr->lastObjectPtr &&
6225 				       oldNodePtr->lastObjectPtr->export.name &&
6226 				       strcmp(oldNodePtr->lastObjectPtr->export.name, $1)) {
6227 				smiPrintError(thisParserPtr,
6228 					      ERR_OIDLABEL_CHANGED,
6229 					      $1, oldNodePtr->lastObjectPtr->export.name);
6230 				smiPrintErrorAtLine(thisParserPtr,
6231 						    ERR_PREVIOUS_DEFINITION,
6232 						    oldNodePtr->lastObjectPtr->line,
6233 						    oldNodePtr->lastObjectPtr->export.name);
6234 				objectPtr = addObject($1,
6235 						      thisParserPtr->parentNodePtr,
6236 						      $3, 0, thisParserPtr);
6237 				setObjectDecl(objectPtr,
6238 					      SMI_DECL_IMPL_OBJECT);
6239 				$$ = objectPtr;
6240 				thisParserPtr->parentNodePtr = $$->nodePtr;
6241 			    } else {
6242 				objectPtr = addObject($1, thisParserPtr->parentNodePtr,
6243 						      $3, 0,
6244 						      thisParserPtr);
6245 				setObjectDecl(objectPtr,
6246 					      SMI_DECL_IMPL_OBJECT);
6247 				$$ = objectPtr;
6248 				thisParserPtr->parentNodePtr = $$->nodePtr;
6249 			    }
6250 			}
6251 	|		moduleName '.' LOWERCASE_IDENTIFIER '(' NUMBER ')'
6252 			{
6253 			    Object *objectPtr = NULL;
6254 			    Object *oldObjectPtr = NULL;
6255 			    Node *oldNodePtr = NULL;
6256 			    char *md;
6257 
6258 			    md = smiMalloc(sizeof(char) *
6259 					   (strlen($1) + strlen($3) + 2));
6260 			    sprintf(md, "%s.%s", $1, $3);
6261 
6262 			    oldNodePtr = findNodeByParentAndSubid(
6263 				thisParserPtr->parentNodePtr, $5);
6264 			    oldObjectPtr = findObjectByModulenameAndName(
6265                                 $1, $3);
6266 
6267 			    if (oldObjectPtr &&
6268 				((oldObjectPtr->nodePtr->subid != $5) ||
6269 				 (oldObjectPtr->nodePtr->parentPtr != thisParserPtr->parentNodePtr))) {
6270 				smiPrintError(thisParserPtr,
6271 					      ERR_ILLEGALLY_QUALIFIED, md);
6272 				smiPrintError(thisParserPtr,
6273 					      ERR_IDENTIFIER_OID_CHANGED,
6274 					      $3);
6275 				smiPrintErrorAtLine(thisParserPtr,
6276 						    ERR_PREVIOUS_DEFINITION,
6277 						    oldObjectPtr->line,
6278 						    oldObjectPtr->export.name);
6279 				objectPtr = addObject($3,
6280 						      thisParserPtr->parentNodePtr,
6281 						      $5, 0, thisParserPtr);
6282 				setObjectDecl(objectPtr,
6283 					      SMI_DECL_IMPL_OBJECT);
6284 				$$ = objectPtr;
6285 				thisParserPtr->parentNodePtr = $$->nodePtr;
6286 			    } else if (oldNodePtr &&
6287 				       oldNodePtr->lastObjectPtr &&
6288 				       strcmp(oldNodePtr->lastObjectPtr->export.name, $3)) {
6289 				smiPrintError(thisParserPtr,
6290 					      ERR_ILLEGALLY_QUALIFIED, md);
6291 				smiPrintError(thisParserPtr,
6292 					      ERR_OIDLABEL_CHANGED,
6293 					      $3, oldNodePtr->lastObjectPtr->export.name);
6294 				smiPrintErrorAtLine(thisParserPtr,
6295 						    ERR_PREVIOUS_DEFINITION,
6296 						    oldNodePtr->lastObjectPtr->line,
6297 						    oldNodePtr->lastObjectPtr->export.name);
6298 				objectPtr = addObject($3,
6299 						      thisParserPtr->parentNodePtr,
6300 						      $5, 0, thisParserPtr);
6301 				setObjectDecl(objectPtr,
6302 					      SMI_DECL_IMPL_OBJECT);
6303 				$$ = objectPtr;
6304 				thisParserPtr->parentNodePtr = $$->nodePtr;
6305 			    } else {
6306 				smiPrintError(thisParserPtr,
6307 					      ERR_ILLEGALLY_QUALIFIED, md);
6308 				objectPtr = addObject($3, thisParserPtr->parentNodePtr,
6309 						      $5, 0,
6310 						      thisParserPtr);
6311 				setObjectDecl(objectPtr,
6312 					      SMI_DECL_IMPL_OBJECT);
6313 				$$ = objectPtr;
6314 				thisParserPtr->parentNodePtr = $$->nodePtr;
6315 			    }
6316 			    smiFree(md);
6317 			}
6318 	;
6319 
6320 objectIdentifier_defval: subidentifiers_defval
6321 			{ $$ = NULL; }
6322         ;		/* TODO */
6323 
6324 subidentifiers_defval:	subidentifier_defval
6325 			{ $$ = 0; }
6326 	|		subidentifiers_defval subidentifier_defval
6327 			{ $$ = 0; }
6328         ;		/* TODO */
6329 
6330 subidentifier_defval:	LOWERCASE_IDENTIFIER '(' NUMBER ')'
6331 			{ $$ = 0; }
6332 	|		NUMBER
6333 			{ $$ = 0; }
6334 	;		/* TODO */
6335 
6336 objectGroupClause:	LOWERCASE_IDENTIFIER
6337 			{
6338 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
6339 			    thisParserPtr->currentDecl = SMI_DECL_OBJECTGROUP;
6340 
6341 			    checkNameLen(thisParserPtr, $1,
6342 					 ERR_OIDNAME_32, ERR_OIDNAME_64);
6343 			    smiCheckObjectName(thisParserPtr,
6344 					       thisModulePtr, $1);
6345 			}
6346 			OBJECT_GROUP
6347 			{
6348 			    Import *importPtr;
6349 
6350 			    if (thisModulePtr->export.language == SMI_LANGUAGE_UNKNOWN)
6351 				thisModulePtr->export.language = SMI_LANGUAGE_SMIV2;
6352 
6353 			    importPtr = findImportByName("OBJECT-GROUP",
6354 							 thisModulePtr);
6355 			    if (importPtr) {
6356 				importPtr->use++;
6357 			    } else {
6358 				smiPrintError(thisParserPtr,
6359 					      ERR_MACRO_NOT_IMPORTED,
6360 					      "OBJECT-GROUP", "SNMPv2-CONF");
6361 			    }
6362 			}
6363 			ObjectGroupObjectsPart
6364 			STATUS Status
6365 			DESCRIPTION Text
6366 			{
6367 			    checkDescr(thisParserPtr, $9);
6368 			}
6369 			ReferPart
6370 			COLON_COLON_EQUAL '{' objectIdentifier '}'
6371 			{
6372 			    Object *objectPtr;
6373 
6374 			    objectPtr = $14;
6375 
6376 			    smiCheckObjectReuse(thisParserPtr, $1, &objectPtr);
6377 
6378 			    objectPtr = setObjectName(objectPtr, $1, thisParserPtr);
6379 			    setObjectDecl(objectPtr, SMI_DECL_OBJECTGROUP);
6380 			    setObjectLine(objectPtr, thisParserPtr->firstStatementLine,
6381 					  thisParserPtr);
6382 			    addObjectFlags(objectPtr, FLAG_REGISTERED);
6383 			    deleteObjectFlags(objectPtr, FLAG_INCOMPLETE);
6384 			    setObjectStatus(objectPtr, $7);
6385 			    setObjectDescription(objectPtr, $9, thisParserPtr);
6386 			    if ($11) {
6387 				setObjectReference(objectPtr, $11, thisParserPtr);
6388 			    }
6389 			    setObjectAccess(objectPtr,
6390 					    SMI_ACCESS_NOT_ACCESSIBLE);
6391 			    setObjectList(objectPtr, $5);
6392 			    $$ = 0;
6393 			}
6394 	;
6395 
6396 notificationGroupClause: LOWERCASE_IDENTIFIER
6397 			{
6398 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
6399 			    thisParserPtr->currentDecl = SMI_DECL_NOTIFICATIONGROUP;
6400 
6401 			    checkNameLen(thisParserPtr, $1,
6402 					 ERR_OIDNAME_32, ERR_OIDNAME_64);
6403 			    smiCheckObjectName(thisParserPtr,
6404 					       thisModulePtr, $1);
6405 			}
6406 			NOTIFICATION_GROUP
6407 			{
6408 			    Import *importPtr;
6409                             if (thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI)
6410                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "NOTIFICATION-GROUP");
6411 
6412 			    if (thisModulePtr->export.language == SMI_LANGUAGE_UNKNOWN)
6413 				thisModulePtr->export.language = SMI_LANGUAGE_SMIV2;
6414 
6415 			    importPtr = findImportByName("NOTIFICATION-GROUP",
6416 							 thisModulePtr);
6417 			    if (importPtr) {
6418 				importPtr->use++;
6419 			    } else {
6420 				smiPrintError(thisParserPtr,
6421 					      ERR_MACRO_NOT_IMPORTED,
6422 					      "NOTIFICATION-GROUP",
6423 					      "SNMPv2-CONF");
6424 			    }
6425 			}
6426 			NotificationsPart
6427 			STATUS Status
6428 			DESCRIPTION Text
6429 			{
6430 			    checkDescr(thisParserPtr, $9);
6431 			}
6432 			ReferPart
6433 			COLON_COLON_EQUAL '{' objectIdentifier '}'
6434 			{
6435 			    Object *objectPtr;
6436 
6437 			    objectPtr = $14;
6438 
6439 			    smiCheckObjectReuse(thisParserPtr, $1, &objectPtr);
6440 
6441 			    objectPtr = setObjectName(objectPtr, $1, thisParserPtr);
6442 			    setObjectDecl(objectPtr,
6443 					  SMI_DECL_NOTIFICATIONGROUP);
6444 			    setObjectLine(objectPtr, thisParserPtr->firstStatementLine,
6445 					  thisParserPtr);
6446 			    addObjectFlags(objectPtr, FLAG_REGISTERED);
6447 			    deleteObjectFlags(objectPtr, FLAG_INCOMPLETE);
6448 			    setObjectStatus(objectPtr, $7);
6449 			    setObjectDescription(objectPtr, $9, thisParserPtr);
6450 			    if ($11) {
6451 				setObjectReference(objectPtr, $11, thisParserPtr);
6452 			    }
6453 			    setObjectAccess(objectPtr,
6454 					    SMI_ACCESS_NOT_ACCESSIBLE);
6455 			    setObjectList(objectPtr, $5);
6456 			    $$ = 0;
6457 			}
6458 	;
6459 
6460 moduleComplianceClause:	LOWERCASE_IDENTIFIER
6461 			{
6462 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
6463 			    thisParserPtr->currentDecl = SMI_DECL_MODULECOMPLIANCE;
6464 
6465 			    checkNameLen(thisParserPtr, $1,
6466 					 ERR_OIDNAME_32, ERR_OIDNAME_64);
6467 			    smiCheckObjectName(thisParserPtr,
6468 					       thisModulePtr, $1);
6469 			}
6470 			MODULE_COMPLIANCE
6471 			{
6472 			    Import *importPtr;
6473 
6474 			    if (thisModulePtr->export.language == SMI_LANGUAGE_UNKNOWN)
6475 				thisModulePtr->export.language = SMI_LANGUAGE_SMIV2;
6476 			    importPtr = findImportByName("MODULE-COMPLIANCE",
6477 							 thisModulePtr);
6478 			    if (importPtr) {
6479 				importPtr->use++;
6480 			    } else {
6481 				smiPrintError(thisParserPtr,
6482 					      ERR_MACRO_NOT_IMPORTED,
6483 					      "MODULE-COMPLIANCE",
6484 					      "SNMPv2-CONF");
6485 			    }
6486 			}
6487 			STATUS Status
6488 			DESCRIPTION Text
6489 			{
6490 			    checkDescr(thisParserPtr, $8);
6491 			}
6492 			ReferPart
6493 			ComplianceModulePart
6494 			COLON_COLON_EQUAL '{' objectIdentifier '}'
6495 			{
6496 			    Object *objectPtr;
6497 			    Option *optionPtr;
6498 			    Refinement *refinementPtr;
6499 			    List *listPtr;
6500 
6501 			    objectPtr = $14;
6502 
6503 			    smiCheckObjectReuse(thisParserPtr, $1, &objectPtr);
6504 
6505 			    setObjectName(objectPtr, $1, thisParserPtr);
6506 			    setObjectDecl(objectPtr,
6507 					  SMI_DECL_MODULECOMPLIANCE);
6508 			    setObjectLine(objectPtr, thisParserPtr->firstStatementLine,
6509 					  thisParserPtr);
6510 			    addObjectFlags(objectPtr, FLAG_REGISTERED);
6511 			    deleteObjectFlags(objectPtr, FLAG_INCOMPLETE);
6512 			    setObjectStatus(objectPtr, $6);
6513 			    setObjectDescription(objectPtr, $8, thisParserPtr);
6514 			    if ($10) {
6515 				setObjectReference(objectPtr, $10, thisParserPtr);
6516 			    }
6517 			    setObjectAccess(objectPtr,
6518 					    SMI_ACCESS_NOT_ACCESSIBLE);
6519 			    setObjectList(objectPtr, $11.mandatorylistPtr);
6520 			    objectPtr->optionlistPtr = $11.optionlistPtr;
6521 			    objectPtr->refinementlistPtr =
6522 				                          $11.refinementlistPtr;
6523 
6524 			    if ($11.optionlistPtr) {
6525 				for (listPtr = $11.optionlistPtr;
6526 				     listPtr;
6527 				     listPtr = listPtr->nextPtr) {
6528 				    optionPtr = ((Option *)(listPtr->ptr));
6529 				    optionPtr->compliancePtr = objectPtr;
6530 				}
6531 			    }
6532 
6533 			    /*
6534 			     * Dirty: Fake the types' names in the
6535 			     * refinement list:
6536 			     * ``<compliancename>+<objecttypename>+type''
6537 			     * ``<compliancename>+<objecttypename>+writetype''
6538 			     */
6539 			    if ($11.refinementlistPtr) {
6540 				for (listPtr = $11.refinementlistPtr;
6541 				     listPtr;
6542 				     listPtr = listPtr->nextPtr) {
6543 				    refinementPtr =
6544 					((Refinement *)(listPtr->ptr));
6545 				    refinementPtr->compliancePtr = objectPtr;
6546 				}
6547 			    }
6548 
6549 			    $$ = 0;
6550 			}
6551 	;
6552 
6553 ComplianceModulePart:	ComplianceModules
6554 			{
6555 			    $$ = $1;
6556 			}
6557 	;
6558 
6559 ComplianceModules:	ComplianceModule
6560 			{
6561 			    $$ = $1;
6562 			}
6563 	|		ComplianceModules ComplianceModule
6564 			{
6565 			    List *listPtr;
6566 
6567 			    /* concatenate lists in $1 and $2 */
6568 			    if ($1.mandatorylistPtr) {
6569 				for (listPtr = $1.mandatorylistPtr;
6570 				     listPtr->nextPtr;
6571 				     listPtr = listPtr->nextPtr);
6572 				listPtr->nextPtr = $2.mandatorylistPtr;
6573 				$$.mandatorylistPtr = $1.mandatorylistPtr;
6574 			    } else {
6575 				$$.mandatorylistPtr = $2.mandatorylistPtr;
6576 			    }
6577 			    if ($1.optionlistPtr) {
6578 				for (listPtr = $1.optionlistPtr;
6579 				     listPtr->nextPtr;
6580 				     listPtr = listPtr->nextPtr);
6581 				listPtr->nextPtr = $2.optionlistPtr;
6582 				$$.optionlistPtr = $1.optionlistPtr;
6583 			    } else {
6584 				$$.optionlistPtr = $2.optionlistPtr;
6585 			    }
6586 			    if ($1.refinementlistPtr) {
6587 				for (listPtr = $1.refinementlistPtr;
6588 				     listPtr->nextPtr;
6589 				     listPtr = listPtr->nextPtr);
6590 				listPtr->nextPtr = $2.refinementlistPtr;
6591 				$$.refinementlistPtr = $1.refinementlistPtr;
6592 			    } else {
6593 				$$.refinementlistPtr = $2.refinementlistPtr;
6594 			    }
6595 			}
6596 	;
6597 
6598 ComplianceModule:	MODULE ComplianceModuleName
6599 			{
6600 			    /*
6601 			     * Remember the module. SMIv2 is broken by
6602 			     * design to allow subsequent clauses to
6603 			     * refer identifiers that are not
6604 			     * imported.  Although, SMIv2 does not
6605 			     * require, we will fake it by inserting
6606 			     * appropriate imports.
6607 			     */
6608 			    if ($2 == thisModulePtr)
6609 				thisParserPtr->complianceModulePtr = NULL;
6610 			    else
6611 				thisParserPtr->complianceModulePtr = $2;
6612 			}
6613 			MandatoryPart
6614 			CompliancePart
6615 			{
6616 			    $$.mandatorylistPtr = $4;
6617 			    $$.optionlistPtr = $5.optionlistPtr;
6618 			    $$.refinementlistPtr = $5.refinementlistPtr;
6619 			    if (thisParserPtr->complianceModulePtr) {
6620 				checkImports(thisParserPtr->complianceModulePtr,
6621 					     thisParserPtr);
6622 				thisParserPtr->complianceModulePtr = NULL;
6623 			    }
6624 			}
6625 	;
6626 
6627 ComplianceModuleName:	UPPERCASE_IDENTIFIER objectIdentifier
6628 			{
6629 			    $$ = findModuleByName($1);
6630 			    /* TODO: handle objectIdentifier */
6631 			    if (!$$) {
6632 				$$ = loadModule($1, thisParserPtr);
6633 			    }
6634 			    smiFree($1);
6635 			}
6636 	|		UPPERCASE_IDENTIFIER
6637 			{
6638 			    $$ = findModuleByName($1);
6639 			    if (!$$) {
6640 				$$ = loadModule($1, thisParserPtr);
6641 			    }
6642 			    smiFree($1);
6643 			}
6644 	|		/* empty, only if contained in MIB module */
6645 			/* TODO: RFC 1904 looks a bit different, is this ok? */
6646 			{
6647 			    $$ = thisModulePtr;
6648 			}
6649 	;
6650 
6651 MandatoryPart:		MANDATORY_GROUPS '{' MandatoryGroups '}'
6652 			{
6653 			    $$ = $3;
6654 			}
6655 	|		/* empty */
6656 			{
6657 			    $$ = NULL;
6658 			}
6659 	;
6660 
6661 MandatoryGroups:	MandatoryGroup
6662 			{
6663 			    $$ = smiMalloc(sizeof(List));
6664 			    $$->ptr = $1;
6665 			    $$->nextPtr = NULL;
6666 			}
6667 	|		MandatoryGroups ',' MandatoryGroup
6668 			{
6669 			    List *p, *pp;
6670 
6671 			    p = smiMalloc(sizeof(List));
6672 			    p->ptr = $3;
6673 			    p->nextPtr = NULL;
6674 			    for (pp = $1; pp->nextPtr; pp = pp->nextPtr);
6675 			    pp->nextPtr = p;
6676 			    $$ = $1;
6677 			}
6678 	;
6679 
6680 MandatoryGroup:		objectIdentifier
6681 			{
6682 			    /* TODO: check that objectIdentifier is
6683 			       found, is defined in thisParserPtr->complianceModulePtr,
6684 			       and is a group node. */
6685 			    Import *importPtr;
6686 
6687 			    $$ = $1;
6688 			    if (thisParserPtr->complianceModulePtr) {
6689 				$$ = findObjectByModuleAndName(
6690 				                           thisParserPtr->complianceModulePtr,
6691 							   $1->export.name);
6692 			    }
6693 			    if (thisParserPtr->complianceModulePtr && $1->export.name) {
6694 				importPtr = findImportByModulenameAndName(
6695 				    thisParserPtr->complianceModulePtr->export.name,
6696 				    $1->export.name, thisModulePtr);
6697 				if (importPtr)
6698 				    importPtr->use++;
6699 			    }
6700 			}
6701 	;
6702 
6703 CompliancePart:		Compliances
6704 			{
6705 			    $$.mandatorylistPtr = NULL;
6706 			    $$.optionlistPtr = $1.optionlistPtr;
6707 			    $$.refinementlistPtr = $1.refinementlistPtr;
6708 			}
6709 	|		/* empty */
6710 			{
6711 			    $$.mandatorylistPtr = NULL;
6712 			    $$.optionlistPtr = NULL;
6713 			    $$.refinementlistPtr = NULL;
6714 			}
6715 	;
6716 
6717 Compliances:		Compliance
6718 			{
6719 			    $$ = $1;
6720 			}
6721 	|		Compliances Compliance
6722 			{
6723 			    List *listPtr;
6724 			    int stop;
6725 
6726 			    $$.mandatorylistPtr = NULL;
6727 
6728 			    /* check for duplicates in optionlist */
6729 			    stop = 0;
6730 			    if ($2.optionlistPtr) {
6731 				for (listPtr = $1.optionlistPtr; listPtr;
6732 				     listPtr = listPtr->nextPtr) {
6733 				    if (((Option *)listPtr->ptr)->objectPtr ==
6734 					((Option *)$2.optionlistPtr->ptr)->objectPtr) {
6735 					smiPrintError(thisParserPtr,
6736 						      ERR_OPTIONALGROUP_ALREADY_EXISTS,
6737 						      ((Option *)$2.optionlistPtr->ptr)->objectPtr->export.name);
6738 					stop = 1;
6739 					$$.optionlistPtr = $1.optionlistPtr;
6740 				    }
6741 				}
6742 			    }
6743 
6744                             /* concatenate optionlists */
6745 			    if ($1.optionlistPtr) {
6746 				for (listPtr = $1.optionlistPtr;
6747 				     listPtr->nextPtr;
6748 				     listPtr = listPtr->nextPtr);
6749 				if (!stop) {
6750 				    listPtr->nextPtr = $2.optionlistPtr;
6751 				}
6752 				$$.optionlistPtr = $1.optionlistPtr;
6753 			    } else {
6754 				$$.optionlistPtr = $2.optionlistPtr;
6755 			    }
6756 
6757 			    /* check for duplicates in refinementlist */
6758 			    stop = 0;
6759 			    if ($2.refinementlistPtr) {
6760 				for (listPtr = $1.refinementlistPtr; listPtr;
6761 				     listPtr = listPtr->nextPtr) {
6762 				    if (((Refinement *)listPtr->ptr)->objectPtr ==
6763 					((Refinement *)$2.refinementlistPtr->ptr)->objectPtr) {
6764 					smiPrintError(thisParserPtr,
6765 						      ERR_REFINEMENT_ALREADY_EXISTS,
6766 						      ((Refinement *)$2.refinementlistPtr->ptr)->objectPtr->export.name);
6767 					stop = 1;
6768 					$$.refinementlistPtr = $1.refinementlistPtr;
6769 				    }
6770 				}
6771 			    }
6772 
6773                             /* concatenate refinementlists */
6774 			    if ($1.refinementlistPtr) {
6775 				for (listPtr = $1.refinementlistPtr;
6776 				     listPtr->nextPtr;
6777 				     listPtr = listPtr->nextPtr);
6778 				if (!stop) {
6779 				    listPtr->nextPtr = $2.refinementlistPtr;
6780 				}
6781 				$$.refinementlistPtr = $1.refinementlistPtr;
6782 			    } else {
6783 				$$.refinementlistPtr = $2.refinementlistPtr;
6784 			    }
6785 			}
6786 	;
6787 
6788 Compliance:		ComplianceGroup
6789 			{
6790 			    $$.mandatorylistPtr = NULL;
6791 			    $$.optionlistPtr = $1;
6792 			    $$.refinementlistPtr = NULL;
6793 			}
6794 	|		ComplianceObject
6795 			{
6796 			    $$.mandatorylistPtr = NULL;
6797 			    $$.optionlistPtr = NULL;
6798 			    $$.refinementlistPtr = $1;
6799 			}
6800 	;
6801 
6802 ComplianceGroup:	GROUP
6803 			{
6804 			    thisParserPtr->firstNestedStatementLine = thisParserPtr->line;
6805 			}
6806 			objectIdentifier
6807 			DESCRIPTION Text
6808 			{
6809 			    Import *importPtr;
6810 
6811 			    if (thisParserPtr->complianceModulePtr && $3->export.name) {
6812 				importPtr = findImportByModulenameAndName(
6813 						    thisParserPtr->complianceModulePtr->export.name,
6814 						    $3->export.name,
6815 						    thisModulePtr);
6816 				if (importPtr)
6817 				    importPtr->use++;
6818 			    }
6819 
6820 			    checkDescr(thisParserPtr, $5);
6821 
6822 			    $$ = smiMalloc(sizeof(List));
6823 			    $$->nextPtr = NULL;
6824 			    $$->ptr = smiMalloc(sizeof(Option));
6825 			    ((Option *)($$->ptr))->line = thisParserPtr->firstNestedStatementLine;
6826 			    ((Option *)($$->ptr))->objectPtr = $3;
6827 			    if (! (thisModulePtr->flags & SMI_FLAG_NODESCR)) {
6828 				((Option *)($$->ptr))->export.description = $5;
6829 			    } else {
6830 				smiFree($5);
6831 			    }
6832 			}
6833 	;
6834 
6835 ComplianceObject:	OBJECT
6836 			{
6837 			    thisParserPtr->firstNestedStatementLine = thisParserPtr->line;
6838 			}
6839 			ObjectName
6840 			SyntaxPart
6841 			WriteSyntaxPart                 /* modified for SPPI */
6842 			AccessPart                      /* modified for SPPI */
6843 			DESCRIPTION Text
6844 			{
6845 			    Import *importPtr;
6846 
6847 			    if (thisParserPtr->complianceModulePtr && $3->export.name) {
6848 				importPtr = findImportByModulenameAndName(
6849 						    thisParserPtr->complianceModulePtr->export.name,
6850 						    $3->export.name,
6851 						    thisModulePtr);
6852 				if (importPtr)
6853 				    importPtr->use++;
6854 			    }
6855 
6856 			    checkDescr(thisParserPtr, $8);
6857 
6858 			    thisParserPtr->flags &= ~FLAG_CREATABLE;
6859 			    $$ = smiMalloc(sizeof(List));
6860 			    $$->nextPtr = NULL;
6861 			    $$->ptr = smiMalloc(sizeof(Refinement));
6862 			    ((Refinement *)($$->ptr))->line =
6863 				thisParserPtr->firstNestedStatementLine;
6864 			    ((Refinement *)($$->ptr))->objectPtr = $3;
6865 			    ((Refinement *)($$->ptr))->typePtr = $4;
6866 			    if ($4) {
6867 				$4->parentPtr = $3->typePtr;
6868 			    }
6869 			    ((Refinement *)($$->ptr))->writetypePtr = $5;
6870 			    if ($5) {
6871 				$5->parentPtr = $3->typePtr;
6872 			    }
6873 			    ((Refinement *)($$->ptr))->export.access = $6;
6874 			    if (! (thisParserPtr->flags & SMI_FLAG_NODESCR)) {
6875 				((Refinement *)($$->ptr))->export.description = $8;
6876 			    } else {
6877 				smiFree($8);
6878 			    }
6879 			}
6880 	;
6881 
6882 SyntaxPart:		SYNTAX Syntax
6883 			{
6884 			    if ($2->export.name) {
6885 				$$ = duplicateType($2, 0, thisParserPtr);
6886 			    } else {
6887 				$$ = $2;
6888 			    }
6889 			}
6890 	|		/* empty */
6891 			{
6892 			    $$ = NULL;
6893 			}
6894 	;
6895 
6896 WriteSyntaxPart:	WRITE_SYNTAX WriteSyntax
6897 			{
6898                             /* must not be present in PIBs */
6899                             if (thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI)
6900                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "WRITE-SYNTAX");
6901 			    if ($2->export.name) {
6902 				$$ = duplicateType($2, 0, thisParserPtr);
6903 			    } else {
6904 				$$ = $2;
6905 			    }
6906 			}
6907 	|		/* empty */
6908 			{
6909 			    $$ = NULL;
6910 			}
6911 	;
6912 
6913 WriteSyntax:		Syntax
6914 			{
6915 			    $$ = $1;
6916 			}
6917 	;
6918 
6919 AccessPart:		MIN_ACCESS Access
6920 			{
6921                             if (thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI)
6922                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "MIN-ACCESS");
6923 			    $$ = $2;
6924 			}
6925         |               PIB_MIN_ACCESS Access
6926                         {
6927                             if (thisParserPtr->modulePtr->export.language != SMI_LANGUAGE_SPPI)
6928                                 smiPrintError(thisParserPtr, ERR_SPPI_CONSTRUCT_IN_MIB, "PIB-MIN-ACCESS");
6929                             if ($2 == SMI_ACCESS_REPORT_ONLY)
6930                                 smiPrintError(thisParserPtr, ERR_REPORT_ONLY_IN_PIB_MIN_ACCESS);
6931                             $$ = $2;
6932                         }
6933 	|		/* empty */
6934 			{
6935 			    $$ = SMI_ACCESS_UNKNOWN;
6936 			}
6937 	;
6938 
6939 agentCapabilitiesClause: LOWERCASE_IDENTIFIER
6940 			{
6941 			    thisParserPtr->firstStatementLine = thisParserPtr->line;
6942 			    thisParserPtr->currentDecl = SMI_DECL_AGENTCAPABILITIES;
6943 
6944 			    checkNameLen(thisParserPtr, $1,
6945 					 ERR_OIDNAME_32, ERR_OIDNAME_64);
6946 			    smiCheckObjectName(thisParserPtr,
6947 					       thisModulePtr, $1);
6948 			}
6949 			AGENT_CAPABILITIES
6950 			{
6951 			    Import *importPtr;
6952                             if (thisParserPtr->modulePtr->export.language == SMI_LANGUAGE_SPPI)
6953                                 smiPrintError(thisParserPtr, ERR_SMI_CONSTRUCT_IN_PIB, "AGENT-CAAPABILITIES");
6954 
6955 			    if (thisModulePtr->export.language == SMI_LANGUAGE_UNKNOWN)
6956 				thisModulePtr->export.language = SMI_LANGUAGE_SMIV2;
6957 
6958 			    importPtr = findImportByName("AGENT-CAPABILITIES",
6959 							 thisModulePtr);
6960 			    if (importPtr) {
6961 				importPtr->use++;
6962 			    } else {
6963 				smiPrintError(thisParserPtr,
6964 					      ERR_MACRO_NOT_IMPORTED,
6965 					      "AGENT-CAPABILITIES",
6966 					      "SNMPv2-CONF");
6967 			    }
6968 			}
6969 			PRODUCT_RELEASE Text
6970 			STATUS Status_Capabilities
6971 			DESCRIPTION Text
6972 			{
6973 			    checkDescr(thisParserPtr, $10);
6974 			}
6975 			ReferPart
6976 			ModulePart_Capabilities
6977 			COLON_COLON_EQUAL '{' objectIdentifier '}'
6978 			{
6979 			    Object *objectPtr;
6980 
6981 			    objectPtr = $16;
6982 
6983 			    smiCheckObjectReuse(thisParserPtr, $1, &objectPtr);
6984 
6985 			    setObjectName(objectPtr, $1, thisParserPtr);
6986 			    setObjectDecl(objectPtr,
6987 					  SMI_DECL_AGENTCAPABILITIES);
6988 			    setObjectLine(objectPtr, thisParserPtr->firstStatementLine,
6989 					  thisParserPtr);
6990 			    addObjectFlags(objectPtr, FLAG_REGISTERED);
6991 			    deleteObjectFlags(objectPtr, FLAG_INCOMPLETE);
6992 			    setObjectStatus(objectPtr, $8);
6993 			    setObjectDescription(objectPtr, $10, thisParserPtr);
6994 			    if ($12) {
6995 				setObjectReference(objectPtr, $12, thisParserPtr);
6996 			    }
6997 			    setObjectAccess(objectPtr,
6998 					    SMI_ACCESS_NOT_ACCESSIBLE);
6999 				/*
7000 				 * TODO: PRODUCT_RELEASE Text
7001 				 * TODO: ModulePart_Capabilities
7002 				 */
7003 			    $$ = 0;
7004 			}
7005 	;
7006 
7007 ModulePart_Capabilities: Modules_Capabilities
7008 			{ $$ = 0; }
7009 	|		/* empty */
7010 			{ $$ = 0; }
7011 	;
7012 
7013 Modules_Capabilities:	Module_Capabilities
7014 			{ $$ = 0; }
7015 	|		Modules_Capabilities Module_Capabilities
7016 			{ $$ = 0; }
7017 	;
7018 
7019 Module_Capabilities:	SUPPORTS ModuleName_Capabilities
7020 			{
7021 			    /*
7022 			     * Remember the module. SMIv2 is broken by
7023 			     * design to allow subsequent clauses to
7024 			     * refer identifiers that are not
7025 			     * imported.  Although, SMIv2 does not
7026 			     * require, we will fake it by inserting
7027 			     * appropriate imports.
7028 			     */
7029 			    if ($2 == thisModulePtr)
7030 				thisParserPtr->capabilitiesModulePtr = NULL;
7031 			    else
7032 				thisParserPtr->capabilitiesModulePtr = $2;
7033 			}
7034 			INCLUDES '{' CapabilitiesGroups '}'
7035 			VariationPart
7036 			{
7037 			    if (thisParserPtr->capabilitiesModulePtr) {
7038 				checkImports(thisParserPtr->capabilitiesModulePtr,
7039 					     thisParserPtr);
7040 				thisParserPtr->capabilitiesModulePtr = NULL;
7041 			    }
7042 			    $$ = 0;
7043 			}
7044 	;
7045 
7046 CapabilitiesGroups:	CapabilitiesGroup
7047 			{
7048 #if 0
7049 			    $$ = smiMalloc(sizeof(List));
7050 			    $$->ptr = $1;
7051 			    $$->nextPtr = NULL;
7052 #else
7053 			    $$ = NULL;
7054 #endif
7055 			}
7056 	|		CapabilitiesGroups ',' CapabilitiesGroup
7057 			{
7058 #if 0
7059 			    List *p, *pp;
7060 
7061 			    p = smiMalloc(sizeof(List));
7062 			    p->ptr = $3;
7063 			    p->nextPtr = NULL;
7064 			    for (pp = $1; pp->nextPtr; pp = pp->nextPtr);
7065 			    pp->nextPtr = p;
7066 			    $$ = $1;
7067 #else
7068 			    $$ = NULL;
7069 #endif
7070 			}
7071 	;
7072 
7073 CapabilitiesGroup:	objectIdentifier
7074 			{
7075 			    $$ = NULL;
7076 			}
7077 	;
7078 
7079 ModuleName_Capabilities: UPPERCASE_IDENTIFIER objectIdentifier
7080 			{
7081 			    $$ = findModuleByName($1);
7082 			    /* TODO: handle objectIdentifier */
7083 			    if (!$$) {
7084 				$$ = loadModule($1, thisParserPtr);
7085 			    }
7086 			    smiFree($1);
7087 			}
7088 	|		UPPERCASE_IDENTIFIER
7089 			{
7090 			    $$ = findModuleByName($1);
7091 			    if (!$$) {
7092 				$$ = loadModule($1, thisParserPtr);
7093 			    }
7094 			    smiFree($1);
7095 			}
7096 	;
7097 
7098 VariationPart:		Variations
7099 			{ $$ = 0; }
7100 	|		/* empty */
7101 			{ $$ = 0; }
7102 	;
7103 
7104 Variations:		Variation
7105 			{ $$ = 0; }
7106 	|		Variations Variation
7107 			{ $$ = 0; }
7108 	;
7109 
7110 Variation:		VARIATION ObjectName
7111 			{
7112 			    if ($2) {
7113 				variationkind = $2->export.nodekind;
7114 			    } else {
7115 				variationkind = SMI_NODEKIND_UNKNOWN;
7116 			    }
7117 			}
7118 			SyntaxPart
7119 			{
7120 			    if (variationkind == SMI_NODEKIND_NOTIFICATION) {
7121 				smiPrintError(thisParserPtr,
7122 				      ERR_NOTIFICATION_VARIATION_SYNTAX);
7123 			    }
7124 			}
7125 			WriteSyntaxPart
7126 			{
7127 			    if (variationkind == SMI_NODEKIND_NOTIFICATION) {
7128 				smiPrintError(thisParserPtr,
7129 				      ERR_NOTIFICATION_VARIATION_WRITESYNTAX);
7130 			    }
7131 			}
7132 			VariationAccessPart
7133 			CreationPart
7134 			{
7135 			    if (variationkind == SMI_NODEKIND_NOTIFICATION) {
7136 				smiPrintError(thisParserPtr,
7137 				      ERR_NOTIFICATION_VARIATION_CREATION);
7138 			    }
7139 			}
7140 			DefValPart
7141 			{
7142 			    if (variationkind == SMI_NODEKIND_NOTIFICATION) {
7143 				smiPrintError(thisParserPtr,
7144 				      ERR_NOTIFICATION_VARIATION_DEFVAL);
7145 			    } else if ($11) {
7146 				adjustDefval(thisParserPtr,
7147 					     $11, $2->typePtr,
7148 					     thisParserPtr->line);
7149 				smiCheckValueType(thisParserPtr,
7150 						  $11, $2->typePtr,
7151 						  thisParserPtr->line);
7152 			    }
7153 			}
7154 			DESCRIPTION Text
7155 			{
7156 			    thisParserPtr->flags &= ~FLAG_CREATABLE;
7157 			    $$ = 0;
7158 			    variationkind = SMI_NODEKIND_UNKNOWN;
7159 
7160 			    checkDescr(thisParserPtr, $14);
7161 			}
7162 	;
7163 
7164 VariationAccessPart:	ACCESS VariationAccess
7165 			{ $$ = $2; }
7166 	|		/* empty */
7167 			{ $$ = 0; }
7168 	;
7169 
7170 VariationAccess:	LOWERCASE_IDENTIFIER
7171 			{
7172 			    if (!strcmp($1, "not-implemented")) {
7173 				$$ = SMI_ACCESS_NOT_IMPLEMENTED;
7174 			    } else if (!strcmp($1, "accessible-for-notify")) {
7175 				if (variationkind ==
7176 				    SMI_NODEKIND_NOTIFICATION) {
7177 				    smiPrintError(thisParserPtr,
7178 				     ERR_INVALID_NOTIFICATION_VARIATION_ACCESS,
7179 					       $1);
7180 				    $$ = SMI_ACCESS_UNKNOWN;
7181 				} else {
7182 				    $$ = SMI_ACCESS_NOTIFY;
7183 				}
7184 			    } else if (!strcmp($1, "read-only")) {
7185 				if (variationkind ==
7186 				    SMI_NODEKIND_NOTIFICATION) {
7187 				    smiPrintError(thisParserPtr,
7188 				     ERR_INVALID_NOTIFICATION_VARIATION_ACCESS,
7189 					       $1);
7190 				    $$ = SMI_ACCESS_UNKNOWN;
7191 				} else {
7192 				    $$ = SMI_ACCESS_READ_ONLY;
7193 				}
7194 			    } else if (!strcmp($1, "read-write")) {
7195 				if (variationkind ==
7196 				    SMI_NODEKIND_NOTIFICATION) {
7197 				    smiPrintError(thisParserPtr,
7198 				     ERR_INVALID_NOTIFICATION_VARIATION_ACCESS,
7199 					       $1);
7200 				    $$ = SMI_ACCESS_UNKNOWN;
7201 				} else {
7202 				    $$ = SMI_ACCESS_READ_WRITE;
7203 				}
7204 			    } else if (!strcmp($1, "read-create")) {
7205 				if (variationkind ==
7206 				    SMI_NODEKIND_NOTIFICATION) {
7207 				    smiPrintError(thisParserPtr,
7208 				     ERR_INVALID_NOTIFICATION_VARIATION_ACCESS,
7209 					       $1);
7210 				    $$ = SMI_ACCESS_UNKNOWN;
7211 				} else {
7212 				    $$ = SMI_ACCESS_READ_WRITE;
7213 				}
7214 			    } else if (!strcmp($1, "write-only")) {
7215 				if (variationkind ==
7216 				    SMI_NODEKIND_NOTIFICATION) {
7217 				    smiPrintError(thisParserPtr,
7218 				     ERR_INVALID_NOTIFICATION_VARIATION_ACCESS,
7219 					       $1);
7220 				    $$ = SMI_ACCESS_UNKNOWN;
7221 				} else {
7222 				    $$ = SMI_ACCESS_READ_WRITE; /* TODO */
7223 				    smiPrintError(thisParserPtr,
7224 					       ERR_SMIV2_WRITE_ONLY);
7225 				}
7226 			    } else {
7227 				smiPrintError(thisParserPtr,
7228 					      ERR_INVALID_VARIATION_ACCESS,
7229 					      $1);
7230 				$$ = SMI_ACCESS_UNKNOWN;
7231 			    }
7232 			}
7233         ;
7234 
7235 CreationPart:		CREATION_REQUIRES '{' Cells '}'
7236 			{ $$ = 0; }
7237 	|		/* empty */
7238 			{ $$ = 0; }
7239 	;
7240 
7241 Cells:			Cell
7242 			{ $$ = 0; }
7243 	|		Cells ',' Cell
7244 			{ $$ = 0; }
7245 	;
7246 
7247 Cell:			ObjectName
7248 			{ $$ = 0; }
7249 	;
7250 
7251 %%
7252 
7253 #endif
7254