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