home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / src / man2hlp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  14.5 KB  |  534 lines

  1. /* Man page to help file converter
  2.    Copyright (C) 1994, 1995 Janne Kukonlehto
  3.    
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.    
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #include <config.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <stdarg.h>
  22. #include <string.h>
  23. #include "help.h"
  24.  
  25. #define BUFFER_SIZE 256
  26.  
  27. static char *filename;        /* The name of the input file */
  28. static int width;        /* Output width in characters */
  29. static int col = 0;        /* Current output column */
  30. static FILE *index_file;    /* HTML index file */
  31. static int out_row = 1;        /* Current output row */
  32. static int in_row = 0;        /* Current input row */
  33. static int old_heading_level = 0;/* Level of the last heading */
  34. static int no_split_flag = 0;    /* Flag: Don't split section on next ".SH" */
  35. static int skip_flag = 0;    /* Flag: Skip this section.
  36.                    0 = don't skip,
  37.                    1 = skipping title,
  38.                    2 = title skipped, skipping text */
  39. static int link_flag = 0;    /* Flag: Next line is a link */
  40. static int verbatim_flag = 0;    /* Flag: Copy input to output verbatim */
  41.  
  42. /* Report error in input */
  43. void print_error (char *message)
  44. {
  45.     fprintf (stderr, "man2hlp: %s in file \"%s\" at row %d\n", message, filename, in_row);
  46. }
  47.  
  48. /* Change output line */
  49. void newline (void)
  50. {
  51.     out_row ++;
  52.     col = 0;
  53.     printf("\n");
  54. }
  55.  
  56. /* Calculate the length of string */
  57. int string_len (char *buffer)
  58. {
  59.     static int anchor_flag = 0;    /* Flag: Inside hypertext anchor name */
  60.     static int link_flag = 0;    /* Flag: Inside hypertext link target name */
  61.     int backslash_flag = 0;    /* Flag: Backslash quoting */
  62.     int i;            /* Index */
  63.     int c;            /* Current character */
  64.     int len = 0;        /* Result: the length of the string */
  65.  
  66.     for (i = 0; i < strlen (buffer); i ++)
  67.     {
  68.     c = buffer [i];
  69.     if (c == CHAR_LINK_POINTER) 
  70.         link_flag = 1;    /* Link target name starts */
  71.     else if (c == CHAR_LINK_END)
  72.         link_flag = 0;    /* Link target name ends */
  73.     else if (c == CHAR_NODE_END){
  74.         /* Node anchor name starts */
  75.         anchor_flag = 1;
  76.         /* Ugly hack to prevent loss of one space */
  77.         len ++;
  78.     }
  79.     /* Don't add control characters to the length */
  80.     if (c < 32)
  81.         continue;
  82.     /* Attempt to handle backslash quoting */
  83.     if (c == '\\' && !backslash_flag){
  84.         backslash_flag = 1;
  85.         continue;
  86.     }
  87.     backslash_flag = 0;
  88.     /* Increase length if not inside anchor name or link target name */
  89.     if (!anchor_flag && !link_flag)
  90.         len ++;
  91.     if (anchor_flag && c == ']'){
  92.         /* Node anchor name ends */
  93.         anchor_flag = 0;
  94.     }
  95.     }
  96.     return len;
  97. }
  98.  
  99. /* Output the string */
  100. void print_string (char *buffer)
  101. {
  102.     int len;    /* The length of current word */
  103.     int i;    /* Index */
  104.     int c;    /* Current character */
  105.     int backslash_flag = 0;
  106.  
  107.     /* Skipping lines? */
  108.     if (skip_flag)
  109.     return;
  110.     /* Copying verbatim? */
  111.     if (verbatim_flag){
  112.     printf("%s", buffer);
  113.     return;
  114.     }
  115.     if (width){
  116.     /* HLP format */
  117.     /* Split into words */
  118.     buffer = strtok (buffer, " \t\n");
  119.     /* Repeat for each word */
  120.     while (buffer){
  121.         /* Skip empty strings */  
  122.         if (strlen (buffer) > 0){
  123.         len = string_len (buffer);
  124.         /* Change the line if about to break the right margin */
  125.         if (col + len >= width)
  126.             newline ();
  127.         /* Words are separated by spaces */
  128.         if (col > 0){
  129.             printf (" ");
  130.             col ++;
  131.         }
  132.         /* Attempt to handle backslash quoting */
  133.         for (i = 0; i < strlen (buffer); i++)
  134.         {
  135.             c = buffer [i];
  136.             if (c == '\\' && !backslash_flag){
  137.             backslash_flag = 1;
  138.             continue;
  139.             }
  140.             backslash_flag = 0;
  141.             printf ("%c", c);
  142.         }
  143.         /* Increase column */
  144.         col += len;
  145.         }
  146.         /* Get the next word */
  147.         buffer = strtok (NULL, " \t\n");
  148.     } /* while */
  149.     } else {
  150.     /* HTML format */
  151.     if (strlen (buffer) > 0){
  152.         /* Attempt to handle backslash quoting */
  153.         for (i = 0; i < strlen (buffer); i++)
  154.         {
  155.         c = buffer [i];
  156.         if (c == '\\' && !backslash_flag){
  157.             backslash_flag = 1;
  158.             continue;
  159.         }
  160.         backslash_flag = 0;
  161.         printf ("%c", c);
  162.         }
  163.     }
  164.     } /* if (width) */
  165. }
  166.  
  167. /* Like print_string but with printf-like syntax */
  168. void printf_string (char *format, ...)
  169. {
  170.     va_list args;
  171.     char buffer [BUFFER_SIZE];
  172.  
  173.     va_start (args, format);
  174.     vsprintf (buffer, format, args);
  175.     va_end (args);
  176.     print_string (buffer);
  177. }
  178.  
  179. /* Handle all the roff dot commands */
  180. void handle_command (char *buffer)
  181. {
  182.     int i, len, heading_level;
  183.  
  184.     /* Get the command name */
  185.     strtok (buffer, " \t");
  186.     if (strcmp (buffer, ".SH") == 0){
  187.     /* If we already skipped a section, don't skip another */
  188.     if (skip_flag == 2){
  189.         skip_flag = 0;
  190.     }
  191.     /* Get the command parameters */
  192.     buffer = strtok (NULL, "");
  193.     if (buffer == NULL){
  194.         print_error ("Syntax error: .SH: no title");
  195.         return;
  196.     } else {
  197.         /* Remove quotes */
  198.         if (buffer[0] == '"'){
  199.         buffer ++;
  200.         len = strlen (buffer);
  201.         if (buffer[len-1] == '"'){
  202.             len --;
  203.             buffer[len] = 0;
  204.         }
  205.         }
  206.         /* Calculate heading level */
  207.         heading_level = 0;
  208.         while (buffer [heading_level] == ' ')
  209.         heading_level ++;
  210.         /* Heading level must be even */
  211.         if (heading_level & 1)
  212.         print_error ("Syntax error: .SH: odd heading level");
  213.         if (no_split_flag){
  214.         /* Don't start a new section */
  215.         if (width){
  216.             /* HLP format */
  217.             newline ();
  218.             print_string (buffer);
  219.             newline ();
  220.             newline ();
  221.         } else {
  222.             /* HTML format */
  223.             newline ();
  224.             printf_string ("<h4>%s</h4>", buffer);
  225.             newline ();
  226.         }
  227.         no_split_flag = 0;
  228.         }
  229.         else if (skip_flag){
  230.         /* Skipping title and marking text for skipping */
  231.         skip_flag = 2;
  232.         }
  233.         else {
  234.         /* Start a new section */
  235.         if (width){
  236.             /* HLP format */
  237.             printf ("%c[%s]", CHAR_NODE_END, buffer);
  238.             col ++;
  239.             newline ();
  240.             print_string (buffer + heading_level);
  241.             newline ();
  242.             newline ();
  243.         } else {
  244.             /* HTML format */
  245.             if (buffer [0]){
  246.             if (heading_level > old_heading_level){
  247.                 for (i = old_heading_level; i < heading_level; i += 2)
  248.                 fprintf (index_file, "<ul>");
  249.             } else {
  250.                 for (i = heading_level; i < old_heading_level; i += 2)
  251.                 fprintf (index_file, "</ul>");
  252.             }
  253.             old_heading_level = heading_level;
  254.             printf_string ("<h%d><a name=\"%s\">%s</a></h%d>",
  255.                        heading_level / 2 + 2, buffer + heading_level,
  256.                        buffer + heading_level, heading_level / 2 + 2);
  257.             newline ();
  258.             fprintf (index_file, "<li><a href=\"#%s\">%s</a>\n",
  259.                  buffer + heading_level, buffer + heading_level);
  260.             } else {
  261.             for (i = 0; i < old_heading_level; i += 2)
  262.                 fprintf (index_file, "</ul>");
  263.             old_heading_level = 0;
  264.             fprintf (index_file, "</ul><p><ul>\n");
  265.             }
  266.         } /* if (width) */
  267.         } /* Start new section */
  268.     } /* Has parameters */
  269.     } /* Command .SH */
  270.     else if (strcmp (buffer, ".\\\"DONT_SPLIT\"") == 0){
  271.     no_split_flag = 1;
  272.     }
  273.     else if (strcmp (buffer, ".\\\"SKIP_SECTION\"") == 0){
  274.     skip_flag = 1;
  275.     }
  276.     else if (strcmp (buffer, ".\\\"LINK\"") == 0){
  277.     /* Next input line is a link */
  278.     link_flag = 1;
  279.     }
  280.     else if (strcmp (buffer, ".\\\"LINK2\"") == 0){
  281.     /* Next two input lines form a link */
  282.     link_flag = 2;
  283.     }
  284.     else if (strcmp (buffer, ".PP") == 0){
  285.     /* End of paragraph */
  286.     if (width){
  287.         /* HLP format */
  288.         if (col > 0) newline();
  289.     } else /* HTML format */
  290.         print_string ("<p>");
  291.     newline ();
  292.     }
  293.     else if (strcmp (buffer, ".nf") == 0){
  294.     /* Following input lines are to be handled verbatim */
  295.     verbatim_flag = 1;
  296.     if (width){
  297.         /* HLP format */
  298.         if (col > 0) newline ();
  299.     } else {
  300.         /* HTML format */
  301.         print_string ("<pre>");
  302.         newline ();
  303.     }
  304.     }
  305.     else if (strcmp (buffer, ".I") == 0 || strcmp (buffer, ".B") == 0){
  306.     /* Bold text or italics text */
  307.     char type = buffer [1];
  308.  
  309.     buffer = strtok (NULL, "");
  310.     if (buffer == NULL){
  311.         print_error ("Syntax error: .I / .B: no text");
  312.         return;
  313.     }
  314.     else {
  315.         if (!width){
  316.         /* HTML format */
  317.         /* Remove quotes */
  318.         if (buffer[0] == '"'){
  319.             buffer ++;
  320.             len = strlen (buffer);
  321.             if (buffer[len-1] == '"'){
  322.             len --;
  323.             buffer[len] = 0;
  324.             }
  325.         }
  326.         printf_string ("<%c>%s</%c>", type, buffer, type);
  327.         newline ();
  328.         } else /* HLP format */
  329.         printf_string ("%c%s%c", 
  330.             (type == 'I') ? CHAR_ITALIC_ON : CHAR_BOLD_ON, 
  331.             buffer, CHAR_BOLD_OFF);
  332.     }
  333.     }
  334.     else if (strcmp (buffer, ".TP") == 0){
  335.     /* End of paragraph? */
  336.     if (width){
  337.         /* HLP format */
  338.         if (col > 0) newline ();
  339.     } else {
  340.         /* HTML format */
  341.         print_string ("<p>");
  342.     }
  343.     newline ();
  344.     }
  345.     else {
  346.     /* Other commands are ignored */
  347.     }
  348. }
  349.  
  350. void handle_link (char *buffer)
  351. {
  352.     static char old [80];
  353.     int len;
  354.  
  355.     switch (link_flag){
  356.     case 1:
  357.     /* Old format link */
  358.     if (width) /* HLP format */
  359.         printf_string ("%c%s%c%s%c\n", CHAR_LINK_START, buffer, CHAR_LINK_POINTER, buffer, CHAR_LINK_END);
  360.     else {
  361.         /* HTML format */
  362.         printf_string ("<a href=\"#%s\">%s</a>", buffer, buffer);
  363.         newline ();
  364.     }
  365.     link_flag = 0;
  366.     break;
  367.     case 2:
  368.     /* First part of new format link */
  369.     strcpy (old, buffer);
  370.     link_flag = 3;
  371.     break;
  372.     case 3:
  373.     /* Second part of new format link */
  374.     if (buffer [0] == '.')
  375.         buffer++;
  376.     if (buffer [0] == '\\')
  377.         buffer++;
  378.     if (buffer [0] == '"')
  379.         buffer++;
  380.     len = strlen (buffer);
  381.     if (len && buffer [len-1] == '"'){
  382.         buffer [--len] = 0;
  383.     }
  384.     if (width) /* HLP format */
  385.         printf_string ("%c%s%c%s%c\n", CHAR_LINK_START, old, CHAR_LINK_POINTER, buffer, CHAR_LINK_END);
  386.     else {
  387.         /* HTML format */
  388.         printf_string ("<a href=\"#%s\">%s</a>", buffer, old);
  389.         newline ();
  390.     }
  391.     link_flag = 0;
  392.     break;
  393.     }
  394. }
  395.  
  396. int main (int argc, char **argv)
  397. {
  398.     int len;            /* Length of input line */
  399.     FILE *file;            /* Input file */
  400.     char buffer2 [BUFFER_SIZE];    /* Temp input line */
  401.     char buffer [BUFFER_SIZE];    /* Input line */
  402.     int i, j;
  403.  
  404.     /* Validity check for arguments */
  405.     if (argc != 3 || (strcmp (argv[1], "0") && (width = atoi (argv[1])) <= 10)){
  406.     fprintf (stderr, "Usage: man2hlp <width> <file.man>\n");
  407.     fprintf (stderr, "zero width will create a html file instead of a hlp file\n");
  408.     return 3;
  409.     }
  410.  
  411.     /* Open the input file */
  412.     filename = argv[2];
  413.     file = fopen (filename, "r");
  414.     if (file == NULL){
  415.     sprintf (buffer, "man2hlp: Can't open file \"%s\"", filename);
  416.     perror (buffer);
  417.     return 3;
  418.     }
  419.  
  420.     if (!width){
  421.     /* HTML format */
  422.     index_file = fopen ("index.html", "w");
  423.     if (index_file == NULL){
  424.         perror ("man2hlp: Can't open file \"index.html\"");
  425.         return 3;
  426.     }
  427.     fprintf (index_file, "<html><head><title>Midnight Commander manual</title>\n");
  428.     fprintf (index_file, "</head><body><pre><img src=\"mc.logo.small.gif\" width=180 height=85 align=\"right\" alt=\""
  429.          "                                                                            \n"
  430.          "______________           ____                          ____                 \n"
  431.          "|////////////#           |//#                          |//#                 \n"
  432.          "|//##+//##+//#           |//#                          |//#                 \n"
  433.          "|//# |//# |//# ____      |//#           ____           |//#                 \n"
  434.          "|//# |//# |//# |//#      |//#           |//#           |//#                 \n"
  435.          "|//# |//# |//# +###      |//#           +###           |//#        ____     \n"
  436.          "|//# |//# |//# ____ _____|//# _________ ____ _________ |//#______ _|//#__   \n"
  437.          "|@@# |@@# |@/# |//# |///////# |///////# |//# |///////# |////////# |/////#   \n"
  438.          "|@@# |@@# |@@# |@/# |//##+//# |//##+//# |//# |//##+//# |//###+//# +#/@###   \n"
  439.          "|@@# |@@# |@@# |@@# |@@# |@@# |@/# |//# |//# |//# |/@# |@@#  |@@#  |@@# ____\n"
  440.          "|@@# |@@# |@@# |@@# |@@#_|@@# |@@# |@@# |@@# |@@#_|@@# |@@#  |@@#  |@@#_|@@#\n"
  441.          "|@@# |@@# |@@# |@@# |@@@@@@@# |@@# |@@# |@@# |@@@@@@@# |@@#  |@@#  |@@@@@@@#\n"
  442.          "+### +### +### +### +######## +### +### +### +####+@@# +###  +###  +########\n"
  443.          "           _______________________________________|@@#                      \n"
  444.          "           |@@@@@@@@@@@ C O M M A N D E R @@@@@@@@@@@#                      \n"
  445.          "           +##########################################                      \n"
  446.          "                                                                            \n"
  447.          "\"></pre><h1>Manual</h1>\nThis is the manual for Midnight Commander version %s.\n"
  448.          "This HTML version of the manual has been compiled from the NROFF version at %s.<p>\n",
  449.          VERSION, __DATE__);
  450.     fprintf (index_file, "<hr><h2>Contents</h2><ul>\n");
  451.     }
  452.  
  453.     /* Repeat for each input line */
  454.     while (!feof (file)){
  455.     /* Read a line */
  456.     if (!fgets (buffer2, BUFFER_SIZE, file)){
  457.         break;
  458.     }
  459.     if (!width){
  460.         /* HTML format */
  461.         if (buffer2 [0] == '\\' && buffer2 [1] == '&')
  462.         i = 2;
  463.         else
  464.         i = 0;
  465.         for (j = 0; i < strlen (buffer2); i++, j++){
  466.         if (buffer2 [i] == '<'){
  467.             buffer [j++] = '&';
  468.             buffer [j++] = 'l';
  469.             buffer [j++] = 't';
  470.             buffer [j] = ';';
  471.         } else if (buffer2 [i] == '>'){
  472.             buffer [j++] = '&';
  473.             buffer [j++] = 'g';
  474.             buffer [j++] = 't';
  475.             buffer [j] = ';';
  476.         } else
  477.             buffer [j] = buffer2 [i];
  478.         }
  479.         buffer [j] = 0;
  480.     } else {
  481.         /* HLP format */
  482.         if (buffer2 [0] == '\\' && buffer2 [1] == '&')
  483.         strcpy (buffer, buffer2 + 2);
  484.         else
  485.         strcpy (buffer, buffer2);
  486.     }
  487.     in_row ++;
  488.     len = strlen (buffer);
  489.     /* Remove terminating newline */
  490.     if (buffer [len-1] == '\n')
  491.     {
  492.         len --;
  493.         buffer [len] = 0;
  494.     }
  495.     if (verbatim_flag){
  496.         /* Copy the line verbatim */
  497.         if (strcmp (buffer, ".fi") == 0){
  498.         verbatim_flag = 0;
  499.             if (!width) print_string ("</pre>"); /* HTML format */
  500.         } else {
  501.         print_string (buffer);
  502.         newline ();
  503.         }
  504.     }
  505.     else if (link_flag)
  506.         /* The line is a link */
  507.         handle_link (buffer);
  508.     else if (buffer[0] == '.')
  509.         /* The line is a roff command */
  510.         handle_command (buffer);
  511.     else
  512.     {
  513.         /* A normal line, just output it */
  514.         print_string (buffer);
  515.         if (!width)    newline (); /* HTML format */
  516.     }
  517.     }
  518.  
  519.     /* All done */
  520.     newline ();
  521.     if (!width){
  522.     /* HTML format */
  523.     print_string ("<hr></body></html>");
  524.     newline ();
  525.     for (i = 0; i < old_heading_level; i += 2)
  526.         fprintf (index_file, "</ul>");
  527.     old_heading_level = 0;
  528.     fprintf (index_file, "</ul><hr>\n");
  529.     fclose (index_file);
  530.     }
  531.     fclose (file);
  532.     return 0;
  533. }
  534.