1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include "Parser.h"
26 #include <cstdio>
27 #include <cstdio>
28 #include <cstdlib>
29 #include <cstdarg>
30 #include <cassert>
31 #include <cctype>
32 #include <string>
33 #include <vector>
34 #include <set>
35 #include <map>
36
37 #include <common.h>
38 #include <strids.h>
39
40 #include "QualifierDecls.h"
41
42 #include <base/strings.h>
43 mike 1.1 #include <base/types.h>
44 #include <base/io.h>
45 #include <base/dir.h>
46 #include <base/env.h>
47 #include <base/paths.h>
48
49 #if defined(CONFIG_OS_WINDOWS)
50 # include <time.h>
51 #else
52 # include <unistd.h>
53 # include <sys/time.h>
54 # include <sys/types.h>
55 #endif
56
57 #include "gen.h"
58
59 // C Provider Templates:
60 #include "cprototypes_t.h"
61 #include "cprovider_t.h"
62 #include "cmodule_t.h"
63 #include "cmakefile_t.h"
64 mike 1.1
65 // C++ Provider Templates:
66 #include "cxxmodule_t.h"
67 #include "cxxprovider_t.h"
68 #include "cxxstubs_t.h"
69 #include "cxxmakefile_t.h"
70
71 using namespace std;
72
73 /* xlc doesn't want to use static inline funciotns inside temaplate functions */
74 int _Scasecmp(const MI_Char* s1, const MI_Char* s2)
75 {
76 return Zcasecmp(s1, s2);
77 }
78
79 //==============================================================================
80 //
81 // GeneratorOptions
82 //
83 //==============================================================================
84
85 mike 1.1 GeneratorOptions::GeneratorOptions()
86 {
87 paths.clear();
88 descriptions = false;
89 values = false;
90 mappingStrings = false;
91 standardQualifiers = false;
92 booleanQualifiers = false;
93 ignoreAllQualifiers = false;
94 filterSupport = false;
95 quiet = false;
96 noProviders = false;
97 all = false;
98 cpp = false;
99 schema.clear();
100 dir.clear();
101 localize = false;
102 providerRegistryPath.clear();
103 association = false;
104 extraClasses.clear();
105 entryPoint.clear();
106 mike 1.1 warnings = false;
107 }
108
109 //==============================================================================
110 //
111 // WARNING
112 //
113 // Message included in all generated files that are not intended to be
114 // modified by the developer.
115 //
116 //==============================================================================
117
118 #define WARNING \
119 "WARNING: THIS FILE WAS AUTOMATICALLY GENERATED. PLEASE DO NOT EDIT."
120
121 //==============================================================================
122 //
123 // arg0
124 //
125 // A global pointer to argv[0] that is set immediately by main().
126 //
127 mike 1.1 //==============================================================================
128
129 static const char* arg0;
130 static FILE* s_stdout;
131
132 //==============================================================================
133 //
134 // providerClasses
135 //
136 // The set of class names for which there are providers (used by generator
137 // to include or exclude various elements).
138 //
139 //==============================================================================
140
141 typedef set<string> ProviderClassSet;
142 static ProviderClassSet providerClasses;
143
144 //==============================================================================
145 //
146 // generated
147 //
148 mike 1.1 // Allows keep tracking of generated classes in 'generateHeader' function
149 //
150 //==============================================================================
151
152 static set<string> generated_headers;
153 static set<string> generated_classes;
154
155 //==============================================================================
156 //
157 // err()
158 //
159 // Writes a formatted error message to standard error (preceded by argv[0])
160 // and then exists.
161 //
162 //==============================================================================
163
164 PRINTF_FORMAT(3, 4)
165 static void Fprintf(FILE* os, int id, const MI_Char* format, ...)
166 {
167 va_list ap;
168 va_start(ap, format);
169 mike 1.1
170 #if defined(_MSC_VER)
171 wchar_t* wformat = LookupString(id);
172
173 if (wformat)
174 {
175 vfwprintf(os, wformat, ap);
176 free(wformat);
177 }
178 else
179 #endif
180 {
181 vfprintf(os, format, ap);
182 }
183
184 va_end(ap);
185 }
186
187 //==============================================================================
188 //
189 // err()
190 mike 1.1 //
191 // Writes a formatted error message to standard error (preceded by argv[0])
192 // and then exists.
193 //
194 //==============================================================================
195
196 PRINTF_FORMAT(2, 3)
197 void FUNCTION_NEVER_RETURNS err(int id, const char* format, ...)
198 {
199 fprintf(stderr, "%s: ", arg0);
200
201 va_list ap;
202 va_start(ap, format);
203
204 #if defined(_MSC_VER)
205 wchar_t* wformat = LookupString(id);
206
207 if (wformat)
208 {
209 vfwprintf(stderr, wformat, ap);
210 free(wformat);
211 mike 1.1 }
212 else
213 #endif
214 {
215 vfprintf(stderr, format, ap);
216 }
217
218 va_end(ap);
219
220 fputc('\n', stderr);
221
222 exit(1);
223 }
224
225 //==============================================================================
226 //
227 // put()
228 //
229 // Write formatted output to the given stream (similar to fprintf).
230 //
231 //==============================================================================
232 mike 1.1
233 PRINTF_FORMAT(2, 3)
234 static void put(FILE* os, const char* fmt, ...)
235 {
236 va_list ap;
237 va_start(ap, fmt);
238 vfprintf(os, fmt, ap);
239 va_end(ap);
240 }
241
242 //==============================================================================
243 //
244 // putl()
245 //
246 // Similar to put() but adds a newline at the end.
247 //
248 //==============================================================================
249
250 PRINTF_FORMAT(2, 3)
251 static void putl(FILE* os, const char* fmt, ...)
252 {
253 mike 1.1 va_list ap;
254 va_start(ap, fmt);
255 vfprintf(os, fmt, ap);
256 va_end(ap);
257 fputc('\n', os);
258 }
259
260 //==============================================================================
261 //
262 // Exists()
263 //
264 // Return true if the given file exists.
265 //
266 //==============================================================================
267
268 static bool Exists(const char* path)
269 {
270 return access(path, F_OK) == 0;
271 }
272
273 //==============================================================================
274 mike 1.1 //
275 // ValidIdent()
276 //
277 // Check whether the given string is a valid C identifier.
278 //
279 //==============================================================================
280
281 static bool ValidIdent(const string& s)
282 {
283 const char* p = s.c_str();
284
285 if (!isalpha((unsigned char)(*p)) && *p != '_')
286 return false;
287
288 p++;
289
290 for (; *p; p++)
291 {
292 if (!isalnum((unsigned char)(*p)) && *p != '_')
293 return false;
294 }
295 mike 1.1
296 return true;
297 }
298
299 //==============================================================================
300 //
301 // Inhale()
302 //
303 // Read the contents of the given file into memory.
304 //
305 //==============================================================================
306
307 static bool Inhale(const char* path, vector<char>& data)
308 {
309 FILE* is = Fopen(path, "r");
310
311 if (!is)
312 return false;
313
314 size_t n;
315 char buf[4096];
316 mike 1.1
317 while ((n = fread(buf, 1, sizeof(buf), is)) != 0)
318 {
319 data.insert(data.end(), buf, buf + n);
320 }
321
322 data.push_back('\0');
323
324 fclose(is);
325
326 return true;
327 }
328
329 //==============================================================================
330 //
331 // puts()
332 //
333 // Put a string onto the output stream.
334 //
335 //==============================================================================
336
337 mike 1.1 static void puts(FILE* os, const string& s)
338 {
339 fprintf(os, "%s", s.c_str());
340 }
341
342 //==============================================================================
343 //
344 // eqi()
345 //
346 // Return true if the two strings are identical except for case.
347 //
348 //==============================================================================
349
350 static bool eqi(const char* s1, const char* s2)
351 {
352 return Strcasecmp(s1, s2) == 0;
353 }
354
355 //==============================================================================
356 //
357 // nl()
358 mike 1.1 //
359 // Print a newline to the given stream.
360 //
361 //==============================================================================
362
363 inline void nl(FILE* os)
364 {
365 fputc('\n', os);
366 }
367
368 //==============================================================================
369 //
370 // Generate a random key
371 //
372 //==============================================================================
373
374 #if 0
375
376 static MI_Uint64 _GetCurrentTime()
377 {
378 #if defined(CONFIG_OS_WINDOWS)
379 mike 1.1 FILETIME ft;
380 ULARGE_INTEGER tmp;
381
382 GetSystemTimeAsFileTime(&ft);
383 tmp.u.LowPart = ft.dwLowDateTime;
384 tmp.u.HighPart = ft.dwHighDateTime;
385 tmp.QuadPart -= 0X19DB1DED53E8000;
386 return tmp.QuadPart / (UINT64)10;
387 #else
388 struct timeval tv;
389 struct timezone tz;
390 memset(&tv, 0, sizeof(tv));
391 memset(&tz, 0, sizeof(tz));
392
393 if (gettimeofday(&tv, &tz) != 0)
394 return MI_RESULT_FAILED;
395
396 return (MI_Uint64)tv.tv_sec * (MI_Uint64)1000000 + (MI_Uint64)tv.tv_usec;
397 #endif
398 }
399
400 mike 1.1 static void _SleepMsec(MI_Uint64 msec)
401 {
402 #if defined(CONFIG_OS_WINDOWS)
403 Sleep((DWORD)msec);
404 #else
405 struct timespec rqtp;
406
407 rqtp.tv_sec = static_cast<long>(msec/1000);
408 rqtp.tv_nsec = static_cast<long>((msec%1000)*1000*1000);
409
410 nanosleep(&rqtp, NULL);
411 #endif
412 }
413
414 static void _MakeID(char id[33])
415 {
416 MI_Uint64 s1 = _GetCurrentTime();
417 _SleepMsec(10);
418 MI_Uint64 s2 = _GetCurrentTime();
419
420 srand((unsigned int)(((s1 >> 32) ^ s1 ^ (s2 >> 32)) | s2));
421 mike 1.1
422 static const char XDIGITS[] =
423 {
424 '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F',
425 };
426
427 for (size_t i = 0; i < 32; i++)
428 {
429 int x = rand() % 16;
430 id[i] = XDIGITS[x];
431 }
432
433 id[32] = '\0';
434 }
435
436 #endif
437
438 //==============================================================================
439 //
440 // GeneratorOptions
441 //
442 mike 1.1 // This structure defines program options. These include:
443 //
444 //==============================================================================
445
446 static GeneratorOptions s_options;
447
448 static set<string> s_generated;
449
450 //==============================================================================
451 //
452 // GenStatikGenLine()
453 //
454 //==============================================================================
455
456 static void GenStatikGenLine(FILE* os)
457 {
458 // Files generated by Statik may be located by searching for files which
459 // contain the following string. The ampersands are separted into a format
460 // argument to prevent this file (generator.cpp) from containg that string.
461 fprintf(os, "/* %cmigen%c */\n", '@', '@');
462 }
463 mike 1.1
464 //==============================================================================
465 //
466 // aliases
467 //
468 // Maps MOF classnames to aliases. This map is built in main before
469 // classes are generated. The generator consults this table to determine
470 // the real name of the C structure (the alias) which may be different
471 // than the name of the MOF class.
472 //
473 //==============================================================================
474
475 typedef map<string, string> Aliases;
476 static Aliases aliases;
477
478 //==============================================================================
479 //
480 // Quote()
481 //
482 // This function puts quotation marks around a string.
483 //
484 mike 1.1 //==============================================================================
485
486 static string Quote(const string& str)
487 {
488 return "MI_T(\"" + str + "\")";
489 }
490
491 //==============================================================================
492 //
493 // ExpandPath()
494 //
495 // Obtain the full path (including directory given by optional -d option).
496 //
497 //==============================================================================
498
499 static string ExpandPath(const string& str)
500 {
501 if (s_options.dir.size())
502 {
503 string r = s_options.dir + "/" + str;
504 return s_options.dir + "/" + str;
505 mike 1.1 }
506 else
507 return str;
508 }
509
510 //==============================================================================
511 //
512 // Contains()
513 //
514 // Return true if this vector contains the given string.
515 //
516 //==============================================================================
517
518 static bool Contains(const vector<string>& v, const string& s)
519 {
520 for (size_t i = 0; i < v.size(); i++)
521 {
522 if (s == v[i])
523 return true;
524 }
525
526 mike 1.1 return false;
527 }
528
529 //==============================================================================
530 //
531 // MakeFlags()
532 //
533 // This function builds a flags expression from a bit mask. For example,
534 // for a key property, the flag expression might look like this:
535 //
536 // MI_FLAG_PROPERTY | MI_FLAG_KEY
537 //
538 // Many structures have a flags field whose bits indicate the type of the
539 // object (e.g., MI_FLAG_CLASS, MI_FLAG_METHOD, MI_FLAG_PROPERTY) as well
540 // as any boolean qualifiers whose values are true (e.g., MI_FLAG_KEY,
541 // MI_FLAG_IN, MI_FLAG_OUT).
542 //
543 //==============================================================================
544
545 static string MakeFlags(MI_Uint32 flags)
546 {
547 mike 1.1 struct
548 {
549 const char* name;
550 MI_Uint32 flag;
551 }
552 _flags[] =
553 {
554 { "CLASS", MI_FLAG_CLASS },
555 { "METHOD", MI_FLAG_METHOD },
556 { "PROPERTY", MI_FLAG_PROPERTY },
557 { "PARAMETER", MI_FLAG_PARAMETER },
558 { "ASSOCIATION", MI_FLAG_ASSOCIATION },
559 { "INDICATION", MI_FLAG_INDICATION },
560 { "REFERENCE", MI_FLAG_REFERENCE },
561 { "KEY", MI_FLAG_KEY },
562 { "IN", MI_FLAG_IN },
563 { "OUT", MI_FLAG_OUT },
564 { "REQUIRED", MI_FLAG_REQUIRED },
565 { "STATIC", MI_FLAG_STATIC },
566 { "ABSTRACT", MI_FLAG_ABSTRACT },
567 { "TERMINAL", MI_FLAG_TERMINAL },
568 mike 1.1 { "EXPENSIVE", MI_FLAG_EXPENSIVE },
569 { "STREAM", MI_FLAG_STREAM },
570 { "ENABLEOVERRIDE", MI_FLAG_ENABLEOVERRIDE },
571 { "DISABLEOVERRIDE", MI_FLAG_DISABLEOVERRIDE },
572 { "RESTRICTED", MI_FLAG_RESTRICTED},
573 { "TOSUBCLASS", MI_FLAG_TOSUBCLASS},
574 { "TRANSLATABLE", MI_FLAG_TRANSLATABLE},
575 };
576
577 string result;
578 size_t count = 0;
579
580 for (size_t i = 0; i < MI_COUNT(_flags); i++)
581 {
582 if (_flags[i].flag & flags)
583 {
584 if (count)
585 result += "|";
586 result += string("MI_FLAG_") + _flags[i].name;
587 count++;
588 }
589 mike 1.1 }
590
591 if (result.size())
592 return result;
593
594 return "0";
595 }
596
597 //==============================================================================
598 //
599 // MakeFlavor()
600 //
601 // This function builds a flavor string from the given flavor mask. For
602 // example:
603 //
604 // MI_FLAG_TOSUBCLASS | MI_FLAG_DISABLEOVERRIDE
605 //
606 //==============================================================================
607
608 static string MakeFlavor(MI_Uint32 flavor)
609 {
610 mike 1.1 struct
611 {
612 MI_Uint32 mask;
613 const char* name;
614 }
615 _flavors[] =
616 {
617 { MI_FLAG_ENABLEOVERRIDE, "MI_FLAG_ENABLEOVERRIDE" },
618 { MI_FLAG_DISABLEOVERRIDE, "MI_FLAG_DISABLEOVERRIDE" },
619 { MI_FLAG_TOSUBCLASS, "MI_FLAG_TOSUBCLASS" },
620 { MI_FLAG_TRANSLATABLE, "MI_FLAG_TRANSLATABLE" },
621 { MI_FLAG_RESTRICTED, "MI_FLAG_RESTRICTED" },
622 };
623
624 string result;
625 size_t count = 0;
626
627 for (size_t i = 0; i < MI_COUNT(_flavors); i++)
628 {
629 if (_flavors[i].mask & flavor)
630 {
631 mike 1.1 if (count)
632 result += "|";
633 result += _flavors[i].name;
634 count++;
635 }
636 }
637
638 if (result.size())
639 return result;
640
641 return "0";
642 }
643
644 //==============================================================================
645 //
646 // MakeScope()
647 //
648 // This function builds a scope string from the given scope mask. For
649 // example:
650 //
651 // MI_FLAG_TOSUBCLASS | MI_FLAG_DISABLEOVERRIDE
652 mike 1.1 //
653 //==============================================================================
654
655 static string MakeScope(MI_Uint32 scope)
656 {
657 struct
658 {
659 MI_Uint32 mask;
660 const char* name;
661 }
662 _scopes[] =
663 {
664 { MI_FLAG_ASSOCIATION, "MI_FLAG_ASSOCIATION" },
665 { MI_FLAG_CLASS, "MI_FLAG_CLASS" },
666 { MI_FLAG_INDICATION, "MI_FLAG_INDICATION" },
667 { MI_FLAG_METHOD, "MI_FLAG_METHOD" },
668 { MI_FLAG_PARAMETER, "MI_FLAG_PARAMETER" },
669 { MI_FLAG_PROPERTY, "MI_FLAG_PROPERTY" },
670 { MI_FLAG_REFERENCE, "MI_FLAG_REFERENCE" },
671 };
672
673 mike 1.1 if ((scope & MI_FLAG_ANY) == MI_FLAG_ANY)
674 return "MI_FLAG_ANY";
675
676 string result;
677 size_t count = 0;
678
679 for (size_t i = 0; i < MI_COUNT(_scopes); i++)
680 {
681 if (_scopes[i].mask & scope)
682 {
683 if (count)
684 result += "|";
685 result += _scopes[i].name;
686 count++;
687 }
688 }
689
690 if (result.size())
691 return result;
692
693 return "0";
694 mike 1.1 }
695
696 //==============================================================================
697 //
698 // MakeType()
699 //
700 // This function returns the type tag string for the given Statik type
701 // (given by the MI_Type structure).
702 //
703 //==============================================================================
704
705 static string MakeType(MI_Uint32 type)
706 {
707 switch (type)
708 {
709 case MI_BOOLEAN: return "MI_BOOLEAN";
710 case MI_UINT8: return "MI_UINT8";
711 case MI_SINT8: return "MI_SINT8";
712 case MI_UINT16: return "MI_UINT16";
713 case MI_SINT16: return "MI_SINT16";
714 case MI_UINT32: return "MI_UINT32";
715 mike 1.1 case MI_SINT32: return "MI_SINT32";
716 case MI_UINT64: return "MI_UINT64";
717 case MI_SINT64: return "MI_SINT64";
718 case MI_REAL32: return "MI_REAL32";
719 case MI_REAL64: return "MI_REAL64";
720 case MI_CHAR16: return "MI_CHAR16";
721 case MI_DATETIME: return "MI_DATETIME";
722 case MI_STRING: return "MI_STRING";
723 case MI_REFERENCE: return "MI_REFERENCE";
724 case MI_INSTANCE: return "MI_INSTANCE";
725 case MI_BOOLEANA: return "MI_BOOLEANA";
726 case MI_UINT8A: return "MI_UINT8A";
727 case MI_SINT8A: return "MI_SINT8A";
728 case MI_UINT16A: return "MI_UINT16A";
729 case MI_SINT16A: return "MI_SINT16A";
730 case MI_UINT32A: return "MI_UINT32A";
731 case MI_SINT32A: return "MI_SINT32A";
732 case MI_UINT64A: return "MI_UINT64A";
733 case MI_SINT64A: return "MI_SINT64A";
734 case MI_REAL32A: return "MI_REAL32A";
735 case MI_REAL64A: return "MI_REAL64A";
736 mike 1.1 case MI_CHAR16A: return "MI_CHAR16A";
737 case MI_DATETIMEA: return "MI_DATETIMEA";
738 case MI_STRINGA: return "MI_STRINGA";
739 case MI_REFERENCEA: return "MI_REFERENCEA";
740 case MI_INSTANCEA: return "MI_INSTANCEA";
741 default: return "UNKNOWN_TYPE";
742 };
743 }
744
745 //==============================================================================
746 //
747 // AliasOf()
748 //
749 // The the given class name is in the alias map, return the alias.
750 // Otherwise, just return the class name.
751 //
752 //==============================================================================
753
754 string AliasOf(const string& className)
755 {
756 Aliases::const_iterator pos = aliases.find(className);
757 mike 1.1
758 if (pos != aliases.end())
759 return (*pos).second;
760
761 return className;
762 }
763
764 //==============================================================================
765 //
766 // PutRule()
767 //
768 // Put a rule line (2 '*' characters followed by 78 '=' characters).
769 //
770 //==============================================================================
771
772 static void PutRule(FILE* os)
773 {
774 put(os, "**");
775
776 for (size_t i = 0; i < 78; i++)
777 put(os, "=");
778 mike 1.1
779 nl(os);
780 }
781
782 //==============================================================================
783 //
784 // PutCommentBox()
785 //
786 // Put a C comment box with a message in it.
787 //
788 //==============================================================================
789
790 static void PutCommentBox(FILE* os, const string& msg)
791 {
792 putl(os, "/*");
793 PutRule(os);
794 putl(os, "**");
795 putl(os, "** %s", msg.c_str());
796 putl(os, "**");
797 PutRule(os);
798 putl(os, "*/");
799 mike 1.1 }
800
801 //==============================================================================
802 //
803 // TypeNameOf()
804 //
805 // Return the C type name for the given Statik type tag. For arrays type
806 // tags, return the C type name of the element type. For example:
807 //
808 // TypeNameOf(MI_UINT8) => "Uint8"
809 // TypeNameOf(MI_UINT8A) => "Uint8"
810 //
811 //==============================================================================
812
813 static const char* TypeNameOf(MI_Uint32 type)
814 {
815 switch (type)
816 {
817 case MI_BOOLEAN:
818 return "Boolean";
819 case MI_SINT8:
820 mike 1.1 return "Sint8";
821 case MI_UINT8:
822 return "Uint8";
823 case MI_SINT16:
824 return "Sint16";
825 case MI_UINT16:
826 return "Uint16";
827 case MI_SINT32:
828 return "Sint32";
829 case MI_UINT32:
830 return "Uint32";
831 case MI_SINT64:
832 return "Sint64";
833 case MI_UINT64:
834 return "Uint64";
835 case MI_REAL32:
836 return "Real32";
837 case MI_REAL64:
838 return "Real64";
839 case MI_CHAR16:
840 return "Char16";
841 mike 1.1 case MI_DATETIME:
842 return "Datetime";
843 case MI_STRING:
844 return "String";
845 case MI_REFERENCE:
846 return "Reference";
847 case MI_INSTANCE:
848 return "Instance";
849 case MI_BOOLEANA:
850 return "Boolean";
851 case MI_SINT8A:
852 return "Sint8";
853 case MI_UINT8A:
854 return "Uint8";
855 case MI_SINT16A:
856 return "Sint16";
857 case MI_UINT16A:
858 return "Uint16";
859 case MI_SINT32A:
860 return "Sint32";
861 case MI_UINT32A:
862 mike 1.1 return "Uint32";
863 case MI_SINT64A:
864 return "Sint64";
865 case MI_UINT64A:
866 return "Uint64";
867 case MI_REAL32A:
868 return "Real32";
869 case MI_REAL64A:
870 return "Real64";
871 case MI_CHAR16A:
872 return "Char16";
873 case MI_DATETIMEA:
874 return "Datetime";
875 case MI_STRINGA:
876 return "String";
877 case MI_REFERENCEA:
878 return "Reference";
879 case MI_INSTANCEA:
880 return "Instance";
881 default:
882 return "UNKNOWN";
883 mike 1.1 }
884 }
885
886 //==============================================================================
887 //
888 // CountRefs()
889 //
890 // Count how many roles (references) the given class has.
891 //
892 //==============================================================================
893
894 static size_t CountRefs(const MI_ClassDecl* cd)
895 {
896 size_t r = 0;
897
898 for (size_t i = 0; i < cd->numProperties; i++)
899 {
900 const MI_PropertyDecl* pd = cd->properties[i];
901
902 if (pd->type == MI_REFERENCE)
903 r++;
904 mike 1.1 }
905
906 return r;
907 }
908
909 //==============================================================================
910 //
911 // CanGenerateAssocRoles()
912 //
913 // returns true if:
914 // - association class has two references
915 // - ref classes are not inherited from each other
916 //
917 //==============================================================================
918
919 static bool CanGenerateAssocRoles(const MI_ClassDecl* cd)
920 {
921 if (2 != CountRefs(cd))
922 return false;
923
924 int index1 = -1, index2 = -1;
925 mike 1.1
926 for (int i = 0; i < (int)cd->numProperties; i++)
927 {
928 const MI_PropertyDecl* pd = cd->properties[i];
929
930 if (pd->type == MI_REFERENCE)
931 {
932 if (-1 == index1)
933 index1 = i;
934 else
935 index2 = i;
936 }
937 }
938
939 if (-1 == index2 ||
940 !cd->properties[index1]->className ||
941 !cd->properties[index2]->className)
942 return false;
943
944 return _Scasecmp(cd->properties[index1]->className,cd->properties[index2]->className) != 0;
945 }
946 mike 1.1
947 //==============================================================================
948 //
949 // FullTypeNameOf()
950 //
951 // Same as TypeNameOf() except that it gives the full typedef name.
952 //
953 // TypeNameOf(MI_UINT8) => "MI_Uint8"
954 //
955 //==============================================================================
956
957 static string FullTypeNameOf(MI_Uint32 type)
958 {
959 return string("MI_") + TypeNameOf(type);
960 }
961
962 //==============================================================================
963 //
964 // CppTypeNameOf()
965 //
966 // Return the Cpp type name for the given Statik type tag. For arrays type
967 mike 1.1 // tags, return the Cpp type name of the element type. For example:
968 //
969 // CppTypeNameOf(MI_UINT8) => "Uint8"
970 // CppTypeNameOf(MI_UINT8A) => "Uint8"
971 //
972 //==============================================================================
973
974 const char* CppTypeNameOf(MI_Uint32 type)
975 {
976 const char* res = TypeNameOf(type);
977
978 return res;
979 }
980
981 //==============================================================================
982 //
983 // ScalarSizeOf()
984 //
985 // Return the size of the given type; for arrays return the element size.
986 //
987 //==============================================================================
988 mike 1.1
989 INLINE MI_Uint32 ScalarSizeOf(MI_Uint32 type)
990 {
991 return (MI_Uint32)Type_SizeOf(Type_ScalarOf(MI_Type(type)));
992 }
993
994 //==============================================================================
995 //
996 // sub()
997 //
998 // Substitute all occurences of 'pattern' with 'replacement' within the
999 // 'str' parameter. Return the result.
1000 //
1001 //==============================================================================
1002
1003 string sub(
1004 const string& str,
1005 const string& pattern,
1006 const string& replacement)
1007 {
1008 size_t pos = 0;
1009 mike 1.1 string r = str;
1010
1011 while ((pos = r.find(pattern, pos)) != string::npos)
1012 {
1013 r = r.substr(0, pos) + replacement + r.substr(pos + pattern.size());
1014 pos += replacement.size();
1015 }
1016
1017 return r;
1018 }
1019
1020 //==============================================================================
1021 //
1022 // subu()
1023 //
1024 // Similiar to sub() but substitutes an unsigned integer.
1025 //
1026 //==============================================================================
1027
1028 static string subu(
1029 const string& str,
1030 mike 1.1 const string& pattern,
1031 MI_Uint32 replacement)
1032 {
1033 char buf[32];
1034 Snprintf(buf, sizeof(buf), "%u", replacement);
1035 return sub(str, pattern, buf);
1036 }
1037
1038 //==============================================================================
1039 //
1040 // subx()
1041 //
1042 // Similiar to sub() but substitutes an unsigned integer (as hex string).
1043 //
1044 //==============================================================================
1045
1046 static string subx(
1047 const string& str,
1048 const string& pattern,
1049 MI_Uint32 replacement)
1050 {
1051 mike 1.1 char buf[32];
1052 Snprintf(buf, sizeof(buf), "0x%08X", replacement);
1053 return sub(str, pattern, buf);
1054 }
1055
1056 //==============================================================================
1057 //
1058 // subd()
1059 //
1060 // Substitute all occurences of 'pattern' with the string form of
1061 // 'replacement' within the 'str' parameter.
1062 //
1063 //==============================================================================
1064
1065 #if 0
1066 static string subd(
1067 const string& str,
1068 const string& pattern,
1069 MI_Sint32 replacement)
1070 {
1071 char buf[32];
1072 mike 1.1 Snprintf(buf, sizeof(buf), "%d", replacement);
1073 return sub(str, pattern, buf);
1074 }
1075 #endif
1076
1077 //==============================================================================
1078 //
1079 // FindStandardQualifierDecl()
1080 //
1081 // Find the standard qualifier declaration with the given name.
1082 //
1083 //==============================================================================
1084
1085 static const MI_QualifierDecl* FindStandardQualifierDecl(const char* name)
1086 {
1087 for (size_t i = 0; i < g_numQualifierDecls; i++)
1088 {
1089 MI_QualifierDecl* qd = g_qualifierDecls[i];
1090
1091 if (Strcasecmp(qd->name, name) == 0)
1092 return qd;
1093 mike 1.1 }
1094 /* Not found! */
1095 return NULL;
1096 }
1097
1098 //==============================================================================
1099 //
1100 // FindPropertyDecl()
1101 //
1102 // Find the named property in the given class declarartion. Return a
1103 // pointer if found, else return NULL.
1104 //
1105 //==============================================================================
1106
1107 static const MI_PropertyDecl* FindPropertyDecl(
1108 const MI_ClassDecl* cd,
1109 const char* name)
1110 {
1111 for (size_t i = 0; i < cd->numProperties; i++)
1112 {
1113 if (Strcasecmp(cd->properties[i]->name, name) == 0)
1114 mike 1.1 return cd->properties[i];
1115 }
1116
1117 /* Not found */
1118 return NULL;
1119 }
1120
1121 //==============================================================================
1122 //
1123 // ExistInstanceQualifier
1124 //
1125 // returns 'true' if EmbeddedInstance/Object qualifier is set
1126 //
1127 //==============================================================================
1128 template< typename PropertyDeclType>
1129 bool ExistInstanceQualifier(
1130 const PropertyDeclType* pd)
1131 {
1132 for ( MI_Uint32 i = 0; i < pd->numQualifiers; i++ )
1133 {
1134 if (_Scasecmp(pd->qualifiers[i]->name,MI_T("EmbeddedInstance")) == 0)
1135 mike 1.1 return true;
1136 if (_Scasecmp(pd->qualifiers[i]->name,MI_T("EmbeddedObject")) == 0)
1137 return true;
1138 }
1139 return false;
1140 }
1141
1142 //==============================================================================
1143 //
1144 // IsPropertyRefOrInstance
1145 //
1146 // returns 'true' if property (or parameter) is
1147 // REFERENCE, REFERENCEA, EmbeddedInstance [arry], EmbeddedObject [array]
1148 //
1149 //==============================================================================
1150 template< typename PropertyDeclType>
1151 bool IsPropertyRefOrInstance(
1152 const PropertyDeclType* pd)
1153 {
1154
1155 if ((pd->type == MI_REFERENCE) || (pd->type == MI_REFERENCEA))
1156 mike 1.1 return true;
1157
1158 if ((pd->type == MI_INSTANCE) || (pd->type == MI_INSTANCEA))
1159 return true;
1160
1161 if ((pd->type == MI_STRING) || (pd->type == MI_STRINGA))
1162 return ExistInstanceQualifier<PropertyDeclType>(pd);
1163
1164 return false;
1165 }
1166
1167 //==============================================================================
1168 //
1169 // GetPropertyClassname
1170 //
1171 // returns 'class-name' of the property; only makes sense for
1172 // REFERENCE, REFERENCEA, EmbeddedInstance [arry], EmbeddedObject [array]
1173 // for EmbeddedObject returns empty string
1174 //
1175 //==============================================================================
1176 template< typename PropertyDeclType>
1177 mike 1.1 string GetPropertyClassname(
1178 const PropertyDeclType* pd)
1179 {
1180
1181 if ((pd->type == MI_REFERENCE) || (pd->type == MI_REFERENCEA))
1182 return pd->className;
1183
1184 if ((pd->type == MI_INSTANCE) || (pd->type == MI_INSTANCEA))
1185 return pd->className ? pd->className : "";
1186
1187 if ((pd->type == MI_STRING) || (pd->type == MI_STRINGA))
1188 {
1189 for ( MI_Uint32 i = 0; i < pd->numQualifiers; i++ )
1190 {
1191 if (_Scasecmp(pd->qualifiers[i]->name,MI_T("EmbeddedInstance"))==0)
1192 {
1193 if (pd->qualifiers[i]->type != MI_STRING)
1194 {
1195 err(ID_EMBEDDEDINSTANCE_ON_NON_STRING,
1196 "EmbeddedInstance qualifier on non-string type: %s",
1197 pd->name);
1198 mike 1.1 }
1199
1200 return (const MI_Char*)pd->qualifiers[i]->value;
1201 }
1202 if (_Scasecmp(pd->qualifiers[i]->name,MI_T("EmbeddedObject")) == 0)
1203 return string();
1204 }
1205 return string();
1206 }
1207
1208 return string();
1209 }
1210
1211 //==============================================================================
1212 //
1213 // GenProperties()
1214 //
1215 // This function writes properties for the MOF class currently being
1216 // generated (i.e., it generates fields for the corresponing C structure).
1217 // Properties are written in the order they are encountered when
1218 // traversing from the root of the inheritance chain to the current class.
1219 mike 1.1 // A property may be defined more than once in the inheritance chain due
1220 // to overriding. In that case, overrides by descendent classes have no
1221 // bearing on the order.
1222 //
1223 //==============================================================================
1224
1225 // Keeps track of property-name/class-name pairs.
1226 typedef map<string,string> NameClassMap;
1227 typedef pair<string,string> NameClassPair;
1228
1229 static void GenProperties(
1230 FILE* os,
1231 Parser& parser,
1232 const MI_ClassDecl* lcd, /* the leaf class in the recursion */
1233 const MI_ClassDecl* cd,
1234 NameClassMap& map)
1235 {
1236 // Inject the property-name and class-name for all reference properties
1237 // first. During recursion we want to use the class-name of the most
1238 // derived reference declaration.
1239
1240 mike 1.1 for (size_t i = 0; i < cd->numProperties; i++)
1241 {
1242 const MI_PropertyDecl* pd = cd->properties[i];
1243
1244 if (pd->type == MI_REFERENCE)
1245 {
1246 if (map.find(pd->name) == map.end())
1247 map.insert(NameClassPair(pd->name, pd->className));
1248 }
1249 }
1250
1251 // Recurse on superclass (if any) and print its properties first.
1252 if (cd->superClass)
1253 {
1254 const MI_ClassDecl* scd = parser.findClassDecl(cd->superClass);
1255
1256 if (!scd)
1257 err(ID_UNKNOWN_SUPERCLASS_FOR, "unknown superclass for %s: %s",
1258 cd->name, cd->superClass);
1259
1260 GenProperties(os, parser, lcd, scd, map);
1261 mike 1.1 }
1262
1263 // Print the local properties of this class.
1264 putl(os, " /* %s properties */", AliasOf(cd->name).c_str());
1265
1266 for (size_t i = 0; i < cd->numProperties; i++)
1267 {
1268 const MI_PropertyDecl* pd = cd->properties[i];
1269
1270 // Skip non-local properties:
1271 if (Strcasecmp(cd->name, pd->origin) != 0)
1272 continue;
1273
1274 // Indent this property.
1275 put(os, " ");
1276
1277 // Put the key attribute if the property in the leaf class has
1278 // the Key qualifier.
1279 {
1280 const MI_PropertyDecl* lpd = FindPropertyDecl(lcd, pd->name);
1281
1282 mike 1.1 if (lpd && (lpd->flags & MI_FLAG_KEY))
1283 put(os, "/*KEY*/ ");
1284 }
1285
1286 if (pd->type == MI_REFERENCE)
1287 {
1288 // If a derived class defines this property, use the classname
1289 // that it uses for the property.
1290
1291 NameClassMap::iterator p = map.find(pd->name);
1292 string al;
1293
1294 if (p == map.end())
1295 {
1296 al = AliasOf(pd->className);
1297 }
1298 else
1299 {
1300 al = AliasOf((*p).second);
1301 }
1302
1303 mike 1.1 putl(os, "%s_ConstRef %s;", al.c_str(), pd->name);
1304 }
1305 else if (pd->type == MI_REFERENCEA)
1306 {
1307 err(ID_REFERENCE_ARRAY_AS_PROPERTY,
1308 "reference arrays are not allowed as properties");
1309 }
1310 else if (IsPropertyRefOrInstance(pd) &&
1311 !GetPropertyClassname(pd).empty())
1312 { // embedded instance
1313 const string al = AliasOf(GetPropertyClassname(pd));
1314
1315 if (pd->type & MI_ARRAY_BIT)
1316 {
1317 putl(os, "%s_ConstArrayRef %s;", al.c_str(), pd->name);
1318 }
1319 else
1320 {
1321 putl(os, "%s_ConstRef %s;", al.c_str(), pd->name);
1322 }
1323 }
1324 mike 1.1 else if (IsPropertyRefOrInstance(pd) && GetPropertyClassname(pd).empty())
1325 { // embedded object
1326 if (pd->type & MI_ARRAY_BIT)
1327 {
1328 putl(os, "MI_ConstReferenceAField %s;", pd->name);
1329 }
1330 else
1331 {
1332 putl(os, "MI_ConstReferenceField %s;", pd->name);
1333 }
1334 }
1335 else if (pd->type & MI_ARRAY_BIT)
1336 {
1337 putl(os, "MI_Const%sAField %s;", TypeNameOf(pd->type),
1338 pd->name);
1339 }
1340 else
1341 {
1342 putl(os, "MI_Const%sField %s;", TypeNameOf(pd->type),
1343 pd->name);
1344 }
1345 mike 1.1 }
1346 }
1347
1348 //==============================================================================
1349 //
1350 // GenSingleParameter()
1351 //
1352 // This function generates the parameter structure, which holds the
1353 // extrinsic method parameters that are passed to an extrinsic method
1354 // provider stub. The return value is also defined in the structure whose
1355 // field name is "MIReturn".
1356 //
1357 //==============================================================================
1358 static void GenSingleParameter(
1359 FILE* os,
1360 const MI_ParameterDecl* pd)
1361 {
1362 if (pd->flags & MI_FLAG_IN && pd->flags & MI_FLAG_OUT)
1363 put(os, " /*IN-OUT*/ ");
1364 else if (pd->flags & MI_FLAG_IN)
1365 put(os, " /*IN*/ ");
1366 mike 1.1 else if (pd->flags & MI_FLAG_OUT)
1367 put(os, " /*OUT*/ ");
1368
1369 if (IsPropertyRefOrInstance(pd) && !GetPropertyClassname(pd).empty())
1370 {
1371 const string al = AliasOf(GetPropertyClassname(pd));
1372
1373 if (pd->type & MI_ARRAY_BIT)
1374 {
1375 putl(os, "%s_ConstArrayRef %s;", al.c_str(), pd->name);
1376 }
1377 else
1378 {
1379 putl(os, "%s_ConstRef %s;", al.c_str(), pd->name);
1380 }
1381 }
1382 else if (IsPropertyRefOrInstance(pd) && GetPropertyClassname(pd).empty())
1383 { // embedded object
1384 if (pd->type & MI_ARRAY_BIT)
1385 {
1386 putl(os, "MI_ConstReferenceAField %s;", pd->name);
1387 mike 1.1 }
1388 else
1389 {
1390 putl(os, "MI_ConstReferenceField %s;", pd->name);
1391 }
1392 }
1393 else if (pd->type & MI_ARRAY_BIT)
1394 {
1395 putl(os, "MI_Const%sAField %s;", TypeNameOf(pd->type),
1396 pd->name);
1397 }
1398 else
1399 {
1400 putl(os, "MI_Const%sField %s;", TypeNameOf(pd->type),
1401 pd->name);
1402 }
1403 }
1404 //==============================================================================
1405 //
1406 // GenParameters()
1407 //
1408 mike 1.1 // This function generates MOF method parameters (i.e., C fields for the
1409 // parameters structure).
1410 //
1411 //==============================================================================
1412
1413 static void GenParameters(
1414 FILE* os,
1415 const MI_ClassDecl* cd,
1416 const MI_MethodDecl* md)
1417 {
1418 for (size_t i = 0; i < md->numParameters; i++)
1419 {
1420 const MI_ParameterDecl* pd = md->parameters[i];
1421
1422 // Skip stream parameters:
1423 if (pd->flags & MI_FLAG_STREAM)
1424 {
1425 if (!(pd->type & MI_ARRAY_BIT))
1426 {
1427 err(ID_STREAM_QUALIFIER_ON_NON_ARRAY,
1428 "'Stream' qualifiers may only appear on array parameters: "
1429 mike 1.1 "%s.%s(): %s",
1430 cd->name, md->name, pd->name);
1431 }
1432
1433 if (!(pd->flags & MI_FLAG_OUT))
1434 {
1435 err(ID_STREAM_QUALIFIER_ON_NON_OUTPUT,
1436 "'Stream' qualifiers may only appear on output parameters: "
1437 "%s.%s(): %s",
1438 cd->name, md->name, pd->name);
1439 }
1440 continue;
1441 }
1442
1443 // Reject properties named "MIReturn".
1444 if (Strcasecmp(pd->name, "MIReturn") == 0)
1445 {
1446 err(ID_RESERVED_PARAMETER_NAME,
1447 "reserved parameter name: %s.%s(): %s", cd->name, md->name,
1448 pd->name);
1449 }
1450 mike 1.1
1451 GenSingleParameter(os,pd);
1452 }
1453 }
1454
1455
1456 //==============================================================================
1457 //
1458 // GenParametersStruct()
1459 //
1460 // This function generates the parameters structure, which holds the
1461 // extrinsic method parameters that are passed to an extrinsic method
1462 // provider stub. The return value is also defined in the structure whose
1463 // field name is "MIReturn".
1464 //
1465 //==============================================================================
1466
1467 static void GenParametersStruct(
1468 FILE* os,
1469 const MI_ClassDecl* cd,
1470 const MI_MethodDecl* md)
1471 mike 1.1 {
1472 const string alias = AliasOf(cd->name);
1473
1474 // Put comment box for the parameter structure name.
1475 const string str = alias + "." + md->name + "()";
1476 PutCommentBox(os, str);
1477 nl(os);
1478
1479 // Put method structure definition.
1480 putl(os, "typedef struct _%s_%s", alias.c_str(), md->name);
1481 putl(os, "{");
1482 putl(os, " MI_Instance __instance;");
1483
1484 {
1485 MI_ParameterDecl pd;
1486 memset(&pd, 0, sizeof(pd));
1487 pd.flags = MI_FLAG_PARAMETER|MI_FLAG_OUT;
1488 pd.name = (char*)"MIReturn";
1489 pd.type = md->returnType;
1490 pd.offset = sizeof(MI_Instance);
1491 pd.numQualifiers = md->numQualifiers;
1492 mike 1.1 pd.qualifiers = md->qualifiers;
1493 GenSingleParameter(os,&pd);
1494 }
1495 GenParameters(os, cd, md);
1496 putl(os, "}");
1497 putl(os, "%s_%s;", alias.c_str(), md->name);
1498 nl(os);
1499 }
1500
1501 //==============================================================================
1502 //
1503 // GenSetter()
1504 //
1505 // This function generates the 'setter' convenience functions for the
1506 // given class property or method parameter.
1507 //
1508 //==============================================================================
1509
1510 static void GenSetter(
1511 FILE* os,
1512 const MI_ClassDecl* cd,
1513 mike 1.1 const MI_MethodDecl* md,
1514 const MI_ParameterDecl* pd)
1515 {
1516 const string alias = AliasOf(cd->name);
1517 string r,r_ptr;
1518 MI_Uint32 index = (MI_Uint32)-1;
1519
1520 // Form the structure prefix (<ALIAS> for classes, <ALIAS><METH> for
1521 // methods.
1522 string prefix = alias;
1523
1524 if (md)
1525 {
1526 prefix += "_";
1527 prefix += md->name;
1528 }
1529
1530 // Find index of this property.
1531 if (md)
1532 {
1533 if (strcmp(pd->name, "MIReturn") == 0)
1534 mike 1.1 {
1535 index = 0;
1536 }
1537 else
1538 {
1539 for (MI_Uint32 i = 0; i < md->numParameters; i++)
1540 {
1541 if (md->parameters[i] == pd)
1542 {
1543 index = i;
1544 break;
1545 }
1546 }
1547
1548 // Increment parameter index to make room for insertion of
1549 // the "MIReturn" pseudo-parameter.
1550 index++;
1551 }
1552 }
1553 else
1554 {
1555 mike 1.1 for (MI_Uint32 i = 0; i < cd->numProperties; i++)
1556 {
1557 if (cd->properties[i] == (MI_PropertyDecl*)pd)
1558 {
1559 index = i;
1560 break;
1561 }
1562 }
1563 }
1564
1565 if (index == (MI_Uint32)-1)
1566 err(ID_INTERNAL_ERROR, "internal error: %s(%u)", __FILE__, __LINE__);
1567
1568 // Generate *_Set_* and *_SetPtr_* functions.
1569
1570 if (pd->type & MI_ARRAY_BIT)
1571 {
1572 const char T[] =
1573 "MI_INLINE MI_Result MI_CALL <PREFIX><SET><PROP>(\n"
1574 " <PREFIX>* self,\n"
1575 " const <TYPEEXPR>* data,\n"
1576 mike 1.1 " MI_Uint32 size)\n"
1577 "{\n"
1578 " MI_Array arr;\n"
1579 " arr.data = (void*)data;\n"
1580 " arr.size = size;\n"
1581 " return self->__instance.ft->SetElementAt(\n"
1582 " (MI_Instance*)&self->__instance,\n"
1583 " <INDEX>,\n"
1584 " (MI_Value*)&arr,\n"
1585 " <TYPE>,\n"
1586 " <COPY_FLAG>);\n"
1587 "}\n"
1588 "\n";
1589
1590 r = T;
1591
1592 r = sub(r, "<PREFIX>", prefix);
1593 r = sub(r, "<PROP>", pd->name);
1594 r = subu(r, "<INDEX>", index);
1595
1596 if (pd->type == MI_REFERENCEA)
1597 mike 1.1 r = sub(r, "<TYPEEXPR>", AliasOf(pd->className) + "* const");
1598 else if (pd->type == MI_STRINGA && IsPropertyRefOrInstance(pd) && !GetPropertyClassname(pd).empty())
1599 {
1600 r = sub(r, "<TYPEEXPR>", AliasOf(GetPropertyClassname(pd)) + string(" * const "));
1601 r = sub(r, "<TYPE>", "MI_INSTANCEA");
1602 }
1603 else if (pd->type == MI_STRINGA && IsPropertyRefOrInstance(pd) && GetPropertyClassname(pd).empty())
1604 {
1605 r = sub(r, "<TYPEEXPR>", "MI_Instance * const ");
1606 r = sub(r, "<TYPE>", "MI_INSTANCEA");
1607 }
1608 else if (pd->type == MI_STRINGA)
1609 r = sub(r, "<TYPEEXPR>", "MI_Char*");
1610 else
1611 r = sub(r, "<TYPEEXPR>", FullTypeNameOf(pd->type));
1612
1613 r = sub(r, "<TYPE>", MakeType(pd->type));
1614
1615 r_ptr = r;
1616 // non-copying version has to be created from initial template
1617 // otherwise name conflict is possible if function name is 'Set'
1618 mike 1.1 r = sub(r, "<SET>", "_Set_");
1619 r = sub(r, "<COPY_FLAG>", "0");
1620 r_ptr = sub(r_ptr, "<SET>", "_SetPtr_");
1621 r_ptr = sub(r_ptr, "<COPY_FLAG>", "MI_FLAG_BORROW");
1622 puts(os, r);
1623 puts(os, r_ptr);
1624 }
1625 else if (IsPropertyRefOrInstance(pd))
1626 {
1627 const char T[] =
1628 "MI_INLINE MI_Result MI_CALL <PREFIX><SET><PROP>(\n"
1629 " <PREFIX>* self,\n"
1630 " const <REFCLASSNAME>* x)\n"
1631 "{\n"
1632 " return self->__instance.ft->SetElementAt(\n"
1633 " (MI_Instance*)&self->__instance,\n"
1634 " <INDEX>,\n"
1635 " (MI_Value*)&x,\n"
1636 " <TYPE>,\n"
1637 " <COPY_FLAG>);\n"
1638 "}\n"
1639 mike 1.1 "\n";
1640
1641 r = T;
1642 r = sub(r, "<PREFIX>", prefix);
1643 r = sub(r, "<PROP>", pd->name);
1644 r = subu(r, "<INDEX>", index);
1645 r = sub(r, "<TYPE>", pd->type == MI_REFERENCE ? "MI_REFERENCE" : "MI_INSTANCE");
1646
1647 if (!GetPropertyClassname(pd).empty())
1648 r = sub(r, "<REFCLASSNAME>", AliasOf(GetPropertyClassname(pd)));
1649 else
1650 r = sub(r, "<REFCLASSNAME>", "MI_Instance");
1651
1652 r_ptr = r;
1653 // non-copying version has to be created from initial template
1654 // otherwise name conflict is possible if function name is 'Set'
1655 r = sub(r, "<SET>", "_Set_");
1656 r = sub(r, "<COPY_FLAG>", "0");
1657 r_ptr = sub(r_ptr, "<SET>", "_SetPtr_");
1658 r_ptr = sub(r_ptr, "<COPY_FLAG>", "MI_FLAG_BORROW");
1659 puts(os, r);
1660 mike 1.1 puts(os, r_ptr);
1661 }
1662 else if (pd->type == MI_STRING)
1663 {
1664 const char T[] =
1665 "MI_INLINE MI_Result MI_CALL <PREFIX><SET><PROP>(\n"
1666 " <PREFIX>* self,\n"
1667 " const MI_Char* str)\n"
1668 "{\n"
1669 " return self->__instance.ft->SetElementAt(\n"
1670 " (MI_Instance*)&self->__instance,\n"
1671 " <INDEX>,\n"
1672 " (MI_Value*)&str,\n"
1673 " MI_STRING,\n"
1674 " <COPY_FLAG>);\n"
1675 "}\n"
1676 "\n";
1677
1678 r = T;
1679 r = sub(r, "<PREFIX>", prefix);
1680 r = sub(r, "<PROP>", pd->name);
1681 mike 1.1 r = subu(r, "<INDEX>", index);
1682
1683 r_ptr = r;
1684 // non-copying version has to be created from initial template
1685 // otherwise name conflict is possible if function name is 'Set'
1686 r = sub(r, "<SET>", "_Set_");
1687 r = sub(r, "<COPY_FLAG>", "0");
1688 r_ptr = sub(r_ptr, "<SET>", "_SetPtr_");
1689 r_ptr = sub(r_ptr, "<COPY_FLAG>", "MI_FLAG_BORROW");
1690 puts(os, r);
1691 puts(os, r_ptr);
1692 }
1693 else
1694 {
1695 const char T[] =
1696 "MI_INLINE MI_Result MI_CALL <PREFIX>_Set_<PROP>(\n"
1697 " <PREFIX>* self,\n"
1698 " MI_<TYPENAME> x)\n"
1699 "{\n"
1700 " ((MI_<TYPENAME>Field*)&self-><PROP>)->value = x;\n"
1701 " ((MI_<TYPENAME>Field*)&self-><PROP>)->exists = 1;\n"
1702 mike 1.1 " return MI_RESULT_OK;\n"
1703 "}\n"
1704 "\n";
1705
1706 r = T;
1707 r = sub(r, "<PREFIX>", prefix);
1708 r = sub(r, "<PROP>", pd->name);
1709 r = sub(r, "<TYPENAME>", TypeNameOf(pd->type));
1710 puts(os, r);
1711 }
1712
1713 // Generate *_Clear_* function.
1714
1715 if ((pd->type & MI_ARRAY_BIT) != 0 ||
1716 pd->type == MI_STRING ||
1717 pd->type == MI_REFERENCE ||
1718 pd->type == MI_INSTANCE)
1719 {
1720 const char T[] =
1721 "MI_INLINE MI_Result MI_CALL <PREFIX>_Clear_<PROP>(\n"
1722 " <PREFIX>* self)\n"
1723 mike 1.1 "{\n"
1724 " return self->__instance.ft->ClearElementAt(\n"
1725 " (MI_Instance*)&self->__instance,\n"
1726 " <INDEX>);\n"
1727 "}\n"
1728 "\n";
1729
1730 r = T;
1731 r = sub(r, "<PREFIX>", prefix);
1732 r = sub(r, "<PROP>", pd->name);
1733 r = subu(r, "<INDEX>", index);
1734 puts(os, r);
1735 }
1736 else
1737 {
1738 const char T[] =
1739 "MI_INLINE MI_Result MI_CALL <PREFIX>_Clear_<PROP>(\n"
1740 " <PREFIX>* self)\n"
1741 "{\n"
1742 " memset((void*)&self-><PROP>, 0, sizeof(self-><PROP>));\n"
1743 " return MI_RESULT_OK;\n"
1744 mike 1.1 "}\n"
1745 "\n";
1746
1747 r = T;
1748 r = sub(r, "<PREFIX>", prefix);
1749 r = sub(r, "<PROP>", pd->name);
1750 puts(os, r);
1751 }
1752
1753 #if 0
1754 // Generate function to obtain the flags for this property:
1755 {
1756 const char T[] =
1757 "MI_INLINE MI_Result MI_CALL <PREFIX>_GetFlags_<PROP>(\n"
1758 " const <PREFIX>* self,\n"
1759 " MI_Uint32* flags)\n"
1760 "{\n"
1761 " return self->__instance.ft->GetElementAt(&self->__instance,\n"
1762 " <INDEX>, NULL, NULL, NULL, flags);\n"
1763 "}\n"
1764 "\n";
1765 mike 1.1
1766 r = T;
1767 r = sub(r, "<PREFIX>", prefix);
1768 r = sub(r, "<PROP>", pd->name);
1769 r = subu(r, "<INDEX>", index);
1770 puts(os, r);
1771 }
1772 #endif
1773 }
1774
1775 //==============================================================================
1776 //
1777 // GenInstanceFunctions()
1778 //
1779 // This function generates the 'initInstance' convenience function for the
1780 // given class.
1781 //
1782 //==============================================================================
1783
1784 static void GenInstanceFunctions(
1785 FILE* os,
1786 mike 1.1 const MI_ClassDecl* cd)
1787 {
1788 const string alias = AliasOf(cd->name);
1789
1790 const char T[] =
1791 "MI_INLINE MI_Result MI_CALL <ALIAS>_Construct(\n"
1792 " <ALIAS>* self,\n"
1793 " MI_Context* context)\n"
1794 "{\n"
1795 " return MI_ConstructInstance(context, &<ALIAS>_rtti,\n"
1796 " (MI_Instance*)&self->__instance);\n"
1797 "}\n"
1798 "\n"
1799 "MI_INLINE MI_Result MI_CALL <ALIAS>_Clone(\n"
1800 " const <ALIAS>* self,\n"
1801 " <ALIAS>** newInstance)\n"
1802 "{\n"
1803 " return MI_Instance_Clone(\n"
1804 " &self->__instance, (MI_Instance**)newInstance);\n"
1805 "}\n"
1806 "\n"
1807 mike 1.1 "MI_INLINE MI_Boolean MI_CALL <ALIAS>_IsA(\n"
1808 " const MI_Instance* self)\n"
1809 "{\n"
1810 " MI_Boolean res = MI_FALSE;\n"
1811 " return MI_Instance_IsA(self, &<ALIAS>_rtti, &res) == MI_RESULT_OK && res;\n"
1812 "}\n"
1813 "\n"
1814 "MI_INLINE MI_Result MI_CALL <ALIAS>_Destruct(<ALIAS>* self)\n"
1815 "{\n"
1816 " return MI_Instance_Destruct(&self->__instance);\n"
1817 "}\n"
1818 "\n"
1819 "MI_INLINE MI_Result MI_CALL <ALIAS>_Delete(<ALIAS>* self)\n"
1820 "{\n"
1821 " return MI_Instance_Delete(&self->__instance);\n"
1822 "}\n"
1823 "\n"
1824 "MI_INLINE MI_Result MI_CALL <ALIAS>_Post(\n"
1825 " const <ALIAS>* self,\n"
1826 " MI_Context* context)\n"
1827 "{\n"
1828 mike 1.1 " return MI_PostInstance(context, &self->__instance);\n"
1829 "}\n"
1830 "\n";
1831
1832 string r = T;
1833 r = sub(r, "<ALIAS>", alias);
1834 puts(os, r);
1835 }
1836
1837 //==============================================================================
1838 //
1839 // GenMethodFunctions()
1840 //
1841 // This function generates convenience functions for the given method.
1842 //
1843 //==============================================================================
1844
1845 static void GenMethodFunctions(
1846 FILE* os,
1847 const MI_ClassDecl* cd,
1848 const MI_MethodDecl* md)
1849 mike 1.1 {
1850 const string alias = AliasOf(cd->name);
1851
1852 const char T[] =
1853 "MI_EXTERN_C MI_CONST MI_MethodDecl <ALIAS>_<METH>_rtti;\n"
1854 "\n"
1855 "MI_INLINE MI_Result MI_CALL <ALIAS>_<METH>_Construct(\n"
1856 " <ALIAS>_<METH>* self,\n"
1857 " MI_Context* context)\n"
1858 "{\n"
1859 " return MI_ConstructParameters(context, &<ALIAS>_<METH>_rtti,\n"
1860 " (MI_Instance*)&self->__instance);\n"
1861 "}\n"
1862 "\n"
1863 "MI_INLINE MI_Result MI_CALL <ALIAS>_<METH>_Clone(\n"
1864 " const <ALIAS>_<METH>* self,\n"
1865 " <ALIAS>_<METH>** newInstance)\n"
1866 "{\n"
1867 " return MI_Instance_Clone(\n"
1868 " &self->__instance, (MI_Instance**)newInstance);\n"
1869 "}\n"
1870 mike 1.1 "\n"
1871 "MI_INLINE MI_Result MI_CALL <ALIAS>_<METH>_Destruct(\n"
1872 " <ALIAS>_<METH>* self)\n"
1873 "{\n"
1874 " return MI_Instance_Destruct(&self->__instance);\n"
1875 "}\n"
1876 "\n"
1877 "MI_INLINE MI_Result MI_CALL <ALIAS>_<METH>_Delete(\n"
1878 " <ALIAS>_<METH>* self)\n"
1879 "{\n"
1880 " return MI_Instance_Delete(&self->__instance);\n"
1881 "}\n"
1882 "\n"
1883 "MI_INLINE MI_Result MI_CALL <ALIAS>_<METH>_Post(\n"
1884 " const <ALIAS>_<METH>* self,\n"
1885 " MI_Context* context)\n"
1886 "{\n"
1887 " return MI_PostInstance(context, &self->__instance);\n"
1888 "}\n"
1889 "\n";
1890
1891 mike 1.1 string r = T;
1892 r = sub(r, "<ALIAS>", alias);
1893 r = sub(r, "<METH>", md->name);
1894 puts(os, r);
1895 }
1896
1897 //==============================================================================
1898 //
1899 // FindDirectDependencies
1900 //
1901 // Find classes that this class depends (via superclasses and references).
1902 //
1903 //==============================================================================
1904
1905 static void FindDirectDependencies(
1906 const MI_ClassDecl* cd,
1907 vector<string>& deps)
1908 {
1909 // Find super classes.
1910 if (cd->superClass)
1911 deps.push_back(cd->superClass);
1912 mike 1.1
1913 // Find property reference dependencies.
1914 for (MI_Uint32 i = 0; i < cd->numProperties; i++)
1915 {
1916 MI_PropertyDecl* pd = cd->properties[i];
1917
1918 if (IsPropertyRefOrInstance(pd))
1919 {
1920 string cn = GetPropertyClassname(pd);
1921
1922 if (!cn.empty() && !Contains(deps, cn))
1923 deps.push_back(cn);
1924 }
1925 }
1926
1927 // Find parameter reference dependencies.
1928 for (MI_Uint32 i = 0; i < cd->numMethods; i++)
1929 {
1930 MI_MethodDecl* md = cd->methods[i];
1931
1932 // check return type
1933 mike 1.1 {
1934 MI_ParameterDecl pd;
1935 memset(&pd, 0, sizeof(pd));
1936 pd.flags = MI_FLAG_PARAMETER|MI_FLAG_OUT;
1937 pd.name = (char*)"MIReturn";
1938 pd.type = md->returnType;
1939 pd.offset = sizeof(MI_Instance);
1940 pd.numQualifiers = md->numQualifiers;
1941 pd.qualifiers = md->qualifiers;
1942
1943 if (IsPropertyRefOrInstance(&pd))
1944 {
1945 string cn = GetPropertyClassname(&pd);
1946
1947 if (!cn.empty() && !Contains(deps, cn))
1948 deps.push_back(cn);
1949 }
1950 }
1951
1952 for (MI_Uint32 j = 0; j < md->numParameters; j++)
1953 {
1954 mike 1.1 MI_ParameterDecl* pd = md->parameters[j];
1955
1956 if (IsPropertyRefOrInstance(pd))
1957 {
1958 string cn = GetPropertyClassname(pd);
1959
1960 if (!cn.empty() && !Contains(deps, cn))
1961 deps.push_back(cn);
1962 }
1963 }
1964 }
1965 }
1966
1967 //==============================================================================
1968 //
1969 // PutCppPropertyAccessor
1970 //
1971 // Generate inline functions to access a single property
1972 //
1973 //==============================================================================
1974 template< typename PropertyDeclType>
1975 mike 1.1 void PutCppPropertyAccessor(
1976 FILE* os,
1977 const PropertyDeclType* pd,
1978 const string& alias)
1979 {
1980 const char T[] =
1981 " //\n"
1982 " // =ALIAS=_Class.=NAME=\n"
1983 " //\n"
1984 " \n"
1985 " const Field<=TYPE=>& =NAME=() const\n"
1986 " {\n"
1987 " const size_t n = offsetof(Self, =NAME=);\n"
1988 " return GetField<=TYPE=>(n);\n"
1989 " }\n"
1990 " \n"
1991 " void =NAME=(const Field<=TYPE=>& x)\n"
1992 " {\n"
1993 " const size_t n = offsetof(Self, =NAME=);\n"
1994 " GetField<=TYPE=>(n) = x;\n"
1995 " }\n"
1996 mike 1.1 " \n"
1997 " const =TYPE=& =NAME=_value() const\n"
1998 " {\n"
1999 " const size_t n = offsetof(Self, =NAME=);\n"
2000 " return GetField<=TYPE=>(n).value;\n"
2001 " }\n"
2002 " \n"
2003 " void =NAME=_value(const =TYPE=& x)\n"
2004 " {\n"
2005 " const size_t n = offsetof(Self, =NAME=);\n"
2006 " GetField<=TYPE=>(n).Set(x);\n"
2007 " }\n"
2008 " \n"
2009 " bool =NAME=_exists() const\n"
2010 " {\n"
2011 " const size_t n = offsetof(Self, =NAME=);\n"
2012 " return GetField<=TYPE=>(n).exists ? true : false;\n"
2013 " }\n"
2014 " \n"
2015 " void =NAME=_clear()\n"
2016 " {\n"
2017 mike 1.1 " const size_t n = offsetof(Self, =NAME=);\n"
2018 " GetField<=TYPE=>(n).Clear();\n"
2019 " }\n";
2020
2021 string r = sub(T, "=ALIAS=", alias);
2022
2023 if (IsPropertyRefOrInstance<PropertyDeclType>(pd) &&
2024 !GetPropertyClassname<PropertyDeclType>(pd).empty())
2025 {
2026 const string al = AliasOf(GetPropertyClassname<PropertyDeclType>(pd));
2027
2028 if (pd->type & MI_ARRAY_BIT)
2029 {
2030 r = sub(r, "=TYPE=", al + "_ClassA");
2031 }
2032 else
2033 {
2034 r = sub(r, "=TYPE=", al + "_Class");
2035 }
2036 }
2037 else if (IsPropertyRefOrInstance<PropertyDeclType>(pd) &&
2038 mike 1.1 GetPropertyClassname<PropertyDeclType>(pd).empty())
2039 { // embedded object
2040 const string al = AliasOf(GetPropertyClassname<PropertyDeclType>(pd));
2041
2042 if (pd->type & MI_ARRAY_BIT)
2043 r = sub(r, "=TYPE=", "InstanceA");
2044 else
2045 r = sub(r, "=TYPE=", "Instance");
2046 }
2047 else if (pd->type & MI_ARRAY_BIT)
2048 {
2049 r = sub(r, "=TYPE=", string(CppTypeNameOf(pd->type)) + "A");
2050 }
2051 else
2052 {
2053 r = sub(r, "=TYPE=", CppTypeNameOf(pd->type));
2054 }
2055
2056 r = sub(r, "=NAME=", pd->name);
2057
2058 puts(os, r);
2059 mike 1.1 }
2060
2061 //==============================================================================
2062 //
2063 // getReturnType
2064 //
2065 // returns 'return-type' for funciton declaration; for instances return false
2066 //
2067 //==============================================================================
2068 template< typename ClassDeclType, typename PropertyDeclType>
2069 bool getReturnType(const ClassDeclType* cd, MI_Uint32& type);
2070
2071 template<>
2072 bool getReturnType<MI_ClassDecl,_MI_PropertyDecl>(
2073 const MI_ClassDecl* ,
2074 MI_Uint32& )
2075 {
2076 return false;
2077 }
2078
2079 template<>
2080 mike 1.1 bool getReturnType<MI_MethodDecl,_MI_ParameterDecl>(
2081 const MI_MethodDecl* cd,
2082 MI_Uint32& type)
2083 {
2084 type = cd->returnType;
2085 return true;
2086 }
2087
2088 //==============================================================================
2089 //
2090 // isPropertyLocal
2091 //
2092 // checks if rpoerty is local
2093 //
2094 //==============================================================================
2095 template< typename ClassDeclType, typename PropertyDeclType>
2096 bool isPropertyLocal(const ClassDeclType* , const PropertyDeclType* );
2097
2098 template<>
2099 bool isPropertyLocal<MI_ClassDecl,_MI_PropertyDecl>(
2100 const MI_ClassDecl* cd,
2101 mike 1.1 const _MI_PropertyDecl* pd)
2102 {
2103 return Strcasecmp(cd->name, pd->origin) == 0;
2104 }
2105
2106 template<>
2107 bool isPropertyLocal<MI_MethodDecl,_MI_ParameterDecl>(
2108 const MI_MethodDecl*,
2109 const _MI_ParameterDecl*)
2110 {
2111 return true;
2112 }
2113
2114 //==============================================================================
2115 //
2116 // HashKeys()
2117 //
2118 // Return true if the given class declaration has any key properties.
2119 //
2120 //==============================================================================
2121
2122 mike 1.1 static bool HasKeys(const MI_ClassDecl* cd)
2123 {
2124 for (MI_Uint32 i = 0; i < cd->numProperties; i++)
2125 {
2126 if (cd->properties[i]->flags & MI_FLAG_KEY)
2127 return true;
2128 }
2129
2130 // No keys found!
2131 return false;
2132 }
2133
2134 //==============================================================================
2135 //
2136 // GenCppPropertiesAccessors
2137 //
2138 // Generate C++ class property accessors funciotns
2139 //
2140 //==============================================================================
2141 template< typename ClassDeclType, typename PropertyDeclType>
2142 void GenCppPropertiesAccessors(
2143 mike 1.1 FILE* os,
2144 const ClassDeclType* cd,
2145 const string& alias,
2146 size_t numProperties,
2147 PropertyDeclType** const properties )
2148 {
2149 // Print the local properties of this class.
2150 {
2151 // put MIReturn if it's a method
2152 MI_Uint32 type = 0;
2153 if (getReturnType<ClassDeclType, PropertyDeclType>(cd,type))
2154 {
2155 MI_ParameterDecl pd;
2156 memset(&pd, 0, sizeof(pd));
2157 pd.flags = MI_FLAG_PARAMETER|MI_FLAG_OUT;
2158 pd.name = (char*)"MIReturn";
2159 pd.type = type;
2160 pd.offset = sizeof(MI_Instance);
2161 pd.numQualifiers = cd->numQualifiers;
2162 pd.qualifiers = cd->qualifiers;
2163
2164 mike 1.1 PutCppPropertyAccessor<MI_ParameterDecl>(os,&pd,alias);
2165
2166 if (numProperties)
2167 nl(os);
2168 }
2169 }
2170
2171 for (size_t i = 0; i < numProperties; i++)
2172 {
2173 const PropertyDeclType* pd = properties[i];
2174
2175 // Skip non-local properties:
2176 if (!isPropertyLocal(cd,pd))
2177 continue;
2178
2179 // Skip stream parameters:
2180 if (pd->flags & MI_FLAG_STREAM)
2181 continue;
2182
2183 // generate skeleton
2184 PutCppPropertyAccessor<PropertyDeclType>(os,pd,alias);
2185 mike 1.1
2186 if (i +1 != numProperties)
2187 nl(os);
2188 }
2189 }
2190
2191 //==============================================================================
2192 //
2193 // GenCppClassDeclaration
2194 //
2195 // Generate C++ class
2196 //
2197 //==============================================================================
2198 template< typename ClassDeclType, typename PropertyDeclType>
2199 void GenCppClassDeclaration(
2200 FILE* os,
2201 const ClassDeclType* cd,
2202 const string& alias,
2203 const char* superClass,
2204 size_t numProperties,
2205 PropertyDeclType** const properties )
2206 mike 1.1 {
2207 ////////////////////////////////////////
2208 // class definition
2209 {
2210 const char T[] =
2211 "class <ALIAS>_Class : public <BASE>\n"
2212 "{\n"
2213 "public:\n"
2214 " \n"
2215 " typedef <ALIAS> Self;\n"
2216 " \n"
2217 " <ALIAS>_Class() :\n"
2218 " <BASE>(&<ALIAS>_rtti)\n"
2219 " {\n"
2220 " }\n"
2221 " \n"
2222 " <ALIAS>_Class(\n"
2223 " const <ALIAS>* instanceName,\n"
2224 " bool keysOnly) :\n"
2225 " <BASE>(\n"
2226 " &<ALIAS>_rtti,\n"
2227 mike 1.1 " &instanceName->__instance,\n"
2228 " keysOnly)\n"
2229 " {\n"
2230 " }\n"
2231 " \n"
2232 " <ALIAS>_Class(\n"
2233 " const MI_ClassDecl* clDecl,\n"
2234 " const MI_Instance* instance,\n"
2235 " bool keysOnly) :\n"
2236 " <BASE>(clDecl, instance, keysOnly)\n"
2237 " {\n"
2238 " }\n"
2239 " \n"
2240 " <ALIAS>_Class(\n"
2241 " const MI_ClassDecl* clDecl) :\n"
2242 " <BASE>(clDecl)\n"
2243 " {\n"
2244 " }\n"
2245 " \n"
2246 " <ALIAS>_Class& operator=(\n"
2247 " const <ALIAS>_Class& x)\n"
2248 mike 1.1 " {\n"
2249 " CopyRef(x);\n"
2250 " return *this;\n"
2251 " }\n"
2252 " \n"
2253 " <ALIAS>_Class(\n"
2254 " const <ALIAS>_Class& x) :\n"
2255 " <BASE>(x)\n"
2256 " {\n"
2257 " }\n"
2258 "\n";
2259 const char S[] =
2260 " static const MI_ClassDecl* GetClassDecl()\n"
2261 " {\n"
2262 " return &<ALIAS>_rtti;\n"
2263 " }\n"
2264 "\n";
2265
2266 string r = sub(T, "<ALIAS>", alias);
2267
2268 if (superClass)
2269 mike 1.1 {
2270 string tmp = AliasOf(superClass) + "_Class";
2271 r = sub(r, "<BASE>", tmp);
2272 }
2273 else
2274 {
2275 r = sub(r, "<BASE>", "Instance");
2276 }
2277 puts(os, r);
2278
2279 if (cd->flags & MI_FLAG_CLASS)
2280 {
2281 r = sub(S, "<ALIAS>", alias);
2282 puts(os, r);
2283 }
2284
2285 }
2286
2287 /// inline funciotns for property access
2288 GenCppPropertiesAccessors<ClassDeclType,PropertyDeclType>(
2289 os,cd,alias,numProperties,properties);
2290 mike 1.1
2291 /// end class
2292 {
2293 const char T[] =
2294 "};\n"
2295 "\n"
2296 "typedef Array<<ALIAS>_Class> <ALIAS>_ClassA;\n"
2297 "\n"
2298 ;
2299
2300 string r = sub(T, "<ALIAS>", alias);
2301 puts(os, r);
2302 }
2303 }
2304
2305 //==============================================================================
2306 //
2307 // SubRoles()
2308 //
2309 // Substitute <ROLE1>, <ROLE2>, <ALIAS1>, and <ALIAS2> with
2310 // property names and classnames for the first and second references
2311 mike 1.1 // (roles) in this class.
2312 //
2313 //==============================================================================
2314
2315 static void SubRoles(const MI_ClassDecl* cd, string& r)
2316 {
2317 size_t role = 1;
2318
2319 for (size_t i = 0; i < cd->numProperties; i++)
2320 {
2321 const MI_PropertyDecl* pd = cd->properties[i];
2322
2323 if (pd->type == MI_REFERENCE)
2324 {
2325 if (role == 1)
2326 {
2327 r = sub(r, "<ROLE1>", pd->name);
2328 r = sub(r, "<ALIAS1>", AliasOf(pd->className).c_str());
2329 role++;
2330 }
2331 else if (role == 2)
2332 mike 1.1 {
2333 r = sub(r, "<ROLE2>", pd->name);
2334 r = sub(r, "<ALIAS2>", AliasOf(pd->className).c_str());
2335 role++;
2336 }
2337 else if (role == 3)
2338 {
2339 err(ID_INTERNAL_ERROR, "internal error: %s(%u)", __FILE__,
2340 __LINE__);
2341 }
2342 }
2343 }
2344 }
2345
2346 //==============================================================================
2347 //
2348 // GenCppClassProviderHeaderNewFile
2349 //
2350 // Generate class provider declaration
2351 // used only to create a new file
2352 //
2353 mike 1.1 //==============================================================================
2354 static void GenCppClassProviderHeaderNewFile(
2355 FILE* os,
2356 const MI_ClassDecl* cd)
2357 {
2358 string alias = AliasOf(cd->name);
2359 GenStatikGenLine(os);
2360
2361 // Prevent multiple inclusion.
2362 putl(os, "#ifndef _%s_Class_Provider_h", alias.c_str());
2363 putl(os, "#define _%s_Class_Provider_h", alias.c_str());
2364 nl(os);
2365
2366 // Include instance class
2367 putl(os, "#include \"%s.h\"", alias.c_str());
2368
2369
2370 // standard starting part
2371 putl(os, "#ifdef __cplusplus");
2372 putl(os, "# include <micxx/micxx.h>");
2373 putl(os, "# include \"module.h\"");
2374 mike 1.1 nl(os);
2375 putl(os, "MI_BEGIN_NAMESPACE");
2376 nl(os);
2377
2378
2379 // Write the intrinsic provider function prototypes.
2380 {
2381 PutCommentBox(os, alias + " provider class declaration");
2382 nl(os);
2383
2384 // Generate forward typedef for Self structure.
2385 string extraDataMemebers;
2386
2387 if (cd->flags & MI_FLAG_ASSOCIATION)
2388 {
2389 string r;
2390
2391 if (!s_options.association && CanGenerateAssocRoles(cd))
2392 {
2393 r = ASSOCIATION_PROVIDER_CLASS_DECLARATION_ROLES;
2394 SubRoles(cd, r);
2395 mike 1.1 }
2396 else
2397 r = ASSOCIATION_PROVIDER_CLASS_DECLARATION;
2398
2399 r = sub(r, "<ALIAS>", alias);
2400 r = sub(r, "<DATA_MEMBERS>", extraDataMemebers);
2401 puts(os, r);
2402 }
2403 else if (cd->flags & MI_FLAG_INDICATION)
2404 {
2405 string r = INDICATION_PROVIDER_CLASS_DECLARATION;
2406 extraDataMemebers = " MI_Context* m_IndicationsContext;\n";
2407 r = sub(r, "<ALIAS>", alias);
2408 r = sub(r, "<DATA_MEMBERS>", extraDataMemebers);
2409 puts(os, r);
2410 }
2411 else
2412 {
2413 string r = INSTANCE_PROVIDER_CLASS_DECLARATION;
2414 r = sub(r, "<ALIAS>", alias);
2415 r = sub(r, "<DATA_MEMBERS>", extraDataMemebers);
2416 mike 1.1 puts(os, r);
2417 }
2418 }
2419
2420 // Write the extrinsic provider function prototypes.
2421 {
2422 for (size_t i = 0; i < cd->numMethods; i++)
2423 {
2424 const MI_MethodDecl* md = cd->methods[i];
2425 string r = sub(EXTRINSIC_METHOD_PROVIDER_CLASS_DECLARATION,
2426 "<ALIAS>", alias);
2427 r = sub(r, "<METHOD>", md->name);
2428 puts(os, r);
2429 }
2430 }
2431
2432 // close class declaration
2433 putl(os, COMMON_PROVIDER_CLASS_DECLARATION_END);
2434 putl(os,"};");
2435 nl(os);
2436
2437 mike 1.1
2438 // end c++ specific part
2439 putl(os, "MI_END_NAMESPACE");
2440 nl(os);
2441 putl(os, "#endif /* __cplusplus */");
2442 nl(os);
2443 putl(os, "#endif /* _%s_Class_Provider_h */", alias.c_str());
2444 nl(os);
2445 }
2446
2447 //==============================================================================
2448 //
2449 // GenCppClassProviderHeader
2450 //
2451 // Generate class provider declaration
2452 // Support patching of methods
2453 //
2454 //==============================================================================
2455 static void GenCppClassProviderHeader(
2456 const MI_ClassDecl* cd)
2457 {
2458 mike 1.1 string alias = AliasOf(cd->name);
2459
2460 // create/patch provider class declaration file.
2461 const string path = ExpandPath(alias + "_Class_Provider.h");
2462 bool append;
2463 vector<char> data;
2464 {
2465 append = Exists(path.c_str());
2466
2467 if (append)
2468 {
2469 if (!Inhale(path.c_str(), data))
2470 {
2471 err(ID_FAILED_TO_READ_FILE, "failed to read file: %s",
2472 path.c_str());
2473 }
2474 }
2475 else
2476 {
2477 FILE* os = Fopen(path.c_str(), "w");
2478
2479 mike 1.1 if (!os)
2480 {
2481 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s",
2482 path.c_str());
2483 }
2484
2485 Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
2486 GenCppClassProviderHeaderNewFile(os,cd);
2487 fclose(os);
2488 return;
2489 }
2490 }
2491
2492
2493 // patch existing file
2494 data.push_back(0);
2495 string str_data = &data[0];
2496
2497 /* remove \r*/
2498 str_data = sub(str_data, "\r", "");
2499
2500 mike 1.1 if (str_data.find(COMMON_PROVIDER_CLASS_DECLARATION_END) == string::npos)
2501 {
2502 err(ID_FAILED_TO_FIND_PATCH_MARKER,
2503 "failed to find patch marker (%s) in file %s",
2504 COMMON_PROVIDER_CLASS_DECLARATION_END,
2505 path.c_str());
2506 }
2507
2508 bool patched = false;
2509
2510 // Add Load/Unload functions if missing
2511 if (str_data.find("void Unload(") == string::npos)
2512 {
2513 if (!patched)
2514 {
2515 Fprintf(s_stdout, ID_PATCHING, "Patching %s\n", path.c_str());
2516 patched = true;
2517 }
2518
2519 str_data = sub(str_data, COMMON_PROVIDER_CLASS_DECLARATION_END,
2520 COMMON_PROVIDER_LOAD_UNLOAD_DECLARATION COMMON_PROVIDER_CLASS_DECLARATION_END);
2521 mike 1.1 }
2522
2523 // Generate extrinsic method declarations (only new one).
2524 for (size_t i = 0; i < cd->numMethods; i++)
2525 {
2526 const MI_MethodDecl* md = cd->methods[i];
2527 string r = sub(EXTRINSIC_METHOD_PROVIDER_CLASS_DECLARATION, "<ALIAS>",
2528 alias);
2529 r = sub(r, "<METHOD>", md->name);
2530
2531 string name = string("Invoke_") + md->name;
2532
2533 // Skip methods already found in file.
2534 if (str_data.find(name) != string::npos)
2535 continue;
2536
2537 if (!patched)
2538 {
2539 Fprintf(s_stdout, ID_PATCHING, "Patching %s\n", path.c_str());
2540 patched = true;
2541 }
2542 mike 1.1
2543 str_data = sub(str_data, COMMON_PROVIDER_CLASS_DECLARATION_END,
2544 r + COMMON_PROVIDER_CLASS_DECLARATION_END);
2545 }
2546
2547 if (!patched)
2548 {
2549 Fprintf(s_stdout, ID_CHECKING, "Checking %s\n", path.c_str());
2550 }
2551 else
2552 {
2553 // Rewrite the file.
2554 FILE* os = Fopen(path.c_str(), "w");
2555
2556 if (!os)
2557 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s",path.c_str());
2558
2559 put(os, "%s", &str_data[0]);
2560
2561 fclose(os);
2562 }
2563 mike 1.1 }
2564
2565
2566 //==============================================================================
2567 //
2568 // GenCppClassHeader
2569 //
2570 // Generate C++ part of the header file for the given MOF class. This part
2571 // contains the c++ wrapper class and provider class definition.
2572 //
2573 //==============================================================================
2574 static void GenCppClassHeader(
2575 Parser& /*parser*/,
2576 const MI_ClassDecl* cd,
2577 FILE* os
2578 )
2579 {
2580 string alias = AliasOf(cd->name);
2581
2582 // Comment box introducing C++ class definiti9on
2583 {
2584 mike 1.1 string tmp = alias + "_Class";
2585 PutCommentBox(os, tmp);
2586 nl(os);
2587 }
2588
2589 // standard starting part
2590 putl(os, "#ifdef __cplusplus");
2591 putl(os, "# include <micxx/micxx.h>");
2592 nl(os);
2593 putl(os, "MI_BEGIN_NAMESPACE");
2594 nl(os);
2595
2596
2597 // instance itself
2598 GenCppClassDeclaration<MI_ClassDecl,_MI_PropertyDecl>(os, cd, alias,
2599 cd->superClass, cd->numProperties, cd->properties);
2600
2601 // gen parameters classes
2602 // Put method definitions and setters for each method parameter.
2603 for (size_t i = 0; !s_options.noProviders && i < cd->numMethods; i++)
2604 {
2605 mike 1.1 const MI_MethodDecl* md = cd->methods[i];
2606
2607 string param_alias = alias + "_" + md->name;
2608
2609 if (Strcasecmp(cd->name, md->propagator) == 0 ||
2610 providerClasses.find(cd->name) != providerClasses.end())
2611 {
2612 GenCppClassDeclaration(os, md, param_alias, 0, md->numParameters,
2613 md->parameters);
2614 }
2615 }
2616
2617 // provider class definition - if required
2618 if (providerClasses.find(cd->name) != providerClasses.end() &&
2619 !s_options.noProviders)
2620 {
2621
2622 GenCppClassProviderHeader(cd);
2623 }
2624
2625 // end c++ specific part
2626 mike 1.1 putl(os, "MI_END_NAMESPACE");
2627 nl(os);
2628 putl(os, "#endif /* __cplusplus */");
2629 nl(os);
2630 }
2631
2632
2633 static void _PatchLoadSignature(
2634 const string& alias,
2635 const string& path,
2636 vector<char>& data)
2637 {
2638 /* special case: patch Load funciton signature */
2639 string old_load = sub(OLD_PROVIDER_LOAD_PROTOTYPES, "<ALIAS>", alias);
2640
2641 data.push_back(0);
2642 string str_data = &data[0];
2643
2644 /* remove \r*/
2645 str_data = sub(str_data, "\r", "");
2646
2647 mike 1.1 if (str_data.find(old_load) != string::npos)
2648 {
2649 string new_load = sub(NEW_PROVIDER_LOAD_PROTOTYPES, "<ALIAS>", alias);
2650
2651 str_data = sub(str_data, old_load, new_load);
2652
2653 // Rewrite the file.
2654 {
2655 FILE* os = Fopen(path.c_str(), "w");
2656
2657 if (!os)
2658 {
2659 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s",
2660 path.c_str());
2661 }
2662
2663 Fprintf(s_stdout, ID_PATCHING, "Patching %s\n", path.c_str());
2664 put(os, "%s", &str_data[0]);
2665
2666 fclose(os);
2667 }
2668 mike 1.1 }
2669 }
2670
2671 /* Patches old cpp skeletons with load/unload funcitons */
2672 static void _PatchLoadUnloadCPP(
2673 const string& alias,
2674 const string& path,
2675 vector<char>& data)
2676 {
2677 /* special case: check if Load/Unload are declared */
2678 string old_load = sub("<ALIAS>_Class_Provider::Load(", "<ALIAS>", alias);
2679
2680 data.push_back(0);
2681 string str_data = &data[0];
2682
2683 /* remove \r*/
2684 str_data = sub(str_data, "\r", "");
2685
2686 if (str_data.find(old_load) == string::npos)
2687 {
2688 string new_load = sub(COMMON_PROVIDER_CLASS_LOAD_UNLOAD_CPP, "<ALIAS>", alias);
2689 mike 1.1
2690 str_data += "MI_BEGIN_NAMESPACE\n";
2691 str_data += new_load;
2692 str_data += "MI_END_NAMESPACE\n";
2693
2694 // Rewrite the file.
2695 {
2696 FILE* os = Fopen(path.c_str(), "w");
2697
2698 if (!os)
2699 {
2700 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s",
2701 path.c_str());
2702 }
2703
2704 Fprintf(s_stdout, ID_PATCHING, "Patching %s\n", path.c_str());
2705 put(os, "%s", &str_data[0]);
2706
2707 fclose(os);
2708 }
2709 }
2710 mike 1.1 }
2711
2712 //==============================================================================
2713 //
2714 // GenCppClassSource
2715 //
2716 // Generate the cpp source file for the given MOF class. This file contains the
2717 // the provider function stubs.
2718 //
2719 //==============================================================================
2720
2721 static void GenCppClassSource(const MI_ClassDecl* cd)
2722 {
2723 const string alias = AliasOf(cd->name);
2724
2725 // Open source file (refuse if it already exists).
2726 bool append;
2727 vector<char> data;
2728 const string path = ExpandPath(alias + "_Class_Provider.cpp");
2729 FILE* os = 0;
2730 {
2731 mike 1.1 append = Exists(path.c_str());
2732
2733 if (append)
2734 {
2735 if (!Inhale(path.c_str(), data))
2736 {
2737 err(ID_FAILED_TO_READ_FILE, "failed to read file: %s",
2738 path.c_str());
2739 }
2740
2741 _PatchLoadUnloadCPP(alias, path, data);
2742
2743 os = Fopen(path.c_str(), "a");
2744
2745 if (!os)
2746 {
2747 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s",
2748 path.c_str());
2749 }
2750 }
2751 else
2752 mike 1.1 {
2753 os = Fopen(path.c_str(), "w");
2754
2755 if (!os)
2756 {
2757 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s",
2758 path.c_str());
2759 }
2760
2761 GenStatikGenLine(os);
2762 Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
2763 }
2764 }
2765
2766 // Include required headers.
2767 if (!append)
2768 {
2769 putl(os, "#include <MI.h>");
2770 putl(os, "#include \"%s_Class_Provider.h\"", alias.c_str());
2771 nl(os);
2772 putl(os, "MI_BEGIN_NAMESPACE");
2773 mike 1.1 nl(os);
2774 }
2775
2776 // spil out provider class implementation (stubs)
2777 if (!append)
2778 {
2779 string r;
2780
2781 if (cd->flags & MI_FLAG_ASSOCIATION)
2782 {
2783 if (!s_options.association && CanGenerateAssocRoles(cd))
2784 {
2785 r = ASSOCIATION_PROVIDER_CLASS_STUBS_CPP_ROLES;
2786 SubRoles(cd, r);
2787 }
2788 else
2789 r = ASSOCIATION_PROVIDER_CLASS_STUBS_CPP;
2790 }
2791 else if (cd->flags & MI_FLAG_INDICATION)
2792 r = INDICATION_PROVIDER_CLASS_STUBS_CPP;
2793 else
2794 mike 1.1 r = INSTANCE_PROVIDER_CLASS_STUBS_CPP;
2795
2796 r = sub(r, "<ALIAS>", alias);
2797 puts(os, r);
2798 }
2799
2800 // spil out provider extrinsic method stubs
2801 if (!append)
2802 {
2803 for (size_t i = 0; i < cd->numMethods; i++)
2804 {
2805 const MI_MethodDecl* md = cd->methods[i];
2806 string r = sub(EXTRINSIC_METHOD_CLASS_STUB_CPP, "<ALIAS>", alias);
2807 r = sub(r, "<METHOD>", md->name);
2808 puts(os, r);
2809 }
2810 }
2811
2812 // close namespace
2813 if (!append)
2814 {
2815 mike 1.1 nl(os);
2816 putl(os, "MI_END_NAMESPACE");
2817 }
2818
2819
2820 // only if we are updating exisitng one
2821 if (append)
2822 {
2823 bool patched = false;
2824
2825 // Generate extrinsic method stubs (not already found in file).
2826 for (size_t i = 0; i < cd->numMethods; i++)
2827 {
2828 const MI_MethodDecl* md = cd->methods[i];
2829 string r = sub(
2830 "MI_BEGIN_NAMESPACE\n\n" EXTRINSIC_METHOD_CLASS_STUB_CPP "\nMI_END_NAMESPACE\n", "<ALIAS>", alias);
2831 r = sub(r, "<METHOD>", md->name);
2832
2833 string name = string("::Invoke_") + md->name;
2834
2835 // Skip methods already found in file.
2836 mike 1.1
2837 if (strstr(&data[0], name.c_str()))
2838 continue;
2839 else
2840 {
2841 if (!patched)
2842 {
2843 Fprintf(s_stdout, ID_PATCHING, "Patching %s\n",
2844 path.c_str());
2845 patched = true;
2846 }
2847 puts(os, r);
2848 }
2849 }
2850
2851 if (!patched)
2852 {
2853 Fprintf(s_stdout, ID_CHECKING, "Checking %s\n", path.c_str());
2854 }
2855 }
2856
2857 mike 1.1 // Close file.
2858 fclose(os);
2859 }
2860
2861 //==============================================================================
2862 //
2863 // GenerateClassStub
2864 //
2865 // Generate wrapper for provider class
2866 //
2867 //==============================================================================
2868
2869 static void GenerateClassStub(FILE* os, const MI_ClassDecl* cd)
2870 {
2871 const string alias = AliasOf(cd->name);
2872
2873 // Generate extrinsic method stubs.
2874 {
2875 if (cd->flags & MI_FLAG_ASSOCIATION)
2876 {
2877 string r;
2878 mike 1.1
2879 if (!s_options.association && CanGenerateAssocRoles(cd))
2880 {
2881 r = ASSOCIATION_PROVIDER_STUBS_CPP_ROLES;
2882 SubRoles(cd, r);
2883 }
2884 else
2885 r = ASSOCIATION_PROVIDER_STUBS_CPP;
2886
2887 r = sub(r, "<ALIAS>", alias);
2888 puts(os, r);
2889 }
2890 else if (cd->flags & MI_FLAG_INDICATION)
2891 {
2892 string r = INDICATION_PROVIDER_STUBS_CPP;
2893 r = sub(r, "<ALIAS>", alias);
2894 puts(os, r);
2895 }
2896 else
2897 {
2898 if (HasKeys(cd))
2899 mike 1.1 {
2900 string r = INSTANCE_PROVIDER_STUBS_CPP;
2901 r = sub(r, "<ALIAS>", alias);
2902 puts(os, r);
2903 }
2904 else
2905 {
2906 string r = COMMON_PROVIDER_STUBS_CPP;
2907 r = sub(r, "<ALIAS>", alias);
2908 puts(os, r);
2909 }
2910 }
2911 }
2912
2913 // generate all extrinsic method stubs (if new one)
2914 {
2915 for (size_t i = 0; i < cd->numMethods; i++)
2916 {
2917 const MI_MethodDecl* md = cd->methods[i];
2918 string r = sub(EXTRINSIC_METHOD_STUB_CPP, "<ALIAS>", alias);
2919 r = sub(r, "<METHOD>", md->name);
2920 mike 1.1 puts(os, r);
2921 }
2922
2923 }
2924 }
2925
2926 //==============================================================================
2927 //
2928 // GenClassHeader
2929 //
2930 // Generate the header file for the given MOF class. This file contains the
2931 // C structure definition, setter functions, parameter structures, and
2932 // provider function prototypes.
2933 //
2934 //==============================================================================
2935
2936 static void GenClassHeader(
2937 Parser& parser,
2938 const MI_ClassDecl* cd,
2939 set<string>& classIdentifiers)
2940 {
2941 mike 1.1 const string alias = AliasOf(cd->name);
2942
2943 // Refuse to generate same class more than once.
2944
2945 if (generated_headers.find(cd->name) != generated_headers.end())
2946 return;
2947
2948 generated_headers.insert(cd->name);
2949
2950 // Find direct dependencies of this class.
2951 vector<string> deps;
2952 FindDirectDependencies(cd, deps);
2953
2954 // Recurse on dependencies.
2955 for (size_t i = 0; i < deps.size(); i++)
2956 {
2957 const MI_ClassDecl* tcd = parser.findClassDecl(deps[i].c_str());
2958
2959 if (!tcd)
2960 err(ID_UNKNOWN_CLASS, "unknown class: %s", deps[i].c_str());
2961
2962 mike 1.1 GenClassHeader(parser, tcd, classIdentifiers);
2963 }
2964
2965 // Open class header file.
2966 string path = ExpandPath(alias + ".h");
2967 Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
2968
2969 FILE* os = Fopen(path.c_str(), "w");
2970
2971 if (!os)
2972 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
2973
2974 GenStatikGenLine(os);
2975
2976 // Put comment header.
2977 PutCommentBox(os, WARNING);
2978
2979 // Prevent multiple inclusion.
2980 putl(os, "#ifndef _%s_h", alias.c_str());
2981 putl(os, "#define _%s_h", alias.c_str());
2982 nl(os);
2983 mike 1.1
2984 // Include <MI.h>
2985 putl(os, "#include <MI.h>");
2986
2987 // Generate includes for direct dependencies.
2988 for (size_t i = 0; i < deps.size(); i++)
2989 {
2990 string al = AliasOf(deps[i]);
2991 putl(os, "#include \"%s.h\"", al.c_str());
2992 }
2993
2994 nl(os);
2995
2996 // Put comment box for the class structure. List the key names for this
2997 // class.
2998 {
2999 putl(os, "/*");
3000 PutRule(os);
3001 putl(os, "**");
3002 putl(os, "** %s [%s]", alias.c_str(), cd->name);
3003 putl(os, "**");
3004 mike 1.1 putl(os, "** Keys:");
3005
3006 for (size_t i = 0; i < cd->numProperties; i++)
3007 {
3008 const MI_PropertyDecl* pd = cd->properties[i];
3009
3010 if (pd->flags & MI_FLAG_KEY)
3011 putl(os, "** %s", pd->name);
3012 }
3013
3014 putl(os, "**");
3015 PutRule(os);
3016 putl(os, "*/");
3017 nl(os);
3018 }
3019
3020 // Put class structure definition with all its properties.
3021 if (cd->superClass)
3022 {
3023 putl(os, "typedef struct _%s /* extends %s */",
3024 alias.c_str(), cd->superClass);
3025 mike 1.1 }
3026 else
3027 {
3028 putl(os, "typedef struct _%s", alias.c_str());
3029 }
3030
3031 putl(os, "{");
3032 putl(os, " MI_Instance __instance;");
3033 NameClassMap map;
3034 GenProperties(os, parser, cd, cd, map);
3035 putl(os, "}");
3036 putl(os, "%s;", alias.c_str());
3037 nl(os);
3038
3039 // Generate a reference of this type (if not an association or indication).
3040 #if 0
3041 if (!(cd->flags & MI_FLAG_ASSOCIATION || cd->flags & MI_FLAG_INDICATION))
3042 #endif
3043 // Associations can be used as endpoints in other associations.
3044 {
3045 {
3046 mike 1.1 const char T[] =
3047 "typedef struct _<ALIAS>_Ref\n"
3048 "{\n"
3049 " <ALIAS>* value;\n"
3050 " MI_Boolean exists;\n"
3051 " MI_Uint8 flags;\n"
3052 "}\n"
3053 "<ALIAS>_Ref;\n"
3054 "\n"
3055 "typedef struct _<ALIAS>_ConstRef\n"
3056 "{\n"
3057 " MI_CONST <ALIAS>* value;\n"
3058 " MI_Boolean exists;\n"
3059 " MI_Uint8 flags;\n"
3060 "}\n"
3061 "<ALIAS>_ConstRef;\n"
3062 "\n";
3063
3064 string r = sub(T, "<ALIAS>", alias);
3065 puts(os, r);
3066 }
3067 mike 1.1 {
3068 const char T[] =
3069 "typedef struct _<ALIAS>_Array\n"
3070 "{\n"
3071 " struct _<ALIAS>** data;\n"
3072 " MI_Uint32 size;\n"
3073 "}\n"
3074 "<ALIAS>_Array;\n"
3075 "\n"
3076 "typedef struct _<ALIAS>_ConstArray\n"
3077 "{\n"
3078 " struct _<ALIAS> MI_CONST* MI_CONST* data;\n"
3079 " MI_Uint32 size;\n"
3080 "}\n"
3081 "<ALIAS>_ConstArray;\n"
3082 "\n"
3083 "typedef struct _<ALIAS>_ArrayRef\n"
3084 "{\n"
3085 " <ALIAS>_Array value;\n"
3086 " MI_Boolean exists;\n"
3087 " MI_Uint8 flags;\n"
3088 mike 1.1 "}\n"
3089 "<ALIAS>_ArrayRef;\n"
3090 "\n"
3091 "typedef struct _<ALIAS>_ConstArrayRef\n"
3092 "{\n"
3093 " <ALIAS>_ConstArray value;\n"
3094 " MI_Boolean exists;\n"
3095 " MI_Uint8 flags;\n"
3096 "}\n"
3097 "<ALIAS>_ConstArrayRef;\n"
3098 "\n";
3099
3100 string r = sub(T, "<ALIAS>", alias);
3101 puts(os, r);
3102 }
3103 }
3104
3105 // Generate an external reference to the class RTTI instance.
3106 if (s_options.cpp || !s_options.noProviders)
3107 {
3108 putl(os, "MI_EXTERN_C MI_CONST MI_ClassDecl %s_rtti;", alias.c_str());
3109 mike 1.1 nl(os);
3110 }
3111
3112 // Generate Instance function
3113 if (!s_options.noProviders)
3114 GenInstanceFunctions(os,cd);
3115
3116 // Gen setters.
3117 if (!s_options.noProviders)
3118 {
3119 for (size_t i = 0; i < cd->numProperties; i++)
3120 GenSetter(os, cd, NULL, (MI_ParameterDecl*)cd->properties[i]);
3121 }
3122
3123 // Put method definitions and setters for each method parameter.
3124 for (size_t i = 0; i < cd->numMethods; i++)
3125 {
3126 const MI_MethodDecl* md = cd->methods[i];
3127 GenParametersStruct(os, cd, md);
3128
3129 // Generate convenience functions.
3130 mike 1.1 if (!s_options.noProviders)
3131 {
3132 if (Strcasecmp(cd->name, md->propagator) == 0 ||
3133 providerClasses.find(cd->name) != providerClasses.end())
3134 {
3135 GenMethodFunctions(os, cd, md);
3136 }
3137 }
3138
3139 // Generate parameter setter for "MIReturn".
3140 if (!s_options.noProviders)
3141 {
3142 MI_ParameterDecl pd;
3143 memset(&pd, 0, sizeof(pd));
3144 pd.flags = MI_FLAG_PARAMETER|MI_FLAG_OUT;
3145 pd.name = (char*)"MIReturn";
3146 pd.type = md->returnType;
3147 pd.offset = sizeof(MI_Instance);
3148 pd.numQualifiers = md->numQualifiers;
3149 pd.qualifiers = md->qualifiers;
3150 GenSetter(os, cd, md, &pd);
3151 mike 1.1 }
3152
3153 if (!s_options.noProviders)
3154 {
3155 for (size_t j = 0; j < md->numParameters; j++)
3156 {
3157 const MI_ParameterDecl* pd = md->parameters[j];
3158
3159 // Skip stream parameters:
3160 if (pd->flags & MI_FLAG_STREAM)
3161 continue;
3162
3163 GenSetter(os, cd, md, pd);
3164 }
3165 }
3166 }
3167
3168 if (providerClasses.find(cd->name) != providerClasses.end())
3169 {
3170
3171 // Write the intrinsic provider function prototypes.
3172 mike 1.1
3173 if (!s_options.noProviders)
3174 {
3175 PutCommentBox(os, alias + " provider function prototypes");
3176 nl(os);
3177
3178 // Generate forward typedef for Self structure.
3179 putl(os,"/* The developer may optionally define this structure */");
3180 putl(os, "typedef struct _%s_Self %s_Self;\n",
3181 alias.c_str(), alias.c_str());
3182
3183 if (cd->flags & MI_FLAG_ASSOCIATION)
3184 {
3185 string r;
3186
3187 if (s_options.association || !CanGenerateAssocRoles(cd))
3188 r = ASSOCIATION_PROVIDER_PROTOTYPES;
3189 else
3190 {
3191 r = ROLE_PROVIDER_PROTOTYPES;
3192 SubRoles(cd, r);
3193 mike 1.1 }
3194
3195 r = sub(r, "<ALIAS>", alias);
3196 puts(os, r);
3197 }
3198 else if (cd->flags & MI_FLAG_INDICATION)
3199 {
3200 string r;
3201 r = INDICATION_PROVIDER_PROTOTYPES;
3202 r = sub(r, "<ALIAS>", alias);
3203 puts(os, r);
3204 }
3205 else
3206 {
3207 if (HasKeys(cd))
3208 {
3209 string r = INSTANCE_PROVIDER_PROTOTYPES;
3210 r = sub(r, "<ALIAS>", alias);
3211 puts(os, r);
3212 }
3213 else
3214 mike 1.1 {
3215 string r = COMMON_PROVIDER_PROTOTYPES;
3216 r = sub(r, "<ALIAS>", alias);
3217 puts(os, r);
3218 }
3219 }
3220 }
3221
3222 // Write the extrinsic provider function prototypes.
3223 if (!s_options.noProviders)
3224 {
3225 for (size_t i = 0; i < cd->numMethods; i++)
3226 {
3227 const MI_MethodDecl* md = cd->methods[i];
3228 string r = sub(EXTRINSIC_METHOD_PROTOTYPE, "<ALIAS>", alias);
3229 r = sub(r, "<METHOD>", md->name);
3230 puts(os, r);
3231 }
3232 }
3233 }
3234
3235 mike 1.1 // Generate the class identifier:
3236 #if 0
3237 {
3238 char id[33];
3239 _MakeID(id);
3240 string classIdentifier = alias + "_" + id;
3241 classIdentifiers.insert(classIdentifier);
3242 putl(os, "#define %s\n", classIdentifier.c_str());
3243 }
3244 #endif
3245
3246 nl(os);
3247
3248 // c++ part
3249 if (s_options.cpp)
3250 GenCppClassHeader(parser, cd, os);
3251
3252 // End ifdef that Prevents multiple inclusion.
3253 putl(os, "#endif /* _%s_h */", alias.c_str());
3254
3255 // Close file.
3256 mike 1.1 fclose(os);
3257 }
3258
3259 //==============================================================================
3260 //
3261 // GenClassSource
3262 //
3263 // Generate the source file for the given MOF class. This file contains the
3264 // the provider function stubs.
3265 //
3266 //==============================================================================
3267
3268 static void GenClassSource(const MI_ClassDecl* cd)
3269 {
3270 const string alias = AliasOf(cd->name);
3271
3272 // Open source file (refuse if it already exists).
3273 bool append;
3274 vector<char> data;
3275 const string path = ExpandPath(alias + ".c");
3276 FILE* os = 0;
3277 mike 1.1 {
3278 append = Exists(path.c_str());
3279
3280 if (append)
3281 {
3282 if (!Inhale(path.c_str(), data))
3283 {
3284 err(ID_FAILED_TO_READ_FILE, "failed to read file: %s",
3285 path.c_str());
3286 }
3287
3288 _PatchLoadSignature(alias, path, data);
3289
3290 os = Fopen(path.c_str(), "a");
3291
3292 if (!os)
3293 {
3294 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s",
3295 path.c_str());
3296 }
3297 }
3298 mike 1.1 else
3299 {
3300 os = Fopen(path.c_str(), "w");
3301
3302 if (!os)
3303 {
3304 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s",
3305 path.c_str());
3306 }
3307
3308 GenStatikGenLine(os);
3309 Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
3310 }
3311 }
3312
3313 // Include required headers.
3314 if (!append)
3315 {
3316 putl(os, "#include <MI.h>");
3317 putl(os, "#include \"%s.h\"", alias.c_str());
3318 nl(os);
3319 mike 1.1 }
3320
3321 // Generate extrinsic method stubs.
3322 if (!append)
3323 {
3324 if (cd->flags & MI_FLAG_ASSOCIATION)
3325 {
3326 string r;
3327 if (s_options.association || !CanGenerateAssocRoles(cd))
3328 r = ASSOCIATION_PROVIDER_STUBS;
3329 else
3330 {
3331 r = ROLE_PROVIDER_STUBS;
3332 SubRoles(cd, r);
3333 }
3334
3335 r = sub(r, "<ALIAS>", alias);
3336 puts(os, r);
3337 }
3338 else if (cd->flags & MI_FLAG_INDICATION)
3339 {
3340 mike 1.1 string r = INDICATION_PROVIDER_STUBS;
3341 r = sub(r, "<ALIAS>", alias);
3342 puts(os, r);
3343 }
3344 else
3345 {
3346 if (HasKeys(cd))
3347 {
3348 string r = INSTANCE_PROVIDER_STUBS;
3349 r = sub(r, "<ALIAS>", alias);
3350 puts(os, r);
3351 }
3352 else
3353 {
3354 string r = COMMON_PROVIDER_STUBS;
3355 r = sub(r, "<ALIAS>", alias);
3356 puts(os, r);
3357 }
3358 }
3359
3360 }
3361 mike 1.1
3362 bool patched = false;
3363
3364 // Generate extrinsic method stubs (not already found in file).
3365 for (size_t i = 0; i < cd->numMethods; i++)
3366 {
3367 const MI_MethodDecl* md = cd->methods[i];
3368 string r = sub(EXTRINSIC_METHOD_STUB, "<ALIAS>", alias);
3369 r = sub(r, "<METHOD>", md->name);
3370
3371 string name = alias + "_Invoke_" + md->name;
3372
3373 // Skip methods already found in file.
3374
3375 if (append && strstr(&data[0], name.c_str()))
3376 continue;
3377 else
3378 {
3379 if (!patched)
3380 {
3381 Fprintf(s_stdout, ID_PATCHING, "Patching %s\n", path.c_str());
3382 mike 1.1 patched = true;
3383 }
3384 puts(os, r);
3385 }
3386 }
3387
3388 if (!patched)
3389 {
3390 Fprintf(s_stdout, ID_CHECKING, "Checking %s\n", path.c_str());
3391 }
3392
3393 // Close file.
3394 fclose(os);
3395 }
3396
3397 //==============================================================================
3398 //
3399 // PutString()
3400 //
3401 // Write a string literal.
3402 //
3403 mike 1.1 //==============================================================================
3404
3405 static void PutStringLiteral(FILE* os, const char* value)
3406 {
3407 put(os, "MI_T(\"");
3408
3409 for (const char* p = value; *p; p++)
3410 {
3411 unsigned char c = (unsigned char)*p;
3412
3413 if (c >= 32 && c <= 127)
3414 put(os, "%c", c);
3415 else
3416 put(os, "\\%04o", c);
3417 }
3418
3419 put(os, "\")");
3420 }
3421
3422 //==============================================================================
3423 //
3424 mike 1.1 // Localize()
3425 //
3426 // Add the string to the localization table and return an integer
3427 // identifier for that string. The localization id is one greater
3428 // than its index in the s_localizations.
3429 //
3430 //==============================================================================
3431
3432 static vector<string> s_localizations;
3433
3434 static MI_Uint32 Localize(const string& msg)
3435 {
3436 for (size_t i = 0; i < s_localizations.size(); i++)
3437 {
3438 if (s_localizations[i] == msg)
3439 return (MI_Uint32)(i + 1);
3440 }
3441
3442 s_localizations.push_back(msg);
3443 return (MI_Uint32)s_localizations.size();
3444 }
3445 mike 1.1
3446 //==============================================================================
3447 //
3448 // GenScalarValueInitializer
3449 //
3450 // Put the value initializer for a property or qualifier value.
3451 //
3452 //==============================================================================
3453
3454 static void GenScalarValueInitializer(
3455 FILE* os,
3456 MI_Type type,
3457 const void* value,
3458 bool localize)
3459 {
3460 // Unsatisfiable condition.
3461 assert(value != NULL);
3462
3463 switch (type)
3464 {
3465 case MI_BOOLEAN:
3466 mike 1.1 {
3467 put(os, "%s", *((MI_Boolean*)value) ? "1" : "0");
3468 break;
3469 }
3470 case MI_UINT8:
3471 {
3472 put(os, "%u", *((MI_Uint8*)value));
3473 break;
3474 }
3475 case MI_SINT8:
3476 {
3477 put(os, "%d", *((MI_Sint8*)value));
3478 break;
3479 }
3480 case MI_UINT16:
3481 {
3482 put(os, "%u", *((MI_Uint16*)value));
3483 break;
3484 }
3485 case MI_SINT16:
3486 {
3487 mike 1.1 put(os, "%d", *((MI_Sint16*)value));
3488 break;
3489 }
3490 case MI_UINT32:
3491 {
3492 MI_Uint32 x = *((MI_Uint32*)value);
3493 put(os, "%uU", x);
3494 break;
3495 }
3496 case MI_SINT32:
3497 {
3498 MI_Sint32 x = *((MI_Sint32*)value);
3499
3500 if (x == -2147483647-1)
3501 put(os, "-2147483647-1");
3502 else
3503 put(os, "%d", x);
3504 break;
3505 }
3506 case MI_UINT64:
3507 {
3508 mike 1.1 put(os, "MI_ULL(" UINT64_FMT ")", *((MI_Uint64*)value));
3509 break;
3510 }
3511 case MI_SINT64:
3512 {
3513 MI_Sint64 x = *((MI_Sint64*)value);
3514 if (x == -MI_LL(9223372036854775807)-MI_LL(1))
3515 put(os, "-MI_LL(9223372036854775807)-MI_LL(1)");
3516 else
3517 {
3518 if (x >= 0)
3519 put(os, "MI_LL(" SINT64_FMT ")", x);
3520 else
3521 put(os, "-MI_LL(" SINT64_FMT ")", -x);
3522 }
3523 break;
3524 }
3525 case MI_REAL32:
3526 {
3527 put(os, "(float)%g", *((MI_Real32*)value));
3528 break;
3529 mike 1.1 }
3530 case MI_REAL64:
3531 {
3532 put(os, "(double)%g", *((MI_Real64*)value));
3533 break;
3534 }
3535 case MI_CHAR16:
3536 {
3537 put(os, "%u", *((MI_Char16*)value));
3538 break;
3539 }
3540 case MI_DATETIME:
3541 {
3542 const MI_Datetime& x = *((MI_Datetime*)value);
3543
3544 if (x.isTimestamp)
3545 {
3546 put(os,"{1,{{%u,%u,%u,%u,%u,%u,%u,%d}}}",
3547 x.u.timestamp.year,
3548 x.u.timestamp.month,
3549 x.u.timestamp.day,
3550 mike 1.1 x.u.timestamp.hour,
3551 x.u.timestamp.minute,
3552 x.u.timestamp.second,
3553 x.u.timestamp.microseconds,
3554 x.u.timestamp.utc);
3555 }
3556 else
3557 {
3558 put(os,"{0,{{%u,%u,%u,%u,%u}}}",
3559 x.u.interval.days,
3560 x.u.interval.hours,
3561 x.u.interval.minutes,
3562 x.u.interval.seconds,
3563 x.u.interval.microseconds);
3564 }
3565 break;
3566 }
3567 case MI_STRING:
3568 {
3569 if (localize && s_options.localize)
3570 {
3571 mike 1.1 MI_Uint32 id = Localize((char*)value);
3572 char buf[9];
3573 Snprintf(buf, MI_COUNT(buf), "%u", id);
3574 PutStringLiteral(os, buf);
3575 }
3576 else
3577 PutStringLiteral(os, (char*)value);
3578 break;
3579 }
3580 default:
3581 // Unreachable!
3582 assert(0);
3583 break;
3584 }
3585 }
3586
3587 //==============================================================================
3588 //
3589 // GenValue()
3590 //
3591 // Generate the value for a property declaration.
3592 mike 1.1 //
3593 //==============================================================================
3594
3595 static void GenValue(
3596 FILE* os,
3597 const string& stem,
3598 MI_Uint32 type,
3599 const void* value,
3600 bool localize)
3601 {
3602 MI_Type stype = (MI_Type)(type & ~MI_ARRAY_BIT);
3603 string typenameof = sub( TypeNameOf(stype), "String", "Char*");
3604
3605 // If the value is null, just return.
3606 if (!value)
3607 return;
3608
3609 // Encode array or scalar.
3610 if (type & MI_ARRAY_BIT)
3611 {
3612 // Write the array data elements.
3613 mike 1.1
3614 putl(os, "static MI_CONST MI_%s %s_data_value[] =",
3615 typenameof.c_str(), stem.c_str());
3616 putl(os, "{");
3617
3618 if (type == MI_STRINGA)
3619 {
3620 MI_StringA* arr = (MI_StringA*)value;
3621
3622 for (MI_Uint32 i = 0; i < arr->size; i++)
3623 {
3624 put(os, " ");
3625 GenScalarValueInitializer(os, stype, arr->data[i], localize);
3626 putl(os, ",");
3627 }
3628 }
3629 else
3630 {
3631 MI_Uint8A* arr = (MI_Uint8A*)value;
3632 MI_Uint8* p = arr->data;
3633
3634 mike 1.1 for (MI_Uint32 i = 0; i < arr->size; i++)
3635 {
3636 put(os, " ");
3637 GenScalarValueInitializer(os, stype, p, localize);
3638 p += ScalarSizeOf(stype);
3639 putl(os, ",");
3640 }
3641 }
3642
3643 putl(os, "};");
3644 nl(os);
3645
3646 // Write the array itself.
3647
3648 putl(os, "static MI_CONST MI_Const%sA %s_value =", TypeNameOf(stype), stem.c_str());
3649 putl(os, "{");
3650 putl(os, " %s_data_value,", stem.c_str());
3651 putl(os, " MI_COUNT(%s_data_value),", stem.c_str());
3652 putl(os, "};");
3653 nl(os);
3654 }
3655 mike 1.1 else
3656 {
3657 put(os, "static MI_CONST MI_%s %s_value = ", typenameof.c_str(), stem.c_str());
3658 GenScalarValueInitializer(os, (MI_Type)type, value, localize);
3659 putl(os, ";");
3660 nl(os);
3661 }
3662 }
3663
3664 //==============================================================================
3665 //
3666 // MI_Qualifier
3667 //
3668 // This function generates a qualifier.
3669 //
3670 //==============================================================================
3671
3672 static void GenQualifier(
3673 Parser& parser,
3674 FILE* os,
3675 const MI_Qualifier* q,
3676 mike 1.1 const string& stem_)
3677 {
3678 string stem = stem_ + "_" + q->name + "_qual";
3679
3680 /* Find qualifier declaration */
3681 const MI_QualifierDecl* qd = parser.findQualifierDecl(q->name);
3682
3683 if (!qd)
3684 err(ID_INTERNAL_ERROR, "internal error: %s(%u)", __FILE__, __LINE__);
3685
3686 /* Generate the value */
3687 GenValue(os, stem, q->type, q->value,
3688 (q->flavor & MI_FLAG_TRANSLATABLE) ? true : false);
3689
3690 const char T[] =
3691 "static MI_CONST MI_Qualifier <STEM> =\n"
3692 "{\n"
3693 " MI_T(\"<NAME>\"),\n"
3694 " <TYPE>,\n"
3695 " <FLAVOR>,\n"
3696 " <VALUE>\n"
3697 mike 1.1 "};\n"
3698 "\n";
3699
3700 string r = T;
3701 r = sub(r, "<STEM>", stem);
3702 r = sub(r, "<NAME>", q->name);
3703 r = sub(r, "<TYPE>", MakeType(q->type));
3704 r = sub(r, "<FLAVOR>", MakeFlavor(q->flavor));
3705
3706 if (q->value)
3707 r = sub(r, "<VALUE>", "&" + stem + "_value");
3708 else
3709 r = sub(r, "<VALUE>", "NULL");
3710
3711 puts(os, r);
3712 }
3713
3714 //==============================================================================
3715 //
3716 // GenQualifiers()
3717 //
3718 mike 1.1 // Generate a list of qualifier definitions. Return the number of qualifiers
3719 // generated (which may be less than numQualifiers due to excluded
3720 // qualifiers, such as boolean).
3721 //
3722 //==============================================================================
3723
3724 static size_t GenQualifiers(
3725 Parser& parser,
3726 FILE* os,
3727 MI_Qualifier** qualifiers,
3728 MI_Uint32 numQualifiers,
3729 const string& stem)
3730 {
3731 size_t count = 0;
3732
3733 if (numQualifiers == 0)
3734 return 0;
3735
3736 /* Check if qualifiers are ignored */
3737 if (s_options.ignoreAllQualifiers)
3738 return 0;
3739 mike 1.1
3740 // Generate qualifiers.
3741
3742 for (MI_Uint32 i = 0; i < numQualifiers; i++)
3743 {
3744 const MI_Qualifier* q = qualifiers[i];
3745
3746 if (q->type == MI_BOOLEAN && !s_options.booleanQualifiers)
3747 continue;
3748
3749 // Skip Description qualifier if -D option was given.
3750 if (eqi(q->name, "Description") && !s_options.descriptions)
3751 continue;
3752
3753 // Skip Values qualifier if -V option was given.
3754 if (eqi(q->name, "Values") && !s_options.values)
3755 continue;
3756
3757 // Skip ValueMap qualifier if -V option was given.
3758 if (eqi(q->name, "ValueMap") && !s_options.values)
3759 continue;
3760 mike 1.1
3761 // Skip Values qualifier if -M option was given.
3762 if (eqi(q->name, "MappingStrings") && !s_options.mappingStrings)
3763 continue;
3764
3765 GenQualifier(parser, os, q, stem);
3766 count++;
3767 }
3768
3769 // If no qualifiers were generated, return now to avoid creating an
3770 // empty array of qualifiers.
3771 if (count == 0)
3772 return 0;
3773
3774 // Generate the array of qualifiers.
3775
3776 putl(os, "static MI_Qualifier MI_CONST* MI_CONST %s_quals[] =", stem.c_str());
3777 putl(os, "{");
3778
3779 for (MI_Uint32 i = 0; i < numQualifiers; i++)
3780 {
3781 mike 1.1 const MI_Qualifier* q = qualifiers[i];
3782
3783 if (q->type == MI_BOOLEAN && !s_options.booleanQualifiers)
3784 continue;
3785
3786 // Skip Description qualifier if -D option was given.
3787 if (eqi(q->name, "Description") && !s_options.descriptions)
3788 continue;
3789
3790 // Skip Values qualifier if -v option was given.
3791 if (eqi(q->name, "Values") && !s_options.values)
3792 continue;
3793
3794 // Skip ValueMap qualifier if -v option was given.
3795 if (eqi(q->name, "ValueMap") && !s_options.values)
3796 continue;
3797
3798 // Skip Values qualifier if -M option was given.
3799 if (eqi(q->name, "MappingStrings") && !s_options.mappingStrings)
3800 continue;
3801
3802 mike 1.1 putl(os, " &%s_%s_qual,", stem.c_str(), q->name);
3803 }
3804
3805 putl(os, "};");
3806 nl(os);
3807
3808 return count;
3809 }
3810
3811 //==============================================================================
3812 //
3813 // HashCode()
3814 //
3815 // Compute a hash code of the given CIM identifier as follows.
3816 //
3817 // (name[0] << 16) | (name[len-1] << 8) | len
3818 //
3819 //==============================================================================
3820
3821 static MI_Uint32 HashCode(const string& s)
3822 {
3823 mike 1.1 MI_Uint32 n = (MI_Uint32)s.size();
3824
3825 if (n == 0)
3826 err(ID_INTERNAL_ERROR, "internal error: %s(%u)", __FILE__, __LINE__);
3827
3828 return tolower((MI_Uint32)s[0])<<16 | tolower((MI_Uint32)s[n-1])<<8 | n;
3829 }
3830
3831 //==============================================================================
3832 //
3833 // GenPropertyDecl()
3834 //
3835 // This function generates a property declaration (i.e., a structure
3836 // initialization of the MI_PropertyDecl structure) for the given property.
3837 //
3838 //==============================================================================
3839
3840 static void GenPropertyDecl(
3841 Parser& parser,
3842 FILE* os,
3843 const MI_ClassDecl* cd,
3844 mike 1.1 const MI_PropertyDecl* pd)
3845 {
3846 const string alias = AliasOf(cd->name);
3847
3848 // Generate the qualifiers first.
3849 size_t numQualifiers = GenQualifiers(
3850 parser,
3851 os,
3852 pd->qualifiers,
3853 pd->numQualifiers,
3854 AliasOf(cd->name) + "_" + pd->name);
3855
3856 // Generate the value.
3857 if (pd->value)
3858 GenValue(os, alias + "_" + pd->name, pd->type, pd->value, false);
3859
3860 static const char T[] =
3861 "/* property <CLASS>.<PROP> */\n"
3862 "static MI_CONST MI_PropertyDecl <CLASS>_<PROP>_prop =\n"
3863 "{\n"
3864 " <FLAGS>, /* flags */\n"
3865 mike 1.1 " <CODE>, /* code */\n"
3866 " MI_T(\"<PROP>\"), /* name */\n"
3867 " <QUALS>, /* qualifiers */\n"
3868 " <NQUALS>, /* numQualifiers */\n"
3869 " <TYPE>, /* type */\n"
3870 " <CLASSNAME>, /* className */\n"
3871 " <SUBSCRIPT>, /* subscript */\n"
3872 " offsetof(<CLASS>, <PROP>), /* offset */\n"
3873 " <ORIGIN>, /* origin */\n"
3874 " <PROPAGATOR>, /* propagator */\n";
3875
3876 string r = T;
3877 r = sub(r, "<CLASS>", alias);
3878 r = subx(r, "<CODE>", HashCode(pd->name));
3879 r = sub(r, "<PROP>", pd->name);
3880 r = sub(r, "<FLAGS>", MakeFlags(pd->flags));
3881
3882 /* check for embedded instances */
3883 if (MI_STRING == (pd->type & ~MI_ARRAY_BIT)
3884 && IsPropertyRefOrInstance(pd))
3885 {
3886 mike 1.1 r = sub(r, "<TYPE>", ((pd->type & MI_ARRAY_BIT) != 0 ? "MI_INSTANCEA" : "MI_INSTANCE"));
3887 }
3888 else
3889 r = sub(r, "<TYPE>", MakeType(pd->type));
3890
3891 if (numQualifiers)
3892 {
3893 string s = AliasOf(cd->name) + "_" + pd->name + "_quals";
3894 r = sub(r, "<QUALS>", s);
3895 r = sub(r, "<NQUALS>", "MI_COUNT(" + s + ")");
3896 }
3897 else
3898 {
3899 r = sub(r, "<QUALS>", "NULL");
3900 r = sub(r, "<NQUALS>", "0");
3901 }
3902
3903 if (!GetPropertyClassname(pd).empty())
3904 r = sub(r, "<CLASSNAME>", Quote(GetPropertyClassname(pd)));
3905 else
3906 r = sub(r, "<CLASSNAME>", "NULL");
3907 mike 1.1
3908 r = subu(r, "<SUBSCRIPT>", pd->subscript);
3909 r = sub(r, "<ORIGIN>", Quote(pd->origin));
3910 r = sub(r, "<PROPAGATOR>", Quote(pd->propagator));
3911
3912 puts(os, r);
3913
3914 // Put the value if any.
3915
3916 if (pd->value)
3917 putl(os, " &%s_%s_value,", alias.c_str(), pd->name);
3918 else
3919 putl(os, " NULL,");
3920
3921 putl(os, "};");
3922 nl(os);
3923 }
3924
3925 //==============================================================================
3926 //
3927 // GenPropertyDecls()
3928 mike 1.1 //
3929 // This function generates an array of property declaration objects for
3930 // the given class.
3931 //
3932 //==============================================================================
3933
3934 static void GenPropertyDecls(
3935 Parser& parser,
3936 FILE* os,
3937 const MI_ClassDecl* cd)
3938 {
3939 const string alias = AliasOf(cd->name);
3940
3941 // Generate a property declaration for each property.
3942 for (size_t i = 0; i < cd->numProperties; i++)
3943 {
3944 const MI_PropertyDecl* pd = cd->properties[i];
3945
3946 // Only generate property declarations if this class is the owner.
3947 if (Strcasecmp(cd->name, pd->propagator) == 0)
3948 {
3949 mike 1.1 GenPropertyDecl(parser, os, cd, pd);
3950 }
3951 }
3952
3953 // Generate the array of property declarations (if any)
3954
3955 if (cd->numProperties)
3956 {
3957 putl(os, "static MI_PropertyDecl MI_CONST* MI_CONST %s_props[] =",
3958 alias.c_str());
3959 putl(os, "{");
3960
3961 for (size_t i = 0; i < cd->numProperties; i++)
3962 {
3963 const MI_PropertyDecl* pd = cd->properties[i];
3964 const string ownerAlias = AliasOf(pd->propagator);
3965 putl(os, " &%s_%s_prop,", ownerAlias.c_str(), pd->name);
3966 }
3967
3968 putl(os, "};");
3969 }
3970 mike 1.1
3971 nl(os);
3972 }
3973
3974 //==============================================================================
3975 //
3976 // GenParameterDecl()
3977 //
3978 // This function generates a parameter declaration for the given method and
3979 // class.
3980 //
3981 //==============================================================================
3982
3983 static void GenParameterDecl(
3984 Parser& parser,
3985 FILE* os,
3986 const MI_ClassDecl* cd,
3987 const MI_MethodDecl* md,
3988 const MI_ParameterDecl* pd)
3989 {
3990 const string alias = AliasOf(cd->name);
3991 mike 1.1
3992 // Generate the qualifiers first.
3993 size_t numQualifiers = GenQualifiers(
3994 parser,
3995 os,
3996 pd->qualifiers,
3997 pd->numQualifiers,
3998 AliasOf(cd->name) + "_" + md->name + "_" + pd->name);
3999
4000 static const char T[] =
4001 "/* parameter <CLASS>.<METH>(): <PARAM> */\n"
4002 "static MI_CONST MI_ParameterDecl <CLASS>_<METH>_<PARAM>_param =\n"
4003 "{\n"
4004 " <FLAGS>, /* flags */\n"
4005 " <CODE>, /* code */\n"
4006 " MI_T(\"<PARAM>\"), /* name */\n"
4007 " <QUALS>, /* qualifiers */\n"
4008 " <NQUALS>, /* numQualifiers */\n"
4009 " <TYPE>, /* type */\n"
4010 " <CLASSNAME>, /* className */\n"
4011 " <SUBSCRIPT>, /* subscript */\n"
4012 mike 1.1 " <OFFSET>, /* offset */\n"
4013 "};\n"
4014 "\n";
4015
4016 string r = T;
4017
4018 if (pd->flags & MI_FLAG_STREAM)
4019 r = sub(r, "<OFFSET>", "0xFFFFFFFF");
4020 else
4021 r = sub(r, "<OFFSET>", "offsetof(<CLASS>_<METH>, <PARAM>)");
4022
4023 r = sub(r, "<CLASS>", alias);
4024 r = subx(r, "<CODE>", HashCode(pd->name));
4025 r = sub(r, "<METH>", md->name);
4026 r = sub(r, "<PARAM>", pd->name);
4027 r = sub(r, "<FLAGS>", MakeFlags(pd->flags));
4028
4029 /* check for embedded instances */
4030 if (MI_STRING == (pd->type & ~MI_ARRAY_BIT)
4031 && IsPropertyRefOrInstance(pd))
4032 {
4033 mike 1.1 r = sub(r, "<TYPE>", ((pd->type & MI_ARRAY_BIT) != 0 ? "MI_INSTANCEA" : "MI_INSTANCE"));
4034 }
4035 else
4036 r = sub(r, "<TYPE>", MakeType(pd->type));
4037
4038 if (numQualifiers)
4039 {
4040 string s = AliasOf(cd->name) + "_" + md->name + "_" +pd->name +"_quals";
4041 r = sub(r, "<QUALS>", s);
4042 r = sub(r, "<NQUALS>", "MI_COUNT(" + s + ")");
4043 }
4044 else
4045 {
4046 r = sub(r, "<QUALS>", "NULL");
4047 r = sub(r, "<NQUALS>", "0");
4048 }
4049
4050 if (!GetPropertyClassname(pd).empty())
4051 r = sub(r, "<CLASSNAME>", Quote(GetPropertyClassname(pd)));
4052 else
4053 r = sub(r, "<CLASSNAME>", "NULL");
4054 mike 1.1
4055 r = subu(r, "<SUBSCRIPT>", pd->subscript);
4056
4057 puts(os, r);
4058 }
4059
4060 //==============================================================================
4061 //
4062 // GenMethodDecl()
4063 //
4064 // This function generates a method declaration for the given class.
4065 //
4066 //==============================================================================
4067
4068 static void GenMethodDecl(
4069 Parser& parser,
4070 FILE* os,
4071 const MI_ClassDecl* cd,
4072 const MI_MethodDecl* md)
4073 {
4074 // Generate the qualifiers first.
4075 mike 1.1 size_t numQualifiers = GenQualifiers(
4076 parser,
4077 os,
4078 md->qualifiers,
4079 md->numQualifiers,
4080 AliasOf(cd->name) + "_" + md->name);
4081
4082 const string alias = AliasOf(cd->name);
4083
4084 // Generate each parameter declartions.
4085 for (size_t i = 0; i < md->numParameters; i++)
4086 {
4087 const MI_ParameterDecl* pd = md->parameters[i];
4088 GenParameterDecl(parser, os, cd, md, pd);
4089 }
4090
4091 // Generate the return parameter declarations.
4092 {
4093 MI_ParameterDecl pd;
4094 memset(&pd, 0, sizeof(pd));
4095 pd.flags = MI_FLAG_PARAMETER|MI_FLAG_OUT;
4096 mike 1.1 pd.name = (char*)"MIReturn";
4097 pd.type = md->returnType;
4098 pd.offset = sizeof(MI_Instance);
4099 pd.numQualifiers = md->numQualifiers;
4100 pd.qualifiers = md->qualifiers;
4101 GenParameterDecl(parser, os, cd, md, &pd);
4102 }
4103
4104 // Generate the parmaeter declaration array.
4105 {
4106 putl(os, "static MI_ParameterDecl MI_CONST* MI_CONST %s_%s_params[] =",
4107 alias.c_str(), md->name);
4108 putl(os, "{");
4109
4110 putl(os, " &%s_%s_MIReturn_param,", alias.c_str(), md->name);
4111
4112 for (size_t i = 0; i < md->numParameters; i++)
4113 {
4114 const MI_ParameterDecl* pd = md->parameters[i];
4115 putl(os, " &%s_%s_%s_param,", alias.c_str(), md->name, pd->name);
4116 }
4117 mike 1.1
4118 putl(os, "};");
4119 nl(os);
4120 }
4121
4122 static const char T[] =
4123 "/* method <ALIAS>.<METH>() */\n"
4124 "MI_CONST MI_MethodDecl <ALIAS>_<METH>_rtti =\n"
4125 "{\n"
4126 " <FLAGS>, /* flags */\n"
4127 " <CODE>, /* code */\n"
4128 " MI_T(\"<METH>\"), /* name */\n"
4129 " <QUALS>, /* qualifiers */\n"
4130 " <NQUALS>, /* numQualifiers */\n"
4131 " <ALIAS>_<METH>_params, /* parameters */\n"
4132 " MI_COUNT(<ALIAS>_<METH>_params), /* numParameters */\n"
4133 " sizeof(<ALIAS>_<METH>), /* size */\n"
4134 " <TYPE>, /* returnType */\n"
4135 " <ORIGIN>, /* origin */\n"
4136 " <PROPAGATOR>, /* propagator */\n"
4137 " &<SCHEMA>, /* schema */\n"
4138 mike 1.1 " <STUB>, /* method */\n"
4139 "};\n"
4140 "\n";
4141
4142 string r = T;
4143
4144 if (s_options.schema.size())
4145 r = sub(r, "<SCHEMA>", s_options.schema.c_str());
4146 else
4147 r = sub(r, "<SCHEMA>", "schemaDecl");
4148
4149 r = sub(r, "<ALIAS>", alias);
4150 r = subx(r, "<CODE>", HashCode(md->name));
4151 r = sub(r, "<METH>", md->name);
4152 r = sub(r, "<FLAGS>", MakeFlags(md->flags));
4153
4154 /* check for embedded instances */
4155 if (MI_STRING == (md->returnType & ~MI_ARRAY_BIT)
4156 && ExistInstanceQualifier(md))
4157 {
4158 r = sub(r, "<TYPE>", ((md->returnType & MI_ARRAY_BIT) != 0 ? "MI_INSTANCEA" : "MI_INSTANCE"));
4159 mike 1.1 }
4160 else
4161 r = sub(r, "<TYPE>", MakeType(md->returnType));
4162
4163 r = sub(r, "<ORIGIN>", Quote(md->origin));
4164 r = sub(r, "<PROPAGATOR>", Quote(md->propagator));
4165
4166 // If there is no provider for this class, set to NULL
4167 if (providerClasses.find(cd->name) == providerClasses.end())
4168 {
4169 r = sub(r, "<STUB>", "NULL");
4170 }
4171 else
4172 {
4173 static const char T_template[] =
4174 "(MI_ProviderFT_Invoke)<ALIAS>_Invoke_<METH>";
4175 string t = T_template;
4176 t = sub(t, "<ALIAS>", alias);
4177 t = sub(t, "<METH>", md->name);
4178 r = sub(r, "<STUB>", t);
4179 }
4180 mike 1.1
4181 if (numQualifiers)
4182 {
4183 string s = AliasOf(cd->name) + "_" + md->name + "_quals";
4184 r = sub(r, "<QUALS>", s);
4185 r = sub(r, "<NQUALS>", "MI_COUNT(" + s + ")");
4186 }
4187 else
4188 {
4189 r = sub(r, "<QUALS>", "NULL");
4190 r = sub(r, "<NQUALS>", "0");
4191 }
4192
4193 puts(os, r);
4194 }
4195
4196 //==============================================================================
4197 //
4198 // GenMethodDecls()
4199 //
4200 // This function generates a method declaration array for the given class.
4201 mike 1.1 //
4202 //==============================================================================
4203
4204 static void GenMethodDecls(
4205 Parser& parser,
4206 FILE* os,
4207 const MI_ClassDecl* cd)
4208 {
4209 const string alias = AliasOf(cd->name);
4210
4211 if (cd->numMethods == 0)
4212 return;
4213
4214 // Generate a property declaration for each property.
4215 for (size_t i = 0; i < cd->numMethods; i++)
4216 {
4217 const MI_MethodDecl* md = cd->methods[i];
4218
4219 // Only generate this definition for the propagating class unless
4220 // the derived class is a class for which there will be a provider.
4221 // In that case we must generate this declaration so it can hold
4222 mike 1.1 // the extrinsic method stub for that provider.
4223 if (Strcasecmp(cd->name, md->propagator) == 0 ||
4224 providerClasses.find(cd->name) != providerClasses.end())
4225 {
4226 GenMethodDecl(parser, os, cd, md);
4227 }
4228 }
4229
4230 // Generate the array of property declarations.
4231
4232 putl(os, "static MI_MethodDecl MI_CONST* MI_CONST %s_meths[] =",
4233 alias.c_str());
4234 putl(os, "{");
4235
4236 for (size_t i = 0; i < cd->numMethods; i++)
4237 {
4238 const MI_MethodDecl* md = cd->methods[i];
4239
4240 if (Strcasecmp(cd->name, md->propagator) == 0 ||
4241 providerClasses.find(cd->name) != providerClasses.end())
4242 {
4243 mike 1.1 putl(os, " &%s_%s_rtti,", alias.c_str(), md->name);
4244 }
4245 else
4246 {
4247 const string ownerAlias = AliasOf(md->propagator);
4248 putl(os, " &%s_%s_rtti,", ownerAlias.c_str(), md->name);
4249 }
4250 }
4251
4252 putl(os, "};");
4253 nl(os);
4254 }
4255
4256 //==============================================================================
4257 //
4258 // GenFunctionTable()
4259 //
4260 // This function generates the function table for the given class. This
4261 // table contains pointers to the provider stubs.
4262 //
4263 //==============================================================================
4264 mike 1.1
4265 static void GenFunctionTable(
4266 FILE* os,
4267 const MI_ClassDecl* cd)
4268 {
4269 const char ROLES[] =
4270 "static void MI_CALL <ALIAS>_AssociatorInstances(\n"
4271 " <ALIAS>_Self* self,\n"
4272 " MI_Context* context,\n"
4273 " const MI_Char* nameSpace,\n"
4274 " const MI_Char* className,\n"
4275 " const MI_Instance* instanceName,\n"
4276 " const MI_Char* resultClass,\n"
4277 " const MI_Char* role,\n"
4278 " const MI_Char* resultRole,\n"
4279 " const MI_PropertySet* propertySet,\n"
4280 " MI_Boolean keysOnly,\n"
4281 " const MI_Filter* filter)\n"
4282 "{\n"
4283 " if (<ALIAS1>_IsA(instanceName))\n"
4284 " {\n"
4285 mike 1.1 " if (_Match(role, MI_T(\"<ROLE1>\")) && \n"
4286 " _Match(resultRole, MI_T(\"<ROLE2>\")))\n"
4287 " {\n"
4288 " <ALIAS>_AssociatorInstances<ROLE1>(\n"
4289 " self, \n"
4290 " context, \n"
4291 " nameSpace, \n"
4292 " className, \n"
4293 " (<ALIAS1>*)instanceName, \n"
4294 " resultClass, \n"
4295 " propertySet, \n"
4296 " keysOnly, \n"
4297 " filter);\n"
4298 " return;\n"
4299 " }\n"
4300 " }\n"
4301 "\n"
4302 " if (<ALIAS2>_IsA(instanceName))\n"
4303 " {\n"
4304 " if (_Match(role, MI_T(\"<ROLE2>\")) && \n"
4305 " _Match(resultRole, MI_T(\"<ROLE1>\")))\n"
4306 mike 1.1 " {\n"
4307 " <ALIAS>_AssociatorInstances<ROLE2>(\n"
4308 " self, \n"
4309 " context, \n"
4310 " nameSpace, \n"
4311 " className, \n"
4312 " (<ALIAS2>*)instanceName, \n"
4313 " resultClass, \n"
4314 " propertySet, \n"
4315 " keysOnly, \n"
4316 " filter);\n"
4317 " return;\n"
4318 " }\n"
4319 " }\n"
4320 "\n"
4321 " MI_PostResult(context, MI_RESULT_OK);\n"
4322 "}\n"
4323 "\n"
4324 "static void MI_CALL <ALIAS>_ReferenceInstances(\n"
4325 " <ALIAS>_Self* self,\n"
4326 " MI_Context* context,\n"
4327 mike 1.1 " const MI_Char* nameSpace,\n"
4328 " const MI_Char* className,\n"
4329 " const MI_Instance* instanceName,\n"
4330 " const MI_Char* role,\n"
4331 " const MI_PropertySet* propertySet,\n"
4332 " MI_Boolean keysOnly,\n"
4333 " const MI_Filter* filter)\n"
4334 "{\n"
4335 " if (<ALIAS1>_IsA(instanceName))\n"
4336 " {\n"
4337 " if (_Match(role, MI_T(\"<ROLE1>\")))\n"
4338 " {\n"
4339 " <ALIAS>_ReferenceInstances<ROLE1>(\n"
4340 " self, \n"
4341 " context, \n"
4342 " nameSpace, \n"
4343 " className, \n"
4344 " (<ALIAS1>*)instanceName, \n"
4345 " propertySet, \n"
4346 " keysOnly, \n"
4347 " filter);\n"
4348 mike 1.1 " return;\n"
4349 " }\n"
4350 " }\n"
4351 "\n"
4352 " if (<ALIAS2>_IsA(instanceName))\n"
4353 " {\n"
4354 " if (_Match(role, MI_T(\"<ROLE2>\")))\n"
4355 " {\n"
4356 " <ALIAS>_ReferenceInstances<ROLE2>(\n"
4357 " self, \n"
4358 " context, \n"
4359 " nameSpace, \n"
4360 " className, \n"
4361 " (<ALIAS2>*)instanceName, \n"
4362 " propertySet, \n"
4363 " keysOnly, \n"
4364 " filter);\n"
4365 " return;\n"
4366 " }\n"
4367 " }\n"
4368 "\n"
4369 mike 1.1 " MI_PostResult(context, MI_RESULT_OK);\n"
4370 "}\n"
4371 "\n";
4372
4373 const string alias = AliasOf(cd->name);
4374
4375 // Generate the array of property declarations.
4376
4377 if (cd->flags & MI_FLAG_ASSOCIATION)
4378 {
4379 if (!s_options.association && CanGenerateAssocRoles(cd))
4380 {
4381 string r = ROLES;
4382 r = sub(r, "<ALIAS>", alias);
4383 SubRoles(cd, r);
4384 puts(os, r);
4385 }
4386
4387 const char T[] =
4388 "static MI_CONST MI_ProviderFT <ALIAS>_funcs =\n"
4389 "{\n"
4390 mike 1.1 " (MI_ProviderFT_Load)<ALIAS>_Load,\n"
4391 " (MI_ProviderFT_Unload)<ALIAS>_Unload,\n"
4392 " (MI_ProviderFT_GetInstance)<GETINSTANCE>,\n"
4393 " (MI_ProviderFT_EnumerateInstances)<ALIAS>_EnumerateInstances,\n"
4394 " (MI_ProviderFT_CreateInstance)<ALIAS>_CreateInstance,\n"
4395 " (MI_ProviderFT_ModifyInstance)<ALIAS>_ModifyInstance,\n"
4396 " (MI_ProviderFT_DeleteInstance)<ALIAS>_DeleteInstance,\n"
4397 " (MI_ProviderFT_AssociatorInstances)<ALIAS>_AssociatorInstances,\n"
4398 " (MI_ProviderFT_ReferenceInstances)<ALIAS>_ReferenceInstances,\n"
4399 " (MI_ProviderFT_EnableIndications)NULL,\n"
4400 " (MI_ProviderFT_DisableIndications)NULL,\n"
4401 " (MI_ProviderFT_Subscribe)NULL,\n"
4402 " (MI_ProviderFT_Unsubscribe)NULL,\n"
4403 " (MI_ProviderFT_Invoke)NULL,\n"
4404 "};\n"
4405 "\n";
4406
4407 /* Create substitution for <GETINSTANCE> */
4408 string gi;
4409 if (Contains(s_options.noGetInstance, cd->name))
4410 gi = "NULL";
4411 mike 1.1 else
4412 gi = sub("<ALIAS>_GetInstance", "<ALIAS>", alias);
4413
4414 string r = sub(T, "<ALIAS>", alias);
4415 r = sub(r, "<GETINSTANCE>", gi);
4416
4417 puts(os, r);
4418 }
4419 else if (cd->flags & MI_FLAG_INDICATION)
4420 {
4421 const char T[] =
4422 "static MI_CONST MI_ProviderFT <ALIAS>_funcs =\n"
4423 "{\n"
4424 " (MI_ProviderFT_Load)<ALIAS>_Load,\n"
4425 " (MI_ProviderFT_Unload)<ALIAS>_Unload,\n"
4426 " (MI_ProviderFT_GetInstance)NULL,\n"
4427 " (MI_ProviderFT_EnumerateInstances)NULL,\n"
4428 " (MI_ProviderFT_CreateInstance)NULL,\n"
4429 " (MI_ProviderFT_ModifyInstance)NULL,\n"
4430 " (MI_ProviderFT_DeleteInstance)NULL,\n"
4431 " (MI_ProviderFT_AssociatorInstances)NULL,\n"
4432 mike 1.1 " (MI_ProviderFT_ReferenceInstances)NULL,\n"
4433 " (MI_ProviderFT_EnableIndications)<ALIAS>_EnableIndications,\n"
4434 " (MI_ProviderFT_DisableIndications)<ALIAS>_DisableIndications,\n"
4435 " (MI_ProviderFT_Subscribe)<ALIAS>_Subscribe,\n"
4436 " (MI_ProviderFT_Unsubscribe)<ALIAS>_Unsubscribe,\n"
4437 " (MI_ProviderFT_Invoke)NULL,\n"
4438 "};\n"
4439 "\n";
4440 string r = sub(T, "<ALIAS>", alias);
4441 puts(os, r);
4442 }
4443 else
4444 {
4445 const char T1[] =
4446 "static MI_CONST MI_ProviderFT <ALIAS>_funcs =\n"
4447 "{\n"
4448 " (MI_ProviderFT_Load)<ALIAS>_Load,\n"
4449 " (MI_ProviderFT_Unload)<ALIAS>_Unload,\n"
4450 " (MI_ProviderFT_GetInstance)<GETINSTANCE>,\n"
4451 " (MI_ProviderFT_EnumerateInstances)<ALIAS>_EnumerateInstances,\n"
4452 " (MI_ProviderFT_CreateInstance)<ALIAS>_CreateInstance,\n"
4453 mike 1.1 " (MI_ProviderFT_ModifyInstance)<ALIAS>_ModifyInstance,\n"
4454 " (MI_ProviderFT_DeleteInstance)<ALIAS>_DeleteInstance,\n"
4455 " (MI_ProviderFT_AssociatorInstances)NULL,\n"
4456 " (MI_ProviderFT_ReferenceInstances)NULL,\n"
4457 " (MI_ProviderFT_EnableIndications)NULL,\n"
4458 " (MI_ProviderFT_DisableIndications)NULL,\n"
4459 " (MI_ProviderFT_Subscribe)NULL,\n"
4460 " (MI_ProviderFT_Unsubscribe)NULL,\n"
4461 " (MI_ProviderFT_Invoke)NULL,\n"
4462 "};\n"
4463 "\n";
4464 const char T2[] =
4465 "static MI_CONST MI_ProviderFT <ALIAS>_funcs =\n"
4466 "{\n"
4467 " (MI_ProviderFT_Load)<ALIAS>_Load,\n"
4468 " (MI_ProviderFT_Unload)<ALIAS>_Unload,\n"
4469 " (MI_ProviderFT_GetInstance)NULL,\n"
4470 " (MI_ProviderFT_EnumerateInstances)NULL,\n"
4471 " (MI_ProviderFT_CreateInstance)NULL,\n"
4472 " (MI_ProviderFT_ModifyInstance)NULL,\n"
4473 " (MI_ProviderFT_DeleteInstance)NULL,\n"
4474 mike 1.1 " (MI_ProviderFT_AssociatorInstances)NULL,\n"
4475 " (MI_ProviderFT_ReferenceInstances)NULL,\n"
4476 " (MI_ProviderFT_EnableIndications)NULL,\n"
4477 " (MI_ProviderFT_DisableIndications)NULL,\n"
4478 " (MI_ProviderFT_Subscribe)NULL,\n"
4479 " (MI_ProviderFT_Unsubscribe)NULL,\n"
4480 " (MI_ProviderFT_Invoke)NULL,\n"
4481 "};\n"
4482 "\n";
4483
4484
4485 // Only generate intrinsics for keyless classes:
4486 if (HasKeys(cd))
4487 {
4488 /* Create substitution for <GETINSTANCE> */
4489 string gi;
4490 if (Contains(s_options.noGetInstance, cd->name))
4491 gi = "NULL";
4492 else
4493 gi = sub("<ALIAS>_GetInstance", "<ALIAS>", alias);
4494
4495 mike 1.1 string r = sub(T1, "<ALIAS>", alias);
4496 r = sub(r, "<GETINSTANCE>", gi);
4497 puts(os, r);
4498 }
4499 else
4500 {
4501 string r = sub(T2, "<ALIAS>", alias);
4502 puts(os, r);
4503 }
4504 }
4505 }
4506
4507 //==============================================================================
4508 //
4509 // GenClassDecl()
4510 //
4511 // This function generates the class declaration for a MOF clas.
4512 //
4513 //==============================================================================
4514
4515 static void GenClassDecl(
4516 mike 1.1 Parser& parser,
4517 FILE* os,
4518 const MI_ClassDecl* cd)
4519 {
4520 const string alias = AliasOf(cd->name);
4521
4522 // Generate the qualifiers first.
4523 size_t numQualifiers = GenQualifiers(
4524 parser,
4525 os,
4526 cd->qualifiers,
4527 cd->numQualifiers,
4528 AliasOf(cd->name));
4529
4530 const char T[] =
4531 "/* class <ALIAS> */\n"
4532 "MI_CONST <STATIC>MI_ClassDecl <ALIAS>_rtti =\n"
4533 "{\n"
4534 " <FLAGS>, /* flags */\n"
4535 " <CODE>, /* code */\n"
4536 " MI_T(\"<CLASS>\"), /* name */\n"
4537 mike 1.1 " <QUALS>, /* qualifiers */\n"
4538 " <NQUALS>, /* numQualifiers */\n"
4539 " <PROPS>, /* properties */\n"
4540 " <NPROPS>, /* numProperties */\n"
4541 " sizeof(<ALIAS>), /* size */\n"
4542 " <SUPER>, /* superClass */\n"
4543 " <SUPERCLASSDECL>, /* superClassDecl */\n"
4544 "<METHODS>"
4545 " &<SCHEMA>, /* schema */\n"
4546 " <FUNCS>, /* functions */\n"
|
4548 mike 1.1 "};\n";
4549
4550 string r = T;
4551 r = sub(r, "<ALIAS>", alias);
4552 r = subx(r, "<CODE>", HashCode(cd->name));
4553 r = sub(r, "<CLASS>", cd->name);
4554 r = sub(r, "<FLAGS>", MakeFlags(cd->flags));
4555
4556 if (s_options.schema.size())
4557 r = sub(r, "<SCHEMA>", s_options.schema.c_str());
4558 else
4559 r = sub(r, "<SCHEMA>", "schemaDecl");
4560
4561 if (s_options.cpp || !s_options.noProviders)
4562 r = sub(r, "<STATIC>", "");
4563 else
4564 r = sub(r, "<STATIC>", "static ");
4565
4566 if (cd->numProperties)
4567 {
4568 string s = alias + "_props";
4569 mike 1.1 r = sub(r, "<PROPS>", s);
4570 r = sub(r, "<NPROPS>", "MI_COUNT(" + s + ")");
4571 }
4572 else
4573 {
4574 r = sub(r, "<PROPS>", "NULL");
4575 r = sub(r, "<NPROPS>", "0");
4576 }
4577
4578 if (numQualifiers)
4579 {
4580 string s = alias + "_quals";
4581 r = sub(r, "<QUALS>", s);
4582 r = sub(r, "<NQUALS>", "MI_COUNT(" + s + ")");
4583 }
4584 else
4585 {
4586 r = sub(r, "<QUALS>", "NULL");
4587 r = sub(r, "<NQUALS>", "0");
4588 }
4589
4590 mike 1.1 if (cd->superClass)
4591 {
4592 r = sub(r, "<SUPER>", Quote(cd->superClass));
4593 string t = "&" + AliasOf(cd->superClass) + "_rtti";
4594 r = sub(r, "<SUPERCLASSDECL>", t);
4595 }
4596 else
4597 {
4598 r = sub(r, "<SUPER>", "NULL");
4599 r = sub(r, "<SUPERCLASSDECL>", "NULL");
4600 }
4601
4602 if (cd->numMethods)
4603 {
4604 const char T2[] =
4605 " <ALIAS>_meths, /* methods */\n"
4606 " MI_COUNT(<ALIAS>_meths), /* numMethods */\n";
4607 string t2 = sub(T2, "<ALIAS>", alias);
4608 r = sub(r, "<METHODS>", t2);
4609 }
4610 else
4611 mike 1.1 {
4612 const char T2[] =
4613 " NULL, /* methods */\n"
4614 " 0, /* numMethods */\n";
4615 r = sub(r, "<METHODS>", T2);
4616 }
4617
4618 if (providerClasses.find(cd->name) == providerClasses.end())
4619 {
4620 r = sub(r, "<FUNCS>", "NULL");
4621 }
4622 else
4623 {
4624 r = sub(r, "<FUNCS>", "&" + alias + "_funcs");
4625 }
4626
4627 puts(os, r);
4628 nl(os);
4629 }
4630
4631 //==============================================================================
4632 mike 1.1 //
4633 // GenQualifierDecl()
4634 //
4635 // This function generates a single qualifier declaration.
4636 //
4637 //==============================================================================
4638
4639 static void GenQualifierDecl(FILE* os, const MI_QualifierDecl* qd)
4640 {
4641 const char T[] =
4642 "static MI_CONST MI_QualifierDecl <NAME>_qual_decl =\n"
4643 "{\n"
4644 " MI_T(\"<NAME>\"), /* name */\n"
4645 " <TYPE>, /* type */\n"
4646 " <SCOPE>, /* scope */\n"
4647 " <FLAVOR>, /* flavor */\n"
4648 " <SUBSCRIPT>, /* subscript */\n"
4649 " <VALUE>, /* value */\n"
4650 "};\n"
4651 "\n";
4652
4653 mike 1.1 string stem = string(qd->name) + "_qual_decl";
4654
4655 // Generate the value.
4656 if (qd->value)
4657 {
4658 if (qd->flavor & MI_FLAG_TRANSLATABLE)
4659 GenValue(os, stem, qd->type, qd->value, true);
4660 else
4661 GenValue(os, stem, qd->type, qd->value, false);
4662 }
4663
4664 string r = T;
4665
4666 r = sub(r, "<NAME>", qd->name);
4667 r = sub(r, "<TYPE>", MakeType(qd->type));
4668 r = subu(r, "<SUBSCRIPT>", qd->subscript);
4669 r = sub(r, "<FLAVOR>", MakeFlavor(qd->flavor));
4670 r = sub(r, "<SCOPE>", MakeScope(qd->scope));
4671
4672 if (qd->value)
4673 r = sub(r, "<VALUE>", "&" + stem + "_value");
4674 mike 1.1 else
4675 r = sub(r, "<VALUE>", "NULL");
4676
4677 puts(os, r);
4678 }
4679
4680 //==============================================================================
4681 //
4682 // GenQualifierDecls()
4683 //
4684 // This function generates an array of qualifier declarations.
4685 //
4686 //==============================================================================
4687
4688 size_t GenQualifierDecls(Parser& parser, FILE* os)
4689 {
4690 size_t count = 0;
4691
4692 /* Check if qualifiers are ignored */
4693 if (s_options.ignoreAllQualifiers)
4694 return 0;
4695 mike 1.1
4696 // Put the comment box.
4697 PutCommentBox(os, "Qualifier declarations");
4698 nl(os);
4699
4700 vector<string> names;
4701 parser.getQualifierDeclNames(names);
4702
4703 // Generate the individual qualifier declarations.
4704 for (size_t i = 0; i < names.size(); i++)
4705 {
4706 const MI_QualifierDecl* qd = parser.findQualifierDecl(names[i]);
4707
4708 if (!qd)
4709 {
4710 err(ID_UNKNOWN_QUALIFIER, "unknown qualifier: %s",
4711 names[i].c_str());
4712 }
4713
4714 // Do not generate standard qualifiers.
4715 if (!s_options.standardQualifiers &&
4716 mike 1.1 FindStandardQualifierDecl(qd->name))
4717 {
4718 continue;
4719 }
4720
4721 GenQualifierDecl(os, qd);
4722 count++;
4723 }
4724
4725 // Generate the qualifier declaration array.
4726 if (count)
4727 {
4728 putl(os,
4729 "static MI_QualifierDecl MI_CONST* MI_CONST qualifierDecls[] =");
4730 putl(os, "{");
4731
4732 for (size_t i = 0; i < names.size(); i++)
4733 {
4734 const MI_QualifierDecl* qd = parser.findQualifierDecl(names[i]);
4735
4736 // Do not generate standard qualifiers.
4737 mike 1.1 if (!s_options.standardQualifiers &&
4738 FindStandardQualifierDecl(qd->name))
4739 {
4740 continue;
4741 }
4742
4743 if (!qd)
4744 {
4745 err(ID_UNKNOWN_QUALIFIER, "unknown qualifier: %s",
4746 names[i].c_str());
4747 }
4748
4749 put(os, " &%s_qual_decl,\n", qd->name);
4750 }
4751
4752 putl(os, "};");
4753 nl(os);
4754 }
4755
4756 return count;
4757 }
4758 mike 1.1
4759 //==============================================================================
4760 //
4761 // GenClassSchema()
4762 //
4763 // This function generates one class for the schema source file.
4764 //
4765 //==============================================================================
4766
4767 static void GenClassSchema(
4768 Parser& parser,
4769 FILE* os,
4770 const MI_ClassDecl* cd,
4771 const vector<string>& classNames)
4772 {
4773 // Prevent recursion.
4774 {
4775 if (s_generated.find(cd->name) != s_generated.end())
4776 return;
4777
4778 s_generated.insert(cd->name);
4779 mike 1.1 }
4780
4781 // Find direct dependencies of this class.
4782 vector<string> deps;
4783 FindDirectDependencies(cd, deps);
4784
4785 // Recurse on dependencies.
4786 for (size_t i = 0; i < deps.size(); i++)
4787 {
4788 const MI_ClassDecl* tcd = parser.findClassDecl(deps[i].c_str());
4789
4790 if (!tcd)
4791 err(ID_UNKNOWN_CLASS, "unknown class: %s", deps[i].c_str());
4792
4793 GenClassSchema(parser, os, tcd, classNames);
4794 }
4795
4796 // Refuse to generate same class more than once.
4797 if (generated_classes.find(cd->name) != generated_classes.end())
4798 return;
4799
4800 mike 1.1 generated_classes.insert(cd->name);
4801
4802 // Generate comment box for this class.
4803 const string al = AliasOf(cd->name);
4804 PutCommentBox(os, al);
4805 nl(os);
4806
4807 // Generate declarations.
4808 GenPropertyDecls(parser, os, cd);
4809
4810 // Generate method declarations.
4811 GenMethodDecls(parser, os, cd);
4812
4813 // Generate provider function table.
4814 if (providerClasses.find(cd->name) != providerClasses.end())
4815 GenFunctionTable(os, cd);
4816
4817 // Generate the class declaration.
4818 GenClassDecl(parser, os, cd);
4819 }
4820
4821 mike 1.1 //==============================================================================
4822 //
4823 // GenSchemaSourceFile()
4824 //
4825 // This function generates the schema.c source file, which contains the
4826 // qualifier declarations, class declarations, and the schema object that
4827 // refers to arrays of each.
4828 //
4829 //==============================================================================
4830
4831 static void GenSchemaSourceFile(
4832 Parser& parser,
4833 const vector<string>& classNames,
4834 const set<string>& /*classIdentifiers*/)
4835 {
4836 // Open the file.
4837 string path = ExpandPath("schema.c");
4838
4839 FILE* os = Fopen(path.c_str(), "w");
4840
4841 if (!os)
4842 mike 1.1 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
4843
4844 GenStatikGenLine(os);
4845
4846 Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
4847
4848 // Print warning box.
4849 PutCommentBox(os, WARNING);
4850
4851 // Include <MI.h> header.
4852 putl(os, "#include <ctype.h>");
4853 putl(os, "#include <MI.h>");
4854
4855 bool generateMatch = false;
4856
4857 // Include each direct header file (headers will indirectly include others).
4858 for (size_t i = 0; i < classNames.size(); i++)
4859 {
4860 // Find the class.
4861 const MI_ClassDecl* cd = parser.findClassDecl(classNames[i].c_str());
4862
4863 mike 1.1 if (!cd)
4864 err(ID_UNKNOWN_CLASS, "unknown class: %s", classNames[i].c_str());
4865
4866 if (!s_options.association && (cd->flags & MI_FLAG_ASSOCIATION) &&
4867 CanGenerateAssocRoles(cd))
4868 {
4869 generateMatch = true;
4870 }
4871
4872 // Include the class header.
4873 const string alias = AliasOf(cd->name);
4874 putl(os, "#include \"%s.h\"", alias.c_str());
4875 }
4876
4877 nl(os);
4878
4879 // Generate forward reference to schema declaration.
4880 {
4881 PutCommentBox(os, "Schema Declaration");
4882 nl(os);
4883
4884 mike 1.1 if (s_options.schema.size())
4885 putl(os, "extern MI_SchemaDecl %s;", s_options.schema.c_str());
4886 else
4887 putl(os, "extern MI_SchemaDecl schemaDecl;");
4888
4889 nl(os);
4890 }
4891
4892 // Generate match function (if necessary)
4893 if (generateMatch)
4894 {
4895 const char MATCH[] =
4896 "static int _Match(const MI_Char* p, const MI_Char* q)\n"
4897 "{\n"
4898 " if (!p || !q || !p[0] || !q[0])\n"
4899 " return 1;\n"
4900 "\n"
4901 " while (*p && *q)\n"
4902 " if (toupper((MI_Uint16)*p++) - toupper((MI_Uint16)*q++))\n"
4903 " return 0;\n"
4904 "\n"
4905 mike 1.1 " return *p == '\\0' && *q == '\\0';\n"
4906 "}\n"
4907 "\n";
4908
4909 PutCommentBox(os, "_Match()");
4910 nl(os);
4911 puts(os, MATCH);
4912 }
4913
4914 // Gen qualifier declarations.
4915 size_t numQualifierDecls = GenQualifierDecls(parser, os);
4916
4917 // Generate class declarations.
4918 for (size_t i = 0; i < classNames.size(); i++)
4919 {
4920 // Find the class.
4921 const MI_ClassDecl* cd = parser.findClassDecl(classNames[i].c_str());
4922
4923 if (!cd)
4924 err(ID_UNKNOWN_CLASS, "unknown class: %s", classNames[i].c_str());
4925
4926 mike 1.1 GenClassSchema(parser, os, cd, classNames);
4927 }
4928
4929 // Generate server declaration.
4930 PutCommentBox(os, "__mi_server");
4931 nl(os);
4932 putl(os, "MI_Server* __mi_server;");
4933
4934 // Generate MI_SchemaDecl.
4935
4936 PutCommentBox(os, "Schema");
4937 nl(os);
4938
4939 putl(os, "static MI_ClassDecl MI_CONST* MI_CONST classes[] =");
4940 putl(os, "{");
4941
4942 set<string>::const_iterator p = generated_classes.begin();
4943 set<string>::const_iterator end = generated_classes.end();
4944
4945 for (; p != end; p++)
4946 {
4947 mike 1.1 // Find the class.
4948 const MI_ClassDecl* cd =
4949 parser.findClassDecl((*p).c_str());
4950
4951 if (!cd)
4952 err(ID_UNKNOWN_CLASS, "unknown class: %s", (*p).c_str());
4953
4954 const string alias = AliasOf(cd->name);
4955 putl(os, " &%s_rtti,", alias.c_str());
4956 }
4957
4958 putl(os, "};");
4959 nl(os);
4960
4961 {
4962 static const char T[] =
4963 "MI_SchemaDecl <SCHEMADECL> =\n"
4964 "{\n"
4965 " <QUALIFIERDECLS>, /* qualifierDecls */\n"
4966 " <NUMQUALIFIERDECLS>, /* numQualifierDecls */\n"
4967 " classes, /* classDecls */\n"
4968 mike 1.1 " MI_COUNT(classes), /* classDecls */\n"
4969 "};\n"
4970 "\n";
4971
4972 string r = T;
4973
4974 if (s_options.schema.size())
4975 r = sub(r, "<SCHEMADECL>", s_options.schema);
4976 else
4977 r = sub(r, "<SCHEMADECL>", "schemaDecl");
4978
4979 if (numQualifierDecls)
4980 {
4981 r = sub(r, "<QUALIFIERDECLS>", "qualifierDecls");
4982 r = sub(r, "<NUMQUALIFIERDECLS>", "MI_COUNT(qualifierDecls)");
4983 }
4984 else
4985 {
4986 r = sub(r, "<QUALIFIERDECLS>", "NULL");
4987 r = sub(r, "<NUMQUALIFIERDECLS>", "0");
4988 }
4989 mike 1.1
4990 puts(os, r);
4991 }
4992
4993 // Generate MI_Server methods.
4994 {
4995 const char T[] =
4996 "MI_Result MI_CALL MI_Server_GetVersion(\n"
4997 " MI_Uint32* version)"
4998 "{\n"
4999 " return __mi_server->serverFT->GetVersion(version);\n"
5000 "}\n"
5001 "\n"
5002 "MI_Result MI_CALL MI_Server_GetSystemName(\n"
5003 " const MI_Char** systemName)\n"
5004 "{\n"
5005 " return __mi_server->serverFT->GetSystemName(systemName);\n"
5006 "}\n";
5007
5008 PutCommentBox(os, "MI_Server Methods");
5009 nl(os);
5010 mike 1.1 puts(os, T);
5011 nl(os);
5012 }
5013
5014 #if 0
5015 // Generate cross-check with class identifiers:
5016 {
5017 set<string>::const_iterator first = classIdentifiers.begin();
5018 set<string>::const_iterator last = classIdentifiers.end();
5019
5020 while (first != last)
5021 {
5022 const string& s = *first++;
5023 putl(os, "#ifndef %s", s.c_str());
5024 putl(os, "# error \"generational inconsistency: %s is undefined\"",
5025 s.c_str());
5026 putl(os, "#endif\n");
5027 }
5028 }
5029 #endif
5030
5031 mike 1.1 // Close the file.
5032 fclose(os);
5033 }
5034
5035 //==============================================================================
5036 //
5037 // GenerateMI_Main()
5038 //
5039 // This function generates the MI_Main() entry point. It returns a
5040 // string instead of writing to the output stream directory. This is to
5041 // support patching of module.c.
5042 //
5043 //==============================================================================
5044
5045 string GenerateMI_Main()
5046 {
5047 string result;
5048
5049 // MI_Main() preamble:
5050 {
5051 string r = MODULE_C_TEMPLATE_2;
5052 mike 1.1
5053 if (s_options.schema.size())
5054 r = sub(r, "<SCHEMADECL>", s_options.schema);
5055 else
5056 r = sub(r, "<SCHEMADECL>", "schemaDecl");
5057
5058 if (s_options.entryPoint.size())
5059 r = sub(r, "<ENTRYPOINT>", s_options.entryPoint);
5060 else
5061 r = sub(r, "<ENTRYPOINT>", "MI_Main");
5062
5063 result += r;
5064 }
5065
5066 // MI_Main() flags:
5067 {
5068 string r;
5069
5070 if (!s_options.ignoreAllQualifiers)
5071 {
5072 if (!s_options.standardQualifiers)
5073 mike 1.1 r += " module.flags |= MI_MODULE_FLAG_STANDARD_QUALIFIERS;\n";
5074
5075 if (s_options.descriptions)
5076 r += " module.flags |= MI_MODULE_FLAG_DESCRIPTIONS;\n";
5077
5078 if (s_options.values)
5079 r += " module.flags |= MI_MODULE_FLAG_VALUES;\n";
5080
5081 if (s_options.mappingStrings)
5082 r += " module.flags |= MI_MODULE_FLAG_MAPPING_STRINGS;\n";
5083
5084 if (s_options.booleanQualifiers)
5085 r += " module.flags |= MI_MODULE_FLAG_BOOLEANS;\n";
5086 }
5087
5088 if (s_options.cpp)
5089 r += " module.flags |= MI_MODULE_FLAG_CPLUSPLUS;\n";
5090
5091 if (s_options.localize)
5092 r += " module.flags |= MI_MODULE_FLAG_LOCALIZED;\n";
5093
5094 mike 1.1 if (s_options.filterSupport)
5095 r += " module.flags |= MI_MODULE_FLAG_FILTER_SUPPORT;\n";
5096
5097 result += r;
5098 }
5099
5100 // MI_Main() postamble:
5101 {
5102 string r = MODULE_C_TEMPLATE_3;
5103
5104 if (s_options.schema.size())
5105 r = sub(r, "<SCHEMADECL>", s_options.schema);
5106 else
5107 r = sub(r, "<SCHEMADECL>", "schemaDecl");
5108
5109 {
5110 char buf[64];
5111 Snprintf(buf, MI_COUNT(buf), "MI_MAKE_VERSION(%u,%u,%u)",
5112 MI_MAJOR, MI_MINOR, MI_REVISON);
5113 r = sub(r, "<VERSION>", buf);
5114 }
5115 mike 1.1
5116 result += r;
5117 }
5118
5119 return result;
5120 }
5121
5122 //==============================================================================
5123 //
5124 // SkipSpace()
5125 //
5126 // Skip over whitespace. Return true when the '\0' character is found.
5127 //
5128 //==============================================================================
5129
5130 static bool SkipSpace(const char*& p)
5131 {
5132 while (isspace((unsigned char)*p))
5133 p++;
5134
5135 return *p == '\0';
5136 mike 1.1 }
5137
5138 //==============================================================================
5139 //
5140 // GenModuleSourceFile()
5141 //
5142 // This function generates the module.c source file, which contains the
5143 // MI_Main() entry point.
5144 //
5145 //==============================================================================
5146
5147 static void GenModuleSourceFile()
5148 {
5149 // Open the file.
5150 const string path = ExpandPath("module.c");
5151
5152 if (Exists(path.c_str()))
5153 {
5154 // Read file into memory.
5155 vector<char> data;
5156
5157 mike 1.1 if (!Inhale(path.c_str(), data))
5158 {
5159 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s",
5160 path.c_str());
5161 }
5162
5163
5164 // Replace MI_Main() body with new MI_Main() body.
5165 const char* start = &data[0];
5166 const char* end = &data[data.size()-1];
5167 const char* p = start;
5168 bool found = false;
5169
5170 // Match "MI_EXTERN_C MI_EXPORT MI_Module* MI_MAIN_CALL MI_Main(...) {}
5171 while (p != end)
5172 {
5173 const char* first = p;
5174
5175 // Expect 'MI_EXTERN_C' [optionally]
5176 if (strncmp(p, "MI_EXTERN_C", 11) == 0)
5177 {
5178 mike 1.1 p += 11;
5179
5180 // Skip whitespace:
5181 if (SkipSpace(p))
5182 break;
5183 }
5184
5185 // Expect 'MI_EXPORT'
5186 if (strncmp(p, "MI_EXPORT", 9) != 0)
5187 {
5188 p++;
5189 continue;
5190 }
5191 p += 9;
5192
5193 // Skip whitespace:
5194 if (SkipSpace(p))
5195 break;
5196
5197 // Expect 'MI_Module'
5198 if (strncmp(p, "MI_Module", 9) != 0)
5199 mike 1.1 {
5200 p++;
5201 continue;
5202 }
5203 p += 9;
5204
5205 // Skip whitespace:
5206 if (SkipSpace(p))
5207 break;
5208
5209 // Expect '*'
5210 if (*p != '*')
5211 {
5212 p++;
5213 continue;
5214 }
5215 p++;
5216
5217 // Skip whitespace:
5218 if (SkipSpace(p))
5219 break;
5220 mike 1.1
5221 // Skip 'MI_MAIN_CALL'
5222 {
5223 const char TMP[] = "MI_MAIN_CALL";
5224
5225 if (strncmp(p, TMP, sizeof(TMP)-1) == 0)
5226 p += sizeof(TMP)-1;
5227 }
5228
5229 // Skip whitespace:
5230 if (SkipSpace(p))
5231 break;
5232
5233 // Expect 'MI_Main'
5234 {
5235 const char *TMP =
5236 (s_options.entryPoint.empty() ? "MI_Main" : s_options.entryPoint.c_str());
5237
5238 if (strncmp(p, TMP, strlen(TMP)) != 0)
5239 {
5240 p++;
5241 mike 1.1 continue;
5242 }
5243 p += strlen(TMP);
5244 }
5245
5246 // Skip whitespace:
5247 if (SkipSpace(p))
5248 break;
5249
5250 // Expect '('
5251 if (*p != '(')
5252 {
5253 p++;
5254 continue;
5255 }
5256
5257 // Skip non ')' chars.
5258 while (*p && *p != ')')
5259 p++;
5260
5261 // Expect ')'
5262 mike 1.1 if (*p != ')')
5263 {
5264 p++;
5265 continue;
5266 }
5267 p++;
5268
5269 // Skip whitespace:
5270 if (SkipSpace(p))
5271 break;
5272
5273 // Expect '{'
5274 if (*p != '{')
5275 {
5276 p++;
5277 continue;
5278 }
5279
5280 // Skip non '}' chars.
5281 while (*p && *p != '}')
5282 p++;
5283 mike 1.1
5284 // Expect '}'
5285 if (*p != '}')
5286 {
5287 p++;
5288 continue;
5289 }
5290 p++;
5291
5292 const char* last = p;
5293
5294 found = true;
5295 string tmp = &data[0];
5296 string r;
5297 r.append(start, first - start);
5298 r.append(GenerateMI_Main());
5299 r.append(last);
5300
5301 // Rewrite the file.
5302 {
5303 FILE* os = Fopen(path.c_str(), "w");
5304 mike 1.1
5305 if (!os)
5306 {
5307 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s",
5308 path.c_str());
5309 }
5310
5311 Fprintf(s_stdout, ID_PATCHING, "Patching %s\n", path.c_str());
5312 put(os, "%s", r.c_str());
5313
5314 fclose(os);
5315 }
5316 break;
5317 }
5318
5319 // If MI_Main() not found.
5320 if (!found)
5321 {
5322 err(ID_FAILED_TO_PATCH_MODULE,
5323 "Unable to patch module.c: cannot find %s() body: %s",
5324 (s_options.entryPoint.empty() ?
5325 mike 1.1 "MI_Main" : s_options.entryPoint.c_str()),
5326 path.c_str());
5327 }
5328
5329 return;
5330 }
5331
5332 FILE* os = Fopen(path.c_str(), "w");
5333
5334 if (!os)
5335 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
5336
5337 GenStatikGenLine(os);
5338 Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
5339
5340 // Generate part 1:
5341 {
5342 string r = MODULE_C_TEMPLATE_1;
5343
5344 if (s_options.schema.size())
5345 r = sub(r, "<SCHEMADECL>", s_options.schema);
5346 mike 1.1 else
5347 r = sub(r, "<SCHEMADECL>", "schemaDecl");
5348
5349 put(os, "%s", r.c_str());
5350 }
5351
5352 // Generate MI_Main()
5353 {
5354 string r = GenerateMI_Main();
5355 put(os, "%s\n", r.c_str());
5356 }
5357
5358 // Close the file.
5359 fclose(os);
5360 }
5361
5362 //==============================================================================
5363 //
5364 // GenModuleCppSourceFile()
5365 //
5366 // This function generates the module.cpp source file, which contains the
5367 mike 1.1 // Module class definiiton.
5368 //
5369 //==============================================================================
5370
5371 static void GenModuleCppSourceFile()
5372 {
5373 // Open the file.
5374 const string path = ExpandPath("module.cpp");
5375
5376 if (Exists(path.c_str()))
5377 {
5378 Fprintf(s_stdout, ID_SKIPPING, "Skipping %s\n", path.c_str());
5379 return;
5380 }
5381
5382 FILE* os = Fopen(path.c_str(), "w");
5383
5384 if (!os)
5385 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
5386
5387 Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
5388 mike 1.1
5389 // simple template - no parameters
5390 {
5391 put(os, "%s\n", MODULE_CPP_TEMPLATE);
5392 }
5393
5394 // Close the file.
5395 fclose(os);
5396 }
5397
5398 //==============================================================================
5399 //
5400 // GenModuleCppHeaderFile()
5401 //
5402 // This function generates the module.h header file, which contains the
5403 // Module class declaration.
5404 //
5405 //==============================================================================
5406
5407 static void GenModuleCppHeaderFile()
5408 {
5409 mike 1.1 // Open the file.
5410 const string path = ExpandPath("module.h");
5411
5412 if (Exists(path.c_str()))
5413 {
5414 Fprintf(s_stdout, ID_SKIPPING, "Skipping %s\n", path.c_str());
5415 return;
5416 }
5417
5418 FILE* os = Fopen(path.c_str(), "w");
5419
5420 if (!os)
5421 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
5422
5423 Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
5424
5425 // simple template - no parameters
5426 {
5427 put(os, "%s\n", MODULE_H_TEMPLATE);
5428 }
5429
5430 mike 1.1 // Close the file.
5431 fclose(os);
5432 }
5433
5434 //==============================================================================
5435 //
5436 // GenModuleStubsFile()
5437 //
5438 // This function generates the stubs.cpp source file, which contains the
5439 // wrapper functions to convert 'c' style server calls into provider class
5440 // calls
5441 //
5442 //==============================================================================
5443
5444 static void GenModuleStubsFile(
5445 Parser& parser,
5446 const vector<string>& classNames)
5447 {
5448 // Open the file.
5449 string path = ExpandPath("stubs.cpp");
5450
5451 mike 1.1 FILE* os = Fopen(path.c_str(), "w");
5452
5453 if (!os)
5454 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
5455
5456 GenStatikGenLine(os);
5457
5458 Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
5459
5460 // Print warning box.
5461 PutCommentBox(os, WARNING);
5462
5463 // Include <MI.h> header.
5464 putl(os, "#include <MI.h>");
5465 putl(os, "#include \"module.h\"");
5466
5467 // Include each direct header file (headers will indirectly include others).
5468 for (size_t i = 0; i < classNames.size(); i++)
5469 {
5470 // Find the class.
5471 const MI_ClassDecl* cd = parser.findClassDecl(classNames[i].c_str());
5472 mike 1.1
5473 if (!cd)
5474 err(ID_UNKNOWN_CLASS, "unknown class: %s", classNames[i].c_str());
5475
5476 /* skip not-requested classes */
5477 if (providerClasses.find(cd->name) == providerClasses.end())
5478 continue;
5479
5480 // Include the class header.
5481 const string alias = AliasOf(cd->name);
5482 putl(os, "#include \"%s_Class_Provider.h\"", alias.c_str());
5483 }
5484
5485 nl(os);
5486 putl(os, "using namespace mi;");
5487 nl(os);
5488
5489 // generate c++ wrappers
5490 for (size_t i = 0; i < classNames.size(); i++)
5491 {
5492 // Find the class.
5493 mike 1.1 const MI_ClassDecl* cd = parser.findClassDecl(classNames[i].c_str());
5494
5495 if (!cd)
5496 err(ID_UNKNOWN_CLASS, "unknown class: %s", classNames[i].c_str());
5497
5498 /* skip not-requested classes */
5499 if (providerClasses.find(cd->name) == providerClasses.end())
5500 continue;
5501
5502 // generate stub for the class
5503 GenerateClassStub( os, cd );
5504 }
5505
5506 // Generate module-level load/unload
5507 {
5508 string r = STUBS_LOAD_UNLOAD_TEMPLATE;
5509
5510 if (s_options.schema.size())
5511 r = sub(r, "<SCHEMADECL>", s_options.schema);
5512 else
5513 r = sub(r, "<SCHEMADECL>", "schemaDecl");
5514 mike 1.1
5515 put(os, "%s", r.c_str());
5516 }
5517
5518 // Generate MI_Main()
5519 {
5520 string r = GenerateMI_Main();
5521 put(os, "%s\n", r.c_str());
5522 }
5523
5524 nl(os);
5525
5526 // Close the file.
5527 fclose(os);
5528 }
5529
5530 //==============================================================================
5531 //
5532 // GenerateStringsFile()
5533 //
5534 // This function generates the string.rc file, which contains the
5535 mike 1.1 // localized qualifier strings (only called if -l option present)
5536 //
5537 //==============================================================================
5538
5539 static void GenerateStringsFile()
5540 {
5541 // Open the file.
5542 const string path = ExpandPath("strings.rc");
5543 FILE* os = Fopen(path.c_str(), "w");
5544
5545 if (!os)
5546 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
5547
5548 GenStatikGenLine(os);
5549 Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
5550
5551 // Generate file with the following format.
5552 //
5553 // STRINGTABLE
5554 // {
5555 // <INTEGER-IDENTIFIER>, <STRING>
5556 mike 1.1 // }
5557 {
5558 fprintf(os, "STRINGTABLE\n");
5559 fprintf(os, "{\n");
5560
5561 for (size_t i = 0; i < s_localizations.size(); i++)
5562 {
5563 MI_Uint32 id = (MI_Uint32)(i + 1);
5564 const string& str = s_localizations[i];
5565 fprintf(os, " %u, \"%s\"\n", id, str.c_str());
5566 }
5567
5568 fprintf(os, "}\n");
5569 }
5570
5571 // Close the file.
5572 fclose(os);
5573 }
5574
5575 static string _GetClassInheritanceRegistrationEntry(
5576 const MI_ClassDecl* cd
5577 mike 1.1 )
5578 {
5579 string res = cd->name;
5580
5581 while (cd->superClassDecl)
5582 {
5583 res += ",";
5584 cd = cd->superClassDecl;
5585 res += cd->name;
5586 }
5587
5588 return res;
5589 }
5590
5591 static string _GetClassRegistrationEntry(
5592 Parser& parser,
5593 const MI_ClassDecl* cd
5594 )
5595 {
5596 string res;
5597
5598 mike 1.1 if (cd->flags & MI_FLAG_ASSOCIATION)
5599 {
5600 const MI_ClassDecl* cd_left = 0, *cd_right = 0;
5601 // find two ref members
5602 for (MI_Uint32 i = 0; i < cd->numProperties; i++)
5603 {
5604 if (cd->properties[i]->type == MI_REFERENCE)
5605 {
5606 const MI_ClassDecl* cd_ref =
5607 parser.findClassDecl(cd->properties[i]->className);
5608
5609 if (!cd_ref)
5610 {
5611 err(ID_UNKNOWN_CLASS, "unknown class: %s",
5612 cd->properties[i]->className);
5613 }
5614
5615 if (!cd_left)
5616 cd_left = cd_ref;
5617 else
5618 cd_right = cd_ref;
5619 mike 1.1 }
5620 }
5621
5622 if (!cd_right)
5623 {
5624 err(ID_INSUFFICIENT_REFERENCES, "insufficient references: "
5625 "class must have 2 or more: %s", cd->name);
5626 }
5627
5628 res = _GetClassInheritanceRegistrationEntry(cd_left) +
5629 "+" +
5630 _GetClassInheritanceRegistrationEntry(cd) +
5631 "+" +
5632 _GetClassInheritanceRegistrationEntry(cd_right);
5633 }
5634 else
5635 {
5636 res = _GetClassInheritanceRegistrationEntry(cd);
5637 }
5638 return res;
5639 }
5640 mike 1.1
5641 //==============================================================================
5642 //
5643 // GenerateRegistryFile()
5644 //
5645 // This function generates skeleton of the provider registry file,
5646 // which contains information server will use to operate with provider
5647 // (only called if -reg option present)
5648 //
5649 //==============================================================================
5650
5651 static void GenerateRegistryFile(
5652 Parser& parser,
5653 const vector<string>& classNames)
5654 {
5655 // Open the file.
5656 const string path = ExpandPath(s_options.providerRegistryPath);
5657 FILE* os = Fopen(path.c_str(), "a");
5658
5659 if (!os)
5660 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
5661 mike 1.1
5662 Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
5663
5664 // Generate file with the following format.
5665 //
5666 // statik:test/c:MSFT_Person,MSFT_Animal,MSFT_Base + MSFT_Friends +
5667 // MSFT_Person,MSFT_Animal,MSFT_Base:PersonProvider
5668 //
5669 {
5670 fprintf(os, "# auto-generated skeleton of registry file\n");
5671 fprintf(os, "# please update it with correct namespace[s]\n");
5672
5673 for (size_t i = 0; i < classNames.size(); i++)
5674 {
5675 const char* cn = classNames[i].c_str();
5676 const MI_ClassDecl* cd = parser.findClassDecl(cn);
5677
5678 if (!cd)
5679 err(ID_UNKNOWN_CLASS, "unknown class: %s", cn);
5680
5681 fprintf(os, "statik:<ns>:%s:<provider>\n",
5682 mike 1.1 _GetClassRegistrationEntry(parser,cd).c_str());
5683
5684 }
5685
5686 for (size_t i = 0; i < s_localizations.size(); i++)
5687 {
5688 MI_Uint32 id = (MI_Uint32)(i + 1);
5689 const string& str = s_localizations[i];
5690 fprintf(os, " %u, \"%s\"\n", id, str.c_str());
5691 }
5692
5693 fprintf(os, "\n");
5694 }
5695
5696 // Close the file.
5697 fclose(os);
5698 }
5699
5700 //==============================================================================
5701 //
5702 // GenMakefile()
5703 mike 1.1 //
5704 // This function generates a 'GNUmakefile' for the given provider.
5705 //
5706 //==============================================================================
5707
5708 static void GenMakefile(
5709 const string& library,
5710 const vector<string>& classNames,
5711 const string& cmdLine)
5712 {
5713 const char MAKEFILE[] = "GNUmakefile";
5714
5715 MI_UNUSED(library);
5716
5717 // If makefile already exists, quit:
5718 if (Exists(MAKEFILE))
5719 {
5720 Fprintf(s_stdout, ID_SKIPPING, "Skipping %s\n", MAKEFILE);
5721 return;
5722 }
5723
5724 mike 1.1 // Open Makefile:
5725 FILE* os = Fopen(MAKEFILE, "w");
5726 if (!os)
5727 err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", MAKEFILE);
5728
5729 {
5730 // 'OMIMAK' variable.
5731 string OMIMAK = string(GetPath(ID_DATADIR)) + "/omi.mak";
5732
5733 // 'PROVIDER' variable.
5734 string PROVIDER = s_options.providerName;
5735
5736 // 'SOURCES' variable.
5737 string SOURCES;
5738 {
5739 if (s_options.cpp)
5740 SOURCES = "$(wildcard *.c *.cpp)";
5741 else
5742 SOURCES = "$(wildcard *.c)";
5743 }
5744
5745 mike 1.1 // 'CLASSNAMES' variable.
5746 string CLASSES;
5747 {
5748 for (size_t i = 0; i < classNames.size(); i++)
5749 {
5750 CLASSES += classNames[i];
5751 if (i + 1 == classNames.size())
5752 CLASSES += ' ';
5753 }
5754 }
5755
5756 string r;
5757
5758 if (s_options.cpp)
5759 r = CXXMAKEFILE_TEMPLATE;
5760 else
5761 r = CMAKEFILE_TEMPLATE;
5762
5763 r = sub(r, "<OMIMAK>", OMIMAK);
5764 r = sub(r, "<PROVIDER>", PROVIDER);
5765 r = sub(r, "<SOURCES>", SOURCES);
5766 mike 1.1 r = sub(r, "<CLASSES>", CLASSES);
5767 r = sub(r, "<CMDLINE>", cmdLine);
5768 puts(os, r);
5769 }
5770
5771 // Print creation message:
5772 Fprintf(s_stdout, ID_CREATING, "Creating %s\n", MAKEFILE);
5773
5774 // Close file:
5775 fclose(os);
5776 }
5777 //==============================================================================
5778 //
5779 // main()
5780 //
5781 // This program generates source code from MOF definitions. The source
5782 // includes run-time type information for class declarations and qualifier
5783 // declarations as well as class provider stubs.
5784 //
5785 //==============================================================================
5786
5787 mike 1.1 int GeneratorMain(
5788 const std::string& programNameArg,
5789 const std::vector<std::string>& mofFilesArg,
5790 const std::vector<std::string>& classNamesArg,
5791 const GeneratorOptions& optionsArg)
5792 {
5793 arg0 = programNameArg.c_str();
5794
5795 // Make a copy of the vector whose strings we can later modify in place.
5796 vector<string> localClassNamesArg;
5797 {
5798 for (size_t i = 0; i < classNamesArg.size(); i++)
5799 localClassNamesArg.push_back(classNamesArg[i].c_str());
5800 }
5801
5802 // WIndows trick to get compatible float format
5803 #ifdef WIN32
5804 _set_output_format(_TWO_DIGIT_EXPONENT);
5805 #endif
5806
5807 // clear global params
5808 mike 1.1 generated_headers.clear();
5809 generated_classes.clear();
5810 providerClasses.clear();
5811 s_generated.clear();
5812 aliases.clear();
5813 s_localizations.clear();
5814
5815 // Save command-line options.
5816 s_options = optionsArg;
5817
5818 // Create directory given by -d option.
5819 if (s_options.dir.size())
5820 Mkdir(s_options.dir.c_str(), 0777);
5821
5822 // Check schema given by -s otpion.
5823 if (s_options.schema.size())
5824 {
5825 /* Check whether this is a valid C identifier */
5826 if (!ValidIdent(s_options.schema))
5827 err(ID_INVALID_SCHEMA_OPTION, "invalid schema option: %s",
5828 s_options.schema.c_str());
5829 mike 1.1 }
5830
5831 if ( s_options.quiet )
5832 {
5833 s_stdout = Fopen(NULL_FILE, "a");
5834 }
5835 else
5836 {
5837 s_stdout = stdout;
5838 }
5839
5840 // Create the parser.
5841 Parser parser(s_options.paths, s_options.warnings);
5842
5843 // Parse all the MOF files.
5844 for (size_t i = 0; i < mofFilesArg.size(); i++)
5845 {
5846 const char* path = mofFilesArg[i].c_str();
5847
5848 if (parser.parse(path) != 0)
5849 {
5850 mike 1.1 err(ID_FAILED_TO_PARSE_MOF_FILE, "failed to parse MOF file: %s",
5851 path);
5852 }
5853 }
5854
5855 // Build the alias table, which maps a MOF classname to an alias name.
5856 // Aliases are introduced by command-line classname arguments of the
5857 // form <CLASSNAME>=<ALIAS>. For each command line argument of this
5858 // form, put an entry in the alias table. Use the lexographical case
5859 // for the class define in MOF (rather than defined on the command line).
5860 for (size_t i = 0; i < localClassNamesArg.size(); i++)
5861 {
5862 const char* className = localClassNamesArg[i].c_str();
5863 char* alias = (char*)strchr(className, '=');
5864
5865 if (alias)
5866 {
5867 *alias++ = '\0';
5868
5869 const MI_ClassDecl* cd = parser.findClassDecl(className);
5870
5871 mike 1.1 if (!cd)
5872 err(ID_UNKNOWN_CLASS, "unknown class: %s", className);
5873
5874 aliases[cd->name] = alias;
5875 }
5876 }
5877
5878 // Form a complete list of class names (excluding duplicates).
5879
5880 vector<string> classNames;
5881
5882 if (s_options.all)
5883 {
5884 parser.getClassNames(classNames);
5885 }
5886 else
5887 {
5888 for (size_t i = 0; i < localClassNamesArg.size(); i++)
5889 {
5890 const char* className = localClassNamesArg[i].c_str();
5891 const MI_ClassDecl* cd = parser.findClassDecl(className);
5892 mike 1.1
5893 if (!cd)
5894 err(ID_UNKNOWN_CLASS, "unknown, class: %s", className);
5895
5896 // Save class name.
5897 if (!Contains(classNames, cd->name))
5898 classNames.push_back(cd->name);
5899
5900 // Reject classes that are abstract.
5901 if (cd->flags & MI_FLAG_ABSTRACT)
5902 {
5903 err(ID_REFUSED_TO_GENERATE_PROVIDER_FOR_ABSTRACT_CLASS,
5904 "refused to generated provider for abstract class: %s",
5905 cd->name);
5906 }
5907 }
5908 }
5909
5910 // Form the set of classes for which there are providers (partial
5911 // generation is performed on dependent classes (for which there is
5912 // no actual provider).
5913 mike 1.1
5914 if (!s_options.noProviders)
5915 {
5916 for (size_t i = 0; i < classNames.size(); i++)
5917 {
5918 providerClasses.insert(classNames[i]);
5919 }
5920 }
5921
5922 // Add extra classes (given by -e option) to class list to be generated.
5923
5924 for (size_t i = 0; i < s_options.extraClasses.size(); i++)
5925 {
5926 const MI_ClassDecl* cd = parser.findClassDecl(
5927 s_options.extraClasses[i].c_str());
5928
5929 if (!cd)
5930 {
5931 err(ID_UNKNOWN_CLASS, "unknown class: %s",
5932 s_options.extraClasses[i].c_str());
5933 }
5934 mike 1.1
5935 classNames.push_back(cd->name);
5936 }
5937
5938 // Generate the classes.
5939
5940 set<string> classIdentifiers;
5941
5942 for (size_t i = 0; i < classNames.size(); i++)
5943 {
5944 const char* cn = classNames[i].c_str();
5945 const MI_ClassDecl* cd = parser.findClassDecl(cn);
5946
5947 if (!cd)
5948 err(ID_UNKNOWN_CLASS, "unknown class: %s", cn);
5949
5950 GenClassHeader(parser, cd, classIdentifiers);
5951
5952 if (providerClasses.find(cd->name) != providerClasses.end())
5953 {
5954 if (s_options.cpp)
5955 mike 1.1 GenCppClassSource(cd);
5956 else
5957 GenClassSource(cd);
5958 }
5959 }
5960
5961 // Generate the schema.c file.
5962 GenSchemaSourceFile(parser, classNames, classIdentifiers);
5963
5964 // generate c++ wrappers - stubs.cpp file
5965 if (!s_options.noProviders && s_options.cpp)
5966 GenModuleStubsFile(parser, classNames);
5967
5968 // Generate the module.h and module.c files.
5969 if (!s_options.noProviders)
5970 {
5971 if (s_options.cpp)
5972 {
5973 GenModuleCppSourceFile();
5974 GenModuleCppHeaderFile();
5975 }
5976 mike 1.1 else
5977 GenModuleSourceFile();
5978 }
5979
5980 // Generate the strings.rc.
5981 if (s_options.localize)
5982 GenerateStringsFile();
5983
5984 // Generate provider registry file.
5985 if (!s_options.providerRegistryPath.empty())
5986 GenerateRegistryFile(parser, classNames);
5987
5988 if ( s_options.quiet )
5989 {
5990 fclose( s_stdout );
5991 s_stdout = 0;
5992 }
5993
5994 // Generate the GNUmakefile.
5995 if (s_options.providerName.size())
5996 GenMakefile(s_options.providerName, classNamesArg, s_options.cmdLine);
5997 mike 1.1
5998 return 0;
5999 }
|