* man2hlp.c (main): Use only stream I/O. Fix checks for error

conditions.  Reformat the whole file.
This commit is contained in:
Pavel Roskin 2002-07-30 22:57:01 +00:00
parent 56a685c3e6
commit 80561f39a7
2 changed files with 199 additions and 169 deletions

View File

@ -1,5 +1,8 @@
2002-07-30 Pavel Roskin <proski@gnu.org> 2002-07-30 Pavel Roskin <proski@gnu.org>
* man2hlp.c (main): Use only stream I/O. Fix checks for error
conditions. Reformat the whole file.
* man2hlp.c: Avoid the need to use gindex.pl. * man2hlp.c: Avoid the need to use gindex.pl.
From Andrew V. Samoilov <sav@bcs.zp.ua> From Andrew V. Samoilov <sav@bcs.zp.ua>
* Makefile.am: Use man2hlp directly. * Makefile.am: Use man2hlp directly.

View File

@ -21,11 +21,6 @@
#include <stdarg.h> #include <stdarg.h>
#include <string.h> #include <string.h>
#include <fcntl.h> /* O_RDONLY, O_WRONLY */
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "help.h" #include "help.h"
#define BUFFER_SIZE 256 #define BUFFER_SIZE 256
@ -54,21 +49,25 @@ static struct node {
} nodes, *cnode; } nodes, *cnode;
/* Report error in input */ /* Report error in input */
static void print_error (char *message) static void
print_error (char *message)
{ {
fprintf (stderr, "man2hlp: %s in file \"%s\" at row %d\n", message, filename, in_row); fprintf (stderr, "man2hlp: %s in file \"%s\" at row %d\n", message,
filename, in_row);
} }
/* Change output line */ /* Change output line */
static void newline (void) static void
newline (void)
{ {
out_row ++; out_row++;
col = 0; col = 0;
printf("\n"); printf ("\n");
} }
/* Calculate the length of string */ /* Calculate the length of string */
static int string_len (char *buffer) static int
string_len (char *buffer)
{ {
static int anchor_flag = 0; /* Flag: Inside hypertext anchor name */ static int anchor_flag = 0; /* Flag: Inside hypertext anchor name */
static int link_flag = 0; /* Flag: Inside hypertext link target name */ static int link_flag = 0; /* Flag: Inside hypertext link target name */
@ -76,32 +75,31 @@ static int string_len (char *buffer)
int c; /* Current character */ int c; /* Current character */
int len = 0; /* Result: the length of the string */ int len = 0; /* Result: the length of the string */
while (*(buffer)) while (*(buffer)) {
{
c = *buffer++; c = *buffer++;
if (c == CHAR_LINK_POINTER) if (c == CHAR_LINK_POINTER)
link_flag = 1; /* Link target name starts */ link_flag = 1; /* Link target name starts */
else if (c == CHAR_LINK_END) else if (c == CHAR_LINK_END)
link_flag = 0; /* Link target name ends */ link_flag = 0; /* Link target name ends */
else if (c == CHAR_NODE_END){ else if (c == CHAR_NODE_END) {
/* Node anchor name starts */ /* Node anchor name starts */
anchor_flag = 1; anchor_flag = 1;
/* Ugly hack to prevent loss of one space */ /* Ugly hack to prevent loss of one space */
len ++; len++;
} }
/* Don't add control characters to the length */ /* Don't add control characters to the length */
if (c >= 0 && c < 32) if (c >= 0 && c < 32)
continue; continue;
/* Attempt to handle backslash quoting */ /* Attempt to handle backslash quoting */
if (c == '\\' && !backslash_flag){ if (c == '\\' && !backslash_flag) {
backslash_flag = 1; backslash_flag = 1;
continue; continue;
} }
backslash_flag = 0; backslash_flag = 0;
/* Increase length if not inside anchor name or link target name */ /* Increase length if not inside anchor name or link target name */
if (!anchor_flag && !link_flag) if (!anchor_flag && !link_flag)
len ++; len++;
if (anchor_flag && c == ']'){ if (anchor_flag && c == ']') {
/* Node anchor name ends */ /* Node anchor name ends */
anchor_flag = 0; anchor_flag = 0;
} }
@ -110,21 +108,22 @@ static int string_len (char *buffer)
} }
/* Output the string */ /* Output the string */
static void print_string (char *buffer) static void
print_string (char *buffer)
{ {
int len; /* The length of current word */ int len; /* The length of current word */
int c; /* Current character */ int c; /* Current character */
int backslash_flag = 0; int backslash_flag = 0;
/* Skipping lines? */ /* Skipping lines? */
if (skip_flag) if (skip_flag)
return; return;
/* Copying verbatim? */ /* Copying verbatim? */
if (verbatim_flag){ if (verbatim_flag) {
/* Attempt to handle backslash quoting */ /* Attempt to handle backslash quoting */
while (*(buffer)){ while (*(buffer)) {
c = *buffer++; c = *buffer++;
if (c == '\\' && !backslash_flag){ if (c == '\\' && !backslash_flag) {
backslash_flag = 1; backslash_flag = 1;
continue; continue;
} }
@ -135,23 +134,22 @@ static void print_string (char *buffer)
/* Split into words */ /* Split into words */
buffer = strtok (buffer, " \t\n"); buffer = strtok (buffer, " \t\n");
/* Repeat for each word */ /* Repeat for each word */
while (buffer){ while (buffer) {
/* Skip empty strings */ /* Skip empty strings */
if (*(buffer)){ if (*(buffer)) {
len = string_len (buffer); len = string_len (buffer);
/* Change the line if about to break the right margin */ /* Change the line if about to break the right margin */
if (col + len >= width) if (col + len >= width)
newline (); newline ();
/* Words are separated by spaces */ /* Words are separated by spaces */
if (col > 0){ if (col > 0) {
printf (" "); printf (" ");
col ++; col++;
} }
/* Attempt to handle backslash quoting */ /* Attempt to handle backslash quoting */
while (*(buffer)) while (*(buffer)) {
{
c = *buffer++; c = *buffer++;
if (c == '\\' && !backslash_flag){ if (c == '\\' && !backslash_flag) {
backslash_flag = 1; backslash_flag = 1;
continue; continue;
} }
@ -163,15 +161,16 @@ static void print_string (char *buffer)
} }
/* Get the next word */ /* Get the next word */
buffer = strtok (NULL, " \t\n"); buffer = strtok (NULL, " \t\n");
} /* while */ } /* while */
} }
} }
/* Like print_string but with printf-like syntax */ /* Like print_string but with printf-like syntax */
static void printf_string (char *format, ...) static void
printf_string (char *format, ...)
{ {
va_list args; va_list args;
char buffer [BUFFER_SIZE]; char buffer[BUFFER_SIZE];
va_start (args, format); va_start (args, format);
vsprintf (buffer, format, args); vsprintf (buffer, format, args);
@ -180,113 +179,111 @@ static void printf_string (char *format, ...)
} }
/* Handle all the roff dot commands */ /* Handle all the roff dot commands */
static void handle_command (char *buffer) static void
handle_command (char *buffer)
{ {
int len, heading_level; int len, heading_level;
/* Get the command name */ /* Get the command name */
strtok (buffer, " \t"); strtok (buffer, " \t");
if ((strcmp (buffer, ".SH") == 0) || (strcmp (buffer, ".\\\"NODE") == 0)){ if ((strcmp (buffer, ".SH") == 0)
|| (strcmp (buffer, ".\\\"NODE") == 0)) {
int SH = (strcmp (buffer, ".SH") == 0); int SH = (strcmp (buffer, ".SH") == 0);
/* If we already skipped a section, don't skip another */ /* If we already skipped a section, don't skip another */
if (skip_flag == 2){ if (skip_flag == 2) {
skip_flag = 0; skip_flag = 0;
} }
/* Get the command parameters */ /* Get the command parameters */
buffer = strtok (NULL, ""); buffer = strtok (NULL, "");
if (buffer == NULL){ if (buffer == NULL) {
print_error ("Syntax error: .SH: no title"); print_error ("Syntax error: .SH: no title");
return; return;
} else { } else {
/* Remove quotes */ /* Remove quotes */
if (buffer[0] == '"'){ if (buffer[0] == '"') {
buffer ++; buffer++;
len = strlen (buffer); len = strlen (buffer);
if (buffer[len-1] == '"'){ if (buffer[len - 1] == '"') {
len --; len--;
buffer[len] = 0; buffer[len] = 0;
} }
} }
/* Calculate heading level */ /* Calculate heading level */
heading_level = 0; heading_level = 0;
while (buffer [heading_level] == ' ') while (buffer[heading_level] == ' ')
heading_level ++; heading_level++;
/* Heading level must be even */ /* Heading level must be even */
if (heading_level & 1) if (heading_level & 1)
print_error ("Syntax error: .SH: odd heading level"); print_error ("Syntax error: .SH: odd heading level");
if (no_split_flag){ if (no_split_flag) {
/* Don't start a new section */ /* Don't start a new section */
newline (); newline ();
print_string (buffer); print_string (buffer);
newline (); newline ();
newline (); newline ();
no_split_flag = 0; no_split_flag = 0;
} } else if (skip_flag) {
else if (skip_flag){
/* Skipping title and marking text for skipping */ /* Skipping title and marking text for skipping */
skip_flag = 2; skip_flag = 2;
} } else {
else { if (!SH || !node) {
if (!SH || !node){ /* Start a new section */
/* Start a new section */ if (!output)
if (!output) printf ("%c[%s]", CHAR_NODE_END, buffer);
printf ("%c[%s]", CHAR_NODE_END, buffer); else {
else { printf ("%c[%s]", CHAR_NODE_END,
printf ("%c[%s]", CHAR_NODE_END, buffer + heading_level); buffer + heading_level);
if (!cnode){ if (!cnode) {
cnode = &nodes; cnode = &nodes;
cnode->next = NULL; cnode->next = NULL;
} else { } else {
cnode->next = malloc (sizeof (nodes)); cnode->next = malloc (sizeof (nodes));
cnode = cnode->next; cnode = cnode->next;
}
cnode->node = strdup (buffer);
cnode->lname = NULL;
} }
cnode->node = strdup (buffer); col++;
cnode->lname = NULL;
}
col ++;
newline (); newline ();
} }
if (SH){ if (SH) {
if (output) if (output)
/* print_string() strtok()es buffer, so */ /* print_string() strtok()es buffer, so */
cnode->lname = strdup (buffer + heading_level); cnode->lname = strdup (buffer + heading_level);
print_string (buffer + heading_level); print_string (buffer + heading_level);
newline (); newline ();
newline (); newline ();
} }
} /* Start new section */ } /* Start new section */
} /* Has parameters */ } /* Has parameters */
node = !SH; node = !SH;
} /* Command .SH */ } /* Command .SH */
else if (strcmp (buffer, ".\\\"DONT_SPLIT\"") == 0){ else if (strcmp (buffer, ".\\\"DONT_SPLIT\"") == 0) {
no_split_flag = 1; no_split_flag = 1;
} } else if (strcmp (buffer, ".\\\"SKIP_SECTION\"") == 0) {
else if (strcmp (buffer, ".\\\"SKIP_SECTION\"") == 0){
skip_flag = 1; skip_flag = 1;
} } else if (strcmp (buffer, ".\\\"LINK2\"") == 0) {
else if (strcmp (buffer, ".\\\"LINK2\"") == 0){
/* Next two input lines form a link */ /* Next two input lines form a link */
link_flag = 2; link_flag = 2;
} } else if (strcmp (buffer, ".PP") == 0) {
else if (strcmp (buffer, ".PP") == 0){
/* End of paragraph */ /* End of paragraph */
if (col > 0) newline(); if (col > 0)
newline ();
newline (); newline ();
} } else if (strcmp (buffer, ".nf") == 0) {
else if (strcmp (buffer, ".nf") == 0){
/* Following input lines are to be handled verbatim */ /* Following input lines are to be handled verbatim */
verbatim_flag = 1; verbatim_flag = 1;
if (col > 0) newline (); if (col > 0)
} newline ();
else if (strcmp (buffer, ".I") == 0 || strcmp (buffer, ".B") == 0){ } else if (strcmp (buffer, ".I") == 0 || strcmp (buffer, ".B") == 0) {
/* Bold text or italics text */ /* Bold text or italics text */
char type = buffer [1]; char type = buffer[1];
char *p; char *p;
char *w = buffer; char *w = buffer;
int backslash_flag = 0; int backslash_flag = 0;
buffer = strtok (NULL, ""); buffer = strtok (NULL, "");
if (buffer == NULL){ if (buffer == NULL) {
print_error ("Syntax error: .I / .B: no text"); print_error ("Syntax error: .I / .B: no text");
return; return;
} }
@ -294,8 +291,8 @@ static void handle_command (char *buffer)
*w = (type == 'I') ? CHAR_ITALIC_ON : CHAR_BOLD_ON; *w = (type == 'I') ? CHAR_ITALIC_ON : CHAR_BOLD_ON;
/* Attempt to handle backslash quoting */ /* Attempt to handle backslash quoting */
for (p = buffer, buffer = w++; *p; p++){ for (p = buffer, buffer = w++; *p; p++) {
if (*p == '\\' && !backslash_flag){ if (*p == '\\' && !backslash_flag) {
backslash_flag = 1; backslash_flag = 1;
continue; continue;
} }
@ -306,19 +303,19 @@ static void handle_command (char *buffer)
*w++ = CHAR_BOLD_OFF; *w++ = CHAR_BOLD_OFF;
*w = 0; *w = 0;
print_string (buffer); print_string (buffer);
} } else if (strcmp (buffer, ".TP") == 0) {
else if (strcmp (buffer, ".TP") == 0){
/* End of paragraph? */ /* End of paragraph? */
if (col > 0) newline (); if (col > 0)
newline ();
newline (); newline ();
} } else if (strcmp (buffer, ".\\\"TOPICS") == 0) {
else if (strcmp (buffer, ".\\\"TOPICS") == 0){ if (out_row > 1) {
if (out_row > 1){ print_error
print_error ("Syntax error: .\\\"TOPICS must be first command"); ("Syntax error: .\\\"TOPICS must be first command");
return; return;
} }
buffer = strtok (NULL, ""); buffer = strtok (NULL, "");
if (buffer == NULL){ if (buffer == NULL) {
print_error ("Syntax error: .\\\"TOPICS: no text"); print_error ("Syntax error: .\\\"TOPICS: no text");
return; return;
} }
@ -326,62 +323,64 @@ static void handle_command (char *buffer)
Topics = strdup (buffer); Topics = strdup (buffer);
else else
printf ("%s\n", buffer); printf ("%s\n", buffer);
} } else {
else {
/* Other commands are ignored */ /* Other commands are ignored */
} }
} }
static void handle_link (char *buffer) static void
handle_link (char *buffer)
{ {
static char old [80]; static char old[80];
int len; int len;
switch (link_flag){ switch (link_flag) {
case 1: case 1:
/* Old format link, not supported */ /* Old format link, not supported */
break; break;
case 2: case 2:
/* First part of new format link */ /* First part of new format link */
/* Bold text or italics text */ /* Bold text or italics text */
if (buffer [0] == '.' && (buffer [1] == 'I' || buffer [1] == 'B')) if (buffer[0] == '.' && (buffer[1] == 'I' || buffer[1] == 'B'))
for (buffer += 2; *buffer == ' ' || *buffer == '\t'; buffer++) for (buffer += 2; *buffer == ' ' || *buffer == '\t'; buffer++);
;
strcpy (old, buffer); strcpy (old, buffer);
link_flag = 3; link_flag = 3;
break; break;
case 3: case 3:
/* Second part of new format link */ /* Second part of new format link */
if (buffer [0] == '.') if (buffer[0] == '.')
buffer++; buffer++;
if (buffer [0] == '\\') if (buffer[0] == '\\')
buffer++; buffer++;
if (buffer [0] == '"') if (buffer[0] == '"')
buffer++; buffer++;
len = strlen (buffer); len = strlen (buffer);
if (len && buffer [len-1] == '"'){ if (len && buffer[len - 1] == '"') {
buffer [--len] = 0; buffer[--len] = 0;
} }
printf_string ("%c%s%c%s%c\n", CHAR_LINK_START, old, CHAR_LINK_POINTER, buffer, CHAR_LINK_END); printf_string ("%c%s%c%s%c\n", CHAR_LINK_START, old,
CHAR_LINK_POINTER, buffer, CHAR_LINK_END);
link_flag = 0; link_flag = 0;
break; break;
} }
} }
int main (int argc, char **argv) int
main (int argc, char **argv)
{ {
int len; /* Length of input line */ int len; /* Length of input line */
FILE *file; /* Input file */ FILE *file; /* Input file */
char buffer2 [BUFFER_SIZE]; /* Temp input line */ FILE *fout; /* Output file */
char buffer2[BUFFER_SIZE]; /* Temp input line */
char *buffer = buffer2; /* Input line */ char *buffer = buffer2; /* Input line */
char *node = NULL; char *node = NULL;
int file_fd; long cont_start, file_end;
long contents_beginning, file_end;
/* Validity check for arguments */ /* Validity check for arguments */
if ((argc != 3 && argc != 5) || ((width = atoi (argv[1])) <= 10)){ if ((argc != 3 && argc != 5) || ((width = atoi (argv[1])) <= 10)) {
fprintf (stderr, "Usage: man2hlp <width> <file.man> [template_file helpfile]\n"); fprintf (stderr,
"Usage: man2hlp <width> <file.man> [template_file helpfile]\n");
return 3; return 3;
} }
@ -391,53 +390,50 @@ int main (int argc, char **argv)
/* Open the input file */ /* Open the input file */
filename = argv[2]; filename = argv[2];
file = fopen (filename, "r"); file = fopen (filename, "r");
if (file == NULL){ if (file == NULL) {
sprintf (buffer, "man2hlp: Cannot open file \"%s\"", filename); sprintf (buffer, "man2hlp: Cannot open file \"%s\"", filename);
perror (buffer); perror (buffer);
return 3; return 3;
} }
if (argc == 5 && freopen (argv [4], "w", stdout) == NULL){ if (argc == 5 && freopen (argv[4], "w", stdout) == NULL) {
sprintf (buffer, "man2hlp: Cannot open file \"%s\"", argv[4]); sprintf (buffer, "man2hlp: Cannot open file \"%s\"", argv[4]);
perror (buffer); perror (buffer);
return 3; return 3;
} }
/* Repeat for each input line */ /* Repeat for each input line */
while (!feof (file)){ while (!feof (file)) {
/* Read a line */ /* Read a line */
if (!fgets (buffer2, BUFFER_SIZE, file)){ if (!fgets (buffer2, BUFFER_SIZE, file)) {
break; break;
} }
if (buffer2 [0] == '\\' && buffer2 [1] == '&') if (buffer2[0] == '\\' && buffer2[1] == '&')
buffer = buffer2 + 2; buffer = buffer2 + 2;
else else
buffer = buffer2; buffer = buffer2;
in_row ++; in_row++;
len = strlen (buffer); len = strlen (buffer);
/* Remove terminating newline */ /* Remove terminating newline */
if (buffer [len-1] == '\n') if (buffer[len - 1] == '\n') {
{ len--;
len --; buffer[len] = 0;
buffer [len] = 0;
} }
if (verbatim_flag){ if (verbatim_flag) {
/* Copy the line verbatim */ /* Copy the line verbatim */
if (strcmp (buffer, ".fi") == 0){ if (strcmp (buffer, ".fi") == 0) {
verbatim_flag = 0; verbatim_flag = 0;
} else { } else {
print_string (buffer); print_string (buffer);
newline (); newline ();
} }
} } else if (link_flag)
else if (link_flag)
/* The line is a link */ /* The line is a link */
handle_link (buffer); handle_link (buffer);
else if (buffer[0] == '.') else if (buffer[0] == '.')
/* The line is a roff command */ /* The line is a roff command */
handle_command (buffer); handle_command (buffer);
else else {
{
/* A normal line, just output it */ /* A normal line, just output it */
print_string (buffer); print_string (buffer);
} }
@ -453,19 +449,19 @@ int main (int argc, char **argv)
/* Open the template file */ /* Open the template file */
filename = argv[3]; filename = argv[3];
file = fopen (filename, "r"); file = fopen (filename, "r");
if (file == NULL){ if (file == NULL) {
sprintf (buffer, "man2hlp: Cannot open file \"%s\"", filename); sprintf (buffer, "man2hlp: Cannot open file \"%s\"", filename);
perror (buffer); perror (buffer);
return 3; return 3;
} }
/* Repeat for each input line */ /* Repeat for each input line */
while (!feof (file)){ while (!feof (file)) {
/* Read a line */ /* Read a line */
if (!fgets (buffer2, BUFFER_SIZE, file)){ if (!fgets (buffer2, BUFFER_SIZE, file)) {
break; break;
} }
if (node){ if (node) {
if (*buffer2 && *buffer2 != '\n'){ if (*buffer2 && *buffer2 != '\n') {
cnode->lname = strdup (buffer2); cnode->lname = strdup (buffer2);
node = strchr (cnode->lname, '\n'); node = strchr (cnode->lname, '\n');
if (node) if (node)
@ -473,43 +469,43 @@ int main (int argc, char **argv)
} }
node = NULL; node = NULL;
} else { } else {
node = strchr (buffer, CHAR_NODE_END); node = strchr (buffer, CHAR_NODE_END);
if (node && (node[1] == '[')){ if (node && (node[1] == '[')) {
char *p = strrchr (node, ']'); char *p = strrchr (node, ']');
if (p && strncmp (node+2, "main", 4) == 0 && node[6] == ']') { if (p && strncmp (node + 2, "main", 4) == 0
node = 0; && node[6] == ']') {
} else { node = 0;
if (!cnode){
cnode = &nodes;
cnode->next = NULL;
} else { } else {
cnode->next = malloc (sizeof (nodes)); if (!cnode) {
cnode = cnode->next; cnode = &nodes;
cnode->next = NULL;
} else {
cnode->next = malloc (sizeof (nodes));
cnode = cnode->next;
}
cnode->node = strdup (node + 2);
cnode->node[p - node - 2] = 0;
cnode->lname = NULL;
} }
cnode->node = strdup (node + 2); } else
cnode->node [p - node - 2] = 0; node = NULL;
cnode->lname = NULL;
}
} else
node = NULL;
} }
fputs (buffer, stdout); fputs (buffer, stdout);
} }
contents_beginning = ftell (stdout); cont_start = ftell (stdout);
printf ("\004[Contents]\n%s\n\n", Topics); printf ("\004[Contents]\n%s\n\n", Topics);
for (cnode = &nodes; cnode && cnode->node; cnode = cnode->next){ for (cnode = &nodes; cnode && cnode->node; cnode = cnode->next) {
char *node = cnode->node; char *node = cnode->node;
int heading_level = 0; int heading_level = 0;
while (*node == ' '){ while (*node == ' ') {
heading_level++; heading_level++;
node++; node++;
} }
if (*node) if (*node)
printf (" %*s\001 %s \002%s\003", heading_level, "", printf (" %*s\001 %s \002%s\003", heading_level, "",
cnode->lname ? cnode->lname : node, cnode->lname ? cnode->lname : node, node);
node);
printf ("\n"); printf ("\n");
free (cnode->node); free (cnode->node);
@ -523,17 +519,48 @@ int main (int argc, char **argv)
fclose (file); fclose (file);
Topics = malloc (file_end); Topics = malloc (file_end);
file_fd = open (output, O_RDONLY); if (!Topics)
if (file_fd == -1) return 1;
fout = fopen (output, "r");
if (!fout) {
perror (output); perror (output);
if (read (file_fd, Topics, file_end) != file_end) return 1;
}
if (fread (Topics, 1, file_end, fout) != file_end) {
perror (output); perror (output);
if (close (file_fd) == -1) return 1;
}
if (fclose (fout) != 0) {
perror (output); perror (output);
file_fd = open (output, O_WRONLY); return 1;
write (file_fd, Topics + contents_beginning, file_end - contents_beginning); }
write (file_fd, Topics, contents_beginning);
close (file_fd); fout = fopen (output, "w");
if (!fout) {
perror (output);
return 1;
}
if (fwrite (Topics + cont_start, 1, file_end - cont_start, fout) !=
file_end - cont_start) {
perror (output);
return 1;
}
if (fwrite (Topics, 1, cont_start, fout) != cont_start) {
perror (output);
return 1;
}
free (Topics);
if (fclose (fout) != 0) {
perror (output);
return 1;
}
return 0; return 0;
} }