(file) Return to gen.cpp CVS log (file) (dir) Up to [OMI] / omi / gen

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

ViewCVS 0.9.2