home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / UTILS / INTERRPT / INT2GUID / INT2GUID.C < prev    next >
Text File  |  1993-07-04  |  22KB  |  726 lines

  1. /* INT2GUID.C
  2.  *
  3.  * from:
  4.  * INT2QH.C
  5.  *
  6.  * Author:   Kai Uwe Rommel
  7.  * Date:     Sun 07-Oct-1990
  8.  * Update:   Sat 20-Oct-1990
  9.  * Update:   Sun 11-Nov-1990  Ralf Brown
  10.  *
  11.  * Compiler: MS C 5.00 and newer / compact model, or TC 2.0 / compact model
  12.  * System:   PC/MS-DOS 3.20 and newer, OS/2 1.0 and newer
  13.  *
  14.  *
  15.  * INT2GUID.C is a GUIDE/MAKEHELP version of INT2QH.C. GUIDE and MAKEHELP
  16.  * are programs for pop-up help included the TurboPower Software package
  17.  * Turbo Professional.
  18.  *
  19.  * Transscriptor:    Bent Lynggaard
  20.  * Date:    1.00    Sun 24-Mar-1991
  21.  * Update:    1.01    Tue 02-Apr-1991    - test '!', ';' in line pos 1.
  22.  *                    - test disk full
  23.  *        1.02    Sun 14-Apr-1991    - smaller index pages
  24.  *                    - main index always leads to start of
  25.  *                      an INT #
  26.  *        1.03    Sun 12-May-1991    - configuration file.
  27.  *        1.04    Sat 18-May-1991 - conditional mask in *.cfg
  28.  *        1.05    Sun 29-Dec-1991 - fixed \n bug in configure()
  29.  *        1.06    Sun 09-May-1992 - adjusted for change in file format
  30.  *                    - "dividerline" info as headings
  31.  *                    - all registers can carry parameters
  32.  *        1.07    Sat 19-Dec-1992 - fixed bug (reading from closed file)
  33.  *                    - "dividerline" info as topics
  34.  *                    - "dividerline" char 9 function info
  35.  *                    - new subtopic criteria
  36.  *                    - program initialization in
  37.  *                        configuration file
  38.  *                    - splitting up long topics
  39.  *        1.08    Sun 04-Apr-1993 - topic # in "Missing divider line"
  40.  *                        to ease manual editing
  41.  *        1.09    Sat 03-Jul-1993 - fixed bug introduced in v. 1.07
  42.  *
  43.  * This program creates output to the standard output device. The output
  44.  * should be redirected to a file INTERRUP.TXT. The created file should
  45.  * be compiled by the TurboPower MAKEHELP program to a INTERRUP.HLP file,
  46.  * which can be interpreted by the TurboPower GUIDE TSR program:
  47.  *    INT2GUID > [ramdisk:]INTERRUP.TXT
  48.  *    MAKEHELP [ramdisk:INTERRUPT] INTERRUP[.HLP] /Q
  49.  *    GUIDE INTERRUP    (or enter GUIDE with a hot key, press F3,
  50.  *            enter INTERRUP)
  51.  *
  52.  * TurboPower Software supplies a program called POPHELP in their Object
  53.  * Professional package, which is a successor to GUIDE. INT2GUID has
  54.  * facilities for conditional interpretation of supplementary files, so
  55.  * these files can include code optimized for both GUIDE and POPHELP, and
  56.  * the parts compiled depends on a mask defined in the configuration file.
  57.  *
  58.  * The following is considered in creating the topic (and popup window)
  59.  * headers:
  60.  * The first word in the header is the interrupt number, so that GUIDE's
  61.  * search mechanism can find the entry if the hot key is pressed when
  62.  * the cursor is at an interrupt number.
  63.  * MAKEHELP restricts the (length of longest header + 1) times the number
  64.  * of topics to 64 kB. INTER191 had about 2200 topics, so the length of
  65.  * the headers should be limited to 25 characters. However, rather than
  66.  * truncating the INTERRUP.LST header lines to some nonsense, this
  67.  * program uses only the interrupt number as topic headings, plus the
  68.  * AH or AX values where applicable.
  69.  * (v. 1.06: "divider line" info (e.g. "214C" in "--------214C------...")
  70.  * is used for headings, thus allowing a more selective search by GUIDE's
  71.  * cursor-word search.)
  72.  * The main index references some subindeces. The subindeces use the
  73.  * MAKEHELP cross reference facility. MAKEHELP limits the number of cross
  74.  * references to 50 per topic, however, this program limits each subindex
  75.  * to 18 entries, so each "topic" can be shown on one single screen with
  76.  * height 20 lines. For each interrupt number, the entries are temporarily
  77.  * stored, and written to the current subindex page only if all entries
  78.  * for the interrupt number fit on the page.
  79.  *
  80.  * MAKEHELP's text wrapping mechanism is disabled, and as the active
  81.  * window is limited to 76 characters, some lines are missing one or two
  82.  * characters.
  83.  * The amount of text that can be displayed per topic is limited by
  84.  * GUIDE's setting of pages/topic (default = 20) and the screen height
  85.  * defined when GUIDE was initialized.
  86.  *
  87.  */
  88.  
  89. #define LABEL    "int2guid.c"
  90. #define VERSION  "1.07"
  91.  
  92. #include <stdio.h>
  93. #include <stdlib.h>
  94. #include <string.h>
  95. #include <ctype.h>
  96.  
  97. #define divider_line(s) (strncmp(s,"--------",8)==0)
  98. #define maxIndeces 18
  99.   /* max 50, 18 gives one page with height 20 (18 active lines) */
  100. #define mainIndex 200
  101.   /* 1-99 reserved for program, 100-199 reserved for user */
  102. #define false 0
  103. #define true 1
  104.  
  105. FILE *input, *output, *topics, *subtopics, *config;
  106.  
  107. char line1[128];
  108. char line2[128];
  109. char configline[128];
  110. char tempBuffer[50 * 128];
  111. char *tempPtr;
  112. char category[4] = "--";
  113. char nextHeader[16] = "??"; /* v. 1.07: 16 rather than 14 */
  114. char infilename[14] = "interrup.lst";
  115. #define infileExt 9
  116. int splitInfile = 0;
  117. int classification = 0;
  118. int WIDTH = 80;
  119.   /* WIDTH is the screen with for GUIDE/POPHELP. 80 is the best choice for
  120.      GUIDE, 78 is the best choice for POPHELP (which does not count the
  121.      frame as a part of the screen). The configuration file can change
  122.      this value. v. 1.07.
  123.   */
  124. long topicStart = 0; /* v. 1.07 */
  125. unsigned maxTopicLength = 32000; /* v. 1.07 */
  126.   /* texts longer than maxTopicLength are split into two or more topics.
  127.      The configuration file can change this value.
  128.   */
  129. char currentHeader[16]; /* v. 1.07 */
  130.  
  131. char configfile[14] = "int2guid.cfg";
  132. char configmarker[18] = "INT2GUIDE CONFIG";
  133.  
  134. char missingFile[] = "Missing include file.";
  135.  
  136. int sub = 0, indexed = 1;
  137. unsigned currentID = 1, activeID = 1, indeces = 0, indexNo = 0, buffered = 0,
  138.   subindeces, activeSub, mask;
  139. int headerlength; /* v. 1.07 */
  140. unsigned reservedID = mainIndex; /* v. 1.07 */
  141.   /* reservedID reserves some topic numbers for long texts that are split
  142.      into more than one topic. currentID must then be incremented via a
  143.      function call in order to skip the reserved topics.
  144.   */
  145.  
  146. void exitfunc(void)
  147. {
  148.   fcloseall();
  149.   unlink("topic.tmp");
  150.   unlink("subtopic.tmp");
  151. }
  152.  
  153. void errorexit(char *msg)
  154. /* writes msg to stderr and exits with error code 1 */
  155. {
  156.   fputs(msg, stderr);
  157.   exit(1);
  158. } /* errorexit */
  159.  
  160. void diskFull(int temporary)
  161. /* reports disk full and exits */
  162. {
  163.   char msg[80];
  164.   sprintf(msg,"\n\nDisk full, %s file\n", temporary ? "temporary" : "output");
  165.   errorexit(msg);
  166. } /* diskFull */
  167.  
  168.  
  169. int _fputs(char *line, FILE *stream)
  170. /* filters TABs to spaces, and inserts a leading space in lines starting
  171.    with the MAKEHELP command and comment characters '!' and ';'. "_fputs"
  172.    should be used when copying from unknown sources. Use "fputs" when
  173.    copying files with information specifically for this program.
  174. */
  175. {
  176.   char buffer[128];
  177.   int cnt = 0;
  178.  
  179.   if ( (*line=='!') || (*line==';') ) /* MAKEHELP command/comment? */
  180.     buffer[cnt++] = ' '; /* start with a space */
  181.  
  182.   while ( *line )
  183.   {
  184.     switch ( *line )
  185.     {
  186.       case '\t': do buffer[cnt++] = ' '; while ( cnt & 7 ); break;
  187.             /* MAKEHELP does not interpret tabs */
  188.       default  : buffer[cnt++] = *line;
  189.     }
  190.     line++;
  191.   }
  192.  
  193.   buffer[cnt] = 0;
  194.  
  195.   if ( (cnt = fputs(buffer, stream)) == EOF )
  196.     diskFull(stream != output);
  197.  
  198.   return cnt;
  199. }
  200.  
  201. char *_fgets(char *s, int n, FILE *stream)
  202. {
  203.   char *ptr;
  204.   ptr = fgets(s, n, stream);
  205.   if ( (ptr==NULL) && (stream==input) ) /* v. 1.09: edited */
  206.   {
  207.     fclose(input); /* 1.09: also unsplit file must be closed */
  208.     input=NULL;
  209.     if ( splitInfile )
  210.     {
  211.       infilename[infileExt]++;
  212.       input = fopen(infilename, "r");
  213.       if ( input != NULL )
  214.       {
  215.     fprintf(stderr, "%s\n", infilename);
  216.     ptr = fgets(s, n, input);
  217.       }
  218.     }
  219.   }
  220.   return ptr;
  221. } /* _fgets */
  222.  
  223. void Initialize(void)
  224. {
  225.   input     = fopen(infilename, "r");
  226.   if ( input == NULL )
  227.   {
  228.     infilename[infileExt] = 'a';
  229.     infilename[infileExt+1] = 0;
  230.     input = fopen(infilename, "r");
  231.     if ( input == NULL )
  232.     {
  233.       fputs("Cannot open input file (INTERRUP.LST or INTERRUP.A)\n", stderr);
  234.       exit(1);
  235.     }
  236.     splitInfile = 1;
  237.   }
  238.   fprintf(stderr, "%s\n", infilename);
  239.   output    = stdout;
  240.   topics    = fopen("topic.tmp", "w");
  241.   subtopics = fopen("subtopic.tmp", "w");
  242.  
  243.   tempPtr = tempBuffer;
  244.  
  245.   fprintf(output,
  246.     ";INTERRUPT help text for MAKEHELP/GUIDE.\n;\n!WIDTH %u\n;\n",WIDTH);
  247.     /* v. 1.07: WIDTH  rather than constant 80. WIDTH is initialized to 80
  248.        and can be changed in the configuration file.
  249.     */
  250.   fprintf(topics, "!TOPIC 1 Interrupt List\n!INDEX %u\n", mainIndex);
  251. }
  252.  
  253. int incrementID(void)
  254. /* v. 1.07: introduced in order to skip reserved IDs when incrementing currentID */
  255. {
  256.   ++currentID;
  257.   if (currentID == mainIndex)
  258.     currentID = reservedID;
  259.   return currentID;
  260. } /* incrementID */
  261.  
  262. void testTopic(void) /* limit xrefs/topic to maxIndeces */
  263. {
  264.   if ( indeces+buffered >= maxIndeces ) /* leave one entry for forw. ref */
  265.   {
  266.     incrementID();
  267.     fprintf(topics, "\004%u\005INT %s\005 (index continued)\n"
  268.       "!TOPIC %u INT %s (cont)\n!INDEX %u\n"
  269.       "(continued \004%u\005from\005)\n",
  270.       currentID, category, currentID, category, ++indexNo, activeID);
  271.     indeces = 1; /* the backwards ref */
  272.     activeID = currentID;
  273.   }
  274. } /* testTopic */
  275.  
  276. void copyBuffer(void)
  277. {
  278.   if ( buffered == 0 )
  279.     return;
  280.  
  281.   testTopic();
  282.   if ( fputs(tempBuffer, topics) == EOF )
  283.       diskFull(true);
  284.   indeces += buffered;
  285.   buffered = 0;
  286.   tempPtr = tempBuffer;
  287. } /* copyBuffer */
  288.  
  289. void Cleanup(void)
  290. {
  291.   copyBuffer();
  292.   fclose(topics);
  293.   fclose(subtopics);
  294.   fputs("Cleaning up\n", stderr);
  295.  
  296.   topics = fopen("topic.tmp", "r");
  297.   subtopics = fopen("subtopic.tmp", "r");
  298.  
  299.   while ( fgets(line1, sizeof(line1), topics) )
  300.     if ( fputs(line1, output) == EOF )
  301.       diskFull(false);
  302.  
  303.   while ( fgets(line1, sizeof(line1), subtopics) )
  304.     if ( fputs(line1, output) == EOF )
  305.       diskFull(false);
  306. } /* Cleanup */
  307.  
  308. void putAndCount(int putFunc(), char *line)
  309. /* split topic if maxTopicLength is exceeded. v. 1.07 */
  310. {
  311.   int ID, rID;
  312.   if ((ftell(output) - topicStart) > maxTopicLength)
  313.   {
  314.     ID = currentID;
  315.     rID = (reservedID > currentID) ? reservedID++ : ++currentID;
  316.     if (fprintf(output,"\004%u\005(text continues)\005\n"
  317.       "!TOPIC %u %s\n!NOINDEX\n"
  318.       "\004%u\005(text continued from)\005\n",
  319.       rID, rID, currentHeader, ID) == EOF)
  320.     diskFull(false);
  321.     topicStart = ftell(output);
  322.   }
  323.   if (putFunc(line, output) == EOF)
  324.     diskFull(false);
  325. } /* putAndCount */
  326.  
  327. int CopyFile(char *name, int commands)
  328. /* copies a file to the database, returns 0 for success or 1 for error */
  329.  
  330. /* If commands!=0, also interprets lines starting with "!! <number>" as
  331.    an update to variable "condition", and copies lines to the database
  332.    only if condition == 0 or (condition & mask) != 0
  333. */
  334. {
  335.   int condition = 0;
  336.   FILE *temp = fopen(name, "r");
  337.   char s[128];
  338.   fprintf(stderr, "%s\n", name);
  339.   if ( temp == NULL )
  340.   {
  341.     fprintf(stderr, "WARNING: Could not open %s\n", name);
  342.     fputs("Information was not available\n", output);
  343.     return 1;
  344.   }
  345.   else
  346.   {
  347.     while ( fgets(line2, sizeof(line2), temp) )
  348.       if ( !commands )
  349.     putAndCount(_fputs, line2);
  350.       else
  351.     /* does line start with "!! <number>" ? */
  352.     if ( sscanf(line2, "!!%i", &condition) != 1 )
  353.       /* yes: condition updated, sscanf returns 1 */
  354.       if ( (condition==0) || (condition & mask) )
  355.       {
  356.         if (sscanf(line2, "!%s", s) == 1)
  357.           if (strcmp(strupr(s), "TOPIC") == 0)
  358.             topicStart = ftell(output);
  359.         putAndCount(fputs, line2);
  360.       }
  361.     fputs("!NOWRAP\n", output); /* in case it was left in !WRAP state */
  362.     fclose(temp);
  363.     return 0;
  364.   }
  365. } /* CopyFile */
  366.  
  367. void testTemp(void)
  368. /* v. 1.06: allow no more than 50 entries in tempBuffer */
  369. /* v. 1.07: allow no more than 48 entries in tempBuffer */
  370. {
  371.   if (buffered >= 48)
  372.   {
  373.     copyBuffer();
  374.     fprintf(stderr,"INT %s has more than 48 subtopics and therefore more than one entry\n"
  375.       "in the main index (topic %u).\n", category, currentID);
  376.   }
  377. } /* testTemp */
  378.  
  379. void testSubtopic(char *marker)
  380. {
  381.   if ( ++subindeces >= maxIndeces )
  382.   {
  383.     testTemp();
  384.     sprintf(tempPtr, "\004%u\005%s\005  (list cont.)\n",
  385.       incrementID(), marker);
  386.     tempPtr += strlen(tempPtr);
  387.     buffered++;
  388.     fprintf(subtopics,
  389.       "\004%u\005%s\005  (list cont.)\n!TOPIC %u %s (list cont)\n!NOINDEX\n"
  390.       "(continued \004%u\005from\005)\n",
  391.       currentID, marker, currentID, category, activeSub);
  392.       activeSub = currentID;
  393.     subindeces = 2;
  394.   }
  395. } /* testSubtopic */
  396.  
  397.  
  398. void StartTopic(char *header, char *marker, char *desc)
  399. {
  400.   topicStart = ftell(output); /* v. 1.07 */
  401.   strncpy(currentHeader, header, sizeof(currentHeader));
  402.   currentHeader[sizeof(currentHeader)-1] = 0;
  403.   if (sub)
  404.   {
  405.     testSubtopic(marker);
  406.     if ( fprintf(subtopics, "\004%u\005%s\005  %s",
  407.       incrementID(), marker, desc) == EOF )
  408.     diskFull(true);
  409.     if (fprintf(output, "\004%u\005INT %s\005 (continued)\n",
  410.       currentID, category) == EOF)
  411.         diskFull(false);
  412.     /* insert a reference to this one in the former topic */
  413.   } /* if (sub) */
  414.   else
  415.   {
  416.     testTemp();
  417.     sprintf(tempPtr, "\004%u\005%s\005  %s", incrementID(), marker, desc);
  418.     tempPtr += strlen(tempPtr);
  419.     buffered++;
  420.   } /* else */
  421.  
  422.   fprintf(output, "!TOPIC %u %s\n", currentID, header);
  423.   if ( indexed )
  424.     indexNo++;
  425.   fprintf(output, indexed ? "!INDEX %u\n" : "!NOINDEX\n", indexNo);
  426. } /* StartTopic */
  427.  
  428. void StartList(void)
  429. /* v. 1.07: reorganized and edited */
  430. {
  431.   fprintf(subtopics, "!TOPIC %u %s (list)\n!NOINDEX\n", incrementID(), category);
  432.   if (fputs(tempBuffer, subtopics) == NULL)
  433.     diskFull(true); /* copy one entry in buffer to subtopics */
  434.   sub = 1;
  435.   subindeces = 1;
  436.   activeSub = currentID;
  437.   tempPtr = tempBuffer; /* reset buffer pointer */
  438.   buffered = 1; /* the entry we are going to use now */
  439.   sprintf(tempPtr, "\004%u\005%s\005  (list)\n", currentID, category);
  440.   tempPtr += strlen(tempPtr);
  441. } /* StartList */
  442.  
  443. /* void EndList(void) - not used */
  444.  
  445. /* char *NextID(void) - not used */
  446.  
  447. int RecognizedTopic(void)
  448. {
  449. /* v. 1.07: revised to use newheader info for marker string rather than
  450.    interpreting lines 1 and 2, and to use subtopics when there is more
  451.    than one entry rather than when there are entries with parameters.
  452. */
  453.   char *ptr, *pdesc, topic[4], marker[20];
  454.  
  455.   if (input == NULL)
  456.     return 0; /* v. 1.07: check input == NULL rather than read second line */
  457.  
  458.   if ( (pdesc = strchr(line1, '-')) == NULL )
  459.     pdesc = "(description not found)\n";
  460.  
  461.   if (headerlength==0) /* if info was missing in the dividerline */
  462.   { /* take INT # from line1[4]-[5] */
  463.     strncpy(nextHeader, &line1[4], 2);
  464.     nextHeader[2] = '\0';
  465.     fprintf(stderr,"Missing divider line info in topic %u:\n%s",
  466.       currentID, line1); /* 1.08: edited */
  467.   }
  468.   strncpy(topic, nextHeader, 2); /* interrupt number */
  469.   topic[2] = '\0';
  470.  
  471.   if ( strcmp(category, topic) )
  472.   {
  473.     sub = 0;
  474.     copyBuffer();
  475.     strcpy(category, topic);
  476.     fprintf(stderr, "%s\015", topic); /* show progress */
  477.   }
  478.   else
  479.   {
  480.     if (sub==0) /* v. 1.07 */
  481.       StartList();
  482.     /* v. 1.07: insert reference was moved to StartTopic */
  483.   }
  484.  
  485.   strcpy(marker, nextHeader); /* v. 1.07: use nextHeader for marker */
  486.   /* nextheader format: IIAHALXXNNNN_F (_F only if headerlength<0 */
  487.   /* marker format: II AHAL XXNNNN F */
  488.   if (headerlength < 0)
  489.   {
  490.     headerlength = abs(headerlength);
  491.     marker[headerlength-2] = ' '; /* '_' to space */
  492.   }
  493.  
  494.   if (headerlength > 2)
  495.   {
  496.     for (ptr = marker+headerlength+1; ptr >= &marker[2]; ptr--)
  497.       ptr[1] = *ptr;
  498.     /* memcpy(&marker[3], &marker[2], headerlength - 1);
  499.        did not work properly (compiler direction handling error)
  500.     */
  501.     marker[2] = ' ';
  502.     if (headerlength > 6+2)
  503.     {
  504.       for (ptr = marker+headerlength+2; ptr >= &marker[7]; ptr--)
  505.     ptr[1] = *ptr;
  506.       /* memcpy(&marker[8], &marker[7], headerlength - 5);
  507.         again. compiler error
  508.       */
  509.       marker[7] = ' ';
  510.       ptr = &marker[6];
  511.       while (*ptr == '_')
  512.     *ptr-- = ' '; /* spaces for AL or AX if unused */
  513.     } /* if (headerlength > 6+2) */
  514.   } /* if (headerlength > 2) *
  515.  
  516. /* v. 1.06: use global "nextHeader" rather than local "header" */
  517. /* v. 1.07: local "header" deleted */
  518.   StartTopic(nextHeader, marker, pdesc);
  519.  
  520.   _fputs(line1, output);
  521.  
  522.   return 1;
  523. } /* RecognizedTopic */
  524.  
  525. void CopyTopic(void)
  526. {
  527. /* v. 1.07: edited to split long texts into two or more topics */
  528.   char *ptr, *ptr2;
  529.  
  530.   for (;;)
  531.   {
  532.     if ( _fgets(line1, sizeof(line1), input) == NULL )
  533.       break;
  534.  
  535.     if ( !divider_line(line1) )
  536.       putAndCount(_fputs, line1);
  537.     else
  538.     {
  539.       if ( _fgets(line2, sizeof(line2), input) == NULL )
  540.     break;
  541.  
  542.       if ( strncmp(line2, "INT ", 4) )
  543.       {
  544.     putAndCount(_fputs, line1);
  545.     putAndCount(_fputs, line2);
  546.       }
  547.       else
  548.       {
  549.     /* v. 1.06: store divider line info as a header */
  550.     /* v. 1.07: edited */
  551.     strncpy(nextHeader, line1+10, 12);
  552.     for (ptr=nextHeader+11; *ptr=='-'; ptr--)
  553.       ;
  554.     if (ptr>&nextHeader[4])
  555.       for (ptr2=&nextHeader[2]; ptr2<ptr && ptr2<&nextHeader[6]; ptr2++)
  556.         if (*ptr2 == '-')
  557.           *ptr2 = '_';
  558.     headerlength = ptr - nextHeader + 1;
  559.     if (classification && line1[8]!='-')
  560.     {
  561.       *++ptr='_'; /* add char. 9 function classification */
  562.       *++ptr=line1[8];
  563.       headerlength = -headerlength-2;
  564.     }
  565.     *++ptr=0;
  566.     strcpy(line1, line2);
  567.     break;
  568.       } /* else */
  569.     } /* else */
  570.   } /* for (;;) */
  571. } /* CopyTopic */
  572.  
  573. void configError(void)
  574. {
  575.   errorexit("\nFormat error in configuration file.\n");
  576. } /* configError */
  577.  
  578. void readconfig(void)
  579. /* reads one line from file config to configline */
  580. {
  581.   if ( fgets(configline, sizeof(configline), config) == NULL )
  582.     configError();
  583. } /* readconfig */
  584.  
  585. void openconfig(void)
  586. /* opens configuration file and reads the initial part up to a line starting
  587.    with "=". This code defines how the initial lines are interpreted.
  588.    v. 1.07 defines:
  589.    configline[0] == '=': end of initial part
  590.    configline[0] == ';': comment
  591.    configline[0] == 'W': assign value to WIDTH
  592.    configline[0] == 'M': assign value to maxTopicLength
  593.    configline[0] == 'C': assign true to classification
  594.    The definitions are case sensitive.
  595. */
  596. {
  597.   int confv, confsubv;
  598.   char dummy[128];
  599.   config = fopen(configfile, "r");
  600.   if ( config == NULL )
  601.   {
  602.     fputs("\nWarning: No configuration file.\n", stderr);
  603.     return;
  604.   }
  605.   readconfig();
  606.   if (strncmp(configline, configmarker, strlen(configmarker)))
  607.     configError();
  608.   readconfig();
  609.   if (sscanf(configline, "%u%u", &confv, &confsubv) < 2)
  610.     configError();
  611.   if ((confv = ((confv << 8) + confsubv)) < 0x104)
  612.     errorexit ("\nThe configuration file is incompatible with this"
  613.     " version of INT2GUID");
  614.   if (confv < 0x107)
  615.     return;
  616.   while (!feof(config))
  617.   {
  618.     readconfig();
  619.     switch (configline[0])
  620.     {
  621.       case '=': return; /* done */
  622.       case ';': break; /* comment */
  623.       case 'W':
  624.       case 'M':
  625.     if ( sscanf(configline, "%s%u", &dummy,
  626.       configline[0]=='W' ? &WIDTH : &maxTopicLength) < 2 )
  627.       configError();
  628.     break;
  629.       case 'C': classification = true; break; /* include classification */
  630.       default: fprintf(stderr, "\nWARNING: Error in configuration file:\n%s",
  631.     configline);
  632.     } /* switch */
  633.   } /* while */
  634. } /* openconfig */
  635.  
  636. void copyline(char *str, int len)
  637. /* copies configline (after deleting the terminating '\n') to str
  638.     for max len characters. */
  639. {
  640.   configline[strlen(configline)-1] = 0; /* ignore '\n' */
  641.   strncpy(str, configline, len);
  642.   str[len] = 0; /* edited: v. 1.05 */
  643. } /* copyline */
  644.  
  645. void configure(void)
  646. /* parses configuration file */
  647. {
  648. #define maxHeader 14
  649. #define markerLen 12
  650.   int command, extraTopics, i;
  651.   char header[(maxHeader+2) & 0xFE], marker[(markerLen+2) & 0xFE],
  652.     desc[(76-markerLen) & 0xFE], filename[80];
  653.   /* v. 1.07: initial part moved to openconfig() */
  654.   while ( !feof(config) )
  655.   {
  656.     while ( (fgets(configline, sizeof(configline), config) != NULL)
  657.       && (configline[0] == ';') ) ;
  658.     if feof(config) break;
  659.     copyline(filename, 79);
  660.     readconfig();
  661.     copyline(header, maxHeader);
  662.     readconfig();
  663.     copyline(marker, markerLen);
  664.     i = strlen(marker);
  665.     while ( i<markerLen-1 ) /* pad with spaces if short */
  666.       marker[i++] = ' '; /* is already 0-terminated at markerLen */
  667.     readconfig();
  668.     copyline(desc, 76-markerLen-2);
  669.     i = strlen(desc); /* edited: v. 1.05 */
  670.     desc[i] = '\n';
  671.     desc[++i] = 0;
  672.     readconfig();
  673.     if ( sscanf(configline, "%u%u%i", &command, &extraTopics, &mask) < 3 )
  674.       configError();
  675.  
  676.     StartTopic(header, marker, desc);
  677.     CopyFile(filename, command);
  678.     currentID += extraTopics;
  679.   }
  680.   fclose(config);
  681. #undef maxHeader
  682. #undef markerLen
  683. } /* configure */
  684.  
  685. void main(void)
  686. {
  687.   fprintf(stderr, "\nINT2GUID %s - (c) Kai Uwe Rommel/Bent Lynggaard - %s\n",
  688.     VERSION, __DATE__);
  689.   atexit(exitfunc);
  690.  
  691.   openconfig();
  692.  
  693.   Initialize(); /* uses topic 1 */
  694.  
  695.   fputs("Including:\n",stderr);
  696.   StartTopic("Copyright etc.", "Copyright  ", "and references.\n");
  697.   if ( CopyFile("int2guid.ref", true) ) /* topic 2 */
  698.     errorexit(missingFile);
  699.  
  700.   StartTopic("INTERRUP.LST", "HEADER     ", "Overview of the Interrupt List\n");
  701.   fputs("(See also \4""4\5INTERRUP.1ST\5)\n", output); /* insert reference */
  702.   CopyTopic(); /* topic 3 */
  703.  
  704.   StartTopic("INTERRUP.1ST", "Mail etc.  ", "How to get/update INTERRUP.LST\n");
  705.   if ( CopyFile("interrup.1st", false) ) /* topic 4 */
  706.     errorexit(missingFile);
  707.  
  708.   StartTopic("GUIDE Program", "GUIDE      ", "Popup Reference Engine.\n");
  709.   if ( CopyFile("int2guid.gui", true) ) /* topic 5 */
  710.     errorexit(missingFile);
  711.  
  712.   configure();
  713.  
  714.   indexed = 0;
  715.   indexNo = mainIndex;
  716.  
  717.   while ( RecognizedTopic() )
  718.     CopyTopic();
  719.  
  720.   Cleanup();
  721.  
  722.   exit(0);
  723. }
  724.  
  725. /* End of INT2GUID.C */
  726.