#ifdef _AIX
#pragma alloca
#endif
int major_version = 1;
int minor_version = 68;
#include "system.h"
#include "getopt.h"
#ifdef TM_IN_SYS_TIME
#include <sys/time.h>
#else
#include <time.h>
#endif
#ifdef __GNUC__
# undef alloca
# define alloca __builtin_alloca
#else
# ifdef HAVE_ALLOCA_H
# include <alloca.h>
# else
# ifndef _AIX
char *alloca ();
# endif
# endif
#endif
#if HAVE_VPRINTF
# if __STDC__
# include <stdarg.h>
# define VA_START(args, lastarg) va_start(args, lastarg)
# else
# include <varargs.h>
# define VA_START(args, lastarg) va_start(args)
# endif
# define VA_FPRINTF(file, fmt, ap) vfprintf (file, fmt, ap)
# define VA_SPRINTF(str, fmt, ap) vsprintf (str, fmt, ap)
#else
# define VA_START(args, lastarg)
# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
# define va_end(args)
#endif
#define DEFAULT_INDENTATION_INCREMENT 5
#define PARAGRAPH_START_INDENT 3
#define DEFAULT_PARAGRAPH_SPACING 1
#define HAVE_MACROS
#define COMPILING_MAKEINFO
#include "makeinfo.h"
static int in_fixed_width_font = 0;
int must_start_paragraph = 0;
static int executing_string = 0;
static int me_executing_string = 0;
#if defined (HAVE_MACROS)
FILE *macro_expansion_output_stream = (FILE *)NULL;
char *macro_expansion_filename;
typedef struct {
char *pointer;
int offset;
} ITEXT;
static ITEXT **itext_info = (ITEXT **)NULL;
static int itext_size = 0;
int me_inhibit_expansion = 0;
ITEXT *remember_itext ();
void forget_itext (), me_append_before_this_command ();
void append_to_expansion_output (), write_region_to_macro_output ();
void maybe_write_itext (), me_execute_string ();
#endif
char *progname;
#define looking_at(string) \
(strncmp (input_text + input_text_offset, string, strlen (string)) == 0)
char *output_filename = (char *)NULL;
char *pretty_output_filename;
char *command_output_filename = (char *)NULL;
char *include_files_path = (char *)NULL;
int output_position;
#define INITIAL_PARAGRAPH_SPACE 5000
int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE;
int filling_enabled = 1;
int non_splitting_words = 0;
int indented_fill = 0;
int paragraph_start_indent = PARAGRAPH_START_INDENT;
int inhibit_paragraph_indentation = 0;
int pending_indent = 0;
int default_indentation_increment = DEFAULT_INDENTATION_INCREMENT;
int no_indent = 1;
int force_flush_right = 0;
int footnote_style_preset = 0;
int number_footnotes = 1;
int current_footnote_number = 1;
char *command;
int command_index;
char node_search_string[] =
{ '\n', COMMAND_PREFIX, 'n', 'o', 'd', 'e', ' ', 0 };
char menu_search_string[] =
{ '\n', COMMAND_PREFIX, 'm', 'e', 'n', 'u', 0 };
char setfilename_search[] =
{ COMMAND_PREFIX,
's', 'e', 't', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', 0 };
typedef struct fstack
{
struct fstack *next;
char *filename;
char *text;
int size;
int offset;
int line_number;
} FSTACK;
FSTACK *filestack = (FSTACK *) NULL;
char *current_node = (char *)NULL;
int current_section = 0;
char *node_filename = (char *)NULL;
typedef struct tentry
{
struct tentry *next_ent;
char *node;
char *prev;
char *next;
char *up;
int position;
int line_no;
char *filename;
int touched;
int flags;
} TAG_ENTRY;
#define PREV_ERROR 0x1
#define NEXT_ERROR 0x2
#define UP_ERROR 0x4
#define NO_WARN 0x8
#define IS_TOP 0x10
TAG_ENTRY *tag_table = (TAG_ENTRY *) NULL;
#define SET 1
#define CLEAR 2
#define IFSET 3
#define IFCLEAR 4
#if defined (HAVE_MACROS)
#define ME_RECURSE 0x01
#define ME_QUOTE_ARG 0x02
typedef struct {
char *name;
char **arglist;
char *body;
char *source_file;
int source_lineno;
int inhibited;
int flags;
} MACRO_DEF;
void add_macro (), execute_macro ();
MACRO_DEF *find_macro (), *delete_macro ();
#endif
enum reftype
{
menu_reference, followed_reference
};
typedef struct node_ref
{
struct node_ref *next;
char *node;
char *containing_node;
int line_no;
int section;
char *filename;
enum reftype type;
} NODE_REF;
NODE_REF *node_references = (NODE_REF *) NULL;
int in_menu = 0;
int in_detailmenu = 0;
int top_node_seen = 0;
int non_top_node_seen = 0;
int force = 0;
int print_warnings = 1;
int validating = 1;
int no_headers = 0;
int max_error_level = 100;
int reference_warning_limit = 1000;
int verbose_mode = 0;
int allow_lax_format = 0;
#define START 0
#define END 1
typedef struct brace_element
{
struct brace_element *next;
COMMAND_FUNCTION *proc;
int pos, line;
int in_fixed_width_font;
} BRACE_ELEMENT;
BRACE_ELEMENT *brace_stack = (BRACE_ELEMENT *) NULL;
extern void do_multitable ();
void print_version_info ();
void usage ();
void push_node_filename (), pop_node_filename ();
void remember_error (), flush_file_stack ();
void convert_from_stream (), convert_from_file (), convert_from_loaded_file ();
void init_internals (), init_paragraph (), init_brace_stack ();
void init_insertion_stack (), init_indices ();
void init_tag_table (), write_tag_table (), write_tag_table_internal ();
void validate_file (), validate_other_references (), split_file ();
void free_node_references (), do_enumeration (), handle_variable ();
void handle_variable_internal ();
void normalize_node_name ();
void undefindex (), top_defindex (), gen_defindex ();
void define_user_command ();
void free_pending_notes (), output_pending_notes ();
char **get_brace_args ();
char *expansion ();
int array_len ();
void free_array ();
static int end_of_sentence_p ();
static void isolate_nodename ();
void reader_loop (), read_command ();
void remember_brace (), remember_brace_1 ();
void pop_and_call_brace (), discard_braces ();
void add_word (), add_char (), insert (), flush_output ();
void insert_string ();
void close_paragraph_with_lines (), close_paragraph ();
void ignore_blank_line ();
void do_flush_right_indentation (), discard_insertions ();
void start_paragraph (), indent ();
#if defined (VA_FPRINTF) && __STDC__
void add_word_args (char *, ...);
void execute_string (char *, ...);
#else
void add_word_args ();
void execute_string ();
#endif
void insert_self (), insert_space (), cm_ignore_line ();
void
cm_TeX (), cm_asterisk (), cm_bullet (), cm_cite (),
cm_code (), cm_copyright (), cm_ctrl (), cm_dfn (), cm_dircategory (),
cm_direntry (), cm_dots (), cm_emph (), cm_enddots (),
cm_kbd (), cm_key (), cm_no_op (), cm_no_op_line_arg (),
cm_not_fixed_width (), cm_strong (), cm_var_sc (), cm_w (), cm_image ();
void
cm_chapter (), cm_unnumbered (), cm_appendix (), cm_top (),
cm_section (), cm_unnumberedsec (), cm_appendixsec (),
cm_subsection (), cm_unnumberedsubsec (), cm_appendixsubsec (),
cm_subsubsection (), cm_unnumberedsubsubsec (), cm_appendixsubsubsec (),
cm_heading (), cm_chapheading (), cm_subheading (), cm_subsubheading (),
cm_majorheading (), cm_raisesections (), cm_lowersections ();
void cm_defun (), cm_accent (), cm_special_char (), cm_dotless ();
void
cm_node (), cm_menu (), cm_xref (), cm_ftable (), cm_vtable (), cm_pxref (),
cm_inforef (), cm_uref (), cm_email (), cm_quotation (),
cm_display (), cm_itemize (),
cm_enumerate (), cm_tab (), cm_table (), cm_itemx (), cm_noindent (),
cm_setfilename (), cm_br (), cm_sp (), cm_page (), cm_group (),
cm_center (), cm_include (), cm_bye (), cm_item (), cm_end (),
cm_ifinfo (), cm_ifnothtml (), cm_ifnottex (), cm_kindex (), cm_cindex (),
cm_findex (), cm_pindex (), cm_vindex (), cm_tindex (),
cm_synindex (), cm_printindex (), cm_minus (), cm_footnote (),
cm_example (), cm_smallexample (), cm_lisp (), cm_format (), cm_exdent (),
cm_defindex (), cm_defcodeindex (), cm_result (), cm_expansion (),
cm_equiv (), cm_print (), cm_error (), cm_point (), cm_today (),
cm_flushleft (), cm_flushright (), cm_smalllisp (), cm_finalout (),
cm_cartouche (), cm_detailmenu (), cm_multitable ();
void cm_set (), cm_clear (), cm_ifset (), cm_ifclear ();
void cm_value (), cm_ifeq ();
#if defined (HAVE_MACROS)
void cm_macro (), cm_unmacro ();
#endif
void cm_paragraphindent (), cm_footnotestyle ();
void command_name_condition (), misplaced_brace (), cm_obsolete (),
cm_ideprecated ();
typedef struct
{
char *name;
COMMAND_FUNCTION *proc;
int argument_in_braces;
} COMMAND;
COMMAND **user_command_array = (COMMAND **) NULL;
int user_command_array_len = 0;
#define NO_BRACE_ARGS 0
#define BRACE_ARGS 1
static COMMAND command_table[] = {
{ "\t", insert_space, NO_BRACE_ARGS },
{ "\n", insert_space, NO_BRACE_ARGS },
{ " ", insert_self, NO_BRACE_ARGS },
{ "!", insert_self, NO_BRACE_ARGS },
{ "\"", insert_self, NO_BRACE_ARGS },
{ "'", insert_self, NO_BRACE_ARGS },
{ "*", cm_asterisk, NO_BRACE_ARGS },
{ ",", cm_accent, BRACE_ARGS },
{ "-", cm_no_op, NO_BRACE_ARGS },
{ ".", insert_self, NO_BRACE_ARGS },
{ ":", cm_no_op, NO_BRACE_ARGS },
{ "=", insert_self, NO_BRACE_ARGS },
{ "?", insert_self, NO_BRACE_ARGS },
{ "@", insert_self, NO_BRACE_ARGS },
{ "^", insert_self, NO_BRACE_ARGS },
{ "`", insert_self, NO_BRACE_ARGS },
{ "{", insert_self, NO_BRACE_ARGS },
{ "|", cm_no_op, NO_BRACE_ARGS },
{ "}", insert_self, NO_BRACE_ARGS },
{ "~", insert_self, NO_BRACE_ARGS },
{ "AA", insert_self, BRACE_ARGS },
{ "AE", insert_self, BRACE_ARGS },
{ "H", cm_accent, BRACE_ARGS },
{ "L", cm_special_char, BRACE_ARGS },
{ "O", cm_special_char, BRACE_ARGS },
{ "OE", insert_self, BRACE_ARGS },
{ "TeX", cm_TeX, BRACE_ARGS },
{ "aa", insert_self, BRACE_ARGS },
{ "ae", insert_self, BRACE_ARGS },
{ "appendix", cm_appendix, NO_BRACE_ARGS },
{ "appendixsection", cm_appendixsec, NO_BRACE_ARGS },
{ "appendixsec", cm_appendixsec, NO_BRACE_ARGS },
{ "appendixsubsec", cm_appendixsubsec, NO_BRACE_ARGS },
{ "appendixsubsubsec", cm_appendixsubsubsec, NO_BRACE_ARGS },
{ "asis", cm_no_op, BRACE_ARGS },
{ "b", cm_not_fixed_width, BRACE_ARGS },
{ "bullet", cm_bullet, BRACE_ARGS },
{ "bye", cm_bye, NO_BRACE_ARGS },
{ "c", cm_ignore_line, NO_BRACE_ARGS },
{ "cartouche", cm_cartouche, NO_BRACE_ARGS },
{ "center", cm_center, NO_BRACE_ARGS },
{ "centerchap", cm_unnumbered, NO_BRACE_ARGS },
{ "chapheading", cm_chapheading, NO_BRACE_ARGS },
{ "chapter", cm_chapter, NO_BRACE_ARGS },
{ "cindex", cm_cindex, NO_BRACE_ARGS },
{ "cite", cm_cite, BRACE_ARGS },
{ "clear", cm_clear, NO_BRACE_ARGS },
{ "code", cm_code, BRACE_ARGS },
{ "comment", cm_ignore_line, NO_BRACE_ARGS },
{ "contents", cm_no_op, NO_BRACE_ARGS },
{ "copyright", cm_copyright, BRACE_ARGS },
{ "ctrl", cm_obsolete, BRACE_ARGS },
{ "defcodeindex", cm_defcodeindex, NO_BRACE_ARGS },
{ "defindex", cm_defindex, NO_BRACE_ARGS },
{ "defcv", cm_defun, NO_BRACE_ARGS },
{ "defcvx", cm_defun, NO_BRACE_ARGS },
{ "deffn", cm_defun, NO_BRACE_ARGS },
{ "deffnx", cm_defun, NO_BRACE_ARGS },
{ "defivar", cm_defun, NO_BRACE_ARGS },
{ "defivarx", cm_defun, NO_BRACE_ARGS },
{ "defmac", cm_defun, NO_BRACE_ARGS },
{ "defmacx", cm_defun, NO_BRACE_ARGS },
{ "defmethod", cm_defun, NO_BRACE_ARGS },
{ "defmethodx", cm_defun, NO_BRACE_ARGS },
{ "defop", cm_defun, NO_BRACE_ARGS },
{ "defopt", cm_defun, NO_BRACE_ARGS },
{ "defoptx", cm_defun, NO_BRACE_ARGS },
{ "defopx", cm_defun, NO_BRACE_ARGS },
{ "defspec", cm_defun, NO_BRACE_ARGS },
{ "defspecx", cm_defun, NO_BRACE_ARGS },
{ "deftp", cm_defun, NO_BRACE_ARGS },
{ "deftpx", cm_defun, NO_BRACE_ARGS },
{ "deftypefn", cm_defun, NO_BRACE_ARGS },
{ "deftypefnx", cm_defun, NO_BRACE_ARGS },
{ "deftypefun", cm_defun, NO_BRACE_ARGS },
{ "deftypefunx", cm_defun, NO_BRACE_ARGS },
{ "deftypemethod", cm_defun, NO_BRACE_ARGS },
{ "deftypemethodx", cm_defun, NO_BRACE_ARGS },
{ "deftypevar", cm_defun, NO_BRACE_ARGS },
{ "deftypevarx", cm_defun, NO_BRACE_ARGS },
{ "deftypevr", cm_defun, NO_BRACE_ARGS },
{ "deftypevrx", cm_defun, NO_BRACE_ARGS },
{ "defun", cm_defun, NO_BRACE_ARGS },
{ "defunx", cm_defun, NO_BRACE_ARGS },
{ "defvar", cm_defun, NO_BRACE_ARGS },
{ "defvarx", cm_defun, NO_BRACE_ARGS },
{ "defvr", cm_defun, NO_BRACE_ARGS },
{ "defvrx", cm_defun, NO_BRACE_ARGS },
{ "detailmenu", cm_detailmenu, NO_BRACE_ARGS },
{ "dfn", cm_dfn, BRACE_ARGS },
{ "dircategory", cm_dircategory, NO_BRACE_ARGS },
{ "direntry", cm_direntry, NO_BRACE_ARGS },
{ "display", cm_display, NO_BRACE_ARGS },
{ "dmn", cm_no_op, BRACE_ARGS },
{ "dotaccent", cm_accent, BRACE_ARGS },
{ "dotless", cm_dotless, BRACE_ARGS },
{ "dots", cm_dots, BRACE_ARGS },
{ "email", cm_email, BRACE_ARGS },
{ "emph", cm_emph, BRACE_ARGS },
{ "end", cm_end, NO_BRACE_ARGS },
{ "enddots", cm_enddots, BRACE_ARGS },
{ "enumerate", cm_enumerate, NO_BRACE_ARGS },
{ "equiv", cm_equiv, BRACE_ARGS },
{ "error", cm_error, BRACE_ARGS },
{ "example", cm_example, NO_BRACE_ARGS },
{ "exclamdown", cm_special_char, BRACE_ARGS },
{ "exdent", cm_exdent, NO_BRACE_ARGS },
{ "expansion", cm_expansion, BRACE_ARGS },
{ "file", cm_code, BRACE_ARGS },
{ "finalout", cm_no_op, NO_BRACE_ARGS },
{ "findex", cm_findex, NO_BRACE_ARGS },
{ "flushleft", cm_flushleft, NO_BRACE_ARGS },
{ "flushright", cm_flushright, NO_BRACE_ARGS },
{ "footnote", cm_footnote, NO_BRACE_ARGS},
{ "footnotestyle", cm_footnotestyle, NO_BRACE_ARGS },
{ "format", cm_format, NO_BRACE_ARGS },
{ "ftable", cm_ftable, NO_BRACE_ARGS },
{ "group", cm_group, NO_BRACE_ARGS },
{ "heading", cm_heading, NO_BRACE_ARGS },
{ "headings", cm_ignore_line, NO_BRACE_ARGS },
{ "html", command_name_condition, NO_BRACE_ARGS },
{ "hyphenation", cm_no_op, BRACE_ARGS },
{ "i", cm_not_fixed_width, BRACE_ARGS },
{ "ifclear", cm_ifclear, NO_BRACE_ARGS },
{ "ifeq", cm_ifeq, NO_BRACE_ARGS },
{ "ifhtml", command_name_condition, NO_BRACE_ARGS },
{ "ifinfo", cm_ifinfo, NO_BRACE_ARGS },
{ "ifnothtml", cm_ifnothtml, NO_BRACE_ARGS },
{ "ifnotinfo", command_name_condition, NO_BRACE_ARGS },
{ "ifnottex", cm_ifnottex, NO_BRACE_ARGS },
{ "ifset", cm_ifset, NO_BRACE_ARGS },
{ "iftex", command_name_condition, NO_BRACE_ARGS },
{ "ignore", command_name_condition, NO_BRACE_ARGS },
{ "image", cm_image, BRACE_ARGS },
{ "include", cm_include, NO_BRACE_ARGS },
{ "inforef", cm_inforef, BRACE_ARGS },
{ "item", cm_item, NO_BRACE_ARGS },
{ "itemize", cm_itemize, NO_BRACE_ARGS },
{ "itemx", cm_itemx, NO_BRACE_ARGS },
{ "kbd", cm_kbd, BRACE_ARGS },
{ "kbdinputstyle", cm_no_op_line_arg, NO_BRACE_ARGS },
{ "key", cm_key, BRACE_ARGS },
{ "kindex", cm_kindex, NO_BRACE_ARGS },
{ "l", cm_special_char, BRACE_ARGS },
{ "lisp", cm_lisp, NO_BRACE_ARGS },
{ "lowersections", cm_lowersections, NO_BRACE_ARGS },
{ "macro", cm_macro, NO_BRACE_ARGS },
{ "majorheading", cm_majorheading, NO_BRACE_ARGS },
{ "math", cm_no_op, BRACE_ARGS },
{ "menu", cm_menu, NO_BRACE_ARGS },
{ "minus", cm_minus, BRACE_ARGS },
{ "multitable", cm_multitable, NO_BRACE_ARGS },
{ "need", cm_ignore_line, NO_BRACE_ARGS },
{ "node", cm_node, NO_BRACE_ARGS },
{ "noindent", cm_noindent, NO_BRACE_ARGS },
{ "nwnode", cm_node, NO_BRACE_ARGS },
{ "o", cm_special_char, BRACE_ARGS },
{ "oe", insert_self, BRACE_ARGS },
{ "page", cm_no_op, NO_BRACE_ARGS },
{ "paragraphindent", cm_paragraphindent, NO_BRACE_ARGS },
{ "pindex", cm_pindex, NO_BRACE_ARGS },
{ "point", cm_point, BRACE_ARGS },
{ "pounds", cm_special_char, BRACE_ARGS },
{ "print", cm_print, BRACE_ARGS },
{ "printindex", cm_printindex, NO_BRACE_ARGS },
{ "pxref", cm_pxref, BRACE_ARGS },
{ "questiondown", cm_special_char, BRACE_ARGS },
{ "quotation", cm_quotation, NO_BRACE_ARGS },
{ "r", cm_not_fixed_width, BRACE_ARGS },
{ "raisesections", cm_raisesections, NO_BRACE_ARGS },
{ "ref", cm_xref, BRACE_ARGS },
{ "refill", cm_no_op, NO_BRACE_ARGS },
{ "result", cm_result, BRACE_ARGS },
{ "ringaccent", cm_accent, BRACE_ARGS },
{ "samp", cm_code, BRACE_ARGS },
{ "sc", cm_var_sc, BRACE_ARGS },
{ "section", cm_section, NO_BRACE_ARGS },
{ "set", cm_set, NO_BRACE_ARGS },
{ "setchapternewpage", cm_ignore_line, NO_BRACE_ARGS },
{ "setchapterstyle", cm_obsolete, NO_BRACE_ARGS },
{ "setfilename", cm_setfilename, NO_BRACE_ARGS },
{ "settitle", cm_ignore_line, NO_BRACE_ARGS },
{ "shortcontents", cm_no_op, NO_BRACE_ARGS },
{ "shorttitlepage", cm_ignore_line, NO_BRACE_ARGS },
{ "smallbook", cm_ignore_line, NO_BRACE_ARGS },
{ "smallexample", cm_smallexample, NO_BRACE_ARGS },
{ "smalllisp", cm_smalllisp, NO_BRACE_ARGS },
{ "sp", cm_sp, NO_BRACE_ARGS },
{ "ss", insert_self, BRACE_ARGS },
{ "strong", cm_strong, BRACE_ARGS },
{ "subheading", cm_subheading, NO_BRACE_ARGS },
{ "subsection", cm_subsection, NO_BRACE_ARGS },
{ "subsubheading", cm_subsubheading, NO_BRACE_ARGS },
{ "subsubsection", cm_subsubsection, NO_BRACE_ARGS },
{ "summarycontents", cm_no_op, NO_BRACE_ARGS },
{ "syncodeindex", cm_synindex, NO_BRACE_ARGS },
{ "synindex", cm_synindex, NO_BRACE_ARGS },
{ "t", cm_no_op, BRACE_ARGS },
{ "tab", cm_tab, NO_BRACE_ARGS },
{ "table", cm_table, NO_BRACE_ARGS },
{ "tex", command_name_condition, NO_BRACE_ARGS },
{ "tieaccent", cm_accent, BRACE_ARGS },
{ "tindex", cm_tindex, NO_BRACE_ARGS },
{ "titlefont", cm_not_fixed_width, BRACE_ARGS },
{ "titlepage", command_name_condition, NO_BRACE_ARGS },
{ "today", cm_today, BRACE_ARGS },
{ "top", cm_top, NO_BRACE_ARGS },
{ "u", cm_accent, BRACE_ARGS },
{ "ubaraccent", cm_accent, BRACE_ARGS },
{ "udotaccent", cm_accent, BRACE_ARGS },
#if defined (HAVE_MACROS)
{ "unmacro", cm_unmacro, NO_BRACE_ARGS },
#endif
{ "unnumbered", cm_unnumbered, NO_BRACE_ARGS },
{ "unnumberedsec", cm_unnumberedsec, NO_BRACE_ARGS },
{ "unnumberedsubsec", cm_unnumberedsubsec, NO_BRACE_ARGS },
{ "unnumberedsubsubsec", cm_unnumberedsubsubsec, NO_BRACE_ARGS },
{ "uref", cm_uref, BRACE_ARGS },
{ "url", cm_code, BRACE_ARGS },
{ "v", cm_accent, BRACE_ARGS },
{ "value", cm_value, BRACE_ARGS },
{ "var", cm_var_sc, BRACE_ARGS },
{ "vindex", cm_vindex, NO_BRACE_ARGS },
{ "vtable", cm_vtable, NO_BRACE_ARGS },
{ "w", cm_w, BRACE_ARGS },
{ "xref", cm_xref, BRACE_ARGS },
{ "iappendix", cm_ideprecated, NO_BRACE_ARGS },
{ "iappendixsec", cm_ideprecated, NO_BRACE_ARGS },
{ "iappendixsection", cm_ideprecated, NO_BRACE_ARGS },
{ "iappendixsubsec", cm_ideprecated, NO_BRACE_ARGS },
{ "iappendixsubsubsec", cm_ideprecated, NO_BRACE_ARGS },
{ "ichapter", cm_ideprecated, NO_BRACE_ARGS },
{ "isection", cm_ideprecated, NO_BRACE_ARGS },
{ "isubsection", cm_ideprecated, NO_BRACE_ARGS },
{ "isubsubsection", cm_ideprecated, NO_BRACE_ARGS },
{ "iunnumbered", cm_ideprecated, NO_BRACE_ARGS },
{ "iunnumberedsec", cm_ideprecated, NO_BRACE_ARGS },
{ "iunnumberedsubsec", cm_ideprecated, NO_BRACE_ARGS },
{ "iunnumberedsubsubsec", cm_ideprecated, NO_BRACE_ARGS },
{ "infoinclude", cm_obsolete, NO_BRACE_ARGS },
{ "titlespec", cm_obsolete, NO_BRACE_ARGS },
{ NULL, NULL, NO_BRACE_ARGS }
};
struct option long_options[] =
{
{ "error-limit", 1, 0, 'e' },
{ "fill-column", 1, 0, 'f' },
{ "footnote-style", 1, 0, 's' },
{ "force", 0, 0, 'F' },
{ "no-headers", 0, &no_headers, 1 },
{ "no-pointer-validate", 0, &validating, 0 },
{ "no-validate", 0, &validating, 0 },
{ "no-split", 0, &splitting, 0 },
{ "no-warn", 0, &print_warnings, 0 },
{ "macro-expand", 1, 0, 'E' },
{ "number-footnotes", 0, &number_footnotes, 1 },
{ "no-number-footnotes", 0, &number_footnotes, 0 },
{ "output", 1, 0, 'o' },
{ "paragraph-indent", 1, 0, 'p' },
{ "reference-limit", 1, 0, 'r' },
{ "verbose", 0, &verbose_mode, 1 },
{ "help", 0, 0, 'h' },
{ "version", 0, 0, 'V' },
{NULL, 0, NULL, 0}
};
int errors_printed = 0;
int
fs_error (filename)
char *filename;
{
remember_error ();
perror (filename);
return (0);
}
void
#if defined (VA_FPRINTF) && __STDC__
error (char *format, ...)
#else
error (format, va_alist)
char *format;
va_dcl
#endif
{
#ifdef VA_FPRINTF
va_list ap;
#endif
remember_error ();
VA_START (ap, format);
#ifdef VA_FPRINTF
VA_FPRINTF (stderr, format, ap);
#else
fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
#endif
va_end (ap);
putc ('\n', stderr);
}
void
#if defined (VA_FPRINTF) && __STDC__
line_error (char *format, ...)
#else
line_error (format, va_alist)
char *format;
va_dcl
#endif
{
#ifdef VA_FPRINTF
va_list ap;
#endif
remember_error ();
fprintf (stderr, "%s:%d: ", input_filename, line_number);
VA_START (ap, format);
#ifdef VA_FPRINTF
VA_FPRINTF (stderr, format, ap);
#else
fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
#endif
va_end (ap);
fprintf (stderr, ".\n");
}
void
#if defined (VA_FPRINTF) && __STDC__
warning (char *format, ...)
#else
warning (format, va_alist)
char *format;
va_dcl
#endif
{
#ifdef VA_FPRINTF
va_list ap;
#endif
if (print_warnings)
{
fprintf (stderr, _("%s:%d: warning: "), input_filename, line_number);
VA_START (ap, format);
#ifdef VA_FPRINTF
VA_FPRINTF (stderr, format, ap);
#else
fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
#endif
va_end (ap);
fprintf (stderr, ".\n");
}
}
void
remember_error ()
{
errors_printed++;
if (max_error_level && (errors_printed > max_error_level))
{
fprintf (stderr, _("Too many errors! Gave up.\n"));
flush_file_stack ();
cm_bye ();
exit (FATAL);
}
}
int
main (argc, argv)
int argc;
char **argv;
{
extern int errors_printed;
char *filename_part ();
int c, ind;
int reading_from_stdin = 0;
progname = filename_part (argv[0]);
#ifdef HAVE_SETLOCALE
setlocale (LC_TIME, "");
#ifdef HAVE_LC_MESSAGES
setlocale (LC_MESSAGES, "");
#endif
#endif
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
while ((c = getopt_long (argc, argv, "D:e:E:f:I:o:p:P:r:s:U:V",
long_options, &ind)) != EOF)
{
if (c == 0 && long_options[ind].flag == 0)
c = long_options[ind].val;
switch (c)
{
case 'D':
case 'U':
handle_variable_internal ((c == 'D') ? SET : CLEAR, optarg);
break;
case 'e':
if (sscanf (optarg, "%d", &max_error_level) != 1)
{
fprintf (stderr,
_("%s: %s arg must be numeric, not `%s'.\n"),
"--error-limit", progname, optarg);
usage (stderr, FATAL);
}
break;
case 'E':
if (!macro_expansion_output_stream)
{
macro_expansion_filename = optarg;
macro_expansion_output_stream
= strcmp (optarg, "-") == 0 ? stdout : fopen (optarg, "w");
if (!macro_expansion_output_stream)
error (_("Couldn't open macro expansion output `%s'"), optarg);
}
else
error (_("Cannot specify more than one macro expansion output"));
break;
case 'f':
if (sscanf (optarg, "%d", &fill_column) != 1)
{
fprintf (stderr,
_("%s: %s arg must be numeric, not `%s'.\n"),
"--fill-column", progname, optarg);
usage (FATAL);
}
break;
case 'F':
force++;
break;
case 'h':
usage (NO_ERROR);
break;
case 'I':
if (!include_files_path)
include_files_path = xstrdup (".");
include_files_path = (char *)
xrealloc (include_files_path,
2 + strlen (include_files_path) + strlen (optarg));
strcat (include_files_path, ":");
strcat (include_files_path, optarg);
break;
case 'o':
command_output_filename = xstrdup (optarg);
break;
case 'p':
if (set_paragraph_indent (optarg) < 0)
{
fprintf (stderr,
_("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"),
progname, optarg);
usage (FATAL);
}
break;
case 'P':
if (!include_files_path)
{
include_files_path = xstrdup (optarg);
include_files_path = (char *) xrealloc (include_files_path,
strlen (include_files_path) + 3);
strcat (include_files_path, ":.");
}
else
{
char *tmp = xstrdup (include_files_path);
include_files_path = (char *) xrealloc (include_files_path,
strlen (include_files_path) + strlen (optarg) + 2);
strcpy (include_files_path, optarg);
strcat (include_files_path, ":");
strcat (include_files_path, tmp);
free (tmp);
}
break;
case 'r':
if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
{
fprintf (stderr,
_("%s: %s arg must be numeric, not `%s'.\n"),
"--reference-limit", progname, optarg);
usage (FATAL);
}
break;
case 's':
if (set_footnote_style (optarg) < 0)
{
fprintf (stderr,
_("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"),
progname, optarg);
usage (FATAL);
}
footnote_style_preset = 1;
break;
case 'V':
print_version_info ();
printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
There is NO warranty. You may redistribute this software\n\
under the terms of the GNU General Public License.\n\
For more information about these matters, see the files named COPYING.\n"),
"1998");
exit (NO_ERROR);
break;
case '?':
usage (FATAL);
break;
}
}
if (optind == argc)
{
if (!isatty (fileno (stdin)))
reading_from_stdin = 1;
else
{
fprintf (stderr, _("%s: missing file argument.\n"), progname);
usage (FATAL);
}
}
if (no_headers)
{
splitting = 0;
if (!command_output_filename)
command_output_filename = xstrdup ("-");
}
if (verbose_mode)
print_version_info ();
if (!reading_from_stdin)
{
while (optind != argc)
convert_from_file (argv[optind++]);
}
else
convert_from_stream (stdin, "stdin");
if (errors_printed)
return (SYNTAX);
else
return (NO_ERROR);
}
void
print_version_info ()
{
printf ("makeinfo (GNU %s %s) %d.%d\n", PACKAGE, VERSION,
major_version, minor_version);
}
void
usage (exit_value)
int exit_value;
{
if (exit_value != 0)
fprintf (stderr, _("Try `%s --help' for more information.\n"), progname);
else
printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n\
\n\
Translate Texinfo source documentation to a format suitable for reading\n\
with GNU Info.\n\
\n\
Options:\n\
-D VAR define a variable, as with @set.\n\
-E MACRO-OFILE process macros only, output texinfo source.\n\
-I DIR append DIR to the @include directory search path.\n\
-P DIR prepend DIR to the @include directory search path.\n\
-U VAR undefine a variable, as with @clear.\n\
--error-limit NUM quit after NUM errors (default %d).\n\
--fill-column NUM break lines at NUM characters (default %d).\n\
--footnote-style STYLE output footnotes according to STYLE:\n\
`separate' to place footnotes in their own node,\n\
`end' to place the footnotes at the end of\n\
the node in which they are defined (the default).\n\
--force preserve output even if errors.\n\
--help display this help and exit.\n\
--no-validate suppress node cross-reference validation.\n\
--no-warn suppress warnings (but not errors).\n\
--no-split suppress splitting of large files.\n\
--no-headers suppress node separators and Node: Foo headers.\n\
--output FILE, -o FILE output to FILE, and ignore any @setfilename.\n\
--paragraph-indent VAL indent paragraphs with VAL spaces (default %d).\n\
if VAL is `none', do not indent; if VAL is `asis',\n\
preserve any existing indentation.\n\
--reference-limit NUM complain about at most NUM references (default %d).\n\
--verbose report about what is being done.\n\
--version display version information and exit.\n\
\n\
Email bug reports to bug-texinfo@gnu.org.\n\
"),
progname, max_error_level, fill_column,
paragraph_start_indent, reference_warning_limit);
exit (exit_value);
}
typedef struct generic_list {
struct generic_list *next;
} GENERIC_LIST;
GENERIC_LIST *
reverse_list (list)
register GENERIC_LIST *list;
{
register GENERIC_LIST *next;
register GENERIC_LIST *prev = (GENERIC_LIST *) NULL;
while (list)
{
next = list->next;
list->next = prev;
prev = list;
list = next;
}
return (prev);
}
char *
find_and_load (filename)
char *filename;
{
struct stat fileinfo;
long file_size;
int file = -1, count = 0;
char *fullpath, *result, *get_file_info_in_path ();
result = fullpath = (char *)NULL;
fullpath = get_file_info_in_path (filename, include_files_path, &fileinfo);
if (!fullpath)
goto error_exit;
filename = fullpath;
file_size = (long) fileinfo.st_size;
file = open (filename, O_RDONLY);
if (file < 0)
goto error_exit;
result = xmalloc (file_size + 2);
#if defined (VMS) || defined (WIN32)
#ifdef VMS
while ((n = read (file, result + count, file_size)) > 0)
#else
while ((n = read (file, result + count, 1)) > 0)
#endif
count += n;
if (n == -1)
#else
count = file_size;
if (read (file, result, file_size) != file_size)
#endif
error_exit:
{
if (result)
free (result);
if (fullpath)
free (fullpath);
if (file != -1)
close (file);
return ((char *) NULL);
}
close (file);
input_text = result;
size_of_input_text = count;
input_filename = fullpath;
node_filename = xstrdup (fullpath);
input_text_offset = 0;
line_number = 1;
input_text[size_of_input_text] = '\n';
input_text[size_of_input_text+1] = 0;
return (result);
}
void
pushfile ()
{
FSTACK *newstack = (FSTACK *) xmalloc (sizeof (FSTACK));
newstack->filename = input_filename;
newstack->text = input_text;
newstack->size = size_of_input_text;
newstack->offset = input_text_offset;
newstack->line_number = line_number;
newstack->next = filestack;
filestack = newstack;
push_node_filename ();
}
void
popfile ()
{
FSTACK *tos = filestack;
if (!tos)
abort ();
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream)
{
maybe_write_itext (input_text, input_text_offset);
forget_itext (input_text);
}
#endif
filestack = filestack->next;
if (!executing_string && !me_executing_string)
discard_braces ();
input_filename = tos->filename;
input_text = tos->text;
size_of_input_text = tos->size;
input_text_offset = tos->offset;
line_number = tos->line_number;
free (tos);
pop_node_filename ();
}
void
flush_file_stack ()
{
while (filestack)
{
char *fname = input_filename;
char *text = input_text;
popfile ();
free (fname);
free (text);
}
}
int node_filename_stack_index = 0;
int node_filename_stack_size = 0;
char **node_filename_stack = (char **)NULL;
void
push_node_filename ()
{
if (node_filename_stack_index + 1 > node_filename_stack_size)
node_filename_stack = (char **)xrealloc
(node_filename_stack, (node_filename_stack_size += 10) * sizeof (char *));
node_filename_stack[node_filename_stack_index] = node_filename;
node_filename_stack_index++;
}
void
pop_node_filename ()
{
node_filename = node_filename_stack[--node_filename_stack_index];
}
char *
filename_part (filename)
char *filename;
{
char *basename;
basename = strrchr (filename, '/');
if (!basename)
basename = filename;
else
basename++;
basename = xstrdup (basename);
#if defined (REMOVE_OUTPUT_EXTENSIONS)
{
char *temp;
temp = strrchr (basename, '.');
if (temp)
*temp = 0;
}
#endif
return (basename);
}
char *
pathname_part (filename)
char *filename;
{
char *expand_filename ();
char *result = (char *) NULL;
register int i;
filename = expand_filename (filename, "");
i = strlen (filename) - 1;
while (i && filename[i] != '/')
i--;
if (filename[i] == '/')
i++;
if (i)
{
result = (char *)xmalloc (1 + i);
strncpy (result, filename, i);
result[i] = 0;
}
free (filename);
return (result);
}
char *
filename_non_directory (name)
char *name;
{
register int i;
for (i = strlen (name) - 1; i; i--)
if (name[i] == '/')
return (xstrdup (name + i + 1));
return (xstrdup (name));
}
char *
expand_filename (filename, input_name)
char *filename, *input_name;
{
register int i;
char *full_pathname ();
if (filename)
filename = full_pathname (filename);
else
{
filename = filename_non_directory (input_name);
if (!*filename)
{
free (filename);
filename = xstrdup ("noname.texi");
}
for (i = strlen (filename) - 1; i; i--)
if (filename[i] == '.')
break;
if (!i)
i = strlen (filename);
if (i + 6 > (strlen (filename)))
filename = (char *)xrealloc (filename, i + 6);
strcpy (filename + i, ".info");
return (filename);
}
if (filename[0] == '.' || filename[0] == '/')
return (filename);
if (filename[0] != '/' && input_name[0] == '/')
{
char *result;
i = strlen (input_name) - 1;
result = (char *)xmalloc (1 + strlen (input_name) + strlen (filename));
strcpy (result, input_name);
while (result[i] != '/' && i)
i--;
if (result[i] == '/')
i++;
strcpy (&result[i], filename);
free (filename);
return (result);
}
return (filename);
}
char *
full_pathname (filename)
char *filename;
{
int initial_character;
char *result;
if (!filename || !(initial_character = *filename))
return (xstrdup (""));
if ((initial_character == '/') ||
((strncmp (filename, "./", 2) == 0) ||
(strncmp (filename, "../", 3) == 0)))
return (xstrdup (filename));
if (initial_character != '~')
{
char *localdir;
localdir = (char *)xmalloc (1025);
#if defined (HAVE_GETCWD)
if (!getcwd (localdir, 1024))
#else
if (!getwd (localdir))
#endif
{
fprintf (stderr, _("%s: getwd: %s, %s\n"),
progname, filename, localdir);
exit (1);
}
strcat (localdir, "/");
strcat (localdir, filename);
result = xstrdup (localdir);
free (localdir);
}
else
{
#ifndef WIN32
if (filename[1] == '/')
{
char *temp_home;
temp_home = (char *) getenv ("HOME");
result = (char *)xmalloc (strlen (&filename[1])
+ 1
+ temp_home ? strlen (temp_home)
: 0);
*result = 0;
if (temp_home)
strcpy (result, temp_home);
strcat (result, &filename[1]);
}
else
{
struct passwd *user_entry;
int i, c;
char *username = (char *)xmalloc (257);
for (i = 1; (c = filename[i]); i++)
{
if (c == '/')
break;
else
username[i - 1] = c;
}
if (c)
username[i - 1] = 0;
user_entry = getpwnam (username);
if (!user_entry)
return (xstrdup (filename));
result = (char *)xmalloc (1 + strlen (user_entry->pw_dir)
+ strlen (&filename[i]));
strcpy (result, user_entry->pw_dir);
strcat (result, &filename[i]);
}
}
#endif
return (result);
}
char *
output_name_from_input_name (name)
char *name;
{
return (expand_filename ((char *)NULL, name));
}
char *
read_token ()
{
int i, character;
char *result;
character = curchar ();
if (self_delimiting (character))
{
input_text_offset++;
if (character == '\n')
line_number++;
result = xstrdup (" ");
*result = character;
return (result);
}
for (i = 0; ((input_text_offset != size_of_input_text)
&& (character = curchar ())
&& command_char (character));
i++, input_text_offset++);
result = (char *)xmalloc (i + 1);
memcpy (result, &input_text[input_text_offset - i], i);
result[i] = 0;
return (result);
}
int
self_delimiting (character)
int character;
{
return member (character, "~{|}`^\\@?=;:.-,*\'\" !\n\t");
}
void
canon_white (string)
char *string;
{
int len = strlen (string);
int x;
if (!len)
return;
for (x = 0; x < len; x++)
{
if (!cr_or_whitespace (string[x]))
{
strcpy (string, string + x);
break;
}
}
len = strlen (string);
if (len)
len--;
while (len > -1 && cr_or_whitespace (string[len]))
len--;
string[len + 1] = 0;
}
void
fix_whitespace (string)
char *string;
{
char *temp = (char *)xmalloc (strlen (string) + 1);
int string_index = 0;
int temp_index = 0;
int c;
canon_white (string);
while (string[string_index])
{
c = temp[temp_index++] = string[string_index++];
if (c == ' ' || c == '\n' || c == '\t')
{
temp[temp_index - 1] = ' ';
while ((c = string[string_index]) && (c == ' ' ||
c == '\t' ||
c == '\n'))
string_index++;
}
}
temp[temp_index] = 0;
strcpy (string, temp);
free (temp);
}
void
discard_until (string)
char *string;
{
int temp = search_forward (string, input_text_offset);
int tt = (temp < 0) ? size_of_input_text : temp + strlen (string);
int from = input_text_offset;
while (from != tt)
if (input_text[from++] == '\n')
line_number++;
if (temp < 0)
{
input_text_offset = size_of_input_text - strlen (string);
if (strcmp (string, "\n") != 0)
{
line_error (_("Expected `%s'"), string);
return;
}
}
else
input_text_offset = temp;
input_text_offset += strlen (string);
}
int
get_until (match, string)
char *match, **string;
{
int len, current_point, x, new_point, tem;
current_point = x = input_text_offset;
new_point = search_forward (match, input_text_offset);
if (new_point < 0)
new_point = size_of_input_text;
len = new_point - current_point;
tem = new_point + (strlen (match) - 1);
while (x != tem)
if (input_text[x++] == '\n')
line_number++;
*string = (char *)xmalloc (len + 1);
memcpy (*string, &input_text[current_point], len);
(*string)[len] = 0;
input_text_offset = tem;
if (input_text_offset > size_of_input_text)
input_text_offset = size_of_input_text;
return (new_point);
}
void
get_until_in_line (expand, match, string)
int expand;
char *match, **string;
{
int real_bottom = size_of_input_text;
int limit = search_forward ("\n", input_text_offset);
if (limit < 0)
limit = size_of_input_text;
if (expand && !executing_string && !me_executing_string)
{
char *xp;
unsigned xp_len, new_len;
unsigned raw_len = limit - input_text_offset;
char *str = xmalloc (raw_len + 1);
strncpy (str, input_text + input_text_offset, raw_len);
str[raw_len] = 0;
xp = expansion (str, 0);
xp_len = strlen (xp);
free (str);
str = xmalloc (real_bottom - limit + 1);
strncpy (str, input_text + limit, real_bottom - limit + 1);
new_len = input_text_offset + xp_len + real_bottom - limit + 1;
input_text = xrealloc (input_text, new_len);
strcpy (input_text + input_text_offset, xp);
strncpy (input_text + input_text_offset + xp_len, str,
real_bottom - limit + 1);
free (str);
free (xp);
limit += xp_len - raw_len;
real_bottom += xp_len - raw_len;
}
size_of_input_text = limit;
get_until (match, string);
size_of_input_text = real_bottom;
}
void
get_rest_of_line (string)
char **string;
{
get_until ("\n", string);
canon_white (*string);
if (curchar () == '\n')
{
line_number++;
input_text_offset++;
}
}
void
backup_input_pointer ()
{
if (input_text_offset)
{
input_text_offset--;
if (curchar () == '\n')
line_number--;
}
}
void
get_until_in_braces (match, string)
char *match, **string;
{
char *temp;
int i, brace = 0;
int match_len = strlen (match);
for (i = input_text_offset; i < size_of_input_text; i++)
{
if (input_text[i] == '{')
brace++;
else if (input_text[i] == '}')
brace--;
else if (input_text[i] == '\n')
line_number++;
if (brace < 0 ||
(brace == 0 && strncmp (input_text + i, match, match_len) == 0))
break;
}
match_len = i - input_text_offset;
temp = (char *)xmalloc (2 + match_len);
strncpy (temp, input_text + input_text_offset, match_len);
temp[match_len] = 0;
input_text_offset = i;
*string = temp;
}
static char *suffixes[] = {
".texinfo",
".texi",
".txinfo",
"",
(char *)NULL
};
void
initialize_conversion ()
{
init_tag_table ();
init_indices ();
init_internals ();
init_paragraph ();
output_position = 0;
}
#define READ_BUFFER_GROWTH (4 * 4096)
void
convert_from_stream (stream, name)
FILE *stream;
char *name;
{
char *buffer = (char *)NULL;
int buffer_offset = 0, buffer_size = 0;
initialize_conversion ();
while (!feof (stream))
{
int count;
if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size)
buffer = (char *)
xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH));
count = fread (buffer + buffer_offset, 1, READ_BUFFER_GROWTH, stream);
if (count < 0)
{
perror (name);
exit (FATAL);
}
buffer_offset += count;
if (count == 0)
break;
}
input_text = buffer;
size_of_input_text = buffer_offset;
input_filename = xstrdup (name);
node_filename = xstrdup (name);
input_text_offset = 0;
line_number = 1;
input_text[size_of_input_text] = '\n';
convert_from_loaded_file (name);
}
void
convert_from_file (name)
char *name;
{
register int i;
char *filename = (char *)xmalloc (strlen (name) + 50);
initialize_conversion ();
for (i = 0; suffixes[i]; i++)
{
strcpy (filename, name);
strcat (filename, suffixes[i]);
if (find_and_load (filename))
break;
if (!suffixes[i][0] && strrchr (filename, '.'))
{
fs_error (filename);
free (filename);
return;
}
}
if (!suffixes[i])
{
fs_error (name);
free (filename);
return;
}
input_filename = filename;
convert_from_loaded_file (name);
}
void
convert_from_loaded_file (name)
char *name;
{
char *expand_filename (), *filename_part ();
char *real_output_filename = (char *)NULL;
#if defined (HAVE_MACROS)
remember_itext (input_text, 0);
#endif
input_text_offset = 0;
while (input_text_offset >= 0)
{
input_text_offset =
search_forward (setfilename_search, input_text_offset);
if ((input_text_offset == 0) ||
((input_text_offset > 0) &&
(input_text[input_text_offset -1] == '\n')))
break;
else if (input_text_offset > 0)
input_text_offset++;
}
if (input_text_offset < 0)
{
if (!command_output_filename)
{
#if defined (REQUIRE_SETFILENAME)
error (_("No `%s' found in `%s'"), setfilename_search, name);
goto finished;
#else
register int i, end_of_first_line;
for (i = 0; i < size_of_input_text - 1; i++)
if (input_text[i] == '\n')
break;
end_of_first_line = i + 1;
input_text_offset = 0;
for (i = 0; i < end_of_first_line; i++)
{
if ((input_text[i] == '\\') &&
(strncmp (input_text + i + 1, "include", 7) == 0))
{
input_text_offset = end_of_first_line;
break;
}
}
command_output_filename = output_name_from_input_name (name);
#endif
}
}
else
input_text_offset += strlen (setfilename_search);
if (!command_output_filename)
get_until ("\n", &output_filename);
else
{
if (input_text_offset != -1)
discard_until ("\n");
else
input_text_offset = 0;
real_output_filename = output_filename = command_output_filename;
command_output_filename = (char *)NULL;
}
canon_white (output_filename);
if (real_output_filename && strcmp (real_output_filename, "-") == 0)
{
if (macro_expansion_filename
&& strcmp (macro_expansion_filename, "-") == 0)
{
fprintf (stderr, _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
progname);
macro_expansion_output_stream = NULL;
}
real_output_filename = xstrdup (real_output_filename);
output_stream = stdout;
splitting = 0;
}
else
{
if (!real_output_filename)
real_output_filename = expand_filename (output_filename, name);
else
real_output_filename = xstrdup (real_output_filename);
output_stream = fopen (real_output_filename, "w");
}
if (output_stream != stdout)
printf (_("Making %s file `%s' from `%s'.\n"),
no_headers ? "text" : "info", output_filename, input_filename);
if (output_stream == NULL)
{
fs_error (real_output_filename);
goto finished;
}
if (output_stream != stdout)
pretty_output_filename = filename_part (output_filename);
else
pretty_output_filename = xstrdup ("stdout");
{
int temp = 0;
line_number = 1;
while (temp != input_text_offset)
if (input_text[temp++] == '\n')
line_number++;
}
if (!no_headers)
{
add_word_args (_("This is Info file %s, produced by Makeinfo version %d.%d"),
output_filename, major_version, minor_version);
add_word_args (_(" from the input file %s.\n"), input_filename);
}
close_paragraph ();
reader_loop ();
finished:
discard_insertions (0);
close_paragraph ();
flush_file_stack ();
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream)
{
fclose (macro_expansion_output_stream);
if (errors_printed && !force
&& strcmp (macro_expansion_filename, "-") != 0
&& strcmp (macro_expansion_filename, "/dev/null") != 0)
{
fprintf (stderr, _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n"),
progname, macro_expansion_filename);
if (unlink (macro_expansion_filename) < 0)
perror (macro_expansion_filename);
}
}
#endif
if (output_stream)
{
output_pending_notes ();
free_pending_notes ();
if (tag_table != NULL)
{
tag_table = (TAG_ENTRY *) reverse_list (tag_table);
if (!no_headers)
write_tag_table ();
}
if (output_stream != stdout)
fclose (output_stream);
if (validating)
validate_file (tag_table);
if (splitting && (!errors_printed || force))
split_file (real_output_filename, 0);
else if (errors_printed && !force
&& strcmp (real_output_filename, "-") != 0
&& strcmp (real_output_filename, "/dev/null") != 0)
{
fprintf (stderr, _("%s: Removing output file `%s' due to errors; use --force to preserve.\n"),
progname, real_output_filename);
if (unlink (real_output_filename) < 0)
perror (real_output_filename);
}
}
free (real_output_filename);
}
void
free_and_clear (pointer)
char **pointer;
{
if (*pointer)
{
free (*pointer);
*pointer = (char *) NULL;
}
}
void
init_internals ()
{
free_and_clear (&output_filename);
free_and_clear (&command);
free_and_clear (&input_filename);
free_node_references ();
init_insertion_stack ();
init_brace_stack ();
current_node = NULL;
command_index = 0;
in_menu = 0;
in_detailmenu = 0;
top_node_seen = 0;
non_top_node_seen = 0;
}
void
init_paragraph ()
{
free_and_clear (&output_paragraph);
output_paragraph = (unsigned char *)xmalloc (paragraph_buffer_len);
output_paragraph[0] = 0;
output_paragraph_offset = 0;
output_column = 0;
paragraph_is_open = 0;
current_indent = 0;
}
void
reader_loop ()
{
int character;
int done = 0;
int dash_count = 0;
while (!done)
{
if (input_text_offset >= size_of_input_text)
break;
character = curchar ();
if (!in_fixed_width_font &&
(character == '\'' || character == '`') &&
input_text[input_text_offset + 1] == character)
{
input_text_offset++;
character = '"';
}
if (character == '-')
{
dash_count++;
if (dash_count == 2 && !in_fixed_width_font)
{
input_text_offset++;
continue;
}
}
else
{
dash_count = 0;
}
if (whitespace (character))
{
register int i = input_text_offset + 1;
while (i < size_of_input_text && whitespace (input_text[i]))
i++;
if (i == size_of_input_text || input_text[i] == '\n')
{
if (i == size_of_input_text)
i--;
input_text_offset = i;
character = curchar ();
}
}
if (character == '\n')
{
line_number++;
if (in_menu && input_text_offset + 1 < size_of_input_text)
{
char *glean_node_from_menu (), *tem;
if (!in_detailmenu)
tem = glean_node_from_menu (1);
}
}
switch (character)
{
case COMMAND_PREFIX:
read_command ();
break;
case '{':
line_error (_("Misplaced %c"), '{');
remember_brace (misplaced_brace);
break;
case '}':
pop_and_call_brace ();
input_text_offset++;
break;
default:
add_char (character);
input_text_offset++;
}
}
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream)
maybe_write_itext (input_text, input_text_offset);
#endif
}
COMMAND *
get_command_entry (string)
char *string;
{
register int i;
for (i = 0; command_table[i].name; i++)
if (strcmp (command_table[i].name, string) == 0)
return (&command_table[i]);
for (i = 0; i < user_command_array_len; i++)
if (user_command_array[i] &&
(strcmp (user_command_array[i]->name, string) == 0))
return (user_command_array[i]);
return ((COMMAND *) -1);
}
void
read_command ()
{
COMMAND *entry;
input_text_offset++;
free_and_clear (&command);
command = read_token ();
#if defined (HAVE_MACROS)
{
MACRO_DEF *def;
def = find_macro (command);
if (def)
{
if (!(def->flags & ME_RECURSE))
def->inhibited = 1;
execute_macro (def);
if (!(def->flags & ME_RECURSE))
def->inhibited = 0;
return;
}
}
#endif
entry = get_command_entry (command);
if (entry == (COMMAND *)-1)
{
line_error (_("Unknown command `%s'"), command);
return;
}
if (entry->argument_in_braces)
remember_brace (entry->proc);
(*(entry->proc)) (START, output_paragraph_offset, 0);
}
char *
find_proc_name (proc)
COMMAND_FUNCTION *proc;
{
register int i;
for (i = 0; command_table[i].name; i++)
if (proc == command_table[i].proc)
return command_table[i].name;
return _("NO_NAME!");
}
void
init_brace_stack ()
{
brace_stack = (BRACE_ELEMENT *) NULL;
}
void
remember_brace (proc)
COMMAND_FUNCTION *proc;
{
if (curchar () != '{')
line_error (_("%c%s expected `{...}'"), COMMAND_PREFIX, command);
else
input_text_offset++;
remember_brace_1 (proc, output_paragraph_offset);
}
void
remember_brace_1 (proc, position)
COMMAND_FUNCTION *proc;
int position;
{
BRACE_ELEMENT *new = (BRACE_ELEMENT *) xmalloc (sizeof (BRACE_ELEMENT));
new->next = brace_stack;
new->proc = proc;
new->pos = position;
new->line = line_number;
new->in_fixed_width_font = in_fixed_width_font;
brace_stack = new;
}
void
pop_and_call_brace ()
{
BRACE_ELEMENT *temp;
COMMAND_FUNCTION *proc;
int pos;
if (brace_stack == (BRACE_ELEMENT *) NULL)
{
line_error (_("Unmatched }"));
return;
}
pos = brace_stack->pos;
proc = brace_stack->proc;
in_fixed_width_font = brace_stack->in_fixed_width_font;
temp = brace_stack->next;
free (brace_stack);
brace_stack = temp;
(*proc) (END, pos, output_paragraph_offset);
}
void
adjust_braces_following (here, amount)
int here, amount;
{
register BRACE_ELEMENT *stack = brace_stack;
while (stack)
{
if (stack->pos >= here)
stack->pos += amount;
stack = stack->next;
}
}
void
discard_braces ()
{
if (!brace_stack)
return;
while (brace_stack)
{
if (brace_stack->proc != misplaced_brace)
{
char *proc_name;
int temp_line_number = line_number;
line_number = brace_stack->line;
proc_name = find_proc_name (brace_stack->proc);
line_error (_("%c%s missing close brace"), COMMAND_PREFIX, proc_name);
line_number = temp_line_number;
pop_and_call_brace ();
}
else
{
BRACE_ELEMENT *temp;
temp = brace_stack->next;
free (brace_stack);
brace_stack = temp;
}
}
}
int
get_char_len (character)
int character;
{
int len;
switch (character)
{
case '\t':
len = (output_column + 8) & 0xf7;
if (len > fill_column)
len = fill_column - output_column;
else
len = len - output_column;
break;
case '\n':
len = fill_column - output_column;
break;
default:
if (0 <= character && character < ' ')
len = 2;
else
len = 1;
}
return (len);
}
void
#if defined (VA_FPRINTF) && __STDC__
add_word_args (char *format, ...)
#else
add_word_args (format, va_alist)
char *format;
va_dcl
#endif
{
char buffer[1000];
#ifdef VA_FPRINTF
va_list ap;
#endif
VA_START (ap, format);
#ifdef VA_SPRINTF
VA_SPRINTF (buffer, format, ap);
#else
sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
#endif
va_end (ap);
add_word (buffer);
}
void
add_word (string)
char *string;
{
while (*string)
add_char (*string++);
}
int last_char_was_newline = 1;
int last_inserted_character = 0;
int line_already_broken = 0;
int insertion_paragraph_closed = 0;
int do_justification = 0;
void
add_char (character)
int character;
{
if (no_headers && (in_menu || in_detailmenu))
return;
if (must_start_paragraph && character != '\n')
{
must_start_paragraph = 0;
line_already_broken = 0;
if (current_indent > output_column)
{
indent (current_indent - output_column);
output_column = current_indent;
}
}
if (non_splitting_words && member (character, " \t\n"))
character = ' ' | 0x80;
insertion_paragraph_closed = 0;
switch (character)
{
case '\n':
if (!filling_enabled)
{
insert ('\n');
if (force_flush_right)
{
close_paragraph ();
flush_output ();
}
output_column = 0;
if (!no_indent && paragraph_is_open)
indent (output_column = current_indent);
break;
}
else
{
if (end_of_sentence_p ())
{
insert (' ');
output_column++;
last_inserted_character = character;
}
}
if (last_char_was_newline)
{
close_paragraph ();
pending_indent = 0;
}
else
{
last_char_was_newline = 1;
insert (' ');
output_column++;
}
break;
default:
{
int len = get_char_len (character);
int suppress_insert = 0;
if ((character == ' ') && (last_char_was_newline))
{
if (!paragraph_is_open)
{
pending_indent++;
return;
}
}
if (!paragraph_is_open)
{
start_paragraph ();
if (!paragraph_start_indent)
indent (pending_indent);
pending_indent = 0;
}
if ((output_column += len) > fill_column)
{
if (filling_enabled)
{
int temp = output_paragraph_offset;
while (--temp > 0 && output_paragraph[temp] != '\n')
{
if (output_paragraph[temp] == ' ')
{
while (temp && whitespace (output_paragraph[temp - 1]))
temp--;
output_paragraph[temp++] = '\n';
{
int t1 = temp;
for (;; t1++)
{
if (t1 == output_paragraph_offset)
{
if (whitespace (character))
suppress_insert = 1;
break;
}
if (!whitespace (output_paragraph[t1]))
break;
}
if (t1 != temp)
{
adjust_braces_following (temp, (- (t1 - temp)));
strncpy ((char *) &output_paragraph[temp],
(char *) &output_paragraph[t1],
(output_paragraph_offset - t1));
output_paragraph_offset -= (t1 - temp);
}
}
if (indented_fill && current_indent)
{
int buffer_len = ((output_paragraph_offset - temp)
+ current_indent);
char *temp_buffer = (char *)xmalloc (buffer_len);
int indentation = 0;
adjust_braces_following (temp, current_indent);
while (current_indent > 0 &&
indentation != current_indent)
temp_buffer[indentation++] = ' ';
strncpy ((char *) &temp_buffer[current_indent],
(char *) &output_paragraph[temp],
buffer_len - current_indent);
if (output_paragraph_offset + buffer_len
>= paragraph_buffer_len)
{
unsigned char *tt = xrealloc
(output_paragraph,
(paragraph_buffer_len += buffer_len));
output_paragraph = tt;
}
strncpy ((char *) &output_paragraph[temp],
temp_buffer, buffer_len);
output_paragraph_offset += current_indent;
free (temp_buffer);
}
output_column = 0;
while (temp < output_paragraph_offset)
output_column +=
get_char_len (output_paragraph[temp++]);
output_column += len;
break;
}
}
}
}
if (!suppress_insert)
{
insert (character);
last_inserted_character = character;
}
last_char_was_newline = 0;
line_already_broken = 0;
}
}
}
void
insert (character)
int character;
{
output_paragraph[output_paragraph_offset++] = character;
if (output_paragraph_offset == paragraph_buffer_len)
{
output_paragraph =
xrealloc (output_paragraph, (paragraph_buffer_len += 100));
}
}
void
insert_string (string)
char *string;
{
while (*string)
insert (*string++);
}
#define post_sentence(c) ((c) == ')' || (c) == '\'' || (c) == '"' \
|| (c) == ']')
static int
end_of_sentence_p ()
{
int loc = output_paragraph_offset - 1;
while (loc > 0 && post_sentence (output_paragraph[loc]))
loc--;
return sentence_ender (output_paragraph[loc]);
}
void
kill_self_indent (count)
int count;
{
if (count < 0)
{
output_column = 0;
while (output_paragraph_offset)
{
if (whitespace (output_paragraph[output_paragraph_offset - 1]))
output_paragraph_offset--;
else
break;
}
}
else
{
while (output_paragraph_offset && count--)
if (whitespace (output_paragraph[output_paragraph_offset - 1]))
output_paragraph_offset--;
else
break;
}
}
static int flushing_ignored = 0;
void
inhibit_output_flushing ()
{
flushing_ignored++;
}
void
uninhibit_output_flushing ()
{
flushing_ignored--;
}
void
flush_output ()
{
register int i;
if (!output_paragraph_offset || flushing_ignored)
return;
for (i = 0; i < output_paragraph_offset; i++)
{
if (output_paragraph[i] & meta_character_bit)
{
int temp = UNMETA (output_paragraph[i]);
if (temp == ' ')
output_paragraph[i] &= 0x7f;
}
}
fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
output_position += output_paragraph_offset;
output_paragraph_offset = 0;
}
int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING;
void
close_single_paragraph ()
{
close_paragraph_with_lines (0);
}
void
close_insertion_paragraph ()
{
if (!insertion_paragraph_closed)
{
close_single_paragraph ();
start_paragraph ();
line_already_broken = 1;
ignore_blank_line ();
}
else
{
if (current_indent < output_column)
kill_self_indent (output_column - current_indent);
}
insertion_paragraph_closed = 1;
}
void
close_paragraph_with_lines (lines)
int lines;
{
int old_spacing = paragraph_spacing;
paragraph_spacing = lines;
close_paragraph ();
paragraph_spacing = old_spacing;
}
void
close_paragraph ()
{
register int i;
insertion_paragraph_closed = 0;
if (paragraph_is_open && !must_start_paragraph)
{
register int tindex, c;
tindex = output_paragraph_offset;
for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex)
{
c = output_paragraph[tindex];
if (c == ' '|| c == '\n')
output_paragraph[tindex] = '\n';
else
break;
}
output_paragraph_offset = ++tindex;
if (paragraph_spacing >= 0)
insert ('\n');
if (!force_flush_right)
{
for (i = 0; i < (paragraph_spacing - line_already_broken); i++)
insert ('\n');
}
if (force_flush_right)
do_flush_right_indentation ();
flush_output ();
paragraph_is_open = 0;
no_indent = 0;
output_column = 0;
}
ignore_blank_line ();
}
void
ignore_blank_line ()
{
last_inserted_character = '\n';
last_char_was_newline = 1;
}
void
do_flush_right_indentation ()
{
char *temp;
int temp_len;
kill_self_indent (-1);
if (output_paragraph[0] != '\n')
{
output_paragraph[output_paragraph_offset] = 0;
if (output_paragraph_offset < fill_column)
{
register int i;
if (fill_column >= paragraph_buffer_len)
output_paragraph =
xrealloc (output_paragraph,
(paragraph_buffer_len += fill_column));
temp_len = strlen ((char *)output_paragraph);
temp = (char *)xmalloc (temp_len + 1);
memcpy (temp, (char *)output_paragraph, temp_len);
for (i = 0; i < fill_column - output_paragraph_offset; i++)
output_paragraph[i] = ' ';
memcpy ((char *)output_paragraph + i, temp, temp_len);
free (temp);
output_paragraph_offset = fill_column;
}
}
}
void
start_paragraph ()
{
if (paragraph_is_open)
close_paragraph ();
insertion_paragraph_closed = 0;
paragraph_is_open = 1;
if (!must_start_paragraph)
{
int amount_to_indent = 0;
if (!no_indent)
{
if (inhibit_paragraph_indentation)
{
amount_to_indent = current_indent;
if (inhibit_paragraph_indentation < 0)
inhibit_paragraph_indentation++;
}
else if (paragraph_start_indent < 0)
amount_to_indent = current_indent;
else
amount_to_indent = current_indent + paragraph_start_indent;
if (amount_to_indent >= output_column)
{
amount_to_indent -= output_column;
indent (amount_to_indent);
output_column += amount_to_indent;
}
}
}
else
must_start_paragraph = 0;
}
void
indent (amount)
int amount;
{
register BRACE_ELEMENT *elt = brace_stack;
while (elt)
{
if (elt->pos >= output_paragraph_offset)
elt->pos += amount;
elt = elt->next;
}
while (--amount >= 0)
insert (' ');
}
int
search_forward (string, from)
char *string;
int from;
{
int len = strlen (string);
while (from < size_of_input_text)
{
if (strncmp (input_text + from, string, len) == 0)
return (from);
from++;
}
return (-1);
}
#if !defined (HAVE_STRCASECMP)
int
strcasecmp (string1, string2)
char *string1, *string2;
{
char ch1, ch2;
for (;;)
{
ch1 = *string1++;
ch2 = *string2++;
if (!(ch1 | ch2))
return (0);
ch1 = coerce_to_upper (ch1);
ch2 = coerce_to_upper (ch2);
if (ch1 != ch2)
return (ch1 - ch2);
}
}
#endif
void
init_insertion_stack ()
{
insertion_stack = (INSERTION_ELT *) NULL;
}
enum insertion_type
current_insertion_type ()
{
if (!insertion_level)
return (bad_type);
else
return (insertion_stack->insertion);
}
char *
current_item_function ()
{
register int level, done;
register INSERTION_ELT *elt;
level = insertion_level;
elt = insertion_stack;
done = 0;
while (!done && (elt != NULL))
{
switch (elt->insertion)
{
case ifinfo:
case ifnothtml:
case ifnottex:
case ifset:
case ifclear:
case cartouche:
elt = elt->next;
level--;
break;
default:
done = 1;
}
}
if (!level)
return ((char *) NULL);
else
return (elt->item_function);
}
char *
get_item_function ()
{
char *item_function;
get_rest_of_line (&item_function);
backup_input_pointer ();
return (item_function);
}
void
push_insertion (type, item_function)
enum insertion_type type;
char *item_function;
{
INSERTION_ELT *new = (INSERTION_ELT *) xmalloc (sizeof (INSERTION_ELT));
new->item_function = item_function;
new->filling_enabled = filling_enabled;
new->indented_fill = indented_fill;
new->insertion = type;
new->line_number = line_number;
new->filename = xstrdup (input_filename);
new->inhibited = inhibit_paragraph_indentation;
new->in_fixed_width_font = in_fixed_width_font;
new->next = insertion_stack;
insertion_stack = new;
insertion_level++;
}
void
pop_insertion ()
{
INSERTION_ELT *temp = insertion_stack;
if (temp == (INSERTION_ELT *) NULL)
return;
in_fixed_width_font = temp->in_fixed_width_font;
inhibit_paragraph_indentation = temp->inhibited;
filling_enabled = temp->filling_enabled;
indented_fill = temp->indented_fill;
free_and_clear (&(temp->item_function));
free_and_clear (&(temp->filename));
insertion_stack = insertion_stack->next;
free (temp);
insertion_level--;
}
char *
insertion_type_pname (type)
enum insertion_type type;
{
if ((int) type < (int) bad_type)
return (insertion_type_names[(int) type]);
else
return (_("Broken-Type in insertion_type_pname"));
}
enum insertion_type
find_type_from_name (name)
char *name;
{
int index = 0;
while (index < (int) bad_type)
{
if (strcmp (name, insertion_type_names[index]) == 0)
return (enum insertion_type) index;
index++;
}
return (bad_type);
}
int
defun_insertion (type)
enum insertion_type type;
{
return
((type == deffn)
|| (type == defun)
|| (type == defmac)
|| (type == defspec)
|| (type == defvr)
|| (type == defvar)
|| (type == defopt)
|| (type == deftypefn)
|| (type == deftypefun)
|| (type == deftypevr)
|| (type == deftypevar)
|| (type == defcv)
|| (type == defivar)
|| (type == defop)
|| (type == defmethod)
|| (type == deftypemethod)
|| (type == deftp));
}
#define max_stack_depth 100
#define ENUM_DIGITS 1
#define ENUM_ALPHA 2
typedef struct {
int enumtype;
int enumval;
} DIGIT_ALPHA;
DIGIT_ALPHA enumstack[max_stack_depth];
int enumstack_offset = 0;
int current_enumval = 1;
int current_enumtype = ENUM_DIGITS;
char *enumeration_arg = (char *)NULL;
void
start_enumerating (at, type)
int at, type;
{
if ((enumstack_offset + 1) == max_stack_depth)
{
line_error (_("Enumeration stack overflow"));
return;
}
enumstack[enumstack_offset].enumtype = current_enumtype;
enumstack[enumstack_offset].enumval = current_enumval;
enumstack_offset++;
current_enumval = at;
current_enumtype = type;
}
void
stop_enumerating ()
{
--enumstack_offset;
if (enumstack_offset < 0)
enumstack_offset = 0;
current_enumval = enumstack[enumstack_offset].enumval;
current_enumtype = enumstack[enumstack_offset].enumtype;
}
void
enumerate_item ()
{
char temp[10];
if (current_enumtype == ENUM_ALPHA)
{
if (current_enumval == ('z' + 1) || current_enumval == ('Z' + 1))
{
current_enumval = ((current_enumval - 1) == 'z' ? 'a' : 'A');
warning (_("lettering overflow, restarting at %c"), current_enumval);
}
sprintf (temp, "%c. ", current_enumval);
}
else
sprintf (temp, "%d. ", current_enumval);
indent (output_column += (current_indent - strlen (temp)));
add_word (temp);
current_enumval++;
}
void
begin_insertion (type)
enum insertion_type type;
{
int no_discard = 0;
if (defun_insertion (type))
{
push_insertion (type, xstrdup (""));
no_discard++;
}
else
push_insertion (type, get_item_function ());
switch (type)
{
case menu:
if (!no_headers)
close_paragraph ();
filling_enabled = no_indent = 0;
inhibit_paragraph_indentation = 1;
if (!no_headers)
add_word (_("* Menu:\n"));
in_menu++;
no_discard++;
break;
case detailmenu:
if (!in_menu)
{
if (!no_headers)
close_paragraph ();
filling_enabled = no_indent = 0;
inhibit_paragraph_indentation = 1;
no_discard++;
}
in_detailmenu++;
break;
case direntry:
close_single_paragraph ();
filling_enabled = no_indent = 0;
inhibit_paragraph_indentation = 1;
insert_string ("START-INFO-DIR-ENTRY\n");
break;
case quotation:
close_single_paragraph ();
last_char_was_newline = no_indent = 0;
indented_fill = filling_enabled = 1;
inhibit_paragraph_indentation = 1;
current_indent += default_indentation_increment;
break;
case display:
case example:
case smallexample:
case lisp:
case smalllisp:
case format:
close_single_paragraph ();
inhibit_paragraph_indentation = 1;
in_fixed_width_font++;
filling_enabled = 0;
last_char_was_newline = 0;
if (type != format)
current_indent += default_indentation_increment;
break;
case multitable:
do_multitable ();
break;
case table:
case ftable:
case vtable:
case itemize:
close_single_paragraph ();
current_indent += default_indentation_increment;
filling_enabled = indented_fill = 1;
#if defined (INDENT_PARAGRAPHS_IN_TABLE)
inhibit_paragraph_indentation = 0;
#else
inhibit_paragraph_indentation = 1;
#endif
if (allow_lax_format && (type == itemize))
{
if (!(*insertion_stack->item_function))
{
free (insertion_stack->item_function);
insertion_stack->item_function = xstrdup ("@bullet");
insertion_stack->item_function[0] = COMMAND_PREFIX;
}
}
if (!*insertion_stack->item_function)
{
line_error (_("%s requires an argument: the formatter for %citem"),
insertion_type_pname (type), COMMAND_PREFIX);
}
break;
case enumerate:
close_single_paragraph ();
no_indent = 0;
#if defined (INDENT_PARAGRAPHS_IN_TABLE)
inhibit_paragraph_indentation = 0;
#else
inhibit_paragraph_indentation = 1;
#endif
current_indent += default_indentation_increment;
filling_enabled = indented_fill = 1;
if (isdigit (*enumeration_arg))
start_enumerating (atoi (enumeration_arg), ENUM_DIGITS);
else
start_enumerating (*enumeration_arg, ENUM_ALPHA);
break;
case group:
if (!insertion_stack->next ||
insertion_stack->next->insertion != example)
close_single_paragraph ();
break;
case ifinfo:
case ifnothtml:
case ifnottex:
case ifset:
case ifclear:
case cartouche:
if (in_menu)
no_discard++;
break;
case deffn:
case defun:
case defmac:
case defspec:
case defvr:
case defvar:
case defopt:
case deftypefn:
case deftypefun:
case deftypevr:
case deftypevar:
case defcv:
case defivar:
case defop:
case defmethod:
case deftypemethod:
case deftp:
inhibit_paragraph_indentation = 1;
filling_enabled = indented_fill = 1;
current_indent += default_indentation_increment;
no_indent = 0;
break;
case flushleft:
close_single_paragraph ();
inhibit_paragraph_indentation = 1;
filling_enabled = indented_fill = no_indent = 0;
break;
case flushright:
close_single_paragraph ();
filling_enabled = indented_fill = no_indent = 0;
inhibit_paragraph_indentation = 1;
force_flush_right++;
break;
}
if (!no_discard)
discard_until ("\n");
}
void
end_insertion (type)
enum insertion_type type;
{
enum insertion_type temp_type;
if (!insertion_level)
return;
temp_type = current_insertion_type ();
if (type == bad_type)
type = temp_type;
if (type != temp_type)
{
line_error
(_("`%cend' expected `%s', but saw `%s'"), COMMAND_PREFIX,
insertion_type_pname (temp_type), insertion_type_pname (type));
return;
}
pop_insertion ();
switch (type)
{
case ifnothtml:
case ifnottex:
case ifinfo:
case ifset:
case ifclear:
break;
case direntry:
insert_string ("END-INFO-DIR-ENTRY\n\n");
close_insertion_paragraph ();
break;
case detailmenu:
in_detailmenu--;
if (!in_menu)
{
if (!no_headers)
close_insertion_paragraph ();
}
break;
case menu:
in_menu--;
if (!no_headers)
close_insertion_paragraph ();
break;
case multitable:
end_multitable ();
break;
case enumerate:
stop_enumerating ();
close_insertion_paragraph ();
current_indent -= default_indentation_increment;
break;
case flushleft:
case group:
case cartouche:
close_insertion_paragraph ();
break;
case format:
case display:
case example:
case smallexample:
case lisp:
case smalllisp:
case quotation:
if (type != format)
current_indent -= default_indentation_increment;
close_insertion_paragraph ();
break;
case table:
case ftable:
case vtable:
case itemize:
current_indent -= default_indentation_increment;
break;
case flushright:
force_flush_right--;
close_insertion_paragraph ();
break;
default:
current_indent -= default_indentation_increment;
close_insertion_paragraph ();
break;
}
}
void
discard_insertions (specials_ok)
int specials_ok;
{
int real_line_number = line_number;
while (insertion_stack)
{
if (specials_ok && (insertion_stack->insertion == ifinfo
|| insertion_stack->insertion == ifset
|| insertion_stack->insertion == ifclear))
break;
else
{
char *offender = insertion_type_pname (insertion_stack->insertion);
char *current_filename = input_filename;
input_filename = insertion_stack->filename;
line_number = insertion_stack->line_number;
line_error (_("No matching `%cend %s'"), COMMAND_PREFIX, offender);
input_filename = current_filename;
pop_insertion ();
}
}
line_number = real_line_number;
}
void
insert_self (arg)
int arg;
{
if (arg == START)
add_word (command);
}
void
insert_space (arg)
int arg;
{
if (arg == START)
add_char (' ');
}
void
cm_asterisk ()
{
close_single_paragraph ();
cm_noindent ();
}
void
cm_dots (arg)
int arg;
{
if (arg == START)
add_word ("...");
}
void
cm_enddots (arg)
int arg;
{
if (arg == START)
add_word ("....");
}
void
cm_bullet (arg)
int arg;
{
if (arg == START)
add_char ('*');
}
void
cm_minus (arg)
int arg;
{
if (arg == START)
add_char ('-');
}
void
cm_TeX (arg)
int arg;
{
if (arg == START)
add_word ("TeX");
}
void
cm_copyright (arg)
int arg;
{
if (arg == START)
add_word ("(C)");
}
void
cm_accent (arg)
int arg;
{
if (arg == START)
{
if (strcmp (command, "dotaccent") == 0)
add_char ('.');
else if (strcmp (command, "H") == 0)
add_word ("''");
else if (strcmp (command, "ringaccent") == 0)
add_char ('*');
else if (strcmp (command, "tieaccent") == 0)
add_char ('[');
else if (strcmp (command, "u") == 0)
add_char ('(');
else if (strcmp (command, "v") == 0)
add_char ('<');
}
else if (arg == END)
{
if (strcmp (command, "ubaraccent") == 0)
add_char ('_');
else if (strcmp (command, "udotaccent") == 0)
add_word ("-.");
else if (strcmp (command, ",") == 0)
add_word (",");
}
}
void
cm_special_char (arg)
{
if (arg == START)
{
if ((*command == 'L' || *command == 'l'
|| *command == 'O' || *command == 'o')
&& command[1] == 0)
{
add_char (*command);
add_char ('/');
}
else if (strcmp (command, "exclamdown") == 0)
add_char ('!');
else if (strcmp (command, "pounds") == 0)
add_char ('#');
else if (strcmp (command, "questiondown") == 0)
add_char ('?');
else
fprintf (stderr, _("How did @%s end up in cm_special_char?\n"), command);
}
}
void
cm_dotless (arg, start, end)
int arg, start, end;
{
if (arg == END)
{
if (output_paragraph[start] != 'i' && output_paragraph[start] != 'j')
line_error (_("%c%s expects `i' or `j' as argument, not `%c'"),
COMMAND_PREFIX, command, output_paragraph[start]);
else if (end - start != 1)
line_error (_("%c%s expects a single character `i' or `j' as argument"),
COMMAND_PREFIX, command);
}
}
void
cm_today (arg)
int arg;
{
static char *months [12] =
{ N_("January"), N_("February"), N_("March"), N_("April"), N_("May"),
N_("June"), N_("July"), N_("August"), N_("September"), N_("October"),
N_("November"), N_("December") };
if (arg == START)
{
time_t timer = time (0);
struct tm *ts = localtime (&timer);
add_word_args ("%d %s %d", ts->tm_mday, _(months[ts->tm_mon]),
ts->tm_year + 1900);
}
}
void
cm_code (arg)
int arg;
{
extern int printing_index;
if (arg == START)
{
in_fixed_width_font++;
if (!printing_index)
add_char ('`');
}
else
{
if (!printing_index)
add_char ('\'');
}
}
void
cm_kbd (arg)
int arg;
{
if (!in_fixed_width_font)
cm_code (arg);
}
void
cm_key (arg)
int arg;
{
add_char (arg == START ? '<' : '>');
}
void
cm_ctrl (arg, start, end)
int arg, start, end;
{
if (arg == END)
{
register int i, character;
#if defined (NO_MULTIPLE_CTRL)
if ((end - start) != 1)
line_error (_("%c%s expects a single character as an argument"),
COMMAND_PREFIX, command);
else
#endif
for (i = start; i < end; i++)
{
character = output_paragraph[i];
if (isletter (character))
output_paragraph[i] = CTL (coerce_to_upper (character));
}
}
}
void
not_fixed_width (arg)
int arg;
{
if (arg == START)
in_fixed_width_font = 0;
}
void
cm_var_sc (arg, start_pos, end_pos)
int arg, start_pos, end_pos;
{
not_fixed_width (arg);
if (arg == END)
{
while (start_pos < end_pos)
{
output_paragraph[start_pos] =
coerce_to_upper (output_paragraph[start_pos]);
start_pos++;
}
}
}
void
cm_dfn (arg, position)
int arg, position;
{
add_char ('"');
}
void
cm_emph (arg)
int arg;
{
add_char ('*');
}
void
cm_strong (arg, position)
int arg, position;
{
cm_emph (arg);
}
void
cm_cite (arg, position)
int arg, position;
{
if (arg == START)
add_word ("`");
else
add_word ("'");
}
void
cm_not_fixed_width (arg, start, end)
int arg, start, end;
{
not_fixed_width (arg);
}
void
cm_no_op ()
{
}
void
cm_no_op_line_arg ()
{
char *temp;
get_rest_of_line (&temp);
free (temp);
}
void
cm_w (arg, start, end)
int arg, start, end;
{
if (arg == START)
non_splitting_words++;
else
non_splitting_words--;
}
void
cm_obsolete (arg, start, end)
int arg, start, end;
{
if (arg == START)
warning (_("%c%s is obsolete"), COMMAND_PREFIX, command);
}
void
insert_and_underscore (with_char)
int with_char;
{
register int i, len;
int old_no_indent, starting_pos, ending_pos;
char *temp;
close_paragraph ();
filling_enabled = indented_fill = 0;
old_no_indent = no_indent;
no_indent = 1;
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream && !executing_string)
append_to_expansion_output (input_text_offset + 1);
#endif
get_rest_of_line (&temp);
starting_pos = output_position + output_paragraph_offset;
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream && !executing_string)
{
char *temp1 = (char *) xmalloc (2 + strlen (temp));
sprintf (temp1, "%s\n", temp);
remember_itext (input_text, input_text_offset);
me_execute_string (temp1);
free (temp1);
}
else
#endif
execute_string ("%s\n", temp);
ending_pos = output_position + output_paragraph_offset;
free (temp);
len = (ending_pos - starting_pos) - 1;
for (i = 0; i < len; i++)
add_char (with_char);
insert ('\n');
close_paragraph ();
filling_enabled = 1;
no_indent = old_no_indent;
}
struct {
char *name;
int level;
} section_alist[] = {
{ "unnumberedsubsubsec", 5 },
{ "unnumberedsubsec", 4 },
{ "unnumberedsec", 3 },
{ "unnumbered", 2 },
{ "appendixsubsubsec", 5 },
{ "appendixsubsec", 4 },
{ "appendixsec", 3 },
{ "appendixsection", 3 },
{ "appendix", 2 },
{ "subsubsec", 5 },
{ "subsubsection", 5 },
{ "subsection", 4 },
{ "section", 3 },
{ "chapter", 2 },
{ "top", 1 },
{ (char *)NULL, 0 }
};
int section_alist_offset = 0;
void
cm_raisesections ()
{
discard_until ("\n");
section_alist_offset--;
}
void
cm_lowersections ()
{
discard_until ("\n");
section_alist_offset++;
}
int
what_section (text)
char *text;
{
register int i, j;
char *t;
find_section_command:
for (j = 0; text[j] && cr_or_whitespace (text[j]); j++);
if (text[j] != COMMAND_PREFIX)
return (-1);
text = text + j + 1;
if ((strncmp (text, "comment", strlen ("comment")) == 0) ||
(text[0] == 'c' && cr_or_whitespace (text[1])) ||
(strcmp (text + 1, "index") == 0))
{
while (*text++ != '\n');
goto find_section_command;
}
if (*text == 'i')
text++;
for (j = 0; text[j] && !cr_or_whitespace (text[j]); j++);
for (i = 0; (t = section_alist[i].name); i++)
{
if (j == strlen (t) && strncmp (t, text, j) == 0)
{
int return_val;
return_val = (section_alist[i].level + section_alist_offset);
if (return_val < 0)
return_val = 0;
else if (return_val > 5)
return_val = 5;
return (return_val);
}
}
return (-1);
}
int
set_top_section_level (level)
int level;
{
register int i, result = -1;
for (i = 0; section_alist[i].name; i++)
if (strcmp (section_alist[i].name, "top") == 0)
{
result = section_alist[i].level;
section_alist[i].level = level;
break;
}
return (result);
}
void
cm_top ()
{
if (top_node_seen)
{
TAG_ENTRY *tag = tag_table;
line_error (_("Node with %ctop as a section already exists"),
COMMAND_PREFIX);
while (tag != (TAG_ENTRY *)NULL)
{
if ((tag->flags & IS_TOP))
{
int old_line_number = line_number;
char *old_input_filename = input_filename;
line_number = tag->line_no;
input_filename = tag->filename;
line_error (_("Here is the %ctop node"), COMMAND_PREFIX);
input_filename = old_input_filename;
line_number = old_line_number;
return;
}
tag = tag->next_ent;
}
}
else
{
top_node_seen = 1;
if (!tag_table)
{
char *top_name;
get_rest_of_line (&top_name);
free (top_name);
line_error (_("%ctop used before %cnode, defaulting to %s"),
COMMAND_PREFIX, COMMAND_PREFIX, top_name);
execute_string ("@node Top, , (dir), (dir)\n@top %s\n", top_name);
return;
}
cm_unnumbered ();
tag_table->flags |= IS_TOP;
{
int orig_offset = input_text_offset;
input_text_offset = search_forward (node_search_string, orig_offset);
if (input_text_offset > 0)
{
int this_section;
non_top_node_seen = 1;
while (input_text[input_text_offset] != '\n')
input_text_offset++;
if (input_text_offset < size_of_input_text)
input_text_offset++;
this_section = what_section (input_text + input_text_offset);
if (this_section != -1)
set_top_section_level (this_section - 1);
}
input_text_offset = orig_offset;
}
}
}
char *scoring_characters = "*=-.";
void
sectioning_underscore (command)
char *command;
{
char character;
char *temp;
int level;
temp = (char *)xmalloc (2 + strlen (command));
temp[0] = COMMAND_PREFIX;
strcpy (&temp[1], command);
level = what_section (temp);
free (temp);
level -= 2;
if (level < 0)
level = 0;
character = scoring_characters[level];
insert_and_underscore (character);
}
void
cm_ideprecated (arg, start, end)
int arg, start, end;
{
warning (_("%c%s is obsolete; use %c%s instead"),
COMMAND_PREFIX, command, COMMAND_PREFIX, command + 1);
sectioning_underscore (command + 1);
}
void
cm_chapter ()
{
sectioning_underscore ("chapter");
}
void
cm_section ()
{
sectioning_underscore ("section");
}
void
cm_subsection ()
{
sectioning_underscore ("subsection");
}
void
cm_subsubsection ()
{
sectioning_underscore ("subsubsection");
}
void
cm_unnumbered ()
{
cm_chapter ();
}
void
cm_unnumberedsec ()
{
cm_section ();
}
void
cm_unnumberedsubsec ()
{
cm_subsection ();
}
void
cm_unnumberedsubsubsec ()
{
cm_subsubsection ();
}
void
cm_appendix ()
{
cm_chapter ();
}
void
cm_appendixsec ()
{
cm_section ();
}
void
cm_appendixsubsec ()
{
cm_subsection ();
}
void
cm_appendixsubsubsec ()
{
cm_subsubsection ();
}
void
cm_majorheading ()
{
cm_chapheading ();
}
void
cm_chapheading ()
{
cm_chapter ();
}
void
cm_heading ()
{
cm_section ();
}
void
cm_subheading ()
{
cm_subsection ();
}
void
cm_subsubheading ()
{
cm_subsubsection ();
}
void
init_tag_table ()
{
while (tag_table != (TAG_ENTRY *) NULL)
{
TAG_ENTRY *temp = tag_table;
free (temp->node);
free (temp->prev);
free (temp->next);
free (temp->up);
tag_table = tag_table->next_ent;
free (temp);
}
}
void
write_tag_table ()
{
write_tag_table_internal (0);
}
void
write_tag_table_indirect ()
{
write_tag_table_internal (1);
}
void
write_tag_table_internal (indirect_p)
int indirect_p;
{
TAG_ENTRY *node = tag_table;
int old_indent = no_indent;
no_indent = 1;
filling_enabled = 0;
must_start_paragraph = 0;
close_paragraph ();
if (!indirect_p)
{
no_indent = 1;
insert ('\n');
}
add_word_args ("\037\nTag Table:\n%s", indirect_p ? "(Indirect)\n" : "");
while (node != (TAG_ENTRY *) NULL)
{
execute_string ("Node: %s", node->node);
add_word_args ("\177%d\n", node->position);
node = node->next_ent;
}
add_word ("\037\nEnd Tag Table\n");
flush_output ();
no_indent = old_indent;
}
char *
get_node_token (expand)
int expand;
{
char *string;
get_until_in_line (expand, ",", &string);
if (curchar () == ',')
input_text_offset++;
canon_white (string);
normalize_node_name (string);
return (string);
}
void
normalize_node_name (string)
char *string;
{
if (strcasecmp (string, "Top") == 0)
strcpy (string, "Top");
}
TAG_ENTRY *
find_node (name)
char *name;
{
TAG_ENTRY *tag = tag_table;
while (tag != (TAG_ENTRY *) NULL)
{
if (strcmp (tag->node, name) == 0)
return (tag);
tag = tag->next_ent;
}
return ((TAG_ENTRY *) NULL);
}
void
remember_node (node, prev, next, up, position, line_no, no_warn)
char *node, *prev, *next, *up;
int position, line_no, no_warn;
{
if (validating)
{
register TAG_ENTRY *tag = find_node (node);
if (tag)
{
line_error (
_("Node `%s' multiply defined (line %d is first definition at)"),
node, tag->line_no);
return;
}
}
current_node = node;
{
TAG_ENTRY *new = (TAG_ENTRY *) xmalloc (sizeof (TAG_ENTRY));
new->node = node;
new->prev = prev;
new->next = next;
new->up = up;
new->position = position;
new->line_no = line_no;
new->filename = node_filename;
new->touched = 0;
new->flags = 0;
if (no_warn)
new->flags |= NO_WARN;
new->next_ent = tag_table;
tag_table = new;
}
}
void
cm_node ()
{
char *node, *prev, *next, *up;
int new_node_pos, defaulting, this_section, no_warn = 0;
extern int already_outputting_pending_notes;
if (strcmp (command, "nwnode") == 0)
no_warn = 1;
discard_braces ();
discard_insertions (1);
if (!already_outputting_pending_notes)
{
close_paragraph ();
output_pending_notes ();
free_pending_notes ();
}
filling_enabled = indented_fill = 0;
new_node_pos = output_position;
current_footnote_number = 1;
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream && !executing_string)
append_to_expansion_output (input_text_offset + 1);
#endif
node = get_node_token (1);
next = get_node_token (0);
prev = get_node_token (0);
up = get_node_token (0);
if (verbose_mode)
printf (_("Formatting node %s...\n"), node);
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream && !executing_string)
remember_itext (input_text, input_text_offset);
#endif
no_indent = 1;
if (!no_headers)
{
add_word_args ("\037\nFile: %s, Node: ", pretty_output_filename);
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream && !executing_string)
me_execute_string (node);
else
#endif
execute_string ("%s", node);
filling_enabled = indented_fill = 0;
}
defaulting = (*next == 0 && *prev == 0 && *up == 0);
this_section = what_section (input_text + input_text_offset);
if (defaulting)
{
NODE_REF *last_ref = (NODE_REF *)NULL;
NODE_REF *ref = node_references;
if ((this_section < 0) && (strcmp (node, "Top") != 0))
{
char *polite_section_name = "top";
int i;
for (i = 0; section_alist[i].name; i++)
if (section_alist[i].level == current_section + 1)
{
polite_section_name = section_alist[i].name;
break;
}
line_error
(_("Node `%s' requires a sectioning command (e.g. %c%s)"),
node, COMMAND_PREFIX, polite_section_name);
}
else
{
if (strcmp (node, "Top") == 0)
{
int saved_input_text_offset = input_text_offset;
int saved_size_of_input_text = size_of_input_text;
char *saved_input_text = input_text;
FSTACK *next_file = filestack;
int orig_offset, orig_size;
char *glean_node_from_menu ();
free (up); up = xstrdup ("(dir)");
while (1)
{
orig_offset = input_text_offset;
orig_size =
search_forward (node_search_string, orig_offset);
if (orig_size < 0)
orig_size = size_of_input_text;
input_text_offset =
search_forward (menu_search_string, orig_offset);
if (input_text_offset > -1)
{
char *nodename_from_menu = (char *)NULL;
input_text_offset =
search_forward ("\n* ", input_text_offset);
if (input_text_offset != -1)
nodename_from_menu = glean_node_from_menu (0);
if (nodename_from_menu)
{
free (next); next = nodename_from_menu;
break;
}
}
if (next_file &&
(strcmp (next_file->filename, input_filename) == 0))
{
input_text = next_file->text;
input_text_offset = next_file->offset;
size_of_input_text = next_file->size;
next_file = next_file->next;
}
else
{
break;
}
}
input_text = saved_input_text;
input_text_offset = saved_input_text_offset;
size_of_input_text = saved_size_of_input_text;
}
}
if (top_node_seen && !non_top_node_seen)
{
int level;
level = set_top_section_level (this_section - 1);
non_top_node_seen = 1;
while (ref)
{
if (ref->section == level)
ref->section = this_section - 1;
ref = ref->next;
}
ref = node_references;
}
while (ref)
{
if (ref->section == (this_section - 1) &&
ref->type == menu_reference &&
strcmp (ref->node, node) == 0)
{
char *containing_node = ref->containing_node;
free (up);
up = xstrdup (containing_node);
if (last_ref &&
last_ref->type == menu_reference &&
(strcmp (last_ref->containing_node,
containing_node) == 0))
{
free (next);
next = xstrdup (last_ref->node);
}
while ((ref->section == this_section - 1) &&
(ref->next) &&
(ref->next->type != menu_reference))
ref = ref->next;
if (ref->next && ref->type == menu_reference &&
(strcmp (ref->next->containing_node,
containing_node) == 0))
{
free (prev);
prev = xstrdup (ref->next->node);
}
else if (!ref->next &&
strcasecmp (ref->containing_node, "Top") == 0)
{
free (prev);
prev = xstrdup (ref->containing_node);
}
break;
}
last_ref = ref;
ref = ref->next;
}
}
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream && !executing_string && !defaulting)
{
char *temp;
int op_orig = output_paragraph_offset;
temp = (char *)xmalloc (3 + strlen (next));
sprintf (temp, ", %s", next);
me_execute_string (temp);
free (temp);
temp = (char *)xmalloc (3 + strlen (prev));
sprintf (temp, ", %s", prev);
me_execute_string (temp);
free (temp);
temp = (char *)xmalloc (4 + strlen (up));
sprintf (temp, ", %s", up);
me_execute_string (temp);
free (temp);
output_paragraph_offset = op_orig;
}
#endif
if (!no_headers)
{
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream)
me_inhibit_expansion++;
#endif
if (*next)
{
execute_string (", Next: %s", next);
filling_enabled = indented_fill = 0;
}
if (*prev)
{
execute_string (", Prev: %s", prev);
filling_enabled = indented_fill = 0;
}
if (*up)
{
execute_string (", Up: %s", up);
filling_enabled = indented_fill = 0;
}
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream)
me_inhibit_expansion--;
#endif
}
close_paragraph ();
no_indent = 0;
if (!*node)
{
line_error ("No node name specified for `%c%s' command",
COMMAND_PREFIX, command);
free (node);
free (next);
free (prev);
free (up);
}
else
{
if (!*next) { free (next); next = (char *)NULL; }
if (!*prev) { free (prev); prev = (char *)NULL; }
if (!*up) { free (up); up = (char *)NULL; }
remember_node (node, prev, next, up, new_node_pos, line_number, no_warn);
}
if (this_section >= 0)
current_section = this_section;
filling_enabled = 1;
}
void
validate_file (tag_table)
TAG_ENTRY *tag_table;
{
char *old_input_filename = input_filename;
TAG_ENTRY *tags = tag_table;
while (tags != (TAG_ENTRY *) NULL)
{
register TAG_ENTRY *temp_tag;
input_filename = tags->filename;
line_number = tags->line_no;
if (tags->flags & NO_WARN)
{
tags = tags->next_ent;
continue;
}
if (tags->next)
{
validate (tags->next, tags->line_no, "Next");
temp_tag = find_node (tags->next);
if (temp_tag)
{
char *prev;
if (temp_tag->flags & NO_WARN)
{
}
else
{
prev = temp_tag->prev;
if (!prev || (strcmp (prev, tags->node) != 0))
{
line_error (_("Node `%s''s Next field not pointed back to"),
tags->node);
line_number = temp_tag->line_no;
input_filename = temp_tag->filename;
line_error
(_("This node (`%s') is the one with the bad `Prev'"),
temp_tag->node);
input_filename = tags->filename;
line_number = tags->line_no;
temp_tag->flags |= PREV_ERROR;
}
}
}
}
if (!(tags->flags & PREV_ERROR) && tags->prev)
{
int valid_p = validate (tags->prev, tags->line_no, "Prev");
if (!valid_p)
tags->flags |= PREV_ERROR;
else
{
if (tags->up && (strcmp (tags->prev, tags->up) != 0))
{
temp_tag = find_node (tags->prev);
if (!temp_tag || (temp_tag->flags & NO_WARN))
{
}
else
{
if (!temp_tag->next ||
(strcmp (temp_tag->next, tags->node) != 0))
{
line_error
(_("Node `%s's Prev field not pointed back to"),
tags->node);
line_number = temp_tag->line_no;
input_filename = temp_tag->filename;
line_error (_("This node (`%s') has the bad Next"),
temp_tag->node);
input_filename = tags->filename;
line_number = tags->line_no;
temp_tag->flags |= NEXT_ERROR;
}
}
}
}
}
if (!tags->up && (strcasecmp (tags->node, _("Top")) != 0))
line_error (_("Node `%s' missing Up field"), tags->node);
else if (tags->up)
{
int valid_p = validate (tags->up, tags->line_no, "Up");
if (valid_p && *tags->up != '(')
{
NODE_REF *nref, *tref, *list;
NODE_REF *find_node_reference ();
tref = (NODE_REF *) NULL;
list = node_references;
for (;;)
{
if (!(nref = find_node_reference (tags->node, list)))
break;
if (strcmp (nref->containing_node, tags->up) == 0)
{
if (nref->type != menu_reference)
{
tref = nref;
list = nref->next;
}
else
break;
}
list = nref->next;
}
if (!nref)
{
temp_tag = find_node (tags->up);
line_number = temp_tag->line_no;
input_filename = temp_tag->filename;
if (!tref)
line_error (
_("`%s' has an Up field of `%s', but `%s' has no menu item for `%s'"),
tags->node, tags->up, tags->up, tags->node);
line_number = tags->line_no;
input_filename = tags->filename;
}
}
}
tags = tags->next_ent;
}
validate_other_references (node_references);
tags = tag_table;
while (tags != (TAG_ENTRY *) NULL)
{
if (tags->flags & NO_WARN)
{
tags = tags->next_ent;
continue;
}
if (tags->touched > reference_warning_limit)
{
input_filename = tags->filename;
line_number = tags->line_no;
warning (_("node `%s' has been referenced %d times"),
tags->node, tags->touched);
}
if (tags->touched == 0)
{
input_filename = tags->filename;
line_number = tags->line_no;
if (strcasecmp (tags->node, _("Top")) != 0)
warning (_("unreferenced node `%s'"), tags->node);
}
tags = tags->next_ent;
}
input_filename = old_input_filename;
}
int
validate (tag, line, label)
char *tag;
int line;
char *label;
{
TAG_ENTRY *result;
if (!tag || !*tag || *tag == '(')
return (1);
result = find_node (tag);
if (!result)
{
line_number = line;
line_error (_("%s reference to nonexistent node `%s'"), label, tag);
return (0);
}
result->touched++;
return (1);
}
void
split_file (filename, size)
char *filename;
int size;
{
char *root_filename, *root_pathname;
char *the_file, *filename_part ();
struct stat fileinfo;
long file_size;
char *the_header;
int header_size;
if (!tag_table)
return;
if (size == 0)
size = DEFAULT_SPLIT_SIZE;
if ((stat (filename, &fileinfo) != 0) ||
(((long) fileinfo.st_size) < SPLIT_SIZE_THRESHOLD))
return;
file_size = (long) fileinfo.st_size;
the_file = find_and_load (filename);
if (!the_file)
return;
root_filename = filename_part (filename);
root_pathname = pathname_part (filename);
if (!root_pathname)
root_pathname = xstrdup ("");
{
int which_file = 1;
TAG_ENTRY *tags = tag_table;
char *indirect_info = (char *)NULL;
the_header = (char *)xmalloc (1 + (header_size = tags->position));
memcpy (the_header, the_file, header_size);
while (tags)
{
int file_top, file_bot, limit;
file_top = file_bot = tags->position;
limit = file_top + size;
if (!tags->next_ent)
{
int i = tags->position + 1;
char last_char = the_file[i];
while (i < file_size)
{
if ((the_file[i] == '\037') &&
((last_char == '\n') ||
(last_char == '\014')))
break;
else
last_char = the_file[i];
i++;
}
file_bot = i;
tags = tags->next_ent;
goto write_region;
}
for (; tags; tags = tags->next_ent)
{
if (!tags->next_ent)
{
int i = tags->position + 1;
char last_char = the_file[i];
while (i < file_size)
{
if ((the_file[i] == '\037') &&
((last_char == '\n') ||
(last_char == '\014')))
break;
else
last_char = the_file[i];
i++;
}
file_bot = i;
if (file_bot < limit)
{
tags = tags->next_ent;
goto write_region;
}
else
{
file_bot = tags->position;
goto write_region;
}
}
if (tags->next_ent->position > limit)
{
if (tags->position == file_top)
tags = tags->next_ent;
file_bot = tags->position;
write_region:
{
int fd;
char *split_filename;
split_filename = (char *) xmalloc
(10 + strlen (root_pathname) + strlen (root_filename));
sprintf
(split_filename,
"%s%s-%d", root_pathname, root_filename, which_file);
fd = open
(split_filename, O_WRONLY | O_TRUNC | O_CREAT, 0666);
if ((fd < 0) ||
(write (fd, the_header, header_size) != header_size) ||
(write (fd, the_file + file_top, file_bot - file_top)
!= (file_bot - file_top)) ||
((close (fd)) < 0))
{
perror (split_filename);
if (fd != -1)
close (fd);
exit (FATAL);
}
if (!indirect_info)
{
indirect_info = the_file + file_top;
sprintf (indirect_info, "\037\nIndirect:\n");
indirect_info += strlen (indirect_info);
}
sprintf (indirect_info, "%s-%d: %d\n",
root_filename, which_file, file_top);
free (split_filename);
indirect_info += strlen (indirect_info);
which_file++;
break;
}
}
}
}
output_stream = fopen (filename, "w");
if (!output_stream)
{
perror (filename);
exit (FATAL);
}
{
int distance = indirect_info - the_file;
fwrite (the_file, 1, distance, output_stream);
paragraph_is_open = 0;
write_tag_table_indirect ();
fclose (output_stream);
free (the_header);
free (the_file);
return;
}
}
}
char *
reftype_type_string (type)
enum reftype type;
{
switch (type)
{
case menu_reference:
return ("Menu");
case followed_reference:
return ("Cross");
default:
return ("Internal-bad-reference-type");
}
}
void
remember_node_reference (node, line, type)
char *node;
int line;
enum reftype type;
{
NODE_REF *temp = (NODE_REF *) xmalloc (sizeof (NODE_REF));
temp->next = node_references;
temp->node = xstrdup (node);
temp->line_no = line;
temp->section = current_section;
temp->type = type;
temp->containing_node = xstrdup (current_node ? current_node : "");
temp->filename = node_filename;
node_references = temp;
}
void
validate_other_references (ref_list)
register NODE_REF *ref_list;
{
char *old_input_filename = input_filename;
while (ref_list != (NODE_REF *) NULL)
{
input_filename = ref_list->filename;
validate (ref_list->node, ref_list->line_no,
reftype_type_string (ref_list->type));
ref_list = ref_list->next;
}
input_filename = old_input_filename;
}
NODE_REF *
find_node_reference (node, ref_list)
char *node;
register NODE_REF *ref_list;
{
while (ref_list)
{
if (strcmp (node, ref_list->node) == 0)
break;
ref_list = ref_list->next;
}
return (ref_list);
}
void
free_node_references ()
{
register NODE_REF *list, *temp;
list = node_references;
while (list)
{
temp = list;
free (list->node);
free (list->containing_node);
list = list->next;
free (temp);
}
node_references = (NODE_REF *) NULL;
}
#define menu_starter "* "
char *
glean_node_from_menu (remember_reference)
int remember_reference;
{
int i, orig_offset = input_text_offset;
char *nodename;
if (strncmp (&input_text[input_text_offset + 1],
menu_starter,
strlen (menu_starter)) != 0)
return ((char *)NULL);
else
input_text_offset += strlen (menu_starter) + 1;
get_until_in_line (0, ":", &nodename);
if (curchar () == ':')
input_text_offset++;
canon_white (nodename);
if (curchar () == ':')
goto save_node;
free (nodename);
get_rest_of_line (&nodename);
line_number--;
isolate_nodename (nodename);
save_node:
input_text_offset = orig_offset;
normalize_node_name (nodename);
i = strlen (nodename);
if (i && nodename[i - 1] == ':')
nodename[i - 1] = 0;
if (remember_reference)
{
remember_node_reference (nodename, line_number, menu_reference);
free (nodename);
return ((char *)NULL);
}
else
return (nodename);
}
static void
isolate_nodename (nodename)
char *nodename;
{
register int i, c;
int paren_seen, paren;
if (!nodename)
return;
canon_white (nodename);
paren_seen = paren = i = 0;
if (*nodename == '.' || !*nodename)
{
*nodename = 0;
return;
}
if (*nodename == '(')
{
paren++;
paren_seen++;
i++;
}
for (; (c = nodename[i]); i++)
{
if (paren)
{
if (c == '(')
paren++;
else if (c == ')')
paren--;
continue;
}
if (c == '\t' ||
c == '\n' ||
c == ',' ||
((paren_seen && nodename[i - 1] == ')') &&
(c == ' ' || c == '.')) ||
(c == '.' &&
((!nodename[i + 1] ||
(cr_or_whitespace (nodename[i + 1])) ||
(nodename[i + 1] == ')')))))
break;
}
nodename[i] = 0;
}
void
cm_menu ()
{
if (current_node == (char *)NULL)
{
warning (_("%cmenu seen before first node"), COMMAND_PREFIX);
warning (_("creating `Top' node"));
execute_string ("@node Top");
}
begin_insertion (menu);
}
void
cm_detailmenu ()
{
if (current_node == (char *)NULL)
{
warning (_("%cmenu seen before first node"), COMMAND_PREFIX);
warning (_("creating `Top' node"));
execute_string ("@node Top");
}
begin_insertion (detailmenu);
}
char *
get_xref_token ()
{
char *string;
get_until_in_braces (",", &string);
if (curchar () == ',')
input_text_offset++;
fix_whitespace (string);
return (string);
}
int px_ref_flag = 0;
void
cm_xref (arg)
{
if (arg == START)
{
char *arg1, *arg2, *arg3, *arg4, *arg5;
arg1 = get_xref_token ();
arg2 = get_xref_token ();
arg3 = get_xref_token ();
arg4 = get_xref_token ();
arg5 = get_xref_token ();
add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
if (*arg5 || *arg4)
{
char *node_name;
if (!*arg2)
{
if (*arg3)
node_name = arg3;
else
node_name = arg1;
}
else
node_name = arg2;
execute_string ("%s: (%s)%s", node_name, arg4, arg1);
if (arg1) free (arg1);
if (arg2) free (arg2);
if (arg3) free (arg3);
if (arg4) free (arg4);
if (arg5) free (arg5);
return;
}
else
remember_node_reference (arg1, line_number, followed_reference);
if (*arg3)
{
if (!*arg2)
execute_string ("%s: %s", arg3, arg1);
else
execute_string ("%s: %s", arg2, arg1);
}
else
{
if (*arg2)
execute_string ("%s: %s", arg2, arg1);
else
execute_string ("%s::", arg1);
}
if (arg1) free (arg1);
if (arg2) free (arg2);
if (arg3) free (arg3);
if (arg4) free (arg4);
if (arg5) free (arg5);
}
else
{
int temp = input_text_offset + 1;
if (output_paragraph[output_paragraph_offset - 2] == ':' &&
output_paragraph[output_paragraph_offset - 1] == ':')
return;
while (temp < size_of_input_text)
{
if (cr_or_whitespace (input_text[temp]))
temp++;
else
{
if (input_text[temp] != '.'
&& input_text[temp] != ','
&& input_text[temp] != '\t')
{
line_error (
_("`.' or `,' must follow cross reference, not %c"),
input_text[temp]);
}
break;
}
}
}
}
void
cm_pxref (arg)
int arg;
{
if (arg == START)
{
px_ref_flag++;
cm_xref (arg);
px_ref_flag--;
}
else
add_char ('.');
}
void
cm_inforef (arg)
int arg;
{
if (arg == START)
{
char *node = get_xref_token ();
char *pname = get_xref_token ();
char *file = get_xref_token ();
if (*pname)
execute_string ("*note %s: (%s)%s", pname, file, node);
else
execute_string ("*note (%s)%s::", file, node);
free (node);
free (pname);
free (file);
}
}
void
cm_uref (arg, start_pos, end_pos)
int arg, start_pos, end_pos;
{
if (arg == END)
{
char *comma;
char *arg = (char *) &output_paragraph[start_pos];
output_paragraph[end_pos] = 0;
output_column -= end_pos - start_pos;
output_paragraph_offset = start_pos;
arg = xstrdup (arg);
comma = strchr (arg, ',');
if (comma)
{
*comma = 0;
for (comma++; isspace (*comma); comma++)
;
add_word (comma);
add_char (' ');
add_char ('(');
add_word (arg);
add_char (')');
}
else
{
extern int printing_index;
if (!printing_index)
add_char ('`');
add_word (arg);
if (!printing_index)
add_char ('\'');
}
free (arg);
}
}
void
cm_email (arg, start_pos, end_pos)
int arg, start_pos, end_pos;
{
if (arg == END)
{
char *comma;
char *arg = (char *) &output_paragraph[start_pos];
output_paragraph[end_pos] = 0;
output_column -= end_pos - start_pos;
output_paragraph_offset = start_pos;
arg = xstrdup (arg);
comma = strchr (arg, ',');
if (comma)
{
*comma = 0;
for (comma++; isspace (*comma); comma++)
;
add_word (comma);
add_char (' ');
}
add_char ('<');
add_word (arg);
add_char ('>');
free (arg);
}
}
void
cm_image (arg)
int arg;
{
if (arg == START)
{
char *name_arg = get_xref_token ();
char *arg = get_xref_token ();
if (arg) free (arg);
arg = get_xref_token ();
if (arg) free (arg);
if (*name_arg)
{
FILE *image_file;
char *name = xmalloc (strlen (name_arg) + 4);
strcpy (name, name_arg);
strcat (name, ".txt");
image_file = fopen (name, "r");
if (image_file)
{
int ch;
int save_inhibit_indentation = inhibit_paragraph_indentation;
int save_filling_enabled = filling_enabled;
inhibit_paragraph_indentation = 1;
filling_enabled = 0;
last_char_was_newline = 0;
while ((ch = getc (image_file)) != EOF)
add_char (ch);
inhibit_paragraph_indentation = save_inhibit_indentation;
filling_enabled = save_filling_enabled;
if (fclose (image_file) != 0) {
perror (name);
}
}
else
warning (_("@image file `%s' unreadable: %s"), name,
strerror (errno));
}
else
line_error (_("@image missing filename argument"));
if (name_arg) free (name_arg);
}
}
void
cm_quotation ()
{
begin_insertion (quotation);
}
void
cm_example ()
{
begin_insertion (example);
}
void
cm_smallexample ()
{
begin_insertion (smallexample);
}
void
cm_lisp ()
{
begin_insertion (lisp);
}
void
cm_smalllisp ()
{
begin_insertion (smalllisp);
}
void
cm_cartouche ()
{
begin_insertion (cartouche);
}
void
cm_format ()
{
begin_insertion (format);
}
void
cm_display ()
{
begin_insertion (display);
}
void
cm_direntry ()
{
if (no_headers)
command_name_condition ();
else
begin_insertion (direntry);
}
void
cm_itemize ()
{
begin_insertion (itemize);
}
void
cm_enumerate ()
{
do_enumeration (enumerate, "1");
}
void
do_enumeration (type, default_string)
int type;
char *default_string;
{
get_until_in_line (0, ".", &enumeration_arg);
canon_white (enumeration_arg);
if (!*enumeration_arg)
{
free (enumeration_arg);
enumeration_arg = xstrdup (default_string);
}
if (!isdigit (*enumeration_arg) && !isletter (*enumeration_arg))
{
warning (_("%s requires letter or digit"), insertion_type_pname (type));
switch (type)
{
case enumerate:
default_string = "1";
break;
}
enumeration_arg = xstrdup (default_string);
}
begin_insertion (type);
}
void
cm_table ()
{
begin_insertion (table);
}
void
cm_multitable ()
{
begin_insertion (multitable);
}
void
cm_ftable ()
{
begin_insertion (ftable);
}
void
cm_vtable ()
{
begin_insertion (vtable);
}
void
cm_group ()
{
begin_insertion (group);
}
void
cm_ifinfo ()
{
begin_insertion (ifinfo);
}
void
cm_ifnothtml ()
{
begin_insertion (ifnothtml);
}
void
cm_ifnottex ()
{
begin_insertion (ifnottex);
}
void
cm_flushleft ()
{
begin_insertion (flushleft);
}
void
cm_flushright ()
{
begin_insertion (flushright);
}
void
cm_end ()
{
char *temp;
enum insertion_type type;
if (!insertion_level)
{
line_error (_("Unmatched `%c%s'"), COMMAND_PREFIX, command);
return;
}
get_rest_of_line (&temp);
if (temp[0] == 0)
line_error (_("`%c%s' needs something after it"), COMMAND_PREFIX, command);
type = find_type_from_name (temp);
if (type == bad_type)
{
line_error (_("Bad argument to `%s', `%s', using `%s'"),
command, temp, insertion_type_pname (current_insertion_type ()));
}
end_insertion (type);
free (temp);
}
typedef struct defines {
struct defines *next;
char *name;
char *value;
} DEFINE;
DEFINE *defines = (DEFINE *)NULL;
void
set (name, value)
char *name;
char *value;
{
DEFINE *temp;
for (temp = defines; temp; temp = temp->next)
if (strcmp (name, temp->name) == 0)
{
free (temp->value);
temp->value = xstrdup (value);
return;
}
temp = (DEFINE *)xmalloc (sizeof (DEFINE));
temp->next = defines;
temp->name = xstrdup (name);
temp->value = xstrdup (value);
defines = temp;
}
void
clear (name)
char *name;
{
register DEFINE *temp, *last;
last = (DEFINE *)NULL;
temp = defines;
while (temp)
{
if (strcmp (temp->name, name) == 0)
{
if (last)
last->next = temp->next;
else
defines = temp->next;
free (temp->name);
free (temp->value);
free (temp);
break;
}
last = temp;
temp = temp->next;
}
}
char *
set_p (name)
char *name;
{
register DEFINE *temp;
for (temp = defines; temp; temp = temp->next)
if (strcmp (temp->name, name) == 0)
return (temp->value);
return ((char *)NULL);
}
void
command_name_condition ()
{
char *discarder;
discarder = (char *)xmalloc (8 + strlen (command));
sprintf (discarder, "\n%cend %s", COMMAND_PREFIX, command);
discard_until (discarder);
discard_until ("\n");
free (discarder);
}
void
cm_set ()
{
handle_variable (SET);
}
void
cm_clear ()
{
handle_variable (CLEAR);
}
void
cm_ifset ()
{
handle_variable (IFSET);
}
void
cm_ifclear ()
{
handle_variable (IFCLEAR);
}
void
cm_ifeq ()
{
char **arglist;
arglist = get_brace_args (0);
if (arglist)
{
if (array_len (arglist) > 1)
{
if ((strcasecmp (arglist[0], arglist[1]) == 0) &&
(arglist[2] != (char *)NULL))
execute_string ("%s\n", arglist[2]);
}
free_array (arglist);
}
}
void
cm_value (arg, start_pos, end_pos)
int arg, start_pos, end_pos;
{
if (arg == END)
{
char *name = (char *) &output_paragraph[start_pos];
char *value;
output_paragraph[end_pos] = 0;
name = xstrdup (name);
value = set_p (name);
output_column -= end_pos - start_pos;
output_paragraph_offset = start_pos;
if (value)
execute_string ("%s", value);
else
add_word_args (_("{No Value For \"%s\"}"), name);
free (name);
}
}
void
handle_variable (action)
int action;
{
char *name;
get_rest_of_line (&name);
backup_input_pointer ();
handle_variable_internal (action, name);
free (name);
}
void
handle_variable_internal (action, name)
int action;
char *name;
{
char *temp;
int delimiter, additional_text_present = 0;
temp = name;
delimiter = 0;
while (*temp && (delimiter || !whitespace (*temp)))
{
if (*temp == '"' || *temp == '\'')
{
if (*temp == delimiter)
delimiter = 0;
else
delimiter = *temp;
}
temp++;
}
if (*temp)
additional_text_present++;
*temp = 0;
if (!*name)
line_error (_("%c%s requires a name"), COMMAND_PREFIX, command);
else
{
switch (action)
{
case SET:
{
char *value;
#if defined (SET_WITH_EQUAL)
for (value = name; *value && *value != '='; value++);
if (*value)
*value++ = 0;
if (*value == '"' || *value == '\'')
{
value++;
value[strlen (value) - 1] = 0;
}
#else
if (additional_text_present)
{
value = temp + 1;
canon_white (value);
}
else
value = "";
#endif
set (name, value);
}
break;
case CLEAR:
clear (name);
break;
case IFSET:
case IFCLEAR:
{
char condition[8];
int condition_len;
int orig_line_number = line_number;
if (action == IFSET)
strcpy (condition, "ifset");
else
strcpy (condition, "ifclear");
condition_len = strlen (condition);
if ((action == IFSET && !set_p (name))
|| (action == IFCLEAR && set_p (name)))
{
int level = 0, done = 0;
while (!done && input_text_offset < size_of_input_text)
{
char *freeable_line, *line;
get_rest_of_line (&freeable_line);
for (line = freeable_line; whitespace (*line); line++);
if (*line == COMMAND_PREFIX &&
(strncmp (line + 1, condition, condition_len) == 0))
level++;
else if (strncmp (line, "@end", 4) == 0)
{
char *cname = line + 4;
char *temp;
while (*cname && whitespace (*cname))
cname++;
temp = cname;
while (*temp && !whitespace (*temp))
temp++;
*temp = 0;
if (strcmp (cname, condition) == 0)
{
if (!level)
{
done = 1;
}
else
level--;
}
}
free (freeable_line);
}
if (!done)
{
int save = line_number;
line_number = orig_line_number;
line_error (_("Reached eof before matching @end %s"),
condition);
line_number = save;
}
break;
}
else
{
if (action == IFSET)
begin_insertion (ifset);
else
begin_insertion (ifclear);
}
}
break;
}
}
}
typedef struct {
char *string;
int size;
int in_use;
} EXECUTION_STRING;
static EXECUTION_STRING **execution_strings = (EXECUTION_STRING **)NULL;
static int execution_strings_index = 0;
static int execution_strings_slots = 0;
EXECUTION_STRING *
get_execution_string (initial_size)
int initial_size;
{
register int i = 0;
EXECUTION_STRING *es = (EXECUTION_STRING *)NULL;
if (execution_strings)
{
for (i = 0; i < execution_strings_index; i++)
if (execution_strings[i] && (execution_strings[i]->in_use == 0))
{
es = execution_strings[i];
break;
}
}
if (!es)
{
if (execution_strings_index + 1 >= execution_strings_slots)
{
execution_strings = (EXECUTION_STRING **)xrealloc
(execution_strings,
(execution_strings_slots += 3) * sizeof (EXECUTION_STRING *));
for (; i < execution_strings_slots; i++)
execution_strings[i] = (EXECUTION_STRING *)NULL;
}
execution_strings[execution_strings_index] =
(EXECUTION_STRING *)xmalloc (sizeof (EXECUTION_STRING));
es = execution_strings[execution_strings_index];
execution_strings_index++;
es->size = 0;
es->string = (char *)NULL;
es->in_use = 0;
}
if (initial_size > es->size)
{
es->string = (char *) xrealloc (es->string, initial_size);
es->size = initial_size;
}
return (es);
}
void
#if defined (VA_FPRINTF) && __STDC__
execute_string (char *format, ...)
#else
execute_string (format, va_alist)
char *format;
va_dcl
#endif
{
EXECUTION_STRING *es;
char *temp_string;
#ifdef VA_FPRINTF
va_list ap;
#endif
es = get_execution_string (4000);
temp_string = es->string;
es->in_use = 1;
VA_START (ap, format);
#ifdef VA_SPRINTF
VA_SPRINTF (temp_string, format, ap);
#else
sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
#endif
va_end (ap);
pushfile ();
input_text_offset = 0;
input_text = temp_string;
input_filename = xstrdup (input_filename);
size_of_input_text = strlen (temp_string);
executing_string++;
reader_loop ();
free (input_filename);
popfile ();
executing_string--;
es->in_use = 0;
}
char *
expansion (str, implicit_code)
char *str;
int implicit_code;
{
int length;
char *result;
int start = output_paragraph_offset;
int saved_paragraph_is_open = paragraph_is_open;
inhibit_output_flushing ();
paragraph_is_open = 1;
execute_string (implicit_code ? "@code{%s}" : "%s", str);
uninhibit_output_flushing ();
length = output_paragraph_offset - start;
result = xmalloc (1 + length);
memcpy (result, (char *) (output_paragraph + start), length);
result[length] = 0;
output_paragraph_offset = start;
paragraph_is_open = saved_paragraph_is_open;
return result;
}
static int itemx_flag = 0;
void
cm_itemx ()
{
itemx_flag++;
cm_item ();
itemx_flag--;
}
void
cm_item ()
{
char *rest_of_line, *item_func;
if (insertion_level)
{
INSERTION_ELT *stack = insertion_stack;
int original_input_text_offset;
skip_whitespace ();
original_input_text_offset = input_text_offset;
get_rest_of_line (&rest_of_line);
item_func = current_item_function ();
switch_top:
switch (stack->insertion)
{
case multitable:
multitable_item ();
if (*rest_of_line)
{
line_number--;
input_text_offset = original_input_text_offset;
}
break;
case ifinfo:
case ifset:
case ifclear:
case cartouche:
stack = stack->next;
if (!stack)
goto no_insertion;
else
goto switch_top;
break;
case menu:
case quotation:
case example:
case smallexample:
case lisp:
case format:
case display:
case group:
line_error (_("The `%c%s' command is meaningless within a `@%s' block"),
COMMAND_PREFIX, command,
insertion_type_pname (current_insertion_type ()));
break;
case itemize:
case enumerate:
if (itemx_flag)
{
line_error (_("%citemx is not meaningful inside of a `%s' block"),
COMMAND_PREFIX,
insertion_type_pname (current_insertion_type ()));
}
else
{
start_paragraph ();
kill_self_indent (-1);
filling_enabled = indented_fill = 1;
if (current_insertion_type () == itemize)
{
indent (output_column = current_indent - 2);
if (item_func && *item_func)
{
if (*item_func == COMMAND_PREFIX)
if (item_func[strlen (item_func) - 1] != '}')
execute_string ("%s{}", item_func);
else
execute_string ("%s", item_func);
else
execute_string ("%s", item_func);
}
insert (' ');
output_column++;
}
else
enumerate_item ();
must_start_paragraph = 1;
if (*rest_of_line)
{
line_number--;
input_text_offset = original_input_text_offset;
}
}
break;
case table:
case ftable:
case vtable:
{
static int last_item_output_position = 0;
kill_self_indent (-1);
if (!itemx_flag && last_item_output_position == output_position)
insert ('\n');
if (last_char_was_newline && filling_enabled && paragraph_is_open)
insert ('\n');
close_paragraph ();
#if defined (INDENT_PARAGRAPHS_IN_TABLE)
{
int save = inhibit_paragraph_indentation;
inhibit_paragraph_indentation = 1;
add_char ('i');
inhibit_paragraph_indentation = save;
}
#else
add_char ('i');
#endif
output_paragraph_offset--;
kill_self_indent (default_indentation_increment + 1);
filling_enabled = 0;
if (item_func && *item_func)
execute_string ("%s{%s}", item_func, rest_of_line);
else
execute_string ("%s", rest_of_line);
if (current_insertion_type () == ftable)
execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line);
else if (current_insertion_type () == vtable)
execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line);
close_single_paragraph ();
indented_fill = filling_enabled = 1;
last_item_output_position = output_position;
}
}
free (rest_of_line);
}
else
{
no_insertion:
line_error (_("%c%s found outside of an insertion block"),
COMMAND_PREFIX, command);
}
}
#define DEFUN_SELF_DELIMITING(c) \
(((c) == '(') \
|| ((c) == ')') \
|| ((c) == '[') \
|| ((c) == ']'))
struct token_accumulator
{
unsigned int length;
unsigned int index;
char **tokens;
};
void
initialize_token_accumulator (accumulator)
struct token_accumulator *accumulator;
{
(accumulator->length) = 0;
(accumulator->index) = 0;
(accumulator->tokens) = NULL;
}
void
accumulate_token (accumulator, token)
struct token_accumulator *accumulator;
char *token;
{
if ((accumulator->index) >= (accumulator->length))
{
(accumulator->length) += 10;
(accumulator->tokens) = (char **) xrealloc
(accumulator->tokens, (accumulator->length * sizeof (char *)));
}
accumulator->tokens[accumulator->index] = token;
accumulator->index += 1;
}
char *
copy_substring (start, end)
char *start;
char *end;
{
char *result, *scan, *scan_result;
result = (char *) xmalloc ((end - start) + 1);
scan_result = result;
scan = start;
while (scan < end)
*scan_result++ = *scan++;
*scan_result = 0;
return (result);
}
int
scan_group_in_string (string_pointer)
char **string_pointer;
{
register int c;
register char *scan_string;
register unsigned int level = 1;
scan_string = (*string_pointer) + 1;
while (1)
{
if (level == 0)
{
(*string_pointer) = scan_string;
return (1);
}
c = (*scan_string++);
if (c == 0)
{
line_number -= 1;
line_error (_("Missing `}' in %cdef arg"), COMMAND_PREFIX);
line_number += 1;
(*string_pointer) = (scan_string - 1);
return (0);
}
if (c == '{')
level += 1;
if (c == '}')
level -= 1;
}
}
char **
args_from_string (string)
char *string;
{
struct token_accumulator accumulator;
register char *scan_string = string;
char *token_start, *token_end;
initialize_token_accumulator (&accumulator);
while ((*scan_string) != 0)
{
if (whitespace (*scan_string))
{
scan_string += 1;
while (whitespace (*scan_string))
scan_string += 1;
accumulate_token ((&accumulator), (xstrdup (" ")));
continue;
}
if ((*scan_string) == COMMAND_PREFIX)
{
token_start = scan_string;
scan_string += 1;
if (self_delimiting (*scan_string))
scan_string += 1;
else
{
register int c;
while (1)
{
c = *scan_string++;
if ((c == 0) || (c == '{') || (whitespace (c)))
{
scan_string -= 1;
break;
}
}
if (*scan_string == '{')
{
char *s = scan_string;
(void) scan_group_in_string (&s);
scan_string = s;
}
}
token_end = scan_string;
}
else if (DEFUN_SELF_DELIMITING (*scan_string))
{
token_start = scan_string;
scan_string += 1;
token_end = scan_string;
}
else if (*scan_string == '{')
{
char *s = scan_string;
int balanced = scan_group_in_string (&s);
token_start = scan_string + 1;
scan_string = s;
token_end = balanced ? (scan_string - 1) : scan_string;
}
else
{
token_start = scan_string;
while (1)
{
register int c;
c = *scan_string++;
if (!c || whitespace (c) || DEFUN_SELF_DELIMITING (c)
|| c == '{')
{
scan_string--;
break;
}
if (c == COMMAND_PREFIX)
{
scan_string--;
break;
}
}
token_end = scan_string;
}
accumulate_token
(&accumulator, copy_substring (token_start, token_end));
}
accumulate_token (&accumulator, NULL);
return (accumulator.tokens);
}
void
process_defun_args (defun_args, auto_var_p)
char **defun_args;
int auto_var_p;
{
int pending_space = 0;
while (1)
{
char *defun_arg = *defun_args++;
if (defun_arg == NULL)
break;
if (defun_arg[0] == ' ')
{
pending_space = 1;
continue;
}
if (pending_space)
{
add_char (' ');
pending_space = 0;
}
if (DEFUN_SELF_DELIMITING (defun_arg[0]))
add_char (defun_arg[0]);
else if (defun_arg[0] == '&')
add_word (defun_arg);
else if (defun_arg[0] == COMMAND_PREFIX)
execute_string ("%s", defun_arg);
else if (auto_var_p)
execute_string ("%cvar{%s}", COMMAND_PREFIX, defun_arg);
else
add_word (defun_arg);
}
}
char *
next_nonwhite_defun_arg (arg_pointer)
char ***arg_pointer;
{
char **scan = (*arg_pointer);
char *arg = (*scan++);
if ((arg != 0) && (*arg == ' '))
arg = *scan++;
if (arg == 0)
scan -= 1;
*arg_pointer = scan;
return ((arg == 0) ? "" : arg);
}
void
defun_internal (type, x_p)
enum insertion_type type;
int x_p;
{
enum insertion_type base_type;
char **defun_args, **scan_args;
char *category, *defined_name, *type_name, *type_name2;
{
char *line;
get_rest_of_line (&line);
defun_args = (args_from_string (line));
free (line);
}
scan_args = defun_args;
switch (type)
{
case defun:
category = _("Function");
base_type = deffn;
break;
case defmac:
category = _("Macro");
base_type = deffn;
break;
case defspec:
category = _("Special Form");
base_type = deffn;
break;
case defvar:
category = _("Variable");
base_type = defvr;
break;
case defopt:
category = _("User Option");
base_type = defvr;
break;
case deftypefun:
category = _("Function");
base_type = deftypefn;
break;
case deftypevar:
category = _("Variable");
base_type = deftypevr;
break;
case defivar:
category = _("Instance Variable");
base_type = defcv;
break;
case defmethod:
category = _("Method");
base_type = defop;
break;
case deftypemethod:
category = _("Method");
base_type = deftypemethod;
break;
default:
category = next_nonwhite_defun_arg (&scan_args);
base_type = type;
break;
}
if ((base_type == deftypefn)
|| (base_type == deftypevr)
|| (base_type == defcv)
|| (base_type == defop)
|| (base_type == deftypemethod))
type_name = next_nonwhite_defun_arg (&scan_args);
if (base_type == deftypemethod)
type_name2 = next_nonwhite_defun_arg (&scan_args);
defined_name = next_nonwhite_defun_arg (&scan_args);
if (*scan_args && **scan_args && !whitespace (**scan_args) &&
(strcmp (defined_name, "@@") == 0))
{
char *tem = (char *)xmalloc (3 + strlen (scan_args[0]));
sprintf (tem, "@@%s", scan_args[0]);
free (scan_args[0]);
scan_args[0] = tem;
scan_args++;
defined_name = tem;
}
if (!x_p)
begin_insertion (type);
current_indent -= default_indentation_increment;
start_paragraph ();
switch (base_type)
{
case deffn:
case defvr:
case deftp:
execute_string (" -- %s: %s", category, defined_name);
break;
case deftypefn:
case deftypevr:
execute_string (" -- %s: %s %s", category, type_name, defined_name);
break;
case defcv:
execute_string (" -- %s of %s: %s", category, type_name, defined_name);
break;
case defop:
execute_string (" -- %s on %s: %s", category, type_name, defined_name);
break;
case deftypemethod:
execute_string (" -- %s on %s: %s %s", category, type_name, type_name2,
defined_name);
break;
}
current_indent += default_indentation_increment;
current_indent += default_indentation_increment;
switch (base_type)
{
case deffn:
case defop:
process_defun_args (scan_args, 1);
break;
default:
process_defun_args (scan_args, 0);
break;
}
current_indent -= default_indentation_increment;
close_single_paragraph ();
switch (base_type)
{
case deffn:
case deftypefn:
execute_string ("%cfindex %s\n", COMMAND_PREFIX, defined_name);
break;
case defvr:
case deftypevr:
case defcv:
execute_string ("%cvindex %s\n", COMMAND_PREFIX, defined_name);
break;
case defop:
case deftypemethod:
execute_string ("%cfindex %s on %s\n",
COMMAND_PREFIX, defined_name, type_name);
break;
case deftp:
execute_string ("%ctindex %s\n", COMMAND_PREFIX, defined_name);
break;
}
scan_args = defun_args;
while (1)
{
char * arg = (*scan_args++);
if (arg == NULL)
break;
free (arg);
}
free (defun_args);
}
void
cm_defun ()
{
int x_p;
enum insertion_type type;
char *temp = xstrdup (command);
x_p = (command[strlen (command) - 1] == 'x');
if (x_p)
temp[strlen (temp) - 1] = 0;
type = find_type_from_name (temp);
free (temp);
if (x_p &&
(!insertion_level || insertion_stack->insertion != type))
{
line_error (_("Must be in a `%s' insertion in order to use `%s'x"),
command, command);
discard_until ("\n");
return;
}
defun_internal (type, x_p);
}
void
cm_noindent ()
{
if (!inhibit_paragraph_indentation)
inhibit_paragraph_indentation = -1;
}
void
cm_setfilename ()
{
char *filename;
get_rest_of_line (&filename);
free (filename);
}
void
cm_ignore_line ()
{
discard_until ("\n");
}
void
cm_br ()
{
if (looking_at ("{}"))
input_text_offset += 2;
if (curchar () == '\n')
{
input_text_offset++;
line_number++;
}
close_paragraph ();
}
void
cm_sp ()
{
int lines;
char *line;
get_rest_of_line (&line);
if (sscanf (line, "%d", &lines) != 1)
{
line_error (_("%csp requires a positive numeric argument"), COMMAND_PREFIX);
}
else
{
if (lines < 0)
lines = 0;
while (lines--)
add_char ('\n');
}
free (line);
}
void
cm_dircategory ()
{
char *line;
get_rest_of_line (&line);;
if (!no_headers)
{
insert_string ("INFO-DIR-SECTION ");
insert_string (line);
insert ('\n');
}
free (line);
}
void
cm_center ()
{
register int i, start, length;
int fudge_factor = 1;
unsigned char *line;
close_paragraph ();
filling_enabled = indented_fill = 0;
cm_noindent ();
start = output_paragraph_offset;
inhibit_output_flushing ();
get_rest_of_line ((char **)&line);
execute_string ("%s", (char *)line);
free (line);
uninhibit_output_flushing ();
i = output_paragraph_offset - 1;
while (i > (start - 1) && output_paragraph[i] == '\n')
i--;
output_paragraph_offset = ++i;
length = output_paragraph_offset - start;
if (length < (fill_column - fudge_factor))
{
line = (unsigned char *)xmalloc (1 + length);
memcpy (line, (char *)(output_paragraph + start), length);
i = (fill_column - fudge_factor - length) / 2;
output_paragraph_offset = start;
while (i--)
insert (' ');
for (i = 0; i < length; i++)
insert (line[i]);
free (line);
}
insert ('\n');
close_paragraph ();
filling_enabled = 1;
}
void
cm_result (arg)
int arg;
{
if (arg == END)
add_word ("=>");
}
void
cm_expansion (arg)
int arg;
{
if (arg == END)
add_word ("==>");
}
void
cm_equiv (arg)
int arg;
{
if (arg == END)
add_word ("==");
}
void
cm_print (arg)
int arg;
{
if (arg == END)
add_word ("-|");
}
void
cm_error (arg)
int arg;
{
if (arg == END)
add_word ("error-->");
}
void
cm_point (arg)
int arg;
{
if (arg == END)
add_word ("-!-");
}
void
cm_exdent ()
{
char *line;
int i = current_indent;
if (current_indent)
current_indent -= default_indentation_increment;
get_rest_of_line (&line);
close_single_paragraph ();
execute_string ("%s", line);
current_indent = i;
free (line);
close_single_paragraph ();
}
void
cm_include ()
{
char *filename;
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream && !executing_string)
me_append_before_this_command ();
#endif
close_paragraph ();
get_rest_of_line (&filename);
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream && !executing_string)
remember_itext (input_text, input_text_offset);
#endif
pushfile ();
if (verbose_mode)
{
register int i = 0;
register FSTACK *stack = filestack;
for (i = 0, stack = filestack; stack; stack = stack->next, i++);
i *= 2;
printf ("%*s", i, "");
printf ("%c%s %s\n", COMMAND_PREFIX, command, filename);
fflush (stdout);
}
if (!find_and_load (filename))
{
extern int errno;
popfile ();
line_number--;
line_error ("%c%s %s: %s", COMMAND_PREFIX, command, filename,
strerror (errno));
free (filename);
return;
}
else
{
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream && !executing_string)
remember_itext (input_text, input_text_offset);
#endif
reader_loop ();
}
free (filename);
popfile ();
}
void
misplaced_brace ()
{
line_error (_("Misplaced %c"), '}');
}
void
cm_bye ()
{
input_text_offset = size_of_input_text;
}
int
set_paragraph_indent (string)
char *string;
{
if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
paragraph_start_indent = 0;
else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
paragraph_start_indent = -1;
else
{
if (sscanf (string, "%d", ¶graph_start_indent) != 1)
return (-1);
else
{
if (paragraph_start_indent == 0)
paragraph_start_indent = -1;
}
}
return (0);
}
void
cm_paragraphindent ()
{
char *arg;
get_rest_of_line (&arg);
if (set_paragraph_indent (arg) != 0)
line_error (_("Bad argument to %c%s"), COMMAND_PREFIX, command);
free (arg);
}
typedef struct index_elt
{
struct index_elt *next;
char *entry;
char *node;
int code;
int defining_line;
char *defining_file;
} INDEX_ELT;
typedef struct
{
char *name;
int read_index;
int write_index;
int code;
} INDEX_ALIST;
INDEX_ALIST **name_index_alist = (INDEX_ALIST **) NULL;
INDEX_ELT **the_indices = (INDEX_ELT **) NULL;
int defined_indices = 0;
void
init_indices ()
{
int i;
if (!the_indices)
{
the_indices = (INDEX_ELT **) xmalloc ((1 + defined_indices) *
sizeof (INDEX_ELT *));
the_indices[defined_indices] = (INDEX_ELT *) NULL;
name_index_alist = (INDEX_ALIST **) xmalloc ((1 + defined_indices) *
sizeof (INDEX_ALIST *));
name_index_alist[defined_indices] = (INDEX_ALIST *) NULL;
}
for (i = 0; i < defined_indices; i++)
{
undefindex (name_index_alist[i]->name);
if (name_index_alist[i])
{
free (name_index_alist[i]->name);
free (name_index_alist[i]);
name_index_alist[i] = (INDEX_ALIST *) NULL;
}
}
top_defindex ("cp", 0);
top_defindex ("fn", 1);
top_defindex ("ky", 1);
top_defindex ("pg", 1);
top_defindex ("tp", 1);
top_defindex ("vr", 1);
}
int
find_index_offset (name)
char *name;
{
register int i;
for (i = 0; i < defined_indices; i++)
if (name_index_alist[i] &&
strcmp (name, name_index_alist[i]->name) == 0)
return (i);
return (-1);
}
INDEX_ALIST *
find_index (name)
char *name;
{
int offset = find_index_offset (name);
if (offset > -1)
return (name_index_alist[offset]);
else
return ((INDEX_ALIST *) NULL);
}
int
translate_index (name)
char *name;
{
INDEX_ALIST *which = find_index (name);
if (which)
return (which->read_index);
else
return (-1);
}
INDEX_ELT *
index_list (name)
char *name;
{
int which = translate_index (name);
if (which < 0)
return ((INDEX_ELT *) -1);
else
return (the_indices[which]);
}
void
free_index (index)
INDEX_ELT *index;
{
INDEX_ELT *temp;
while ((temp = index) != (INDEX_ELT *) NULL)
{
free (temp->entry);
index = index->next;
free (temp);
}
}
void
undefindex (name)
char *name;
{
int i;
int which = find_index_offset (name);
if (which < 0 || !name_index_alist[which])
return;
i = name_index_alist[which]->read_index;
free_index (the_indices[i]);
the_indices[i] = (INDEX_ELT *) NULL;
free (name_index_alist[which]->name);
free (name_index_alist[which]);
name_index_alist[which] = (INDEX_ALIST *) NULL;
}
void
defindex (name, code)
char *name;
int code;
{
register int i, slot;
undefindex (name);
slot = -1;
for (i = 0; i < defined_indices; i++)
if (!name_index_alist[i])
{
slot = i;
break;
}
if (slot < 0)
{
slot = defined_indices;
defined_indices++;
name_index_alist = (INDEX_ALIST **)
xrealloc ((char *)name_index_alist,
(1 + defined_indices) * sizeof (INDEX_ALIST *));
the_indices = (INDEX_ELT **)
xrealloc ((char *)the_indices,
(1 + defined_indices) * sizeof (INDEX_ELT *));
}
name_index_alist[slot] = (INDEX_ALIST *) xmalloc (sizeof (INDEX_ALIST));
name_index_alist[slot]->name = xstrdup (name);
name_index_alist[slot]->read_index = slot;
name_index_alist[slot]->write_index = slot;
name_index_alist[slot]->code = code;
the_indices[slot] = (INDEX_ELT *) NULL;
}
void
index_add_arg (name)
char *name;
{
int which;
char *index_entry;
INDEX_ALIST *tem;
tem = find_index (name);
which = tem ? tem->write_index : -1;
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream && !executing_string)
append_to_expansion_output (input_text_offset + 1);
#endif
get_rest_of_line (&index_entry);
ignore_blank_line ();
#if defined (HAVE_MACROS)
if (macro_expansion_output_stream && !executing_string)
{
int op_orig;
remember_itext (input_text, input_text_offset);
op_orig = output_paragraph_offset;
me_execute_string (index_entry);
me_execute_string ("\n");
output_paragraph_offset = op_orig;
}
#endif
if (which < 0)
{
line_error (_("Unknown index `%s'"), name);
free (index_entry);
}
else
{
INDEX_ELT *new = (INDEX_ELT *) xmalloc (sizeof (INDEX_ELT));
new->next = the_indices[which];
new->entry = index_entry;
new->node = current_node;
new->code = tem->code;
new->defining_line = line_number - 1;
new->defining_file = input_filename;
the_indices[which] = new;
}
}
#define INDEX_COMMAND_SUFFIX "index"
void
gen_index ()
{
char *name = xstrdup (command);
if (strlen (name) >= strlen ("index"))
name[strlen (name) - strlen ("index")] = 0;
index_add_arg (name);
free (name);
}
void
top_defindex (name, code)
char *name;
int code;
{
char *temp;
temp = (char *) xmalloc (1 + strlen (name) + strlen ("index"));
sprintf (temp, "%sindex", name);
define_user_command (temp, gen_index, 0);
defindex (name, code);
free (temp);
}
void
cm_defindex ()
{
gen_defindex (0);
}
void
cm_defcodeindex ()
{
gen_defindex (1);
}
void
gen_defindex (code)
int code;
{
char *name;
get_rest_of_line (&name);
if (find_index (name))
{
line_error (_("Index `%s' already exists"), name);
free (name);
return;
}
else
{
char *temp = (char *) alloca (1 + strlen (name) + strlen ("index"));
sprintf (temp, "%sindex", name);
define_user_command (temp, gen_index, 0);
defindex (name, code);
free (name);
}
}
void
cm_synindex ()
{
int source, target;
char *abbrev1, *abbrev2;
skip_whitespace ();
get_until_in_line (0, " ", &abbrev1);
target = find_index_offset (abbrev1);
skip_whitespace ();
get_until_in_line (0, " ", &abbrev2);
source = find_index_offset (abbrev2);
if (source < 0 || target < 0)
{
line_error (_("Unknown index `%s' and/or `%s' in @synindex"),
abbrev1, abbrev2);
}
else
{
name_index_alist[target]->write_index
= name_index_alist[source]->write_index;
}
free (abbrev1);
free (abbrev2);
}
void
cm_pindex ()
{
index_add_arg ("pg");
}
void
cm_vindex ()
{
index_add_arg ("vr");
}
void
cm_kindex ()
{
index_add_arg ("ky");
}
void
cm_cindex ()
{
index_add_arg ("cp");
}
void
cm_findex ()
{
index_add_arg ("fn");
}
void
cm_tindex ()
{
index_add_arg ("tp");
}
int
index_element_compare (element1, element2)
INDEX_ELT **element1, **element2;
{
return (strcasecmp ((*element1)->entry, (*element2)->entry));
}
void
make_index_entries_unique (array, count)
INDEX_ELT **array;
int count;
{
register int i, j;
INDEX_ELT **copy;
int counter = 1;
copy = (INDEX_ELT **)xmalloc ((1 + count) * sizeof (INDEX_ELT *));
for (i = 0, j = 0; i < count; i++)
{
if ((i == (count - 1)) ||
(array[i]->node != array[i + 1]->node) ||
(strcmp (array[i]->entry, array[i + 1]->entry) != 0))
copy[j++] = array[i];
else
{
free (array[i]->entry);
free (array[i]);
}
}
copy[j] = (INDEX_ELT *)NULL;
for (i = 0; copy[i] != (INDEX_ELT *)NULL; i++)
{
copy[i]->next = copy[i + 1];
if ((copy[i + 1] != (INDEX_ELT *)NULL) &&
(strcmp (copy[i]->entry, copy[i + 1]->entry) == 0))
{
char *new_entry_name;
new_entry_name = (char *)xmalloc (10 + strlen (copy[i]->entry));
sprintf (new_entry_name, "%s <%d>", copy[i]->entry, counter);
free (copy[i]->entry);
copy[i]->entry = new_entry_name;
counter++;
}
else
counter = 1;
array[i] = copy[i];
}
array[i] = (INDEX_ELT *)NULL;
free (copy);
}
INDEX_ELT **
sort_index (index)
INDEX_ELT *index;
{
INDEX_ELT **array;
INDEX_ELT *temp = index;
int count = 0;
int save_line_number = line_number;
char *save_input_filename = input_filename;
while (temp != (INDEX_ELT *) NULL)
{
count++;
temp = temp->next;
}
array = (INDEX_ELT **) xmalloc ((count + 1) * sizeof (INDEX_ELT *));
count = 0;
temp = index;
while (temp != (INDEX_ELT *) NULL)
{
array[count++] = temp;
line_number = array[count - 1]->defining_line;
input_filename = array[count - 1]->defining_file;
array[count - 1]->entry = expansion (temp->entry, index->code);
temp = temp->next;
}
array[count] = (INDEX_ELT *) NULL;
line_number = save_line_number;
input_filename = save_input_filename;
qsort (array, count, sizeof (INDEX_ELT *), index_element_compare);
make_index_entries_unique (array, count);
return (array);
}
int printing_index = 0;
void
cm_printindex ()
{
int item;
INDEX_ELT *index;
INDEX_ELT **array;
char *index_name;
unsigned line_length;
char *line;
int saved_inhibit_paragraph_indentation = inhibit_paragraph_indentation;
int saved_filling_enabled = filling_enabled;
close_paragraph ();
get_rest_of_line (&index_name);
index = index_list (index_name);
if (index == (INDEX_ELT *)-1)
{
line_error (_("Unknown index `%s' in @printindex"), index_name);
free (index_name);
return;
}
else
free (index_name);
printing_index = 1;
filling_enabled = 0;
inhibit_paragraph_indentation = 1;
array = sort_index (index);
close_paragraph ();
add_word (_("* Menu:\n\n"));
#if defined (HAVE_MACROS)
me_inhibit_expansion++;
#endif
line_length = 100;
line = xmalloc (line_length);
for (item = 0; (index = array[item]); item++)
{
char *index_node = index->node ? index->node : "(none)";
unsigned new_length = strlen (index->entry);
if (new_length < 37)
new_length = 37;
new_length += strlen (index_node) + 7;
if (new_length > line_length)
{
line_length = new_length;
line = xrealloc (line, line_length);
}
sprintf (line, "* %-37s %s.\n", index->entry, index_node);
line[2 + strlen (index->entry)] = ':';
insert_string (line);
flush_output ();
}
free (line);
#if defined (HAVE_MACROS)
me_inhibit_expansion--;
#endif
printing_index = 0;
free (array);
close_single_paragraph ();
filling_enabled = saved_filling_enabled;
inhibit_paragraph_indentation = saved_inhibit_paragraph_indentation;
}
void
define_user_command (name, proc, needs_braces_p)
char *name;
COMMAND_FUNCTION *proc;
int needs_braces_p;
{
int slot = user_command_array_len;
user_command_array_len++;
if (!user_command_array)
user_command_array = (COMMAND **) xmalloc (1 * sizeof (COMMAND *));
user_command_array = (COMMAND **) xrealloc (user_command_array,
(1 + user_command_array_len) *
sizeof (COMMAND *));
user_command_array[slot] = (COMMAND *) xmalloc (sizeof (COMMAND));
user_command_array[slot]->name = xstrdup (name);
user_command_array[slot]->proc = proc;
user_command_array[slot]->argument_in_braces = needs_braces_p;
}
#define SeparateNode 0
#define EndNode 1
int footnote_style = EndNode;
int first_footnote_this_node = 1;
int footnote_count = 0;
int
set_footnote_style (string)
char *string;
{
if ((strcasecmp (string, "separate") == 0) ||
(strcasecmp (string, "MN") == 0))
footnote_style = SeparateNode;
else if ((strcasecmp (string, "end") == 0) ||
(strcasecmp (string, "EN") == 0))
footnote_style = EndNode;
else
return (-1);
return (0);
}
void
cm_footnotestyle ()
{
char *arg;
get_rest_of_line (&arg);
if (!footnote_style_preset && set_footnote_style (arg) != 0)
line_error ("Bad argument to %c%s", COMMAND_PREFIX, command);
free (arg);
}
typedef struct fn
{
struct fn *next;
char *marker;
char *note;
} FN;
FN *pending_notes = (FN *) NULL;
void
remember_note (marker, note)
char *marker, *note;
{
FN *temp = (FN *) xmalloc (sizeof (FN));
temp->marker = xstrdup (marker);
temp->note = xstrdup (note);
temp->next = pending_notes;
pending_notes = temp;
footnote_count++;
}
void
free_pending_notes ()
{
FN *temp;
while ((temp = pending_notes) != (FN *) NULL)
{
free (temp->marker);
free (temp->note);
pending_notes = pending_notes->next;
free (temp);
}
first_footnote_this_node = 1;
footnote_count = 0;
}
void
cm_footnote ()
{
char *marker;
char *note;
get_until ("{", &marker);
canon_white (marker);
if (macro_expansion_output_stream && !executing_string)
append_to_expansion_output (input_text_offset + 1);
if (curchar () != '{')
{
line_error (_("`%c%s' needs an argument `{...}', not just `%s'"),
COMMAND_PREFIX, command, marker);
free (marker);
return;
}
else
{
int len;
int braces = 1;
int loc = ++input_text_offset;
while (braces)
{
if (loc == size_of_input_text)
{
line_error (_("No closing brace for footnote `%s'"), marker);
return;
}
if (input_text[loc] == '{')
braces++;
else if (input_text[loc] == '}')
braces--;
else if (input_text[loc] == '\n')
line_number++;
loc++;
}
len = (loc - input_text_offset) - 1;
note = (char *)xmalloc (len + 1);
strncpy (note, &input_text[input_text_offset], len);
note[len] = 0;
input_text_offset = loc;
}
if (macro_expansion_output_stream && !executing_string)
{
int op_orig;
remember_itext (input_text, input_text_offset);
op_orig = output_paragraph_offset;
me_execute_string (note);
write_region_to_macro_output ("}", 0, 1);
output_paragraph_offset = op_orig;
}
if (!current_node || !*current_node)
{
line_error (_("Footnote defined without parent node"));
free (marker);
free (note);
return;
}
if (!*marker)
{
free (marker);
if (number_footnotes)
{
marker = (char *)xmalloc (10);
sprintf (marker, "%d", current_footnote_number);
current_footnote_number++;
}
else
marker = xstrdup ("*");
}
remember_note (marker, note);
switch (footnote_style)
{
case SeparateNode:
add_word_args ("(%s)", marker);
if (first_footnote_this_node)
{
char *temp_string;
temp_string = (char *)
xmalloc ((strlen (current_node)) + (strlen (_("-Footnotes"))) + 1);
add_word_args (" (*note %s-Footnotes::)", current_node);
strcpy (temp_string, current_node);
strcat (temp_string, "-Footnotes");
remember_node_reference (temp_string, line_number, followed_reference);
free (temp_string);
first_footnote_this_node = 0;
}
break;
case EndNode:
add_word_args ("(%s)", marker);
break;
default:
break;
}
free (marker);
free (note);
}
int already_outputting_pending_notes = 0;
void
output_pending_notes ()
{
FN *footnote = pending_notes;
if (!pending_notes)
return;
switch (footnote_style)
{
case SeparateNode:
{
char *old_current_node = current_node;
char *old_command = xstrdup (command);
already_outputting_pending_notes++;
execute_string ("%cnode %s-Footnotes,,,%s\n",
COMMAND_PREFIX, current_node, current_node);
already_outputting_pending_notes--;
current_node = old_current_node;
free (command);
command = old_command;
}
break;
case EndNode:
close_paragraph ();
in_fixed_width_font++;
execute_string (_("---------- Footnotes ----------\n\n"));
in_fixed_width_font--;
break;
}
{
FN **array = (FN **) xmalloc ((footnote_count + 1) * sizeof (FN *));
array[footnote_count] = (FN *) NULL;
while (--footnote_count > -1)
{
array[footnote_count] = footnote;
footnote = footnote->next;
}
filling_enabled = 1;
indented_fill = 1;
while ((footnote = array[++footnote_count]))
{
execute_string ("(%s) %s", footnote->marker, footnote->note);
close_paragraph ();
}
close_paragraph ();
free (array);
}
}
#if defined (HAVE_MACROS)
MACRO_DEF **macro_list = (MACRO_DEF **)NULL;
int macro_list_len = 0;
int macro_list_size = 0;
MACRO_DEF *
find_macro (name)
char *name;
{
register int i;
register MACRO_DEF *def;
def = (MACRO_DEF *)NULL;
for (i = 0; macro_list && (def = macro_list[i]); i++)
{
if ((!def->inhibited) && (strcmp (def->name, name) == 0))
break;
}
return (def);
}
void
add_macro (name, arglist, body, source_file, source_lineno, flags)
char *name;
char **arglist;
char *body;
char *source_file;
int source_lineno, flags;
{
register MACRO_DEF *def;
def = find_macro (name);
if (!def)
{
if (macro_list_len + 2 >= macro_list_size)
macro_list = (MACRO_DEF **)xrealloc
(macro_list, ((macro_list_size += 10) * sizeof (MACRO_DEF *)));
macro_list[macro_list_len] = (MACRO_DEF *)xmalloc (sizeof (MACRO_DEF));
macro_list[macro_list_len + 1] = (MACRO_DEF *)NULL;
def = macro_list[macro_list_len];
macro_list_len += 1;
def->name = name;
}
else
{
char *temp_filename = input_filename;
int temp_line = line_number;
warning (_("macro `%s' previously defined"), name);
input_filename = def->source_file;
line_number = def->source_lineno;
warning (_("here is the previous definition of `%s'"), name);
input_filename = temp_filename;
line_number = temp_line;
if (def->arglist)
{
register int i;
for (i = 0; def->arglist[i]; i++)
free (def->arglist[i]);
free (def->arglist);
}
free (def->source_file);
free (def->body);
}
def->source_file = xstrdup (source_file);
def->source_lineno = source_lineno;
def->body = body;
def->arglist = arglist;
def->inhibited = 0;
def->flags = flags;
}
MACRO_DEF *
delete_macro (name)
char *name;
{
register int i;
register MACRO_DEF *def;
def = (MACRO_DEF *)NULL;
for (i = 0; macro_list && (def = macro_list[i]); i++)
if (strcmp (def->name, name) == 0)
{
memmove (macro_list + i, macro_list + i + 1,
((macro_list_len + 1) - i) * sizeof (MACRO_DEF *));
macro_list_len--;
break;
}
return (def);
}
int braces_required_for_macro_args = 0;
char **
get_macro_args (def)
MACRO_DEF *def;
{
register int i;
char *word;
for (i = input_text_offset; i < size_of_input_text; i++)
if (!cr_or_whitespace (input_text[i]))
break;
if (input_text[i] != '{')
{
if (braces_required_for_macro_args)
{
return ((char **)NULL);
}
else
{
if (def->arglist && def->arglist[0] && !def->arglist[1])
{
char **arglist;
get_rest_of_line (&word);
if (input_text[input_text_offset - 1] == '\n')
{
input_text_offset--;
line_number--;
}
arglist = (char **)xmalloc (2 * sizeof (char *));
arglist[0] = word;
arglist[1] = (char *)NULL;
return (arglist);
}
else
{
return ((char **)NULL);
}
}
}
return (get_brace_args (def->flags & ME_QUOTE_ARG));
}
char *
apply (named, actuals, body)
char **named, **actuals, *body;
{
register int i;
int new_body_index, new_body_size;
char *new_body, *text;
int length_of_actuals;
length_of_actuals = array_len (actuals);
new_body_size = strlen (body);
new_body = (char *)xmalloc (1 + new_body_size);
i = 0; new_body_index = 0;
while (1)
{
if (!body[i])
break;
if (body[i] != '\\')
new_body[new_body_index++] = body[i++];
else
{
char *param;
int param_start, which, len;
param_start = ++i;
while ((body[i]) && (body[i] != '\\'))
i++;
len = i - param_start;
param = (char *)xmalloc (1 + len);
memcpy (param, body + param_start, len);
param[len] = 0;
if (body[i])
i++;
for (which = 0; named && named[which]; which++)
if (strcmp (named[which], param) == 0)
break;
if (named && named[which])
{
if (which < length_of_actuals)
text = actuals[which];
else
text = (char *)NULL;
if (!text)
text = "";
len = strlen (text);
}
else
{
i = body[i] ? (i - 1) : i;
len++;
text = xmalloc (1 + len);
sprintf (text, "\\%s", param);
}
if ((2 + strlen (param)) < len)
{
new_body_size += len + 1;
new_body = xrealloc (new_body, new_body_size);
}
free (param);
strcpy (new_body + new_body_index, text);
new_body_index += len;
if (!named || !named[which])
free (text);
}
}
new_body[new_body_index] = 0;
return (new_body);
}
void
execute_macro (def)
MACRO_DEF *def;
{
char **arglist;
int num_args;
char *execution_string = (char *)NULL;
if (macro_expansion_output_stream && !executing_string && !me_inhibit_expansion)
me_append_before_this_command ();
num_args = array_len (def->arglist);
arglist = get_macro_args (def);
if (num_args < array_len (arglist))
{
free_array (arglist);
line_error (_("Macro `%s' called with too many args"), def->name);
return;
}
if (def->body)
execution_string = apply (def->arglist, arglist, def->body);
free_array (arglist);
if (def->body)
{
if (macro_expansion_output_stream && !executing_string && !me_inhibit_expansion)
{
remember_itext (input_text, input_text_offset);
me_execute_string (execution_string);
}
else
execute_string ("%s", execution_string);
free (execution_string);
}
}
void
cm_macro ()
{
register int i;
char *name, **arglist, *body, *line;
int body_size, body_index;
int depth = 1;
int defining_line = line_number;
int flags = 0;
arglist = (char **)NULL;
body = (char *)NULL;
body_size = 0;
body_index = 0;
if (macro_expansion_output_stream && !executing_string)
me_append_before_this_command ();
skip_whitespace ();
{
int start = input_text_offset;
int len;
for (i = start;
(i < size_of_input_text) &&
(input_text[i] != '{') &&
(!cr_or_whitespace (input_text[i]));
i++);
len = i - start;
name = (char *)xmalloc (1 + len);
strncpy (name, input_text + start, len);
name[len] = 0;
input_text_offset = i;
}
skip_whitespace ();
if (curchar () == '{')
{
int arglist_index = 0, arglist_size = 0;
int gathering_words = 1;
char *word = (char *)NULL;
int character;
input_text_offset++;
skip_whitespace_and_newlines ();
while (gathering_words)
{
int len;
for (i = input_text_offset;
(character = input_text[i]);
i++)
{
switch (character)
{
case '\n':
line_number++;
case ' ':
case '\t':
case ',':
case '}':
len = i - input_text_offset;
word = (char *)xmalloc (1 + len);
strncpy (word, input_text + input_text_offset, len);
word[len] = 0;
input_text_offset = i;
while ((character = curchar ())
&& character != ','
&& character != '}')
{
input_text_offset++;
if (character == '\n')
line_number++;
}
if ((arglist_index + 2) >= arglist_size)
arglist = (char **)xrealloc
(arglist, (arglist_size += 10) * sizeof (char *));
arglist[arglist_index++] = word;
arglist[arglist_index] = (char *)NULL;
break;
}
if (character == '}')
{
input_text_offset++;
gathering_words = 0;
break;
}
if (character == ',')
{
input_text_offset++;
skip_whitespace_and_newlines ();
i = input_text_offset - 1;
}
}
}
}
skip_whitespace_and_newlines ();
while (depth)
{
if ((input_text_offset + 9) > size_of_input_text)
{
int temp_line = line_number;
line_number = defining_line;
line_error (_("%cend macro not found"), COMMAND_PREFIX);
line_number = temp_line;
return;
}
get_rest_of_line (&line);
if ((*line == COMMAND_PREFIX) && (depth == 1) &&
(strncmp (line + 1, "allow-recursion", 15) == 0) &&
(line[16] == 0 || whitespace (line[16])))
{
for (i = 16; whitespace (line[i]); i++);
strcpy (line, line + i);
flags |= ME_RECURSE;
if (!*line)
{
free (line);
continue;
}
}
if ((*line == COMMAND_PREFIX) && (depth == 1) &&
(strncmp (line + 1, "quote-arg", 9) == 0) &&
(line[10] == 0 || whitespace (line[10])))
{
for (i = 10; whitespace (line[i]); i++);
strcpy (line, line + i);
if (arglist && arglist[0] && !arglist[1])
{
flags |= ME_QUOTE_ARG;
if (!*line)
{
free (line);
continue;
}
}
else
{
line_error (_("%cquote-arg only useful when the macro takes a single argument"),
COMMAND_PREFIX);
}
}
if ((*line == COMMAND_PREFIX) &&
(strncmp (line + 1, "macro ", 6) == 0))
depth++;
if ((*line == COMMAND_PREFIX) &&
(strncmp (line + 1, "end macro", 9) == 0))
depth--;
if (depth)
{
if ((body_index + strlen (line) + 3) >= body_size)
body = (char *)xrealloc
(body, body_size += 3 + strlen (line));
strcpy (body + body_index, line);
body_index += strlen (line);
body[body_index++] = '\n';
body[body_index] = 0;
}
free (line);
}
if (!body)
{
body = (char *)malloc(1);
*body = 0;
}
if (body && strlen (body))
body[strlen (body) - 1] = 0;
add_macro (name, arglist, body, input_filename, defining_line, flags);
if (macro_expansion_output_stream && !executing_string)
remember_itext (input_text, input_text_offset);
}
void
cm_unmacro ()
{
register int i;
char *line, *name;
MACRO_DEF *def;
if (macro_expansion_output_stream && !executing_string)
me_append_before_this_command ();
get_rest_of_line (&line);
for (i = 0; line[i] && !whitespace (line[i]); i++);
name = (char *)xmalloc (i + 1);
strncpy (name, line, i);
name[i] = 0;
def = delete_macro (name);
if (def)
{
free (def->source_file);
free (def->name);
free (def->body);
if (def->arglist)
{
register int i;
for (i = 0; def->arglist[i]; i++)
free (def->arglist[i]);
free (def->arglist);
}
free (def);
}
free (line);
free (name);
if (macro_expansion_output_stream && !executing_string)
remember_itext (input_text, input_text_offset);
}
ITEXT *
remember_itext (pointer, offset)
char *pointer;
int offset;
{
register int i;
ITEXT *itext = (ITEXT *)NULL;
if (!itext_info)
{
itext_info = (ITEXT **)xmalloc ((itext_size = 10) * sizeof (ITEXT *));
for (i = 0; i < itext_size; i++)
itext_info[i] = (ITEXT *)NULL;
}
for (i = 0; i < itext_size; i++)
if ((itext_info[i] != (ITEXT *)NULL) &&
(itext_info[i]->pointer == pointer))
{
itext = itext_info[i];
itext_info[i]->offset = offset;
break;
}
if (i == itext_size)
{
for (i = 0; i < itext_size; i++)
if (itext_info[i] == (ITEXT *)NULL)
break;
if (i == itext_size)
{
register int j;
itext_info = (ITEXT **)xrealloc
(itext_info, (itext_size += 10) * sizeof (ITEXT *));
for (j = i; j < itext_size; j++)
itext_info[j] = (ITEXT *)NULL;
}
itext_info[i] = (ITEXT *)xmalloc (sizeof (ITEXT));
itext_info[i]->pointer = pointer;
itext_info[i]->offset = offset;
itext = itext_info[i];
}
return (itext);
}
void
forget_itext (pointer)
char *pointer;
{
register int i;
for (i = 0; i < itext_size; i++)
if (itext_info[i] && (itext_info[i]->pointer == pointer))
{
free (itext_info[i]);
itext_info[i] = (ITEXT *)NULL;
break;
}
}
void
me_append_before_this_command ()
{
register int i;
for (i = input_text_offset; i && (input_text[i] != COMMAND_PREFIX); i--);
maybe_write_itext (input_text, i);
}
void
me_execute_string (execution_string)
char *execution_string;
{
pushfile ();
input_text_offset = 0;
input_text = execution_string;
input_filename = xstrdup (input_filename);
size_of_input_text = strlen (execution_string);
remember_itext (execution_string, 0);
me_executing_string++;
reader_loop ();
popfile ();
me_executing_string--;
}
void
append_to_expansion_output (offset)
int offset;
{
register int i;
ITEXT *itext = (ITEXT *)NULL;
for (i = 0; i < itext_size; i++)
if (itext_info[i] && itext_info[i]->pointer == input_text)
{
itext = itext_info[i];
break;
}
if (!itext)
return;
if (offset > itext->offset)
{
write_region_to_macro_output
(input_text, itext->offset, offset);
remember_itext (input_text, offset);
}
}
void
maybe_write_itext (pointer, offset)
char *pointer;
int offset;
{
register int i;
ITEXT *itext = (ITEXT *)NULL;
for (i = 0; i < itext_size; i++)
if (itext_info[i] && (itext_info[i]->pointer == pointer))
{
itext = itext_info[i];
break;
}
if (itext && (itext->offset < offset))
{
write_region_to_macro_output (itext->pointer, itext->offset, offset);
remember_itext (pointer, offset);
}
}
void
write_region_to_macro_output (string, start, end)
char *string;
int start, end;
{
if (macro_expansion_output_stream)
fwrite (string + start, 1, end - start, macro_expansion_output_stream);
}
#endif
int
array_len (array)
char **array;
{
register int i = 0;
if (array)
for (i = 0; array[i] != (char *)NULL; i++);
return (i);
}
void
free_array (array)
char **array;
{
if (array)
{
register int i;
for (i = 0; array[i] != (char *)NULL; i++)
free (array[i]);
free (array);
}
}
char **
get_brace_args (quote_single)
int quote_single;
{
char **arglist, *word;
int arglist_index, arglist_size;
int character, escape_seen, start;
int depth = 1;
skip_whitespace_and_newlines ();
input_text_offset++;
arglist = (char **)NULL;
arglist_index = arglist_size = 0;
get_arg:
skip_whitespace_and_newlines ();
start = input_text_offset;
escape_seen = 0;
while ((character = curchar ()))
{
if (character == '\\')
{
input_text_offset += 2;
escape_seen = 1;
}
else if (character == '{')
{
depth++;
input_text_offset++;
}
else if ((character == ',' && !quote_single) ||
((character == '}') && depth == 1))
{
int len = input_text_offset - start;
if (len || (character != '}'))
{
word = (char *)xmalloc (1 + len);
strncpy (word, input_text + start, len);
word[len] = 0;
if (escape_seen)
{
register int i;
for (i = 0; word[i]; i++)
if (word[i] == '\\')
memmove (word + i, word + i + 1,
1 + strlen (word + i + 1));
}
if (arglist_index + 2 >= arglist_size)
arglist = (char **)xrealloc
(arglist, (arglist_size += 10) * sizeof (char *));
arglist[arglist_index++] = word;
arglist[arglist_index] = (char *)NULL;
}
input_text_offset++;
if (character == '}')
break;
else
goto get_arg;
}
else if (character == '}')
{
depth--;
input_text_offset++;
}
else
{
input_text_offset++;
if (character == '\n') line_number++;
}
}
return (arglist);
}
char *
extract_colon_unit (string, index)
char *string;
int *index;
{
int i, start;
i = *index;
if (!string || (i >= strlen (string)))
return ((char *)NULL);
if (i && string[i] == ':')
i++;
start = i;
while (string[i] && string[i] != ':') i++;
*index = i;
if (i == start)
{
if (string[i])
(*index)++;
return (xstrdup (""));
}
else
{
char *value;
value = (char *)xmalloc (1 + (i - start));
strncpy (value, &string[start], (i - start));
value [i - start] = 0;
return (value);
}
}
char *
get_file_info_in_path (filename, path, finfo)
char *filename, *path;
struct stat *finfo;
{
char *dir;
int result, index = 0;
if (path == (char *)NULL)
path = ".";
if (*filename == '/' ||
(*filename == '.' &&
(filename[1] == '/' ||
(filename[1] == '.' && filename[2] == '/')))
#ifdef WIN32
|| (isalpha (*filename) && filename [1] == ':'
&& (filename [2] == '/' || filename [2] == '\\'))
#endif
)
{
if (stat (filename, finfo) == 0)
return (xstrdup (filename));
else
return ((char *)NULL);
}
while ((dir = extract_colon_unit (path, &index)))
{
char *fullpath;
if (!*dir)
{
free (dir);
dir = xstrdup (".");
}
fullpath = (char *)xmalloc (2 + strlen (dir) + strlen (filename));
sprintf (fullpath, "%s/%s", dir, filename);
free (dir);
result = stat (fullpath, finfo);
if (result == 0)
return (fullpath);
else
free (fullpath);
}
return NULL;
}