/*
** $PROJECT:
**
** $VER: autodoc.c 2.2 (25.01.95)
**
** by
**
** Stefan Ruppert , Windthorststra_e 5 , 65439 Flvrsheim , GERMANY
**
** (C) Copyright 1995
** All Rights Reserved !
**
** $HISTORY:
**
** 25.01.95 : 002.002 : changed to patchlevel 33
** 22.01.95 : 000.001 : initial
*/
#include "c2man.h"
#include "manpage.h"
#include "output.h"
#include <ctype.h>
#ifdef DEBUG
#define D(x) x
#else
#define D(x)
#endif
#define MAX_TAG 10
static const int linelength = 79;
static const int tablength = 4;
static const int indentlength = 4;
static int indent = 4;
static int list_indent = 0;
static int column = 0;
static int newline = FALSE;
static int breakline = FALSE;
static int see_also = FALSE;
static int fileend = FALSE;
static int acttable = -1;
static int tablemaxtag[MAX_TAG];
void autodoc_format(text)
const char *text;
{
if(see_also)
{
if(column + ((text) ? strlen(text) + 2 : 1) > linelength)
{
putchar('\n');
newline = TRUE;
}
}
if(newline)
{
int i;
column = i = indent + list_indent;
for(; i ; i--)
putchar(' ');
newline = FALSE;
}
}
void autodoc_text(text)
const char *text;
{
int br = 1;
autodoc_format(text);
if(!see_also || (br = strcmp(text,",\n")))
{
if(see_also < 2)
{
put_string(text);
column += strlen(text);
}
} else if(!br)
{
column += 2;
put_string(", ");
}
}
void autodoc_char(c)
const int c;
{
if(c != '\f')
{
autodoc_format(NULL);
if(c == '\t')
{
int i = tablength - (column % tablength);
column += i;
for(; i ; i--)
putchar(' ');
} else
{
if(see_also)
{
if(c == '(')
see_also++;
else if(c == ')')
see_also--;
}
putchar(c);
column++;
}
if((newline = (c == '\n')))
column = 0;
}
}
void autodoc_comment() { }
void autodoc_header(firstpage, input_files, grouped, name, terse, section)
ManualPage *firstpage;
int input_files;
boolean grouped;
const char *name;
const char *terse;
const char *section;
{
const char *basename = strrchr(firstpage->sourcefile, '/');
int len;
int spc;
fileend = FALSE;
if(basename && *basename == '/')
basename++;
len = ((basename) ? strlen(basename) + 1 : 0) + strlen(name);
spc = linelength - 2 * len;
see_also = FALSE;
if(basename)
{
autodoc_text(basename);
autodoc_char('/');
}
autodoc_text(name);
if(spc > 0)
{
while(spc)
{
autodoc_char(' ');
spc--;
}
if(basename)
{
autodoc_text(basename);
autodoc_char('/');
}
autodoc_text(name);
} else
{
const char *ptr = name;
len = linelength - 1 - len;
while(len)
{
if(basename && *basename)
{
autodoc_char(*basename);
basename++;
} else
{
if(ptr == name && basename)
autodoc_char('/');
else
{
autodoc_char(*ptr);
ptr++;
}
}
len--;
}
}
put_string("\n");
}
void autodoc_dash() { put_string("-"); }
void autodoc_section(name)
const char *name;
{
D((fprintf(stderr,"section : %s\n",name)));
newline = FALSE;
see_also = FALSE;
put_string("\n");
if(!strcmp(name,"DESCRIPTION"))
name = "FUNCTION";
else if(!strcmp(name,"PARAMETERS"))
name = "INPUTS";
else if(!strcmp(name,"RETURNS"))
name = "RESULT";
else if(!strcmp(name,"SEE ALSO"))
see_also = TRUE;
put_string(" ");
autodoc_text(name);
indent = 8;
list_indent = 0;
autodoc_char('\n');
}
void autodoc_sub_section(name)
const char *name;
{
autodoc_text(name);
indent = 12;
}
void autodoc_break_line()
{
breakline = TRUE;
}
void autodoc_blank_line()
{
autodoc_char('\n');
}
void autodoc_code_start() { }
void autodoc_code_end() { }
void autodoc_code(text)
const char *text;
{
autodoc_text(text);
}
void autodoc_tag_entry_start()
{
if(list_indent > 0)
{
autodoc_char('\n');
list_indent -= indentlength;
}
}
void autodoc_tag_entry_start_extra()
{
if(list_indent > 0)
{
autodoc_char('\n');
list_indent -= indentlength;
}
}
void autodoc_tag_entry_end()
{
list_indent += indentlength;
autodoc_char('\n');
}
void autodoc_tag_entry_end_extra(text)
const char *text;
{
put_string("\" \"\t(");
autodoc_text(text);
put_string(")\"\n");
list_indent += indentlength;
}
void autodoc_table_start(longestag)
const char *longestag;
{
if(acttable < MAX_TAG - 1)
{
acttable++;
tablemaxtag[acttable] = strlen(longestag);
}
indent += indentlength;
newline = TRUE;
}
void autodoc_table_entry(name, description)
const char *name;
const char *description;
{
int i = tablemaxtag[acttable] - strlen(name) + 1;
autodoc_code(name);
while(i > 0)
{
putchar(' ');
i--;
}
putchar('-');
putchar(' ');
if (description)
output_comment(description);
else
autodoc_char('\n');
}
void autodoc_table_end()
{
if(acttable > -1)
acttable--;
autodoc_char('\n');
indent -= indentlength;
if(list_indent > 0)
list_indent -= indentlength;
}
void autodoc_indent()
{
int i;
for(i = indent + list_indent; i ; i--)
autodoc_char(' ');
}
void autodoc_list_start()
{
indent += indentlength;
newline = TRUE;
}
void autodoc_list_entry(name)
const char *name;
{
autodoc_code(name);
}
void autodoc_list_separator() { put_string(" ,"); }
void autodoc_list_end() { autodoc_char('\n'); autodoc_table_end(); }
void autodoc_include(filename)
const char *filename;
{
}
void autodoc_terse_sep()
{
autodoc_char(' ');
autodoc_dash();
autodoc_char(' ');
}
void autodoc_name(name)
const char *name;
{
if(name)
autodoc_text(name);
else
autodoc_section("NAME");
}
void autodoc_file_end()
{
if(!fileend)
putchar('\f');
fileend = TRUE;
newline = FALSE;
}
/* ideally, this should be made aware of embedded autodoc commands */
void autodoc_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 == '*'))
{
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 autodoc commands */
void
autodoc_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();
}
struct Output autodoc_output =
{
autodoc_comment,
autodoc_header,
autodoc_dash,
autodoc_section,
autodoc_sub_section,
autodoc_break_line,
autodoc_blank_line,
autodoc_code_start,
autodoc_code_end,
autodoc_code,
dummy, /* autodoc_tag_list_start */
dummy, /* autodoc_tag_list_end */
autodoc_tag_entry_start,
autodoc_tag_entry_start_extra,
autodoc_tag_entry_end,
autodoc_tag_entry_end_extra,
autodoc_table_start,
autodoc_table_entry,
autodoc_table_end,
autodoc_indent,
autodoc_list_start,
autodoc_code, /* autodoc_list_entry */
autodoc_list_separator,
autodoc_list_end,
autodoc_include,
autodoc_file_end, /* autodoc_file_end */
autodoc_text,
autodoc_char,
NULL, /* autodoc_parse_option */
dummy, /* autodoc_print_options */
autodoc_name,
autodoc_terse_sep,
autodoc_text, /* autodoc_reference */
autodoc_text, /* autodoc_emphasized */
autodoc_description,
autodoc_returns
};
syntax highlighted by Code2HTML, v. 0.9.1