/* duplicate the first n bytes of a string and terminate it */ const char *vtkParse_CacheString(StringCache *cache, const char *in, size_t n) { char *res = NULL; res = vtkParse_NewString(cache, n); strncpy(res, in, n); res[n] = '\0'; return res; }
/* read options from a file, return zero on error */ static int read_option_file( StringCache *strings, const char *filename, int *argn, char ***args) { static int option_file_stack_max = 10; static int option_file_stack_size = 0; static const char *option_file_stack[10]; FILE *fp; char *line; const char *ccp; char *argstring; char *arg; size_t maxlen = 15; size_t i, n; int j; int in_string; line = (char *)malloc(maxlen); fp = fopen(filename, "r"); if (fp == NULL) { return 0; } /* read the file line by line */ while (fgets(line, (int)maxlen, fp)) { n = strlen(line); /* if buffer not long enough, increase it */ while (n == maxlen-1 && line[n-1] != '\n' && !feof(fp)) { maxlen *= 2; line = (char *)realloc(line, maxlen); if (!fgets(&line[n], (int)(maxlen-n), fp)) { break; } n += strlen(&line[n]); } /* allocate a string to hold the parsed arguments */ argstring = vtkParse_NewString(strings, n); arg = argstring; i = 0; /* break the line into individual options */ ccp = line; in_string = 0; while (*ccp != '\0') { for (;;) { if (*ccp == '\\') { ccp++; } else if (*ccp == '\"' || *ccp == '\'') { if (!in_string) { in_string = *ccp++; continue; } else if (*ccp == in_string) { in_string = 0; ccp++; continue; } } else if (!in_string && isspace(*ccp)) { do { ccp++; } while (isspace(*ccp)); break; } if (*ccp == '\0') { break; } /* append character to argument */ arg[i++] = *ccp++; } arg[i++] = '\0'; if (arg[0] == '@') { /* recursively expand '@file' option */ if (option_file_stack_size == option_file_stack_max) { fprintf(stderr, "%s: @file recursion is too deep.\n", (*args)[0]); exit(1); } /* avoid reading the same file recursively */ option_file_stack[option_file_stack_size++] = filename; for (j = 0; j < option_file_stack_size; j++) { if (strcmp(&arg[1], option_file_stack[j]) == 0) { break; } } if (j < option_file_stack_size) { parse_append_arg(argn, args, arg); } else if (read_option_file(strings, &arg[1], argn, args) == 0) { parse_append_arg(argn, args, arg); } option_file_stack_size--; } else if (arg[0] != '\0') { parse_append_arg(argn, args, arg); } /* prepare for next arg */ arg += i; i = 0; } } return 1; }
/* try to resolve "Using" declarations with the given class. */ void vtkParseMerge_MergeUsing( FileInfo *finfo, MergeInfo *info, ClassInfo *merge, const ClassInfo *super, unsigned long depth) { unsigned long i, j, k, ii, n, m; char *cp; size_t l; int match; UsingInfo *u; UsingInfo *v; FunctionInfo *func; FunctionInfo *f2; ValueInfo *param; const char *lastval; int is_constructor; /* if scope matches, rename scope to "Superclass", */ /* this will cause any inherited scopes to match */ match = 0; for (ii = 0; ii < merge->NumberOfUsings; ii++) { u = merge->Usings[ii]; if (u->Scope) { match = 1; if (strcmp(u->Scope, super->Name) == 0) { u->Scope = "Superclass"; } } } if (!match) { /* nothing to do! */ return; } m = merge->NumberOfFunctions; n = super->NumberOfFunctions; for (i = 0; i < n; i++) { func = super->Functions[i]; if (!func->Name) { continue; } /* destructors cannot be used */ if (func->Name[0] == '~' && strcmp(&func->Name[1], super->Name) == 0) { continue; } /* constructors can be used, with limitations */ is_constructor = 0; if (strcmp(func->Name, super->Name) == 0) { is_constructor = 1; if (func->Template) { /* templated constructors cannot be "used" */ continue; } } /* check that the function is being "used" */ match = 0; for (ii = 0; ii < merge->NumberOfUsings; ii++) { u = merge->Usings[ii]; if (u->Scope && strcmp(u->Scope, "Superclass") == 0) { if (u->Name && strcmp(u->Name, func->Name) == 0) { match = 1; break; } } } if (!match) { continue; } /* look for override of this signature */ match = 0; for (j = 0; j < m; j++) { f2 = merge->Functions[j]; if (f2->Name && ((is_constructor && strcmp(f2->Name, merge->Name) == 0) || (!is_constructor && strcmp(f2->Name, func->Name) == 0))) { if (vtkParse_CompareFunctionSignature(func, f2) != 0) { match = 1; break; } } } if (!match) { /* copy into the merge */ if (is_constructor) { /* constructors require special default argument handling, there * is a different used constructor for each arg with a default */ for (j = func->NumberOfParameters; j > 0; j--) { param = func->Parameters[0]; if (j == 1 && param->TypeName && strcmp(param->TypeName, super->Name) == 0 && (param->Type & VTK_PARSE_POINTER_MASK) == 0) { /* it is a copy constructor, it will not be "used" */ continue; } f2 = (FunctionInfo *)malloc(sizeof(FunctionInfo)); vtkParse_InitFunction(f2); f2->Access = u->Access; f2->Name = merge->Name; f2->Class = merge->Name; f2->Comment = func->Comment; f2->IsExplicit = func->IsExplicit; l = vtkParse_FunctionInfoToString(f2, NULL, VTK_PARSE_EVERYTHING); cp = vtkParse_NewString(finfo->Strings, l); vtkParse_FunctionInfoToString(f2, cp, VTK_PARSE_EVERYTHING); f2->Signature = cp; for (k = 0; k < j; k++) { param = (ValueInfo *)malloc(sizeof(ValueInfo)); vtkParse_CopyValue(param, func->Parameters[k]); lastval = param->Value; param->Value = NULL; /* clear default parameter value */ vtkParse_AddParameterToFunction(f2, param); } vtkParse_AddFunctionToClass(merge, f2); if (info) { vtkParseMerge_PushFunction(info, depth); } if (lastval == NULL) { /* continue if last parameter had a default value */ break; } } } else { /* non-constructor methods are simple */ f2 = (FunctionInfo *)malloc(sizeof(FunctionInfo)); vtkParse_CopyFunction(f2, func); f2->Access = u->Access; f2->Class = merge->Name; vtkParse_AddFunctionToClass(merge, f2); if (info) { vtkParseMerge_PushFunction(info, depth); } } } } /* remove any using declarations that were satisfied */ for (i = 0; i < merge->NumberOfUsings; i++) { u = merge->Usings[i]; if (u->Scope && strcmp(u->Scope, "Superclass") == 0) { match = 0; for (j = 0; j < super->NumberOfUsings && !match; j++) { v = super->Usings[j]; if (v->Name && u->Name && strcmp(u->Name, v->Name) == 0) { /* get the new scope so that recursion will occur */ u->Scope = v->Scope; match = 1; } } for (j = 0; j < super->NumberOfFunctions && !match; j++) { func = super->Functions[j]; if (u->Name && func->Name && strcmp(func->Name, u->Name) == 0) { /* ignore this "using" from now on */ merge->Usings[i]->Name = NULL; merge->Usings[i]->Scope = NULL; match = 1; } } } } }