1998-02-27 07:54:42 +03:00
|
|
|
/* Man page to help file converter
|
|
|
|
Copyright (C) 1994, 1995 Janne Kukonlehto
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
2000-08-23 02:50:00 +04:00
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <string.h>
|
2002-07-31 02:20:26 +04:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
#include "help.h"
|
|
|
|
|
|
|
|
#define BUFFER_SIZE 256
|
|
|
|
|
|
|
|
static int width; /* Output width in characters */
|
|
|
|
static int col = 0; /* Current output column */
|
|
|
|
static int out_row = 1; /* Current output row */
|
|
|
|
static int in_row = 0; /* Current input row */
|
|
|
|
static int no_split_flag = 0; /* Flag: Don't split section on next ".SH" */
|
|
|
|
static int skip_flag = 0; /* Flag: Skip this section.
|
|
|
|
0 = don't skip,
|
|
|
|
1 = skipping title,
|
|
|
|
2 = title skipped, skipping text */
|
|
|
|
static int link_flag = 0; /* Flag: Next line is a link */
|
|
|
|
static int verbatim_flag = 0; /* Flag: Copy input to output verbatim */
|
2002-02-28 17:38:38 +03:00
|
|
|
static int node = 0; /* Flag: This line is an original ".SH" */
|
1998-02-27 07:54:42 +03:00
|
|
|
|
2002-08-20 20:13:13 +04:00
|
|
|
static const char *c_out; /* Output filename */
|
|
|
|
static FILE *f_out; /* Output file */
|
|
|
|
|
2002-07-31 02:20:26 +04:00
|
|
|
static char *Topics = "Topics:";
|
|
|
|
|
|
|
|
static struct node {
|
|
|
|
char *node;
|
|
|
|
char *lname;
|
|
|
|
struct node *next;
|
|
|
|
} nodes, *cnode;
|
|
|
|
|
2002-08-16 20:48:27 +04:00
|
|
|
#define MAX_STREAM_BLOCK 8192
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read in blocks of reasonable size and make sure we read everything.
|
|
|
|
* Failure to read everything is an error.
|
|
|
|
*/
|
|
|
|
static size_t
|
|
|
|
persistent_fread (void *data, size_t len, FILE * stream)
|
|
|
|
{
|
|
|
|
size_t count;
|
|
|
|
size_t bytes_done = 0;
|
|
|
|
char *ptr = (char *) data;
|
|
|
|
|
|
|
|
while (bytes_done < len) {
|
|
|
|
count = len - bytes_done;
|
|
|
|
if (count > MAX_STREAM_BLOCK)
|
|
|
|
count = MAX_STREAM_BLOCK;
|
|
|
|
|
|
|
|
count = fread (ptr, 1, count, stream);
|
|
|
|
|
|
|
|
if (count <= 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
bytes_done += count;
|
|
|
|
ptr += count;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bytes_done;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Write in blocks of reasonable size and make sure we write everything.
|
|
|
|
* Failure to write everything is an error.
|
|
|
|
*/
|
|
|
|
static size_t
|
|
|
|
persistent_fwrite (const void *data, size_t len, FILE * stream)
|
|
|
|
{
|
|
|
|
size_t count;
|
|
|
|
size_t bytes_done = 0;
|
|
|
|
const char *ptr = (const char *) data;
|
|
|
|
|
|
|
|
while (bytes_done < len) {
|
|
|
|
count = len - bytes_done;
|
|
|
|
if (count > MAX_STREAM_BLOCK)
|
|
|
|
count = MAX_STREAM_BLOCK;
|
|
|
|
|
|
|
|
count = fwrite (ptr, 1, count, stream);
|
|
|
|
|
|
|
|
if (count <= 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
bytes_done += count;
|
|
|
|
ptr += count;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bytes_done;
|
|
|
|
}
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Report error in input */
|
2002-07-31 02:57:01 +04:00
|
|
|
static void
|
|
|
|
print_error (char *message)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2002-07-31 02:57:01 +04:00
|
|
|
fprintf (stderr, "man2hlp: %s in file \"%s\" at row %d\n", message,
|
2002-08-20 20:13:13 +04:00
|
|
|
c_out, in_row);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Change output line */
|
2002-07-31 02:57:01 +04:00
|
|
|
static void
|
|
|
|
newline (void)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2002-07-31 02:57:01 +04:00
|
|
|
out_row++;
|
1998-02-27 07:54:42 +03:00
|
|
|
col = 0;
|
2002-08-20 20:13:13 +04:00
|
|
|
fprintf (f_out, "\n");
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Calculate the length of string */
|
2002-07-31 02:57:01 +04:00
|
|
|
static int
|
|
|
|
string_len (char *buffer)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
static int anchor_flag = 0; /* Flag: Inside hypertext anchor name */
|
|
|
|
static int link_flag = 0; /* Flag: Inside hypertext link target name */
|
|
|
|
int backslash_flag = 0; /* Flag: Backslash quoting */
|
|
|
|
int c; /* Current character */
|
|
|
|
int len = 0; /* Result: the length of the string */
|
|
|
|
|
2002-07-31 02:57:01 +04:00
|
|
|
while (*(buffer)) {
|
2002-02-28 17:12:34 +03:00
|
|
|
c = *buffer++;
|
2002-07-31 02:57:01 +04:00
|
|
|
if (c == CHAR_LINK_POINTER)
|
1998-02-27 07:54:42 +03:00
|
|
|
link_flag = 1; /* Link target name starts */
|
|
|
|
else if (c == CHAR_LINK_END)
|
|
|
|
link_flag = 0; /* Link target name ends */
|
2002-07-31 02:57:01 +04:00
|
|
|
else if (c == CHAR_NODE_END) {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Node anchor name starts */
|
|
|
|
anchor_flag = 1;
|
|
|
|
/* Ugly hack to prevent loss of one space */
|
2002-07-31 02:57:01 +04:00
|
|
|
len++;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
/* Don't add control characters to the length */
|
2002-02-22 08:54:00 +03:00
|
|
|
if (c >= 0 && c < 32)
|
1998-02-27 07:54:42 +03:00
|
|
|
continue;
|
|
|
|
/* Attempt to handle backslash quoting */
|
2002-07-31 02:57:01 +04:00
|
|
|
if (c == '\\' && !backslash_flag) {
|
1998-02-27 07:54:42 +03:00
|
|
|
backslash_flag = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
backslash_flag = 0;
|
|
|
|
/* Increase length if not inside anchor name or link target name */
|
|
|
|
if (!anchor_flag && !link_flag)
|
2002-07-31 02:57:01 +04:00
|
|
|
len++;
|
|
|
|
if (anchor_flag && c == ']') {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Node anchor name ends */
|
|
|
|
anchor_flag = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Output the string */
|
2002-07-31 02:57:01 +04:00
|
|
|
static void
|
|
|
|
print_string (char *buffer)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2002-07-31 02:57:01 +04:00
|
|
|
int len; /* The length of current word */
|
|
|
|
int c; /* Current character */
|
1998-02-27 07:54:42 +03:00
|
|
|
int backslash_flag = 0;
|
|
|
|
|
|
|
|
/* Skipping lines? */
|
|
|
|
if (skip_flag)
|
|
|
|
return;
|
|
|
|
/* Copying verbatim? */
|
2002-07-31 02:57:01 +04:00
|
|
|
if (verbatim_flag) {
|
2001-08-16 05:36:41 +04:00
|
|
|
/* Attempt to handle backslash quoting */
|
2002-07-31 02:57:01 +04:00
|
|
|
while (*(buffer)) {
|
2002-02-28 17:12:34 +03:00
|
|
|
c = *buffer++;
|
2002-07-31 02:57:01 +04:00
|
|
|
if (c == '\\' && !backslash_flag) {
|
2001-08-16 05:36:41 +04:00
|
|
|
backslash_flag = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
backslash_flag = 0;
|
2002-08-20 20:13:13 +04:00
|
|
|
fprintf (f_out, "%c", c);
|
2001-08-16 05:36:41 +04:00
|
|
|
}
|
|
|
|
} else {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Split into words */
|
|
|
|
buffer = strtok (buffer, " \t\n");
|
|
|
|
/* Repeat for each word */
|
2002-07-31 02:57:01 +04:00
|
|
|
while (buffer) {
|
|
|
|
/* Skip empty strings */
|
|
|
|
if (*(buffer)) {
|
1998-02-27 07:54:42 +03:00
|
|
|
len = string_len (buffer);
|
|
|
|
/* Change the line if about to break the right margin */
|
|
|
|
if (col + len >= width)
|
|
|
|
newline ();
|
|
|
|
/* Words are separated by spaces */
|
2002-07-31 02:57:01 +04:00
|
|
|
if (col > 0) {
|
2002-08-20 20:13:13 +04:00
|
|
|
fprintf (f_out, " ");
|
2002-07-31 02:57:01 +04:00
|
|
|
col++;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
/* Attempt to handle backslash quoting */
|
2002-07-31 02:57:01 +04:00
|
|
|
while (*(buffer)) {
|
2002-02-28 17:38:38 +03:00
|
|
|
c = *buffer++;
|
2002-07-31 02:57:01 +04:00
|
|
|
if (c == '\\' && !backslash_flag) {
|
1998-02-27 07:54:42 +03:00
|
|
|
backslash_flag = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
backslash_flag = 0;
|
2002-08-20 20:13:13 +04:00
|
|
|
fprintf (f_out, "%c", c);
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
/* Increase column */
|
|
|
|
col += len;
|
|
|
|
}
|
|
|
|
/* Get the next word */
|
|
|
|
buffer = strtok (NULL, " \t\n");
|
2002-07-31 02:57:01 +04:00
|
|
|
} /* while */
|
2001-08-16 05:36:41 +04:00
|
|
|
}
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Like print_string but with printf-like syntax */
|
2002-07-31 02:57:01 +04:00
|
|
|
static void
|
|
|
|
printf_string (char *format, ...)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
va_list args;
|
2002-07-31 02:57:01 +04:00
|
|
|
char buffer[BUFFER_SIZE];
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
va_start (args, format);
|
|
|
|
vsprintf (buffer, format, args);
|
|
|
|
va_end (args);
|
|
|
|
print_string (buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle all the roff dot commands */
|
2002-07-31 02:57:01 +04:00
|
|
|
static void
|
|
|
|
handle_command (char *buffer)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2001-08-16 05:36:41 +04:00
|
|
|
int len, heading_level;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
/* Get the command name */
|
|
|
|
strtok (buffer, " \t");
|
2002-07-31 02:57:01 +04:00
|
|
|
if ((strcmp (buffer, ".SH") == 0)
|
|
|
|
|| (strcmp (buffer, ".\\\"NODE") == 0)) {
|
2002-02-28 17:38:38 +03:00
|
|
|
int SH = (strcmp (buffer, ".SH") == 0);
|
1998-02-27 07:54:42 +03:00
|
|
|
/* If we already skipped a section, don't skip another */
|
2002-07-31 02:57:01 +04:00
|
|
|
if (skip_flag == 2) {
|
1998-02-27 07:54:42 +03:00
|
|
|
skip_flag = 0;
|
|
|
|
}
|
|
|
|
/* Get the command parameters */
|
|
|
|
buffer = strtok (NULL, "");
|
2002-07-31 02:57:01 +04:00
|
|
|
if (buffer == NULL) {
|
1998-02-27 07:54:42 +03:00
|
|
|
print_error ("Syntax error: .SH: no title");
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
/* Remove quotes */
|
2002-07-31 02:57:01 +04:00
|
|
|
if (buffer[0] == '"') {
|
|
|
|
buffer++;
|
1998-02-27 07:54:42 +03:00
|
|
|
len = strlen (buffer);
|
2002-07-31 02:57:01 +04:00
|
|
|
if (buffer[len - 1] == '"') {
|
|
|
|
len--;
|
1998-02-27 07:54:42 +03:00
|
|
|
buffer[len] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Calculate heading level */
|
|
|
|
heading_level = 0;
|
2002-07-31 02:57:01 +04:00
|
|
|
while (buffer[heading_level] == ' ')
|
|
|
|
heading_level++;
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Heading level must be even */
|
|
|
|
if (heading_level & 1)
|
|
|
|
print_error ("Syntax error: .SH: odd heading level");
|
2002-07-31 02:57:01 +04:00
|
|
|
if (no_split_flag) {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Don't start a new section */
|
2001-08-16 05:36:41 +04:00
|
|
|
newline ();
|
|
|
|
print_string (buffer);
|
|
|
|
newline ();
|
|
|
|
newline ();
|
1998-02-27 07:54:42 +03:00
|
|
|
no_split_flag = 0;
|
2002-07-31 02:57:01 +04:00
|
|
|
} else if (skip_flag) {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Skipping title and marking text for skipping */
|
|
|
|
skip_flag = 2;
|
2002-07-31 02:57:01 +04:00
|
|
|
} else {
|
|
|
|
if (!SH || !node) {
|
|
|
|
/* Start a new section */
|
2002-08-20 20:13:13 +04:00
|
|
|
fprintf (f_out, "%c[%s]", CHAR_NODE_END,
|
|
|
|
buffer + heading_level);
|
|
|
|
if (!cnode) {
|
|
|
|
cnode = &nodes;
|
|
|
|
cnode->next = NULL;
|
|
|
|
} else {
|
|
|
|
cnode->next = malloc (sizeof (nodes));
|
|
|
|
cnode = cnode->next;
|
2002-07-31 02:20:26 +04:00
|
|
|
}
|
2002-08-20 20:13:13 +04:00
|
|
|
cnode->node = strdup (buffer);
|
|
|
|
cnode->lname = NULL;
|
2002-07-31 02:57:01 +04:00
|
|
|
col++;
|
2002-02-28 17:38:38 +03:00
|
|
|
newline ();
|
|
|
|
}
|
2002-07-31 02:57:01 +04:00
|
|
|
if (SH) {
|
2002-08-20 20:13:13 +04:00
|
|
|
/* print_string() strtok()es buffer, so */
|
|
|
|
cnode->lname = strdup (buffer + heading_level);
|
2002-02-28 17:38:38 +03:00
|
|
|
print_string (buffer + heading_level);
|
|
|
|
newline ();
|
|
|
|
newline ();
|
|
|
|
}
|
2002-07-31 02:57:01 +04:00
|
|
|
} /* Start new section */
|
|
|
|
} /* Has parameters */
|
2002-02-28 17:38:38 +03:00
|
|
|
node = !SH;
|
1998-02-27 07:54:42 +03:00
|
|
|
} /* Command .SH */
|
2002-07-31 02:57:01 +04:00
|
|
|
else if (strcmp (buffer, ".\\\"DONT_SPLIT\"") == 0) {
|
1998-02-27 07:54:42 +03:00
|
|
|
no_split_flag = 1;
|
2002-07-31 02:57:01 +04:00
|
|
|
} else if (strcmp (buffer, ".\\\"SKIP_SECTION\"") == 0) {
|
1998-02-27 07:54:42 +03:00
|
|
|
skip_flag = 1;
|
2002-07-31 02:57:01 +04:00
|
|
|
} else if (strcmp (buffer, ".\\\"LINK2\"") == 0) {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Next two input lines form a link */
|
|
|
|
link_flag = 2;
|
2002-07-31 02:57:01 +04:00
|
|
|
} else if (strcmp (buffer, ".PP") == 0) {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* End of paragraph */
|
2002-07-31 02:57:01 +04:00
|
|
|
if (col > 0)
|
|
|
|
newline ();
|
1998-02-27 07:54:42 +03:00
|
|
|
newline ();
|
2002-07-31 02:57:01 +04:00
|
|
|
} else if (strcmp (buffer, ".nf") == 0) {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Following input lines are to be handled verbatim */
|
|
|
|
verbatim_flag = 1;
|
2002-07-31 02:57:01 +04:00
|
|
|
if (col > 0)
|
|
|
|
newline ();
|
|
|
|
} else if (strcmp (buffer, ".I") == 0 || strcmp (buffer, ".B") == 0) {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Bold text or italics text */
|
2002-07-31 02:57:01 +04:00
|
|
|
char type = buffer[1];
|
2002-03-21 11:13:58 +03:00
|
|
|
char *p;
|
2002-07-31 02:57:01 +04:00
|
|
|
char *w = buffer;
|
2002-03-21 11:13:58 +03:00
|
|
|
int backslash_flag = 0;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
buffer = strtok (NULL, "");
|
2002-07-31 02:57:01 +04:00
|
|
|
if (buffer == NULL) {
|
1998-02-27 07:54:42 +03:00
|
|
|
print_error ("Syntax error: .I / .B: no text");
|
|
|
|
return;
|
|
|
|
}
|
2002-03-21 11:13:58 +03:00
|
|
|
|
|
|
|
*w = (type == 'I') ? CHAR_ITALIC_ON : CHAR_BOLD_ON;
|
|
|
|
|
|
|
|
/* Attempt to handle backslash quoting */
|
2002-07-31 02:57:01 +04:00
|
|
|
for (p = buffer, buffer = w++; *p; p++) {
|
|
|
|
if (*p == '\\' && !backslash_flag) {
|
2002-03-21 11:13:58 +03:00
|
|
|
backslash_flag = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
backslash_flag = 0;
|
|
|
|
*w++ = *p;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
2002-03-21 11:13:58 +03:00
|
|
|
|
|
|
|
*w++ = CHAR_BOLD_OFF;
|
|
|
|
*w = 0;
|
|
|
|
print_string (buffer);
|
2002-07-31 02:57:01 +04:00
|
|
|
} else if (strcmp (buffer, ".TP") == 0) {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* End of paragraph? */
|
2002-07-31 02:57:01 +04:00
|
|
|
if (col > 0)
|
|
|
|
newline ();
|
1998-02-27 07:54:42 +03:00
|
|
|
newline ();
|
2002-07-31 02:57:01 +04:00
|
|
|
} else if (strcmp (buffer, ".\\\"TOPICS") == 0) {
|
|
|
|
if (out_row > 1) {
|
|
|
|
print_error
|
|
|
|
("Syntax error: .\\\"TOPICS must be first command");
|
2002-03-20 17:03:55 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
buffer = strtok (NULL, "");
|
2002-07-31 02:57:01 +04:00
|
|
|
if (buffer == NULL) {
|
2002-03-20 17:03:55 +03:00
|
|
|
print_error ("Syntax error: .\\\"TOPICS: no text");
|
|
|
|
return;
|
|
|
|
}
|
2002-08-25 22:13:37 +04:00
|
|
|
/* Remove quotes */
|
|
|
|
if (buffer[0] == '"') {
|
|
|
|
buffer++;
|
|
|
|
len = strlen (buffer);
|
|
|
|
if (buffer[len - 1] == '"') {
|
|
|
|
len--;
|
|
|
|
buffer[len] = 0;
|
|
|
|
}
|
|
|
|
}
|
2002-08-20 20:13:13 +04:00
|
|
|
Topics = strdup (buffer);
|
2002-07-31 02:57:01 +04:00
|
|
|
} else {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Other commands are ignored */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-07-31 02:57:01 +04:00
|
|
|
static void
|
|
|
|
handle_link (char *buffer)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
2002-07-31 02:57:01 +04:00
|
|
|
static char old[80];
|
1998-02-27 07:54:42 +03:00
|
|
|
int len;
|
|
|
|
|
2002-07-31 02:57:01 +04:00
|
|
|
switch (link_flag) {
|
1998-02-27 07:54:42 +03:00
|
|
|
case 1:
|
2001-08-16 05:36:41 +04:00
|
|
|
/* Old format link, not supported */
|
1998-02-27 07:54:42 +03:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
/* First part of new format link */
|
2002-03-21 16:01:20 +03:00
|
|
|
/* Bold text or italics text */
|
2002-07-31 02:57:01 +04:00
|
|
|
if (buffer[0] == '.' && (buffer[1] == 'I' || buffer[1] == 'B'))
|
|
|
|
for (buffer += 2; *buffer == ' ' || *buffer == '\t'; buffer++);
|
1998-02-27 07:54:42 +03:00
|
|
|
strcpy (old, buffer);
|
|
|
|
link_flag = 3;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
/* Second part of new format link */
|
2002-07-31 02:57:01 +04:00
|
|
|
if (buffer[0] == '.')
|
1998-02-27 07:54:42 +03:00
|
|
|
buffer++;
|
2002-07-31 02:57:01 +04:00
|
|
|
if (buffer[0] == '\\')
|
1998-02-27 07:54:42 +03:00
|
|
|
buffer++;
|
2002-07-31 02:57:01 +04:00
|
|
|
if (buffer[0] == '"')
|
1998-02-27 07:54:42 +03:00
|
|
|
buffer++;
|
|
|
|
len = strlen (buffer);
|
2002-07-31 02:57:01 +04:00
|
|
|
if (len && buffer[len - 1] == '"') {
|
|
|
|
buffer[--len] = 0;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
2002-07-31 02:57:01 +04:00
|
|
|
printf_string ("%c%s%c%s%c\n", CHAR_LINK_START, old,
|
|
|
|
CHAR_LINK_POINTER, buffer, CHAR_LINK_END);
|
1998-02-27 07:54:42 +03:00
|
|
|
link_flag = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-07-31 02:57:01 +04:00
|
|
|
int
|
|
|
|
main (int argc, char **argv)
|
1998-02-27 07:54:42 +03:00
|
|
|
{
|
|
|
|
int len; /* Length of input line */
|
2002-08-20 20:13:13 +04:00
|
|
|
const char *c_man; /* Manual filename */
|
|
|
|
const char *c_tmpl; /* Template filename */
|
|
|
|
FILE *f_man; /* Manual file */
|
|
|
|
FILE *f_tmpl; /* Template file */
|
2002-07-31 02:57:01 +04:00
|
|
|
char buffer2[BUFFER_SIZE]; /* Temp input line */
|
2002-02-28 17:12:34 +03:00
|
|
|
char *buffer = buffer2; /* Input line */
|
2002-07-31 02:20:26 +04:00
|
|
|
char *node = NULL;
|
|
|
|
|
2002-07-31 02:57:01 +04:00
|
|
|
long cont_start, file_end;
|
1998-02-27 07:54:42 +03:00
|
|
|
|
|
|
|
/* Validity check for arguments */
|
2002-08-20 20:13:13 +04:00
|
|
|
if ((argc != 5) || ((width = atoi (argv[1])) <= 10)) {
|
2002-07-31 02:57:01 +04:00
|
|
|
fprintf (stderr,
|
2002-08-20 20:13:13 +04:00
|
|
|
"Usage: man2hlp width file.man template_file helpfile\n");
|
1998-02-27 07:54:42 +03:00
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
2002-08-20 20:13:13 +04:00
|
|
|
c_man = argv[2];
|
|
|
|
c_tmpl = argv[3];
|
|
|
|
c_out = argv[4];
|
2002-07-31 02:20:26 +04:00
|
|
|
|
2002-08-20 20:13:13 +04:00
|
|
|
/* Open the input file (manual) */
|
|
|
|
f_man = fopen (c_man, "r");
|
|
|
|
if (f_man == NULL) {
|
|
|
|
sprintf (buffer, "man2hlp: Cannot open file \"%s\"", c_man);
|
1998-02-27 07:54:42 +03:00
|
|
|
perror (buffer);
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
2002-08-20 20:13:13 +04:00
|
|
|
f_out = fopen (c_out, "w");
|
|
|
|
if (f_out == NULL) {
|
|
|
|
sprintf (buffer, "man2hlp: Cannot open file \"%s\"", c_out);
|
2002-07-31 02:20:26 +04:00
|
|
|
perror (buffer);
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Repeat for each input line */
|
2002-08-20 20:13:13 +04:00
|
|
|
while (!feof (f_man)) {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Read a line */
|
2002-08-20 20:13:13 +04:00
|
|
|
if (!fgets (buffer2, BUFFER_SIZE, f_man)) {
|
1998-02-27 07:54:42 +03:00
|
|
|
break;
|
|
|
|
}
|
2002-07-31 02:57:01 +04:00
|
|
|
if (buffer2[0] == '\\' && buffer2[1] == '&')
|
2002-02-28 17:12:34 +03:00
|
|
|
buffer = buffer2 + 2;
|
2001-08-16 05:36:41 +04:00
|
|
|
else
|
2002-02-28 17:12:34 +03:00
|
|
|
buffer = buffer2;
|
2002-07-31 02:57:01 +04:00
|
|
|
in_row++;
|
1998-02-27 07:54:42 +03:00
|
|
|
len = strlen (buffer);
|
|
|
|
/* Remove terminating newline */
|
2002-07-31 02:57:01 +04:00
|
|
|
if (buffer[len - 1] == '\n') {
|
|
|
|
len--;
|
|
|
|
buffer[len] = 0;
|
1998-02-27 07:54:42 +03:00
|
|
|
}
|
2002-07-31 02:57:01 +04:00
|
|
|
if (verbatim_flag) {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* Copy the line verbatim */
|
2002-07-31 02:57:01 +04:00
|
|
|
if (strcmp (buffer, ".fi") == 0) {
|
1998-02-27 07:54:42 +03:00
|
|
|
verbatim_flag = 0;
|
|
|
|
} else {
|
|
|
|
print_string (buffer);
|
|
|
|
newline ();
|
|
|
|
}
|
2002-07-31 02:57:01 +04:00
|
|
|
} else if (link_flag)
|
1998-02-27 07:54:42 +03:00
|
|
|
/* The line is a link */
|
|
|
|
handle_link (buffer);
|
|
|
|
else if (buffer[0] == '.')
|
|
|
|
/* The line is a roff command */
|
|
|
|
handle_command (buffer);
|
2002-07-31 02:57:01 +04:00
|
|
|
else {
|
1998-02-27 07:54:42 +03:00
|
|
|
/* A normal line, just output it */
|
|
|
|
print_string (buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* All done */
|
|
|
|
newline ();
|
2002-08-20 20:13:13 +04:00
|
|
|
fclose (f_man);
|
2002-07-31 02:20:26 +04:00
|
|
|
|
|
|
|
/* Open the template file */
|
2002-08-20 20:13:13 +04:00
|
|
|
f_tmpl = fopen (c_tmpl, "r");
|
|
|
|
if (f_tmpl == NULL) {
|
|
|
|
sprintf (buffer, "man2hlp: Cannot open file \"%s\"", c_tmpl);
|
2002-07-31 02:20:26 +04:00
|
|
|
perror (buffer);
|
|
|
|
return 3;
|
|
|
|
}
|
2002-08-20 20:13:13 +04:00
|
|
|
|
2002-07-31 02:20:26 +04:00
|
|
|
/* Repeat for each input line */
|
2002-08-20 20:13:13 +04:00
|
|
|
while (!feof (f_tmpl)) {
|
2002-07-31 02:20:26 +04:00
|
|
|
/* Read a line */
|
2002-08-20 20:13:13 +04:00
|
|
|
if (!fgets (buffer2, BUFFER_SIZE, f_tmpl)) {
|
2002-07-31 02:20:26 +04:00
|
|
|
break;
|
|
|
|
}
|
2002-07-31 02:57:01 +04:00
|
|
|
if (node) {
|
|
|
|
if (*buffer2 && *buffer2 != '\n') {
|
2002-07-31 02:20:26 +04:00
|
|
|
cnode->lname = strdup (buffer2);
|
|
|
|
node = strchr (cnode->lname, '\n');
|
|
|
|
if (node)
|
|
|
|
*node = 0;
|
|
|
|
}
|
|
|
|
node = NULL;
|
|
|
|
} else {
|
2002-07-31 02:57:01 +04:00
|
|
|
node = strchr (buffer, CHAR_NODE_END);
|
|
|
|
if (node && (node[1] == '[')) {
|
|
|
|
char *p = strrchr (node, ']');
|
|
|
|
if (p && strncmp (node + 2, "main", 4) == 0
|
|
|
|
&& node[6] == ']') {
|
|
|
|
node = 0;
|
2002-07-31 02:20:26 +04:00
|
|
|
} else {
|
2002-07-31 02:57:01 +04:00
|
|
|
if (!cnode) {
|
|
|
|
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;
|
2002-07-31 02:20:26 +04:00
|
|
|
}
|
2002-07-31 02:57:01 +04:00
|
|
|
} else
|
|
|
|
node = NULL;
|
2002-07-31 02:20:26 +04:00
|
|
|
}
|
2002-08-20 20:13:13 +04:00
|
|
|
fputs (buffer, f_out);
|
2002-07-31 02:20:26 +04:00
|
|
|
}
|
|
|
|
|
2002-08-20 20:13:13 +04:00
|
|
|
cont_start = ftell (f_out);
|
|
|
|
fprintf (f_out, "\004[Contents]\n%s\n\n", Topics);
|
2002-07-31 02:20:26 +04:00
|
|
|
|
2002-07-31 04:08:51 +04:00
|
|
|
for (cnode = &nodes; cnode && cnode->node;) {
|
2002-07-31 02:20:26 +04:00
|
|
|
char *node = cnode->node;
|
|
|
|
int heading_level = 0;
|
2002-07-31 04:08:51 +04:00
|
|
|
struct node *next = cnode->next;
|
|
|
|
|
2002-07-31 02:57:01 +04:00
|
|
|
while (*node == ' ') {
|
2002-07-31 02:20:26 +04:00
|
|
|
heading_level++;
|
|
|
|
node++;
|
|
|
|
}
|
|
|
|
if (*node)
|
2002-08-20 20:13:13 +04:00
|
|
|
fprintf (f_out, " %*s\001 %s \002%s\003", heading_level, "",
|
|
|
|
cnode->lname ? cnode->lname : node, node);
|
|
|
|
fprintf (f_out, "\n");
|
2002-07-31 02:20:26 +04:00
|
|
|
|
|
|
|
free (cnode->node);
|
|
|
|
if (cnode->lname)
|
|
|
|
free (cnode->lname);
|
|
|
|
if (cnode != &nodes)
|
|
|
|
free (cnode);
|
2002-07-31 04:08:51 +04:00
|
|
|
cnode = next;
|
2002-07-31 02:20:26 +04:00
|
|
|
}
|
|
|
|
|
2002-08-20 20:13:13 +04:00
|
|
|
file_end = ftell (f_out);
|
|
|
|
fclose (f_out);
|
|
|
|
|
|
|
|
if (file_end <= 0) {
|
|
|
|
perror (c_out);
|
2002-08-20 20:14:48 +04:00
|
|
|
return 1;
|
2002-08-20 20:13:13 +04:00
|
|
|
}
|
2002-07-31 02:20:26 +04:00
|
|
|
|
|
|
|
Topics = malloc (file_end);
|
2002-07-31 02:57:01 +04:00
|
|
|
if (!Topics)
|
|
|
|
return 1;
|
|
|
|
|
2002-08-20 20:13:13 +04:00
|
|
|
f_out = fopen (c_out, "r");
|
|
|
|
if (!f_out) {
|
|
|
|
perror (c_out);
|
2002-07-31 02:57:01 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2002-08-20 20:13:13 +04:00
|
|
|
if (persistent_fread (Topics, file_end, f_out) < 0) {
|
|
|
|
perror (c_out);
|
2002-07-31 02:57:01 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2002-08-20 20:13:13 +04:00
|
|
|
if (fclose (f_out) != 0) {
|
|
|
|
perror (c_out);
|
2002-07-31 02:57:01 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2002-08-20 20:13:13 +04:00
|
|
|
f_out = fopen (c_out, "w");
|
|
|
|
if (!f_out) {
|
|
|
|
perror (c_out);
|
2002-07-31 02:57:01 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2002-08-16 20:48:27 +04:00
|
|
|
if (persistent_fwrite
|
2002-08-20 20:13:13 +04:00
|
|
|
(Topics + cont_start, file_end - cont_start, f_out)
|
2002-08-16 20:48:27 +04:00
|
|
|
< 0) {
|
2002-08-20 20:13:13 +04:00
|
|
|
perror (c_out);
|
2002-07-31 02:57:01 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2002-08-20 20:13:13 +04:00
|
|
|
if (persistent_fwrite (Topics, cont_start, f_out) < 0) {
|
|
|
|
perror (c_out);
|
2002-07-31 02:57:01 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
free (Topics);
|
|
|
|
|
2002-08-20 20:13:13 +04:00
|
|
|
if (fclose (f_out) != 0) {
|
|
|
|
perror (c_out);
|
2002-07-31 02:57:01 +04:00
|
|
|
return 1;
|
|
|
|
}
|
2002-07-31 02:20:26 +04:00
|
|
|
|
1998-02-27 07:54:42 +03:00
|
|
|
return 0;
|
|
|
|
}
|