home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / gfx / 3d / irit / docs / progman.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-09  |  35.1 KB  |  1,043 lines

  1. /*****************************************************************************
  2. *   Programmer's manual processor of IRIT- a 3d solid modeller.             *
  3. ******************************************************************************
  4. * Usage:                                     *
  5. *  prgmman [-m] [-t] [-l] [-o OutFileName] [-z] [InFileNames]             *
  6. *                                         *
  7. * Written by:  Gershon Elber                Ver 1.0, Oct. 1994   *
  8. *****************************************************************************/
  9.  
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include <string.h>
  13. #include "irit_sm.h"
  14. #include "imalloc.h"
  15.  
  16. #define MAX_DESCRIPTION        1000
  17. #define MAX_PARAM_DESCRIPTION    100
  18. #define MAX_PARAMETERS        100
  19. #define MAX_KEYWORDS        100
  20. #define MAX_INDENTATION        20
  21.  
  22. typedef enum {
  23.     UNDEFINED_DOC_PROCESS = 0,
  24.  
  25.     PLAIN_TEXT_DOCS,
  26.     LATEX_DOCS
  27. } DocProcessType;
  28.  
  29. typedef struct ParamStruct {
  30.     char *ParamName;
  31.     char **Description;
  32. } ParamStruct;
  33.  
  34. typedef struct FunctionStruct {
  35.     struct FunctionStruct *Pnext;
  36.     char **Description;
  37.     struct ParamStruct **Parameters;
  38.     struct ParamStruct *RetVal;
  39.     char **Keywords;
  40.     char **Prototype;
  41.     char *FileName;
  42.     int LineNumber;
  43. } FunctionStruct;
  44.  
  45. static struct FunctionStruct
  46.     *GlblFuncList = NULL;
  47.  
  48. static char **GetFuncDescription(FILE *Fin, int *LineNum);
  49. static ParamStruct **GetFuncParameters(FILE *Fin, int *LineNum);
  50. static ParamStruct *GetFuncRetVal(FILE *Fin, int *LineNum);
  51. static char **GetFuncKeywords(FILE *Fin, int *LineNum);
  52. static char **GetFuncPrototype(FILE *Fin, int *LineNum);
  53. static void ProcessFiles(FILE *Fin, char *FileName, int MoreInfo);
  54. static char *StrdupTabToSpaces(char*Line);
  55. static char *ConvertTabsToSpaces(char*Line);
  56. static char *FilterEOLMV(char *Line, int Skip);
  57. static char *FilterFirstNonSpace(char *Line);
  58. static char *FilterCRLF(char *Line, int Skip);
  59. static void DumpInfoText(FILE *Fout);
  60. static void PutLatexString(FILE *Fout, char *Str);
  61. static void DumpDescriptionForLatex(FILE *Fout, char **Desc);
  62. static void DumpInfoLatex(FILE *Fout);
  63.  
  64. #if defined(ultrix) && defined(mips)
  65. static int FuncQSortComp(VoidPtr VPoly1, VoidPtr VPoly2);
  66. #else
  67. static int FuncQSortComp(const VoidPtr VPoly1, const VoidPtr VPoly2);
  68. #endif /* ultrix && mips (no const support) */
  69.  
  70. /*****************************************************************************
  71. * DESCRIPTION:                                                               M
  72. * Main module - process command line options.                     M
  73. *                                                                            *
  74. * PARAMETERS:                                                                M
  75. *   argc, argv: command line options.                         M
  76. *                                                                            *
  77. * RETURN VALUE:                                                              M
  78. *   void                                                                     M
  79. *                                                                            *
  80. * KEYWORDS:                                                                  M
  81. *   main                                                                     M
  82. *****************************************************************************/
  83. void main(int argc, char **argv)
  84. {
  85.     int MoreInfo = FALSE;
  86.     FILE
  87.     *Fin = stdin,
  88.     *Fout = stdout;
  89.     DocProcessType
  90.     OutputDocType = UNDEFINED_DOC_PROCESS;
  91.  
  92.     while (argc > 1) {
  93.     if (strcmp(argv[1], "-t") == 0) {
  94.         OutputDocType = PLAIN_TEXT_DOCS;
  95.         argc--;
  96.         argv++;
  97.     }
  98.     else if (strcmp(argv[1], "-l") == 0) {
  99.         OutputDocType = LATEX_DOCS;
  100.         argc--;
  101.         argv++;
  102.     }
  103.     else if (strcmp(argv[1], "-m") == 0) {
  104.         MoreInfo = TRUE;
  105.         argc--;
  106.         argv++;
  107.     }
  108.     else if (strcmp(argv[1], "-o") == 0) {
  109.         if ((Fout = fopen(argv[2], "w")) == NULL) {
  110.         fprintf(stderr, "Failed to open \"%s\".\n", argv[2]);
  111.         exit(1);
  112.         }
  113.         argc -= 2;
  114.         argv += 2;
  115.     }
  116.     else if (strcmp(argv[1], "-z") == 0) {
  117.         fprintf(stderr, "Usage: PrgmMan [-t] [-l] [-o OutFileName] [-z] [InFileName].\n");
  118.         exit(0);
  119.     }
  120.     else
  121.         break;
  122.     }
  123.  
  124.  
  125.     if (OutputDocType == UNDEFINED_DOC_PROCESS) {
  126.     fprintf(stderr, "One of [-t] [-l] [-h] must be specified.\n");
  127.     exit(1);
  128.     }
  129.  
  130.     if (argc > 1) {
  131.     while (argc > 1) {
  132.         fprintf(stderr, "Processing %s\n", argv[1]);
  133.         if ((Fin = fopen(argv[1], "r")) == NULL) {
  134.         fprintf(stderr, "Failed to open \"%s\".\n", argv[2]);
  135.         argc--;
  136.         argv++;
  137.         continue;
  138.         }
  139.  
  140.         ProcessFiles(Fin, argv[1], MoreInfo);
  141.         fclose(Fin);
  142.         argc--;
  143.         argv++;
  144.     }
  145.     }
  146.     else /* Only stdin. */
  147.     ProcessFiles(Fin, "stdin", OutputDocType);
  148.  
  149.     switch( OutputDocType) {
  150.     case LATEX_DOCS:
  151.         DumpInfoLatex(Fout);
  152.         break;
  153.     case PLAIN_TEXT_DOCS:
  154.     default:
  155.         DumpInfoText(Fout);
  156.         break;
  157.     }
  158.  
  159.     fclose(Fout);
  160.  
  161.     exit(0);
  162. }
  163.  
  164. /*****************************************************************************
  165. * DESCRIPTION:                                                               *
  166. * Validates input line during a comment parsing. Any Line that has non space *
  167. * characters between the first and the last non space characters is valid.   *
  168. *                                                                            *
  169. * PARAMETERS:                                                                *
  170. *   Line:      To validate.                                             *
  171. *                                                                            *
  172. * RETURN VALUE:                                                              *
  173. *   int:       TRUE if valid, FALSE otherwise                                *
  174. *****************************************************************************/
  175. static int ValidateLine(char *Line)
  176. {
  177.     char *p;
  178.     int Count = 0;
  179.  
  180.     for (p = Line; *p != 0; p++)
  181.     if (!isspace(*p))
  182.         Count++;
  183.     
  184.     return Count > 2;
  185. }
  186.  
  187. /*****************************************************************************
  188. * DESCRIPTION:                                                               *
  189. * Read in the DESCRIPTION portion of a function comment.             *
  190. *                                                                            *
  191. * PARAMETERS:                                                                *
  192. *   Fin:           File to read from, probably a c source file.              *
  193. *                                                                            *
  194. * RETURN VALUE:                                                              *
  195. *   char **:       NULL terminated array of strings. No processing is done   *
  196. *                  the read lines.                         *
  197. *****************************************************************************/
  198. static char **GetFuncDescription(FILE *Fin, int *LineNum)
  199. {
  200.     char *Desc[MAX_DESCRIPTION], Line[LINE_LEN_LONG];
  201.     int LCount = 0;
  202.  
  203.     while (fgets(Line, LINE_LEN_LONG - 1, Fin) != NULL) {
  204.     (*LineNum)++;
  205.  
  206.     if (strncmp(Line, "* PARAMETERS:", 12) == 0) {
  207.         int i;
  208.         char **RetVal;
  209.  
  210.         RetVal = (char **) IritMalloc((LCount + 1) * sizeof(char *));
  211.         for (i = 0; i < LCount; i++)
  212.         RetVal[i] = Desc[i];
  213.         for (i = LCount - 1; i >= 0; i--)
  214.         if (ValidateLine(RetVal[i])) {
  215.             i++;
  216.             break;
  217.         }
  218.  
  219.         RetVal[i] = NULL;
  220.         return RetVal;
  221.     }
  222.     else if (strstr(Line, "*/") != NULL) {
  223.         fprintf(stderr,
  224.             "\tLine %d: Premature end of comment in file description\n",
  225.             *LineNum);
  226.         return NULL;
  227.     }
  228.     else {
  229.         if (LCount >= MAX_DESCRIPTION) {
  230.         fprintf(stderr,
  231.             "\tLine %d: Maximum lines for description (%d) reached\n",
  232.             *LineNum, LCount);
  233.         return NULL;
  234.         }
  235.         
  236.         Desc[LCount++] = StrdupTabToSpaces(Line);
  237.     }
  238.     }
  239.  
  240.     return NULL;
  241. }
  242.  
  243. /*****************************************************************************
  244. * DESCRIPTION:                                                               *
  245. * Read in the PARAMETERS portion of a function comment.                 *
  246. *                                                                            *
  247. * PARAMETERS:                                                                *
  248. *   Fin:           File to read from, probably a c source file.              *
  249. *   LineNum:       To get/update line number in file.                 *
  250. *                                                                            *
  251. * RETURN VALUE:                                                              *
  252. *   ParamStruct **:       NULL terminated array of ParamStruct's.         *
  253. *****************************************************************************/
  254. static ParamStruct **GetFuncParameters(FILE *Fin, int *LineNum)
  255. {
  256.     ParamStruct *Params[MAX_PARAMETERS];
  257.     char Line[LINE_LEN_LONG], *ParamDesc[MAX_PARAM_DESCRIPTION];
  258.     int PDescCount = 0,
  259.     FirstInvalid = TRUE,
  260.     PCount = 0;
  261.  
  262.     while (fgets(Line, LINE_LEN_LONG - 1, Fin) != NULL) {
  263.     (*LineNum)++;
  264.  
  265.     if (!ValidateLine(Line)) {
  266.         if (FirstInvalid) {
  267.         FirstInvalid = FALSE;
  268.         continue;
  269.         }
  270.         else {
  271.         fprintf(stderr,
  272.             "\tLine %d: Empty line in middle of parameter\n",
  273.             *LineNum);
  274.         return NULL;
  275.         }
  276.     }
  277.  
  278.     if (strstr(Line, "*/") != NULL) {
  279.         fprintf(stderr,
  280.             "\tLine %d: Premature end of comment in parameters\n",
  281.             *LineNum);
  282.         return NULL;
  283.     }
  284.     else {
  285.         if (PCount - 1 >= MAX_PARAMETERS) {
  286.         fprintf(stderr,
  287.             "\tLine %d: Maximum parameters (%d) reached\n",
  288.             *LineNum, PCount);
  289.         return NULL;
  290.         }
  291.  
  292.         if ((strchr(Line, ':') != NULL ||
  293.          strncmp(FilterFirstNonSpace(Line), "None", 4) == 0 ||
  294.          strncmp(Line, "* RETURN VALUE:", 14) == 0) &&
  295.         PDescCount != 0) {
  296.         int i;
  297.         char *p, *q;
  298.         ParamStruct
  299.             *Param = (ParamStruct *) IritMalloc(sizeof(ParamStruct));
  300.  
  301.         /* We have a previous variable to place. */
  302.         Params[PCount++] = Param;
  303.  
  304.         if ((p = strchr(ParamDesc[0], ':')) == NULL &&
  305.             strncmp(FilterFirstNonSpace(ParamDesc[0]), "None", 4) != 0) {
  306.             fprintf(stderr,
  307.                 "\tLine %d: Colon, ':', was expected for parameter\n",
  308.                 *LineNum);
  309.             return NULL;
  310.         }
  311.         Param -> Description = (char **)
  312.             IritMalloc((PDescCount + 1) * sizeof(char*));
  313.         if (strncmp(FilterFirstNonSpace(ParamDesc[0]), "None", 4) == 0) {
  314.             Param -> Description = NULL;
  315.             Param -> ParamName = NULL;
  316.         }
  317.         else {
  318.             Param -> Description[0] = StrdupTabToSpaces(p + 1);
  319.             for (i = 1; i < PDescCount; i++)
  320.             Param -> Description[i] = ParamDesc[i];
  321.             Param -> Description[PDescCount] = NULL;
  322.  
  323.             for (p = &ParamDesc[0][1]; *p != 0 && isspace(*p); p++);
  324.             movmem(p, ParamDesc[0], strlen(p) + 1);
  325.             p = strchr(ParamDesc[0], ':');
  326.             *p = 0;
  327.             Param -> ParamName = ParamDesc[0];
  328.             PDescCount = 0;
  329.         }
  330.         }
  331.  
  332.         if (strncmp(Line, "* RETURN VALUE:", 14) == 0) {
  333.         int i;
  334.         ParamStruct **RetVal;
  335.  
  336.         RetVal = (ParamStruct **)
  337.             IritMalloc((PCount + 1) * sizeof(ParamStruct *));
  338.         for (i = 0; i < PCount; i++)
  339.             RetVal[i] = Params[i];
  340.         RetVal[PCount] = NULL;
  341.         return RetVal;
  342.         }
  343.  
  344.         ParamDesc[PDescCount++] = StrdupTabToSpaces(Line);
  345.     }
  346.     }
  347.  
  348.     return NULL;
  349. }
  350.  
  351. /*****************************************************************************
  352. * DESCRIPTION:                                                               *
  353. * Read in the RETURN VALUE portion of a function comment, if any.         *
  354. *                                                                            *
  355. * PARAMETERS:                                                                *
  356. *   Fin:           File to read from, probably a c source file.              *
  357. *   LineNum:       To get/update line number in file.                 *
  358. *                                                                            *
  359. * RETURN VALUE:                                                              *
  360. *   ParamStruct *:   A ParamStruct, or NULL if no return value.             *
  361. *****************************************************************************/
  362. static ParamStruct *GetFuncRetVal(FILE *Fin, int *LineNum)
  363. {
  364.     char Line[LINE_LEN_LONG], *ParamDesc[MAX_PARAM_DESCRIPTION];
  365.     int PDescCount = 0,
  366.     FirstInvalid = TRUE;
  367.  
  368.     if (fgets(Line, LINE_LEN_LONG - 1, Fin) != NULL) {
  369.     char *p, *q;
  370.     ParamStruct
  371.         *Param = (ParamStruct *) IritMalloc(sizeof(ParamStruct));
  372.  
  373.     (*LineNum)++;
  374.  
  375.     if (!ValidateLine(Line)) {
  376.         fprintf(stderr,
  377.             "\tLine %d: Empty line in middle of return value\n",
  378.             *LineNum);
  379.         return NULL;
  380.     }
  381.  
  382.     if ((p = strchr(Line, ':')) == NULL && strstr(Line, "void") == NULL) {
  383.         fprintf(stderr,
  384.             "\tLine %d: Colon, ':', was expected for returned value\n",
  385.             *LineNum);
  386.         return NULL;
  387.     }
  388.  
  389.     ParamDesc[PDescCount++] = StrdupTabToSpaces(Line);
  390.  
  391.     while (fgets(Line, LINE_LEN_LONG - 1, Fin) != NULL) {
  392.         (*LineNum)++;
  393.  
  394.         if (!ValidateLine(Line)) {
  395.         if (FirstInvalid) {
  396.             FirstInvalid = FALSE;
  397.             continue;
  398.         }
  399.         else {
  400.             fprintf(stderr,
  401.                 "\tLine %d: Empty line in middle of return value\n",
  402.                 *LineNum);
  403.             return NULL;
  404.         }
  405.         }
  406.  
  407.         if (strncmp(Line, "* KEYWORDS:", 10) == 0) {
  408.         int i;
  409.         ParamStruct
  410.             *Param = (ParamStruct *) IritMalloc(sizeof(ParamStruct));
  411.  
  412.         Param -> Description = (char **)
  413.             IritMalloc((PDescCount + 1) * sizeof(char*));
  414.         for (i = 0; i < PDescCount; i++)
  415.             Param -> Description[i] = ParamDesc[i];
  416.         Param -> Description[PDescCount] = NULL;
  417.         return Param;
  418.         }
  419.         else if (strstr(Line, "*/") != NULL) {
  420.         fprintf(stderr,
  421.             "\tLine %d: Premature end of comment in return value\n",
  422.             *LineNum);
  423.         return NULL;
  424.         }
  425.         else
  426.         ParamDesc[PDescCount++] = StrdupTabToSpaces(Line);
  427.     }
  428.     }
  429.  
  430.     return NULL;
  431. }
  432.  
  433. /*****************************************************************************
  434. * DESCRIPTION:                                                               *
  435. * Read in the KEYWORDS portion of a function comment, if any             *
  436. *                                                                            *
  437. * PARAMETERS:                                                                *
  438. *   Fin:           File to read from, probably a c source file.              *
  439. *   LineNum:       To get/update line number in file.                 *
  440. *                                                                            *
  441. * RETURN VALUE:                                                              *
  442. *   char **:       NULL terminated array of strings, or NULL if none.         *
  443. *****************************************************************************/
  444. static char **GetFuncKeywords(FILE *Fin, int *LineNum)
  445. {
  446.     char *Keywords[MAX_KEYWORDS];
  447.     char Line[LINE_LEN_LONG], CrntKeyword[LINE_LEN];
  448.     int KCount = 0;
  449.  
  450.     CrntKeyword[0] = 0;
  451.     while (fgets(Line, LINE_LEN_LONG - 1, Fin) != NULL) {
  452.     (*LineNum)++;
  453.  
  454.     if (strncmp(Line, "************", 10) == 0 ||
  455.         strstr(Line, "*/") != NULL ||
  456.         !ValidateLine(Line)) {
  457.         int i;
  458.         char **RetVal;
  459.  
  460.         if (strlen(CrntKeyword) > 0) {
  461.         char *p;
  462.  
  463.         for (p = CrntKeyword; *p != 0 && isspace(*p); p++);
  464.         Keywords[KCount++] = StrdupTabToSpaces(p);
  465.         CrntKeyword[0] = 0;
  466.         }
  467.  
  468.         RetVal = (char **) IritMalloc((KCount + 1) * sizeof(char *));
  469.         for (i = 0; i < KCount; i++)
  470.         RetVal[i] = Keywords[i];
  471.         RetVal[KCount] = NULL;
  472.         return RetVal;
  473.     }
  474.     else {
  475.         char *p, *q;
  476.  
  477.         FilterEOLMV(Line, 0);
  478.  
  479.         q = &Line[4];
  480.  
  481.         do {
  482.         p = strchr(q, ',');
  483.  
  484.         if (p)
  485.             *p++ = 0;
  486.  
  487.         if (strlen(CrntKeyword) > 0)
  488.             strcat(CrntKeyword, " ");
  489.         strcat(CrntKeyword, q);
  490.         if (p != NULL) {
  491.             for (q = CrntKeyword; *q != 0 && isspace(*q); q++);
  492.             Keywords[KCount++] = StrdupTabToSpaces(q);
  493.             CrntKeyword[0] = 0;
  494.         }
  495.  
  496.         q = p;
  497.         }
  498.         while (p != NULL);
  499.     }
  500.     }
  501.  
  502.     return NULL;
  503. }
  504.  
  505. /*****************************************************************************
  506. * DESCRIPTION:                                                               *
  507. * Read in the PROTOTYPE portion of a function.                     *
  508. *                                                                            *
  509. * PARAMETERS:                                                                *
  510. *   Fin:           File to read from, probably a c source file.              *
  511. *   LineNum:       To get/update line number in file.                 *
  512. *                                                                            *
  513. * RETURN VALUE:                                                              *
  514. *   char **:       NULL terminated array of strings.                  *
  515. *****************************************************************************/
  516. static char **GetFuncPrototype(FILE *Fin, int *LineNum)
  517. {
  518.     char *Prototype[MAX_KEYWORDS];
  519.     char Line[LINE_LEN_LONG];
  520.     int PCount = 0;
  521.  
  522.     while (fgets(Line, LINE_LEN_LONG - 1, Fin) != NULL) {
  523.     (*LineNum)++;
  524.     if (strstr(Line, "{") != NULL) {
  525.         int i;
  526.         char **RetVal;
  527.  
  528.         RetVal = (char **) IritMalloc((PCount + 1) * sizeof(char *));
  529.         for (i = 0; i < PCount; i++)
  530.         RetVal[i] = Prototype[i];
  531.         RetVal[PCount] = NULL;
  532.         return RetVal;
  533.     }
  534.     else {
  535.         Prototype[PCount++] = StrdupTabToSpaces(Line);
  536.     }
  537.     }
  538.  
  539.     return NULL;
  540. }
  541.  
  542. /*****************************************************************************
  543. * DESCRIPTION:                                                               *
  544. * Reads input file, process comment of external functions, and save them as  *
  545. * a linked list to be sorted out.                         *
  546. *                                                                            *
  547. * PARAMETERS:                                                                *
  548. *   Fin:           File to read from, probably a c source file.              *
  549. *   OutputDocType: Type of output - tex, doc, etc.                           *
  550. *                                                                            *
  551. * RETURN VALUE:                                                              *
  552. *   void                                                                     *
  553. *****************************************************************************/
  554. static void ProcessFiles(FILE *Fin, char *FileName, int MoreInfo)
  555. {
  556.     char Line[LINE_LEN_LONG];
  557.     int LineNum = 0;
  558.  
  559.     /* Skip file header comments: */
  560.     while (fgets(Line, LINE_LEN_LONG - 1, Fin) != NULL) {
  561.     LineNum++;
  562.     if (strstr(Line, "/*") == NULL)
  563.         break;
  564.     }
  565.  
  566.     while (fgets(Line, LINE_LEN_LONG - 1, Fin) != NULL) {
  567.     LineNum++;
  568.     if (strncmp(Line, "/*********", 10) == 0) {
  569.         FunctionStruct *Func;
  570.  
  571.         /* We have a beginning of a comment. */
  572.         if (fgets(Line, LINE_LEN_LONG - 1, Fin) != NULL &&
  573.         strncmp(Line, "* DESCRIPTION:", 14) != 0) {
  574.         LineNum++;
  575.         fprintf(stderr, "\tLine %d: Unrecognized comment format\n",
  576.             LineNum);
  577.         continue;
  578.         }
  579.         LineNum++;
  580.  
  581.         /* If it is a static function - ignore. */
  582.         if (strchr(&Line[strlen(Line) - 3], 'M') == NULL)
  583.         continue;
  584.  
  585.         /* We found a comment of an external function - get its data. */
  586.         Func = (FunctionStruct *) IritMalloc(sizeof(FunctionStruct));
  587.         if ((Func -> Description = GetFuncDescription(Fin, &LineNum)) &&
  588.         (Func -> Parameters = GetFuncParameters(Fin, &LineNum)) &&
  589.         (Func -> RetVal = GetFuncRetVal(Fin, &LineNum)) &&
  590.         (Func -> Keywords = GetFuncKeywords(Fin, &LineNum)) &&
  591.         (Func -> Prototype = GetFuncPrototype(Fin, &LineNum))) {
  592.         if (strncmp(FileName, "../", 3) == 0)
  593.             Func -> FileName = IritStrdup(&FileName[3]);
  594.         else
  595.             Func -> FileName = IritStrdup(FileName);
  596.         Func -> LineNumber = LineNum - 1;
  597.         if (Func -> Parameters[0] -> ParamName == NULL) {
  598.             /* No parameters. */
  599.             IritFree(Func -> Parameters[0]);
  600.             Func -> Parameters = NULL;
  601.         }
  602.         if (MoreInfo)
  603.             fprintf(stderr, "\t\tLine %d: %s\n",
  604.                 LineNum - 1, *(Func -> Keywords));
  605.         Func -> Pnext = GlblFuncList;
  606.         GlblFuncList = Func;
  607.         }
  608.     }
  609.     }
  610. }
  611.  
  612. /*****************************************************************************
  613. * DESCRIPTION:                                                               *
  614. * A comparison function between two func structures by name.             *
  615. *                                                                            *
  616. * PARAMETERS:                                                                *
  617. *   VPoly1, VPoly2:  Two pointers to structures.                             *
  618. *                                                                            *
  619. * RETURN VALUE:                                                              *
  620. *   int:   >0, 0, or <0 as the relation between the two polygons.            *
  621. *****************************************************************************/
  622. #if defined(ultrix) && defined(mips)
  623. static int FuncQSortComp(VoidPtr Func1, VoidPtr Func2)
  624. #else
  625. static int FuncQSortComp(const VoidPtr Func1, const VoidPtr Func2)
  626. #endif /* ultrix && mips (no const support) */
  627. {
  628.     return strcmp(*((*((FunctionStruct **) Func1)) -> Keywords),
  629.           *((*((FunctionStruct **) Func2)) -> Keywords));
  630. }
  631.  
  632. /*****************************************************************************
  633. * DESCRIPTION:                                                               *
  634. * Converts all tabs in input line to spaces and returns a duplicated string. *
  635. *                                                                            *
  636. * PARAMETERS:                                                                *
  637. *   Line:      To filter out tabs.                                           *
  638. *                                                                            *
  639. * RETURN VALUE:                                                              *
  640. *   char*:     Line but with no tabs. A pointer to a dynamic space.          *
  641. *****************************************************************************/
  642. static char *StrdupTabToSpaces(char*Line)
  643. {
  644.     return IritStrdup(ConvertTabsToSpaces(Line));
  645. }
  646.  
  647. /*****************************************************************************
  648. * DESCRIPTION:                                                               *
  649. * Converts all tabs in input line to spaces.                                 *
  650. *                                                                            *
  651. * PARAMETERS:                                                                *
  652. *   Line:      To filter out tabs.                                           *
  653. *                                                                            *
  654. * RETURN VALUE:                                                              *
  655. *   char *:     Line but with no tabs. A pointer to a static local space.    *
  656. *****************************************************************************/
  657. static char *ConvertTabsToSpaces(char*Line)
  658. {
  659.     static char NewLine[LINE_LEN_LONG];
  660.     int i, j;
  661.     char *p = Line;
  662.  
  663.     for (i = 0; *p != 0; p++) {
  664.     if (*p == 0x09)
  665.         do {
  666.         NewLine[i++] = ' ';
  667.         }
  668.         while (i % 8 != 0);
  669.     else 
  670.         NewLine[i++] = *p;
  671.     }
  672.     NewLine[i] = 0;
  673.  
  674.     return NewLine;
  675. }
  676.  
  677. /*****************************************************************************
  678. * DESCRIPTION:                                                               *
  679. * Filters out CR/LF, M or V and spaces at the end of the line, in place         *
  680. *                                                                            *
  681. * PARAMETERS:                                                                *
  682. *   Line:      To filter out its end.                                        *
  683. *   Skip:      How many characters to skip from the beginning.             *
  684. *                                                                            *
  685. * RETURN VALUE:                                                              *
  686. *   char *:    Line                                                          *
  687. *****************************************************************************/
  688. static char *FilterEOLMV(char *Line, int Skip)
  689. {
  690.     char *p;
  691.  
  692.     for (p = Line + strlen(Line) - 1; *p <= ' ' || *p == 'M' || *p == 'V'; p--);
  693.     
  694.     *++p = 0;
  695.  
  696.     return strlen(Line) > Skip ? &Line[Skip] : "";
  697. }
  698.  
  699. /*****************************************************************************
  700. * DESCRIPTION:                                                               *
  701. * Returns the first non space character in line after the first *.              *
  702. *                                                                            *
  703. * PARAMETERS:                                                                *
  704. *   Line:      To find first interesting char.                               *
  705. *                                                                            *
  706. * RETURN VALUE:                                                              *
  707. *   char *:    First interesting character in Line.                          *
  708. *****************************************************************************/
  709. static char *FilterFirstNonSpace(char *Line)
  710. {
  711.     char *p;
  712.  
  713.     for (p = Line + 1; *p != 0 && isspace(*p); p++);
  714.     return p;
  715. }
  716.  
  717. /*****************************************************************************
  718. * DESCRIPTION:                                                               *
  719. * Filters out the CR/LF from the end of the line, in place.                     *
  720. *                                                                            *
  721. * PARAMETERS:                                                                *
  722. *   Line:      To filter out its end.                                        *
  723. *   Skip:      How many characters to skip from the beginning.             *
  724. *                                                                            *
  725. * RETURN VALUE:                                                              *
  726. *   char *:    Line                                                          *
  727. *****************************************************************************/
  728. static char *FilterCRLF(char *Line, int Skip)
  729. {
  730.     char *p;
  731.  
  732.     for (p = Line + strlen(Line) - 1; *p < ' '; p--);
  733.     *++p = 0;
  734.  
  735.     return strlen(Line) > Skip ? &Line[Skip] : "";
  736. }
  737.  
  738. /*****************************************************************************
  739. * DESCRIPTION:                                                               *
  740. * Dumps out the functions in the regular text format.                 *
  741. *                                                                            *
  742. * PARAMETERS:                                                                *
  743. *   Fout:      Where output goes to.                                         *
  744. *                                                                            *
  745. * RETURN VALUE:                                                              *
  746. *   void                                                                     *
  747. *****************************************************************************/
  748. static void DumpInfoText(FILE *Fout)
  749. {
  750.     int i, j;
  751.     FunctionStruct *Func, **SortFunc;
  752.  
  753.     /* Sort the functions by name. */
  754.     for (Func = GlblFuncList, i = 0; Func != NULL; Func = Func -> Pnext, i++);
  755.     SortFunc = (FunctionStruct **)
  756.     IritMalloc((i + 1) * sizeof(FunctionStruct *));
  757.     for (Func = GlblFuncList, i = 0; Func != NULL; Func = Func -> Pnext, i++)
  758.     SortFunc[i] = Func;
  759.     qsort(SortFunc, i, sizeof(FunctionStruct *), FuncQSortComp);
  760.  
  761.     for (j = 0; j < i; j++) {
  762.     int k, l;
  763.     char **Data;
  764.     ParamStruct *Param, **Params;
  765.  
  766.     Func = SortFunc[j];
  767.     fprintf(Fout, "%s  (%s:%d):\n\n",
  768.         Func -> Keywords[0], Func -> FileName, Func -> LineNumber);
  769.  
  770.     fprintf(Fout, "Prototype:\n");
  771.     Data = Func -> Prototype;
  772.     for (k = 0; Data[k] != NULL; k++)
  773.         fprintf(Fout, "  %s\n", FilterEOLMV(Data[k], 0));
  774.  
  775.     fprintf(Fout, "\n Description:\n");
  776.     Data = Func -> Description;
  777.     for (k = 0; Data[k] != NULL; k++)
  778.         fprintf(Fout, "  %s\n", FilterEOLMV(Data[k], 2));
  779.  
  780.     fprintf(Fout, "\n Parameters:\n");
  781.     if (Func -> Parameters) {
  782.         for (Params = Func -> Parameters, l = 0; Params[l] != NULL; l++) {
  783.         Param = Params[l];
  784.         fprintf(Fout, "  %s:", Param -> ParamName);
  785.         Data = Param -> Description;
  786.         for (k = 0; Data[k] != NULL; k++)
  787.             fprintf(Fout, "  %s\n",
  788.                 FilterEOLMV(Data[k], k == 0 ? 0 : 2));
  789.         }
  790.     }
  791.     else
  792.         fprintf(Fout, "  None:\n");
  793.  
  794.     fprintf(Fout, "\n Returned Value:\n");
  795.     Param = Func -> RetVal;
  796.     Data = Param -> Description;
  797.     for (k = 0; Data[k] != NULL; k++)
  798.         fprintf(Fout, "  %s\n", FilterEOLMV(Data[k], 4));
  799.  
  800.     fprintf(Fout, "\n Keywords:\n");
  801.     Data = Func -> Keywords;
  802.     for (k = 1; Data[k] != NULL; k++)
  803.         fprintf(Fout, "  %s\n", FilterEOLMV(Data[k], 0));
  804.  
  805.     fprintf(Fout, "\n\n");
  806.     }
  807. }
  808. /*****************************************************************************
  809. * DESCRIPTION:                                                               *
  810. * Prints out a string, after escaping all Latex's spacial characters.        *
  811. *                                                                            *
  812. * PARAMETERS:                                                                *
  813. *   Fout:     Where output goes to.                                          *
  814. *   Str:      String to output in Latex acceptable format.                   *
  815. *                                                                            *
  816. * RETURN VALUE:                                                              *
  817. *   void                                                                     *
  818. *****************************************************************************/
  819. static void PutLatexString(FILE *Fout, char *Str)
  820. {
  821.     int j;
  822.  
  823.     for (j = 0; Str[j] != 0; j++) {
  824.     switch (Str[j]) {
  825.         case '^':
  826.         case '\\':
  827.         fprintf(Fout, "\\verb+%c+", Str[j]);
  828.         break;
  829.         case '&':
  830.         case '#':
  831.         case '_':
  832.         case '$':
  833.         case '%':
  834.         case '{':
  835.         case '}':
  836.         fprintf(Fout, "\\%c", Str[j]);
  837.         break;
  838.         case '>':
  839.         case '<':
  840.         case '|':
  841.         fprintf(Fout, "$%c$", Str[j]);
  842.         break;
  843.         default:
  844.         fputc(Str[j], Fout);
  845.     }
  846.     }
  847. }
  848.  
  849. /*****************************************************************************
  850. * DESCRIPTION:                                                               *
  851. * Dumps out the desscription of a function for Latex.                 *
  852. *                                                                            *
  853. * PARAMETERS:                                                                *
  854. *   Fout:      Where output goes to.                                         *
  855. *   Desc:      A NULL terminated array of strings.                           *
  856. *                                                                            *
  857. * RETURN VALUE:                                                              *
  858. *   void                                                                     *
  859. *****************************************************************************/
  860. static void DumpDescriptionForLatex(FILE *Fout, char **Desc)
  861. {
  862.     int InVerbatim = FALSE;
  863.     int i, j,
  864.         IndentNesting = 0,
  865.     Indent[MAX_INDENTATION];
  866.  
  867.     Indent[IndentNesting] = 0;
  868.  
  869.     fprintf(Fout, "{\\bf Description:} ");
  870.     for (i = 0; Desc[i] != NULL; i++)
  871.     {
  872.     if (ValidateLine(Desc[i])) {
  873.         char
  874.         *p = FilterCRLF(Desc[i], 1),
  875.         *p2 = FilterFirstNonSpace(p);
  876.  
  877.         /* Make sure we are in the right mode according to 'M' or 'V' in */
  878.         /* the end of the line and drop this mark once set.             */
  879.         if (p[strlen(p) - 1] == 'V' && !InVerbatim) {
  880.         fprintf(Fout, "\\begin{verbatim}\n");
  881.         InVerbatim = TRUE;
  882.         }
  883.         else if (p[strlen(p) - 1] == 'M' && InVerbatim) {
  884.         fprintf(Fout, "\\end{verbatim}\n");
  885.         InVerbatim = FALSE;
  886.         }
  887.         FilterEOLMV(p, 0);
  888.  
  889.         if (!InVerbatim && isdigit(p2[0]) && p2[1] == '.') {
  890.         int Ind = ((int) p2) - ((int) p);
  891.  
  892.         /* Need to ident this one in. */
  893.         if (Indent[IndentNesting] == Ind) {
  894.             /* Same list, but a new item. */
  895.             fprintf(Fout, "\\item ");
  896.         }
  897.         else if (Indent[IndentNesting] < Ind) {
  898.             /* A new indentation level - add a new list. */
  899.             fprintf(Fout, "\\begin{list}{}{\\setlength{\\itemindent}{-0.3in}\\setlength{\\leftmargin}{0.3in}}\n");
  900.             fprintf(Fout, "\\item ");
  901.             if (IndentNesting + 1 >= MAX_INDENTATION) {
  902.             fprintf(stderr,
  903.                 "\\tOutput:  list indentation too large (>%d)\n",
  904.                 MAX_INDENTATION);
  905.             return;
  906.             }
  907.             Indent[++IndentNesting] = Ind;
  908.         }
  909.         else {
  910.             while (Indent[IndentNesting] > Ind) {
  911.             /* Close the lists. */
  912.             fprintf(Fout, "\\end{list}\n\\item ");
  913.             IndentNesting--;
  914.             }
  915.         }
  916.         }
  917.  
  918.         if (InVerbatim) {
  919.         fprintf(Fout, "%s\n", p);
  920.         }
  921.         else {
  922.         PutLatexString(Fout, p2);
  923.         fputc('\n', Fout);
  924.         }
  925.     }
  926.     else {
  927.         if (InVerbatim) {
  928.         fprintf(Fout, "\\end{verbatim}\n");
  929.         InVerbatim = FALSE;
  930.         }
  931.  
  932.         while (IndentNesting > 0) {
  933.         /* Close all lists. */
  934.         fprintf(Fout, "\\end{list}\n");
  935.         IndentNesting--;
  936.         }
  937.  
  938.         fprintf(Fout, "\\mbox{\\hspace{0.01in}} \\newline ");
  939.     }
  940.     }
  941.  
  942.     if (InVerbatim) {
  943.     fprintf(Fout, "\\end{verbatim}\n");
  944.     InVerbatim = FALSE;
  945.     }
  946.  
  947.     /* Make sure no nesting remains. */
  948.     while (IndentNesting > 0) {
  949.     /* Close the lists. */
  950.     fprintf(Fout, "\\end{list}\n");
  951.     IndentNesting--;
  952.     }
  953. }
  954.  
  955. /*****************************************************************************
  956. * DESCRIPTION:                                                               *
  957. * Dumps out the functions in the latex format.                     *
  958. *                                                                            *
  959. * PARAMETERS:                                                                *
  960. *   Fout:      Where output goes to.                                         *
  961. *                                                                            *
  962. * RETURN VALUE:                                                              *
  963. *   void                                                                     *
  964. *****************************************************************************/
  965. static void DumpInfoLatex(FILE *Fout)
  966. {
  967.     int i, j;
  968.     FunctionStruct *Func, **SortFunc;
  969.  
  970.     /* Sort the functions by name. */
  971.     for (Func = GlblFuncList, i = 0; Func != NULL; Func = Func -> Pnext, i++);
  972.     SortFunc = (FunctionStruct **)
  973.     IritMalloc((i + 1) * sizeof(FunctionStruct *));
  974.     for (Func = GlblFuncList, i = 0; Func != NULL; Func = Func -> Pnext, i++)
  975.     SortFunc[i] = Func;
  976.     qsort(SortFunc, i, sizeof(FunctionStruct *), FuncQSortComp);
  977.  
  978.     for (j = 0; j < i; j++) {
  979.     int k, l;
  980.     char **Data;
  981.     ParamStruct *Param, **Params;
  982.  
  983.     Func = SortFunc[j];
  984.     fprintf(Fout, "\\subsection{");
  985.     PutLatexString(Fout, Func -> Keywords[0]);
  986.     Data = Func -> Keywords;
  987.     for (k = 1; Data[k] != NULL; k++)
  988.         fprintf(Fout, "\\index{%s}\n", FilterEOLMV(Data[k], 0));
  989.     fprintf(Fout, " {\\normalsize (");
  990.     PutLatexString(Fout, Func -> FileName);
  991.     fprintf(Fout, ":%d)}}\n\n", Func -> LineNumber);
  992.  
  993.     fprintf(Fout, "\\begin{picture}(0, 0)\n");
  994.     for (k = 1; Data[k] != NULL; k++)
  995.         fprintf(Fout, "    \\put(400, %d){\\fbox{\\tiny %s}}\n",
  996.             (k - 1) * -15, Data[k]);
  997.     fprintf(Fout, "\\end{picture}\n\n");
  998.  
  999.     Data = Func -> Prototype;
  1000.     fprintf(Fout, "\\begin{verbatim}\n");
  1001.     for (k = 0; Data[k] != NULL; k++)
  1002.         fprintf(Fout, "  %s\n", FilterEOLMV(Data[k], 0));
  1003.     fprintf(Fout, "\\end{verbatim}\n");
  1004.  
  1005.     if (Func -> Parameters) {
  1006.         fprintf(Fout, "\\begin{list}{}{\\setlength{\\itemindent}{-0.3in}\\setlength{\\leftmargin}{0.6in}}\n");
  1007.         for (Params = Func -> Parameters, l = 0; Params[l] != NULL; l++) {
  1008.         Param = Params[l];
  1009.         fprintf(Fout, "\\item {\\bf ");
  1010.         PutLatexString(Fout, Param -> ParamName);
  1011.         fprintf(Fout, ":} ");
  1012.         Data = Param -> Description;
  1013.         for (k = 0; Data[k] != NULL; k++) {
  1014.             PutLatexString(Fout, FilterEOLMV(Data[k],
  1015.                              k == 0 ? 0 : 2));
  1016.             fprintf(Fout, "\n");
  1017.         }
  1018.         }
  1019.         fprintf(Fout, "\\end{list}\n\n");
  1020.     }
  1021.  
  1022.     Param = Func -> RetVal;
  1023.     Data = Param -> Description;
  1024.     if (Data[1] != NULL || strncmp(&Data[0][4], "void", 4) != 0) {
  1025.         char
  1026.         *p = strchr(Data[0], ':');
  1027.  
  1028.         fprintf(Fout, "\\begin{list}{}{\\setlength{\\itemindent}{-0.3in}\\setlength{\\leftmargin}{0.6in}}\n");
  1029.         fprintf(Fout, "\\item {\\bf Returns:} ");
  1030.         if (p != NULL)
  1031.         PutLatexString(Fout, FilterEOLMV(p + 1, 0));
  1032.         else
  1033.         PutLatexString(Fout, FilterEOLMV(Data[0], 2));
  1034.         for (k = 1; Data[k] != NULL; k++)
  1035.         PutLatexString(Fout, FilterEOLMV(Data[k], 2));
  1036.         fprintf(Fout, "\n\n");
  1037.         fprintf(Fout, "\\end{list}\n\n");
  1038.     }
  1039.  
  1040.     DumpDescriptionForLatex(Fout, Func -> Description);
  1041.     }
  1042. }
  1043.