2 * compiler/core/val_parser.c
3 * given a string with txt ASN.1 value notation, the length of
4 * the string and the ASN.1 type the value notion defines a value
5 * for, return a Value that contains the internal version
8 * currently limited to parsing OBJECT IDENTIFIERs.
9 * should be easy to extend for other values as needed
11 * Copyright (C) 1991, 1992 Michael Sample
12 * and the University of British Columbia
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * $Header: /cvs/root/Security/SecuritySNACCRuntime/compiler/core/Attic/val-parser.c,v 1.1 2001/06/20 21:27:59 dmitch Exp $
20 * $Log: val-parser.c,v $
21 * Revision 1.1 2001/06/20 21:27:59 dmitch
22 * Adding missing snacc compiler files.
24 * Revision 1.1.1.1 1999/03/16 18:06:53 aram
25 * Originals from SMIME Free Library.
27 * Revision 1.4 1997/10/10 13:43:16 wan
28 * Corrected bug in generic table decoder wrt. indefinite length elements
29 * Corrected compiler access to freed memory (bug reported by Markku Savela)
30 * Broke asnwish.c into two pieces so that one can build ones on wish
31 * Added beredit tool (based on asnwish, allowes to edit BER messages)
33 * Revision 1.3 1995/07/25 19:41:46 rj
34 * changed `_' to `-' in file names.
36 * Revision 1.2 1994/09/01 00:47:33 rj
37 * snacc_config.h removed; val_parser.h includet.
39 * Revision 1.1 1994/08/28 09:49:44 rj
40 * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.
46 #include <ctype.h> /* for isalpha, isdigit etc macros */
50 #include "asn1module.h"
52 #include "snacc-util.h"
53 #include "oid.h" /* arcname->number mapping */
54 #include "val-parser.h"
57 * a bunch of macros for 'standard' parse routines
65 #define RESTORE_POS()\
73 if (*vStr > farthestPosG)\
74 farthestPosG = *vStr;\
86 * a couple macros for errmsg generation
88 #define PRINT_ERR_LOC(m, vd)\
89 fprintf (stderr,"file \"%s\", line %d (or near): ", m->asn1SrcFileName, valLineNoG);
92 #define PRINT_VAL(vd)\
93 PrintValueDef (stderr, vd);
98 static ValueDefList
*newValsG
;
99 static int parseValuesErrG
;
100 static unsigned long valLineNoG
;
101 static char *farthestPosG
;
104 * prototypes for non-exported routines
106 char *StripComments
PROTO ((char *asn1Str
, int len
));
107 Value
*ParseValue
PROTO ((ModuleList
*mods
, Module
*m
, ValueDef
*vd
, Type
*t
, char *valueNotation
, int len
));
109 Value
*ParseValueInternal
PROTO ((ModuleList
*mods
, Module
*m
, ValueDef
*vd
, Type
*t
, char **valueNotation
, char *eof
));
111 int ParseOidValue
PROTO ((ModuleList
*mods
, Module
*m
, ValueDef
*vd
, Type
*t
, char **valueNotation
, char *eof
, Value
**result
));
113 void SkipWht
PROTO ((char **vStr
, char *eof
));
114 int ParseIdentifier
PROTO ((char **valueNotation
, char *eof
, char **result
));
115 int ParseNum
PROTO ((char **valueNotation
, char *eof
, char **result
));
116 void AddNewValueDef
PROTO ((ValueDefList
*vdl
, char *name
, Value
*value
));
121 * returns 0 if no parse errors occurred
122 * otherwise returns non-zero
125 ParseValues
PARAMS ((mods
, m
),
126 ModuleList
*mods _AND_
132 newValsG
= AsnListNew (sizeof (void*));
134 FOR_EACH_LIST_ELMT (v
, m
->valueDefs
)
136 if (v
->value
->basicValue
->choiceId
== BASICVALUE_VALUENOTATION
)
138 valLineNoG
= v
->value
->lineNo
;
139 pv
= ParseValue (mods
, m
, v
, v
->value
->type
, v
->value
->basicValue
->a
.valueNotation
->octs
, v
->value
->basicValue
->a
.valueNotation
->octetLen
);
141 /* replace value notation value with parsed version */
144 pv
->lineNo
= v
->value
->lineNo
;
145 pv
->type
= v
->value
->type
;
146 Free (v
->value
->basicValue
->a
.valueNotation
->octs
);
147 Free (v
->value
->basicValue
->a
.valueNotation
);
148 Free (v
->value
->basicValue
);
156 * should traverse type structures for default values etc
160 /* add any new value defs */
161 m
->valueDefs
= AsnListConcat (m
->valueDefs
, newValsG
);
164 return parseValuesErrG
;
171 * returns the Value that resuls from parsing the given
172 * value notation string
175 ParseValue
PARAMS ((mods
, m
, vd
, t
, valueNotationStr
, vnLen
),
176 ModuleList
*mods _AND_
180 char *valueNotationStr _AND_
188 /* make copy of value notation with ASN.1 comments zapped */
189 vStrOrig
= vStr
= StripComments (valueNotationStr
, vnLen
);
190 vStrLen
= strlen (vStr
);
192 retVal
= ParseValueInternal (mods
, m
, vd
, t
, &vStr
, (vStr
+ vStrLen
));
194 /* use original since parsing has changed vStr */
201 * vStr is a handle to a commentless ASN.1 value string,
202 * eof is a char * to character after the last valid character
203 * in vStr. vStr will be advanced to the current parse location.
206 ParseValueInternal
PARAMS ((mods
, m
, vd
, t
, vStr
, eof
),
207 ModuleList
*mods _AND_
216 int parseResult
= FALSE
;
218 dT
= ParanoidGetType (t
); /* skip type refs to get defining type */
225 switch (dT
->basicType
->choiceId
)
227 case BASICTYPE_SEQUENCE
:
229 case BASICTYPE_CHOICE
:
230 case BASICTYPE_SEQUENCEOF
:
231 case BASICTYPE_SETOF
:
232 /* don't do constructed types yet */
236 case BASICTYPE_SELECTION
:
237 case BASICTYPE_COMPONENTSOF
:
238 case BASICTYPE_ANYDEFINEDBY
:
239 case BASICTYPE_UNKNOWN
:
241 /* don't do weird types */
246 * The following simple types will need to be filled in
247 * when the constructed types are parsed.
248 * (ie ParseValueInternal becomes recursive)
249 * (currenly all simple types not in {}'s are parsed
250 * in the main yacc parser.)
253 case BASICTYPE_BOOLEAN
:
256 case BASICTYPE_INTEGER
:
257 case BASICTYPE_ENUMERATED
:
263 case BASICTYPE_BITSTRING
:
269 case BASICTYPE_OCTETSTRING
:
273 /* assume all macro values in {}'s are OID values */
275 case BASICTYPE_MACROTYPE
:
276 parseResult
= ParseOidValue (mods
, m
, vd
, t
, vStr
, eof
, &retVal
);
291 } /* ParseValueInternal */
295 * Strips ASN.1 comments from the given string.
296 * returns a null terminated malloc'd copy without the comments
299 StripComments
PARAMS ((s
, len
),
304 int sIndex
, cpyIndex
;
307 cpy
= (char*)Malloc (len
+1);
309 for (sIndex
= 0; sIndex
< len
; )
311 if ((s
[sIndex
] == '-') &&
312 ((sIndex
+1) < len
) && (s
[sIndex
+1]== '-'))
314 /* eat comment body */
315 for (sIndex
+= 2; sIndex
< len
; )
317 if ((s
[sIndex
] == '-') &&
318 ((sIndex
+1) < len
) && (s
[sIndex
+1]== '-'))
321 break; /* exit for */
323 else if (s
[sIndex
] == '\n')
326 break; /* exit for */
332 else /* not in or start of comment */
333 cpy
[cpyIndex
++] = s
[sIndex
++];
336 cpy
[cpyIndex
] == '\0'; /* add NULL terminator */
338 } /* StripComments */
344 * Returns TRUE if successfully parsed an OID
345 * otherwise returns FALSE. Puts the resulting OID Value in
346 * result if successful.
347 * The result Value's type is BASICVALUE_LINKEDOID
349 * Pseudo reg expr of the expected oid format:
352 *(defined_oid_elmt_name | digit+ | int_or_enum_val_ref |name"(" digit")")*
355 * Does not attempt to link/lookup referenced values
358 * for { ccitt foo (1) bar bell (bunt) 2 }
361 * arcnum is set to number from oid table (oid.c)
364 * - sets up a new integer value def "foo"
365 * defined as 1 *CHANGED -see changes*
366 * - makes oid valueref a value ref to foo (doesn't link it tho)
368 * - makes oid valueref a value ref to bar (doesn't link it tho)
370 * - sets up a new integer value def "bell" defined
371 * as a val ref to "bunt" *CHANGED -see changes*
372 * - makes oid valueref a value ref to bell (doesn't link it tho)
374 * -arc num is set to 2
377 * 93/05/03 - named arcs such as foo (1) or bell (bunt) handling
378 * changed. The names (foo and bell) are now ignored
379 * and *do not* define new integer values.
380 * The old way led to problems of defining some values
381 * more than once. E.g. in X.500 the { .. ds (5) }
382 * arc name is used everywhere - "ds INTEGER ::= 5"
383 * was defined multiple times as a result.
384 * Then the snacc error checker halted the compilation
385 * since the integer value "ds" was mulitply defined.
389 ParseOidValue
PARAMS ((mods
, m
, vd
, t
, vStr
, eof
, result
),
390 ModuleList
*mods _AND_
416 PRINT_ERR_LOC (m
, vd
);
417 fprintf (stderr
,"ERROR - expecting more data in OBJECT IDENTIFER value\n");
425 PRINT_ERR_LOC (m
, vd
);
426 fprintf (stderr
,"ERROR - OBJECT IDENTIFER values must begin with an \"{\".\n");
430 (*vStr
)++; /* skip opening { */
435 nextOid
= &parsedOid
;
437 while (**vStr
!= '}')
439 if (ParseIdentifier (vStr
, eof
, &id
))
442 * check for named number ident (num) or ident (valref)
443 * make a new value def with the name ident if is name
450 (*vStr
)++; /* skip opening ( */
453 arcNum
= NULL_OID_ARCNUM
;
455 * ident (num)/ident (valref) yields a new value definition
456 * ident. The oid then refences this new value def.
460 * first case check if of form
461 * { ... ident (valref) ... }
463 if (ParseIdentifier (vStr
, eof
, &id2
))
466 /* check if modname.val format */
470 if (!ParseIdentifier (vStr
, eof
, &id3
))
472 PRINT_ERR_LOC (m
, vd
);
473 fprintf (stderr
,"ERROR - missing a module name after the \"%s.\" value reference", id2
);
484 PRINT_ERR_LOC (m
, vd
);
485 fprintf (stderr
,"ERROR - missing a closing \")\", after the \"%s\" value reference.\n", id2
);
489 if (id3
!= NULL
) /* modname.val format */
491 SetupValue (&newVal
, BASICVALUE_IMPORTVALUEREF
,valLineNoG
);
492 newVal
->basicValue
->a
.importValueRef
=
493 (ValueRef
*)Malloc (sizeof (ValueRef
));
494 newVal
->basicValue
->a
.importValueRef
->valueName
= id2
;
495 newVal
->basicValue
->a
.importValueRef
->moduleName
= id3
;
497 AddPrivateImportElmt (m
, id2
, id3
, valLineNoG
);
502 SetupValue (&newVal
, BASICVALUE_LOCALVALUEREF
,valLineNoG
);
503 newVal
->basicValue
->a
.localValueRef
=
504 (ValueRef
*)Malloc (sizeof (ValueRef
));
505 newVal
->basicValue
->a
.localValueRef
->valueName
= id2
;
509 /* check this form { ... ident (2)...}*/
510 else if (ParseNum (vStr
, eof
, &num
))
518 PRINT_ERR_LOC (m
, vd
);
519 fprintf (stderr
,"ERROR - missing a closing \")\" after the \"%s (%s\".\n", id2
, num
);
527 else /* neither an ident or num after the "(" */
529 PRINT_ERR_LOC (m
, vd
);
530 fprintf (stderr
,"ERROR - expecting either a value reference or number after the \"(\".\n");
534 *nextOid
= (OID
*) Malloc (sizeof (OID
));
535 (*nextOid
)->valueRef
= newVal
;
536 (*nextOid
)->arcNum
= arcNum
;
537 nextOid
= &(*nextOid
)->next
;
539 } /* end of ident (num) and ident (ident) form */
541 else /* value ref: { ... ident .... } */
543 *nextOid
= (OID
*) Malloc (sizeof (OID
));
544 (*nextOid
)->arcNum
= NULL_OID_ARCNUM
;
547 * check if special defined oid elmt name
548 * like joint-iso-ccitt, iso, standard etc.
551 arcNum
= OidArcNameToNum (id
);
554 (*nextOid
)->arcNum
= arcNum
;
556 else /* value reference */
558 SetupValue (&newVal
, BASICVALUE_LOCALVALUEREF
,valLineNoG
);
559 newVal
->basicValue
->a
.localValueRef
=
560 (ValueRef
*)Malloc (sizeof (ValueRef
));
561 newVal
->basicValue
->a
.localValueRef
->valueName
= id
;
563 (*nextOid
)->valueRef
= newVal
;
565 nextOid
= &(*nextOid
)->next
;
568 else if (ParseNum (vStr
, eof
, &num
)) /* { .. 2 .. } */
570 *nextOid
= (OID
*) Malloc (sizeof (OID
));
571 (*nextOid
)->arcNum
= atoi (num
);
572 nextOid
= &(*nextOid
)->next
;
577 PRINT_ERR_LOC (m
, vd
);
578 fprintf (stderr
,"ERROR - bady formed arc number\n");
585 (*vStr
)++; /* move over closing } */
587 SetupValue (&oidVal
, BASICVALUE_LINKEDOID
, valLineNoG
);
588 oidVal
->basicValue
->a
.linkedOid
= parsedOid
;
595 SkipWht
PARAMS ((vStr
, eof
),
602 case '\n': /* newline */
603 case '\f': /* form feed ?*/
604 case '\v': /* vertical tab ?*/
605 case '\r': valLineNoG
++; /* carriage return */
607 case ' ': /* space */
608 case '\007': /* bell? */
609 case '\b': /* back spc */
620 * advances the vStr over ASN.1 identifier, returns a copy
621 * in result, and returns TRUE. otherwise returns FALSE
623 * ASN.1 identifier is: lowercase letter followed by a
624 * string of letters (upper and lower case allowed), digtits, or single
625 * hyphens. last char cannot be a hyphen.
628 ParseIdentifier
PARAMS ((vStr
, eof
, result
),
643 if (!islower (**vStr
))
650 /* allow letters, digits and single hyphens */
651 if ((isalpha (**vStr
)) || isdigit (**vStr
) ||
652 ((**vStr
== '-') && !(*(*vStr
- 1) == '-')))
655 break; /* exit for loop */
659 /* don't allow hyphens on the end */
660 if (*(*vStr
- 1) == '-')
664 *result
= Malloc (len
+1);
665 strncpy (*result
, start
, len
);
666 (*result
)[len
] = '\0'; /* null terminate */
669 } /* ParseIdentifier */
674 * advances the vStr over ASN.1 number, returns a
675 * null terminated ascii copy of the number
676 * in result, and returns TRUE. otherwise returns FALSE
679 ParseNum
PARAMS ((vStr
, eof
, result
),
697 if (isdigit (**vStr
))
700 break; /* exit for loop */
707 *result
= Malloc (len
+1);
708 strncpy (*result
, start
, len
);
709 (*result
)[len
] = '\0'; /* null terminate */
715 * adds a new value def to the vdl. Used
716 * when parsing oid's that defined arc values
717 * eg { 1 2 foo (3) } --> defined foo INTEGER ::= 3
718 * (should be foo INTEGER (0..MAX) ::= 3)
721 AddNewValueDef
PARAMS ((vdl
, name
, value
),
722 ValueDefList
*vdl _AND_
729 vd
= (ValueDef
*)Malloc (sizeof (ValueDef
));
730 vd
->definedName
= name
;
732 tmpVd
= (ValueDef
**)AsnListAppend (vdl
);
734 } /* AddNewValueDef */