/* $Id: texinfo.c,v 2.0.1.19 2000/02/25 02:20:44 greyham Exp greyham $
* functions for texinfo style output.
*/
#include "c2man.h"
#include "manpage.h"
#include "output.h"
#include "semantic.h"
#include <ctype.h>
static char *heading_not_in_contents[] =
{"@chapheading ", "@heading ", "@subheading ", "@subsubheading "};
static char *heading_in_contents[] =
{"@chapter ", "@section ", "@subsection ", "@subsubsection "};
#define n_levels (sizeof(heading_not_in_contents) / sizeof(char *))
#define level(n) ((n) >= n_levels ? n_levels - 1 : (n))
/* section level for man page entry */
static int top_level = 1;
/* always output node for manpage, even if embedded */
static int embed_node_info = 0;
/* use title as name of section, rather than "NAME" */
static int title_name = 0;
/* the section title, filled in by texinfo_header */
static const char *title = "INTERNAL ERROR, BOGUS TITLE DUDE!";
/* do section titles get capitalized? */
static int capitalize_sections = 0;
void texinfo_char(c)
const int c;
{
int i;
switch(c)
{
case '\t':
for (i = 0; i < NUM_TAB_SPACES; i++)
putchar(' ');
break;
default:
putchar(c);
break;
}
}
void texinfo_text(text)
const char *text;
{
while (*text)
texinfo_char(*text++);
}
void put_section(text)
const char *text;
{
if (capitalize_sections)
{
int first_letter = 1;
for ( ; *text ; text++)
{
texinfo_char(first_letter ? toupper(*text) : tolower(*text));
first_letter = isspace(*text);
}
}
else
texinfo_text(text);
}
void texinfo_comment() { put_string("@c "); }
void texinfo_header(firstpage, input_files, grouped, name, terse, section)
ManualPage *firstpage;
int input_files;
boolean grouped;
const char *name;
const char *terse;
const char *section;
{
if (! make_embeddable)
{
put_string("\\input texinfo @c -*-texinfo-*-\n");
output_warning();
put_string("@c %**start of header\n");
put_string("@setfilename ");
texinfo_text(name);
put_string(".info\n@settitle ");
texinfo_text(name);
putchar('\n');
put_string("@c %**end of header\n");
put_string("@node Top, ");
texinfo_text(name);
put_string(", (dir), (dir)\n");
}
if (! make_embeddable || embed_node_info)
{
put_string("@node ");
texinfo_text(name);
put_string(", (dir), Top, (dir)\n");
}
title = name;
}
void texinfo_dash() { put_string("---"); }
void texinfo_section(name)
const char *name;
{
put_string(heading_not_in_contents[level(top_level)]);
put_section(name);
putchar('\n');
put_string("@noindent\n");
}
void texinfo_section_in_contents(name)
const char *name;
{
put_string(heading_in_contents[level(top_level)]);
put_section(name);
putchar('\n');
put_string("@noindent\n");
}
void texinfo_sub_section(name)
const char *name;
{
put_string(heading_not_in_contents[level(top_level+1)]);
put_section(name);
putchar('\n');
put_string("@noindent\n");
}
void texinfo_break_line() { /* put_string("@*\n"); */ }
void texinfo_blank_line() { put_string("@sp 1\n"); }
void texinfo_code_start() { put_string("@example\n"); }
void texinfo_code_end() { put_string("@end example\n"); }
void texinfo_code(text)
const char *text;
{
put_string("@code{");
texinfo_text(text);
put_string("}");
}
void texinfo_tag_list_start() { put_string("@quotation\n@table @code\n"); }
void texinfo_tag_entry_start() { put_string("@item "); }
void texinfo_tag_entry_end() { putchar('\n'); }
void texinfo_tag_entry_end_extra(text)
const char *text;
{
putchar('(');
texinfo_text(text);
putchar(')');
texinfo_tag_entry_end();
}
void texinfo_tag_list_end() { put_string("@end table\n@end quotation\n"); }
void texinfo_table_start(longestag)
const char *longestag;
{ put_string("@quotation\n@table @code\n"); }
void texinfo_table_entry(name, description)
const char *name;
const char *description;
{
put_string("@item ");
texinfo_text(name);
putchar('\n');
if (description)
output_comment(description);
else
putchar('\n');
}
void texinfo_table_end() { put_string("@end table\n@end quotation\n"); }
void texinfo_list_start() { }
void texinfo_list_entry(text)
const char *text;
{
texinfo_code(text);
}
void texinfo_list_separator() { put_string(",\n"); }
void texinfo_list_end() { putchar('\n'); }
void texinfo_include(filename)
const char *filename;
{
put_string("@include ");
texinfo_text(filename);
put_string("\n");
}
void texinfo_file_end() { put_string("@bye\n"); }
static int first_name = 1;
void texinfo_name(name)
const char *name;
{
if (name)
{
if (!first_name || !title_name || strcmp(title,name))
texinfo_text(name);
first_name = 0;
}
else
{
first_name = 1;
if (title_name)
{
/* don't muck around with capitalization of title */
int capitalize_sections_save = capitalize_sections;
capitalize_sections = 0;
texinfo_section_in_contents(title);
capitalize_sections = capitalize_sections_save;
}
else
texinfo_section("NAME");
}
}
void texinfo_terse_sep()
{
if (!title_name || group_together)
{
texinfo_char(' ');
texinfo_dash();
texinfo_char(' ');
}
}
void texinfo_reference(text)
const char *text;
{
texinfo_text(text);
texinfo_char('(');
texinfo_text(manual_section);
texinfo_char(')');
}
/* ideally, this should be made aware of embedded texinfo commands */
void texinfo_description(text)
const char *text;
{
enum { TEXT, PERIOD, CAPITALISE } state = CAPITALISE;
boolean new_line = TRUE;
/* correct punctuation a bit as it goes out */
for (;*text;text++)
{
int c = *text;
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) || ispunct(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 (state == TEXT) output->character('.');
}
/* ideally, this should be made aware of embedded texinfo commands */
void
texinfo_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;
{
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');
/* 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();
}
int texinfo_parse_option(option)
const char *option;
{
if (option[0] == 't')
title_name = 1;
else if (option[0] == 'n')
embed_node_info = 1;
else if (option[0] == 's')
{
top_level = atoi(&option[1]);
if (top_level < 0) return 1;
}
else if (option[0] == 'C')
capitalize_sections = 1;
else return 1;
return 0;
}
void texinfo_print_options()
{
fputs("\ttexinfo options:\n", stderr);
fputs("\tt\tuse manpage title as NAME title\n", stderr);
fputs("\tn\toutput node info if embedded output\n", stderr);
fputs("\ts<n>\tset top heading level to <n>\n", stderr);
fputs("\tC\tcaptialize section titles\n", stderr);
}
struct Output texinfo_output =
{
texinfo_comment,
texinfo_header,
texinfo_dash,
texinfo_section,
texinfo_sub_section,
texinfo_break_line,
texinfo_blank_line,
texinfo_code_start,
texinfo_code_end,
texinfo_code,
texinfo_tag_list_start,
texinfo_tag_list_end,
texinfo_tag_entry_start,
texinfo_tag_entry_start, /* entry_start_extra */
texinfo_tag_entry_end,
texinfo_tag_entry_end_extra,
texinfo_table_start,
texinfo_table_entry,
texinfo_table_end,
dummy, /* texinfo_indent */
texinfo_list_start,
texinfo_list_entry,
texinfo_list_separator,
texinfo_list_end,
texinfo_include,
texinfo_file_end,
texinfo_text,
texinfo_char,
texinfo_parse_option,
texinfo_print_options,
texinfo_name,
texinfo_terse_sep,
texinfo_reference,
texinfo_text,
texinfo_description,
texinfo_returns
};
syntax highlighted by Code2HTML, v. 0.9.1