Back to index

salome-paravis  6.5.0
vtkWrapHierarchy.c
Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program:   Visualization Toolkit
00004   Module:    vtkWrapHierarchy.c
00005 
00006   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
00007   All rights reserved.
00008   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
00009 
00010      This software is distributed WITHOUT ANY WARRANTY; without even
00011      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00012      PURPOSE.  See the above copyright notice for more information.
00013 
00014 =========================================================================*/
00015 /*-------------------------------------------------------------------------
00016   Copyright (c) 2010 David Gobbi.
00017 
00018   Contributed to the VisualizationToolkit by the author in June 2010
00019   under the terms of the Visualization Toolkit 2008 copyright.
00020 -------------------------------------------------------------------------*/
00021 
00040 #include "vtkParse.h"
00041 #include "vtkParseInternal.h"
00042 #include "vtkParsePreprocess.h"
00043 #include <stdio.h>
00044 #include <string.h>
00045 #include <stdlib.h>
00046 #include <ctype.h>
00047 #ifdef _WIN32
00048 # include <windows.h>
00049 #else
00050 # include <unistd.h>
00051 #endif
00052 
00056 static char **append_unique_line(char **lines, char *line, size_t *np)
00057 {
00058   size_t l, n;
00059 
00060   n = *np;
00061 
00062   /* check to make sure this line isn't a duplicate */
00063   for (l = 0; l < n; l++)
00064     {
00065     if (strcmp(line, lines[l]) == 0)
00066       {
00067       break;
00068       }
00069     }
00070   if (l == n)
00071     {
00072     /* allocate more memory if n+1 is a power of two */
00073     if (((n+1) & n) == 0)
00074       {
00075       lines = (char **)realloc(lines, (n+1)*2*sizeof(char *));
00076       }
00077 
00078     lines[n] = (char *)malloc(strlen(line)+1);
00079     strcpy(lines[n++], line);
00080     lines[n] = NULL;
00081     }
00082 
00083   *np = n;
00084   return lines;
00085 }
00086 
00090 static char *append_to_line(
00091   char *line, const char *text, size_t *pos, size_t *maxlen)
00092 {
00093   size_t n;
00094 
00095   n = strlen(text);
00096 
00097   if ((*pos) + n + 1 > (*maxlen))
00098     {
00099     *maxlen = ((*pos) + n + 1 + 2*(*maxlen));
00100     line = (char *)realloc(line, (*maxlen));
00101     }
00102 
00103   strcpy(&line[*pos], text);
00104   *pos = (*pos) + n;
00105 
00106   return line;
00107 }
00108 
00112 static char *append_scope_to_line(
00113   char *line, size_t *m, size_t *maxlen, const char *scope)
00114 {
00115   if (scope && scope[0] != '\0')
00116     {
00117     line = append_to_line(line, scope, m, maxlen);
00118     line = append_to_line(line, "::", m, maxlen);
00119     }
00120 
00121   return line;
00122 }
00123 
00127 static char *append_template_to_line(
00128   char *line, size_t *m, size_t *maxlen, TemplateArgs *template_args)
00129 {
00130   TemplateArg *arg;
00131   int j;
00132 
00133   line = append_to_line(line, "<", m, maxlen);
00134 
00135   for (j = 0; j < template_args->NumberOfArguments; j++)
00136     {
00137     arg = template_args->Arguments[j];
00138     line = append_to_line(line, arg->Name, m, maxlen);
00139     if (arg->Value && arg->Value[0] != '\n')
00140       {
00141       line = append_to_line(line, "=", m, maxlen);
00142       line = append_to_line(line, arg->Value, m, maxlen);
00143       }
00144     if (j+1 < template_args->NumberOfArguments)
00145       {
00146       line = append_to_line(line, ",", m, maxlen);
00147       }
00148     }
00149 
00150   line = append_to_line(line, ">", m, maxlen);
00151 
00152   return line;
00153 }
00154 
00158 static char *append_class_to_line(
00159   char *line, size_t *m, size_t *maxlen, ClassInfo *class_info)
00160 {
00161   int j;
00162 
00163   line = append_to_line(line, class_info->Name, m, maxlen);
00164 
00165   if (class_info->Template)
00166     {
00167     line = append_template_to_line(line, m, maxlen, class_info->Template);
00168     }
00169 
00170   line = append_to_line(line, " ", m, maxlen);
00171 
00172   if (class_info->NumberOfSuperClasses)
00173     {
00174     line = append_to_line(line, ": ", m, maxlen);
00175     }
00176 
00177   for (j = 0; j < class_info->NumberOfSuperClasses; j++)
00178     {
00179     line = append_to_line(line, class_info->SuperClasses[j], m, maxlen);
00180     line = append_to_line(line, " ", m, maxlen);
00181     if (j+1 < class_info->NumberOfSuperClasses)
00182       {
00183       line = append_to_line(line, ", ", m, maxlen);
00184       }
00185     }
00186 
00187   return line;
00188 }
00189 
00193 static char *append_enum_to_line(
00194   char *line, size_t *m, size_t *maxlen, EnumInfo *enum_info)
00195 {
00196   line = append_to_line(line, enum_info->Name, m, maxlen);
00197   line = append_to_line(line, " : enum ", m, maxlen);
00198 
00199   return line;
00200 }
00201 
00205 static char *append_trailer(
00206   char *line, size_t *m, size_t *maxlen,
00207   const char *header_file, const char *module_name, const char *flags)
00208 {
00209   line = append_to_line(line, "; ", m, maxlen);
00210   line = append_to_line(line, header_file, m, maxlen);
00211 
00212   line = append_to_line(line, " ; ", m, maxlen);
00213   line = append_to_line(line, module_name, m, maxlen);
00214 
00215   if (flags && flags[0] != '\0')
00216     {
00217     line = append_to_line(line, " ; ", m, maxlen);
00218     line = append_to_line(line, flags, m, maxlen);
00219     }
00220 
00221   return line;
00222 }
00223 
00227 static char *append_typedef_to_line(
00228   char *line, size_t *m, size_t *maxlen, ValueInfo *typedef_info)
00229 {
00230   unsigned int type;
00231   int ndims;
00232   int dim;
00233 
00234   line = append_to_line(line, typedef_info->Name, m, maxlen);
00235   line = append_to_line(line, " = ", m, maxlen);
00236 
00237   type = typedef_info->Type;
00238 
00239   if ((type & VTK_PARSE_REF) != 0)
00240     {
00241     line = append_to_line(line, "&", m, maxlen);
00242     }
00243 
00244   ndims = typedef_info->NumberOfDimensions;
00245 
00246   for (dim = 0; dim < ndims; dim++)
00247     {
00248     line = append_to_line(line, "[", m, maxlen);
00249     line = append_to_line(line, typedef_info->Dimensions[dim],
00250                           m, maxlen);
00251     line = append_to_line(line, "]", m, maxlen);
00252     }
00253 
00254   type = (type & VTK_PARSE_POINTER_MASK);
00255   if (ndims > 0 && (type & VTK_PARSE_POINTER_LOWMASK) == VTK_PARSE_ARRAY)
00256     {
00257     type = ((type >> 2) & VTK_PARSE_POINTER_MASK);
00258     }
00259   else if (ndims == 1)
00260     {
00261     type = ((type >> 2) & VTK_PARSE_POINTER_MASK);
00262     }
00263 
00264   /* pointers are printed after brackets, and are intentionally
00265    * printed in reverse order as compared to C++ declarations */
00266   while (type)
00267     {
00268     unsigned int bits = (type & VTK_PARSE_POINTER_LOWMASK);
00269     type = ((type >> 2) & VTK_PARSE_POINTER_MASK);
00270 
00271     if (bits == VTK_PARSE_POINTER)
00272       {
00273       line = append_to_line(line, "*", m, maxlen);
00274       }
00275     else if (bits == VTK_PARSE_CONST_POINTER)
00276       {
00277       line = append_to_line(line, "const*", m, maxlen);
00278       }
00279     else
00280       {
00281       line = append_to_line(line, "[]", m, maxlen);
00282       }
00283     }
00284 
00285   if (line[*m-1] != ' ')
00286     {
00287     line = append_to_line(line, " ", m, maxlen);
00288     }
00289 
00290   if ((type & VTK_PARSE_CONST) != 0)
00291     {
00292     line = append_to_line(line, "const ", m, maxlen);
00293     }
00294 
00295   line = append_to_line(line, typedef_info->Class, m, maxlen);
00296   line = append_to_line(line, " ", m, maxlen);
00297 
00298   return line;
00299 }
00300 
00304 static char **append_class_contents(
00305   char **lines, size_t *np, ClassInfo *data,
00306   const char *scope, const char *header_file, const char *module_name)
00307 {
00308   int i;
00309   const char *tmpflags;
00310   char *new_scope;
00311   char *line;
00312   size_t m, n, maxlen;
00313   size_t scope_m, scope_maxlen;
00314 
00315   /* append the name to the scope */
00316   new_scope = 0;
00317   n = 0;
00318   m = 0;
00319   if (scope)
00320     {
00321     n = strlen(scope);
00322     }
00323   if (data->Name)
00324     {
00325     m = strlen(data->Name);
00326     }
00327   if (m && (n || data->Template))
00328     {
00329     scope_maxlen = n + m + 3;
00330     scope_m = 0;
00331     new_scope = (char *)malloc(scope_maxlen);
00332     new_scope[0] = '\0';
00333     if (n)
00334       {
00335       new_scope = append_to_line(new_scope, scope, &scope_m, &scope_maxlen);
00336       new_scope = append_to_line(new_scope, "::", &scope_m, &scope_maxlen);
00337       }
00338     new_scope = append_to_line(new_scope, data->Name, &scope_m, &scope_maxlen);
00339     if (data->Template)
00340       {
00341       new_scope = append_template_to_line(
00342         new_scope, &scope_m, &scope_maxlen, data->Template);
00343       }
00344     scope = new_scope;
00345     }
00346   else if (m)
00347     {
00348     scope = data->Name;
00349     }
00350 
00351   /* start with a buffer of 15 chars and grow from there */
00352   maxlen = 15;
00353   m = 0;
00354   line = (char *)malloc(maxlen);
00355 
00356   /* add a line for each type that is found */
00357   for (i = 0; i < data->NumberOfItems; i++)
00358     {
00359     m = 0;
00360     line[m] = '\0';
00361 
00362     tmpflags = 0;
00363 
00364     if (data->Items[i].Type == VTK_CLASS_INFO ||
00365         data->Items[i].Type == VTK_STRUCT_INFO)
00366       {
00367       ClassInfo *class_info =
00368         data->Classes[data->Items[i].Index];
00369 
00370       line = append_scope_to_line(line, &m, &maxlen, scope);
00371       line = append_class_to_line(line, &m, &maxlen, class_info);
00372       tmpflags = "WRAP_EXCLUDE";
00373       }
00374     else if (data->Items[i].Type == VTK_ENUM_INFO)
00375       {
00376       line = append_scope_to_line(line, &m, &maxlen, scope);
00377       line = append_enum_to_line(line, &m, &maxlen,
00378         data->Enums[data->Items[i].Index]);
00379       }
00380     else if (data->Items[i].Type == VTK_TYPEDEF_INFO)
00381       {
00382       line = append_scope_to_line(line, &m, &maxlen, scope);
00383       line = append_typedef_to_line(line, &m, &maxlen,
00384         data->Typedefs[data->Items[i].Index]);
00385       }
00386     else
00387       {
00388       /* unhandled file element */
00389       continue;
00390       }
00391 
00392     /* append filename and flags */
00393     line = append_trailer(
00394       line, &m, &maxlen, header_file, module_name, tmpflags);
00395 
00396     /* append the line to the file */
00397     lines = append_unique_line(lines, line, np);
00398 
00399     /* for classes, add all typed defined within the class */
00400     if ((data->Items[i].Type == VTK_CLASS_INFO ||
00401          data->Items[i].Type == VTK_STRUCT_INFO) &&
00402         data->Classes[data->Items[i].Index]->Name)
00403       {
00404       lines = append_class_contents(lines, np,
00405         data->Classes[data->Items[i].Index],
00406         scope, header_file, module_name);
00407       }
00408     }
00409 
00410   free(line);
00411 
00412   if (new_scope != 0)
00413     {
00414     free(new_scope);
00415     }
00416 
00417   return lines;
00418 }
00419 
00420 
00424 static char **append_namespace_contents(
00425   char **lines, size_t *np, NamespaceInfo *data, ClassInfo *main_class,
00426   const char *scope, const char *header_file, const char *module_name,
00427   const char *flags)
00428 {
00429   int i;
00430   const char *tmpflags;
00431   char *line;
00432   char *new_scope;
00433   size_t n, m, maxlen;
00434 
00435   /* append the name to the scope */
00436   new_scope = 0;
00437   n = 0;
00438   m = 0;
00439   if (scope)
00440     {
00441     n = strlen(scope);
00442     }
00443   if (data->Name)
00444     {
00445     m = strlen(data->Name);
00446     }
00447   if (m && n)
00448     {
00449     new_scope = (char *)malloc(m + n + 3);
00450     if (n)
00451       {
00452       strncpy(new_scope, scope, n);
00453       new_scope[n++] = ':';
00454       new_scope[n++] = ':';
00455       }
00456     strncpy(&new_scope[n], data->Name, m);
00457     new_scope[n+m] = '\0';
00458     scope = new_scope;
00459     }
00460   else if (m)
00461     {
00462     scope = data->Name;
00463     }
00464 
00465   /* start with a buffer of 15 chars and grow from there */
00466   maxlen = 15;
00467   m = 0;
00468   line = (char *)malloc(maxlen);
00469 
00470   /* add a line for each type that is found */
00471   for (i = 0; i < data->NumberOfItems; i++)
00472     {
00473     tmpflags = 0;
00474     m = 0;
00475     line[m] = '\0';
00476 
00477     if (data->Items[i].Type == VTK_CLASS_INFO ||
00478         data->Items[i].Type == VTK_STRUCT_INFO)
00479       {
00480       ClassInfo *class_info =
00481         data->Classes[data->Items[i].Index];
00482 
00483       /* all but the main class in each file is excluded from wrapping */
00484       tmpflags = "WRAP_EXCLUDE";
00485       if (class_info == main_class)
00486         {
00487         tmpflags = flags;
00488         }
00489 
00490       line = append_scope_to_line(line, &m, &maxlen, scope);
00491       line = append_class_to_line(line, &m, &maxlen, class_info);
00492       }
00493     else if (data->Items[i].Type == VTK_ENUM_INFO)
00494       {
00495       line = append_scope_to_line(line, &m, &maxlen, scope);
00496       line = append_enum_to_line(line, &m, &maxlen,
00497         data->Enums[data->Items[i].Index]);
00498       }
00499     else if (data->Items[i].Type == VTK_TYPEDEF_INFO)
00500       {
00501       line = append_scope_to_line(line, &m, &maxlen, scope);
00502       line = append_typedef_to_line(line, &m, &maxlen,
00503         data->Typedefs[data->Items[i].Index]);
00504       }
00505     else
00506       {
00507       /* unhandled file element */
00508       continue;
00509       }
00510 
00511     /* append filename and flags */
00512     line = append_trailer(
00513       line, &m, &maxlen, header_file, module_name, tmpflags);
00514 
00515     /* append the line to the file */
00516     lines = append_unique_line(lines, line, np);
00517 
00518     /* for classes, add all typed defined within the class */
00519     if ((data->Items[i].Type == VTK_CLASS_INFO ||
00520          data->Items[i].Type == VTK_STRUCT_INFO) &&
00521         data->Classes[data->Items[i].Index]->Name)
00522       {
00523       lines = append_class_contents(lines, np,
00524         data->Classes[data->Items[i].Index],
00525         scope, header_file, module_name);
00526       }
00527 
00528     /* for namespaces, add all types in the namespace */
00529     if (data->Items[i].Type == VTK_NAMESPACE_INFO &&
00530         data->Namespaces[data->Items[i].Index]->Name)
00531       {
00532       lines = append_namespace_contents(lines, np,
00533         data->Namespaces[data->Items[i].Index], 0,
00534         scope, header_file, module_name, "WRAP_EXCLUDE");
00535       }
00536     }
00537 
00538   free(line);
00539 
00540   if (new_scope != 0)
00541     {
00542     free(new_scope);
00543     }
00544 
00545   return lines;
00546 }
00547 
00554 static char **vtkWrapHierarchy_ParseHeaderFile(
00555   FILE *fp, const char *filename, const char *module_name,
00556   const char *flags, char **lines)
00557 {
00558   FileInfo *data;
00559   const char *header_file;
00560   size_t k, n;
00561 
00562   /* start with just a single output line and grow from there */
00563   if (lines == NULL)
00564     {
00565     lines = (char **)malloc(sizeof(char *));
00566     lines[0] = NULL;
00567     }
00568 
00569   /* always ignore BTX markers when building hierarchy files */
00570   vtkParse_SetIgnoreBTX(1);
00571 
00572   /* the "concrete" flag doesn't matter, just set to zero */
00573   data = vtkParse_ParseFile(filename, fp, stderr);
00574 
00575   if (!data)
00576     {
00577     free(lines);
00578     return 0;
00579     }
00580 
00581   /* find the last line in "lines" */
00582   n = 0;
00583   while (lines[n] != NULL)
00584     {
00585     n++;
00586     }
00587 
00588   k = strlen(data->FileName) - 1;
00589   while (k > 0 && data->FileName[k-1] != '/' && data->FileName[k-1] != '\\')
00590     {
00591     k--;
00592     }
00593   header_file = &data->FileName[k];
00594 
00595   /* append the file contents to the output */
00596   lines = append_namespace_contents(
00597     lines, &n, data->Contents, data->MainClass, 0,
00598     header_file, module_name, flags);
00599 
00600   vtkParse_Free(data);
00601 
00602   return lines;
00603 }
00604 
00608 static char **vtkWrapHierarchy_ReadHierarchyFile(FILE *fp, char **lines)
00609 {
00610   char *line;
00611   size_t maxlen = 15;
00612   size_t i, n;
00613 
00614   line = (char *)malloc(maxlen);
00615 
00616   if (lines == NULL)
00617     {
00618     lines = (char **)malloc(sizeof(char *));
00619     lines[0] = NULL;
00620     }
00621 
00622   while (fgets(line, (int)maxlen, fp))
00623     {
00624     n = strlen(line);
00625 
00626     /* if buffer not long enough, increase it */
00627     while (n == maxlen-1 && line[n-1] != '\n' && !feof(fp))
00628       {
00629       maxlen *= 2;
00630       line = (char *)realloc(line, maxlen);
00631       if (!fgets(&line[n], (int)(maxlen-n), fp)) { break; }
00632       n += strlen(&line[n]);
00633       }
00634 
00635     while (n > 0 && isspace(line[n-1]))
00636       {
00637       n--;
00638       }
00639     line[n] = '\0';
00640 
00641     if (line[0] == '\0')
00642       {
00643       continue;
00644       }
00645 
00646     for (i = 0; lines[i] != NULL; i++)
00647       {
00648       if (strcmp(line, lines[i]) == 0)
00649         {
00650         break;
00651         }
00652       }
00653 
00654     if (lines[i] == NULL)
00655       {
00656       /* allocate more memory if n+1 is a power of two */
00657       if (((i+1) & i) == 0)
00658         {
00659         lines = (char **)realloc(lines, (i+1)*2*sizeof(char *));
00660         }
00661 
00662       lines[i] = (char *)malloc(n+1);
00663       strcpy(lines[i], line);
00664       lines[i+1] = NULL;
00665       }
00666     }
00667 
00668   free(line);
00669 
00670   if (!feof(fp))
00671     {
00672     free(lines);
00673     return 0;
00674     }
00675 
00676   return lines;
00677 }
00678 
00682 static int vtkWrapHierarchy_CompareHierarchyFile(FILE *fp, char *lines[])
00683 {
00684   unsigned char *matched;
00685   char *line;
00686   size_t maxlen = 15;
00687   size_t i, n;
00688 
00689   line = (char *)malloc(maxlen);
00690 
00691   for (i = 0; lines[i] != NULL; i++) { ; };
00692   matched = (unsigned char *)malloc(i);
00693   memset(matched, 0, i);
00694 
00695   while (fgets(line, (int)maxlen, fp))
00696     {
00697     n = strlen(line);
00698 
00699     /* if buffer not long enough, increase it */
00700     while (n == maxlen-1 && line[n-1] != '\n' && !feof(fp))
00701       {
00702       maxlen *= 2;
00703       line = (char *)realloc(line, maxlen);
00704       if (!fgets(&line[n], (int)(maxlen-n), fp)) { break; }
00705       n += strlen(&line[n]);
00706       }
00707 
00708     while (n > 0 && isspace(line[n-1]))
00709       {
00710       n--;
00711       }
00712     line[n] = '\0';
00713 
00714     if (line[0] == '\0')
00715       {
00716       continue;
00717       }
00718 
00719     for (i = 0; lines[i] != NULL; i++)
00720       {
00721       if (strcmp(line, lines[i]) == 0)
00722         {
00723         break;
00724         }
00725       }
00726 
00727     if (lines[i] == NULL)
00728       {
00729       free(matched);
00730       return 0;
00731       }
00732 
00733     matched[i] = 1;
00734     }
00735 
00736   for (i = 0; lines[i] != NULL; i++)
00737     {
00738     if (matched[i] == 0)
00739       {
00740       free(matched);
00741       return 0;
00742       }
00743     }
00744 
00745   free(line);
00746   free(matched);
00747 
00748   if (!feof(fp))
00749     {
00750     return 0;
00751     }
00752 
00753   return 1;
00754 }
00755 
00759 static int vtkWrapHierarchy_WriteHierarchyFile(FILE *fp, char *lines[])
00760 {
00761   size_t i;
00762 
00763   for (i = 0; lines[i] != NULL; i++)
00764     {
00765     if (fprintf(fp, "%s\n", lines[i]) < 0)
00766       {
00767       return 0;
00768       }
00769     }
00770 
00771   return 1;
00772 }
00773 
00777 static char **vtkWrapHierarchy_TryParseHeaderFile(
00778   const char *file_name, const char *module_name,
00779   const char *flags, char **lines)
00780 {
00781   FILE *input_file;
00782 
00783   input_file = fopen(file_name, "r");
00784 
00785   if (!input_file)
00786     {
00787     fprintf(stderr, "vtkWrapHierarchy: couldn't open file %s\n",
00788             file_name);
00789     exit(1);
00790     }
00791 
00792   lines = vtkWrapHierarchy_ParseHeaderFile(
00793                  input_file, file_name, module_name, flags, lines);
00794 
00795   if (!lines)
00796     {
00797     fclose(input_file);
00798     exit(1);
00799     }
00800   fclose(input_file);
00801 
00802   return lines;
00803 }
00804 
00808 static char **vtkWrapHierarchy_TryReadHierarchyFile(
00809   const char *file_name, char **lines)
00810 {
00811   FILE *input_file;
00812 
00813   input_file = fopen(file_name, "r");
00814   if (!input_file)
00815     {
00816     fprintf(stderr, "vtkWrapHierarchy: couldn't open file %s\n",
00817             file_name);
00818     exit(1);
00819     }
00820 
00821   lines = vtkWrapHierarchy_ReadHierarchyFile(input_file, lines);
00822   if (!lines)
00823     {
00824     fclose(input_file);
00825     fprintf(stderr, "vtkWrapHierarchy: error reading file %s\n",
00826             file_name);
00827     exit(1);
00828     }
00829   fclose(input_file);
00830 
00831   return lines;
00832 }
00833 
00837 static int vtkWrapHierarchy_TryWriteHierarchyFile(
00838   const char *file_name, char *lines[])
00839 {
00840   FILE *output_file;
00841   int matched = 0;
00842 
00843   output_file = fopen(file_name, "r");
00844   if (output_file && vtkWrapHierarchy_CompareHierarchyFile(output_file, lines))
00845     {
00846     matched = 1;
00847     }
00848   if (output_file)
00849     {
00850     fclose(output_file);
00851     }
00852 
00853   if (!matched)
00854     {
00855     int tries = 1;
00856     output_file = fopen(file_name, "w");
00857     while (!output_file && tries < 5)
00858       {
00859       /* There are two CMAKE_CUSTOM_COMMANDS for vtkWrapHierarchy,
00860        * make sure they do not collide. */
00861       tries++;
00862 #ifdef _WIN32
00863       Sleep(1000);
00864 #else
00865       sleep(1);
00866 #endif
00867       output_file = fopen(file_name, "r+");
00868       if (output_file &&
00869           vtkWrapHierarchy_CompareHierarchyFile(output_file, lines))
00870         {
00871         /* if the contents match, no need to write it */
00872         fclose(output_file);
00873         return 0;
00874         }
00875       if (output_file)
00876         {
00877         /* close and open in order to truncate the file */
00878         fclose(output_file);
00879         output_file = fopen(file_name, "w");
00880         }
00881       }
00882     if (!output_file)
00883       {
00884       fprintf(stderr, "vtkWrapHierarchy: tried %i times to write %s\n",
00885               tries, file_name);
00886       exit(1);
00887       }
00888     if (!vtkWrapHierarchy_WriteHierarchyFile(output_file, lines))
00889       {
00890       fclose(output_file);
00891       fprintf(stderr, "vtkWrapHierarchy: error writing file %s\n",
00892               file_name);
00893       exit(1);
00894       }
00895     fclose(output_file);
00896     }
00897 
00898   return 0;
00899 }
00900 
00901 static int string_compare(const void *vp1, const void *vp2)
00902 {
00903   return strcmp(*(const char **)vp1, *(const char **)vp2);
00904 }
00905 
00906 int main(int argc, char *argv[])
00907 {
00908   int usage_error = 0;
00909   char *output_filename = 0;
00910   int i, argi;
00911   size_t j, n;
00912   char **lines = 0;
00913   char **files = 0;
00914   char *flags;
00915   char *module_name;
00916   char *option;
00917   char *optionarg;
00918   const char *optionargval;
00919 
00920   /* parse command-line options */
00921   for (argi = 1; argi < argc && argv[argi][0] == '-'; argi++)
00922     {
00923     if (strncmp(argv[argi], "-o", 2) == 0 ||
00924         strncmp(argv[argi], "-I", 2) == 0 ||
00925         strncmp(argv[argi], "-D", 2) == 0 ||
00926         strncmp(argv[argi], "-U", 2) == 0)
00927       {
00928       option = argv[argi];
00929       optionarg = &argv[argi][2];
00930       if (argv[argi][2] == '\0')
00931         {
00932         argi++;
00933         if (argi >= argc || argv[argi][0] == '-')
00934           {
00935           usage_error = 1;
00936           break;
00937           }
00938         optionarg = argv[argi];
00939         }
00940       if (strncmp(option, "-o", 2) == 0)
00941         {
00942         output_filename = optionarg;
00943         }
00944       else if (strncmp(option, "-I", 2) == 0)
00945         {
00946         vtkParse_IncludeDirectory(optionarg);
00947         }
00948       else if (strncmp(option, "-D", 2) == 0)
00949         {
00950         optionargval = "1";
00951         j = 0;
00952         while (optionarg[j] != '\0' && optionarg[j] != '=') { j++; }
00953         if (optionarg[j] == '=')
00954           {
00955           optionargval = &optionarg[j+1];
00956           }
00957         vtkParse_DefineMacro(optionarg, optionargval);
00958         }
00959       else if (strncmp(option, "-U", 2) == 0)
00960         {
00961         vtkParse_UndefineMacro(optionarg);
00962         }
00963       }
00964     }
00965 
00966   if (usage_error || !output_filename || argc - argi < 1)
00967     {
00968     fprintf(stderr,
00969             "Usage: %s -o output_file data_file [files_to_merge]\n",
00970             argv[0]);
00971     exit(1);
00972     }
00973 
00974   /* read the data file */
00975   files = vtkWrapHierarchy_TryReadHierarchyFile(argv[argi++], files);
00976 
00977   /* read in all the prior files */
00978   while (argi < argc)
00979     {
00980     lines = vtkWrapHierarchy_TryReadHierarchyFile(argv[argi++], lines);
00981     }
00982 
00983   /* merge the files listed in the data file */
00984   for (i = 0; files[i] != NULL; i++)
00985     {
00986     /* look for semicolon that marks the module name */
00987     module_name = files[i];
00988     while(*module_name != ';' && *module_name != '\0') { module_name++; };
00989     if (*module_name == ';') { *module_name++ = '\0'; }
00990 
00991     /* look for semicolon that marks start of flags */
00992     flags = module_name;
00993     while(*flags != ';' && *flags != '\0') { flags++; };
00994     if (*flags == ';') { *flags++ = '\0'; }
00995 
00996     lines = vtkWrapHierarchy_TryParseHeaderFile(
00997       files[i], module_name, flags, lines);
00998     }
00999 
01000   /* sort the lines to ease lookups in the file */
01001   for (n = 0; lines[n]; n++) { ; };
01002   qsort(lines, n, sizeof(char *), &string_compare);
01003 
01004   /* write the file, if it has changed */
01005   vtkWrapHierarchy_TryWriteHierarchyFile(output_filename, lines);
01006 
01007   for (j = 0; j < n; j++)
01008     {
01009     free(lines[j]);
01010     }
01011 
01012   free(files);
01013   free(lines);
01014   return 0;
01015 }