/* Output for c2man in raw text (ASCII) format
* 1998 by B. Luevelsmeyer
* This is a modified version of "nroff.c".
*/
#include <ctype.h>
#include "c2man.h"
#include "manpage.h"
#include "output.h"
static int indention = 0;
/* The number of indents at line-start.
* I print this number of tabs.
* Used in ascii_text() and set in the tag_entry() functions.
*/
static void ascii_emphasized();
static void ascii_text(const char *text)
{
if (indention>0)
{
const char *p;
for (p = text; *p; p++)
{
putchar(*p);
if (*p == '\n')
{
int i;
for (i = indention; i; i--)
put_string("\t");
}
}
}
else
put_string(text);
}
static void ascii_char(const int c)
{
char b[2] = "x";
b[0] = c;
ascii_text(b);
}
static void ascii_comment(void)
{
put_string("# ");
}
static void ascii_header(ManualPage * firstpage, int input_files, boolean grouped,
const char *name, const char * terse, const char *section)
{
#ifdef HAS_STRFTIME
char month[20];
#else
char *month;
static char *month_list[] =
{"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"};
#endif
Time_t raw_time;
struct tm *filetime;
indention = 0;
if (make_embeddable) return;
output_warning();
/* if lots of files contributed, use the current time; otherwise use the
* time of the source file they came from.
*/
raw_time = (grouped && input_files > 1) ? time((Time_t *) NULL)
: firstpage->sourcetime;
filetime = localtime(&raw_time);
#ifdef HAS_STRFTIME
/* generate the date format string */
strftime(month, sizeof month, "%B", filetime);
#else
month = month_list[filetime->tm_mon];
#endif
ascii_text(name);
printf("(%s) \t%d %s %d",
section, filetime->tm_mday, month, filetime->tm_year + 1900);
printf(", %s:", progname);
if ((input_files <= 1 || !grouped) && firstpage->sourcefile)
{
const char *basename = strrchr(firstpage->sourcefile, '/');
if (basename == NULL)
basename = firstpage->sourcefile;
else
basename++;
printf(" %s", basename);
}
if (manual_name)
printf(" %s", manual_name);
put_string("\n");
}
static void ascii_dash()
{
ascii_text("-");
}
static void ascii_section(const char *name)
{
indention=0;
ascii_text("\n\n");
ascii_emphasized(name);
ascii_text("\n\n");
}
static void ascii_sub_section(const char *name)
{
indention=0;
ascii_text("\n");
ascii_emphasized(name);
indention++;
ascii_text("\n\n");
}
static void ascii_break_line()
{
;
}
static void ascii_blank_line()
{
ascii_text("\n");
}
static void ascii_code_start()
{
;
}
static void ascii_code_end()
{
;
}
static void ascii_code(const char *text)
{
ascii_text("\n");
ascii_text(text);
}
static void ascii_tag_list_start(void)
{
indention++;
}
static void ascii_tag_list_end(void)
{
indention--;
}
static void ascii_tag_entry_start(void)
{
indention--;
ascii_text("\n");
}
static void ascii_tag_entry_start_extra(void)
{
indention--;
ascii_text("\n");
}
static void ascii_tag_entry_end(void)
{
indention++;
ascii_text("\n");
}
static void ascii_tag_entry_end_extra(const char *text)
{
ascii_text(" (");
ascii_text(text);
indention++;
ascii_text(")\n");
}
static void ascii_table_start(const char *longestag)
{
indention++;
ascii_text("\n");
}
static void ascii_table_entry(const char *name, const char *description)
{
ascii_code(name);
if (description)
{
indention++;
ascii_text("\n");
output_comment(description);
indention--;
}
else
ascii_text("\n");
}
static void ascii_table_end(void)
{
indention--;
ascii_text("\n");
}
static void ascii_indent(void)
{
;
}
static void ascii_list_start(void)
{
ascii_text("list");
}
static void ascii_list_entry(const char *name)
{
ascii_code(name);
}
static void ascii_list_separator()
{
ascii_text(",\n");
}
static void ascii_list_end()
{
ascii_char('\n');
ascii_table_end();
}
static void ascii_include(const char *filename)
{
printf("(see also %s)\n", filename);
}
static void ascii_file_end(void)
{
indention=0;
puts(""); /* just in case there was no \n */
}
#define ascii_parse_option 0
static void ascii_print_options(void) { ; }
static void ascii_name(name)
const char *name;
{
if (name) ascii_text(name);
else ascii_section("NAME");
}
static void ascii_terse_sep()
{
ascii_char(' ');
ascii_dash();
ascii_char(' ');
}
static void ascii_emphasized(text)
const char *text;
{
const char *p;
if (make_embeddable) ascii_text(text);
else
for(p=text;*p;p++)
if(isspace(*p)) ascii_char(*p);
else
{ char r[4];
r[0] = r[2] = *p;
#ifdef DEBUG
r[1] = '_';
#else
r[1] = '\b';
#endif
r[3] = 0;
ascii_text(r);
}
}
static void ascii_reference(text)
const char *text;
{
ascii_text(text);
ascii_char('(');
ascii_text(manual_section);
ascii_char(')');
}
static void ascii_description(text)
const char *text;
{
enum { TEXT, PERIOD, CAPITALISE } state = CAPITALISE;
boolean new_line = TRUE;
boolean dot_command = FALSE;
/* correct punctuation a bit as it goes out */
for (;*text;text++)
{
int c = *text;
if (dot_command)
{
if (c == '\n') dot_command = FALSE;
}
else if (new_line && c == '.')
dot_command = TRUE;
else if (new_line && (c == '-' || c == '*' || is_numbered(text)))
{
output->break_line();
state = CAPITALISE;
}
else if (c == '.')
state = PERIOD;
else if (isspace(c) && state == PERIOD)
state = CAPITALISE;
else if (isalnum(c))
{
if (islower(c) && state == CAPITALISE) c = toupper(c);
state = TEXT;
}
output->character(c);
new_line = c == '\n';
}
/* do a full stop if there wasn't one */
if (!dot_command && state == TEXT) output->character('.');
}
static void
ascii_returns(comment)
const char *comment;
{
enum { TEXT, PERIOD, CAPITALISE } state = CAPITALISE;
char lastchar = '\n';
boolean tag_list_started = FALSE;
/* for each line... */
while (*comment)
{
boolean tagged = FALSE;
/* explicitly reject dot commands */
if (*comment && *comment != '.')
{
const char *c = comment;
/* search along until the end of a word */
while (*c && *c != ':' && !isspace(*c))
c++;
/* skip all spaces or tabs after the first word */
while (*c && *c != '\n')
{
if (*c == '\t' || *c == ':')
{
tagged = TRUE;
break;
}
else if (!isspace(*c))
break;
c++;
}
}
/* is it tagged?; explicitly reject dot commands */
if (tagged)
{
/* output lingering newline if necessary */
if (lastchar != '\n')
{
if (state == TEXT && !ispunct(lastchar)) output->character('.');
output->character(lastchar = '\n');
}
if (!tag_list_started)
{
output->tag_list_start();
tag_list_started = TRUE;
}
/* output the taggy bit */
output->tag_entry_start();
while (*comment && *comment != ':' && !isspace(*comment))
output->character(*comment++);
output->tag_entry_end();
/* skip any extra tabs or spaces */
while (*comment == ':' || (isspace(*comment) && *comment != '\n'))
comment++;
state = CAPITALISE;
}
/* terminate the previous line if necessary */
if (lastchar != '\n') output->character(lastchar = '\n');
/* dot commands go out unaltered */
if (*comment == '.')
{
for (;*comment && *comment != '\n'; comment++)
output->character(*comment);
output->character('\n');
}
else
{
/* correct punctuation a bit as the line goes out */
for (;*comment && *comment != '\n'; comment++)
{
char c = *comment;
if (c == '.')
state = PERIOD;
else if (isspace(c) && state == PERIOD)
state = CAPITALISE;
else if (isalnum(c))
{
if (islower(c) && state == CAPITALISE && fixup_comments)
c = toupper(c);
state = TEXT;
}
output->character(lastchar = c);
}
/* if it ended in punctuation, just output the nl straight away. */
if (ispunct(lastchar))
{
if (lastchar == '.') state = CAPITALISE;
output->character(lastchar = '\n');
}
}
if (*comment) comment++;
}
/* output lingering newline if necessary */
if (lastchar != '\n')
{
if (state == TEXT && !ispunct(lastchar) && fixup_comments)
output->character('.');
output->character('\n');
}
if (tag_list_started)
output->tag_list_end();
}
struct Output ascii_output =
{
ascii_comment,
ascii_header,
ascii_dash,
ascii_section,
ascii_sub_section,
ascii_break_line,
ascii_blank_line,
ascii_code_start,
ascii_code_end,
ascii_code,
ascii_tag_list_start,
ascii_tag_list_end,
ascii_tag_entry_start,
ascii_tag_entry_start_extra,
ascii_tag_entry_end,
ascii_tag_entry_end_extra,
ascii_table_start,
ascii_table_entry,
ascii_table_end,
ascii_indent,
ascii_list_start,
ascii_list_entry,
ascii_list_separator,
ascii_list_end,
ascii_include,
ascii_file_end,
ascii_text,
ascii_char,
ascii_parse_option,
ascii_print_options,
ascii_name,
ascii_terse_sep,
ascii_reference,
ascii_emphasized,
ascii_description,
ascii_returns
};
syntax highlighted by Code2HTML, v. 0.9.1