home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / programs / misc / wingnuplot / doc2ag / doc2ag.c < prev    next >
C/C++ Source or Header  |  1995-02-27  |  12KB  |  476 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: doc2ag.c%v 3.38.2.70 1993/09/19 23:02:23 woo Exp woo $";
  3. #endif
  4.  
  5.  
  6. /*
  7.  * doc2ag.c  -- program to convert Gnuplot .DOC format to AmigaGuide® document
  8.  *
  9.  * This is version 1.0 written by Thomas Huchtemeier
  10.  *
  11.  * usage:  doc2ag [file.doc [file.guide]]
  12.  *
  13.  *   where file.doc is a Gnuplot .DOC file, and file.guide will be an
  14.  *   AmigaGuide® hyper-text file
  15.  *
  16.  * typical usage for GNUPLOT:
  17.  *
  18.  *   doc2ag gnuplot.doc gnuplot.guide
  19.  */
  20.  
  21. /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
  22. /*!!!!!!!!!!!!!    DO NOT EDIT THE FOLLOWING LINES  !!!!!!!*/
  23. /*!!!!!!!!!!!!!    FOR MODIFICATIOS SEE doc2ag.user !!!!!!!*/
  24. /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
  25.  
  26. char   Version[]  = "$VER: Doc2AG V1.1 ";
  27.  
  28. #define TEMP_FILE       "temp_gnu.guide"
  29. #define TRUE            1
  30. #define FALSE           0
  31.  
  32. #include "doc2ag.user"
  33.  
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <ctype.h>
  38.  
  39. typedef int boolean;
  40.  
  41. struct topicList {
  42.   int depth;
  43.   char *string;
  44.   char *orgString;
  45. };
  46.  
  47. struct linkList {
  48.   char *search;
  49.   char *linkTo;
  50. };
  51.  
  52. FILE   *temp_guide,
  53.        *infile,
  54.        *outfile;
  55. struct topicList *topic[MAX_TOPIC_NUM];
  56. struct linkList *linkEntry[MAX_LINK_NUM];
  57. int    topicNum = 0,
  58.        linkNum = 0,
  59.        oldDepth = 2;
  60.        result = 0;
  61.  
  62. void file_header(void);
  63. void make_topics(void);
  64. void make_nodes(void);
  65. void insert_text(void);
  66. void filter_line(char *line);
  67. void make_links(char *line);
  68. void make_entry(int topicDepth, char *topicString, char *orgString);
  69. void parse_line(char *line);
  70. char *upcase(char *string);
  71. void section(char *line);
  72.  
  73. main(int argc, char *argv[])
  74. {
  75.   infile = stdin;
  76.   outfile = stdout;
  77.  
  78.   if (argc > 3) {
  79.     fprintf(stderr, "Usage: %s [infile [outfile]]\n", argv[0]);
  80.     exit(1);
  81.   }
  82.   if (argc >= 2)
  83.     if ( (infile = fopen(argv[1], "r")) == (FILE *)NULL) {
  84.       fprintf(stderr, "doc2ag error: Can't open %s for reading\n", argv[1]);
  85.       exit(1);
  86.     }
  87.   if (argc == 3)
  88.     if ( (outfile = fopen(argv[2], "w+")) == (FILE *)NULL) {
  89.       fprintf(stderr, "doc2ag error: Can't open %s for writing\n", argv[2]);
  90.     }
  91.   if ( (temp_guide = fopen(TEMP_FILE,"w+")) == (FILE *)NULL) {
  92.     fprintf(stderr, "doc2ag error: Can't open %s for writing\n", TEMP_FILE);
  93.   }
  94.  
  95.   file_header();
  96.   make_nodes();
  97.   topicNum -= 1;
  98.   make_topics();
  99.   fclose(temp_guide);
  100.   remove(TEMP_FILE);
  101.   fprintf(stderr, "doc2ag success: Conversion completed. Found %d topics and %d links.\n", topicNum,
  102.      linkNum);
  103.   exit(0);
  104. }
  105.  
  106. /* The file header gives the required information for an AmigaGuide® database */
  107.  
  108. void file_header(void)
  109. {
  110.   fputs("@database \"gnuplot.guide\"\n@master \"gnuplot.doc\"\n@wordwrap\n\n",
  111.     temp_guide);
  112. }
  113.  
  114. /* Find out the beginning and the end of each node */
  115.  
  116. void make_nodes(void)
  117. {
  118.   static char line[MAX_LINE_LEN];
  119.  
  120.    while (fgets(line,MAX_LINE_LEN, infile)) {
  121.      filter_line(line);
  122.    }
  123.   fputs("@endnode\n", temp_guide);
  124.   rewind(temp_guide);
  125. }
  126.  
  127. /* Insert (sub)topics to special nodes */
  128.  
  129. void make_topics(void)
  130. {
  131.   static char line[MAX_LINE_LEN];
  132.   int         actStart,
  133.               actEnd,
  134.               actDepth,
  135.               maxDepth,
  136.               counter = 1,
  137.               oldDepth,
  138.               oldCounter,
  139.               depthBuffer,
  140.               sectionPos[MAX_TOPIC_NUM],
  141.               sectionCounter,
  142.               tempCounter;
  143.   boolean     cont, firstTopic = TRUE;
  144.  
  145.   while (fgets(line, MAX_LINE_LEN, temp_guide)) {
  146.     if (line[0] == ' ') {
  147.       parse_line(line);
  148.     }
  149.     else {
  150.       fputs(line, outfile);
  151.     }
  152.     maxDepth = 3;
  153.     sectionCounter = 0;
  154.     cont = TRUE;
  155.     if ((strcmp(line, SUBTOPIC_STRING) == 0) && (firstTopic)) {
  156.       firstTopic = FALSE;
  157.       fputc('\n', outfile);
  158.       while (counter <= topicNum) {
  159.         if (topic[counter]->depth == 2) {
  160.       fputs(topic[counter]->string, outfile);
  161.       fputc('\n', outfile);
  162.         }
  163.       counter++;
  164.       }
  165.     counter = 1;
  166.     }
  167.     else if ((strcmp(line, SUBTOPIC_STRING) == 0) && (!firstTopic)) {
  168.       while ((topic[counter]->depth == 2) && (counter <= topicNum)) {
  169.     counter++;
  170.       }
  171.       actStart = counter;
  172.       while ((topic[counter]->depth > 2) && (counter <= topicNum)) {
  173.         if (topic[counter]->depth > maxDepth) {
  174.           maxDepth = topic[counter]->depth;
  175.         }
  176.     counter++;
  177.       }
  178.       actEnd = counter - 1;
  179.       actDepth = topic[actStart]->depth;
  180.       counter = actStart;
  181.       fputc('\n', outfile);
  182.       while (counter <= actEnd) {
  183.         if (topic[counter]->depth == actDepth) {
  184.           fputs(topic[counter]->string, outfile);
  185.       fputc('\n', outfile);
  186.         }
  187.         counter++;
  188.       }
  189.       insert_text();
  190.       actDepth++;
  191.       counter = actStart;
  192.       while ((topic[counter]->depth < actDepth) && (counter <= actEnd)) {
  193.         counter++;
  194.       }
  195.       oldDepth = topic[counter]->depth;
  196.       fputc('\n', outfile);
  197.       while (counter <= actEnd) {
  198.         if (topic[counter]->depth == actDepth) {
  199.           fputs(topic[counter]->string, outfile);
  200.       fputc('\n', outfile);
  201.           cont = TRUE;
  202.         }
  203.         else {
  204.           if ((topic[counter]->depth < oldDepth)) {
  205.             depthBuffer = topic[counter]->depth;
  206.             oldCounter = counter;
  207.             while ((topic[counter]->depth == depthBuffer) && (counter <= actEnd)) {
  208.               counter++;
  209.             }
  210.             counter--;
  211.             if (counter != actEnd) {
  212.               insert_text();
  213.             }
  214.             counter = oldCounter;
  215.           }
  216.           if ((topic[counter]->depth > actDepth) && (cont)) {
  217.             if (cont) {
  218.               sectionCounter++;
  219.               sectionPos[sectionCounter] = counter;
  220.               cont = FALSE;
  221.             }
  222.           }
  223.         }
  224.  
  225.         oldDepth = topic[counter]->depth;
  226.         counter++;
  227.       }
  228.       counter = actEnd + 1;
  229.     }
  230.     if ((sectionCounter > 0) && (topic[counter]->depth < oldDepth)) {
  231.       insert_text();
  232.       tempCounter = 1;
  233.       while (tempCounter <= sectionCounter) {
  234.         fputc('\n', outfile);
  235.         while (topic[sectionPos[tempCounter]]->depth == 5) {
  236.           fputs(topic[sectionPos[tempCounter]]->string, outfile);
  237.       fputc('\n', outfile);
  238.           sectionPos[tempCounter]++;
  239.         }
  240.         if (tempCounter != sectionCounter) {
  241.           insert_text();
  242.         }
  243.         tempCounter++;
  244.       }
  245.     }
  246.   }
  247. }
  248.  
  249. /* Read the temp_guide.gnu file until another (sub)topic occurs */
  250.  
  251. void insert_text(void)
  252. {
  253.   static char line[MAX_LINE_LEN];
  254.  
  255.   while ((fgets(line, MAX_LINE_LEN, temp_guide)) && (strcmp(line, SUBTOPIC_STRING) != 0)) {
  256.     if (line[0] == ' ') {
  257.       parse_line(line);
  258.     }
  259.     else {
  260.       fputs(line, outfile);
  261.     }
  262.   }
  263.   if (strcmp(line, SUBTOPIC_STRING) == 0) {
  264.     fputs(line, outfile);
  265.   }
  266. }
  267.  
  268. /* Seperate relevant from non-relevant lines */
  269.  
  270. void filter_line(char *line)
  271. {
  272.   switch(line[0]) {                    /* control character */
  273.     case '?' :  {                /* interactive help entry */
  274.       make_links(line);
  275.       break;
  276.     }
  277.     case '@' :  break;                /* start/end table */
  278.     case '#' :  break;                /* latex table entry */
  279.     case '%' :  break;                /* troff table entry */
  280.     case '\n':                     /* empty text line */
  281.     case ' ' :  {                /* normal text line */
  282.       fputs(line, temp_guide);
  283.       break;
  284.     }
  285.     default  : {
  286.       if (isdigit(line[0])) {              /* start of a (sub)topic */
  287.         section(line);
  288.     make_links(line+1);
  289.       }
  290.       else {
  291.         fprintf(stderr, "doc2ag error: Unknown control code '%c' in column 1\n", line[0]);
  292.       }
  293.       break;
  294.     }
  295.   }
  296. }
  297.  
  298. /* Upcase strings */
  299.  
  300. char *upcase(char *string)
  301. {
  302.   static char upString[MAX_LINE_LEN];
  303.   int counter = 0;
  304.  
  305.   while(string[counter]) {
  306.     upString[counter] = toupper(string[counter]);
  307.     counter++;
  308.   }
  309.   upString[counter] = '\0';
  310.   return upString;
  311. }
  312.  
  313. /* Mark keywords found in each line */
  314.  
  315. void parse_line(char *line)
  316. {
  317.   register char actChar;
  318.   static boolean inquote = FALSE;
  319.   char upStringBuffer[MAX_LINE_LEN],
  320.        upLinkSearch[MAX_LINE_LEN],
  321.        stringBuffer[MAX_LINE_LEN];
  322.   int counter = 0, linkCounter = 1;
  323.   static boolean foundLink = FALSE;
  324.  
  325.   while( (actChar = *line++) != '\0') {
  326.     switch(actChar) {
  327.       case '`':
  328.         if (inquote) {
  329.           inquote = FALSE;
  330.       stringBuffer[counter] = '\0';
  331.           while ((!foundLink) && (linkCounter <= linkNum)) {
  332.         strcpy(upStringBuffer ,upcase(stringBuffer));
  333.         strcpy(upLinkSearch ,upcase(linkEntry[linkCounter]->search));
  334.          if (strcmp(upStringBuffer, upLinkSearch) == 0) {
  335.           foundLink = TRUE;
  336.           fprintf(outfile, "@{\" %s \" link \"%s\"}", stringBuffer,
  337.         linkEntry[linkCounter]->linkTo);
  338.         }
  339.         else {
  340.           linkCounter++;
  341.         }
  342.       }
  343.       if ((!foundLink) && (linkCounter >= linkNum)) {
  344.         fprintf(outfile, "%s%s%s", MARK_TEXT, stringBuffer, UNMARK_TEXT);
  345.       }
  346.         }
  347.         else {
  348.           inquote = TRUE;
  349.           foundLink = FALSE;
  350.           linkCounter = 1;
  351.       counter = 0;
  352.         }
  353.         break;
  354.       default:
  355.     if (inquote) {
  356.       stringBuffer[counter++] = actChar;
  357.         }
  358.     else {
  359.           fputc(actChar, outfile);
  360.      }
  361.         break;
  362.     }
  363.   }
  364. }
  365.  
  366.  
  367. /* Make an entry to the (sub)topic-list */
  368.  
  369. void make_entry(int topicDepth, char *topicString, char *orgString)
  370. {
  371.   if (topic[topicNum] = calloc(1, sizeof(struct topicList))) {
  372.     if (topic[topicNum]->string=calloc(strlen(topicString)+1,1)) {
  373.       if (topic[topicNum]->orgString=calloc(strlen(orgString)+1,1)) {
  374.         topic[topicNum]->depth = topicDepth;
  375.         strcpy(topic[topicNum]->string, topicString);
  376.         strcpy(topic[topicNum]->orgString, orgString);
  377.       }
  378.     }
  379.   }
  380.   else {
  381.     fprintf(stderr, "doc2ag error: Conversion terminated. Sorry, not enough memory to do my work.\n");
  382.     exit(0);
  383.   }
  384. }
  385.  
  386. /* Link interactive help-entries to the recommended (sub)topic */
  387.  
  388. void make_links(char *line)
  389. {
  390.   static char string[MAX_LINE_LEN];
  391.   boolean noMemory = FALSE;
  392.  
  393.   sscanf(line+1,"%[^\n]s", string);
  394.   if (string[0] != '\0') {
  395.     linkNum++;
  396.     if (linkNum <= MAX_LINK_NUM) {
  397.       if (linkEntry[linkNum] = calloc(1, sizeof(struct linkList))) {
  398.         if (linkEntry[linkNum]->search=calloc(strlen(string)+1,1)) {
  399.           strcpy(linkEntry[linkNum]->search, string);
  400.           if (isspace(line[0])) {
  401.             if (linkEntry[linkNum]->linkTo=calloc(strlen(string)+1,1)) {
  402.               strcpy(linkEntry[linkNum]->linkTo, string);
  403.         }
  404.         else {
  405.               noMemory = TRUE;
  406.         }
  407.           }
  408.           else {
  409.             if (linkEntry[linkNum]->linkTo=calloc(strlen(topic[topicNum-1]->orgString)+1,1)) {
  410.               strcpy(linkEntry[linkNum]->linkTo, topic[topicNum-1]->orgString);
  411.             }
  412.         else {
  413.               noMemory = TRUE;
  414.         }
  415.           }
  416.         }
  417.       }
  418.       else {
  419.         noMemory = TRUE;
  420.       }
  421.       if (noMemory) {
  422.         fprintf(stderr, "doc2ag error: Conversion terminated. Sorry, not enough memory to do my work\n");
  423.         exit(0);
  424.       }
  425.     }
  426.     else {
  427.       fprintf(stderr, "doc2ag error: Conversion terminated. Sorry, too many links. Please revise your #DEFINEs.\n");
  428.       exit(0);
  429.     }
  430.   }
  431. }
  432.  
  433. /* Insert (sub)topic entries (nodes) to the temp_guide.gnu file and compound
  434.    link-entry for the (sub)topic-list */
  435.  
  436. void section(char *line)
  437. {
  438.   static char buttonString[MAX_LINE_LEN],
  439.               stringBuffer[MAX_LINE_LEN],
  440.               string[MAX_LINE_LEN],
  441.               titleString[MAX_LINE_LEN];
  442.   int         actDepth;
  443.  
  444.   sscanf(line,"%d %[^\n]s", &actDepth, string);
  445.   sprintf(buttonString, "%-20s", string);
  446.   switch(actDepth) {
  447.     case 1:
  448.       fputs("@node main \"", temp_guide);
  449.       break;
  450.     default:
  451.       if (oldDepth < actDepth){
  452.         fputs(SUBTOPIC_STRING, temp_guide);
  453.     fputs("\n@endnode\n", temp_guide);
  454.       }
  455.       else {
  456.         fputs("@endnode\n", temp_guide);
  457.       }
  458.       sprintf(stringBuffer, "   @{\" %s \" link \"%s\"}", buttonString, string);
  459.       make_entry(actDepth, stringBuffer, string);
  460.       fputs("\n@node \"", temp_guide);
  461.       break;
  462.   }
  463.   if (islower(string[0])) {
  464.     string[0] = toupper(string[0]);
  465.   }
  466.   strcpy(titleString, TITLE);
  467.   strcat(titleString, string);
  468.   fprintf(temp_guide, "%s\"\n@title \"%s\"\n", string, titleString);
  469.   oldDepth = actDepth;
  470.   topicNum++;
  471.   if (topicNum > MAX_TOPIC_NUM) {
  472.     fprintf(stderr, "doc2ag error: Conversion terminated. Sorry, too many topics. Please revise your #DEFINEs.\n");
  473.     exit(0);
  474.   }
  475. }
  476.