1 mike 1.1 %{
2
3 #include "config.h"
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "config.h"
8 #include "buffer.h"
9 #include "types.h"
10 #include "state.h"
11 #include "ptrarray.h"
12
13 #define ARRAYOF(TYPE) ((MI_Uint32)TYPE | (MI_Uint32)MI_ARRAY_BIT)
14
15 extern int yylex();
16 extern int openIncludeFile(const char* path);
17
18 %}
19
20 %union
21 {
22 mike 1.1 MI_Boolean boolean;
23 MI_Sint64 integer;
24 MI_Real64 real;
25 MI_Char16 character;
26 char* string;
27 char* identifier;
28 char* dollarIdentifier;
29 MI_Type type;
30 MI_PropertyDecl* property;
31 MI_MethodDecl* methodDecl;
32 MI_ParameterDecl* parameter;
33 MOF_ParameterList parameterList;
34 MOF_FeatureList featureList;
35 MI_QualifierDecl* qualifierDeclaration;
36 MOF_ConstantValue constantValue;
37 MOF_Initializer initializer;
38 MI_Uint32 flags;
39 MI_Qualifier* qualifier;
40 MOF_QualifierList qualifierList;
41 MI_ClassDecl* classDeclaration;
42 MI_InstanceDecl* instanceDeclaration;
43 mike 1.1 }
44
45 %start mofSpecification
46
47 %token TOK_ERROR
48 %token TOK_BOOLEAN
49 %token TOK_SINT8
50 %token TOK_UINT8
51 %token TOK_SINT16
52 %token TOK_UINT16
53 %token TOK_SINT32
54 %token TOK_UINT32
55 %token TOK_SINT64
56 %token TOK_UINT64
57 %token TOK_REAL32
58 %token TOK_REAL64
59 %token TOK_DATETIME
60 %token TOK_CHAR16
61 %token TOK_STRING
62 %token TOK_BOOLEAN_VALUE
63 %token TOK_REF
64 mike 1.1 %token TOK_SCOPE
65 %token TOK_CLASS
66 %token TOK_ASSOCIATION
67 %token TOK_INDICATION
68 %token TOK_QUALIFIER
69 %token TOK_PROPERTY
70 %token TOK_REFERENCE
71 %token TOK_METHOD
72 %token TOK_PARAMETER
73 %token TOK_ANY
74 %token TOK_FLAVOR
75 %token TOK_ENABLEOVERRIDE
76 %token TOK_DISABLEOVERRIDE
77 %token TOK_RESTRICTED
78 %token TOK_TOSUBCLASS
79 %token TOK_TRANSLATABLE
80 %token TOK_INSTANCE
81 %token TOK_OF
82 %token TOK_AS
83 %token TOK_PRAGMA
84 %token TOK_SCHEMA
85 mike 1.1 %token TOK_INTEGER_VALUE
86 %token TOK_REAL_VALUE
87 %token TOK_STRING_VALUE
88 %token TOK_CHAR_VALUE
89 %token TOK_IDENT
90 %token TOK_ALIAS_IDENTIFIER
91 %token TOK_NULL
92
93 %type <string> stringValue
94 %type <string> TOK_STRING_VALUE
95 %type <string> identifier
96 %type <string> objectRef
97 %type <integer> TOK_INTEGER_VALUE
98 %type <real> TOK_REAL_VALUE
99 %type <character> TOK_CHAR_VALUE
100 %type <boolean> TOK_BOOLEAN_VALUE
101 %type <string> TOK_IDENT
102 %type <string> TOK_ALIAS_IDENTIFIER
103 %type <string> alias
104 %type <constantValue> constantValue
105 %type <type> dataType
106 mike 1.1 %type <property> propertyDeclaration
107 %type <parameter> parameter
108 %type <parameterList> parameterList
109 %type <property> referenceDeclaration
110 %type <methodDecl> methodDeclaration
111 %type <featureList> classFeatureList
112 %type <featureList> classBody
113 %type <featureList> instanceBody
114 %type <qualifierDeclaration> qualifierDeclaration
115 %type <qualifierDeclaration> qualifierType
116 %type <integer> subscript
117 %type <initializer> initializer
118 %type <initializer> arrayInitializer
119 %type <initializer> arrayInitializerList
120 %type <flags> scope
121 %type <flags> scopeList
122 %type <flags> scopeExpr
123 %type <flags> flavor
124 %type <flags> flavorList
125 %type <flags> flavorExpr
126 %type <qualifier> qualifier
127 mike 1.1 %type <qualifierList> qualifierList
128 %type <qualifierList> qualifierExpr
129 %type <initializer> qualifierParameter
130 %type <classDeclaration> classDeclaration
131 %type <instanceDeclaration> instanceDeclaration
132 %type <property> valueInitializer
133 %type <featureList> valueInitializerList
134
135 %%
136
137 mofSpecification
138 : mofProduction
139 {
140 }
141 | mofSpecification mofProduction
142 {
143 }
144 | TOK_ERROR
145 {
146 YYABORT;
147 }
148 mike 1.1
149 mofProduction
150 : compilerDirective
151 {
152 }
153 | classDeclaration
154 {
155 /* [TODO: validate the class here] */
156 $1->flags = MI_FLAG_CLASS;
157 $1->flags |= GetQualFlags($1->qualifiers, $1->numQualifiers);
158 if (FinalizeClass($1) != 0)
159 YYABORT;
160
161 AddClassDecl($1);
162
163 if (state.classDeclCallback)
164 (*state.classDeclCallback)($1, state.classDeclCallbackData);
165 }
166 | qualifierDeclaration
167 {
168 AddQualifierDeclaration($1);
169 mike 1.1
170 if (state.qualifierDeclCallback)
171 (*state.qualifierDeclCallback)($1, state.qualifierDeclCallbackData);
172 }
173 | instanceDeclaration
174 {
175 if (FinalizeInstance($1) != 0)
176 YYABORT;
177
178 AddInstanceDecl($1);
179
180 if (state.instanceDeclCallback)
181 (*state.instanceDeclCallback)($1, state.instanceDeclCallbackData);
182 }
183
184 compilerDirective
185 : TOK_PRAGMA TOK_IDENT '(' stringValue ')'
186 {
187 if (strcmp($2, "include") == 0)
188 {
189 if (openIncludeFile($4) != 0)
190 mike 1.1 YYABORT;
191 }
192 else if (strcmp($2, "instancelocale") == 0)
193 {
194 if (state.pragmaCallback)
195 (*state.pragmaCallback)($2, $4, state.pragmaCallbackData);
196 }
197 else if (strcmp($2, "locale") == 0)
198 {
199 if (state.pragmaCallback)
200 (*state.pragmaCallback)($2, $4, state.pragmaCallbackData);
201 }
202 else if (strcmp($2, "namespace") == 0)
203 {
204 if (state.pragmaCallback)
205 (*state.pragmaCallback)($2, $4, state.pragmaCallbackData);
206 }
207 else
208 {
209 yywarnf(ID_UNKNOWN_PRAGMA,
210 "warning: unknown pragma: %s=%s", $2, $4);
211 mike 1.1
212 if (state.pragmaCallback)
213 (*state.pragmaCallback)($2, $4, state.pragmaCallbackData);
214 }
215 }
216
217 classDeclaration
218 : TOK_CLASS identifier classBody
219 {
220 /* Check whether class already exists */
221 if (FindClassDecl($2))
222 {
223 yyerrorf(ID_CLASS_ALREADY_DEFINED,
224 "class already defined: \"%s\"", $2);
225 YYABORT;
226 }
227
228 $$ = CALLOC_T(MI_ClassDecl, 1);
229 $$->flags = MI_FLAG_CLASS;
230 $$->name = $2;
231 $$->properties = $3.propertySet.data;
232 mike 1.1 $$->numProperties = $3.propertySet.size;
233 $$->methods = $3.methodList.data;
234 $$->numMethods = $3.methodList.size;
235 }
236 | TOK_CLASS identifier ':' identifier classBody
237 {
238 const MI_ClassDecl* scd;
239
240 /* Check whether class already exists */
241 if (FindClassDecl($2))
242 {
243 yyerrorf(ID_CLASS_ALREADY_DEFINED,
244 "class already defined: \"%s\"", $2);
245 YYABORT;
246 }
247
248 /* Check whether superclass exists */
249 scd = FindClassDecl($4);
250
251 if (!scd)
252 {
253 mike 1.1 yyerrorf(ID_UNDEFINED_SUPERCLASS,
254 "super class of \"%s\" is undefined: \"%s\"", $2, $4);
255 YYABORT;
256 }
257
258 $$ = CALLOC_T(MI_ClassDecl, 1);
259 $$->flags = MI_FLAG_CLASS;
260 $$->name = $2;
261 $$->superClass = $4;
262 $$->superClassDecl = (MI_ClassDecl*)scd;
263 $$->properties = $5.propertySet.data;
264 $$->numProperties = $5.propertySet.size;
265 $$->methods = $5.methodList.data;
266 $$->numMethods = $5.methodList.size;
267 }
268 | qualifierExpr TOK_CLASS identifier classBody
269 {
270 /* Check qualifier scope */
271 if (CheckScope(MI_FLAG_CLASS, &$1) != 0)
272 YYABORT;
273
274 mike 1.1 /* Check whether class already exists */
275 if (FindClassDecl($3))
276 {
277 yyerrorf(ID_CLASS_ALREADY_DEFINED,
278 "class already defined: \"%s\"", $3);
279 YYABORT;
280 }
281
282 $$ = CALLOC_T(MI_ClassDecl, 1);
283 $$->flags = MI_FLAG_CLASS;
284 $$->name = $3;
285 $$->properties = $4.propertySet.data;
286 $$->numProperties = $4.propertySet.size;
287 $$->methods = $4.methodList.data;
288 $$->numMethods = $4.methodList.size;
289 $$->qualifiers = $1.data;
290 $$->numQualifiers = $1.size;
291 }
292 | qualifierExpr TOK_CLASS identifier ':' identifier classBody
293 {
294 const MI_ClassDecl* scd;
295 mike 1.1
296 /* Check qualifier scope */
297 if (CheckScope(MI_FLAG_CLASS, &$1) != 0)
298 YYABORT;
299
300 /* Check whether class already exists */
301 if (FindClassDecl($3))
302 {
303 yyerrorf(ID_CLASS_ALREADY_DEFINED,
304 "class already defined: \"%s\"", $3);
305 YYABORT;
306 }
307
308 /* Check whether superclass exists */
309 scd = FindClassDecl($5);
310
311 if (!scd)
312 {
313 yyerrorf(ID_UNDEFINED_SUPERCLASS,
314 "super class of \"%s\" is undefined: \"%s\"", $3, $5);
315 YYABORT;
316 mike 1.1 }
317
318 $$ = CALLOC_T(MI_ClassDecl, 1);
319 $$->flags = MI_FLAG_CLASS;
320 $$->name = $3;
321 $$->superClass = scd->name;
322 $$->superClassDecl = (MI_ClassDecl*)scd;
323 $$->properties = $6.propertySet.data;
324 $$->numProperties = $6.propertySet.size;
325 $$->methods = $6.methodList.data;
326 $$->numMethods = $6.methodList.size;
327 $$->qualifiers = $1.data;
328 $$->numQualifiers = $1.size;
329 }
330
331 classBody
332 : '{' classFeatureList '}' ';'
333 {
334 $$ = $2;
335 }
336 | '{' '}' ';'
337 mike 1.1 {
338 $$.propertySet.data = NULL;
339 $$.propertySet.size = 0;
340 $$.methodList.data = NULL;
341 $$.methodList.size = 0;
342 }
343
344 classFeatureList
345 : propertyDeclaration
346 {
347 if (CheckPropertyValueConstraints($1) != 0)
348 {
349 YYABORT;
350 }
351 $$.propertySet.data = NULL;
352 $$.propertySet.size = 0;
353 $$.methodList.data = NULL;
354 $$.methodList.size = 0;
355 $1->flags = MI_FLAG_PROPERTY;
356 $1->flags |= GetQualFlags($1->qualifiers, $1->numQualifiers);
357 PtrArray_Append((PtrArray*)&$$.propertySet, $1);
358 mike 1.1 }
359 | methodDeclaration
360 {
361 $$.propertySet.data = NULL;
362 $$.propertySet.size = 0;
363 $$.methodList.data = NULL;
364 $$.methodList.size = 0;
365 $1->flags = MI_FLAG_METHOD;
366 $1->flags |= GetQualFlags($1->qualifiers, $1->numQualifiers);
367 PtrArray_Append((PtrArray*)&$$.methodList, $1);
368 }
369 | referenceDeclaration
370 {
371 $$.propertySet.data = NULL;
372 $$.propertySet.size = 0;
373 $$.methodList.data = NULL;
374 $$.methodList.size = 0;
375 $1->flags = MI_FLAG_PROPERTY;
376 $1->flags |= GetQualFlags($1->qualifiers, $1->numQualifiers);
377 PtrArray_Append((PtrArray*)&$$.propertySet, $1);
378 }
379 mike 1.1 | classFeatureList propertyDeclaration
380 {
381 if (CheckPropertyValueConstraints($2) != 0)
382 {
383 YYABORT;
384 }
385
386 if (FindProperty(&$1.propertySet, $2->name))
387 {
388 yyerrorf(ID_CLASS_FEATURE_ALREADY_DEFINED,
389 "class feature already defined: \"%s\"", $2->name);
390 YYABORT;
391 }
392
393 $2->flags = MI_FLAG_PROPERTY;
394 $2->flags |= GetQualFlags($2->qualifiers, $2->numQualifiers);
395 PtrArray_Append((PtrArray*)&$$.propertySet, $2);
396 }
397 | classFeatureList methodDeclaration
398 {
399 if (FindMethod(&$1.methodList, $2->name))
400 mike 1.1 {
401 yyerrorf(ID_CLASS_FEATURE_ALREADY_DEFINED,
402 "class feature already defined: \"%s\"", $2->name);
403 YYABORT;
404 }
405
406 $2->flags = MI_FLAG_METHOD;
407 $2->flags |= GetQualFlags($2->qualifiers, $2->numQualifiers);
408 PtrArray_Append((PtrArray*)&$$.methodList, $2);
409 }
410 | classFeatureList referenceDeclaration
411 {
412 if (FindProperty(&$1.propertySet, $2->name))
413 {
414 yyerrorf(ID_CLASS_FEATURE_ALREADY_DEFINED,
415 "class feature already defined: \"%s\"", $2->name);
416 YYABORT;
417 }
418
419 $2->flags = MI_FLAG_PROPERTY;
420 $2->flags |= GetQualFlags($2->qualifiers, $2->numQualifiers);
421 mike 1.1 PtrArray_Append((PtrArray*)&$$.propertySet, $2);
422 }
423
424 qualifierExpr
425 : '[' qualifierList ']'
426 {
427 $$ = $2;
428 }
429
430 qualifierList
431 : qualifier
432 {
433 $$.data = NULL;
434 $$.size = 0;
435 PtrArray_Append((PtrArray*)&$$, $1);
436 }
437 | qualifierList ',' qualifier
438 {
439 if (FindQualifier(&$1, $3->name))
440 {
441 yyerrorf(ID_DUPLICATE_QUALIFIER,
442 mike 1.1 "duplicate qualifier: \"%s\"", $3->name);
443 YYABORT;
444 }
445
446 PtrArray_Append((PtrArray*)&$$, $3);
447 }
448
449 qualifier
450 : identifier
451 {
452 MI_Qualifier* q;
453 const MI_QualifierDecl* qd;
454
455 qd = FindQualifierDeclaration($1);
456
457 if (!qd)
458 {
459 yyerrorf(ID_UNDEFINED_QUALIFIER, "undefined qualifier: \"%s\"", $1);
460 YYABORT;
461 }
462
463 mike 1.1 if (qd->type != MI_BOOLEAN)
464 {
465 yyerrorf(ID_MISSING_QUALIFIER_INITIALIZER,
466 "qualifier is missing initializer: \"%s\"", $1);
467 YYABORT;
468 }
469
470
471 q = CALLOC_T(MI_Qualifier, 1);
472 q->name = qd->name; /* use casing of qualifier declaration name */
473 q->type = qd->type;
474 q->flavor = qd->flavor;
475 q->value = NewTrueValue();
476 $$ = q;
477 }
478 | identifier qualifierParameter
479 {
480 MI_Qualifier* q;
481 const MI_QualifierDecl* qd;
482 void* value;
483
484 mike 1.1 qd = FindQualifierDeclaration($1);
485
486 if (!qd)
487 {
488 yyerrorf(ID_UNDEFINED_QUALIFIER, "undefined qualifier: \"%s\"", $1);
489 YYABORT;
490 }
491
492 if (InitializerToValue(&$2, qd->type, &value) != 0)
493 {
494 yyerrorf(ID_INVALID_QUALIFIER_INITIALIZER,
495 "invalid initializer for qualifer: \"%s\"", $1);
496 YYABORT;
497 }
498
499 q = CALLOC_T(MI_Qualifier, 1);
500 q->name = qd->name; /* use casing of qualifier declaration name */
501 q->type = qd->type;
502 q->flavor = qd->flavor;
503 q->value = value;
504 $$ = q;
505 mike 1.1 }
506 | identifier ':' flavor
507 {
508 MI_Qualifier* q;
509 const MI_QualifierDecl* qd;
510
511 qd = FindQualifierDeclaration($1);
512
513 if (!qd)
514 {
515 yyerrorf(ID_UNDEFINED_QUALIFIER, "undefined qualifier: \"%s\"", $1);
516 YYABORT;
517 }
518
519 if (qd->type != MI_BOOLEAN)
520 {
521 yyerrorf(ID_MISSING_QUALIFIER_INITIALIZER,
522 "qualifier is missing initializer: \"%s\"", $1);
523 YYABORT;
524 }
525
526 mike 1.1 q = CALLOC_T(MI_Qualifier, 1);
527 q->name = qd->name; /* use casing of qualifier declaration name */
528 q->type = qd->type;
529 q->flavor = PropagateFlavors($3, qd->flavor);
530 q->value = NewTrueValue();
531 $$ = q;
532 }
533 | identifier qualifierParameter ':' flavor
534 {
535 MI_Qualifier* q;
536 const MI_QualifierDecl* qd;
537 void* value;
538
539 qd = FindQualifierDeclaration($1);
540
541 if (!qd)
542 {
543 yyerrorf(ID_UNDEFINED_QUALIFIER, "undefined qualifier: \"%s\"", $1);
544 YYABORT;
545 }
546
547 mike 1.1 if (InitializerToValue(&$2, qd->type, &value) != 0)
548 {
549 yyerrorf(ID_INVALID_QUALIFIER_INITIALIZER,
550 "invalid initializer for qualifer: \"%s\"", $1);
551 YYABORT;
552 }
553
554 q = CALLOC_T(MI_Qualifier, 1);
555 q->name = qd->name; /* use casing of qualifier declaration name */
556 q->type = qd->type;
557 q->value = value;
558 q->flavor = PropagateFlavors($4, qd->flavor);
559 $$ = q;
560 }
561
562 qualifierParameter
563 : '(' constantValue ')'
564 {
565 memset(&$$, 0, sizeof($$));
566 $$.data = CALLOC_T(MOF_ConstantValue, 1);
567 $$.data[0] = $2;
568 mike 1.1 $$.size = 1;
569 }
570 | arrayInitializer
571 {
572 $$ = $1;
573 }
574
575 flavorList
576 : flavor
577 {
578 $$ = $1;
579 }
580 | flavorList ',' flavor
581 {
582 $$ |= $3;
583 }
584
585 flavor
586 : TOK_ENABLEOVERRIDE
587 {
588 $$ = MI_FLAG_ENABLEOVERRIDE;
589 mike 1.1 }
590 | TOK_DISABLEOVERRIDE
591 {
592 $$ = MI_FLAG_DISABLEOVERRIDE;
593 }
594 | TOK_RESTRICTED
595 {
596 $$ = MI_FLAG_RESTRICTED;
597 }
598 | TOK_TOSUBCLASS
599 {
600 $$ = MI_FLAG_TOSUBCLASS;
601 }
602 | TOK_TRANSLATABLE
603 {
604 $$ = MI_FLAG_TRANSLATABLE;
605 }
606
607 propertyDeclaration
608 : dataType identifier ';'
609 {
610 mike 1.1 $$ = CALLOC_T(MI_PropertyDecl, 1);
611 $$->name = $2;
612 $$->type = $1;
613 }
614 | qualifierExpr dataType identifier ';'
615 {
616 /* Check qualifier scope */
617 if (CheckScope(MI_FLAG_PROPERTY, &$1) != 0)
618 YYABORT;
619
620 $$ = CALLOC_T(MI_PropertyDecl, 1);
621 $$->name = $3;
622 $$->type = $2;
623 $$->qualifiers = $1.data;
624 $$->numQualifiers = $1.size;
625 }
626 | dataType identifier subscript ';'
627 {
628 $$ = CALLOC_T(MI_PropertyDecl, 1);
629 $$->name = $2;
630 $$->type = ARRAYOF($1);
631 mike 1.1 $$->subscript = (MI_Uint32)$3;
632 }
633 | qualifierExpr dataType identifier subscript ';'
634 {
635 /* Check qualifier scope */
636 if (CheckScope(MI_FLAG_PROPERTY, &$1) != 0)
637 YYABORT;
638
639 $$ = CALLOC_T(MI_PropertyDecl, 1);
640 $$->name = $3;
641 $$->type = ARRAYOF($2);
642 $$->qualifiers = $1.data;
643 $$->numQualifiers = $1.size;
644 $$->subscript = (MI_Uint32)$4;
645 }
646 | dataType identifier '=' initializer ';'
647 {
648 void* value;
649
650 if (InitializerToValue(&$4, $1, &value) != 0)
651 {
652 mike 1.1 yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
653 YYABORT;
654 }
655
656 $$ = CALLOC_T(MI_PropertyDecl, 1);
657 $$->name = $2;
658 $$->type = $1;
659 $$->value = value;
660 }
661 | qualifierExpr dataType identifier '=' initializer ';'
662 {
663 void* value;
664
665 /* Check qualifier scope */
666 if (CheckScope(MI_FLAG_PROPERTY, &$1) != 0)
667 YYABORT;
668
669 if (InitializerToValue(&$5, $2, &value) != 0)
670 {
671 yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
672 YYABORT;
673 mike 1.1 }
674
675 $$ = CALLOC_T(MI_PropertyDecl, 1);
676 $$->name = $3;
677 $$->type = $2;
678 $$->qualifiers = $1.data;
679 $$->numQualifiers = $1.size;
680 $$->value = value;
681 }
682 | dataType identifier subscript '=' initializer ';'
683 {
684 void* value;
685
686 if (InitializerToValue(&$5, ARRAYOF($1), &value) != 0)
687 {
688 yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
689 YYABORT;
690 }
691
692 $$ = CALLOC_T(MI_PropertyDecl, 1);
693 $$->name = $2;
694 mike 1.1 $$->type = ARRAYOF($1);
695 $$->subscript = (MI_Uint32)$3;
696 $$->value = value;
697 }
698 | qualifierExpr dataType identifier subscript '=' initializer ';'
699 {
700 void* value;
701
702 /* Check qualifier scope */
703 if (CheckScope(MI_FLAG_PROPERTY, &$1) != 0)
704 YYABORT;
705
706 if (InitializerToValue(&$6, ARRAYOF($2), &value) != 0)
707 {
708 yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
709 YYABORT;
710 }
711
712 $$ = CALLOC_T(MI_PropertyDecl, 1);
713 $$->name = $3;
714 $$->type = ARRAYOF($2);
715 mike 1.1 $$->qualifiers = $1.data;
716 $$->numQualifiers = $1.size;
717 $$->subscript = (MI_Uint32)$4;
718 $$->value = value;
719 }
720
721 referenceDeclaration
722 : objectRef identifier ';'
723 {
724 const MI_ClassDecl* cd;
725
726 /* Verify that class exists */
727 cd = FindClassDecl($1);
728 if (!cd)
729 {
730 yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $1);
731 YYABORT;
732 }
733
734 $$ = CALLOC_T(MI_PropertyDecl, 1);
735 $$->type = MI_REFERENCE;
736 mike 1.1 $$->name = $2;
737 $$->className = cd->name;
738 }
739 | qualifierExpr objectRef identifier ';'
740 {
741 const MI_ClassDecl* cd;
742
743 /* Verify that class exists */
744 cd = FindClassDecl($2);
745 if (!cd)
746 {
747 yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $2);
748 YYABORT;
749 }
750
751 /* Check qualifier scope */
752 if (CheckScope(MI_FLAG_REFERENCE, &$1) != 0)
753 YYABORT;
754
755 $$ = CALLOC_T(MI_PropertyDecl, 1);
756 $$->type = MI_REFERENCE;
757 mike 1.1 $$->name = $3;
758 $$->className = cd->name;
759 $$->qualifiers = $1.data;
760 $$->numQualifiers = $1.size;
761 }
762 | objectRef identifier initializer';'
763 {
764 const MI_ClassDecl* cd;
765
766 /* Verify that class exists */
767 cd = FindClassDecl($1);
768 if (!cd)
769 {
770 yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $1);
771 YYABORT;
772 }
773
774 $$ = CALLOC_T(MI_PropertyDecl, 1);
775 $$->type = MI_REFERENCE;
776 $$->name = $2;
777 $$->className = cd->name;
778 mike 1.1 yywarnf(ID_IGNORED_INITIALIZER, "warning: ignored initializer");
779 /* [TODO: use initializer */
780 }
781 | qualifierExpr objectRef identifier initializer ';'
782 {
783 const MI_ClassDecl* cd;
784
785 /* Verify that class exists */
786 cd = FindClassDecl($2);
787 if (!cd)
788 {
789 yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $2);
790 YYABORT;
791 }
792
793 /* Check qualifier scope */
794 if (CheckScope(MI_FLAG_REFERENCE, &$1) != 0)
795 YYABORT;
796
797 $$ = CALLOC_T(MI_PropertyDecl, 1);
798 $$->type = MI_REFERENCE;
799 mike 1.1 $$->name = $3;
800 $$->className = cd->name;
801 $$->qualifiers = $1.data;
802 $$->numQualifiers = $1.size;
803 yywarnf(ID_IGNORED_INITIALIZER, "warning: ignored initializer");
804 /* [TODO: use initializer */
805 }
806
807 methodDeclaration
808 : dataType identifier '(' parameterList ')' ';'
809 {
810 $$ = CALLOC_T(MI_MethodDecl, 1);
811 $$->name = $2;
812 $$->parameters = $4.data;
813 $$->numParameters = $4.size;
814 $$->returnType = $1;
815 }
816 | qualifierExpr dataType identifier '(' parameterList ')' ';'
817 {
818 /* Check qualifier scope */
819 if (CheckScope(MI_FLAG_METHOD, &$1) != 0)
820 mike 1.1 YYABORT;
821
822 $$ = CALLOC_T(MI_MethodDecl, 1);
823 $$->name = $3;
824 $$->parameters = $5.data;
825 $$->numParameters = $5.size;
826 $$->qualifiers = $1.data;
827 $$->numQualifiers = $1.size;
828 $$->returnType = $2;
829 }
830 | dataType identifier '(' ')' ';'
831 {
832 MOF_ParameterList parameterList = PTRARRAY_INITIALIZER;
833
834 $$ = CALLOC_T(MI_MethodDecl, 1);
835 $$->name = $2;
836 $$->parameters = parameterList.data;
837 $$->numParameters = parameterList.size;
838 $$->returnType = $1;
839 }
840 | qualifierExpr dataType identifier '(' ')' ';'
841 mike 1.1 {
842 MOF_ParameterList parameterList = PTRARRAY_INITIALIZER;
843
844 /* Check qualifier scope */
845 if (CheckScope(MI_FLAG_METHOD, &$1) != 0)
846 YYABORT;
847
848 $$ = CALLOC_T(MI_MethodDecl, 1);
849 $$->name = $3;
850 $$->parameters = parameterList.data;
851 $$->numParameters = parameterList.size;
852 $$->qualifiers = $1.data;
853 $$->numQualifiers = $1.size;
854 $$->returnType = $2;
855 }
856
857 dataType
858 : TOK_BOOLEAN
859 {
860 $$ = MI_BOOLEAN;
861 }
862 mike 1.1 | TOK_SINT8
863 {
864 $$ = MI_SINT8;
865 }
866 | TOK_UINT8
867 {
868 $$ = MI_UINT8;
869 }
870 | TOK_SINT16
871 {
872 $$ = MI_SINT16;
873 }
874 | TOK_UINT16
875 {
876 $$ = MI_UINT16;
877 }
878 | TOK_SINT32
879 {
880 $$ = MI_SINT32;
881 }
882 | TOK_UINT32
883 mike 1.1 {
884 $$ = MI_UINT32;
885 }
886 | TOK_SINT64
887 {
888 $$ = MI_SINT64;
889 }
890 | TOK_UINT64
891 {
892 $$ = MI_UINT64;
893 }
894 | TOK_REAL32
895 {
896 $$ = MI_REAL32;
897 }
898 | TOK_REAL64
899 {
900 $$ = MI_REAL64;
901 }
902 | TOK_CHAR16
903 {
904 mike 1.1 $$ = MI_CHAR16;
905 }
906 | TOK_DATETIME
907 {
908 $$ = MI_DATETIME;
909 }
910 | TOK_STRING
911 {
912 $$ = MI_STRING;
913 }
914
915 objectRef
916 : identifier TOK_REF
917 {
918 $$ = $1;
919 }
920
921 parameterList
922 : parameter
923 {
924 $1->flags = MI_FLAG_PARAMETER;
925 mike 1.1 $1->flags |= GetQualFlags($1->qualifiers, $1->numQualifiers);
926 $$.data = NULL;
927 $$.size = 0;
928 PtrArray_Append((PtrArray*)&$$, $1);
929 }
930 | parameterList ',' parameter
931 {
932 if (FindParameter(&$1, $3->name))
933 {
934 yyerrorf(ID_PARAMETER_ALREADY_DEFINED,
935 "parameter already defined: \"%s\"", $3->name);
936 YYABORT;
937 }
938
939 $3->flags = MI_FLAG_PARAMETER;
940 $3->flags |= GetQualFlags($3->qualifiers, $3->numQualifiers);
941 PtrArray_Append((PtrArray*)&$$, $3);
942 }
943
944 parameter
945 : dataType identifier
946 mike 1.1 {
947 $$ = CALLOC_T(MI_ParameterDecl, 1);
948 $$->name = $2;
949 $$->type = $1;
950 }
951 | objectRef identifier
952 {
953 const MI_ClassDecl* cd;
954
955 /* Verify that class exists */
956 cd = FindClassDecl($1);
957 if (!cd)
958 {
959 yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $1);
960 YYABORT;
961 }
962
963 $$ = CALLOC_T(MI_ParameterDecl, 1);
964 $$->name = $2;
965 $$->type = MI_REFERENCE;
966 $$->className = cd->name;
967 mike 1.1 }
968 | qualifierExpr dataType identifier
969 {
970 /* Check qualifier scope */
971 if (CheckScope(MI_FLAG_PARAMETER, &$1) != 0)
972 YYABORT;
973
974 $$ = CALLOC_T(MI_ParameterDecl, 1);
975 $$->name = $3;
976 $$->type = $2;
977 $$->qualifiers = $1.data;
978 $$->numQualifiers = $1.size;
979 }
980 | qualifierExpr objectRef identifier
981 {
982 const MI_ClassDecl* cd;
983
984 /* Verify that class exists */
985 cd = FindClassDecl($2);
986 if (!cd)
987 {
988 mike 1.1 yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $2);
989 YYABORT;
990 }
991
992 /* Check qualifier scope */
993 if (CheckScope(MI_FLAG_PARAMETER, &$1) != 0)
994 YYABORT;
995
996 $$ = CALLOC_T(MI_ParameterDecl, 1);
997 $$->name = $3;
998 $$->type = MI_REFERENCE;
999 $$->className = cd->name;
1000 $$->qualifiers = $1.data;
1001 $$->numQualifiers = $1.size;
1002 }
1003 | dataType identifier subscript
1004 {
1005 $$ = CALLOC_T(MI_ParameterDecl, 1);
1006 $$->name = $2;
1007 $$->type = ARRAYOF($1);
1008 $$->subscript = (MI_Uint32)$3;
1009 mike 1.1 }
1010 | objectRef identifier subscript
1011 {
1012 const MI_ClassDecl* cd;
1013
1014 /* Verify that class exists */
1015 cd = FindClassDecl($1);
1016 if (!cd)
1017 {
1018 yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $1);
1019 YYABORT;
1020 }
1021
1022 $$ = CALLOC_T(MI_ParameterDecl, 1);
1023 $$->name = $2;
1024 $$->type = ARRAYOF(MI_REFERENCE);
1025 $$->className = cd->name;
1026 $$->subscript = (MI_Uint32)$3;
1027 }
1028 | qualifierExpr dataType identifier subscript
1029 {
1030 mike 1.1 /* Check qualifier scope */
1031 if (CheckScope(MI_FLAG_PARAMETER, &$1) != 0)
1032 YYABORT;
1033
1034 $$ = CALLOC_T(MI_ParameterDecl, 1);
1035 $$->name = $3;
1036 $$->type = ARRAYOF($2);
1037 $$->subscript = (MI_Uint32)$4;
1038 $$->qualifiers = $1.data;
1039 $$->numQualifiers = $1.size;
1040 }
1041 | qualifierExpr objectRef identifier subscript
1042 {
1043 const MI_ClassDecl* cd;
1044
1045 /* Verify that class exists */
1046 cd = FindClassDecl($2);
1047 if (!cd)
1048 {
1049 yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $2);
1050 YYABORT;
1051 mike 1.1 }
1052
1053 /* Check qualifier scope */
1054 if (CheckScope(MI_FLAG_PARAMETER, &$1) != 0)
1055 YYABORT;
1056
1057 $$ = CALLOC_T(MI_ParameterDecl, 1);
1058 $$->name = $3;
1059 $$->type = ARRAYOF(MI_REFERENCE);
1060 $$->className = cd->name;
1061 $$->subscript = (MI_Uint32)$4;
1062 $$->qualifiers = $1.data;
1063 $$->numQualifiers = $1.size;
1064 }
1065
1066 subscript
1067 : '[' TOK_INTEGER_VALUE ']'
1068 {
1069 if ($2 <= 0)
1070 {
1071 yyerrorf(ID_ILLEGAL_ARRAY_SUBSCRIPT,
1072 mike 1.1 "illegal array subscript: " SINT64_FMT, $2);
1073 YYABORT;
1074 }
1075
1076 $$ = $2;
1077 }
1078 | '[' ']'
1079 {
1080 /* 0 signifies a dynamic array */
1081 $$ = 0;
1082 }
1083
1084 initializer
1085 : constantValue
1086 {
1087 memset(&$$, 0, sizeof($$));
1088 $$.data = CALLOC_T(MOF_ConstantValue, 1);
1089 $$.data[0] = $1;
1090 $$.size = 1;
1091 }
1092 | arrayInitializer
1093 mike 1.1 {
1094 $$ = $1;
1095 }
1096 | TOK_ALIAS_IDENTIFIER
1097 {
1098 memset(&$$, 0, sizeof($$));
1099 $$.data = CALLOC_T(MOF_ConstantValue, 1);
1100 $$.data[0].type = TOK_STRING_VALUE;
1101 $$.data[0].value.string = $1;
1102 $$.size = 0;
1103 }
1104
1105 arrayInitializer
1106 : '{' arrayInitializerList '}'
1107 {
1108 $$ = $2;
1109 }
1110
1111 arrayInitializerList
1112 : constantValue
1113 {
1114 mike 1.1 memset(&$$, 0, sizeof($$));
1115 $$.data = CALLOC_T(MOF_ConstantValue, 1);
1116 $$.data[0] = $1;
1117 $$.size = 1;
1118 $$.isArray = 1;
1119 }
1120 | arrayInitializerList ',' constantValue
1121 {
1122 $1.data = REALLOC_T(MOF_ConstantValue, $1.data, $1.size + 1);
1123 $1.data[$1.size] = $3;
1124 $1.size++;
1125 $$ = $1;
1126 }
1127
1128 constantValue
1129 : TOK_INTEGER_VALUE
1130 {
1131 $$.type = TOK_INTEGER_VALUE;
1132 $$.value.integer = $1;
1133 }
1134 | TOK_REAL_VALUE
1135 mike 1.1 {
1136 $$.type = TOK_REAL_VALUE;
1137 $$.value.real = $1;
1138 }
1139 | TOK_CHAR_VALUE
1140 {
1141 $$.type = TOK_CHAR_VALUE;
1142 $$.value.character = $1;
1143 }
1144 | stringValue
1145 {
1146 $$.type = TOK_STRING_VALUE;
1147 $$.value.string = $1;
1148 }
1149 | TOK_BOOLEAN_VALUE
1150 {
1151 $$.type = TOK_BOOLEAN_VALUE;
1152 $$.value.boolean = $1;
1153 }
1154 | TOK_NULL
1155 {
1156 mike 1.1 $$.type = TOK_NULL;
1157 }
1158
1159 stringValue
1160 : TOK_STRING_VALUE
1161 {
1162 $$ = $1;
1163 }
1164 | stringValue TOK_STRING_VALUE
1165 {
1166 size_t size = strlen($1) + strlen($2) + 1;
1167 $$ = (char*)MOF_Realloc(&state.heap, $1, size);
1168 Strcat($$, size, $2);
1169 MOF_Free(&state.heap, $2);
1170 }
1171
1172 qualifierDeclaration
1173 : TOK_QUALIFIER identifier qualifierType scopeExpr ';'
1174 {
1175 $3->name = $2;
1176 $3->scope = $4;
1177 mike 1.1 $3->flavor = 0;
1178 $$ = $3;
1179 }
1180 | TOK_QUALIFIER identifier qualifierType scopeExpr flavorExpr ';'
1181 {
1182 $3->name = $2;
1183 $3->scope = $4;
1184 $3->flavor = $5;
1185 $$ = $3;
1186 }
1187
1188 qualifierType
1189 : ':' dataType
1190 {
1191 $$ = CALLOC_T(MI_QualifierDecl, 1);
1192 $$->type = $2;
1193 }
1194 | ':' dataType '=' initializer
1195 {
1196 void* value;
1197
1198 mike 1.1 if (InitializerToValue(&$4, $2, &value) != 0)
1199 {
1200 yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
1201 YYABORT;
1202 }
1203
1204 $$ = CALLOC_T(MI_QualifierDecl, 1);
1205 $$->type = $2;
1206 $$->value = value;
1207 ReleaseInitializer(&$4);
1208 }
1209 | ':' dataType subscript
1210 {
1211 $$ = CALLOC_T(MI_QualifierDecl, 1);
1212 $$->type = ARRAYOF($2);
1213 $$->subscript = (MI_Uint32)$3;
1214 }
1215 | ':' dataType subscript '=' initializer
1216 {
1217 void* value = NULL;
1218
1219 mike 1.1 if (InitializerToValue(&$5, ARRAYOF($2), &value) != 0)
1220 {
1221 yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
1222 YYABORT;
1223 }
1224
1225 $$ = CALLOC_T(MI_QualifierDecl, 1);
1226 $$->type = ARRAYOF($2);
1227 $$->subscript = (MI_Uint32)$3;
1228 $$->value = value;
1229 ReleaseInitializer(&$5);
1230 }
1231
1232 scopeExpr
1233 : ',' TOK_SCOPE '(' scopeList ')'
1234 {
1235 $$ = $4;
1236 }
1237
1238 scopeList
1239 : scope
1240 mike 1.1 {
1241 $$ = $1;
1242 }
1243 | scopeList ',' scope
1244 {
1245 $$ |= $3;
1246 }
1247
1248 scope
1249 : TOK_CLASS
1250 {
1251 $$ = MI_FLAG_CLASS;
1252 }
1253 | TOK_ASSOCIATION
1254 {
1255 $$ = MI_FLAG_ASSOCIATION;
1256 }
1257 | TOK_INDICATION
1258 {
1259 $$ = MI_FLAG_INDICATION;
1260 }
1261 mike 1.1 | TOK_PROPERTY
1262 {
1263 $$ = MI_FLAG_PROPERTY;
1264 }
1265 | TOK_REFERENCE
1266 {
1267 $$ = MI_FLAG_REFERENCE;
1268 }
1269 | TOK_METHOD
1270 {
1271 $$ = MI_FLAG_METHOD;
1272 }
1273 | TOK_PARAMETER
1274 {
1275 $$ = MI_FLAG_PARAMETER;
1276 }
1277 | TOK_ANY
1278 {
1279 $$ = MI_FLAG_ANY;
1280 }
1281
1282 mike 1.1 flavorExpr
1283 : ',' TOK_FLAVOR '(' flavorList ')'
1284 {
1285 /* Reject incompatiable ToSubclass and Restricted flavors */
1286 if ($4 & MI_FLAG_TOSUBCLASS && $4 & MI_FLAG_RESTRICTED)
1287 {
1288 yyerrorf(ID_INCOMPATIBLE_FLAVORS, "incompatible flavors: %s/%s",
1289 "ToSubclass", "Restricted");
1290 YYABORT;
1291 }
1292
1293 /* Reject incompatiable EnableOverride and DisableOverride flavors */
1294 if ($4 & MI_FLAG_ENABLEOVERRIDE && $4 & MI_FLAG_DISABLEOVERRIDE)
1295 {
1296 yyerrorf(ID_INCOMPATIBLE_FLAVORS, "incompatible flavors: %s/%s",
1297 "EnableOverride", "DisableOverride");
1298 YYABORT;
1299 }
1300
1301 $$ = $4;
1302 }
1303 mike 1.1
1304 instanceDeclaration
1305 : TOK_INSTANCE TOK_OF identifier instanceBody
1306 {
1307 $$ = CALLOC_T(MI_InstanceDecl, 1);
1308 $$->flags = 0;
1309 $$->name = $3;
1310 $$->properties = $4.propertySet.data;
1311 $$->numProperties = $4.propertySet.size;
1312 }
1313 | qualifierExpr TOK_INDICATION TOK_OF identifier instanceBody
1314 {
1315 $$ = CALLOC_T(MI_InstanceDecl, 1);
1316 $$->flags = 0;
1317 $$->name = $4;
1318 $$->properties = $5.propertySet.data;
1319 $$->numProperties = $5.propertySet.size;
1320 $$->qualifiers = $1.data;
1321 $$->numQualifiers = $1.size;
1322 }
1323 | TOK_INSTANCE TOK_OF identifier alias instanceBody
1324 mike 1.1 {
1325 /* [TODO]: handle alias */
1326 $$ = CALLOC_T(MI_InstanceDecl, 1);
1327 $$->flags = 0;
1328 $$->name = $3;
1329 $$->properties = $5.propertySet.data;
1330 $$->numProperties = $5.propertySet.size;
1331 }
1332 | qualifierExpr TOK_INDICATION TOK_OF identifier alias instanceBody
1333 {
1334 /* [TODO]: handle alias */
1335 $$ = CALLOC_T(MI_InstanceDecl, 1);
1336 $$->flags = 0;
1337 $$->name = $4;
1338 $$->properties = $6.propertySet.data;
1339 $$->numProperties = $6.propertySet.size;
1340 $$->qualifiers = $1.data;
1341 $$->numQualifiers = $1.size;
1342 }
1343
1344 instanceBody
1345 mike 1.1 : '{' valueInitializerList '}' ';'
1346 {
1347 $$ = $2;
1348 }
1349
1350 alias
1351 : TOK_AS TOK_ALIAS_IDENTIFIER
1352 {
1353 $$ = $2;
1354 }
1355
1356 valueInitializerList
1357 : valueInitializer
1358 {
1359 $$.propertySet.data = NULL;
1360 $$.propertySet.size = 0;
1361 $1->flags = MI_FLAG_PROPERTY;
1362 $1->flags |= GetQualFlags($1->qualifiers, $1->numQualifiers);
1363 PtrArray_Append((PtrArray*)&$$.propertySet, $1);
1364 }
1365 | valueInitializerList valueInitializer
1366 mike 1.1 {
1367 if (FindProperty(&$1.propertySet, $2->name))
1368 {
1369 yyerrorf(ID_CLASS_FEATURE_ALREADY_DEFINED,
1370 "instance property already defined: \"%s\"", $2->name);
1371 YYABORT;
1372 }
1373
1374 $2->flags = MI_FLAG_PROPERTY;
1375 $2->flags |= GetQualFlags($2->qualifiers, $2->numQualifiers);
1376 PtrArray_Append((PtrArray*)&$$.propertySet, $2);
1377 }
1378
1379 valueInitializer
1380 : identifier '=' initializer ';'
1381 {
1382 void* value;
1383 MI_Type type = InitializerToType(&$3);
1384
1385 if (InitializerToValue(&$3, type, &value) != 0)
1386 {
1387 mike 1.1 yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
1388 YYABORT;
1389 }
1390
1391 $$ = CALLOC_T(MI_PropertyDecl, 1);
1392 $$->name = $1;
1393 $$->type = type;
1394 $$->value = value;
1395 }
1396 | qualifierExpr identifier '=' initializer ';'
1397 {
1398 void* value;
1399 MI_Type type = InitializerToType(&$4);
1400
1401 if (InitializerToValue(&$4, type, &value) != 0)
1402 {
1403 yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
1404 YYABORT;
1405 }
1406
1407 $$ = CALLOC_T(MI_PropertyDecl, 1);
1408 mike 1.1 $$->name = $2;
1409 $$->type = type;
1410 $$->value = value;
1411 $$->qualifiers = $1.data;
1412 $$->numQualifiers = $1.size;
1413 }
1414
1415 identifier
1416 : TOK_IDENT
1417 {
1418 $$ = $1;
1419 }
1420 | TOK_ASSOCIATION
1421 {
1422 $$ = MOF_Strdup(&state.heap, "Association");
1423 }
1424 | TOK_INDICATION
1425 {
1426 $$ = MOF_Strdup(&state.heap, "Indication");
1427 }
1428 | TOK_REFERENCE
1429 mike 1.1 {
1430 $$ = MOF_Strdup(&state.heap, "Reference");
1431 }
1432 | TOK_PROPERTY
1433 {
1434 $$ = MOF_Strdup(&state.heap, "Property");
1435 }
|