(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                   "};\n";
4548           
4549               string r = T;
4550               r = sub(r, "<ALIAS>", alias);
4551               r = subx(r, "<CODE>", HashCode(cd->name));
4552               r = sub(r, "<CLASS>", cd->name);
4553               r = sub(r, "<FLAGS>", MakeFlags(cd->flags));
4554           
4555               if (s_options.schema.size())
4556                   r = sub(r, "<SCHEMA>", s_options.schema.c_str());
4557               else
4558 mike  1.1         r = sub(r, "<SCHEMA>", "schemaDecl");
4559           
4560               if (s_options.cpp || !s_options.noProviders)
4561                   r = sub(r, "<STATIC>", "");
4562               else
4563                   r = sub(r, "<STATIC>", "static ");
4564           
4565               if (cd->numProperties)
4566               {
4567                   string s = alias + "_props";
4568                   r = sub(r, "<PROPS>", s);
4569                   r = sub(r, "<NPROPS>", "MI_COUNT(" + s + ")");
4570               }
4571               else
4572               {
4573                   r = sub(r, "<PROPS>", "NULL");
4574                   r = sub(r, "<NPROPS>", "0");
4575               }
4576           
4577               if (numQualifiers)
4578               {
4579 mike  1.1         string s = alias + "_quals";
4580                   r = sub(r, "<QUALS>", s);
4581                   r = sub(r, "<NQUALS>", "MI_COUNT(" + s + ")");
4582               }
4583               else
4584               {
4585                   r = sub(r, "<QUALS>", "NULL");
4586                   r = sub(r, "<NQUALS>", "0");
4587               }
4588           
4589               if (cd->superClass)
4590               {
4591                   r = sub(r, "<SUPER>", Quote(cd->superClass));
4592                   string t = "&" + AliasOf(cd->superClass) + "_rtti";
4593                   r = sub(r, "<SUPERCLASSDECL>", t);
4594               }
4595               else
4596               {
4597                   r = sub(r, "<SUPER>", "NULL");
4598                   r = sub(r, "<SUPERCLASSDECL>", "NULL");
4599               }
4600 mike  1.1 
4601               if (cd->numMethods)
4602               {
4603                   const char T2[] =
4604                       "    <ALIAS>_meths, /* methods */\n"
4605                       "    MI_COUNT(<ALIAS>_meths), /* numMethods */\n";
4606                   string t2 = sub(T2, "<ALIAS>", alias);
4607                   r = sub(r, "<METHODS>", t2);
4608               }
4609               else
4610               {
4611                   const char T2[] =
4612                       "    NULL, /* methods */\n"
4613                       "    0, /* numMethods */\n";
4614                   r = sub(r, "<METHODS>", T2);
4615               }
4616           
4617               if (providerClasses.find(cd->name) == providerClasses.end())
4618               {
4619                   r = sub(r, "<FUNCS>", "NULL");
4620               }
4621 mike  1.1     else
4622               {
4623                   r = sub(r, "<FUNCS>", "&" + alias + "_funcs");
4624               }
4625           
4626               puts(os, r);
4627               nl(os);
4628           }
4629           
4630           //==============================================================================
4631           //
4632           // GenQualifierDecl()
4633           //
4634           //     This function generates a single qualifier declaration.
4635           //
4636           //==============================================================================
4637           
4638           static void GenQualifierDecl(FILE* os, const MI_QualifierDecl* qd)
4639           {
4640               const char T[] =
4641                   "static MI_CONST MI_QualifierDecl <NAME>_qual_decl =\n"
4642 mike  1.1         "{\n"
4643                   "    MI_T(\"<NAME>\"), /* name */\n"
4644                   "    <TYPE>, /* type */\n"
4645                   "    <SCOPE>, /* scope */\n"
4646                   "    <FLAVOR>, /* flavor */\n"
4647                   "    <SUBSCRIPT>, /* subscript */\n"
4648                   "    <VALUE>, /* value */\n"
4649                   "};\n"
4650                   "\n";
4651           
4652               string stem = string(qd->name) + "_qual_decl";
4653           
4654               // Generate the value.
4655               if (qd->value)
4656               {
4657                   if (qd->flavor & MI_FLAG_TRANSLATABLE)
4658                       GenValue(os, stem, qd->type, qd->value, true);
4659                   else
4660                       GenValue(os, stem, qd->type, qd->value, false);
4661               }
4662           
4663 mike  1.1     string r = T;
4664           
4665               r = sub(r, "<NAME>", qd->name);
4666               r = sub(r, "<TYPE>", MakeType(qd->type));
4667               r = subu(r, "<SUBSCRIPT>", qd->subscript);
4668               r = sub(r, "<FLAVOR>", MakeFlavor(qd->flavor));
4669               r = sub(r, "<SCOPE>", MakeScope(qd->scope));
4670           
4671               if (qd->value)
4672                   r = sub(r, "<VALUE>", "&" + stem + "_value");
4673               else
4674                   r = sub(r, "<VALUE>", "NULL");
4675           
4676               puts(os, r);
4677           }
4678           
4679           //==============================================================================
4680           //
4681           // GenQualifierDecls()
4682           //
4683           //     This function generates an array of qualifier declarations.
4684 mike  1.1 //
4685           //==============================================================================
4686           
4687           size_t GenQualifierDecls(Parser& parser, FILE* os)
4688           {
4689               size_t count = 0;
4690           
4691               /* Check if qualifiers are ignored */
4692               if (s_options.ignoreAllQualifiers)
4693                   return 0;
4694           
4695               // Put the comment box.
4696               PutCommentBox(os, "Qualifier declarations");
4697               nl(os);
4698           
4699               vector<string> names;
4700               parser.getQualifierDeclNames(names);
4701           
4702               // Generate the individual qualifier declarations.
4703               for (size_t i = 0; i < names.size(); i++)
4704               {
4705 mike  1.1         const MI_QualifierDecl* qd = parser.findQualifierDecl(names[i]);
4706           
4707                   if (!qd)
4708                   {
4709                       err(ID_UNKNOWN_QUALIFIER, "unknown qualifier: %s", 
4710                           names[i].c_str());
4711                   }
4712           
4713                   // Do not generate standard qualifiers.
4714                   if (!s_options.standardQualifiers && 
4715                       FindStandardQualifierDecl(qd->name))
4716                   {
4717                       continue;
4718                   }
4719           
4720                   GenQualifierDecl(os, qd);
4721                   count++;
4722               }
4723           
4724               // Generate the qualifier declaration array.
4725               if (count)
4726 mike  1.1     {
4727                   putl(os, 
4728                       "static MI_QualifierDecl MI_CONST* MI_CONST qualifierDecls[] =");
4729                   putl(os, "{");
4730           
4731                   for (size_t i = 0; i < names.size(); i++)
4732                   {
4733                       const MI_QualifierDecl* qd = parser.findQualifierDecl(names[i]);
4734           
4735                       // Do not generate standard qualifiers.
4736                       if (!s_options.standardQualifiers && 
4737                           FindStandardQualifierDecl(qd->name))
4738                       {
4739                           continue;
4740                       }
4741           
4742                       if (!qd)
4743                       {
4744                           err(ID_UNKNOWN_QUALIFIER, "unknown qualifier: %s", 
4745                               names[i].c_str());
4746                       }
4747 mike  1.1 
4748                       put(os, "    &%s_qual_decl,\n", qd->name);
4749                   }
4750           
4751                   putl(os, "};");
4752                   nl(os);
4753               }
4754           
4755               return count;
4756           }
4757           
4758           //==============================================================================
4759           //
4760           // GenClassSchema()
4761           //
4762           //     This function generates one class for the schema source file.
4763           //
4764           //==============================================================================
4765           
4766           static void GenClassSchema(
4767               Parser& parser,
4768 mike  1.1     FILE* os,
4769               const MI_ClassDecl* cd,
4770               const vector<string>& classNames)
4771           {
4772               // Prevent recursion.
4773               {
4774                   if (s_generated.find(cd->name) != s_generated.end())
4775                       return;
4776           
4777                   s_generated.insert(cd->name);
4778               }
4779           
4780               // Find direct dependencies of this class.
4781               vector<string> deps;
4782               FindDirectDependencies(cd, deps);
4783           
4784               // Recurse on dependencies.
4785               for (size_t i = 0; i < deps.size(); i++)
4786               {
4787                   const MI_ClassDecl* tcd = parser.findClassDecl(deps[i].c_str());
4788           
4789 mike  1.1         if (!tcd)
4790                       err(ID_UNKNOWN_CLASS, "unknown class: %s", deps[i].c_str());
4791           
4792                   GenClassSchema(parser, os, tcd, classNames);
4793               }
4794           
4795               // Refuse to generate same class more than once.
4796               if (generated_classes.find(cd->name) != generated_classes.end())
4797                   return;
4798           
4799               generated_classes.insert(cd->name);
4800           
4801               // Generate comment box for this class.
4802               const string al = AliasOf(cd->name);
4803               PutCommentBox(os, al);
4804               nl(os);
4805           
4806               // Generate declarations.
4807               GenPropertyDecls(parser, os, cd);
4808           
4809               // Generate method declarations.
4810 mike  1.1     GenMethodDecls(parser, os, cd);
4811           
4812               // Generate provider function table.
4813               if (providerClasses.find(cd->name) != providerClasses.end())
4814                   GenFunctionTable(os, cd);
4815           
4816               // Generate the class declaration.
4817               GenClassDecl(parser, os, cd);
4818           }
4819           
4820           //==============================================================================
4821           //
4822           // GenSchemaSourceFile()
4823           //
4824           //     This function generates the schema.c source file, which contains the
4825           //     qualifier declarations, class declarations, and the schema object that
4826           //     refers to arrays of each.
4827           //
4828           //==============================================================================
4829           
4830           static void GenSchemaSourceFile(
4831 mike  1.1     Parser& parser,
4832               const vector<string>& classNames,
4833               const set<string>& /*classIdentifiers*/)
4834           {
4835               // Open the file.
4836               string path = ExpandPath("schema.c");
4837           
4838               FILE* os = Fopen(path.c_str(), "w");
4839           
4840               if (!os)
4841                   err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
4842           
4843               GenStatikGenLine(os);
4844           
4845               Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
4846           
4847               // Print warning box.
4848               PutCommentBox(os, WARNING);
4849           
4850               // Include <MI.h> header.
4851               putl(os, "#include <ctype.h>");
4852 mike  1.1     putl(os, "#include <MI.h>");
4853           
4854               bool generateMatch = false;
4855           
4856               // Include each direct header file (headers will indirectly include others).
4857               for (size_t i = 0; i < classNames.size(); i++)
4858               {
4859                   // Find the class.
4860                   const MI_ClassDecl* cd = parser.findClassDecl(classNames[i].c_str());
4861           
4862                   if (!cd)
4863                       err(ID_UNKNOWN_CLASS, "unknown class: %s", classNames[i].c_str());
4864           
4865                   if (!s_options.association && (cd->flags & MI_FLAG_ASSOCIATION) &&
4866                       CanGenerateAssocRoles(cd))
4867                   {
4868                       generateMatch = true;
4869                   }
4870           
4871                   // Include the class header.
4872                   const string alias = AliasOf(cd->name);
4873 mike  1.1         putl(os, "#include \"%s.h\"", alias.c_str());
4874               }
4875           
4876               nl(os);
4877           
4878               // Generate forward reference to schema declaration.
4879               {
4880                   PutCommentBox(os, "Schema Declaration");
4881                   nl(os);
4882           
4883                   if (s_options.schema.size())
4884                       putl(os, "extern MI_SchemaDecl %s;", s_options.schema.c_str());
4885                   else
4886                       putl(os, "extern MI_SchemaDecl schemaDecl;");
4887           
4888                   nl(os);
4889               }
4890           
4891               // Generate match function (if necessary)
4892               if (generateMatch)
4893               {
4894 mike  1.1         const char MATCH[] =
4895                       "static int _Match(const MI_Char* p, const MI_Char* q)\n"
4896                       "{\n"
4897                       "    if (!p || !q || !p[0] || !q[0])\n"
4898                       "        return 1;\n"
4899                       "\n"
4900                       "    while (*p && *q)\n"
4901                       "        if (toupper((MI_Uint16)*p++) - toupper((MI_Uint16)*q++))\n"
4902                       "            return 0;\n"
4903                       "\n"
4904                       "    return *p == '\\0' && *q == '\\0';\n"
4905                       "}\n"
4906                       "\n";
4907           
4908                   PutCommentBox(os, "_Match()");
4909                   nl(os);
4910                   puts(os, MATCH);
4911               }
4912           
4913               // Gen qualifier declarations.
4914               size_t numQualifierDecls = GenQualifierDecls(parser, os);
4915 mike  1.1 
4916               // Generate class declarations.
4917               for (size_t i = 0; i < classNames.size(); i++)
4918               {
4919                   // Find the class.
4920                   const MI_ClassDecl* cd = parser.findClassDecl(classNames[i].c_str());
4921           
4922                   if (!cd)
4923                       err(ID_UNKNOWN_CLASS, "unknown class: %s", classNames[i].c_str());
4924           
4925                   GenClassSchema(parser, os, cd, classNames);
4926               }
4927           
4928               // Generate server declaration.
4929               PutCommentBox(os, "__mi_server");
4930               nl(os);
4931               putl(os, "MI_Server* __mi_server;");
4932           
4933               // Generate MI_SchemaDecl.
4934           
4935               PutCommentBox(os, "Schema");
4936 mike  1.1     nl(os);
4937           
4938               putl(os, "static MI_ClassDecl MI_CONST* MI_CONST classes[] =");
4939               putl(os, "{");
4940           
4941               set<string>::const_iterator p = generated_classes.begin();
4942               set<string>::const_iterator end = generated_classes.end();
4943           
4944               for (; p != end; p++)
4945               {
4946                   // Find the class.
4947                   const MI_ClassDecl* cd = 
4948                       parser.findClassDecl((*p).c_str());
4949           
4950                   if (!cd)
4951                       err(ID_UNKNOWN_CLASS, "unknown class: %s", (*p).c_str());
4952           
4953                   const string alias = AliasOf(cd->name);
4954                   putl(os, "    &%s_rtti,", alias.c_str());
4955               }
4956           
4957 mike  1.1     putl(os, "};");
4958               nl(os);
4959           
4960               {
4961                   static const char T[] =
4962                       "MI_SchemaDecl <SCHEMADECL> =\n"
4963                       "{\n"
4964                       "    <QUALIFIERDECLS>, /* qualifierDecls */\n"
4965                       "    <NUMQUALIFIERDECLS>, /* numQualifierDecls */\n"
4966                       "    classes, /* classDecls */\n"
4967                       "    MI_COUNT(classes), /* classDecls */\n"
4968                       "};\n"
4969                       "\n";
4970           
4971                   string r = T;
4972           
4973                   if (s_options.schema.size())
4974                       r = sub(r, "<SCHEMADECL>", s_options.schema);
4975                   else
4976                       r = sub(r, "<SCHEMADECL>", "schemaDecl");
4977           
4978 mike  1.1         if (numQualifierDecls)
4979                   {
4980                       r = sub(r, "<QUALIFIERDECLS>", "qualifierDecls");
4981                       r = sub(r, "<NUMQUALIFIERDECLS>", "MI_COUNT(qualifierDecls)");
4982                   }
4983                   else
4984                   {
4985                       r = sub(r, "<QUALIFIERDECLS>", "NULL");
4986                       r = sub(r, "<NUMQUALIFIERDECLS>", "0");
4987                   }
4988           
4989                   puts(os, r);
4990               }
4991           
4992               // Generate MI_Server methods.
4993               {
4994                   const char T[] =
4995                       "MI_Result MI_CALL MI_Server_GetVersion(\n"
4996                       "    MI_Uint32* version)"
4997                       "{\n"
4998                       "    return __mi_server->serverFT->GetVersion(version);\n"
4999 mike  1.1             "}\n"
5000                       "\n"
5001                       "MI_Result MI_CALL MI_Server_GetSystemName(\n"
5002                       "    const MI_Char** systemName)\n"
5003                       "{\n"
5004                       "    return __mi_server->serverFT->GetSystemName(systemName);\n"
5005                       "}\n";
5006           
5007                   PutCommentBox(os, "MI_Server Methods");
5008                   nl(os);
5009                   puts(os, T);
5010                   nl(os);
5011               }
5012           
5013           #if 0
5014               // Generate cross-check with class identifiers:
5015               {
5016                   set<string>::const_iterator first = classIdentifiers.begin();
5017                   set<string>::const_iterator last = classIdentifiers.end();
5018           
5019                   while (first != last)
5020 mike  1.1         {
5021                       const string& s = *first++;
5022                       putl(os, "#ifndef %s", s.c_str());
5023                       putl(os, "# error \"generational inconsistency: %s is undefined\"", 
5024                           s.c_str());
5025                       putl(os, "#endif\n");
5026                   }
5027               }
5028           #endif
5029           
5030               // Close the file.
5031               fclose(os);
5032           }
5033           
5034           //==============================================================================
5035           //
5036           // GenerateMI_Main()
5037           //
5038           //     This function generates the MI_Main() entry point. It returns a 
5039           //     string instead of writing to the output stream directory. This is to
5040           //     support patching of module.c.
5041 mike  1.1 //
5042           //==============================================================================
5043           
5044           string GenerateMI_Main()
5045           {
5046               string result;
5047           
5048               // MI_Main() preamble:
5049               {
5050                   string r = MODULE_C_TEMPLATE_2;
5051           
5052                   if (s_options.schema.size()) 
5053                       r = sub(r, "<SCHEMADECL>", s_options.schema);
5054                   else
5055                       r = sub(r, "<SCHEMADECL>", "schemaDecl");
5056           
5057                   if (s_options.entryPoint.size()) 
5058                       r = sub(r, "<ENTRYPOINT>", s_options.entryPoint);
5059                   else
5060                       r = sub(r, "<ENTRYPOINT>", "MI_Main");
5061           
5062 mike  1.1         result += r;
5063               }
5064           
5065               // MI_Main() flags:
5066               {
5067                   string r;
5068           
5069                   if (!s_options.ignoreAllQualifiers)
5070                   {
5071                       if (!s_options.standardQualifiers)
5072                           r += "    module.flags |= MI_MODULE_FLAG_STANDARD_QUALIFIERS;\n";
5073           
5074                       if (s_options.descriptions)
5075                           r += "    module.flags |= MI_MODULE_FLAG_DESCRIPTIONS;\n";
5076           
5077                       if (s_options.values)
5078                           r += "    module.flags |= MI_MODULE_FLAG_VALUES;\n";
5079           
5080                       if (s_options.mappingStrings)
5081                           r += "    module.flags |= MI_MODULE_FLAG_MAPPING_STRINGS;\n";
5082           
5083 mike  1.1             if (s_options.booleanQualifiers)
5084                           r += "    module.flags |= MI_MODULE_FLAG_BOOLEANS;\n";
5085                   }
5086           
5087                   if (s_options.cpp)
5088                       r += "    module.flags |= MI_MODULE_FLAG_CPLUSPLUS;\n";
5089           
5090                   if (s_options.localize)
5091                       r += "    module.flags |= MI_MODULE_FLAG_LOCALIZED;\n";
5092           
5093                   if (s_options.filterSupport)
5094                       r += "    module.flags |= MI_MODULE_FLAG_FILTER_SUPPORT;\n";
5095           
5096                   result += r;
5097               }
5098           
5099               // MI_Main() postamble:
5100               {
5101                   string r = MODULE_C_TEMPLATE_3;
5102           
5103                   if (s_options.schema.size()) 
5104 mike  1.1             r = sub(r, "<SCHEMADECL>", s_options.schema);
5105                   else
5106                       r = sub(r, "<SCHEMADECL>", "schemaDecl");
5107           
5108                   {
5109                       char buf[64];
5110                       Snprintf(buf, MI_COUNT(buf), "MI_MAKE_VERSION(%u,%u,%u)", 
5111                           MI_MAJOR, MI_MINOR, MI_REVISON);
5112                       r = sub(r, "<VERSION>", buf);
5113                   }
5114           
5115                   result += r;
5116               }
5117           
5118               return result;
5119           }
5120           
5121           //==============================================================================
5122           //
5123           // SkipSpace()
5124           //
5125 mike  1.1 //     Skip over whitespace. Return true when the '\0' character is found.
5126           //
5127           //==============================================================================
5128           
5129           static bool SkipSpace(const char*& p)
5130           {
5131               while (isspace((unsigned char)*p))
5132                   p++;
5133           
5134               return *p == '\0';
5135           }
5136           
5137           //==============================================================================
5138           //
5139           // GenModuleSourceFile()
5140           //
5141           //     This function generates the module.c source file, which contains the
5142           //     MI_Main() entry point.
5143           //
5144           //==============================================================================
5145           
5146 mike  1.1 static void GenModuleSourceFile()
5147           {
5148               // Open the file.
5149               const string path = ExpandPath("module.c");
5150           
5151               if (Exists(path.c_str()))
5152               {
5153                   // Read file into memory.
5154                   vector<char> data;
5155           
5156                   if (!Inhale(path.c_str(), data))
5157                   {
5158                       err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", 
5159                           path.c_str());
5160                   }
5161           
5162           
5163                   // Replace MI_Main() body with new MI_Main() body.
5164                   const char* start = &data[0];
5165                   const char* end = &data[data.size()-1];
5166                   const char* p = start;
5167 mike  1.1         bool found = false;
5168           
5169                   // Match "MI_EXTERN_C MI_EXPORT MI_Module* MI_MAIN_CALL MI_Main(...) {}
5170                   while (p != end)
5171                   {
5172                       const char* first = p;
5173           
5174                       // Expect 'MI_EXTERN_C' [optionally]
5175                       if (strncmp(p, "MI_EXTERN_C", 11) == 0)
5176                       {
5177                           p += 11;
5178           
5179                           // Skip whitespace:
5180                           if (SkipSpace(p))
5181                               break;
5182                       }
5183           
5184                       // Expect 'MI_EXPORT'
5185                       if (strncmp(p, "MI_EXPORT", 9) != 0)
5186                       {
5187                           p++;
5188 mike  1.1                 continue;
5189                       }
5190                       p += 9;
5191           
5192                       // Skip whitespace:
5193                       if (SkipSpace(p))
5194                           break;
5195           
5196                       // Expect 'MI_Module'
5197                       if (strncmp(p, "MI_Module", 9) != 0)
5198                       {
5199                           p++;
5200                           continue;
5201                       }
5202                       p += 9;
5203           
5204                       // Skip whitespace:
5205                       if (SkipSpace(p))
5206                           break;
5207           
5208                       // Expect '*'
5209 mike  1.1             if (*p != '*')
5210                       {
5211                           p++;
5212                           continue;
5213                       }
5214                       p++;
5215           
5216                       // Skip whitespace:
5217                       if (SkipSpace(p))
5218                           break;
5219           
5220                       // Skip 'MI_MAIN_CALL'
5221                       {
5222                           const char TMP[] = "MI_MAIN_CALL";
5223           
5224                           if (strncmp(p, TMP, sizeof(TMP)-1) == 0)
5225                               p += sizeof(TMP)-1;
5226                       }
5227           
5228                       // Skip whitespace:
5229                       if (SkipSpace(p))
5230 mike  1.1                 break;
5231           
5232                       // Expect 'MI_Main'
5233                       {
5234                           const char *TMP = 
5235                               (s_options.entryPoint.empty() ? "MI_Main" : s_options.entryPoint.c_str());
5236           
5237                           if (strncmp(p, TMP, strlen(TMP)) != 0)
5238                           {
5239                               p++;
5240                               continue;
5241                           }
5242                           p += strlen(TMP);
5243                       }
5244           
5245                       // Skip whitespace:
5246                       if (SkipSpace(p))
5247                           break;
5248           
5249                       // Expect '('
5250                       if (*p != '(')
5251 mike  1.1             {
5252                           p++;
5253                           continue;
5254                       }
5255           
5256                       // Skip non ')' chars.
5257                       while (*p && *p != ')')
5258                           p++;
5259           
5260                       // Expect ')'
5261                       if (*p != ')')
5262                       {
5263                           p++;
5264                           continue;
5265                       }
5266                       p++;
5267           
5268                       // Skip whitespace:
5269                       if (SkipSpace(p))
5270                           break;
5271           
5272 mike  1.1             // Expect '{'
5273                       if (*p != '{')
5274                       {
5275                           p++;
5276                           continue;
5277                       }
5278           
5279                       // Skip non '}' chars.
5280                       while (*p && *p != '}')
5281                           p++;
5282           
5283                       // Expect '}'
5284                       if (*p != '}')
5285                       {
5286                           p++;
5287                           continue;
5288                       }
5289                       p++;
5290           
5291                       const char* last = p;
5292           
5293 mike  1.1             found = true;
5294                       string tmp = &data[0];
5295                       string r;
5296                       r.append(start, first - start);
5297                       r.append(GenerateMI_Main());
5298                       r.append(last);
5299           
5300                       // Rewrite the file.
5301                       {
5302                           FILE* os = Fopen(path.c_str(), "w");
5303           
5304                           if (!os)
5305                           {
5306                               err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", 
5307                                   path.c_str());
5308                           }
5309           
5310                           Fprintf(s_stdout, ID_PATCHING, "Patching %s\n", path.c_str());
5311                           put(os, "%s", r.c_str());
5312           
5313                           fclose(os);
5314 mike  1.1             }
5315                       break;
5316                   }
5317           
5318                   // If MI_Main() not found.
5319                   if (!found)
5320                   {
5321                       err(ID_FAILED_TO_PATCH_MODULE, 
5322                           "Unable to patch module.c: cannot find %s() body: %s",
5323                           (s_options.entryPoint.empty() ? 
5324                               "MI_Main" : s_options.entryPoint.c_str()),
5325                           path.c_str());
5326                   }
5327           
5328                   return;
5329               }
5330           
5331               FILE* os = Fopen(path.c_str(), "w");
5332               
5333               if (!os)
5334                   err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
5335 mike  1.1 
5336               GenStatikGenLine(os);
5337               Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
5338           
5339               // Generate part 1:
5340               {
5341                   string r = MODULE_C_TEMPLATE_1;
5342           
5343                   if (s_options.schema.size()) 
5344                       r = sub(r, "<SCHEMADECL>", s_options.schema);
5345                   else
5346                       r = sub(r, "<SCHEMADECL>", "schemaDecl");
5347           
5348                   put(os, "%s", r.c_str());
5349               }
5350           
5351               // Generate MI_Main()
5352               {
5353                   string r = GenerateMI_Main();
5354                   put(os, "%s\n", r.c_str());
5355               }
5356 mike  1.1 
5357               // Close the file.
5358               fclose(os);
5359           }
5360           
5361           //==============================================================================
5362           //
5363           // GenModuleCppSourceFile()
5364           //
5365           //     This function generates the module.cpp source file, which contains the
5366           //     Module class definiiton.
5367           //
5368           //==============================================================================
5369           
5370           static void GenModuleCppSourceFile()
5371           {
5372               // Open the file.
5373               const string path = ExpandPath("module.cpp");
5374           
5375               if (Exists(path.c_str()))
5376               {
5377 mike  1.1         Fprintf(s_stdout, ID_SKIPPING, "Skipping %s\n", path.c_str());
5378                   return;
5379               }
5380           
5381               FILE* os = Fopen(path.c_str(), "w");
5382               
5383               if (!os)
5384                   err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
5385           
5386               Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
5387           
5388               // simple template - no parameters
5389               {
5390                   put(os, "%s\n", MODULE_CPP_TEMPLATE);
5391               }
5392           
5393               // Close the file.
5394               fclose(os);
5395           }
5396           
5397           //==============================================================================
5398 mike  1.1 //
5399           // GenModuleCppHeaderFile()
5400           //
5401           //     This function generates the module.h header file, which contains the
5402           //     Module class declaration.
5403           //
5404           //==============================================================================
5405           
5406           static void GenModuleCppHeaderFile()
5407           {
5408               // Open the file.
5409               const string path = ExpandPath("module.h");
5410           
5411               if (Exists(path.c_str()))
5412               {
5413                   Fprintf(s_stdout, ID_SKIPPING, "Skipping %s\n", path.c_str());
5414                   return;
5415               }
5416           
5417               FILE* os = Fopen(path.c_str(), "w");
5418               
5419 mike  1.1     if (!os)
5420                   err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
5421           
5422               Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
5423           
5424               // simple template - no parameters
5425               {
5426                   put(os, "%s\n", MODULE_H_TEMPLATE);
5427               }
5428           
5429               // Close the file.
5430               fclose(os);
5431           }
5432           
5433           //==============================================================================
5434           //
5435           // GenModuleStubsFile()
5436           //
5437           //     This function generates the stubs.cpp source file, which contains the
5438           //     wrapper functions to convert 'c' style server calls into provider class 
5439           //     calls
5440 mike  1.1 //
5441           //==============================================================================
5442           
5443           static void GenModuleStubsFile(
5444               Parser& parser,
5445               const vector<string>& classNames)
5446           {
5447               // Open the file.
5448               string path = ExpandPath("stubs.cpp");
5449           
5450               FILE* os = Fopen(path.c_str(), "w");
5451           
5452               if (!os)
5453                   err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
5454           
5455               GenStatikGenLine(os);
5456           
5457               Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
5458           
5459               // Print warning box.
5460               PutCommentBox(os, WARNING);
5461 mike  1.1 
5462               // Include <MI.h> header.
5463               putl(os, "#include <MI.h>");
5464               putl(os, "#include \"module.h\"");
5465           
5466               // Include each direct header file (headers will indirectly include others).
5467               for (size_t i = 0; i < classNames.size(); i++)
5468               {
5469                   // Find the class.
5470                   const MI_ClassDecl* cd = parser.findClassDecl(classNames[i].c_str());
5471           
5472                   if (!cd)
5473                       err(ID_UNKNOWN_CLASS, "unknown class: %s", classNames[i].c_str());
5474           
5475                   /* skip not-requested classes */
5476                   if (providerClasses.find(cd->name) == providerClasses.end())
5477                       continue;
5478           
5479                   // Include the class header.
5480                   const string alias = AliasOf(cd->name);
5481                   putl(os, "#include \"%s_Class_Provider.h\"", alias.c_str());
5482 mike  1.1     }
5483           
5484               nl(os);
5485               putl(os, "using namespace mi;");
5486               nl(os);
5487           
5488               // generate c++ wrappers
5489               for (size_t i = 0; i < classNames.size(); i++)
5490               {
5491                   // Find the class.
5492                   const MI_ClassDecl* cd = parser.findClassDecl(classNames[i].c_str());
5493           
5494                   if (!cd)
5495                       err(ID_UNKNOWN_CLASS, "unknown class: %s", classNames[i].c_str());
5496           
5497                   /* skip not-requested classes */
5498                   if (providerClasses.find(cd->name) == providerClasses.end())
5499                       continue;
5500           
5501                   // generate stub for the class
5502                   GenerateClassStub( os, cd );
5503 mike  1.1     }
5504           
5505               // Generate module-level load/unload
5506               {
5507                   string r = STUBS_LOAD_UNLOAD_TEMPLATE;
5508           
5509                   if (s_options.schema.size()) 
5510                       r = sub(r, "<SCHEMADECL>", s_options.schema);
5511                   else
5512                       r = sub(r, "<SCHEMADECL>", "schemaDecl");
5513           
5514                   put(os, "%s", r.c_str());
5515               }
5516           
5517               // Generate MI_Main()
5518               {
5519                   string r = GenerateMI_Main();
5520                   put(os, "%s\n", r.c_str());
5521               }
5522           
5523               nl(os);
5524 mike  1.1 
5525               // Close the file.
5526               fclose(os);
5527           }
5528           
5529           //==============================================================================
5530           //
5531           // GenerateStringsFile()
5532           //
5533           //     This function generates the string.rc file, which contains the
5534           //     localized qualifier strings (only called if -l option present)
5535           //
5536           //==============================================================================
5537           
5538           static void GenerateStringsFile()
5539           {
5540               // Open the file.
5541               const string path = ExpandPath("strings.rc");
5542               FILE* os = Fopen(path.c_str(), "w");
5543               
5544               if (!os)
5545 mike  1.1         err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
5546           
5547               GenStatikGenLine(os);
5548               Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
5549           
5550               // Generate file with the following format.
5551               //
5552               //     STRINGTABLE
5553               //     {
5554               //         <INTEGER-IDENTIFIER>, <STRING>
5555               //     }
5556               {
5557                   fprintf(os, "STRINGTABLE\n");
5558                   fprintf(os, "{\n");
5559           
5560                   for (size_t i = 0; i < s_localizations.size(); i++)
5561                   {
5562                       MI_Uint32 id = (MI_Uint32)(i + 1);
5563                       const string& str = s_localizations[i];
5564                       fprintf(os, "    %u, \"%s\"\n", id, str.c_str());
5565                   }
5566 mike  1.1 
5567                   fprintf(os, "}\n");
5568               }
5569           
5570               // Close the file.
5571               fclose(os);
5572           }
5573           
5574           static string _GetClassInheritanceRegistrationEntry(
5575               const MI_ClassDecl* cd
5576               )
5577           {
5578               string res = cd->name;
5579           
5580               while (cd->superClassDecl)
5581               {
5582                   res += ",";
5583                   cd = cd->superClassDecl;
5584                   res += cd->name;
5585               }
5586           
5587 mike  1.1     return res;
5588           }
5589           
5590           static string _GetClassRegistrationEntry(
5591               Parser& parser,
5592               const MI_ClassDecl* cd
5593               )
5594           {
5595               string res;
5596           
5597               if (cd->flags & MI_FLAG_ASSOCIATION)
5598               {
5599                   const MI_ClassDecl* cd_left = 0, *cd_right = 0;
5600                   // find two ref members
5601                   for (MI_Uint32 i = 0; i < cd->numProperties; i++)
5602                   {
5603                       if (cd->properties[i]->type == MI_REFERENCE)
5604                       {
5605                           const MI_ClassDecl* cd_ref = 
5606                               parser.findClassDecl(cd->properties[i]->className);
5607           
5608 mike  1.1                 if (!cd_ref)
5609                           {
5610                               err(ID_UNKNOWN_CLASS, "unknown class: %s", 
5611                                   cd->properties[i]->className);
5612                           }
5613           
5614                           if (!cd_left)
5615                               cd_left = cd_ref;
5616                           else
5617                               cd_right = cd_ref;
5618                       }
5619                   }
5620           
5621                   if (!cd_right)
5622                   {
5623                       err(ID_INSUFFICIENT_REFERENCES, "insufficient references: "
5624                           "class must have 2 or more: %s", cd->name);
5625                   }
5626           
5627                   res = _GetClassInheritanceRegistrationEntry(cd_left) +
5628                       "+" +
5629 mike  1.1             _GetClassInheritanceRegistrationEntry(cd) + 
5630                       "+" +
5631                       _GetClassInheritanceRegistrationEntry(cd_right);
5632               }
5633               else
5634               {
5635                   res = _GetClassInheritanceRegistrationEntry(cd);
5636               }
5637               return res;
5638           }
5639           
5640           //==============================================================================
5641           //
5642           // GenerateRegistryFile()
5643           //
5644           //     This function generates skeleton of the provider registry file, 
5645           //     which contains information server will use to operate with provider 
5646           //     (only called if -reg option present)
5647           //
5648           //==============================================================================
5649           
5650 mike  1.1 static void GenerateRegistryFile( 
5651               Parser& parser, 
5652               const vector<string>& classNames)
5653           {
5654               // Open the file.
5655               const string path = ExpandPath(s_options.providerRegistryPath);
5656               FILE* os = Fopen(path.c_str(), "a");
5657               
5658               if (!os)
5659                   err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", path.c_str());
5660           
5661               Fprintf(s_stdout, ID_CREATING, "Creating %s\n", path.c_str());
5662           
5663               // Generate file with the following format.
5664               //
5665               //     statik:test/c:MSFT_Person,MSFT_Animal,MSFT_Base + MSFT_Friends + 
5666               //     MSFT_Person,MSFT_Animal,MSFT_Base:PersonProvider
5667               //
5668               {
5669                   fprintf(os, "# auto-generated skeleton of registry file\n");
5670                   fprintf(os, "# please update it with correct namespace[s]\n");
5671 mike  1.1 
5672                   for (size_t i = 0; i < classNames.size(); i++)
5673                   {
5674                       const char* cn = classNames[i].c_str();
5675                       const MI_ClassDecl* cd = parser.findClassDecl(cn);
5676           
5677                       if (!cd)
5678                           err(ID_UNKNOWN_CLASS, "unknown class: %s", cn);
5679           
5680                       fprintf(os, "statik:<ns>:%s:<provider>\n",
5681                           _GetClassRegistrationEntry(parser,cd).c_str());
5682           
5683                   }
5684           
5685                   for (size_t i = 0; i < s_localizations.size(); i++)
5686                   {
5687                       MI_Uint32 id = (MI_Uint32)(i + 1);
5688                       const string& str = s_localizations[i];
5689                       fprintf(os, "    %u, \"%s\"\n", id, str.c_str());
5690                   }
5691           
5692 mike  1.1         fprintf(os, "\n");
5693               }
5694           
5695               // Close the file.
5696               fclose(os);
5697           }
5698           
5699           //==============================================================================
5700           //
5701           // GenMakefile()
5702           //
5703           //     This function generates a 'GNUmakefile' for the given provider.
5704           //
5705           //==============================================================================
5706           
5707           static void GenMakefile(
5708               const string& library,
5709               const vector<string>& classNames,
5710               const string& cmdLine)
5711           {
5712               const char MAKEFILE[] = "GNUmakefile";
5713 mike  1.1 
5714               MI_UNUSED(library);
5715           
5716               // If makefile already exists, quit:
5717               if (Exists(MAKEFILE))
5718               {
5719                   Fprintf(s_stdout, ID_SKIPPING, "Skipping %s\n", MAKEFILE);
5720                   return;
5721               }
5722           
5723               // Open Makefile:
5724               FILE* os = Fopen(MAKEFILE, "w");
5725               if (!os)
5726                   err(ID_FAILED_TO_OPEN_FILE, "failed to open file: %s", MAKEFILE);
5727           
5728               {
5729                   // 'OMIMAK' variable.
5730                   string OMIMAK = string(GetPath(ID_DATADIR)) + "/omi.mak";
5731           
5732                   // 'PROVIDER' variable.
5733                   string PROVIDER = s_options.providerName;
5734 mike  1.1 
5735                   // 'SOURCES' variable.
5736                   string SOURCES;
5737                   {
5738                       if (s_options.cpp)
5739                           SOURCES = "$(wildcard *.c *.cpp)";
5740                       else
5741                           SOURCES = "$(wildcard *.c)";
5742                   }
5743           
5744                   // 'CLASSNAMES' variable.
5745                   string CLASSES;
5746                   {
5747                       for (size_t i = 0; i < classNames.size(); i++)
5748                       {
5749                           CLASSES += classNames[i];
5750                           if (i + 1 == classNames.size())
5751                               CLASSES += ' ';
5752                       }
5753                   }
5754           
5755 mike  1.1         string r;
5756           
5757                   if (s_options.cpp)
5758                       r = CXXMAKEFILE_TEMPLATE;
5759                   else
5760                       r = CMAKEFILE_TEMPLATE;
5761           
5762                   r = sub(r, "<OMIMAK>", OMIMAK);
5763                   r = sub(r, "<PROVIDER>", PROVIDER);
5764                   r = sub(r, "<SOURCES>", SOURCES);
5765                   r = sub(r, "<CLASSES>", CLASSES);
5766                   r = sub(r, "<CMDLINE>", cmdLine);
5767                   puts(os, r);
5768               }
5769           
5770               // Print creation message:
5771               Fprintf(s_stdout, ID_CREATING, "Creating %s\n", MAKEFILE);
5772           
5773               // Close file:
5774               fclose(os);
5775           }
5776 mike  1.1 //==============================================================================
5777           //
5778           // main()
5779           //
5780           //     This program generates source code from MOF definitions. The source 
5781           //     includes run-time type information for class declarations and qualifier
5782           //     declarations as well as class provider stubs.
5783           //
5784           //==============================================================================
5785           
5786           int GeneratorMain(
5787               const std::string& programNameArg,
5788               const std::vector<std::string>& mofFilesArg,
5789               const std::vector<std::string>& classNamesArg,
5790               const GeneratorOptions& optionsArg)
5791           {
5792               arg0 = programNameArg.c_str();
5793           
5794               // Make a copy of the vector whose strings we can later modify in place.
5795               vector<string> localClassNamesArg;
5796               {
5797 mike  1.1         for (size_t i = 0; i < classNamesArg.size(); i++)
5798                       localClassNamesArg.push_back(classNamesArg[i].c_str());
5799               }
5800           
5801               // WIndows trick to get compatible float format
5802           #ifdef WIN32
5803               _set_output_format(_TWO_DIGIT_EXPONENT);
5804           #endif
5805           
5806               // clear global params 
5807               generated_headers.clear();
5808               generated_classes.clear();
5809               providerClasses.clear();
5810               s_generated.clear();
5811               aliases.clear();
5812               s_localizations.clear();
5813           
5814               // Save command-line options.
5815               s_options = optionsArg;
5816           
5817               // Create directory given by -d option.
5818 mike  1.1     if (s_options.dir.size())
5819                   Mkdir(s_options.dir.c_str(), 0777);
5820           
5821               // Check schema given by -s otpion.
5822               if (s_options.schema.size())
5823               {
5824                   /* Check whether this is a valid C identifier */
5825                   if (!ValidIdent(s_options.schema))
5826                       err(ID_INVALID_SCHEMA_OPTION, "invalid schema option: %s", 
5827                           s_options.schema.c_str());
5828               }
5829           
5830               if ( s_options.quiet )
5831               {
5832                   s_stdout = Fopen(NULL_FILE, "a");
5833               }
5834               else
5835               {
5836                   s_stdout = stdout;
5837               }
5838           
5839 mike  1.1     // Create the parser.
5840               Parser parser(s_options.paths, s_options.warnings);
5841           
5842               // Parse all the MOF files.
5843               for (size_t i = 0; i < mofFilesArg.size(); i++)
5844               {
5845                   const char* path = mofFilesArg[i].c_str();
5846           
5847                   if (parser.parse(path) != 0)
5848                   {
5849                       err(ID_FAILED_TO_PARSE_MOF_FILE, "failed to parse MOF file: %s",
5850                           path);
5851                   }
5852               }
5853           
5854               // Build the alias table, which maps a MOF classname to an alias name.
5855               // Aliases are introduced by command-line classname arguments of the 
5856               // form <CLASSNAME>=<ALIAS>. For each command line argument of this
5857               // form, put an entry in the alias table. Use the lexographical case
5858               // for the class define in MOF (rather than defined on the command line).
5859               for (size_t i = 0; i < localClassNamesArg.size(); i++)
5860 mike  1.1     {
5861                   const char* className = localClassNamesArg[i].c_str();
5862                   char* alias = (char*)strchr(className, '=');
5863           
5864                   if (alias)
5865                   {
5866                       *alias++ = '\0';
5867           
5868                       const MI_ClassDecl* cd = parser.findClassDecl(className);
5869           
5870                       if (!cd)
5871                           err(ID_UNKNOWN_CLASS, "unknown class: %s", className);
5872           
5873                       aliases[cd->name] = alias;
5874                   }
5875               }
5876           
5877               // Form a complete list of class names (excluding duplicates).
5878           
5879               vector<string> classNames;
5880           
5881 mike  1.1     if (s_options.all)
5882               {
5883                   parser.getClassNames(classNames);
5884               }
5885               else
5886               {
5887                   for (size_t i = 0; i < localClassNamesArg.size(); i++)
5888                   {
5889                       const char* className = localClassNamesArg[i].c_str();
5890                       const MI_ClassDecl* cd = parser.findClassDecl(className);
5891           
5892                       if (!cd)
5893                           err(ID_UNKNOWN_CLASS, "unknown, class: %s", className);
5894           
5895                       // Save class name.
5896                       if (!Contains(classNames, cd->name))
5897                           classNames.push_back(cd->name);
5898           
5899                       // Reject classes that are abstract.
5900                       if (cd->flags & MI_FLAG_ABSTRACT)
5901                       {
5902 mike  1.1                 err(ID_REFUSED_TO_GENERATE_PROVIDER_FOR_ABSTRACT_CLASS, 
5903                               "refused to generated provider for abstract class: %s", 
5904                               cd->name);
5905                       }
5906                   }
5907               }
5908           
5909               // Form the set of classes for which there are providers (partial 
5910               // generation is performed on dependent classes (for which there is
5911               // no actual provider).
5912           
5913               if (!s_options.noProviders)
5914               {
5915                   for (size_t i = 0; i < classNames.size(); i++)
5916                   {
5917                       providerClasses.insert(classNames[i]);
5918                   }
5919               }
5920           
5921               // Add extra classes (given by -e option) to class list to be generated.
5922           
5923 mike  1.1     for (size_t i = 0; i < s_options.extraClasses.size(); i++)
5924               {
5925                   const MI_ClassDecl* cd = parser.findClassDecl(
5926                       s_options.extraClasses[i].c_str());
5927           
5928                   if (!cd)
5929                   {
5930                       err(ID_UNKNOWN_CLASS, "unknown class: %s", 
5931                           s_options.extraClasses[i].c_str());
5932                   }
5933           
5934                   classNames.push_back(cd->name);
5935               }
5936           
5937               // Generate the classes.
5938           
5939               set<string> classIdentifiers;
5940           
5941               for (size_t i = 0; i < classNames.size(); i++)
5942               {
5943                   const char* cn = classNames[i].c_str();
5944 mike  1.1         const MI_ClassDecl* cd = parser.findClassDecl(cn);
5945           
5946                   if (!cd)
5947                       err(ID_UNKNOWN_CLASS, "unknown class: %s", cn);
5948           
5949                   GenClassHeader(parser, cd, classIdentifiers);
5950           
5951                   if (providerClasses.find(cd->name) != providerClasses.end())
5952                   {
5953                       if (s_options.cpp)
5954                           GenCppClassSource(cd);
5955                       else
5956                           GenClassSource(cd);
5957                   }
5958               }
5959           
5960               // Generate the schema.c file.
5961               GenSchemaSourceFile(parser, classNames, classIdentifiers);
5962           
5963               // generate c++ wrappers - stubs.cpp file
5964               if (!s_options.noProviders && s_options.cpp)
5965 mike  1.1         GenModuleStubsFile(parser, classNames);
5966           
5967               // Generate the module.h and module.c files.
5968               if (!s_options.noProviders)
5969               {
5970                   if (s_options.cpp)
5971                   {
5972                       GenModuleCppSourceFile();
5973                       GenModuleCppHeaderFile();
5974                   }
5975                   else
5976                       GenModuleSourceFile();
5977               }
5978           
5979               // Generate the strings.rc.
5980               if (s_options.localize)
5981                   GenerateStringsFile();
5982           
5983               // Generate provider registry file.
5984               if (!s_options.providerRegistryPath.empty())
5985                   GenerateRegistryFile(parser, classNames);
5986 mike  1.1 
5987               if ( s_options.quiet )
5988               {
5989                   fclose( s_stdout );
5990                   s_stdout = 0;
5991               }
5992           
5993               // Generate the GNUmakefile.
5994               if (s_options.providerName.size())
5995                   GenMakefile(s_options.providerName, classNamesArg, s_options.cmdLine);
5996           
5997               return 0;
5998           }

ViewCVS 0.9.2