]> git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/compiler/back-ends/idl-gen/types.c
fffb4b4748edcd8647b8b5a8a4a044ac336cc634
[apple/security.git] / SecuritySNACCRuntime / compiler / back-ends / idl-gen / types.c
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /*
20 * compiler/back_ends/idl_gen/types.c - fills in IDL type information
21 *
22 * MS 91/92
23 * Copyright (C) 1991, 1992 Michael Sample
24 * and the University of British Columbia
25 *
26 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation; either version 2 of the License, or
29 * (at your option) any later version.
30 *
31 * $Header: /cvs/root/Security/SecuritySNACCRuntime/compiler/back-ends/idl-gen/Attic/types.c,v 1.1.1.1 2001/05/18 23:14:09 mb Exp $
32 * $Log: types.c,v $
33 * Revision 1.1.1.1 2001/05/18 23:14:09 mb
34 * Move from private repository to open source repository
35 *
36 * Revision 1.2 2001/05/05 00:59:29 rmurphy
37 * Adding darwin license headers
38 *
39 * Revision 1.1.1.1 1999/03/16 18:06:45 aram
40 * Originals from SMIME Free Library.
41 *
42 * Revision 1.1 1997/01/01 20:25:40 rj
43 * first draft
44 *
45 */
46
47 #include <ctype.h>
48 #include <stdio.h>
49
50 #include "asn-incl.h"
51 #include "define.h"
52 #include "asn1module.h"
53 #include "mem.h"
54 #include "snacc-util.h"
55 #include "str-util.h"
56 #include "rules.h"
57 #include "c++-gen/kwd.h"
58 #include "types.h"
59
60 extern Module *usefulTypeModG;
61
62 static DefinedObj *definedNamesG;
63
64 /* unexported prototypes */
65
66 void FillIDLTypeDefInfo PROTO ((IDLRules *r, Module *m, TypeDef *td));
67
68 static void FillIDLFieldNames PROTO ((IDLRules *r, NamedTypeList *firstSibling));
69
70 static void FillIDLTypeRefInfo PROTO ((IDLRules *r, Module *m, TypeDef *td, Type *parent, Type *t));
71
72 static void FillIDLStructElmts PROTO ((IDLRules *r, Module *m, TypeDef *td, Type *parent, NamedTypeList *t));
73
74 static void FillIDLChoiceElmts PROTO ((IDLRules *r, Module *m, TypeDef *td, Type *parent, NamedTypeList *first));
75
76 static int IsIDLPtr PROTO ((IDLRules *r, TypeDef *td, Type *parent, Type *t));
77
78 void FillIDLTDIDefaults PROTO ((IDLRules *r, IDLTDI *ctdi, TypeDef *td));
79
80
81 /*
82 * allocates and fills all the idlTypeInfos
83 * in the type trees for every module in the list
84 */
85 void
86 FillIDLTypeInfo PARAMS ((r, modList),
87 IDLRules *r _AND_
88 ModuleList *modList)
89 {
90 TypeDef *td;
91 Module *m;
92
93 /*
94 * go through each module's type defs and fill
95 * in the C type and enc/dec routines etc
96 */
97 definedNamesG = NULL;
98
99 /* do useful types first */
100 if (usefulTypeModG != NULL)
101 {
102 FOR_EACH_LIST_ELMT (td, usefulTypeModG->typeDefs)
103 FillIDLTypeDefInfo (r, usefulTypeModG, td);
104 }
105
106 FOR_EACH_LIST_ELMT (m, modList)
107 {
108 FOR_EACH_LIST_ELMT (td, m->typeDefs)
109 FillIDLTypeDefInfo (r, m, td);
110 }
111
112 /*
113 * now that type def info is filled in
114 * set up set/seq/list/choice elements that ref
115 * those definitions
116 */
117
118 /* do useful types first */
119 if (usefulTypeModG != NULL)
120 {
121 FOR_EACH_LIST_ELMT (td, usefulTypeModG->typeDefs)
122 FillIDLTypeRefInfo (r, usefulTypeModG, td, NULL, td->type);
123 }
124
125 FOR_EACH_LIST_ELMT (m, modList)
126 {
127 FOR_EACH_LIST_ELMT (td, m->typeDefs)
128 FillIDLTypeRefInfo (r, m, td, NULL, td->type);
129 }
130
131 /*
132 * modules compiled together (ie one call to snacc with
133 * multiple args) likely to be C compiled together so
134 * need a unique routines/types/defines/enum values
135 * since assuming they share same name space.
136 * All Typedefs, union, struct & enum Tags, and defined values
137 * (enum consts), #define names
138 * are assumed to share the same name space
139 */
140
141 /* done with checking for name conflicts */
142 FreeDefinedObjs (&definedNamesG);
143
144 } /* FillIDLTypeInfo */
145
146
147 /*
148 * allocates and fills structure holding C type definition information
149 * fo the given ASN.1 type definition. Does not fill CTRI for contained
150 * types etc.
151 */
152 void
153 FillIDLTypeDefInfo PARAMS ((r, m, td),
154 IDLRules *r _AND_
155 Module *m _AND_
156 TypeDef *td)
157 {
158 int digit;
159 int len;
160 char *tmpName;
161 IDLTDI *idltdi;
162
163 /*
164 * if IDLTDI is present this type def has already been 'filled'
165 */
166 if (td->idlTypeDefInfo != NULL)
167 return;
168
169
170 idltdi = MT (IDLTDI);
171 td->idlTypeDefInfo = idltdi;
172
173 /* get default type def attributes from table for type on rhs of ::= */
174
175 FillIDLTDIDefaults (r, idltdi, td);
176
177
178 /*
179 * if defined by a ref to another type definition fill in that type
180 * def's IDLTDI so can inherit (actully completly replace default
181 * attributes) from it
182 */
183 if ((td->type->basicType->choiceId == BASICTYPE_LOCALTYPEREF) ||
184 (td->type->basicType->choiceId == BASICTYPE_IMPORTTYPEREF))
185 {
186 /*
187 * Fill in IDLTDI for defining type if nec.
188 * this works for importTypeRef as well since both a.localTypeRef
189 * and a.importTypeRef are of type TypeRef
190 */
191 FillIDLTypeDefInfo (r, td->type->basicType->a.localTypeRef->module, td->type->basicType->a.localTypeRef->link);
192
193 tmpName = idltdi->typeName; /* save typeName */
194 /* copy all type def info and restore name related stuff - hack*/
195 *idltdi = *td->type->basicType->a.localTypeRef->link->idlTypeDefInfo;
196 idltdi->typeName = tmpName; /* restore typeName */
197 }
198
199
200 /*
201 * check for any "--snacc" attributes that overide the current
202 * idltdi fields
203 * UNDEFINED FOR C++
204 ParseTypeDefAttribs (idltdi, td->attrList);
205 */
206
207 } /* FillIDLTypeDefInfo */
208
209
210 static void
211 FillIDLTypeRefInfo PARAMS ((r, m, td, parent, t),
212 IDLRules *r _AND_
213 Module *m _AND_
214 TypeDef *td _AND_
215 Type *parent _AND_
216 Type *t)
217 {
218 IDLTRI *idltri;
219 IDLTDI *tmpidltdi;
220 ValueDef *namedElmt;
221 CNamedElmt *cne;
222 CNamedElmt **cneHndl;
223 char *elmtName;
224 char *listName;
225 char *choiceName;
226 char *unionName;
227 Type *tmpT;
228 int len, digit;
229 enum BasicTypeChoiceId
230 basicTypeId;
231
232 /*
233 * you must check for cycles yourself before calling this
234 */
235 if (t->idlTypeRefInfo == NULL)
236 {
237 idltri = MT (IDLTRI);
238 t->idlTypeRefInfo = idltri;
239 }
240 else
241 idltri = t->idlTypeRefInfo;
242
243 basicTypeId = t->basicType->choiceId;
244
245 tmpidltdi = &r->typeConvTbl[basicTypeId];
246
247 /* get base type def info from the conversion table in the rules */
248 idltri->isEnc = tmpidltdi->isEnc;
249 idltri->typeName = tmpidltdi->typeName;
250 idltri->optTestRoutineName = tmpidltdi->optTestRoutineName;
251
252
253 /*
254 * convert named elmts to IDL names.
255 * check for name conflict with other defined Types/Names/Values
256 */
257 if ((basicTypeId == BASICTYPE_INTEGER || basicTypeId == BASICTYPE_ENUMERATED || basicTypeId == BASICTYPE_BITSTRING) && !(LIST_EMPTY (t->basicType->a.integer)))
258 {
259 idltri->namedElmts = AsnListNew (sizeof (void *));
260 FOR_EACH_LIST_ELMT (namedElmt, t->basicType->a.integer)
261 {
262 cneHndl = (CNamedElmt **)AsnListAppend (idltri->namedElmts);
263 cne = *cneHndl = MT (CNamedElmt);
264 elmtName = Asn1ValueName2CValueName (namedElmt->definedName);
265 #if 0
266 if (basicTypeId == BASICTYPE_BITSTRING)
267 #endif
268 {
269 len = strlen (elmtName);
270 cne->name = Malloc (len + 1 + r->maxDigitsToAppend);
271 strcpy (cne->name, elmtName);
272 }
273 #if 0
274 else
275 {
276 len = strlen (idltri->typeName) + 7 + strlen (elmtName);
277 cne->name = Malloc (len + 1 + r->maxDigitsToAppend);
278 strcpy (cne->name, idltri->typeName);
279 strcat (cne->name, "Choice_");
280 strcat (cne->name, elmtName);
281 }
282 #endif
283 Free (elmtName); /* not very efficient */
284
285 if (namedElmt->value->basicValue->choiceId == BASICVALUE_INTEGER)
286 cne->value = namedElmt->value->basicValue->a.integer;
287 else
288 {
289 fprintf (stderr, "Warning: unlinked defined value. Using -9999999\n");
290 cne->value = -9999999;
291 }
292
293 if (r->capitalizeNamedElmts)
294 Str2UCase (cne->name, len);
295
296 /*
297 * append digits if enum value name is a keyword
298 */
299 MakeCxxStrUnique (definedNamesG, cne->name, r->maxDigitsToAppend, 1);
300 DefineObj (&definedNamesG, cne->name);
301 }
302 }
303
304 /* fill in rest of type info depending on the type */
305 switch (basicTypeId)
306 {
307 case BASICTYPE_BOOLEAN: /* library types */
308 case BASICTYPE_INTEGER:
309 case BASICTYPE_BITSTRING:
310 case BASICTYPE_OCTETSTRING:
311 case BASICTYPE_NULL:
312 case BASICTYPE_OID:
313 case BASICTYPE_REAL:
314 case BASICTYPE_ENUMERATED:
315 /* don't need to do anything else */
316 break;
317
318
319 case BASICTYPE_SEQUENCEOF: /* list types */
320 case BASICTYPE_SETOF:
321 /* fill in component type */
322 FillIDLTypeRefInfo (r, m, td, t, t->basicType->a.setOf);
323 break;
324
325 case BASICTYPE_IMPORTTYPEREF: /* type references */
326 case BASICTYPE_LOCALTYPEREF:
327 /*
328 * grab class name from link (link is the def of the
329 * the ref'd type)
330 */
331 if (t->basicType->a.localTypeRef->link != NULL)
332 {
333 /* inherit attributes from referenced type */
334 tmpidltdi= t->basicType->a.localTypeRef->link->idlTypeDefInfo;
335 idltri->typeName = tmpidltdi->typeName;
336 idltri->isEnc = tmpidltdi->isEnc;
337 idltri->optTestRoutineName = tmpidltdi->optTestRoutineName;
338 }
339
340 break;
341
342 case BASICTYPE_ANYDEFINEDBY: /* ANY types */
343 break; /* these are handled now */
344
345 case BASICTYPE_ANY:
346 #if 0
347 PrintErrLoc (m->asn1SrcFileName, t->lineNo);
348 fprintf (stderr, "Warning - generated code for the \"ANY\" type in type \"%s\" will need modification by YOU.", td->definedName);
349 fprintf (stderr, " The source files will have a \"/* ANY - Fix Me! */\" comment before related code.\n\n");
350 #endif
351
352 break;
353
354 case BASICTYPE_CHOICE:
355 /*
356 * must fill field names BEFORE filling choice elmts
357 * (allows better naming for choice ids)
358 */
359 FillIDLFieldNames (r, t->basicType->a.choice);
360 FillIDLChoiceElmts (r, m, td, t, t->basicType->a.choice);
361 break;
362
363 case BASICTYPE_SET:
364 case BASICTYPE_SEQUENCE:
365 FillIDLStructElmts (r, m, td, t, t->basicType->a.set);
366 FillIDLFieldNames (r, t->basicType->a.set);
367 break;
368
369 case BASICTYPE_COMPONENTSOF:
370 case BASICTYPE_SELECTION:
371 fprintf (stderr, "Compiler error - COMPONENTS OF or SELECTION type slipped through normalizing phase.\n");
372 break;
373
374 case BASICTYPE_UNKNOWN:
375 case BASICTYPE_MACRODEF:
376 case BASICTYPE_MACROTYPE:
377 /* do nothing */
378 break;
379
380 }
381
382 /*
383 * figure out whether this is a ptr based on the enclosing
384 * type (if any) and optionality/default
385 */
386 idltri->isPtr = IsIDLPtr (r, td, parent, t);
387
388 /* let user overide any defaults with the --snacc attributes */
389 /* undefined for C++ ParseTypeRefAttribs (ctri, t->attrList); */
390
391
392 } /* FillIDLTypeRefInfo */
393
394
395
396 static void
397 FillIDLStructElmts PARAMS ((r, m, td, parent, elmts),
398 IDLRules *r _AND_
399 Module *m _AND_
400 TypeDef *td _AND_
401 Type *parent _AND_
402 NamedTypeList *elmts)
403 {
404 NamedType *et;
405
406 FOR_EACH_LIST_ELMT (et, elmts)
407 {
408 FillIDLTypeRefInfo (r, m, td, parent, et->type);
409 }
410
411 } /* FillIDLStructElmts */
412
413
414
415 /*
416 * Figures out non-conflicting enum names for the
417 * choice id's
418 */
419 static void
420 FillIDLChoiceElmts PARAMS ((r, m, td, parent, elmts),
421 IDLRules *r _AND_
422 Module *m _AND_
423 TypeDef *td _AND_
424 Type *parent _AND_
425 NamedTypeList *elmts)
426 {
427 NamedType *et;
428 int idCount = 0;
429 IDLTRI *idltri;
430 int len;
431
432 /*
433 * fill in type info for elmt types first
434 */
435 FOR_EACH_LIST_ELMT (et, elmts)
436 FillIDLTypeRefInfo (r, m, td, parent, et->type);
437
438 /*
439 * set choiceId Symbol & value
440 * eg
441 * Car ::= CHOICE { enum CarChoice {
442 * chev ChevCar, carChoice_chev,
443 * ford FordCar, carChoice_ford,
444 * toyota ToyotaCar carChoice_toyota
445 * } };
446 * union Car switch (CarChoice) {
447 * ChevCar *chev;
448 * FordCar *ford;
449 * ToyotaCar *toyota; };
450 * };
451 * NOTE that the union is anonymous
452 */
453 FOR_EACH_LIST_ELMT (et, elmts)
454 {
455 idltri = et->type->idlTypeRefInfo;
456
457 if (idltri == NULL)
458 continue; /* wierd type */
459
460 idltri->choiceIdValue = idCount++;
461
462 len = strlen (td->idlTypeDefInfo->typeName) + strlen (idltri->fieldName);
463 idltri->choiceIdSymbol = Malloc (len + 6 + 1);
464 strcpy (idltri->choiceIdSymbol, td->idlTypeDefInfo->typeName);
465 strcat (idltri->choiceIdSymbol, "Choice_");
466 strcat (idltri->choiceIdSymbol, idltri->fieldName);
467
468 if (r->capitalizeNamedElmts)
469 Str2UCase (idltri->choiceIdSymbol, len);
470
471 Str2LCase (idltri->choiceIdSymbol, 1);
472 }
473
474 } /* FillIDLChoiceElmts */
475
476
477 /*
478 * takes a list of "sibling" (eg same level in a structure)
479 * ElmtTypes and fills sets up the c field names in
480 * the IDLTRI struct
481 */
482 static void
483 FillIDLFieldNames PARAMS ((r, elmts),
484 IDLRules *r _AND_
485 NamedTypeList *elmts)
486 {
487 NamedType *et;
488 IDLTRI *idltri;
489 DefinedObj *fieldNames;
490 int len, num, digit, i, tmpLen;
491 char *tmpName;
492 char *asn1FieldName;
493 char *cFieldName;
494
495 /*
496 * Initialize fieldname data
497 * allocate (if nec) and fill in CTRI fieldname if poss
498 * from asn1 field name. leave blank otherwise
499 */
500 fieldNames = NewObjList();
501 FOR_EACH_LIST_ELMT (et, elmts)
502 {
503 idltri = et->type->idlTypeRefInfo;
504 if (idltri == NULL)
505 {
506 idltri = MT (IDLTRI);
507 et->type->idlTypeRefInfo = idltri;
508 }
509 if (et->fieldName != NULL)
510 {
511 /*
512 * can assume that the field names are
513 * distinct because they have passed the
514 * error checking step.
515 * However, still call MakeCxxStrUnique
516 * to change any field names that
517 * conflict with C++ keywords
518 */
519 asn1FieldName = et->fieldName;
520 tmpName = Asn1FieldName2CFieldName (asn1FieldName);
521 idltri->fieldName = Malloc (strlen (tmpName) + 1 + r->maxDigitsToAppend);
522 strcpy (idltri->fieldName, tmpName);
523 Free (tmpName);
524
525 /* old idltri->fieldName = Asn1FieldName2CFieldName (asn1FieldName); */
526
527 MakeCxxStrUnique (fieldNames, idltri->fieldName, r->maxDigitsToAppend, 1);
528 DefineObj (&fieldNames, idltri->fieldName);
529 }
530 }
531
532
533 FOR_EACH_LIST_ELMT (et, elmts)
534 {
535 idltri = et->type->idlTypeRefInfo;
536
537 /*
538 * generate field names for those without them
539 */
540 if (idltri->fieldName == NULL)
541 {
542 if ((et->type->basicType->choiceId == BASICTYPE_LOCALTYPEREF) ||
543 (et->type->basicType->choiceId == BASICTYPE_IMPORTTYPEREF))
544 {
545 /*
546 * take ref'd type name as field name
547 * convert first let to lower case
548 */
549 tmpName = et->type->basicType->a.localTypeRef->link->idlTypeDefInfo->typeName;
550 tmpName = Asn1TypeName2CTypeName (tmpName);
551 cFieldName = Malloc (strlen (tmpName) + r->maxDigitsToAppend +1);
552 strcpy (cFieldName, tmpName);
553 Free (tmpName);
554 if (isupper (cFieldName[0]))
555 cFieldName[0] = tolower (cFieldName[0]);
556 }
557 else
558 {
559 /*
560 * get default field name for this type
561 */
562 tmpName = r->typeConvTbl[et->type->basicType->choiceId].defaultFieldName;
563 cFieldName = Malloc (strlen (tmpName) + r->maxDigitsToAppend +1);
564 strcpy (cFieldName, tmpName);
565
566 if (isupper (cFieldName[0]))
567 cFieldName[0] = tolower (cFieldName[0]);
568 }
569
570
571 len = strlen (cFieldName);
572
573 /*
574 * try to use just the type name (with lower case first char).
575 * if that is already used in this type or a C++ keyword,
576 * append ascii digits to field name until unique
577 * in this type
578 */
579 MakeCxxStrUnique (fieldNames, cFieldName, r->maxDigitsToAppend, 1);
580 DefineObj (&fieldNames, cFieldName);
581 idltri->fieldName = cFieldName;
582 }
583 }
584 FreeDefinedObjs (&fieldNames);
585 } /* FillIDLFieldNames */
586
587
588
589 /*
590 * returns true if this c type for this type should be
591 * be ref'd as a ptr
592 */
593 static int
594 IsIDLPtr PARAMS ((r, td, parent, t),
595 IDLRules *r _AND_
596 TypeDef *td _AND_
597 Type *parent _AND_
598 Type *t)
599 {
600 IDLTDI *idltdi;
601 int retVal = FALSE;
602
603 /*
604 * inherit ptr attriubutes from ref'd type if any
605 * otherwise grab lib c type def from the IDLRules
606 */
607 if ((t->basicType->choiceId == BASICTYPE_LOCALTYPEREF) ||
608 (t->basicType->choiceId == BASICTYPE_IMPORTTYPEREF))
609 {
610 idltdi = t->basicType->a.localTypeRef->link->idlTypeDefInfo;
611 }
612 else
613 idltdi = &r->typeConvTbl[GetBuiltinType (t)];
614
615 /* no parent means t is the root of a typedef */
616 if ((parent == NULL) && (idltdi->isPtrForTypeDef))
617 retVal = TRUE;
618
619 else if ((parent != NULL) &&
620 ((parent->basicType->choiceId == BASICTYPE_SET) ||
621 (parent->basicType->choiceId == BASICTYPE_SEQUENCE)) &&
622 (idltdi->isPtrInSetAndSeq))
623 retVal = TRUE;
624
625 else if ((parent != NULL) &&
626 ((parent->basicType->choiceId == BASICTYPE_SETOF) ||
627 (parent->basicType->choiceId == BASICTYPE_SEQUENCEOF)) &&
628 (idltdi->isPtrInList))
629 retVal = TRUE;
630
631 else if ((parent != NULL) &&
632 (parent->basicType->choiceId == BASICTYPE_CHOICE) &&
633 (idltdi->isPtrInChoice))
634 retVal = TRUE;
635
636 else if (((t->optional) || (t->defaultVal != NULL)) && (idltdi->isPtrForOpt))
637 retVal = TRUE;
638
639 return retVal;
640 } /* IsIDLPtr */
641
642
643
644 /* fill given idltdi with defaults from table for given typedef */
645 void
646 FillIDLTDIDefaults PARAMS ((r, idltdi, td),
647 IDLRules *r _AND_
648 IDLTDI *idltdi _AND_
649 TypeDef *td)
650 {
651 IDLTDI *tblidltdi;
652 int typeIndex;
653 char *tmpName;
654
655 typeIndex = GetBuiltinType (td->type);
656
657 if (typeIndex < 0)
658 return;
659
660 tblidltdi = &r->typeConvTbl[typeIndex];
661
662 memcpy (idltdi, tblidltdi, sizeof (IDLTDI));
663
664 /* make sure class name is unique wrt to previously defined classes */
665 tmpName = Asn1TypeName2CTypeName (td->definedName);
666 idltdi->typeName = Malloc (strlen (tmpName) + 2 + r->maxDigitsToAppend +1);
667 strcpy (idltdi->typeName, tmpName);
668 if (tblidltdi->asn1TypeId != BASICTYPE_CHOICE)
669 strcat (idltdi->typeName, "_T");
670 Free (tmpName);
671
672 MakeCxxStrUnique (definedNamesG, idltdi->typeName, r->maxDigitsToAppend, 1);
673 DefineObj (&definedNamesG, idltdi->typeName);
674
675 } /* FillIDLTDIDefaults */