(file) Return to main.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           #ifndef MI_CHAR_TYPE
 26           # define MI_CHAR_TYPE 1
 27           #endif
 28           
 29           #include <common.h>
 30           #include <gen/gen.h>
 31           #include <base/paths.h>
 32           #include <base/io.h>
 33           #include <base/env.h>
 34           #include <base/conf.h>
 35           #include <base/getopt.h>
 36           
 37           static const char HELP[] = "\
 38           Usage: %s [OPTIONS] PATH CLASSNAME[=ALIAS] ...\n\
 39           \n\
 40           OVERVIEW:\n\
 41               This program generates provider source code from MOF class definitions.\n\
 42               PATH is a file that contains the MOF definitions (or includes them).\n\
 43 mike  1.1     It must include any dependent MOF defintions as well (such as the CIM\n\
 44               schema). The PATH is followed by a list of CLASSNAME arguments, which are\n\
 45               the names of the MOF classes to be generated. Each CLASSNAME argument may\n\
 46               be followed by an optional ALIAS argument (separated by an equal sign).\n\
 47               The ALIAS provides an alternative name for the class to be used within\n\
 48               the C source code. For example, 'CIM_ComputerSystem=CompSys' says to\n\
 49               use 'CompSys' in C sources instead of 'CIM_ComputerSystem'.\n\
 50           \n\
 51           OPTIONS:\n\
 52               -I PATH                     Search this directory for included MOF files.\n\
 53               -D                          Generate 'Description' qualifiers.\n\
 54               -V                          Generate 'Values' and 'ValueMap' qualifiers.\n\
 55               -M                          Generate 'MappingStrings' qualifiers.\n\
 56               -S                          Generate standard CIM qualifier declarations.\n\
 57               -B                          Generate boolean qualifiers.\n\
 58               -Q                          Suppress qualifier declarations generation.\n\
 59               -q                          Quiet mode - do not print anything on stdout.\n\
 60               -h, --help                  Print this help message.\n\
 61               -v, --version               Print the program version.\n\
 62               -s SCHEMA                   Specify C name of the schema [schemaDecl].\n\
 63               -n                          Suppress provider generation (only schema.c).\n\
 64 mike  1.1     --cpp                       Generate cpp skeleton for the provider.\n\
 65               -d PATH                     Place output files in this directory.\n\
 66               -l                          Generate strings.rc file.\n\
 67               -f                          Set filter support flag into MI_Main().\n\
 68               -A                          Generate single association function.\n\
 69               -e CLASS                    Generate extra class with this name.\n\
 70               -y NAME                     Use NAME as entry point (default MI_Main).\n\
 71               -W                          Print MOF warnings (suppressed by default).\n\
 72               -C, --schemafile PATH       Alternative path of main CIM schema file.\n\
 73               -m PROVIDERNAME             Generate provider makefile.\n\
 74               --nogi CLASSNAME            Set MI_ProviderFT.GetInstance to NULL for\n\
 75                                           the given class. This forces the provider\n\
 76                                           manager to use the EnumerateInstances method\n\
 77                                           to satisfy all GetInstance requests on this\n\
 78                                           class.\n\
 79           \n\
 80           EXAMPLES:\n\
 81               The following example generates a 'MSFT_ComputerSystem' class, which is\n\
 82               defined in schema.mof.\n\
 83           \n\
 84                   $ omigen schema.mof MSFT_ComputerSystem=CompSys\n\
 85 mike  1.1         Created CompSys.h\n\
 86                   Created CompSys.c\n\
 87                   Created schema.c\n\
 88                   Created module.c\n\
 89           \n\
 90               CompSys.h defines the 'CompSys' structure. schema.c defines run-time type\n\
 91               information for the CompSys structure. CompSys.c contains the provider\n\
 92               stubs and module.c contains the MI_Main() provider entry point.\n\
 93           \n\
 94           FILES:\n\
 95               .omigenrc\n\
 96                   This file contains an option per line as it might appear on the \n\
 97                   command line (-OPTION [ARGUMENT]). These options are appended to the\n\
 98                   command line options, which take precedence. The program first\n\
 99                   attempts to open this file in the current directory followed by\n\
100                   the home directory (given by the 'HOME' environment variable).\n\
101                   The following is an example of the contents of this file.\n\
102           \n\
103                       -I /opt/microsoft/sca/mof/cim222\n\
104                       -I /opt/microsoft/sca/mof/extras\n\
105           \n\
106 mike  1.1 ";
107           
108           using namespace std;
109           
110           static const char* arg0;
111           
112           //==============================================================================
113           //
114           // err()
115           //
116           //     Writes a formatted error message to standard error (preceded by argv[0])
117           //     and then exists.
118           //
119           //==============================================================================
120           
121           PRINTF_FORMAT(1, 2)
122           static void FUNCTION_NEVER_RETURNS err(const char* fmt, ...)
123           {
124               fprintf(stderr, "%s: ", arg0);
125           
126               va_list ap;
127 mike  1.1     va_start(ap, fmt);
128               vfprintf(stderr, fmt, ap);
129               va_end(ap);
130           
131               fputc('\n', stderr);
132               exit(1);
133           }
134           
135           static void _GetCommandLineDestDirOption(
136               int* argc_,
137               const char* argv[])
138           {
139               int argc = *argc_;
140               int i;
141               const char* destdir = NULL;
142           
143               for (i = 1; i < argc; )
144               {
145                   if (strcmp(argv[i], "--destdir") == 0)
146                   {
147                       if (i + 1 == argc)
148 mike  1.1                 err("missing argument for --destdir option");
149           
150                       destdir = argv[i+1];
151                       memmove((char*)&argv[i], (char*)&argv[i+2], 
152                           sizeof(char*) * (argc-i-1));
153                       argc -= 2;
154                   }
155                   else if (strncmp(argv[i], "--destdir=", 10) == 0)
156                   {
157                       destdir = argv[i] + 10;
158                       memmove((char*)&argv[i], (char*)&argv[i+1], 
159                           sizeof(char*) * (argc-i));
160           
161                       argc -= 1;
162                   }
163                   else
164                       i++;
165               }
166           
167               if (destdir)
168               {
169 mike  1.1         if (SetPath(ID_DESTDIR, destdir) != 0)
170                       err("failed to set destdir");
171               }
172           
173               *argc_ = argc;
174           }
175           
176           //==============================================================================
177           //
178           // _GetCommandLineOptions()
179           //
180           //     This function processes command line options. Each option begins with 
181           //     the '-' character followed by a single alphabetic character. An option
182           //     may be followed by an optional argument. GeneratorOptions and their 
183           //     optional arguments are removed from the argc-argv array upon return. 
184           //     Extracted options are stored in the options parameter (see the 
185           //     GeneratorOptions structure defined above).
186           //
187           //==============================================================================
188           
189           static string schemafile;
190 mike  1.1 
191           static void _GetCommandLineOptions( 
192               int& argc, 
193               const char**& argv, 
194               GeneratorOptions& options)
195           {
196               GetOptState state = GETOPTSTATE_INITIALIZER;
197           
198               const char* opts[] =
199               {
200                   "-I:",
201                   "-h",
202                   "--help",
203                   "-v",
204                   "--version",
205                   "-D",
206                   "-V",
207                   "-M",
208                   "-S",
209                   "-B",
210                   "-Q",
211 mike  1.1         "-f",
212                   "-q",
213                   "-W",
214                   "-a",
215                   "-n",
216                   "--cpp",
217                   "-s:",
218                   "-d:",
219                   "-e:",
220                   "-y:",
221                   "-l",
222                   "-reg:",
223                   "-A",
224                   "-C:",
225                   "--schemafile:",
226                   "-m:",
227                   "--nogi:",
228                   NULL,
229               };
230           
231               /* For each argument */
232 mike  1.1     for (;;)
233               {
234                   int r = GetOpt(&argc, (const char**)argv, opts, &state);
235           
236                   if (r == 1)
237                       break;
238           
239                   if (r == -1)
240                       err("%s", state.err);
241           
242                   /* Check for -I option */
243                   if (strcmp(state.opt, "-I") == 0)
244                   {
245                       options.paths.push_back(state.arg);
246                   }
247                   else if (strcmp(state.opt, "-h") == 0 ||
248                       strcmp(state.opt, "--help") == 0)
249                   {
250                       printf(HELP, arg0);
251                       exit(1);
252                   }
253 mike  1.1         else if (strcmp(state.opt, "-v") == 0 ||
254                            strcmp(state.opt, "--version") == 0)
255                   {
256                       printf("%s: %s\n", arg0,
257                           CONFIG_PRODUCT "-" CONFIG_VERSION " - " CONFIG_DATE);
258                       exit(0);
259                   }
260                   else if (strcmp(state.opt, "-D") == 0)
261                   {
262                       options.descriptions = true;
263                   }
264                   else if (strcmp(state.opt, "-V") == 0)
265                   {
266                       options.values = true;
267                   }
268                   else if (strcmp(state.opt, "-M") == 0)
269                   {
270                       options.mappingStrings = true;
271                   }
272                   else if (strcmp(state.opt, "-S") == 0)
273                   {
274 mike  1.1             options.standardQualifiers = true;
275                   }
276                   else if (strcmp(state.opt, "-B") == 0)
277                   {
278                       options.booleanQualifiers = true;
279                   }
280                   else if (strcmp(state.opt, "-Q") == 0)
281                   {
282                       options.ignoreAllQualifiers = true;
283                   }
284                   else if (strcmp(state.opt, "-f") == 0)
285                   {
286                       options.filterSupport = true;
287                   }
288                   else if (strcmp(state.opt, "-q") == 0)
289                   {
290                       options.quiet = true;
291                   }
292                   else if (strcmp(state.opt, "-W") == 0)
293                   {
294                       options.warnings = true;
295 mike  1.1         }
296                   else if (strcmp(state.opt, "-a") == 0)
297                   {
298                       options.all = true;
299                   }
300                   else if (strcmp(state.opt, "-n") == 0)
301                   {
302                       options.noProviders = true;
303                   }
304                   else if (strcmp(state.opt, "--cpp") == 0)
305                   {
306                       options.cpp = true;
307                   }
308                   else if (strcmp(state.opt, "-s") == 0)
309                   {
310                       options.schema = state.arg;
311                   }
312                   else if (strcmp(state.opt, "-d") == 0)
313                   {
314                       options.dir = state.arg;
315                   }
316 mike  1.1         else if (strcmp(state.opt, "-e") == 0)
317                   {
318                       options.extraClasses.push_back(state.arg);
319                   }
320                   else if (strcmp(state.opt, "-y") == 0)
321                   {
322                       options.entryPoint = state.arg;
323                   }
324                   else if (strcmp(state.opt, "-l") == 0)
325                   {
326                       options.localize = true;
327                   }
328                   else if (strcmp(state.opt, "-reg") == 0)
329                   {
330                       options.providerRegistryPath = state.arg;
331                   }
332                   else if (strcmp(state.opt, "-A") == 0)
333                   {
334                       options.association = true;
335                   }
336                   else if (strcmp(state.opt, "-C") == 0 ||
337 mike  1.1                  strcmp(state.opt, "--schemafile") == 0)
338                   {
339                       schemafile = state.arg;
340           
341                       if (schemafile.size() && access(schemafile.c_str(), R_OK) != 0)
342                       {
343                           err("file given by %s option does not exist: %s", 
344                               state.opt, schemafile.c_str());
345                       }
346                   }
347                   else if (strcmp(state.opt, "-m") == 0)
348                   {
349                       options.providerName = state.arg;
350                   }
351                   else if (strcmp(state.opt, "--nogi") == 0)
352                   {
353                       options.noGetInstance.push_back(state.arg);
354                   }
355               }
356           }
357           
358 mike  1.1 //==============================================================================
359           //
360           // FindConfigFile()
361           //
362           //     Find the configuration file by checking in following order:
363           //
364           //         ./.omigenrc
365           //         home/.omigenrc
366           //         sysconfdir/.omigenrc
367           //
368           //==============================================================================
369           
370           static int FindConfigFile(char path[MAX_PATH_SIZE])
371           {
372               /* Look in current directory */
373               {
374                   Strlcpy(path, "./.omigenrc", MAX_PATH_SIZE);
375           
376                   if (access(path, R_OK) == 0)
377                       return 0;
378               }
379 mike  1.1 
380               /* Look in HOME directory */
381               char* home = Dupenv("HOME");
382               if (home)
383               {
384                   Strlcpy(path, home, MAX_PATH_SIZE);
385                   Strlcat(path, "/.omigenrc", MAX_PATH_SIZE);
386           
387                   if (access(path, R_OK) == 0)
388                   {
389                       free(home);
390                       return 0;
391                   }
392                   free(home);
393               }
394           
395               /* Look in system config directory */
396               {
397                   Strlcpy(path, GetPath(ID_DESTDIR), MAX_PATH_SIZE);
398 mike  1.2         Strlcat(path, "/", MAX_PATH_SIZE);
399 mike  1.1         Strlcat(path, GetPath(ID_SYSCONFDIR), MAX_PATH_SIZE);
400                   Strlcat(path, "/omigen.conf", MAX_PATH_SIZE);
401           
402                   if (access(path, R_OK) == 0)
403                       return 0;
404               }
405           
406               /* Not found */
407               return -1;
408           }
409           
410           //==============================================================================
411           //
412           // _GetConfigFileOptions()
413           //
414           //     Read options from the omigen configuration file.
415           //
416           //==============================================================================
417           
418           static void _GetConfigFileOptions(GeneratorOptions& opts)
419           {
420 mike  1.1     char path[MAX_PATH_SIZE];
421               Conf* conf;
422           
423               MI_UNUSED(opts);
424           
425               /* Form the configuration file path */
426               if (FindConfigFile(path) != 0)
427                   err("failed to find configuration file");
428           
429               /* Open the configuration file */
430               conf = Conf_Open(path);
431               if (!conf)
432                   err("failed to open configuration file: %s", path);
433           
434               /* For each key=value pair in configuration file */
435               for (;;)
436               {
437                   const char* key;
438                   const char* value;
439                   int r = Conf_Read(conf, &key, &value);
440           
441 mike  1.1         if (r == -1)
442                       err("%s: %s\n", path, Conf_Error(conf));
443           
444                   if (r == 1)
445                       break;
446           
447                   if (strcmp(key, "schemafile") == 0)
448                   {
449                       schemafile = value;
450           
451                       if (schemafile.size() && access(schemafile.c_str(), R_OK) != 0)
452                       {
453                           err("%s(%u): file given by '%s' key does not exist: %s", 
454                               path, Conf_Line(conf), key, schemafile.c_str());
455                       }
456                   }
457                   else
458                       err("%s(%u): unknown key: %s", path, Conf_Line(conf), key);
459               }
460           
461               /* Close configuration file */
462 mike  1.1     Conf_Close(conf);
463           }
464           
465           //==============================================================================
466           //
467           // _EncodeStr()
468           //
469           //     Encodes special characters in a string; replaces all 'lookfor wtih replacewith
470           //
471           //==============================================================================
472           
473           static void _EncodeStr(
474               std::string& str, 
475               const std::string lookfor, 
476               const std::string& replacewith)
477           {
478               std::string::size_type start = 0;
479               std::string::size_type pos;
480           
481               for(;;)
482               {
483 mike  1.1         pos = str.find(lookfor, start);
484           
485                   if (pos == std::string::npos)
486                       break;
487           
488                   str.replace(pos, lookfor.size(), replacewith);
489                   start = pos + replacewith.size();
490               }
491           }
492           
493           int main(int argc, const char** argv)
494           {
495               arg0 = argv[0];
496               GeneratorOptions options;
497           
498           
499               // command line
500               {
501                   for (int i = 1; i < argc; i++)
502                   {
503                       std::string arg = argv[i];
504 mike  1.1 
505                       // escape special characters
506                       _EncodeStr(arg, "\\", "\\\\");
507                       _EncodeStr(arg, "\"", "\\\"");
508                       _EncodeStr(arg, " ", "\\ ");
509           
510                       if (!options.cmdLine.empty())
511                           options.cmdLine += " ";
512           
513                       options.cmdLine += arg;
514                   }
515               }
516           
517               // Get --destdir command-line option.
518               _GetCommandLineDestDirOption(&argc, argv);
519           
520               // Set path of default CIM schema file.
521               schemafile = GetPath(ID_SCHEMAFILE);
522           
523               // Get configuraiton file options.
524               _GetConfigFileOptions(options);
525 mike  1.1 
526               // Get command-line options.
527               _GetCommandLineOptions(argc, argv, options);
528           
529               // Check arguments. There must one or mores class name arguments unless
530               // the -a options was given.
531               if (argc < 2 || (!options.all && argc < 3))
532               {
533                   fprintf(stderr, "Usage: %s PATH CLASSNAME[=ALIAS] ...\n", arg0);
534                   fprintf(stderr, "Try '%s -h' for help\n\n", arg0);
535                   exit(1);
536               }
537           
538               // ProgramName argument:
539               string programName = argv[0];
540           
541               // MofFiles argument (only one file):
542               vector<string> mofFiles;
543               {
544                   if (schemafile.size())
545                       mofFiles.push_back(schemafile);
546 mike  1.1 
547                   mofFiles.push_back(argv[1]);
548               }
549           
550               // ClassNames argument:
551               vector<string> classNames;
552               {
553                   for (int i = 2; i < argc; i++)
554                       classNames.push_back(argv[i]);
555               }
556           
557               // Invoke generator:
558               return GeneratorMain(programName, mofFiles, classNames, options);
559           }

ViewCVS 0.9.2