1 /*=========================================================================
3 Program: Visualization Toolkit
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
14 =========================================================================*/
18 This file provides a unified front-end for the wrapper generators.
23 #include "vtkParseData.h"
24 #include "vtkParseMain.h"
30 /* This is the struct that contains the options */
33 /* Get the base filename */
34 static const char *parse_exename(const char *cmd)
38 /* remove directory part of exe name */
39 for (exename = cmd + strlen(cmd); exename > cmd; --exename)
41 char pc = exename[-1];
42 if (pc == ':' || pc == '/' || pc == '\\')
52 static void parse_print_help(FILE *fp, const char *cmd, int multi)
55 "Usage: %s [options] infile... \n"
56 " --help print this help message\n"
57 " --version print the VTK version\n"
58 " -o <file> the output file\n"
59 " -I <dir> add an include directory\n"
60 " -D <macro[=def]> define a preprocessor macro\n"
61 " -U <macro> undefine a preprocessor macro\n"
62 " @<file> read arguments from a file\n",
65 /* args for describing a singe header file input */
69 " --hints <file> the hints file to use\n"
70 " --types <file> the type hierarchy file to use\n"
71 " --concrete force concrete class (ignored, deprecated)\n"
72 " --abstract force abstract class (ignored, deprecated)\n"
73 " --vtkobject vtkObjectBase-derived class (ignored, deprecated)\n"
74 " --special non-vtkObjectBase class (ignored, deprecated)\n");
78 /* append an arg to the arglist */
79 static void parse_append_arg(int *argn, char ***args, char *arg)
81 /* if argn is a power of two, allocate more space */
82 if (*argn > 0 && (*argn & (*argn - 1)) == 0)
84 *args = (char **)realloc(*args, 2*(*argn)*sizeof(char *));
86 /* append argument to list */
91 /* read options from a file, return zero on error */
92 static int read_option_file(
93 StringCache *strings, const char *filename, int *argn, char ***args)
95 static int option_file_stack_max = 10;
96 static int option_file_stack_size = 0;
97 static const char *option_file_stack[10];
108 line = (char *)malloc(maxlen);
110 fp = fopen(filename, "r");
117 /* read the file line by line */
118 while (fgets(line, (int)maxlen, fp))
122 /* if buffer not long enough, increase it */
123 while (n == maxlen-1 && line[n-1] != '\n' && !feof(fp))
126 line = (char *)realloc(line, maxlen);
127 if (!fgets(&line[n], (int)(maxlen-n), fp)) { break; }
128 n += strlen(&line[n]);
131 /* allocate a string to hold the parsed arguments */
132 argstring = vtkParse_NewString(strings, n);
136 /* break the line into individual options */
147 else if (*ccp == '\"' || *ccp == '\'')
154 else if (*ccp == in_string)
161 else if (!in_string && isspace(*ccp))
163 do { ccp++; } while (isspace(*ccp));
170 /* append character to argument */
177 /* recursively expand '@file' option */
178 if (option_file_stack_size == option_file_stack_max)
180 fprintf(stderr, "%s: @file recursion is too deep.\n",
184 /* avoid reading the same file recursively */
185 option_file_stack[option_file_stack_size++] = filename;
186 for (j = 0; j < option_file_stack_size; j++)
188 if (strcmp(&arg[1], option_file_stack[j]) == 0)
193 if (j < option_file_stack_size)
195 parse_append_arg(argn, args, arg);
197 else if (read_option_file(strings, &arg[1], argn, args) == 0)
199 parse_append_arg(argn, args, arg);
201 option_file_stack_size--;
203 else if (arg[0] != '\0')
205 parse_append_arg(argn, args, arg);
207 /* prepare for next arg */
216 /* expand any "@file" args that occur in the command-line args */
217 static void parse_expand_args(
218 StringCache *strings, int argc, char *argv[], int *argn, char ***args)
223 *args = (char **)malloc(sizeof(char *));
225 for (i = 0; i < argc; i++)
227 /* check for "@file" unless this is the command name */
228 if (i > 0 || argv[i][0] == '@')
230 /* if read_option_file returns null, add "@file" to the args */
231 /* (this mimics the way that gcc expands @file arguments) */
232 if (read_option_file(strings, &argv[i][1], argn, args) == 0)
234 parse_append_arg(argn, args, argv[i]);
239 /* append any other arg */
240 parse_append_arg(argn, args, argv[i]);
245 /* Check the options: "multi" should be zero for wrapper tools that
246 * only take one input file, or one for wrapper tools that take multiple
247 * input files. Returns zero for "--version" or "--help", or returns -1
248 * if an error occurred. Otherwise, it returns the number of args
249 * that were successfully parsed. */
250 static int parse_check_options(int argc, char *argv[], int multi)
257 options.NumberOfFiles = 0;
258 options.Files = NULL;
259 options.InputFileName = NULL;
260 options.OutputFileName = NULL;
261 options.HierarchyFileName = 0;
262 options.HintFileName = 0;
264 for (i = 1; i < argc; i++)
266 if (strcmp(argv[i], "--help") == 0)
268 parse_print_help(stdout, argv[0], multi);
271 else if (strcmp(argv[i], "--version") == 0)
273 const char *ver = VTK_PARSE_VERSION;
274 fprintf(stdout, "%s %s\n", parse_exename(argv[0]), ver);
277 else if (argv[i][0] != '-')
279 if (options.NumberOfFiles == 0)
281 options.Files = (char **)malloc(sizeof(char *));
283 else if ((options.NumberOfFiles & (options.NumberOfFiles - 1)) == 0)
285 options.Files = (char **)realloc(
286 options.Files, 2*options.NumberOfFiles*sizeof(char *));
288 options.Files[options.NumberOfFiles++] = argv[i];
290 else if (argv[i][0] == '-' && isalpha(argv[i][1]))
297 if (i >= argc || argv[i][0] == '-')
306 options.OutputFileName = cp;
310 vtkParse_IncludeDirectory(cp);
315 while (cp[j] != '\0' && cp[j] != '=') { j++; }
316 if (cp[j] == '=') { j++; }
317 vtkParse_DefineMacro(cp, &cp[j]);
321 vtkParse_UndefineMacro(cp);
324 else if (!multi && strcmp(argv[i], "--hints") == 0)
327 if (i >= argc || argv[i][0] == '-')
331 options.HintFileName = argv[i];
333 else if (!multi && strcmp(argv[i], "--types") == 0)
336 if (i >= argc || argv[i][0] == '-')
340 options.HierarchyFileName = argv[i];
342 else if (strcmp(argv[i], "--vtkobject") == 0 ||
343 strcmp(argv[i], "--special") == 0 ||
344 strcmp(argv[i], "--abstract") == 0 ||
345 strcmp(argv[i], "--concrete") == 0)
347 fprintf(stderr, "Warning: the %s option is deprecated "
348 "and will be ignored.\n", argv[i]);
355 /* Return a pointer to the static OptionInfo struct */
356 OptionInfo *vtkParse_GetCommandLineOptions()
361 /* Command-line argument handler for wrapper tools */
362 FileInfo *vtkParse_Main(int argc, char *argv[])
373 /* expand any "@file" args */
374 vtkParse_InitStringCache(&strings);
375 parse_expand_args(&strings, argc, argv, &argn, &args);
377 /* read the args into the static OptionInfo struct */
378 argi = parse_check_options(argn, args, 0);
380 /* was output file already specified by the "-o" option? */
381 expected_files = (options.OutputFileName == NULL ? 2 : 1);
383 /* verify number of args, print usage if not valid */
389 else if (argi < 0 || options.NumberOfFiles != expected_files)
391 parse_print_help(stderr, args[0], 0);
395 /* open the input file */
396 options.InputFileName = options.Files[0];
398 if (!(ifile = fopen(options.InputFileName, "r")))
400 fprintf(stderr, "Error opening input file %s\n", options.InputFileName);
404 if (options.OutputFileName == NULL &&
405 options.NumberOfFiles > 1)
407 /* allow outfile to be given after infile, if "-o" option not used */
408 options.OutputFileName = options.Files[1];
409 fprintf(stderr, "Deprecated: specify output file with \"-o\".\n");
412 /* free the expanded args */
415 /* open the hint file, if given on the command line */
416 if (options.HintFileName && options.HintFileName[0] != '\0')
418 if (!(hfile = fopen(options.HintFileName, "r")))
420 fprintf(stderr, "Error opening hint file %s\n", options.HintFileName);
426 /* make sure than an output file was given on the command line */
427 if (options.OutputFileName == NULL)
429 fprintf(stderr, "No output file was specified\n");
438 /* if a hierarchy is was given, then BTX/ETX can be ignored */
439 vtkParse_SetIgnoreBTX(0);
440 if (options.HierarchyFileName)
442 vtkParse_SetIgnoreBTX(1);
445 /* parse the input file */
446 data = vtkParse_ParseFile(options.InputFileName, ifile, stderr);
453 /* fill in some blanks by using the hints file */
456 vtkParse_ReadHints(data, hfile, stderr);
461 /* mark class as abstract unless it has New() method */
462 int nfunc = data->MainClass->NumberOfFunctions;
464 for (ifunc = 0; ifunc < nfunc; ifunc++)
466 FunctionInfo *func = data->MainClass->Functions[ifunc];
467 if (func && func->Access == VTK_ACCESS_PUBLIC &&
468 func->Name && strcmp(func->Name, "New") == 0 &&
469 func->NumberOfParameters == 0)
474 data->MainClass->IsAbstract = ((ifunc == nfunc) ? 1 : 0);
480 /* Command-line argument handler for wrapper tools */
481 void vtkParse_MainMulti(int argc, char *argv[])
488 /* expand any "@file" args */
489 vtkParse_InitStringCache(&strings);
490 parse_expand_args(&strings, argc, argv, &argn, &args);
492 /* read the args into the static OptionInfo struct */
493 argi = parse_check_options(argn, args, 1);
500 else if (argi < 0 || options.NumberOfFiles == 0)
502 parse_print_help(stderr, argv[0], 1);
507 options.InputFileName = options.Files[0];