home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / TEXT / INFO / INTER30C.ZIP / INT2GUID.ZIP / INT2GUID.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-29  |  15.1 KB  |  567 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 configurate()
  29.  *
  30.  * This program creates output to the standard output device. The output
  31.  * should be redirected to a file INTERRUP.TXT. The created file should
  32.  * be compiled by the TurboPower MAKEHELP program to a INTERRUP.HLP file,
  33.  * which can be interpreted by the TurboPower GUIDE TSR program:
  34.  *    INT2GUID > [ramdisk:]INTERRUP.TXT
  35.  *    MAKEHELP [ramdisk:INTERRUPT] INTERRUP[.HLP] /Q
  36.  *    GUIDE INTERRUP    (or enter GUIDE with a hot key, press F3,
  37.  *            enter INTERRUP)
  38.  *
  39.  * TurboPower Software supplies a program called POPHELP in their Object
  40.  * Professional package, which is a successor to GUIDE. INT2GUID has
  41.  * facilities for conditional interpretation of supplementary files, so
  42.  * these files can include code optimized for both GUIDE and POPHELP, and
  43.  * the parts compiled depends on a mask defined in the configuration file.
  44.  *
  45.  * The following is considered in creating the topic (and popup window)
  46.  * headers:
  47.  * The first word in the header is the interrupt number, so that GUIDE's
  48.  * search mechanism can find the entry if the hot key is pressed when
  49.  * the cursor is at an interrupt number.
  50.  * MAKEHELP restricts the (length of longest header + 1) times the number
  51.  * of topics to 64 kB. INTER191 had about 2200 topics, so the length of
  52.  * the headers should be limited to 25 characters. However, rather than
  53.  * truncating the INTERRUP.LST header lines to some nonsence, this
  54.  * program uses only the interrupt number as topic headings, plus the
  55.  * AH or AX values where applicable.
  56.  * The main index references some subindeces. The subindeces use the
  57.  * MAKEHELP cross reference facility. MAKEHELP limits the number of cross
  58.  * references to 50 per topic, however, this program limits each subindex
  59.  * to 18 entries, so each "topic" can be shown on one single screen with
  60.  * height 20 lines. For each interrupt number, the entries are temporarily
  61.  * stored, and written to the current subindex page only if all entries
  62.  * for the interrupt number fit on the page.
  63.  *
  64.  * MAKEHELP's text wrapping mechanism is disabled, and as the active
  65.  * window is limited to 76 characters, some lines are missing one or two
  66.  * characters.
  67.  * The amount of text that can be displayed per topic is limited by
  68.  * GUIDE's setting of pages/topic (default = 20) and the screen height
  69.  * defined when GUIDE was initialized.
  70.  *
  71.  */
  72.  
  73. #define LABEL    "int2guid.c"
  74. #define VERSION  "1.05"
  75.  
  76. #include <stdio.h>
  77. #include <stdlib.h>
  78. #include <string.h>
  79. #include <ctype.h>
  80.  
  81. #define divider_line(s) (strncmp(s,"--------",8)==0)
  82. #define maxIndeces 18
  83.   /* max 50, 18 gives one page with height 20 (18 active lines) */
  84. #define mainIndex 200
  85.   /* 1-99 reserved for program, 100-199 reserved for user */
  86. #define false 0
  87. #define true 1
  88.  
  89. FILE *input, *output, *topics, *subtopics, *config;
  90.  
  91. char line1[128];
  92. char line2[128];
  93. char tempBuffer[50 * 128];
  94. char *tempPtr;
  95. char category[4] = "--";
  96. char infilename[14] = "interrup.lst";
  97. #define infileExt 9
  98. int splitInfile = 0;
  99.  
  100. char configfile[14] = "int2guid.cfg";
  101. char configmarker[18] = "INT2GUIDE CONFIG";
  102.  
  103. char missingFile[] = "Missing include file.";
  104.  
  105. int sub = 0, indexed = 1;
  106. unsigned currentID = 1, activeID = 1, indeces = 0, indexNo = 0, buffered = 0,
  107.   subindeces, activeSub, mask;
  108.  
  109. void exitfunc(void)
  110. {
  111.   fcloseall();
  112.   unlink("topic.tmp");
  113.   unlink("subtopic.tmp");
  114. }
  115.  
  116. void errorexit(char *msg)
  117. /* writes msg to stderr and exits with error code 1 */
  118. {
  119.   fputs(msg, stderr);
  120.   exit(1);
  121. } /* errorexit */
  122.  
  123. void diskFull(int temporary)
  124. /* reports disk full and exits */
  125. {
  126.   char msg[80];
  127.   sprintf(msg,"\n\nDisk full, %s file\n", temporary ? "temporary" : "output");
  128.   errorexit(msg);
  129. } /* diskFull */
  130.  
  131.  
  132. int _fputs(char *line, FILE *stream)
  133. /* filters TABs to spaces, and inserts a leading space in lines starting
  134.    with the MAKEHELP command and comment characters '!' and ';'. "_fputs"
  135.    should be used when copying from unknown sources. Use "fputs" when
  136.    copying files with information specifically for this program.
  137. */
  138. {
  139.   char buffer[128];
  140.   int cnt = 0;
  141.  
  142.   if ( (*line=='!') || (*line==';') ) /* MAKEHELP command/comment? */
  143.     buffer[cnt++] = ' '; /* start with a space */
  144.  
  145.   while ( *line )
  146.   {
  147.     switch ( *line )
  148.     {
  149.       case '\t': do buffer[cnt++] = ' '; while ( cnt & 7 ); break;
  150.             /* MAKEHELP does not interpret tabs */
  151.       default  : buffer[cnt++] = *line;
  152.     }
  153.     line++;
  154.   }
  155.  
  156.   buffer[cnt] = 0;
  157.  
  158.   if ( (cnt = fputs(buffer, stream)) == EOF )
  159.     diskFull(stream != output);
  160.  
  161.   return cnt;
  162. }
  163.  
  164. char *_fgets(char *s, int n, FILE *stream)
  165. {
  166.   char *ptr;
  167.   ptr = fgets(s, n, stream);
  168.   if ( (ptr==NULL) && (stream==input) && splitInfile )
  169.   {
  170.     fclose(input);
  171.     infilename[infileExt]++;
  172.     input = fopen(infilename, "r");
  173.     if ( input != NULL )
  174.     {
  175.       fprintf(stderr, "%s\n", infilename);
  176.       ptr = fgets(s, n, input);
  177.     }
  178.   }
  179.   return ptr;
  180. } /* _fgets */
  181.  
  182. void Initialize(void)
  183. {
  184.   input     = fopen(infilename, "r");
  185.   if ( input == NULL )
  186.   {
  187.     infilename[infileExt] = 'a';
  188.     infilename[infileExt+1] = 0;
  189.     input = fopen(infilename, "r");
  190.     if ( input == NULL )
  191.     {
  192.       fputs("Cannot open input file (INTERRUP.LST or INTERRUP.A)\n", stderr);
  193.       exit(1);
  194.     }
  195.     splitInfile = 1;
  196.   }
  197.   fprintf(stderr, "%s\n", infilename);
  198.   output    = stdout;
  199.   topics    = fopen("topic.tmp", "w");
  200.   subtopics = fopen("subtopic.tmp", "w");
  201.  
  202.   tempPtr = tempBuffer;
  203.  
  204.   fprintf(output,
  205.     ";INTERRUPT help text for MAKEHELP/GUIDE.\n;\n!WIDTH 80\n;\n");
  206.   fprintf(topics, "!TOPIC 1 Interrupt List\n!INDEX %u\n", mainIndex);
  207. }
  208.  
  209.  
  210. void testTopic(void) /* limit xrefs/topic to maxIndeces */
  211. {
  212.   if ( indeces+buffered >= maxIndeces ) /* leave one entry for forw. ref */
  213.   {
  214.     currentID++;
  215.     fprintf(topics, "\004%u\005INT %s\005 (index continued)\n"
  216.       "!TOPIC %u INT %s (cont)\n!INDEX %u\n"
  217.       "(continued \004%u\005from\005)\n",
  218.       currentID, category, currentID, category, ++indexNo, activeID);
  219.     indeces = 1; /* the backwards ref */
  220.     activeID = currentID;
  221.   }
  222. } /* testTopic */
  223.  
  224. void copyBuffer(void)
  225. {
  226.   if ( buffered == 0 )
  227.     return;
  228.  
  229.   testTopic();
  230.   if ( fputs(tempBuffer, topics) == EOF )
  231.       diskFull(true);
  232.   indeces += buffered;
  233.   buffered = 0;
  234.   tempPtr = tempBuffer;
  235. } /* copyBuffer */
  236.  
  237. void Cleanup(void)
  238. {
  239.   copyBuffer();
  240.   fclose(topics);
  241.   fclose(subtopics);
  242.   fputs("Cleaning up\n", stderr);
  243.  
  244.   topics = fopen("topic.tmp", "r");
  245.   subtopics = fopen("subtopic.tmp", "r");
  246.  
  247.   while ( fgets(line1, sizeof(line1), topics) )
  248.     if ( fputs(line1, output) == EOF )
  249.       diskFull(false);
  250.  
  251.   while ( fgets(line1, sizeof(line1), subtopics) )
  252.     if ( fputs(line1, output) == EOF )
  253.       diskFull(false);
  254. }
  255.  
  256.  
  257. int CopyFile(char *name, int commands)
  258. /* copies a file to the database, returns 0 for success or 1 for error */
  259.  
  260. /* If commands!=0, also interprets lines starting with "!! <number>" as
  261.    an update to variable "condition", and copies lines to the database
  262.    only if condition == 0 or (condition & mask) != 0
  263. */
  264. {
  265.   int condition = 0;
  266.   FILE *temp = fopen(name, "r");
  267.   fprintf(stderr, "%s\n", name);
  268.   if ( temp == NULL )
  269.   {
  270.     fprintf(stderr, "WARNING: Could not open %s\n", name);
  271.     fputs("Information was not available\n", output);
  272.     return 1;
  273.   }
  274.   else
  275.   {
  276.     while ( fgets(line2, sizeof(line2), temp) )
  277.       if ( !commands )
  278.     _fputs(line2, output);
  279.       else
  280.     /* does line start with "!! <number>" ? */
  281.     if ( sscanf(line2, "!!%i", &condition) != 1 )
  282.       /* yes: condition updated, sscanf returns 1 */
  283.       if ( (condition==0) || (condition & mask) )
  284.         fputs(line2, output);
  285.  
  286.     fputs("!NOWRAP\n", output); /* in case it was left in !WRAP state */
  287.     fclose(temp);
  288.     return 0;
  289.   }
  290. } /* CopyFile */
  291.  
  292. void testSubtopic(char *marker)
  293. {
  294.   if ( ++subindeces >= maxIndeces )
  295.   {
  296.     sprintf(tempPtr, "\004%u\005%s\005  (list cont.)\n",
  297.       ++currentID, marker);
  298.     tempPtr += strlen(tempPtr);
  299.     buffered++;
  300.     fprintf(subtopics,
  301.       "\004%u\005%s\005  (list cont.)\n!TOPIC %u %s (list cont)\n!NOINDEX\n"
  302.       "(continued \004%u\005from\005)\n",
  303.       currentID, marker, currentID, category, activeSub);
  304.       activeSub = currentID;
  305.     subindeces = 2;
  306.   }
  307. } /* testSubtopic */
  308.  
  309.  
  310. void StartTopic(char *header, char *marker, char *desc)
  311. {
  312.   if ( sub )
  313.   {
  314.     testSubtopic(marker);
  315.     if ( fprintf(subtopics, "\004%u\005%s\005  %s",
  316.       ++currentID, marker, desc) == EOF )
  317.     diskFull(true);
  318.   }
  319.   else
  320.   {
  321.     sprintf(tempPtr, "\004%u\005%s\005  %s", ++currentID, marker, desc);
  322.     tempPtr += strlen(tempPtr);
  323.     buffered++;
  324.   }
  325.  
  326.   fprintf(output, "!TOPIC %u %s\n", currentID, header);
  327.   if ( indexed )
  328.     indexNo++;
  329.   fprintf(output, indexed ? "!INDEX %u\n" : "!NOINDEX\n", indexNo);
  330. }
  331.  
  332.  
  333. void StartList(void)
  334. {
  335.   sprintf(tempPtr, "\004%u\005INT %s\005  (list)\n",
  336.     ++currentID, category);
  337.   tempPtr += strlen(tempPtr);
  338.   buffered++;
  339.   fprintf(subtopics, "!TOPIC %u %s (list)\n!NOINDEX\n",
  340.     currentID, category);
  341.  
  342.   sub = 1;
  343.   subindeces = 0;
  344.   activeSub = currentID;
  345. }
  346.  
  347.  
  348. /* void EndList(void) - not used */
  349.  
  350.  
  351. /* char *NextID(void) - not used */
  352.  
  353.  
  354. int RecognizedTopic(void)
  355. {
  356.   char *ptr, *pdesc, topic[4], header[16], marker[20];
  357.   int i;
  358.  
  359.   if ( _fgets(line2, sizeof(line2), input) == NULL )
  360.     return 0;
  361.  
  362.   if ( (ptr = strchr(line1, '-')) == NULL )
  363.     return 0;
  364.  
  365.   pdesc = ptr;
  366.   while ( isspace(*--ptr) ) /* through spaces/tabs */
  367.     ;
  368.   while ( !isspace(*--ptr) ) /* through NNh */
  369.     ;
  370.   strncpy(topic, ++ptr, 2); /* interrupt number */
  371.   topic[2] = '\0';
  372.  
  373.   if ( strcmp(category, topic) )
  374.   {
  375.     sub = 0;
  376.     copyBuffer();
  377.     strcpy(category, topic);
  378.     fprintf(stderr, "%s\015", topic); /* show progress */
  379.   }
  380.   else
  381.     fprintf(output, "\004%u\005INT %s\005 (continued)\n",
  382.       currentID+1, topic);
  383.     /* insert a reference to this one in the former topic */
  384.  
  385.   strcpy(header, topic);
  386.  
  387.   for (ptr = line2 ; isspace(*ptr) ; ptr++)
  388.      ;
  389.  
  390.   if ( !strncmp(ptr, "AX =", 4) ||
  391.     !strncmp(ptr, "AH =", 4) ||
  392.     !strncmp(ptr, "AL =", 4)
  393.       )
  394.   {
  395.     for ( i = 5; (tolower(ptr[i]) != 'h') && !isspace(ptr[i]); i++ )
  396.       ;
  397.     if ( i < 11 )
  398.     {
  399.       if ( !sub )
  400.     StartList();
  401.       strcat(header, "  ");
  402.       strncat(header, ptr, i);
  403.     }
  404.   }
  405.  
  406.   strcpy(marker, "INT ");
  407.   strcat(marker, header);
  408.  
  409.   StartTopic(header, marker, pdesc);
  410.  
  411.   _fputs(line1, output);
  412.   if ( !divider_line(line2) )
  413.     _fputs(line2, output);
  414.  
  415.   return 1;
  416. }
  417.  
  418.  
  419. void CopyTopic(void)
  420. {
  421.   if ( divider_line(line2) )
  422.   { /* kludge for one-line interrupts */
  423.     _fgets(line1, sizeof(line2), input);
  424.     return;
  425.   }
  426.  
  427.   for (;;)
  428.   {
  429.     if ( _fgets(line1, sizeof(line1), input) == NULL )
  430.       break;
  431.  
  432.     if ( !divider_line(line1) )
  433.       _fputs(line1, output);
  434.     else
  435.     {
  436.       if ( _fgets(line2, sizeof(line2), input) == NULL )
  437.     break;
  438.  
  439.       if ( strncmp(line2, "INT ", 4) )
  440.       {
  441.     _fputs(line1, output);
  442.     _fputs(line2, output);
  443.       }
  444.       else
  445.       {
  446.     strcpy(line1, line2);
  447.     break;
  448.       }
  449.     }
  450.   }
  451. }
  452.  
  453. void configError(void)
  454. {
  455.   errorexit("\nFormat error in configuration file.\n");
  456. } /* configError */
  457.  
  458. void readconfig(void)
  459. /* reads one line from file config to line2 */
  460. {
  461.   if ( fgets(line2, sizeof(line2), config) == NULL )
  462.     configError();
  463. } /* readconfig */
  464.  
  465. void copyline(char *str, int len)
  466. /* copies line2 (after deleting the terminating '\n') to str
  467.     for max len characters. */
  468. {
  469.   line2[strlen(line2)-1] = 0; /* ignore '\n' */
  470.   strncpy(str, line2, len);
  471.   str[len] = 0; /* edited: v. 1.05 */
  472. } /* copyline */
  473.  
  474. void configurate(void)
  475. /* parses configuration file */
  476. {
  477. #define maxHeader 14
  478. #define markerLen 12
  479.   int confv, confsubv, command, extraTopics, i;
  480.   char header[(maxHeader+2) & 0xFE], marker[(markerLen+2) & 0xFE],
  481.     desc[(76-markerLen) & 0xFE], filename[80];
  482.   config = fopen(configfile, "r");
  483.   if ( config == NULL )
  484.   {
  485.     fputs("\nWarning: No configuration file.\n", stderr);
  486.     return;
  487.   }
  488.   readconfig();
  489.   if ( strncmp(line2, configmarker, strlen(configmarker)) )
  490.     configError();
  491.   readconfig();
  492.   if ( sscanf(line2, "%u%u", &confv, &confsubv) < 2 )
  493.     configError();
  494.   if ( ((confv << 8) + confsubv) < 0x104 )
  495.     errorexit ("\nThe configuration file is incompatible with this"
  496.     " version of INT2GUID");
  497.   while ( !feof(config) )
  498.   {
  499.     while ( (fgets(line2, sizeof(line2), config) != NULL)
  500.       && (line2[0] == ';') ) ;
  501.     if feof(config) break;
  502.     copyline(filename, 79);
  503.     readconfig();
  504.     copyline(header, maxHeader);
  505.     readconfig();
  506.     copyline(marker, markerLen);
  507.     i = strlen(marker);
  508.     while ( i<markerLen-1 ) /* pad with spaces if short */
  509.       marker[i++] = ' '; /* is already 0-terminated at markerLen */
  510.     readconfig();
  511.     copyline(desc, 76-markerLen-2);
  512.     i = strlen(desc); /* edited: v. 1.05 */
  513.     desc[i] = '\n';
  514.     desc[++i] = 0;
  515.     readconfig();
  516.     if ( sscanf(line2, "%u%u%i", &command, &extraTopics, &mask) < 3 )
  517.       configError();
  518.  
  519.     StartTopic(header, marker, desc);
  520.     CopyFile(filename, command);
  521.     currentID += extraTopics;
  522.   }
  523.   fclose(config);
  524. #undef maxHeader
  525. #undef markerLen
  526. } /* configurate */
  527.  
  528. void main(void)
  529. {
  530.   fprintf(stderr, "\nINT2GUID %s - (c) Kai Uwe Rommel/Bent Lynggaard - %s\n",
  531.     VERSION, __DATE__);
  532.   atexit(exitfunc);
  533.  
  534.   Initialize(); /* uses topic 1 */
  535.  
  536.   fputs("Including:\n",stderr);
  537.   StartTopic("Copyright etc.", "Copyright  ", "and references.\n");
  538.   if ( CopyFile("int2guid.ref", true) ) /* topic 2 */
  539.     errorexit(missingFile);
  540.  
  541.   StartTopic("INTERRUP.LST", "HEADER     ", "Overview of the Interrupt List\n");
  542.   fputs("(See also \4""4\5INTERRUP.1ST\5)\n", output); /* insert reference */
  543.   CopyTopic(); /* topic 3 */
  544.  
  545.   StartTopic("INTERRUP.1ST", "Mail etc.  ", "How to get/update INTERRUP.LST\n");
  546.   if ( CopyFile("interrup.1st", false) ) /* topic 4 */
  547.     errorexit(missingFile);
  548.  
  549.   StartTopic("GUIDE Program", "GUIDE      ", "Popup Reference Engine.\n");
  550.   if ( CopyFile("int2guid.gui", true) ) /* topic 5 */
  551.     errorexit(missingFile);
  552.  
  553.   configurate();
  554.  
  555.   indexed = 0;
  556.   indexNo = mainIndex;
  557.  
  558.   while ( RecognizedTopic() )
  559.     CopyTopic();
  560.  
  561.   Cleanup();
  562.  
  563.   exit(0);
  564. }
  565.  
  566. /* End of INT2GUID.C */
  567.