diff options
Diffstat (limited to 'contrib/texinfo/makeinfo/makeinfo.c')
-rw-r--r-- | contrib/texinfo/makeinfo/makeinfo.c | 6226 |
1 files changed, 3256 insertions, 2970 deletions
diff --git a/contrib/texinfo/makeinfo/makeinfo.c b/contrib/texinfo/makeinfo/makeinfo.c index f30d366..ef892db 100644 --- a/contrib/texinfo/makeinfo/makeinfo.c +++ b/contrib/texinfo/makeinfo/makeinfo.c @@ -1,7 +1,8 @@ -/* Makeinfo -- convert texinfo format files into info files. - $Id: makeinfo.c,v 1.37 1996/10/04 18:20:52 karl Exp $ +/* Makeinfo -- convert Texinfo source files into Info files. + $Id: makeinfo.c,v 1.60 1998/02/25 20:36:22 karl Exp $ - Copyright (C) 1987, 92, 93, 94, 95, 96 Free Software Foundation, Inc. + Copyright (C) 1987, 92, 93, 94, 95, 96, 97, 98 + Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,12 +18,58 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - Makeinfo is authored by Brian Fox (bfox@ai.mit.edu). */ + Makeinfo was authored by Brian Fox (bfox@ai.mit.edu). */ + +/* Indent #pragma so that older Cpp's don't try to parse it. */ +#ifdef _AIX + #pragma alloca +#endif /* _AIX */ int major_version = 1; -int minor_version = 67; +int minor_version = 68; + +#include "system.h" +#include "getopt.h" + +#ifdef TM_IN_SYS_TIME +#include <sys/time.h> +#else +#include <time.h> +#endif /* !TM_IN_SYS_TIME */ + +#ifdef __GNUC__ +# undef alloca +# define alloca __builtin_alloca +#else +# ifdef HAVE_ALLOCA_H +# include <alloca.h> +# else +# ifndef _AIX +char *alloca (); +# endif +# endif +#endif + +/* We'd like to take advantage of _doprnt if it's around, a la error.c, + but then we'd have no VA_SPRINTF. */ +#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 /* not HAVE_VPRINTF */ +# 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 -/* You can change some of the behaviour of Makeinfo by changing the +/* You can change some of the behavior of Makeinfo by changing the following defines: */ /* Define INDENT_PARAGRAPHS_IN_TABLE if you want the paragraphs which @@ -50,113 +97,48 @@ int minor_version = 67; #define DEFAULT_PARAGRAPH_SPACING 1 /* Define HAVE_MACROS to enable the macro facility of Texinfo. Using this - facility, users can create their own command procedures with arguments. */ + facility, users can create their own command procedures with + arguments. Must always be defined. */ #define HAVE_MACROS -/* Indent #pragma so that older Cpp's don't try to parse it. */ -#if defined (_AIX) - # pragma alloca -#endif /* _AIX */ - -#include <stdio.h> -#include <sys/types.h> -#include <ctype.h> -#include <sys/stat.h> -#include <pwd.h> -#include <errno.h> - -#if defined (HAVE_VARARGS_H) -#include <varargs.h> -#endif /* HAVE_VARARGS_H */ -#include "getopt.h" - -#if defined (HAVE_UNISTD_H) -#include <unistd.h> -#endif /* HAVE_UNISTD_H */ - -#if defined (VMS) -#include <perror.h> -#endif - -#if defined (HAVE_STRING_H) -#include <string.h> -#else -#include <strings.h> -#endif /* !HAVE_STRING_H */ - -#if defined (TM_IN_SYS_TIME) -#include <sys/time.h> -#else -#include <time.h> -#endif /* !TM_IN_SYS_TIME */ - -#if defined (HAVE_SYS_FCNTL_H) -#include <sys/fcntl.h> -#else -#include <fcntl.h> -#endif /* !HAVE_SYS_FCNTL_H */ - -#if defined (HAVE_SYS_FILE_H) -#include <sys/file.h> -#endif /* HAVE_SYS_FILE_H */ - -#if defined (__GNUC__) -#define alloca __builtin_alloca -#else -#if defined(HAVE_ALLOCA_H) -#include <alloca.h> -#else /* !HAVE_ALLOCA_H */ -#if !defined (_AIX) -extern char *alloca (); -#endif /* !_AIX */ -#endif /* !HAVE_ALLOCA_H */ -#endif /* !__GNUC__ */ - -void *xmalloc (), *xrealloc (); -#if defined (__osf__) -extern void *malloc (), *realloc (); -#endif /* __osf__ */ - -char **get_brace_args (); -int array_len (); -void free_array (); -static void isolate_nodename (); - #define COMPILING_MAKEINFO #include "makeinfo.h" -/* Non-zero means that we are currently hacking the insides of an +/* Nonzero means that we are currently hacking the insides of an insertion which would use a fixed width font. */ static int in_fixed_width_font = 0; -/* Non-zero means that start_paragraph () MUST be called before we pay +/* Nonzero means that start_paragraph () MUST be called before we pay any attention to close_paragraph () calls. */ int must_start_paragraph = 0; -/* Non-zero means a string is in execution, as opposed to a file. */ +/* Nonzero means a string is in execution, as opposed to a file. */ static int executing_string = 0; +/* Nonzero means a macro string is in execution, as opposed to a file. */ +static int me_executing_string = 0; + #if defined (HAVE_MACROS) /* If non-NULL, this is an output stream to write the full macro expansion - of the input text to. The resultant file is another texinfo file, but + of the input text to. The result is another texinfo file, but missing @include, @infoinclude, @macro, and macro invocations. Instead, all of the text is placed within the file. */ FILE *macro_expansion_output_stream = (FILE *)NULL; +char *macro_expansion_filename; /* Here is a structure used to remember input text strings and offsets within them. */ typedef struct { - char *pointer; /* Pointer to the input text. */ - int offset; /* Offset of the last character output. */ + char *pointer; /* Pointer to the input text. */ + int offset; /* Offset of the last character output. */ } ITEXT; static ITEXT **itext_info = (ITEXT **)NULL; static int itext_size = 0; -/* Non-zero means to inhibit the writing of macro expansions to the output - stream. This is used in special cases where the output has already been - written. */ +/* Nonzero means to inhibit writing macro expansions to the output + stream, because it has already been written. */ int me_inhibit_expansion = 0; ITEXT *remember_itext (); @@ -165,19 +147,17 @@ void append_to_expansion_output (), write_region_to_macro_output (); void maybe_write_itext (), me_execute_string (); #endif /* HAVE_MACROS */ -/* Some systems don't declare this function in pwd.h. */ -struct passwd *getpwnam (); /* **************************************************************** */ -/* */ -/* Global Variables */ -/* */ +/* */ +/* Global Variables */ +/* */ /* **************************************************************** */ /* Global pointer to argv[0]. */ char *progname; -/* Return non-zero if STRING is the text at input_text + input_text_offset, +/* Return nonzero if STRING is the text at input_text + input_text_offset, else zero. */ #define looking_at(string) \ (strncmp (input_text + input_text_offset, string, strlen (string)) == 0) @@ -196,24 +176,20 @@ char *command_output_filename = (char *)NULL; with @include. This can be controlled with the `-I' option to makeinfo. */ char *include_files_path = (char *)NULL; -/* Current output stream. */ -FILE *output_stream; - /* Position in the output file. */ int output_position; #define INITIAL_PARAGRAPH_SPACE 5000 int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE; -/* Filling.. */ -/* Non-zero indicates that filling will take place on long lines. */ +/* Nonzero indicates that filling will take place on long lines. */ int filling_enabled = 1; -/* Non-zero means that words are not to be split, even in long lines. This +/* Nonzero means that words are not to be split, even in long lines. This gets changed for cm_w (). */ int non_splitting_words = 0; -/* Non-zero indicates that filling a line also indents the new line. */ +/* Nonzero indicates that filling a line also indents the new line. */ int indented_fill = 0; /* The amount of indentation to add at the starts of paragraphs. @@ -226,7 +202,7 @@ int indented_fill = 0; this is 3. */ int paragraph_start_indent = PARAGRAPH_START_INDENT; -/* Non-zero means that the use of paragraph_start_indent is inhibited. +/* Nonzero means that the use of paragraph_start_indent is inhibited. @example uses this to line up the left columns of the example text. A negative value for this variable is incremented each time it is used. @noindent uses this to inhibit indentation for a single paragraph. */ @@ -240,17 +216,17 @@ int pending_indent = 0; /* The amount that indentation increases/decreases by. */ int default_indentation_increment = DEFAULT_INDENTATION_INCREMENT; -/* Non-zero indicates that indentation is temporarily turned off. */ +/* Nonzero indicates that indentation is temporarily turned off. */ int no_indent = 1; -/* Non-zero means forcing output text to be flushright. */ +/* Nonzero means forcing output text to be flushright. */ int force_flush_right = 0; -/* Non-zero means that the footnote style for this document was set on +/* Nonzero means that the footnote style for this document was set on the command line, which overrides any other settings. */ int footnote_style_preset = 0; -/* Non-zero means that we automatically number footnotes that have no +/* Nonzero means that we automatically number footnotes that have no specified marker. */ int number_footnotes = 1; @@ -267,16 +243,16 @@ int command_index; /* A search string which is used to find a line defining a node. */ char node_search_string[] = - { '\n', COMMAND_PREFIX, 'n', 'o', 'd', 'e', ' ', '\0' }; + { '\n', COMMAND_PREFIX, 'n', 'o', 'd', 'e', ' ', 0 }; /* A search string which is used to find a line defining a menu. */ char menu_search_string[] = - { '\n', COMMAND_PREFIX, 'm', 'e', 'n', 'u', '\0' }; + { '\n', COMMAND_PREFIX, 'm', 'e', 'n', 'u', 0 }; /* A search string which is used to find the first @setfilename. */ char setfilename_search[] = { COMMAND_PREFIX, - 's', 'e', 't', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', '\0' }; + 's', 'e', 't', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', 0 }; /* A stack of file information records. If a new file is read in with "@input", we remember the old input file state on this stack. */ @@ -306,15 +282,15 @@ char *node_filename = (char *)NULL; typedef struct tentry { struct tentry *next_ent; - char *node; /* name of this node. */ - char *prev; /* name of "Prev:" for this node. */ - char *next; /* name of "Next:" for this node. */ - char *up; /* name of "Up:" for this node. */ - int position; /* output file position of this node. */ - int line_no; /* defining line in source file. */ - char *filename; /* The file that this node was found in. */ - int touched; /* non-zero means this node has been referenced. */ - int flags; /* Room for growth. Right now, contains 1 bit. */ + char *node; /* name of this node. */ + char *prev; /* name of "Prev:" for this node. */ + char *next; /* name of "Next:" for this node. */ + char *up; /* name of "Up:" for this node. */ + int position; /* output file position of this node. */ + int line_no; /* defining line in source file. */ + char *filename; /* The file that this node was found in. */ + int touched; /* Nonzero means this node has been referenced. */ + int flags; /* Room for growth. Right now, contains 1 bit. */ } TAG_ENTRY; /* If node-a has a "Next" for node-b, but node-b has no "Prev" for node-a, @@ -324,24 +300,30 @@ typedef struct tentry #define PREV_ERROR 0x1 #define NEXT_ERROR 0x2 #define UP_ERROR 0x4 -#define NO_WARN 0x8 -#define IS_TOP 0x10 +#define NO_WARN 0x8 +#define IS_TOP 0x10 TAG_ENTRY *tag_table = (TAG_ENTRY *) NULL; +/* Values for calling handle_variable_internal (). */ +#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 +#define ME_RECURSE 0x01 +#define ME_QUOTE_ARG 0x02 /* Macro definitions for user-defined commands. */ typedef struct { - char *name; /* Name of the macro. */ - char **arglist; /* Args to replace when executing. */ - char *body; /* Macro body. */ - char *source_file; /* File where this macro is defined. */ - int source_lineno; /* Line number within FILENAME. */ - int inhibited; /* Non-zero means make find_macro () fail. */ - int flags; /* ME_RECURSE, ME_QUOTE_ARG, etc. */ + char *name; /* Name of the macro. */ + char **arglist; /* Args to replace when executing. */ + char *body; /* Macro body. */ + char *source_file; /* File where this macro is defined. */ + int source_lineno; /* Line number within FILENAME. */ + int inhibited; /* Nonzero means make find_macro () fail. */ + int flags; /* ME_RECURSE, ME_QUOTE_ARG, etc. */ } MACRO_DEF; void add_macro (), execute_macro (); @@ -361,12 +343,12 @@ enum reftype typedef struct node_ref { struct node_ref *next; - char *node; /* Name of node referred to. */ - char *containing_node; /* Name of node containing this reference. */ - int line_no; /* Line number where the reference occurs. */ - int section; /* Section level where the reference occurs. */ - char *filename; /* Name of file where the reference occurs. */ - enum reftype type; /* Type of reference, either menu or note. */ + char *node; /* Name of node referred to. */ + char *containing_node; /* Name of node containing this reference. */ + int line_no; /* Line number where the reference occurs. */ + int section; /* Section level where the reference occurs. */ + char *filename; /* Name of file where the reference occurs. */ + enum reftype type; /* Type of reference, either menu or note. */ } NODE_REF; /* The linked list of such structures. */ @@ -378,21 +360,24 @@ int in_menu = 0; /* Flag which tells us how to examine menu lines. */ int in_detailmenu = 0; -/* Non-zero means that we have seen "@top" once already. */ +/* Nonzero means that we have seen "@top" once already. */ int top_node_seen = 0; -/* Non-zero means that we have seen a non-"@top" node already. */ +/* Nonzero means that we have seen a non-"@top" node already. */ int non_top_node_seen = 0; /* Flags controlling the operation of the program. */ +/* Default is to remove output if there were errors. */ +int force = 0; + /* Default is to notify users of bad choices. */ int print_warnings = 1; /* Default is to check node references. */ int validating = 1; -/* Non-zero means do not output "Node: Foo" for node separations. */ +/* Nonzero means do not output "Node: Foo" for node separations. */ int no_headers = 0; /* Number of errors that we tolerate on a given fileset. */ @@ -401,11 +386,11 @@ int max_error_level = 100; /* Maximum number of references to a single node before complaining. */ int reference_warning_limit = 1000; -/* Non-zero means print out information about what is going on when it +/* Nonzero means print out information about what is going on when it is going on. */ int verbose_mode = 0; -/* Non-zero means to be relaxed about the input file. This is useful when +/* Nonzero means to be relaxed about the input file. This is useful when we can successfully format the input, but it doesn't strictly match our somewhat pedantic ideas of correctness. Right now, it affects what @table and @itemize do without arguments. */ @@ -431,17 +416,12 @@ typedef struct brace_element BRACE_ELEMENT *brace_stack = (BRACE_ELEMENT *) NULL; -/* Forward declarations. */ -#if !defined (HAVE_STRDUP) -extern char *strdup (); -#endif /* HAVE_STRDUP */ - extern void do_multitable (); void print_version_info (); void usage (); void push_node_filename (), pop_node_filename (); -void remember_error (); +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 (); @@ -449,21 +429,34 @@ 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 execute_string (); 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_args (), add_word (), add_char (), insert (), flush_output (); +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 (); +void do_flush_right_indentation (), discard_insertions (); void start_paragraph (), indent (); +#if defined (VA_FPRINTF) && __STDC__ +/* Unfortunately we must use prototypes if we are to use <stdarg.h>. */ +void add_word_args (char *, ...); +void execute_string (char *, ...); +#else +void add_word_args (); +void execute_string (); +#endif /* will not use prototypes */ void insert_self (), insert_space (), cm_ignore_line (); @@ -471,8 +464,8 @@ 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_angle_brackets (), cm_no_op (), cm_not_fixed_width (), - cm_strong (), cm_var (), cm_w (); + 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 (); /* Sectioning. */ void @@ -483,21 +476,22 @@ void cm_heading (), cm_chapheading (), cm_subheading (), cm_subsubheading (), cm_majorheading (), cm_raisesections (), cm_lowersections (); -/* All @defxxx commands map to cm_defun, most accent commands map to +/* All @def... commands map to cm_defun, most accent commands map to cm_accent, most non-English letters map to cm_special_char. */ 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_quotation (), cm_display (), cm_itemize (), + 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_kindex (), cm_cindex (), + 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_sc (), cm_result (), cm_expansion (), + 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 (); @@ -532,7 +526,7 @@ int user_command_array_len = 0; #define NO_BRACE_ARGS 0 #define BRACE_ARGS 1 -static COMMAND CommandTable[] = { +static COMMAND command_table[] = { { "\t", insert_space, NO_BRACE_ARGS }, { "\n", insert_space, NO_BRACE_ARGS }, { " ", insert_self, NO_BRACE_ARGS }, @@ -632,7 +626,7 @@ static COMMAND CommandTable[] = { { "dotaccent", cm_accent, BRACE_ARGS }, { "dotless", cm_dotless, BRACE_ARGS }, { "dots", cm_dots, BRACE_ARGS }, - { "email", cm_angle_brackets, BRACE_ARGS }, + { "email", cm_email, BRACE_ARGS }, { "emph", cm_emph, BRACE_ARGS }, { "end", cm_end, NO_BRACE_ARGS }, { "enddots", cm_enddots, BRACE_ARGS }, @@ -655,29 +649,33 @@ static COMMAND CommandTable[] = { { "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 }, - { "key", cm_angle_brackets, 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 }, -#if defined (HAVE_MACROS) { "macro", cm_macro, NO_BRACE_ARGS }, -#endif { "majorheading", cm_majorheading, NO_BRACE_ARGS }, { "math", cm_no_op, BRACE_ARGS }, { "menu", cm_menu, NO_BRACE_ARGS }, @@ -706,7 +704,7 @@ static COMMAND CommandTable[] = { { "result", cm_result, BRACE_ARGS }, { "ringaccent", cm_accent, BRACE_ARGS }, { "samp", cm_code, BRACE_ARGS }, - { "sc", cm_sc, 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 }, @@ -748,10 +746,11 @@ static COMMAND CommandTable[] = { { "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, 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 }, @@ -772,46 +771,159 @@ static COMMAND CommandTable[] = { { "iunnumberedsubsec", cm_ideprecated, NO_BRACE_ARGS }, { "iunnumberedsubsubsec", cm_ideprecated, NO_BRACE_ARGS }, - /* Now @include does what this was supposed to. */ + /* Now @include does what this was used to. */ { "infoinclude", cm_obsolete, NO_BRACE_ARGS }, { "titlespec", cm_obsolete, NO_BRACE_ARGS }, - {(char *) NULL, (COMMAND_FUNCTION *) NULL}, NO_BRACE_ARGS}; + { NULL, NULL, NO_BRACE_ARGS } +}; struct option long_options[] = { - { "error-limit", 1, 0, 'e' }, /* formerly -el */ - { "fill-column", 1, 0, 'f' }, /* formerly -fc */ - { "footnote-style", 1, 0, 's' }, /* formerly -ft */ - { "no-headers", 0, &no_headers, 1 }, /* Do not output Node: foo */ + { "error-limit", 1, 0, 'e' }, /* formerly -el */ + { "fill-column", 1, 0, 'f' }, /* formerly -fc */ + { "footnote-style", 1, 0, 's' }, /* formerly -ft */ + { "force", 0, 0, 'F' }, /* do not remove output */ + { "no-headers", 0, &no_headers, 1 }, /* do not output Node: foo */ { "no-pointer-validate", 0, &validating, 0 }, /* formerly -nv */ - { "no-validate", 0, &validating, 0 }, /* formerly -nv */ - { "no-split", 0, &splitting, 0 }, /* formerly -ns */ - { "no-warn", 0, &print_warnings, 0 }, /* formerly -nw */ -#if defined (HAVE_MACROS) + { "no-validate", 0, &validating, 0 }, /* formerly -nv */ + { "no-split", 0, &splitting, 0 }, /* formerly -ns */ + { "no-warn", 0, &print_warnings, 0 }, /* formerly -nw */ { "macro-expand", 1, 0, 'E' }, -#endif /* HAVE_MACROS */ { "number-footnotes", 0, &number_footnotes, 1 }, { "no-number-footnotes", 0, &number_footnotes, 0 }, { "output", 1, 0, 'o' }, - { "paragraph-indent", 1, 0, 'p' }, /* formerly -pi */ - { "reference-limit", 1, 0, 'r' }, /* formerly -rl */ - { "verbose", 0, &verbose_mode, 1 }, /* formerly -verbose */ + { "paragraph-indent", 1, 0, 'p' }, /* formerly -pi */ + { "reference-limit", 1, 0, 'r' }, /* formerly -rl */ + { "verbose", 0, &verbose_mode, 1 }, /* formerly -verbose */ { "help", 0, 0, 'h' }, { "version", 0, 0, 'V' }, {NULL, 0, NULL, 0} }; -/* Values for calling handle_variable_internal (). */ -#define SET 1 -#define CLEAR 2 -#define IFSET 3 -#define IFCLEAR 4 +/* **************************************************************** */ +/* */ +/* Error Handling */ +/* */ +/* **************************************************************** */ + +/* Number of errors encountered. */ +int errors_printed = 0; + +/* Print the last error gotten from the file system. */ +int +fs_error (filename) + char *filename; +{ + remember_error (); + perror (filename); + return (0); +} + +/* Print an error message, and return false. */ +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 /* not VA_FPRINTF */ + va_end (ap); + + putc ('\n', stderr); +} + +/* Just like error (), but print the line number as well. */ +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 /* not VA_FPRINTF */ + 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 /* not VA_FPRINTF */ + va_end (ap); + fprintf (stderr, ".\n"); + } +} + + +/* Remember that an error has been printed. If more than + max_error_level have been printed, then exit the program. */ +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); + } +} + /* **************************************************************** */ -/* */ -/* Main () Start of code */ -/* */ +/* */ +/* Main () Start of code */ +/* */ /* **************************************************************** */ /* For each file mentioned in the command line, process it, turning @@ -829,144 +941,174 @@ main (argc, argv) /* The name of this program is the last filename in argv[0]. */ progname = filename_part (argv[0]); +#ifdef HAVE_SETLOCALE + /* Do not use LC_ALL, because LC_NUMERIC screws up the scanf parsing + of the argument to @multicolumn. */ + setlocale (LC_TIME, ""); + setlocale (LC_MESSAGES, ""); +#endif + + /* Set the text message domain. */ + bindtextdomain (PACKAGE, LOCALEDIR); + textdomain (PACKAGE); + /* Parse argument flags from the input line. */ - while ((c = getopt_long - (argc, argv, -#if defined (HAVE_MACROS) - "D:E:U:I:f:o:p:e:r:s:V", -#else - "D:U:I:f:o:p:e:r:s:V", -#endif /* !HAVE_MACROS */ - long_options, &ind)) - != EOF) + 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; + c = long_options[ind].val; switch (c) - { - /* User specified variable to set or clear? */ - case 'D': - case 'U': - handle_variable_internal ((c == 'D') ? SET : CLEAR, optarg); - break; - -#if defined (HAVE_MACROS) - /* Use specified a macro expansion output file? */ - case 'E': - if (!macro_expansion_output_stream) - { - macro_expansion_output_stream = 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; -#endif /* HAVE_MACROS */ - - /* User specified include file path? */ - case 'I': - if (!include_files_path) - include_files_path = strdup ("."); - - 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; - - /* User specified fill_column? */ - case 'f': - if (sscanf (optarg, "%d", &fill_column) != 1) - { - fprintf (stderr, - "%s: --fill-column arg must be numeric, not `%s'.\n", - progname, optarg); - usage (FATAL); - } - break; - - /* User specified output file? */ - case 'o': - command_output_filename = strdup (optarg); - break; - - /* User specified paragraph indent (paragraph_start_index)? */ - 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; - - /* User specified error level? */ - case 'e': - if (sscanf (optarg, "%d", &max_error_level) != 1) - { - fprintf (stderr, - "%s: --error-limit arg must be numeric, not `%s'.\n", - progname, optarg); - } - usage (stderr, FATAL); - break; - - /* User specified reference warning limit? */ - case 'r': - if (sscanf (optarg, "%d", &reference_warning_limit) != 1) - { - fprintf (stderr, - "%s: --reference-limit arg must be numeric, not `%s'.\n", + { + case 'D': + case 'U': + /* User specified variable to set or clear. */ + handle_variable_internal ((c == 'D') ? SET : CLEAR, optarg); + break; + + case 'e': + /* User specified error level. */ + 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': + /* User specified a macro expansion output file. */ + 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': + /* User specified fill_column. */ + 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++; /* Do not remove erroneous output. */ + break; + + case 'h': + usage (NO_ERROR); + break; + + case 'I': + /* Append user-specified dir to include file path. */ + 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': + /* User specified output file. */ + command_output_filename = xstrdup (optarg); + break; + + case 'p': + /* User specified paragraph indent (paragraph_start_index). */ + 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; - - /* User specified footnote style? */ - case 's': - if (set_footnote_style (optarg) < 0) - { - fprintf (stderr, - "%s: --footnote-style arg must be `separate' or `end', not `%s'.\n", + usage (FATAL); + } + break; + + case 'P': + /* Prepend user-specified include dir to include path. */ + if (!include_files_path) + { + include_files_path = xstrdup (optarg); + include_files_path = (char *) xrealloc (include_files_path, + strlen (include_files_path) + 3); /* 3 for ":.\0" */ + 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); /* 2 for ":\0" */ + strcpy (include_files_path, optarg); + strcat (include_files_path, ":"); + strcat (include_files_path, tmp); + free (tmp); + } + break; + + case 'r': + /* User specified reference warning limit. */ + 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': + /* User specified footnote style. */ + 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 'h': - usage (NO_ERROR); - break; - - /* User requested version info? */ - case 'V': - print_version_info (); - puts ("Copyright (C) 1996 Free Software Foundation, Inc.\n\ + usage (FATAL); + } + footnote_style_preset = 1; + break; + + case 'V': + /* User requested version info. */ + 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."); - exit (NO_ERROR); - break; - - case '?': - usage (FATAL); - break; - } +For more information about these matters, see the files named COPYING.\n"), + "1998"); + exit (NO_ERROR); + break; + + case '?': + usage (FATAL); + break; + } } if (optind == argc) { /* Check to see if input is a file. If so, process that. */ if (!isatty (fileno (stdin))) - reading_from_stdin = 1; + reading_from_stdin = 1; else { - fprintf (stderr, "%s: missing file argument.\n", progname); - usage (FATAL); + fprintf (stderr, _("%s: missing file argument.\n"), progname); + usage (FATAL); } } @@ -978,10 +1120,9 @@ For more information about these matters, see the files named COPYING."); { splitting = 0; - /* If the user has not specified an output file, then use stdout by - default. */ + /* If the user has not specified an output file, use stdout. */ if (!command_output_filename) - command_output_filename = strdup ("-"); + command_output_filename = xstrdup ("-"); } if (verbose_mode) @@ -992,7 +1133,7 @@ For more information about these matters, see the files named COPYING."); if (!reading_from_stdin) { while (optind != argc) - convert_from_file (argv[optind++]); + convert_from_file (argv[optind++]); } else convert_from_stream (stdin, "stdin"); @@ -1007,7 +1148,8 @@ For more information about these matters, see the files named COPYING."); void print_version_info () { - printf ("GNU Makeinfo (Texinfo 3.9) %d.%d\n", major_version, minor_version); + printf ("makeinfo (GNU %s %s) %d.%d\n", PACKAGE, VERSION, + major_version, minor_version); } /* **************************************************************** */ @@ -1057,12 +1199,6 @@ xrealloc (pointer, nbytes) else temp = (void *)realloc (pointer, nbytes); - if (nbytes && !temp) - memory_error ("xrealloc", nbytes); - - return (temp); -} - /* If EXIT_VALUE is zero, print the full usage message to stdout. Otherwise, just say to use --help for more info. Then exit with EXIT_VALUE. */ @@ -1071,17 +1207,18 @@ usage (exit_value) int exit_value; { if (exit_value != 0) - fprintf (stderr, "Try `%s --help' for more information.\n", progname); + fprintf (stderr, _("Try `%s --help' for more information.\n"), progname); else - printf ("Usage: %s [OPTION]... TEXINFO-FILE...\n\ + 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 add DIR to the directory search list for @include.\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\ @@ -1089,21 +1226,24 @@ Options:\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 NUM indent paragraphs with NUM spaces (default %d).\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@prep.ai.mit.edu.\n\ -", - progname, paragraph_start_indent, - fill_column, max_error_level, reference_warning_limit); +Email bug reports to bug-texinfo@gnu.org.\n\ +"), + progname, max_error_level, fill_column, + paragraph_start_indent, reference_warning_limit); exit (exit_value); } @@ -1143,7 +1283,7 @@ find_and_load (filename) { struct stat fileinfo; long file_size; - int file = -1, n, i, count = 0; + int file = -1, count = 0; char *fullpath, *result, *get_file_info_in_path (); result = fullpath = (char *)NULL; @@ -1160,31 +1300,35 @@ find_and_load (filename) if (file < 0) goto error_exit; - /* Load the file. */ - result = (char *)xmalloc (1 + file_size); + /* Load the file, with enough room for a newline and a null. */ + result = xmalloc (file_size + 2); /* VMS stat lies about the st_size value. The actual number of readable bytes is always less than this value. The arcane mysteries of VMS/RMS are too much to probe, so this hack suffices to make things work. */ -#if defined (VMS) +#if defined (VMS) || defined (WIN32) +#ifdef VMS while ((n = read (file, result + count, file_size)) > 0) +#else /* WIN32 */ + while ((n = read (file, result + count, 1)) > 0) +#endif /* WIN32 */ count += n; if (n == -1) -#else /* !VMS */ +#else /* !VMS && !WIN32 */ count = file_size; if (read (file, result, file_size) != file_size) -#endif /* !VMS */ +#endif /* !VMS && !WIN32 */ error_exit: { if (result) - free (result); + free (result); if (fullpath) - free (fullpath); + free (fullpath); if (file != -1) - close (file); + close (file); return ((char *) NULL); } @@ -1194,13 +1338,15 @@ find_and_load (filename) input_text = result; size_of_input_text = count; input_filename = fullpath; - node_filename = strdup (fullpath); + node_filename = xstrdup (fullpath); input_text_offset = 0; line_number = 1; /* Not strictly necessary. This magic prevents read_token () from doing extra unnecessary work each time it is called (that is a lot of times). - The SIZE_OF_INPUT_TEXT is one past the actual end of the text. */ + SIZE_OF_INPUT_TEXT is one past the actual end of the text. */ input_text[size_of_input_text] = '\n'; + /* This, on the other hand, is always necessary. */ + input_text[size_of_input_text+1] = 0; return (result); } @@ -1227,7 +1373,7 @@ popfile () FSTACK *tos = filestack; if (!tos) - abort (); /* My fault. I wonder what I did? */ + abort (); /* My fault. I wonder what I did? */ #if defined (HAVE_MACROS) if (macro_expansion_output_stream) @@ -1241,7 +1387,7 @@ popfile () filestack = filestack->next; /* Make sure that commands with braces have been satisfied. */ - if (!executing_string) + if (!executing_string && !me_executing_string) discard_braces (); /* Get the top of the stack into the globals. */ @@ -1306,7 +1452,7 @@ filename_part (filename) else basename++; - basename = strdup (basename); + basename = xstrdup (basename); #if defined (REMOVE_OUTPUT_EXTENSIONS) /* See if there is an extension to remove. If so, remove it. */ @@ -1315,7 +1461,7 @@ filename_part (filename) temp = strrchr (basename, '.'); if (temp) - *temp = '\0'; + *temp = 0; } #endif /* REMOVE_OUTPUT_EXTENSIONS */ return (basename); @@ -1343,7 +1489,7 @@ pathname_part (filename) { result = (char *)xmalloc (1 + i); strncpy (result, filename, i); - result[i] = '\0'; + result[i] = 0; } free (filename); return (result); @@ -1357,9 +1503,9 @@ filename_non_directory (name) for (i = strlen (name) - 1; i; i--) if (name[i] == '/') - return (strdup (name + i + 1)); + return (xstrdup (name + i + 1)); - return (strdup (name)); + return (xstrdup (name)); } /* Return the expansion of FILENAME. */ @@ -1377,24 +1523,24 @@ expand_filename (filename, input_name) filename = filename_non_directory (input_name); if (!*filename) - { - free (filename); - filename = strdup ("noname.texi"); - } + { + free (filename); + filename = xstrdup ("noname.texi"); + } for (i = strlen (filename) - 1; i; i--) - if (filename[i] == '.') - break; + if (filename[i] == '.') + break; if (!i) - i = strlen (filename); + i = strlen (filename); if (i + 6 > (strlen (filename))) - filename = (char *)xrealloc (filename, i + 6); + filename = (char *)xrealloc (filename, i + 6); strcpy (filename + i, ".info"); return (filename); } - + if (filename[0] == '.' || filename[0] == '/') return (filename); @@ -1409,10 +1555,10 @@ expand_filename (filename, input_name) strcpy (result, input_name); while (result[i] != '/' && i) - i--; + i--; if (result[i] == '/') - i++; + i++; strcpy (&result[i], filename); free (filename); @@ -1431,13 +1577,13 @@ full_pathname (filename) /* No filename given? */ if (!filename || !(initial_character = *filename)) - return (strdup ("")); + return (xstrdup ("")); /* Already absolute? */ if ((initial_character == '/') || ((strncmp (filename, "./", 2) == 0) || (strncmp (filename, "../", 3) == 0))) - return (strdup (filename)); + return (xstrdup (filename)); if (initial_character != '~') { @@ -1447,66 +1593,68 @@ full_pathname (filename) #if defined (HAVE_GETCWD) if (!getcwd (localdir, 1024)) #else /* !HAVE_GETCWD */ - if (!getwd (localdir)) + if (!getwd (localdir)) #endif /* !HAVE_GETCWD */ - { - fprintf (stderr, "%s: getwd: %s, %s\n", - progname, filename, localdir); - exit (1); - } + { + fprintf (stderr, _("%s: getwd: %s, %s\n"), + progname, filename, localdir); + exit (1); + } strcat (localdir, "/"); strcat (localdir, filename); - result = strdup (localdir); + result = xstrdup (localdir); free (localdir); } else { +#ifndef WIN32 if (filename[1] == '/') - { - /* Return the concatenation of the environment variable HOME - and the rest of the string. */ - 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]); - } + { + /* Return the concatenation of the environment variable HOME + and the rest of the string. */ + 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 (strdup (filename)); - - result = (char *)xmalloc (1 + strlen (user_entry->pw_dir) - + strlen (&filename[i])); - strcpy (result, user_entry->pw_dir); - strcat (result, &filename[i]); - } + { + 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 /* not WIN32 */ return (result); } @@ -1518,139 +1666,9 @@ output_name_from_input_name (name) } /* **************************************************************** */ -/* */ -/* Error Handling */ -/* */ -/* **************************************************************** */ - -/* Number of errors encountered. */ -int errors_printed = 0; - -/* Print the last error gotten from the file system. */ -int -fs_error (filename) - char *filename; -{ - remember_error (); - perror (filename); - return (0); -} - -/* Print an error message, and return false. */ -#if defined (HAVE_VARARGS_H) && defined (HAVE_VFPRINTF) - -int -error (va_alist) - va_dcl -{ - char *format; - va_list args; - - remember_error (); - va_start (args); - format = va_arg (args, char *); - vfprintf (stderr, format, args); - va_end (args); - putc ('\n', stderr); -} - -/* Just like error (), but print the line number as well. */ -int -line_error (va_alist) - va_dcl -{ - char *format; - va_list args; - - remember_error (); - va_start (args); - format = va_arg (args, char *); - fprintf (stderr, "%s:%d: ", input_filename, line_number); - vfprintf (stderr, format, args); - fprintf (stderr, ".\n"); - va_end (args); - return ((int) 0); -} - -int -warning (va_alist) - va_dcl -{ - char *format; - va_list args; - - va_start (args); - format = va_arg (args, char *); - if (print_warnings) - { - fprintf (stderr, "%s:%d: Warning: ", input_filename, line_number); - vfprintf (stderr, format, args); - fprintf (stderr, ".\n"); - } - va_end (args); - return ((int) 0); -} - -#else /* !(HAVE_VARARGS_H && HAVE_VFPRINTF) */ - -int -error (format, arg1, arg2, arg3, arg4, arg5) - char *format; -{ - remember_error (); - fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5); - putc ('\n', stderr); - return ((int) 0); -} - -/* Just like error (), but print the line number as well. */ -int -line_error (format, arg1, arg2, arg3, arg4, arg5) - char *format; -{ - remember_error (); - fprintf (stderr, "%s:%d: ", input_filename, line_number); - fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5); - fprintf (stderr, ".\n"); - return ((int) 0); -} - -int -warning (format, arg1, arg2, arg3, arg4, arg5) - char *format; -{ - if (print_warnings) - { - fprintf (stderr, "%s:%d: Warning: ", input_filename, line_number); - fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5); - fprintf (stderr, ".\n"); - } - return ((int) 0); -} - -#endif /* !(HAVE_VARARGS_H && HAVE_VFPRINTF) */ - -/* Remember that an error has been printed. If this is the first - error printed, then tell them which program is printing them. - If more than max_error_level have been printed, then exit the - program. */ -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 (1); - } -} - -/* **************************************************************** */ -/* */ -/* Hacking Tokens and Strings */ -/* */ +/* */ +/* Hacking Tokens and Strings */ +/* */ /* **************************************************************** */ /* Return the next token as a string pointer. We cons the string. */ @@ -1668,24 +1686,24 @@ read_token () input_text_offset++; if (character == '\n') - line_number++; + line_number++; - result = strdup (" "); + result = xstrdup (" "); *result = character; return (result); } for (i = 0; ((input_text_offset != size_of_input_text) - && (character = curchar ()) - && command_char (character)); + && (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'; + result[i] = 0; return (result); } -/* Return non-zero if CHARACTER is self-delimiting. */ +/* Return nonzero if CHARACTER is self-delimiting. */ int self_delimiting (character) int character; @@ -1709,17 +1727,17 @@ canon_white (string) for (x = 0; x < len; x++) { if (!cr_or_whitespace (string[x])) - { - strcpy (string, string + x); - break; - } + { + strcpy (string, string + x); + break; + } } len = strlen (string); if (len) len--; while (len > -1 && cr_or_whitespace (string[len])) len--; - string[len + 1] = '\0'; + string[len + 1] = 0; } /* Bash STRING, replacing all whitespace with just one space. */ @@ -1739,15 +1757,15 @@ fix_whitespace (string) 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'; + { + 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); } @@ -1773,10 +1791,10 @@ discard_until (string) input_text_offset = size_of_input_text - strlen (string); if (strcmp (string, "\n") != 0) - { - line_error ("Expected `%s'", string); - return; - } + { + line_error (_("Expected `%s'"), string); + return; + } } else input_text_offset = temp; @@ -1810,7 +1828,7 @@ get_until (match, string) *string = (char *)xmalloc (len + 1); memcpy (*string, &input_text[current_point], len); - (*string)[len] = '\0'; + (*string)[len] = 0; /* Now leave input_text_offset in a consistent state. */ input_text_offset = tem; @@ -1824,18 +1842,68 @@ get_until (match, string) /* Read characters from the file until we are at MATCH or end of line. Place the characters read into STRING. */ void -get_until_in_line (match, string) +get_until_in_line (expand, match, string) + int expand; char *match, **string; { - int real_bottom, temp; - - real_bottom = size_of_input_text; - temp = search_forward ("\n", input_text_offset); - - if (temp < 0) - temp = size_of_input_text; + int real_bottom = size_of_input_text; + int limit = search_forward ("\n", input_text_offset); + if (limit < 0) + limit = size_of_input_text; + + /* Replace input_text[input_text_offset .. limit-1] with its macro + expansion (actually, we expand all commands). This allows the node + names themselves to be constructed via a macro, as in: + @macro foo{p, q} + Together: \p\ & \q\. + @end macro + + @node @foo{A,B}, next, prev, top + + Otherwise, the `,' separating the macro args A and B is taken as + the node argument separator, so the node name is `@foo{A'. This + expansion is only necessary on the first call, since we expand the + whole line then. + + Furthermore, if we're executing a string, don't do it -- we'll end + up shrinking the execution string which is currently aliased to + `input_text', so it might get moved, and not updated in the + `execution_strings' array. This happens when processing the + (synthetic) Overview-Footnotes node in the Texinfo manual. */ + + if (expand && !executing_string && !me_executing_string) + { + char *xp; + unsigned xp_len, new_len; + + /* Get original string from input. */ + 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; + + /* Expand it. */ + xp = expansion (str, 0); + xp_len = strlen (xp); + free (str); + + /* Plunk the expansion into the middle of `input_text' -- + which is terminated by a newline, not a null. */ + 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 = temp; + size_of_input_text = limit; get_until (match, string); size_of_input_text = real_bottom; } @@ -1847,7 +1915,7 @@ get_rest_of_line (string) get_until ("\n", string); canon_white (*string); - if (curchar () == '\n') /* as opposed to the end of the file... */ + if (curchar () == '\n') /* as opposed to the end of the file... */ { line_number++; input_text_offset++; @@ -1863,7 +1931,7 @@ backup_input_pointer () { input_text_offset--; if (curchar () == '\n') - line_number--; + line_number--; } } @@ -1873,36 +1941,36 @@ void get_until_in_braces (match, string) char *match, **string; { + char *temp; int i, brace = 0; int match_len = strlen (match); - char *temp; for (i = input_text_offset; i < size_of_input_text; i++) { if (input_text[i] == '{') - brace++; + brace++; else if (input_text[i] == '}') - brace--; + brace--; else if (input_text[i] == '\n') - line_number++; + line_number++; if (brace < 0 || - (brace == 0 && strncmp (input_text + i, match, match_len) == 0)) - break; + (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'; + temp[match_len] = 0; input_text_offset = i; *string = temp; } /* **************************************************************** */ -/* */ -/* Converting the File */ -/* */ +/* */ +/* Converting the File */ +/* */ /* **************************************************************** */ /* Convert the file named by NAME. The output is saved on the file @@ -1934,7 +2002,7 @@ initialize_conversion () on unix systems. */ #define READ_BUFFER_GROWTH (4 * 4096) -/* Convert the texinfo file coming from the open stream STREAM. Assume the +/* Convert the Texinfo file coming from the open stream STREAM. Assume the source of the stream is named NAME. */ void convert_from_stream (stream, name) @@ -1954,27 +2022,27 @@ convert_from_stream (stream, name) int count; if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size) - buffer = (char *) - xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH)); + 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); - } + { + perror (name); + exit (FATAL); + } buffer_offset += count; if (count == 0) - break; + break; } /* Set the globals to the new file. */ input_text = buffer; size_of_input_text = buffer_offset; - input_filename = strdup (name); - node_filename = strdup (name); + input_filename = xstrdup (name); + node_filename = xstrdup (name); input_text_offset = 0; line_number = 1; @@ -2004,14 +2072,14 @@ convert_from_file (name) strcat (filename, suffixes[i]); if (find_and_load (filename)) - break; + break; if (!suffixes[i][0] && strrchr (filename, '.')) - { - fs_error (filename); - free (filename); - return; - } + { + fs_error (filename); + free (filename); + return; + } } if (!suffixes[i]) @@ -2043,47 +2111,47 @@ convert_from_loaded_file (name) while (input_text_offset >= 0) { input_text_offset = - search_forward (setfilename_search, 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; + ((input_text_offset > 0) && + (input_text[input_text_offset -1] == '\n'))) + break; else if (input_text_offset > 0) - input_text_offset++; + 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; + error (_("No `%s' found in `%s'"), setfilename_search, name); + goto finished; #else - register int i, end_of_first_line; - - /* Find the end of the first line in the file. */ - 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); + register int i, end_of_first_line; + + /* Find the end of the first line in the file. */ + 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 /* !REQUIRE_SETFILENAME */ - } + } } else input_text_offset += strlen (setfilename_search); @@ -2093,9 +2161,9 @@ convert_from_loaded_file (name) else { if (input_text_offset != -1) - discard_until ("\n"); + discard_until ("\n"); else - input_text_offset = 0; + input_text_offset = 0; real_output_filename = output_filename = command_output_filename; command_output_filename = (char *)NULL; @@ -2103,25 +2171,31 @@ convert_from_loaded_file (name) canon_white (output_filename); - if (real_output_filename && - strcmp (real_output_filename, "-") == 0) + if (real_output_filename && strcmp (real_output_filename, "-") == 0) { - real_output_filename = strdup (real_output_filename); + 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; /* Cannot split when writing to stdout. */ + splitting = 0; /* Cannot split when writing to stdout. */ } else { if (!real_output_filename) - real_output_filename = expand_filename (output_filename, name); + real_output_filename = expand_filename (output_filename, name); else - real_output_filename = strdup (real_output_filename); + real_output_filename = xstrdup (real_output_filename); output_stream = fopen (real_output_filename, "w"); } - if (verbose_mode && output_stream != stdout) - printf ("Making %s file `%s' from `%s'.\n", + if (output_stream != stdout) + printf (_("Making %s file `%s' from `%s'.\n"), no_headers ? "text" : "info", output_filename, input_filename); if (output_stream == NULL) @@ -2135,7 +2209,7 @@ convert_from_loaded_file (name) if (output_stream != stdout) pretty_output_filename = filename_part (output_filename); else - pretty_output_filename = strdup ("stdout"); + pretty_output_filename = xstrdup ("stdout"); /* For this file only, count the number of newlines from the top of the file to here. This way, we keep track of line numbers for @@ -2146,50 +2220,69 @@ convert_from_loaded_file (name) line_number = 1; while (temp != input_text_offset) if (input_text[temp++] == '\n') - line_number++; + 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); + 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); + { + 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 /* HAVE_MACROS */ - if (output_stream != NULL) + 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 (); - } + { + tag_table = (TAG_ENTRY *) reverse_list (tag_table); + if (!no_headers) + write_tag_table (); + } if (output_stream != stdout) - fclose (output_stream); + fclose (output_stream); /* If validating, then validate the entire file right now. */ if (validating) - validate_file (tag_table); - - /* This used to test && !errors_printed. - But some files might have legit warnings. So split anyway. */ - if (splitting) - split_file (real_output_filename, 0); + 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) + { /* If there were errors, and no --force, remove the output. */ + 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); } @@ -2198,7 +2291,7 @@ void free_and_clear (pointer) char **pointer; { - if ((*pointer) != (char *) NULL) + if (*pointer) { free (*pointer); *pointer = (char *) NULL; @@ -2209,13 +2302,13 @@ free_and_clear (pointer) void init_internals () { - free_and_clear (¤t_node); 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; /* sometimes already freed */ command_index = 0; in_menu = 0; in_detailmenu = 0; @@ -2228,7 +2321,7 @@ init_paragraph () { free_and_clear (&output_paragraph); output_paragraph = (unsigned char *)xmalloc (paragraph_buffer_len); - output_paragraph[0] = '\0'; + output_paragraph[0] = 0; output_paragraph_offset = 0; output_column = 0; paragraph_is_open = 0; @@ -2250,100 +2343,99 @@ reader_loop () while (!done) { if (input_text_offset >= size_of_input_text) - break; + break; character = curchar (); if (!in_fixed_width_font && - (character == '\'' || character == '`') && - input_text[input_text_offset + 1] == character) - { - input_text_offset++; - character = '"'; - } + (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; - } - } + { + dash_count++; + if (dash_count == 2 && !in_fixed_width_font) + { + input_text_offset++; + continue; + } + } else - { - dash_count = 0; - } + { + dash_count = 0; + } /* If this is a whitespace character, then check to see if the line - is blank. If so, advance to the carriage return. */ + is blank. If so, advance to the carriage return. */ if (whitespace (character)) - { - register int i = input_text_offset + 1; + { + register int i = input_text_offset + 1; - while (i < size_of_input_text && whitespace (input_text[i])) - i++; + 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--; + if (i == size_of_input_text || input_text[i] == '\n') + { + if (i == size_of_input_text) + i--; - input_text_offset = i; - character = curchar (); - } - } + input_text_offset = i; + character = curchar (); + } + } if (character == '\n') - { - line_number++; - - /* Check for a menu entry here, since the "escape sequence" - that begins menu entries is "\n* ". */ - if (in_menu && input_text_offset + 1 < size_of_input_text) - { - char *glean_node_from_menu (), *tem; - - /* Note that the value of TEM is discarded, since it is - gauranteed to be NULL when glean_node_from_menu () is - called with a non-zero argument. */ - if (!in_detailmenu) - tem = glean_node_from_menu (1); - } - } + { + line_number++; + + /* Check for a menu entry here, since the "escape sequence" + that begins menu entries is "\n* ". */ + if (in_menu && input_text_offset + 1 < size_of_input_text) + { + char *glean_node_from_menu (), *tem; + + /* Note that the value of TEM is discarded, since it is + gauranteed to be NULL when glean_node_from_menu () is + called with a Nonzero argument. */ + if (!in_detailmenu) + tem = glean_node_from_menu (1); + } + } switch (character) - { - case COMMAND_PREFIX: - read_command (); - break; - - case '{': - - /* Special case. I'm not supposed to see this character by itself. - If I do, it means there is a syntax error in the input text. - Report the error here, but remember this brace on the stack so - you can ignore its partner. */ - - line_error ("Misplaced `{'"); - remember_brace (misplaced_brace); - - /* Don't advance input_text_offset since this happens in - remember_brace (). - input_text_offset++; + { + case COMMAND_PREFIX: + read_command (); + break; + + case '{': + /* Special case. I'm not supposed to see this character by itself. + If I do, it means there is a syntax error in the input text. + Report the error here, but remember this brace on the stack so + you can ignore its partner. */ + + line_error (_("Misplaced %c"), '{'); + remember_brace (misplaced_brace); + + /* Don't advance input_text_offset since this happens in + remember_brace (). + input_text_offset++; */ - break; + break; - case '}': - pop_and_call_brace (); - input_text_offset++; - break; + case '}': + pop_and_call_brace (); + input_text_offset++; + break; - default: - add_char (character); - input_text_offset++; - } + default: + add_char (character); + input_text_offset++; + } } #if defined (HAVE_MACROS) if (macro_expansion_output_stream) @@ -2360,18 +2452,18 @@ get_command_entry (string) { register int i; - for (i = 0; CommandTable[i].name; i++) - if (strcmp (CommandTable[i].name, string) == 0) - return (&CommandTable[i]); + for (i = 0; command_table[i].name; i++) + if (strcmp (command_table[i].name, string) == 0) + return (&command_table[i]); /* This command is not in our predefined command table. Perhaps it is a user defined command. */ for (i = 0; i < user_command_array_len; i++) if (user_command_array[i] && - (strcmp (user_command_array[i]->name, string) == 0)) + (strcmp (user_command_array[i]->name, string) == 0)) return (user_command_array[i]); - /* Nope, we never heard of this command. */ + /* We never heard of this command. */ return ((COMMAND *) -1); } @@ -2395,26 +2487,25 @@ read_command () if (def) { - /* We disallow recursive use of a macro call. Inhibit the expansion - of this macro during the life of its execution. */ - if (!(def->flags & ME_RECURSE)) - def->inhibited = 1; + /* We disallow recursive use of a macro call. Inhibit the expansion + of this macro during the life of its execution. */ + if (!(def->flags & ME_RECURSE)) + def->inhibited = 1; - execute_macro (def); + execute_macro (def); - if (!(def->flags & ME_RECURSE)) - def->inhibited = 0; + if (!(def->flags & ME_RECURSE)) + def->inhibited = 0; - return; + return; } } #endif /* HAVE_MACROS */ entry = get_command_entry (command); - if (entry == (COMMAND *)-1) { - line_error ("Unknown command `%s'", command); + line_error (_("Unknown command `%s'"), command); return; } @@ -2431,10 +2522,10 @@ find_proc_name (proc) { register int i; - for (i = 0; CommandTable[i].name; i++) - if (proc == CommandTable[i].proc) - return (CommandTable[i].name); - return ("NO_NAME!"); + for (i = 0; command_table[i].name; i++) + if (proc == command_table[i].proc) + return command_table[i].name; + return _("NO_NAME!"); } void @@ -2448,7 +2539,7 @@ remember_brace (proc) COMMAND_FUNCTION *proc; { if (curchar () != '{') - line_error ("%c%s expected `{..}'", COMMAND_PREFIX, command); + line_error (_("%c%s expected `{...}'"), COMMAND_PREFIX, command); else input_text_offset++; remember_brace_1 (proc, output_paragraph_offset); @@ -2481,7 +2572,7 @@ pop_and_call_brace () if (brace_stack == (BRACE_ELEMENT *) NULL) { - line_error ("Unmatched }"); + line_error (_("Unmatched }")); return; } @@ -2505,7 +2596,7 @@ adjust_braces_following (here, amount) while (stack) { if (stack->pos >= here) - stack->pos += amount; + stack->pos += amount; stack = stack->next; } } @@ -2523,23 +2614,23 @@ discard_braces () 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 (); - } + { + 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; - } + { + BRACE_ELEMENT *temp; + temp = brace_stack->next; + free (brace_stack); + brace_stack = temp; + } } } @@ -2555,9 +2646,9 @@ get_char_len (character) case '\t': len = (output_column + 8) & 0xf7; if (len > fill_column) - len = fill_column - output_column; + len = fill_column - output_column; else - len = len - output_column; + len = len - output_column; break; case '\n': @@ -2565,44 +2656,42 @@ get_char_len (character) break; default: - if (character < ' ') - len = 2; + /* ASCII control characters appear as two characters in the output + (e.g., ^A). But characters with the high bit set are just one + on suitable terminals, so don't count them as two for line + breaking purposes. */ + if (0 <= character && character < ' ') + len = 2; else - len = 1; + len = 1; } return (len); } -#if defined (HAVE_VARARGS_H) && defined (HAVE_VSPRINTF) - void -add_word_args (va_alist) - va_dcl +#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]; - char *format; - va_list args; - - va_start (args); - format = va_arg (args, char *); - vsprintf (buffer, format, args); - va_end (args); - add_word (buffer); -} - -#else /* !(HAVE_VARARGS_H && HAVE_VSPRINTF) */ +#ifdef VA_FPRINTF + va_list ap; +#endif -void -add_word_args (format, arg1, arg2, arg3, arg4, arg5) - char *format; -{ - char buffer[1000]; - sprintf (buffer, format, arg1, arg2, arg3, arg4, arg5); + VA_START (ap, format); +#ifdef VA_SPRINTF + VA_SPRINTF (buffer, format, ap); +#else + sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8); +#endif /* not VA_SPRINTF */ + va_end (ap); add_word (buffer); } -#endif /* !(HAVE_VARARGS_H && HAVE_VSPRINTF) */ - /* Add STRING to output_paragraph. */ void add_word (string) @@ -2612,26 +2701,26 @@ add_word (string) add_char (*string++); } -/* Non-zero if the last character inserted has the syntax class of NEWLINE. */ +/* Nonzero if the last character inserted has the syntax class of NEWLINE. */ int last_char_was_newline = 1; /* The actual last inserted character. Note that this may be something other than NEWLINE even if last_char_was_newline is 1. */ int last_inserted_character = 0; -/* Non-zero means that a newline character has already been +/* Nonzero means that a newline character has already been inserted, so close_paragraph () should insert one less. */ int line_already_broken = 0; -/* When non-zero we have finished an insertion (see end_insertion ()) and we +/* When nonzero we have finished an insertion (see `end_insertion') and we want to ignore false continued paragraph closings. */ int insertion_paragraph_closed = 0; -/* Non-zero means attempt to make all of the lines have fill_column width. */ +/* Nonzero means attempt to make all of the lines have fill_column width. */ int do_justification = 0; /* Add the character to the current paragraph. If filling_enabled is - non-zero, then do filling as well. */ + nonzero, then do filling as well. */ void add_char (character) int character; @@ -2646,12 +2735,12 @@ add_char (character) if (must_start_paragraph && character != '\n') { must_start_paragraph = 0; - line_already_broken = 0; /* The line is no longer broken. */ + line_already_broken = 0; /* The line is no longer broken. */ if (current_indent > output_column) - { - indent (current_indent - output_column); - output_column = current_indent; - } + { + indent (current_indent - output_column); + output_column = current_indent; + } } if (non_splitting_words && member (character, " \t\n")) @@ -2663,168 +2752,168 @@ add_char (character) { case '\n': if (!filling_enabled) - { - insert ('\n'); - - if (force_flush_right) - { - close_paragraph (); - /* Hack to force single blank lines out in this mode. */ - flush_output (); - } - - output_column = 0; - - if (!no_indent && paragraph_is_open) - indent (output_column = current_indent); - break; - } + { + insert ('\n'); + + if (force_flush_right) + { + close_paragraph (); + /* Hack to force single blank lines out in this mode. */ + flush_output (); + } + + output_column = 0; + + if (!no_indent && paragraph_is_open) + indent (output_column = current_indent); + break; + } else /* CHARACTER is newline, and filling is enabled. */ - { - if (sentence_ender (last_inserted_character)) - { - insert (' '); - output_column++; - last_inserted_character = character; - } - } + { + if (end_of_sentence_p ()) + { + insert (' '); + output_column++; + last_inserted_character = character; + } + } if (last_char_was_newline) - { - close_paragraph (); - pending_indent = 0; - } + { + close_paragraph (); + pending_indent = 0; + } else - { - last_char_was_newline = 1; - insert (' '); - output_column++; - } + { + 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 the paragraph is supposed to be indented a certain way, - then discard all of the pending whitespace. Otherwise, we - let the whitespace stay. */ - 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 we have found a space, we have the place to break - the line. */ - if (output_paragraph[temp] == ' ') - { - /* Remove trailing whitespace from output. */ - while (temp && whitespace (output_paragraph[temp - 1])) - temp--; - - output_paragraph[temp++] = '\n'; - - /* We have correctly broken the line where we want - to. What we don't want is spaces following where - we have decided to break the line. We get rid of - them. */ - { - 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); - } - } - - /* Filled, but now indent if that is right. */ - if (indented_fill && current_indent) - { - int buffer_len = ((output_paragraph_offset - temp) - + current_indent); - char *temp_buffer = (char *)xmalloc (buffer_len); - int indentation = 0; - - /* We have to shift any markers that are in - front of the wrap point. */ - 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; + 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 the paragraph is supposed to be indented a certain way, + then discard all of the pending whitespace. Otherwise, we + let the whitespace stay. */ + 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 we have found a space, we have the place to break + the line. */ + if (output_paragraph[temp] == ' ') + { + /* Remove trailing whitespace from output. */ + while (temp && whitespace (output_paragraph[temp - 1])) + temp--; + + output_paragraph[temp++] = '\n'; + + /* We have correctly broken the line where we want + to. What we don't want is spaces following where + we have decided to break the line. We get rid of + them. */ + { + 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); + } + } + + /* Filled, but now indent if that is right. */ + if (indented_fill && current_indent) + { + int buffer_len = ((output_paragraph_offset - temp) + + current_indent); + char *temp_buffer = (char *)xmalloc (buffer_len); + int indentation = 0; + + /* We have to shift any markers that are in + front of the wrap point. */ + 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; } } } @@ -2838,7 +2927,7 @@ insert (character) if (output_paragraph_offset == paragraph_buffer_len) { output_paragraph = - xrealloc (output_paragraph, (paragraph_buffer_len += 100)); + xrealloc (output_paragraph, (paragraph_buffer_len += 100)); } } @@ -2851,6 +2940,23 @@ insert_string (string) insert (*string++); } + +/* Sentences might have these characters after the period (or whatever). */ +#define post_sentence(c) ((c) == ')' || (c) == '\'' || (c) == '"' \ + || (c) == ']') + +/* Return true if at an end-of-sentence character, possibly followed by + post-sentence punctuation to ignore. */ +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]); +} + + /* Remove upto COUNT characters of whitespace from the the current output line. If COUNT is less than zero, then remove until none left. */ @@ -2863,24 +2969,24 @@ kill_self_indent (count) { output_column = 0; while (output_paragraph_offset) - { - if (whitespace (output_paragraph[output_paragraph_offset - 1])) - output_paragraph_offset--; - else - break; - } + { + 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; + if (whitespace (output_paragraph[output_paragraph_offset - 1])) + output_paragraph_offset--; + else + break; } } -/* Non-zero means do not honor calls to flush_output (). */ +/* Nonzero means do not honor calls to flush_output (). */ static int flushing_ignored = 0; /* Prevent calls to flush_output () from having any effect. */ @@ -2913,7 +3019,7 @@ flush_output () { int temp = UNMETA (output_paragraph[i]); if (temp == ' ') - output_paragraph[i] &= 0x7f; + output_paragraph[i] &= 0x7f; } } @@ -2947,30 +3053,28 @@ close_insertion_paragraph () /* Close the current paragraph, breaking the line. */ close_single_paragraph (); - /* Start a new paragraph here, inserting whatever indention is correct - for the now current insertion level (one above the one that we are - ending). */ + /* Start a new paragraph, with the correct indentation for the now + current insertion level (one above the one that we are ending). */ start_paragraph (); - /* Tell close_paragraph () that the previous line has already been - broken, so it should insert one less newline. */ + /* Tell `close_paragraph' that the previous line has already been + broken, so it should insert one less newline. */ line_already_broken = 1; - /* Let functions such as add_char () know that we have already found a - newline. */ + /* Tell functions such as `add_char' we've already found a newline. */ ignore_blank_line (); } else { /* If the insertion paragraph is closed already, then we are seeing - two `@end' commands in a row. Note that the first one we saw was - handled in the first part of this if-then-else clause, and at that - time start_paragraph () was called, partially to handle the proper - indentation of the current line. However, the indentation level - may have just changed again, so we may have to outdent the current - line to the new indentation level. */ + two `@end' commands in a row. Note that the first one we saw was + handled in the first part of this if-then-else clause, and at that + time `start_paragraph' was called, partially to handle the proper + indentation of the current line. However, the indentation level + may have just changed again, so we may have to outdent the current + line to the new indentation level. */ if (current_indent < output_column) - kill_self_indent (output_column - current_indent); + kill_self_indent (output_column - current_indent); } insertion_paragraph_closed = 1; @@ -3002,37 +3106,37 @@ close_paragraph () tindex = output_paragraph_offset; /* Back up to last non-newline/space character, forcing all such - subsequent characters to be newlines. This isn't strictly - necessary, but a couple of functions use the presence of a newline - to make decisions. */ + subsequent characters to be newlines. This isn't strictly + necessary, but a couple of functions use the presence of a newline + to make decisions. */ for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex) - { - c = output_paragraph[tindex]; + { + c = output_paragraph[tindex]; - if (c == ' '|| c == '\n') - output_paragraph[tindex] = '\n'; - else - break; - } + if (c == ' '|| c == '\n') + output_paragraph[tindex] = '\n'; + else + break; + } /* All trailing whitespace is ignored. */ output_paragraph_offset = ++tindex; /* Break the line if that is appropriate. */ if (paragraph_spacing >= 0) - insert ('\n'); + insert ('\n'); - /* Add as many blank lines as is specified in PARAGRAPH_SPACING. */ + /* Add as many blank lines as is specified in `paragraph_spacing'. */ if (!force_flush_right) - { - for (i = 0; i < (paragraph_spacing - line_already_broken); i++) - insert ('\n'); - } + { + for (i = 0; i < (paragraph_spacing - line_already_broken); i++) + insert ('\n'); + } /* If we are doing flush right indentation, then do it now - on the paragraph (really a single line). */ + on the paragraph (really a single line). */ if (force_flush_right) - do_flush_right_indentation (); + do_flush_right_indentation (); flush_output (); paragraph_is_open = 0; @@ -3061,28 +3165,28 @@ do_flush_right_indentation () if (output_paragraph[0] != '\n') { - output_paragraph[output_paragraph_offset] = '\0'; + output_paragraph[output_paragraph_offset] = 0; if (output_paragraph_offset < fill_column) - { - register int i; + { + register int i; - if (fill_column >= paragraph_buffer_len) - output_paragraph = - xrealloc (output_paragraph, - (paragraph_buffer_len += fill_column)); + 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); + 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] = ' '; + 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; - } + memcpy ((char *)output_paragraph + i, temp, temp_len); + free (temp); + output_paragraph_offset = fill_column; + } } } @@ -3109,25 +3213,25 @@ start_paragraph () /* If doing indentation, then insert the appropriate amount. */ 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; - } - } + { + 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; @@ -3145,7 +3249,7 @@ indent (amount) while (elt) { if (elt->pos >= output_paragraph_offset) - elt->pos += amount; + elt->pos += amount; elt = elt->next; } @@ -3165,7 +3269,7 @@ search_forward (string, from) while (from < size_of_input_text) { if (strncmp (input_text + from, string, len) == 0) - return (from); + return (from); from++; } return (-1); @@ -3187,13 +3291,13 @@ strcasecmp (string1, string2) ch2 = *string2++; if (!(ch1 | ch2)) - return (0); + return (0); ch1 = coerce_to_upper (ch1); ch2 = coerce_to_upper (ch2); if (ch1 != ch2) - return (ch1 - ch2); + return (ch1 - ch2); } } #endif /* !HAVE_STRCASECMP */ @@ -3230,18 +3334,20 @@ current_item_function () while (!done && (elt != NULL)) { switch (elt->insertion) - { - case ifinfo: - case ifset: - case ifclear: - case cartouche: - elt = elt->next; - level--; - break; - - default: - done = 1; - } + { + case ifinfo: + case ifnothtml: + case ifnottex: + case ifset: + case ifclear: + case cartouche: + elt = elt->next; + level--; + break; + + default: + done = 1; + } } if (!level) @@ -3256,7 +3362,6 @@ get_item_function () char *item_function; get_rest_of_line (&item_function); backup_input_pointer (); - canon_white (item_function); return (item_function); } @@ -3273,7 +3378,7 @@ push_insertion (type, item_function) new->indented_fill = indented_fill; new->insertion = type; new->line_number = line_number; - new->filename = strdup (input_filename); + new->filename = xstrdup (input_filename); new->inhibited = inhibit_paragraph_indentation; new->in_fixed_width_font = in_fixed_width_font; new->next = insertion_stack; @@ -3311,7 +3416,7 @@ insertion_type_pname (type) if ((int) type < (int) bad_type) return (insertion_type_names[(int) type]); else - return ("Broken-Type in insertion_type_pname"); + return (_("Broken-Type in insertion_type_pname")); } /* Return the insertion_type associated with NAME. @@ -3324,7 +3429,7 @@ find_type_from_name (name) while (index < (int) bad_type) { if (strcmp (name, insertion_type_names[index]) == 0) - return (enum insertion_type) index; + return (enum insertion_type) index; index++; } return (bad_type); @@ -3377,7 +3482,7 @@ start_enumerating (at, type) { if ((enumstack_offset + 1) == max_stack_depth) { - line_error ("Enumeration stack overflow"); + line_error (_("Enumeration stack overflow")); return; } enumstack[enumstack_offset].enumtype = current_enumtype; @@ -3407,10 +3512,10 @@ enumerate_item () 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); - } + { + current_enumval = ((current_enumval - 1) == 'z' ? 'a' : 'A'); + warning (_("lettering overflow, restarting at %c"), current_enumval); + } sprintf (temp, "%c. ", current_enumval); } else @@ -3432,7 +3537,7 @@ begin_insertion (type) if (defun_insertion (type)) { - push_insertion (type, strdup ("")); + push_insertion (type, xstrdup ("")); no_discard++; } else @@ -3442,30 +3547,29 @@ begin_insertion (type) { case menu: if (!no_headers) - close_paragraph (); + close_paragraph (); filling_enabled = no_indent = 0; inhibit_paragraph_indentation = 1; if (!no_headers) - add_word ("* Menu:\n"); + add_word (_("* Menu:\n")); in_menu++; no_discard++; break; case detailmenu: - if (!in_menu) - { - if (!no_headers) - close_paragraph (); + { + if (!no_headers) + close_paragraph (); - filling_enabled = no_indent = 0; - inhibit_paragraph_indentation = 1; + filling_enabled = no_indent = 0; + inhibit_paragraph_indentation = 1; - no_discard++; - } + no_discard++; + } in_detailmenu++; break; @@ -3478,7 +3582,7 @@ begin_insertion (type) break; /* I think @quotation is meant to do filling. - If you don't want filling, then use @display. */ + If you don't want filling, then use @display. */ case quotation: close_single_paragraph (); last_char_was_newline = no_indent = 0; @@ -3494,16 +3598,13 @@ begin_insertion (type) case smalllisp: /* Just like @example, but no indentation. */ 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; - + current_indent += default_indentation_increment; break; case multitable: @@ -3525,20 +3626,20 @@ begin_insertion (type) /* Make things work for losers who forget the itemize syntax. */ if (allow_lax_format && (type == itemize)) - { - if (!(*insertion_stack->item_function)) - { - free (insertion_stack->item_function); - insertion_stack->item_function = strdup ("@bullet"); - insertion_stack->item_function[0] = COMMAND_PREFIX; - } - } + { + 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); - } + { + line_error (_("%s requires an argument: the formatter for %citem"), + insertion_type_pname (type), COMMAND_PREFIX); + } break; case enumerate: @@ -3554,26 +3655,28 @@ begin_insertion (type) filling_enabled = indented_fill = 1; if (isdigit (*enumeration_arg)) - start_enumerating (atoi (enumeration_arg), ENUM_DIGITS); + start_enumerating (atoi (enumeration_arg), ENUM_DIGITS); else - start_enumerating (*enumeration_arg, ENUM_ALPHA); + start_enumerating (*enumeration_arg, ENUM_ALPHA); break; /* Does nothing special in makeinfo. */ case group: /* Only close the paragraph if we are not inside of an @example. */ if (!insertion_stack->next || - insertion_stack->next->insertion != example) - close_single_paragraph (); + insertion_stack->next->insertion != example) + close_single_paragraph (); break; /* Insertions that are no-ops in info, but do something in TeX. */ case ifinfo: + case ifnothtml: + case ifnottex: case ifset: case ifclear: case cartouche: if (in_menu) - no_discard++; + no_discard++; break; case deffn: @@ -3617,11 +3720,10 @@ begin_insertion (type) discard_until ("\n"); } -/* Try to end the insertion with the specified TYPE. - TYPE, with a value of bad_type, gets translated to match - the value currently on top of the stack. - Otherwise, if TYPE doesn't match the top of the insertion stack, - give error. */ +/* Try to end the insertion with the specified TYPE. With a value of + `bad_type', TYPE gets translated to match the value currently on top + of the stack. Otherwise, if TYPE doesn't match the top of the + insertion stack, give error. */ void end_insertion (type) enum insertion_type type; @@ -3639,8 +3741,8 @@ end_insertion (type) if (type != temp_type) { line_error - ("`%cend' expected `%s', but saw `%s'", COMMAND_PREFIX, - insertion_type_pname (temp_type), insertion_type_pname (type)); + (_("`%cend' expected `%s', but saw `%s'"), COMMAND_PREFIX, + insertion_type_pname (temp_type), insertion_type_pname (type)); return; } @@ -3649,6 +3751,8 @@ end_insertion (type) switch (type) { /* Insertions which have no effect on paragraph formatting. */ + case ifnothtml: + case ifnottex: case ifinfo: case ifset: case ifclear: @@ -3660,18 +3764,18 @@ end_insertion (type) break; case detailmenu: - in_detailmenu--; /* No longer hacking menus. */ + in_detailmenu--; /* No longer hacking menus. */ if (!in_menu) - { - if (!no_headers) - close_insertion_paragraph (); - } + { + if (!no_headers) + close_insertion_paragraph (); + } break; case menu: - in_menu--; /* No longer hacking menus. */ + in_menu--; /* No longer hacking menus. */ if (!no_headers) - close_insertion_paragraph (); + close_insertion_paragraph (); break; case multitable: @@ -3697,14 +3801,13 @@ end_insertion (type) case lisp: case smalllisp: case quotation: - /* @format is the only fixed_width insertion without a change - in indentation. */ + in indentation. */ if (type != format) - current_indent -= default_indentation_increment; + current_indent -= default_indentation_increment; /* The ending of one of these insertions always marks the - start of a new paragraph. */ + start of a new paragraph. */ close_insertion_paragraph (); break; @@ -3729,33 +3832,32 @@ end_insertion (type) } /* Insertions cannot cross certain boundaries, such as node beginnings. In - code that creates such boundaries, you should call discard_insertions () + code that creates such boundaries, you should call `discard_insertions' before doing anything else. It prints the errors for you, and cleans up - the insertion stack. */ + the insertion stack. With nonzero SPECIALS_OK, allows unmatched + ifinfo, ifset, ifclear, otherwise not. */ void -discard_insertions () +discard_insertions (specials_ok) + int specials_ok; { int real_line_number = line_number; while (insertion_stack) { - if (insertion_stack->insertion == ifinfo || - insertion_stack->insertion == ifset || - insertion_stack->insertion == ifclear) - break; + if (specials_ok && (insertion_stack->insertion == ifinfo + || insertion_stack->insertion == ifset + || insertion_stack->insertion == ifclear)) + break; else - { - char *offender; - char *current_filename; - - current_filename = input_filename; - offender = (char *)insertion_type_pname (insertion_stack->insertion); - input_filename = insertion_stack->filename; - line_number = insertion_stack->line_number; - line_error ("This `%s' doesn't have a matching `%cend %s'", offender, - COMMAND_PREFIX, offender); - input_filename = current_filename; - pop_insertion (); - } + { + 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; } @@ -3784,9 +3886,7 @@ void cm_asterisk () { close_single_paragraph (); -#if !defined (ASTERISK_NEW_PARAGRAPH) cm_noindent (); -#endif /* ASTERISK_NEW_PARAGRAPH */ } /* Insert ellipsis. */ @@ -3893,7 +3993,7 @@ cm_special_char (arg) else if (strcmp (command, "questiondown") == 0) add_char ('?'); else - fprintf (stderr, "How did @%s end up in cm_special_char?\n", command); + fprintf (stderr, _("How did @%s end up in cm_special_char?\n"), command); } } @@ -3907,12 +4007,12 @@ cm_dotless (arg, start, end) if (output_paragraph[start] != 'i' && output_paragraph[start] != 'j') /* This error message isn't perfect if the argument is multiple characters, but it doesn't seem worth getting right. */ - line_error ("%c%s expects `i' or `j' as argument, not `%c'", + 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); + line_error (_("%c%s expects a single character `i' or `j' as argument"), + COMMAND_PREFIX, command); /* We've already inserted the `i' or `j', so nothing to do. */ } @@ -3922,18 +4022,16 @@ void cm_today (arg) int arg; { - static char * months [12] = - { "January", "February", "March", "April", "May", "June", "July", - "August", "September", "October", "November", "December" }; + 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)); + add_word_args ("%d %s %d", ts->tm_mday, _(months[ts->tm_mon]), + ts->tm_year + 1900); } } @@ -3948,12 +4046,12 @@ cm_code (arg) in_fixed_width_font++; if (!printing_index) - add_char ('`'); + add_char ('`'); } else { if (!printing_index) - add_char ('\''); + add_char ('\''); } } @@ -3968,7 +4066,7 @@ cm_kbd (arg) } void -cm_angle_brackets (arg) +cm_key (arg) int arg; { add_char (arg == START ? '<' : '>'); @@ -3985,17 +4083,17 @@ cm_ctrl (arg, start, 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); + 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]; + for (i = start; i < end; i++) + { + character = output_paragraph[i]; - if (isletter (character)) - output_paragraph[i] = CTL (coerce_to_upper (character)); - } + if (isletter (character)) + output_paragraph[i] = CTL (coerce_to_upper (character)); + } } } @@ -4008,9 +4106,9 @@ not_fixed_width (arg) in_fixed_width_font = 0; } -/* Small caps in makeinfo has to do just all caps. */ +/* Small caps and @var in makeinfo just uppercase the text. */ void -cm_sc (arg, start_pos, end_pos) +cm_var_sc (arg, start_pos, end_pos) int arg, start_pos, end_pos; { not_fixed_width (arg); @@ -4018,29 +4116,11 @@ cm_sc (arg, start_pos, end_pos) if (arg == END) { while (start_pos < end_pos) - { - output_paragraph[start_pos] = - coerce_to_upper (output_paragraph[start_pos]); - start_pos++; - } - } -} - -/* @var in makeinfo just uppercases the text. */ -void -cm_var (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++; - } + { + output_paragraph[start_pos] = + coerce_to_upper (output_paragraph[start_pos]); + start_pos++; + } } } @@ -4083,12 +4163,21 @@ cm_not_fixed_width (arg, start, end) not_fixed_width (arg); } -/* Various commands are NOP's. */ +/* Various commands are no-op's. */ void cm_no_op () { } +/* No-op that eats its argument on same line. */ +void +cm_no_op_line_arg () +{ + char *temp; + get_rest_of_line (&temp); + free (temp); +} + /* Prevent the argument from being split across two lines. */ void cm_w (arg, start, end) @@ -4108,7 +4197,7 @@ cm_obsolete (arg, start, end) int arg, start, end; { if (arg == START) - warning ("The command `%c%s' is obsolete", COMMAND_PREFIX, command); + warning (_("%c%s is obsolete"), COMMAND_PREFIX, command); } /* Insert the text following input_text_offset up to the end of the line @@ -4128,7 +4217,7 @@ insert_and_underscore (with_char) no_indent = 1; #if defined (HAVE_MACROS) - if (macro_expansion_output_stream) + if (macro_expansion_output_stream && !executing_string) append_to_expansion_output (input_text_offset + 1); #endif /* HAVE_MACROS */ @@ -4136,11 +4225,9 @@ insert_and_underscore (with_char) starting_pos = output_position + output_paragraph_offset; #if defined (HAVE_MACROS) - if (macro_expansion_output_stream) + if (macro_expansion_output_stream && !executing_string) { - char *temp1; - - temp1 = (char *)xmalloc (2 + strlen (temp)); + char *temp1 = (char *) xmalloc (2 + strlen (temp)); sprintf (temp1, "%s\n", temp); remember_itext (input_text, input_text_offset); me_execute_string (temp1); @@ -4148,7 +4235,7 @@ insert_and_underscore (with_char) } else #endif /* HAVE_MACROS */ - execute_string ("%s\n", temp); + execute_string ("%s\n", temp); ending_pos = output_position + output_paragraph_offset; free (temp); @@ -4237,20 +4324,20 @@ what_section (text) for (j = 0; text[j] && !cr_or_whitespace (text[j]); j++); - for (i = 0; t = section_alist[i].name; i++) + for (i = 0; (t = section_alist[i].name); i++) { if (j == strlen (t) && strncmp (t, text, j) == 0) - { - int return_val; + { + int return_val; - return_val = (section_alist[i].level + section_alist_offset); + 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); - } + if (return_val < 0) + return_val = 0; + else if (return_val > 5) + return_val = 5; + return (return_val); + } } return (-1); } @@ -4265,9 +4352,9 @@ set_top_section_level (level) 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; + result = section_alist[i].level; + section_alist[i].level = level; + break; } return (result); } @@ -4282,25 +4369,25 @@ cm_top () { TAG_ENTRY *tag = tag_table; - line_error ("There already is a node having %ctop as a section", - COMMAND_PREFIX); + 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; - } + { + 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 { @@ -4308,16 +4395,16 @@ cm_top () /* It is an error to use @top before you have used @node. */ 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; - } + { + 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 (); @@ -4326,33 +4413,33 @@ cm_top () /* Now set the logical hierarchical level of the Top node. */ { - int orig_offset = input_text_offset; + int orig_offset = input_text_offset; - input_text_offset = search_forward (node_search_string, orig_offset); + input_text_offset = search_forward (node_search_string, orig_offset); - if (input_text_offset > 0) - { - int this_section; + if (input_text_offset > 0) + { + int this_section; - /* We have encountered a non-top node, so mark that one exists. */ - non_top_node_seen = 1; + /* We have encountered a non-top node, so mark that one exists. */ + non_top_node_seen = 1; - /* Move to the end of this line, and find out what the - sectioning command is here. */ - while (input_text[input_text_offset] != '\n') - input_text_offset++; + /* Move to the end of this line, and find out what the + sectioning command is here. */ + while (input_text[input_text_offset] != '\n') + input_text_offset++; - if (input_text_offset < size_of_input_text) - input_text_offset++; + if (input_text_offset < size_of_input_text) + input_text_offset++; - this_section = what_section (input_text + input_text_offset); + this_section = what_section (input_text + input_text_offset); - /* If we found a sectioning command, then give the top section - a level of this section - 1. */ - if (this_section != -1) - set_top_section_level (this_section - 1); - } - input_text_offset = orig_offset; + /* If we found a sectioning command, then give the top section + a level of this section - 1. */ + if (this_section != -1) + set_top_section_level (this_section - 1); + } + input_text_offset = orig_offset; } } } @@ -4388,8 +4475,8 @@ void cm_ideprecated (arg, start, end) int arg, start, end; { - warning ("The command `%c%s' is obsolete; use `%c%s' instead", - COMMAND_PREFIX, command, COMMAND_PREFIX, command + 1); + warning (_("%c%s is obsolete; use %c%s instead"), + COMMAND_PREFIX, command, COMMAND_PREFIX, command + 1); sectioning_underscore (command + 1); } @@ -4512,9 +4599,9 @@ cm_subsubheading () } /* **************************************************************** */ -/* */ -/* Adding nodes, and making tags */ -/* */ +/* */ +/* Adding nodes, and making tags */ +/* */ /* **************************************************************** */ /* Start a new tag table. */ @@ -4536,7 +4623,7 @@ init_tag_table () void write_tag_table () { - write_tag_table_internal (0); /* Not indirect. */ + write_tag_table_internal (0); /* Not indirect. */ } void @@ -4580,11 +4667,12 @@ write_tag_table_internal (indirect_p) } char * -get_node_token () +get_node_token (expand) + int expand; { char *string; - get_until_in_line (",", &string); + get_until_in_line (expand, ",", &string); if (curchar () == ',') input_text_offset++; @@ -4617,7 +4705,7 @@ find_node (name) while (tag != (TAG_ENTRY *) NULL) { if (strcmp (tag->node, name) == 0) - return (tag); + return (tag); tag = tag->next_ent; } return ((TAG_ENTRY *) NULL); @@ -4634,11 +4722,12 @@ remember_node (node, prev, next, up, position, line_no, no_warn) { register TAG_ENTRY *tag = find_node (node); if (tag) - { - line_error ("Node `%s' multiply defined (%d is first definition)", - node, tag->line_no); - return; - } + { + line_error ( + _("Node `%s' multiply defined (line %d is first definition at)"), + node, tag->line_no); + return; + } } /* First, make this the current node. */ @@ -4654,7 +4743,7 @@ remember_node (node, prev, next, up, position, line_no, no_warn) new->position = position; new->line_no = line_no; new->filename = node_filename; - new->touched = 0; /* not yet referenced. */ + new->touched = 0; /* not yet referenced. */ new->flags = 0; if (no_warn) new->flags |= NO_WARN; @@ -4684,7 +4773,7 @@ cm_node () /* There also might be insertions left lying around that haven't been ended yet. Do that also. */ - discard_insertions (); + discard_insertions (1); if (!already_outputting_pending_notes) { @@ -4698,17 +4787,20 @@ cm_node () current_footnote_number = 1; #if defined (HAVE_MACROS) - if (macro_expansion_output_stream) + if (macro_expansion_output_stream && !executing_string) append_to_expansion_output (input_text_offset + 1); #endif /* HAVE_MACROS */ - node = get_node_token (); - next = get_node_token (); - prev = get_node_token (); - up = get_node_token (); + 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) + if (macro_expansion_output_stream && !executing_string) remember_itext (input_text, input_text_offset); #endif /* HAVE_MACROS */ @@ -4718,18 +4810,16 @@ cm_node () add_word_args ("\037\nFile: %s, Node: ", pretty_output_filename); #if defined (HAVE_MACROS) - if (macro_expansion_output_stream) - me_execute_string (node); + if (macro_expansion_output_stream && !executing_string) + me_execute_string (node); else #endif /* HAVE_MACROS */ - execute_string ("%s", node); + execute_string ("%s", node); filling_enabled = indented_fill = 0; } /* Check for defaulting of this node's next, prev, and up fields. */ - defaulting = ((strlen (next) == 0) && - (strlen (prev) == 0) && - (strlen (up) == 0)); + defaulting = (*next == 0 && *prev == 0 && *up == 0); this_section = what_section (input_text + input_text_offset); @@ -4744,164 +4834,164 @@ cm_node () 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); - } + { + 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) - { - /* Default the NEXT pointer to be the first menu item in - this node, if there is a menu in this node. We have to - try very hard to find the menu, as it may be obscured - by execution_strings which are on the filestack. For - every member of the filestack which has a FILENAME - member which is identical to the current INPUT_FILENAME, - search forward from that offset. */ - 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 (); - - /* No matter what, make this file point back at `(dir)'. */ - free (up); up = strdup ("(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; - } - } - - /* We got here, so it hasn't been found yet. Try - the next file on the filestack if there is one. */ - 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 - { - /* No more input files to check. */ - break; - } - } - - input_text = saved_input_text; - input_text_offset = saved_input_text_offset; - size_of_input_text = saved_size_of_input_text; - } - } + { + if (strcmp (node, "Top") == 0) + { + /* Default the NEXT pointer to be the first menu item in + this node, if there is a menu in this node. We have to + try very hard to find the menu, as it may be obscured + by execution_strings which are on the filestack. For + every member of the filestack which has a FILENAME + member which is identical to the current INPUT_FILENAME, + search forward from that offset. */ + 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 (); + + /* No matter what, make this file point back at `(dir)'. */ + 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; + } + } + + /* We got here, so it hasn't been found yet. Try + the next file on the filestack if there is one. */ + 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 + { + /* No more input files to check. */ + break; + } + } + + input_text = saved_input_text; + input_text_offset = saved_input_text_offset; + size_of_input_text = saved_size_of_input_text; + } + } /* Fix the level of the menu references in the Top node, iff it - was declared with @top, and no subsequent reference was found. */ + was declared with @top, and no subsequent reference was found. */ if (top_node_seen && !non_top_node_seen) - { - /* Then this is the first non-@top node seen. */ - int level; + { + /* Then this is the first non-@top node seen. */ + int level; - level = set_top_section_level (this_section - 1); - non_top_node_seen = 1; + 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; - } + while (ref) + { + if (ref->section == level) + ref->section = this_section - 1; + ref = ref->next; + } - ref = node_references; - } + 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 = strdup (containing_node); - - if (last_ref && - last_ref->type == menu_reference && - (strcmp (last_ref->containing_node, - containing_node) == 0)) - { - free (next); - next = strdup (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 = strdup (ref->next->node); - } - else if (!ref->next && - strcasecmp (ref->containing_node, "Top") == 0) - { - free (prev); - prev = strdup (ref->containing_node); - } - break; - } - last_ref = ref; - ref = ref->next; - } + { + 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) /* Insert the correct args if we are expanding macros, and the node's pointers weren't defaulted. */ - if (macro_expansion_output_stream && !defaulting) + if (macro_expansion_output_stream && !executing_string && !defaulting) { char *temp; int op_orig = output_paragraph_offset; @@ -4929,29 +5019,29 @@ cm_node () { #if defined (HAVE_MACROS) if (macro_expansion_output_stream) - me_inhibit_expansion++; + me_inhibit_expansion++; #endif /* HAVE_MACROS */ if (*next) - { - execute_string (", Next: %s", next); - filling_enabled = indented_fill = 0; - } + { + execute_string (", Next: %s", next); + filling_enabled = indented_fill = 0; + } if (*prev) - { - execute_string (", Prev: %s", prev); - filling_enabled = indented_fill = 0; - } + { + execute_string (", Prev: %s", prev); + filling_enabled = indented_fill = 0; + } if (*up) - { - execute_string (", Up: %s", up); - filling_enabled = indented_fill = 0; - } + { + execute_string (", Up: %s", up); + filling_enabled = indented_fill = 0; + } #if defined (HAVE_MACROS) if (macro_expansion_output_stream) - me_inhibit_expansion--; + me_inhibit_expansion--; #endif /* HAVE_MACROS */ } @@ -4961,7 +5051,7 @@ cm_node () if (!*node) { line_error ("No node name specified for `%c%s' command", - COMMAND_PREFIX, command); + COMMAND_PREFIX, command); free (node); free (next); free (prev); @@ -5012,141 +5102,141 @@ validate_file (tag_table) /* If this is a "no warn" node, don't validate it in any way. */ if (tags->flags & NO_WARN) - { - tags = tags->next_ent; - continue; - } + { + tags = tags->next_ent; + continue; + } /* If this node has a Next, then make sure that the Next exists. */ if (tags->next) - { - validate (tags->next, tags->line_no, "Next"); - - /* If the Next node exists, and there is no Up, then make - sure that the Prev of the Next points back. */ - if (temp_tag = find_node (tags->next)) - { - char *prev; - - if (temp_tag->flags & NO_WARN) - { - /* Do nothing if we aren't supposed to issue warnings - about this node. */ - } - 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; - } - } - } - } + { + validate (tags->next, tags->line_no, "Next"); + + /* If the Next node exists, and there is no Up, then make + sure that the Prev of the Next points back. */ + temp_tag = find_node (tags->next); + if (temp_tag) + { + char *prev; + + if (temp_tag->flags & NO_WARN) + { + /* Do nothing if we aren't supposed to issue warnings + about this node. */ + } + 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; + } + } + } + } /* Validate the Prev field if there is one, and we haven't already - complained about it in some way. You don't have to have a Prev - field at this stage. */ + complained about it in some way. You don't have to have a Prev + field at this stage. */ if (!(tags->flags & PREV_ERROR) && tags->prev) - { - int valid = validate (tags->prev, tags->line_no, "Prev"); - - if (!valid) - tags->flags |= PREV_ERROR; - else - { - /* If the Prev field is not the same as the Up field, - then the node pointed to by the Prev field must have - a Next field which points to this node. */ - if (tags->up && (strcmp (tags->prev, tags->up) != 0)) - { - temp_tag = find_node (tags->prev); - - /* If we aren't supposed to issue warnings about the - target node, do nothing. */ - if (!temp_tag || (temp_tag->flags & NO_WARN)) - { - /* Do nothing. */ - } - 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') is the one with 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' is missing an \"Up\" field", tags->node); + { + int valid_p = validate (tags->prev, tags->line_no, "Prev"); + + if (!valid_p) + tags->flags |= PREV_ERROR; + else + { + /* If the Prev field is not the same as the Up field, + then the node pointed to by the Prev field must have + a Next field which points to this node. */ + if (tags->up && (strcmp (tags->prev, tags->up) != 0)) + { + temp_tag = find_node (tags->prev); + + /* If we aren't supposed to issue warnings about the + target node, do nothing. */ + if (!temp_tag || (temp_tag->flags & NO_WARN)) + { + /* Do nothing. */ + } + 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 = validate (tags->up, tags->line_no, "Up"); - - /* If node X has Up: Y, then warn if Y fails to have a menu item - or note pointing at X, if Y isn't of the form "(Y)". */ - if (valid && *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; - } - } - } + { + int valid_p = validate (tags->up, tags->line_no, "Up"); + + /* If node X has Up: Y, then warn if Y fails to have a menu item + or note pointing at X, if Y isn't of the form "(Y)". */ + 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; } @@ -5159,32 +5249,32 @@ validate_file (tag_table) { /* If this node is a "no warn" node, do nothing. */ if (tags->flags & NO_WARN) - { - tags = tags->next_ent; - continue; - } + { + tags = tags->next_ent; + continue; + } /* Special hack. If the node in question appears to have been referenced more than REFERENCE_WARNING_LIMIT times, give a warning. */ 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); - } + { + 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; - - /* Notice that the node "Top" is special, and doesn't have to - be referenced. */ - if (strcasecmp (tags->node, "Top") != 0) - warning ("Unreferenced node `%s'", tags->node); - } + { + input_filename = tags->filename; + line_number = tags->line_no; + + /* Notice that the node "Top" is special, and doesn't have to + be referenced. */ + if (strcasecmp (tags->node, _("Top")) != 0) + warning (_("unreferenced node `%s'"), tags->node); + } tags = tags->next_ent; } input_filename = old_input_filename; @@ -5210,9 +5300,7 @@ validate (tag, line, label) if (!result) { line_number = line; - line_error ( -"Validation error. `%s' field points to node `%s', which doesn't exist", - label, tag); + line_error (_("%s reference to nonexistent node `%s'"), label, tag); return (0); } result->touched++; @@ -5256,7 +5344,7 @@ split_file (filename, size) root_pathname = pathname_part (filename); if (!root_pathname) - root_pathname = strdup (""); + root_pathname = xstrdup (""); /* Start splitting the file. Walk along the tag table outputting sections of the file. When we have written @@ -5275,122 +5363,122 @@ split_file (filename, size) while (tags) { - int file_top, file_bot, limit; - - /* Have to include the Control-_. */ - file_top = file_bot = tags->position; - limit = file_top + size; - - /* If the rest of this file is only one node, then - that is the entire subfile. */ - 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; - } - - /* Otherwise, find the largest number of nodes that can fit in - this subfile. */ - for (; tags; tags = tags->next_ent) - { - if (!tags->next_ent) - { - /* This entry is the last node. Search forward for the end - of this node, and that is the end of this file. */ - 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 - { - /* Here we want to write out everything before the last - node, and then write the last node out in a file - by itself. */ - 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; - } - } - } + int file_top, file_bot, limit; + + /* Have to include the Control-_. */ + file_top = file_bot = tags->position; + limit = file_top + size; + + /* If the rest of this file is only one node, then + that is the entire subfile. */ + 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; + } + + /* Otherwise, find the largest number of nodes that can fit in + this subfile. */ + for (; tags; tags = tags->next_ent) + { + if (!tags->next_ent) + { + /* This entry is the last node. Search forward for the end + of this node, and that is the end of this file. */ + 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 + { + /* Here we want to write out everything before the last + node, and then write the last node out in a file + by itself. */ + 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; + } + } + } } /* We have sucessfully created the subfiles. Now write out the @@ -5399,8 +5487,8 @@ split_file (filename, size) output_stream = fopen (filename, "w"); if (!output_stream) { - perror (filename); - exit (FATAL); + perror (filename); + exit (FATAL); } { @@ -5419,10 +5507,8 @@ split_file (filename, size) } } -/* Some menu hacking. This is used to remember menu references while - reading the input file. After the output file has been written, if - validation is on, then we use the contents of NODE_REFERENCES as a - list of nodes to validate. */ +/* The strings here are followed in the message by `reference to...' in + the `validate' routine. */ char * reftype_type_string (type) enum reftype type; @@ -5432,13 +5518,16 @@ reftype_type_string (type) case menu_reference: return ("Menu"); case followed_reference: - return ("Followed-Reference"); + return ("Cross"); default: return ("Internal-bad-reference-type"); } } -/* Remember this node name for later validation use. */ +/* Remember this node name for later validation use. This is used to + remember menu references while reading the input file. After the + output file has been written, if validation is on, then we use the + contents of `node_references' as a list of nodes to validate. */ void remember_node_reference (node, line, type) char *node; @@ -5448,11 +5537,11 @@ remember_node_reference (node, line, type) NODE_REF *temp = (NODE_REF *) xmalloc (sizeof (NODE_REF)); temp->next = node_references; - temp->node = strdup (node); + temp->node = xstrdup (node); temp->line_no = line; temp->section = current_section; temp->type = type; - temp->containing_node = strdup (current_node ? current_node : ""); + temp->containing_node = xstrdup (current_node ? current_node : ""); temp->filename = node_filename; node_references = temp; @@ -5468,7 +5557,7 @@ validate_other_references (ref_list) { input_filename = ref_list->filename; validate (ref_list->node, ref_list->line_no, - reftype_type_string (ref_list->type)); + reftype_type_string (ref_list->type)); ref_list = ref_list->next; } input_filename = old_input_filename; @@ -5483,7 +5572,7 @@ find_node_reference (node, ref_list) while (ref_list) { if (strcmp (node, ref_list->node) == 0) - break; + break; ref_list = ref_list->next; } return (ref_list); @@ -5520,13 +5609,13 @@ glean_node_from_menu (remember_reference) char *nodename; if (strncmp (&input_text[input_text_offset + 1], - menu_starter, - strlen (menu_starter)) != 0) + menu_starter, + strlen (menu_starter)) != 0) return ((char *)NULL); else input_text_offset += strlen (menu_starter) + 1; - get_until_in_line (":", &nodename); + get_until_in_line (0, ":", &nodename); if (curchar () == ':') input_text_offset++; canon_white (nodename); @@ -5552,7 +5641,7 @@ save_node: normalize_node_name (nodename); i = strlen (nodename); if (i && nodename[i - 1] == ':') - nodename[i - 1] = '\0'; + nodename[i - 1] = 0; if (remember_reference) { @@ -5579,7 +5668,7 @@ isolate_nodename (nodename) if (*nodename == '.' || !*nodename) { - *nodename = '\0'; + *nodename = 0; return; } @@ -5590,32 +5679,32 @@ isolate_nodename (nodename) i++; } - for (; c = nodename[i]; i++) + for (; (c = nodename[i]); i++) { if (paren) - { - if (c == '(') - paren++; - else if (c == ')') - paren--; + { + if (c == '(') + paren++; + else if (c == ')') + paren--; - continue; - } + continue; + } /* If the character following the close paren is a space, then this - node has no more characters associated with it. */ + node has no more characters associated with it. */ 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; + 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'; + nodename[i] = 0; } void @@ -5623,8 +5712,8 @@ cm_menu () { if (current_node == (char *)NULL) { - warning ("%cmenu seen before a node has been defined", COMMAND_PREFIX); - warning ("Creating `TOP' node."); + warning (_("%cmenu seen before first node"), COMMAND_PREFIX); + warning (_("creating `Top' node")); execute_string ("@node Top"); } begin_insertion (menu); @@ -5635,19 +5724,21 @@ cm_detailmenu () { if (current_node == (char *)NULL) { - warning ("%cmenu seen before a node has been defined", COMMAND_PREFIX); - warning ("Creating `TOP' node."); + warning (_("%cmenu seen before first node"), COMMAND_PREFIX); + warning (_("creating `Top' node")); execute_string ("@node Top"); } begin_insertion (detailmenu); } /* **************************************************************** */ -/* */ -/* Cross Reference Hacking */ -/* */ +/* */ +/* Cross Reference Hacking */ +/* */ /* **************************************************************** */ +/* Return next comma-delimited argument, but do not cross a close-brace + boundary. Clean up whitespace, too. */ char * get_xref_token () { @@ -5660,7 +5751,7 @@ get_xref_token () return (string); } -int px_ref_flag = 0; /* Controls initial output string. */ +int px_ref_flag = 0; /* Controls initial output string. */ /* Make a cross reference. */ void @@ -5679,45 +5770,45 @@ cm_xref (arg) 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); - /* Free all of the arguments found. */ - if (arg1) free (arg1); - if (arg2) free (arg2); - if (arg3) free (arg3); - if (arg4) free (arg4); - if (arg5) free (arg5); - return; - } + { + 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); + /* Free all of the arguments found. */ + 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); + 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); - } + { + 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 (*arg2) + execute_string ("%s: %s", arg2, arg1); + else + execute_string ("%s::", arg1); + } /* Free all of the arguments found. */ if (arg1) free (arg1); @@ -5734,26 +5825,25 @@ cm_xref (arg) int temp = input_text_offset + 1; if (output_paragraph[output_paragraph_offset - 2] == ':' && - output_paragraph[output_paragraph_offset - 1] == ':') - return; + 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') - return; - else - { - line_error ( - "Cross-reference must be terminated with a period or a comma"); - return; - } - } - } + { + 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; + } + } } } @@ -5777,20 +5867,159 @@ cm_inforef (arg) { if (arg == START) { - char *node, *pname, *file; + 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); + } +} + +/* A URL reference. */ +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, ','); /* let's hope for no commas in the url */ + if (comma) + { + *comma = 0; + /* Ignore spaces at beginning of second arg. */ + 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); + } +} + +/* An email reference. */ +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]; - node = get_xref_token (); - pname = get_xref_token (); - file = get_xref_token (); + output_paragraph[end_pos] = 0; + output_column -= end_pos - start_pos; + output_paragraph_offset = start_pos; - execute_string ("*note %s: (%s)%s", pname, file, node); + 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); + } +} + +/* An external image is a reference, kind of. The parsing is (not + coincidentally) similar, anyway. */ +void +cm_image (arg) + int arg; +{ + if (arg == START) + { + char *name_arg = get_xref_token (); + /* We don't yet care about any other args, but read them so they + don't end up in the text. */ + char *arg = get_xref_token (); + if (arg) free (arg); + arg = get_xref_token (); + if (arg) free (arg); + + if (*name_arg) + { + /* Try to open foo.txt. */ + 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; + + /* Maybe we need to remove the final newline if the image + file is only one line to allow in-line images. On the + other hand, they could just make the file without a + final newline. */ + 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); } } /* **************************************************************** */ -/* */ -/* Insertion Command Stubs */ -/* */ +/* */ +/* Insertion Command Stubs */ +/* */ /* **************************************************************** */ void @@ -5824,7 +6053,7 @@ cm_smalllisp () } /* @cartouche/@end cartouche draws box with rounded corners in - TeX output. Right now, just a NOP insertion. */ + TeX output. Right now, just a no-op insertion. */ void cm_cartouche () { @@ -5871,26 +6100,26 @@ do_enumeration (type, default_string) int type; char *default_string; { - get_until_in_line (".", &enumeration_arg); + get_until_in_line (0, ".", &enumeration_arg); canon_white (enumeration_arg); if (!*enumeration_arg) { free (enumeration_arg); - enumeration_arg = strdup (default_string); + enumeration_arg = xstrdup (default_string); } if (!isdigit (*enumeration_arg) && !isletter (*enumeration_arg)) { - warning ("%s requires a letter or a digit", insertion_type_pname (type)); + warning (_("%s requires letter or digit"), insertion_type_pname (type)); switch (type) - { - case enumerate: - default_string = "1"; - break; - } - enumeration_arg = strdup (default_string); + { + case enumerate: + default_string = "1"; + break; + } + enumeration_arg = xstrdup (default_string); } begin_insertion (type); } @@ -5904,7 +6133,7 @@ cm_table () void cm_multitable () { - begin_insertion (multitable); /* @@ */ + begin_insertion (multitable); /* @@ */ } void @@ -5931,6 +6160,18 @@ cm_ifinfo () begin_insertion (ifinfo); } +void +cm_ifnothtml () +{ + begin_insertion (ifnothtml); +} + +void +cm_ifnottex () +{ + begin_insertion (ifnottex); +} + /* Begin an insertion where the lines are not filled or indented. */ void cm_flushleft () @@ -5945,11 +6186,40 @@ cm_flushright () { begin_insertion (flushright); } + +/* End existing insertion block. */ +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); +} /* **************************************************************** */ -/* */ -/* Conditional Handling */ -/* */ +/* */ +/* Conditional Handling */ +/* */ /* **************************************************************** */ /* A structure which contains `defined' variables. */ @@ -5973,15 +6243,15 @@ set (name, value) for (temp = defines; temp; temp = temp->next) if (strcmp (name, temp->name) == 0) { - free (temp->value); - temp->value = strdup (value); - return; + free (temp->value); + temp->value = xstrdup (value); + return; } temp = (DEFINE *)xmalloc (sizeof (DEFINE)); temp->next = defines; - temp->name = strdup (name); - temp->value = strdup (value); + temp->name = xstrdup (name); + temp->value = xstrdup (value); defines = temp; } @@ -5998,17 +6268,17 @@ clear (name) 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; - } + { + if (last) + last->next = temp->next; + else + defines = temp->next; + + free (temp->name); + free (temp->value); + free (temp); + break; + } last = temp; temp = temp->next; } @@ -6078,7 +6348,6 @@ cm_ifclear () void cm_ifeq () { - register int i; char **arglist; arglist = get_brace_args (0); @@ -6086,11 +6355,11 @@ cm_ifeq () if (arglist) { if (array_len (arglist) > 1) - { - if ((strcasecmp (arglist[0], arglist[1]) == 0) && - (arglist[2] != (char *)NULL)) - execute_string ("%s\n", arglist[2]); - } + { + if ((strcasecmp (arglist[0], arglist[1]) == 0) && + (arglist[2] != (char *)NULL)) + execute_string ("%s\n", arglist[2]); + } free_array (arglist); } @@ -6102,10 +6371,10 @@ cm_value (arg, start_pos, end_pos) { if (arg == END) { - char *name, *value; - name = (char *)&output_paragraph[start_pos]; - output_paragraph[end_pos] = '\0'; - name = strdup (name); + 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; @@ -6113,7 +6382,7 @@ cm_value (arg, start_pos, end_pos) if (value) execute_string ("%s", value); else - add_word_args ("{No Value For \"%s\"}", name); + add_word_args (_("{No Value For \"%s\"}"), name); free (name); } @@ -6128,7 +6397,6 @@ handle_variable (action) get_rest_of_line (&name); backup_input_pointer (); - canon_white (name); handle_variable_internal (action, name); free (name); } @@ -6148,12 +6416,12 @@ handle_variable_internal (action, name) { /* #if defined (SET_WITH_EQUAL) */ if (*temp == '"' || *temp == '\'') - { - if (*temp == delimiter) - delimiter = 0; - else - delimiter = *temp; - } + { + if (*temp == delimiter) + delimiter = 0; + else + delimiter = *temp; + } /* #endif SET_WITH_EQUAL */ temp++; } @@ -6161,135 +6429,146 @@ handle_variable_internal (action, name) if (*temp) additional_text_present++; - *temp = '\0'; + *temp = 0; if (!*name) - line_error ("%c%s requires a name", COMMAND_PREFIX, command); + line_error (_("%c%s requires a name"), COMMAND_PREFIX, command); else { switch (action) - { - case SET: - { - char *value; + { + case SET: + { + char *value; #if defined (SET_WITH_EQUAL) - /* Allow a value to be saved along with a variable. The value is - the text following an `=' sign in NAME, if any is present. */ + /* Allow a value to be saved along with a variable. The value is + the text following an `=' sign in NAME, if any is present. */ - for (value = name; *value && *value != '='; value++); + for (value = name; *value && *value != '='; value++); - if (*value) - *value++ = '\0'; + if (*value) + *value++ = 0; - if (*value == '"' || *value == '\'') - { - value++; - value[strlen (value) - 1] = '\0'; - } + if (*value == '"' || *value == '\'') + { + value++; + value[strlen (value) - 1] = 0; + } #else /* !SET_WITH_EQUAL */ - /* The VALUE of NAME is the remainder of the line sans - whitespace. */ - if (additional_text_present) - { - value = temp + 1; - canon_white (value); - } - else - value = ""; + /* The VALUE of NAME is the remainder of the line sans + whitespace. */ + if (additional_text_present) + { + value = temp + 1; + canon_white (value); + } + else + value = ""; #endif /* !SET_WITH_VALUE */ - set (name, value); - } - break; - - case CLEAR: - clear (name); - break; - - case IFSET: - case IFCLEAR: - /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set, - read lines from the the file until we reach a matching - "@end CONDITION". This means that we only take note of - "@ifset/clear" and "@end" commands. */ - { - char condition[8]; - int condition_len; - - 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) - { - 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); - } - /* We found the end of a false @ifset/ifclear. If we are - in a menu, back up over the newline that ends the ifset, - since that newline may also begin the next menu entry. */ - break; - } - else - { - if (action == IFSET) - begin_insertion (ifset); - else - begin_insertion (ifclear); - } - } - break; - } + set (name, value); + } + break; + + case CLEAR: + clear (name); + break; + + case IFSET: + case IFCLEAR: + /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set, + read lines from the the file until we reach a matching + "@end CONDITION". This means that we only take note of + "@ifset/clear" and "@end" commands. */ + { + 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; + } + + /* We found the end of a false @ifset/ifclear. If we are + in a menu, back up over the newline that ends the ifset, + since that newline may also begin the next menu entry. */ + break; + } + else + { + if (action == IFSET) + begin_insertion (ifset); + else + begin_insertion (ifclear); + } + } + break; + } } } /* Execution of random text not in file. */ typedef struct { - char *string; /* The string buffer. */ - int size; /* The size of the buffer. */ - int in_use; /* Non-zero means string currently in use. */ + char *string; /* The string buffer. */ + int size; /* The size of the buffer. */ + int in_use; /* Nonzero means string currently in use. */ } EXECUTION_STRING; static EXECUTION_STRING **execution_strings = (EXECUTION_STRING **)NULL; @@ -6306,26 +6585,26 @@ get_execution_string (initial_size) 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 (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_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)); + (EXECUTION_STRING *)xmalloc (sizeof (EXECUTION_STRING)); es = execution_strings[execution_strings_index]; execution_strings_index++; @@ -6344,46 +6623,37 @@ get_execution_string (initial_size) /* Execute the string produced by formatting the ARGs with FORMAT. This is like submitting a new file with @include. */ -#if defined (HAVE_VARARGS_H) && defined (HAVE_VSPRINTF) void -execute_string (va_alist) - va_dcl -{ - EXECUTION_STRING *es; - char *temp_string; - char *format; - va_list args; - - es = get_execution_string (4000); - temp_string = es->string; - es->in_use = 1; - - va_start (args); - format = va_arg (args, char *); - vsprintf (temp_string, format, args); - va_end (args); - -#else /* !(HAVE_VARARGS_H && HAVE_VSPRINTF) */ - -void -execute_string (format, arg1, arg2, arg3, arg4, arg5) - char *format; +#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; - sprintf (temp_string, format, arg1, arg2, arg3, arg4, arg5); - -#endif /* !(HAVE_VARARGS_H && HAVE_VSPRINTF) */ + 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 /* not VA_SPRINTF */ + va_end (ap); pushfile (); input_text_offset = 0; input_text = temp_string; - input_filename = strdup (input_filename); + input_filename = xstrdup (input_filename); size_of_input_text = strlen (temp_string); executing_string++; @@ -6412,6 +6682,7 @@ expansion (str, implicit_code) 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 (); @@ -6455,179 +6726,183 @@ cm_item () original_input_text_offset = input_text_offset; get_rest_of_line (&rest_of_line); - canon_white (rest_of_line); item_func = current_item_function (); /* Okay, do the right thing depending on which insertion function - is active. */ + is active. */ switch_top: switch (stack->insertion) - { - case multitable: - multitable_item (); - /* Ultra special hack. It appears that some people incorrectly - place text directly after the @item, instead of on a new line - by itself. This happens to work in TeX, so I make it work - here. */ - 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); - - /* I need some way to determine whether this command - takes braces or not. I believe the user can type - either "@bullet" or "@bullet{}". Of course, they - can also type "o" or "#" or whatever else they want. */ - 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 (); - - /* Special hack. This makes close paragraph ignore you until - the start_paragraph () function has been called. */ - must_start_paragraph = 1; - - /* Ultra special hack. It appears that some people incorrectly - place text directly after the @item, instead of on a new line - by itself. This happens to work in TeX, so I make it work - here. */ - if (*rest_of_line) - { - line_number--; - input_text_offset = original_input_text_offset; - } - } - break; - - case table: - case ftable: - case vtable: - { - /* Get rid of extra characters. */ - kill_self_indent (-1); - - /* close_paragraph () almost does what we want. The problem - is when paragraph_is_open, and last_char_was_newline, and - the last newline has been turned into a space, because - filling_enabled. I handle it here. */ - if (last_char_was_newline && filling_enabled && paragraph_is_open) - insert ('\n'); - close_paragraph (); + { + case multitable: + multitable_item (); + /* Ultra special hack. It appears that some people incorrectly + place text directly after the @item, instead of on a new line + by itself. This happens to work in TeX, so I make it work + here. */ + 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); + + /* I need some way to determine whether this command + takes braces or not. I believe the user can type + either "@bullet" or "@bullet{}". Of course, they + can also type "o" or "#" or whatever else they want. */ + 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 (); + + /* Special hack. This makes `close_paragraph' a no-op until + `start_paragraph' has been called. */ + must_start_paragraph = 1; + + /* Handle text directly after the @item. */ + if (*rest_of_line) + { + line_number--; + input_text_offset = original_input_text_offset; + } + } + break; + + case table: + case ftable: + case vtable: + { + /* We need this to determine if we have two @item's in a row + (see test just below). */ + static int last_item_output_position = 0; + + /* Get rid of extra characters. */ + kill_self_indent (-1); + + /* If we have one @item followed directly by another @item, + we need to insert a blank line. This is not true for + @itemx, though. */ + if (!itemx_flag && last_item_output_position == output_position) + insert ('\n'); + + /* `close_paragraph' almost does what we want. The problem + is when paragraph_is_open, and last_char_was_newline, and + the last newline has been turned into a space, because + filling_enabled. I handle it here. */ + if (last_char_was_newline && filling_enabled && paragraph_is_open) + insert ('\n'); + close_paragraph (); #if defined (INDENT_PARAGRAPHS_IN_TABLE) - /* Indent on a new line, but back up one indentation level. */ - { - int t; - - t = inhibit_paragraph_indentation; - inhibit_paragraph_indentation = 1; - /* At this point, inserting any non-whitespace character will - force the existing indentation to be output. */ - add_char ('i'); - inhibit_paragraph_indentation = t; - } + /* Indent on a new line, but back up one indentation level. */ + { + int save = inhibit_paragraph_indentation; + inhibit_paragraph_indentation = 1; + /* At this point, inserting any non-whitespace character will + force the existing indentation to be output. */ + add_char ('i'); + inhibit_paragraph_indentation = save; + } #else /* !INDENT_PARAGRAPHS_IN_TABLE */ - add_char ('i'); + add_char ('i'); #endif /* !INDENT_PARAGRAPHS_IN_TABLE */ - output_paragraph_offset--; - kill_self_indent (default_indentation_increment + 1); - - /* Add item's argument to the line. */ - 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); - - if (current_insertion_type () == vtable) - execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line); - - /* Start a new line, and let start_paragraph () - do the indenting of it for you. */ - close_single_paragraph (); - indented_fill = filling_enabled = 1; - } - } + output_paragraph_offset--; + kill_self_indent (default_indentation_increment + 1); + + /* Add item's argument to the line. */ + 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); + + /* Start a new line, and let start_paragraph () + do the indenting of it for you. */ + 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); + line_error (_("%c%s found outside of an insertion block"), + COMMAND_PREFIX, command); } } /* **************************************************************** */ -/* */ -/* Defun and Friends */ -/* */ +/* */ +/* Defun and Friends */ +/* */ /* **************************************************************** */ -#define DEFUN_SELF_DELIMITING(c) \ - (((c) == '(') \ - || ((c) == ')') \ - || ((c) == '[') \ +#define DEFUN_SELF_DELIMITING(c) \ + (((c) == '(') \ + || ((c) == ')') \ + || ((c) == '[') \ || ((c) == ']')) struct token_accumulator @@ -6655,7 +6930,7 @@ accumulate_token (accumulator, token) { (accumulator->length) += 10; (accumulator->tokens) = (char **) xrealloc - (accumulator->tokens, (accumulator->length * sizeof (char *))); + (accumulator->tokens, (accumulator->length * sizeof (char *))); } accumulator->tokens[accumulator->index] = token; accumulator->index += 1; @@ -6675,7 +6950,7 @@ copy_substring (start, end) while (scan < end) *scan_result++ = *scan++; - *scan_result = '\0'; + *scan_result = 0; return (result); } @@ -6694,25 +6969,25 @@ scan_group_in_string (string_pointer) while (1) { if (level == 0) - { - (*string_pointer) = scan_string; - return (1); - } + { + (*string_pointer) = scan_string; + return (1); + } c = (*scan_string++); - if (c == '\0') - { - /* Tweak line_number to compensate for fact that - we gobbled the whole line before coming here. */ - line_number -= 1; - line_error ("Missing `}' in %cdef arg", COMMAND_PREFIX); - line_number += 1; - (*string_pointer) = (scan_string - 1); - return (0); - } + if (c == 0) + { + /* Tweak line_number to compensate for fact that + we gobbled the whole line before coming here. */ + 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; + level += 1; if (c == '}') - level -= 1; + level -= 1; } } @@ -6730,103 +7005,103 @@ args_from_string (string) initialize_token_accumulator (&accumulator); - while ((*scan_string) != '\0') + while ((*scan_string) != 0) { /* Replace arbitrary whitespace by a single space. */ if (whitespace (*scan_string)) - { - scan_string += 1; - while (whitespace (*scan_string)) - scan_string += 1; - accumulate_token ((&accumulator), (strdup (" "))); - continue; - } + { + scan_string += 1; + while (whitespace (*scan_string)) + scan_string += 1; + accumulate_token ((&accumulator), (xstrdup (" "))); + continue; + } /* Commands count as single tokens. */ 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; - } + { + 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; + } /* Parentheses and brackets are self-delimiting. */ else if (DEFUN_SELF_DELIMITING (*scan_string)) - { - token_start = scan_string; - scan_string += 1; - token_end = scan_string; - } + { + token_start = scan_string; + scan_string += 1; + token_end = scan_string; + } /* Open brace introduces a group that is a single token. */ else if (*scan_string == '{') - { - char *s = scan_string; - int balanced = scan_group_in_string (&s); + { + 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; - } + token_start = scan_string + 1; + scan_string = s; + token_end = balanced ? (scan_string - 1) : scan_string; + } /* Otherwise a token is delimited by whitespace, parentheses, - brackets, or braces. A token is also ended by a command. */ + brackets, or braces. A token is also ended by a command. */ else - { - token_start = scan_string; + { + token_start = scan_string; - while (1) - { - register int c; + while (1) + { + register int c; - c = *scan_string++; + c = *scan_string++; /* Do not back up if we're looking at a }; since the only valid }'s are those matched with {'s, we want to give an error. If we back up, we go into an infinite loop. */ - if (!c || whitespace (c) || DEFUN_SELF_DELIMITING (c) - || c == '{') - { - scan_string--; - break; - } - - /* If we encounter a command embedded within a token, - then end the token. */ - if (c == COMMAND_PREFIX) - { - scan_string--; - break; - } - } - token_end = scan_string; - } + if (!c || whitespace (c) || DEFUN_SELF_DELIMITING (c) + || c == '{') + { + scan_string--; + break; + } + + /* If we encounter a command embedded within a token, + then end the token. */ + if (c == COMMAND_PREFIX) + { + scan_string--; + break; + } + } + token_end = scan_string; + } accumulate_token - (&accumulator, copy_substring (token_start, token_end)); + (&accumulator, copy_substring (token_start, token_end)); } accumulate_token (&accumulator, NULL); return (accumulator.tokens); @@ -6844,30 +7119,30 @@ process_defun_args (defun_args, auto_var_p) char *defun_arg = *defun_args++; if (defun_arg == NULL) - break; + break; if (defun_arg[0] == ' ') - { - pending_space = 1; - continue; - } + { + pending_space = 1; + continue; + } if (pending_space) - { - add_char (' '); - pending_space = 0; - } + { + add_char (' '); + pending_space = 0; + } if (DEFUN_SELF_DELIMITING (defun_arg[0])) - add_char (defun_arg[0]); + add_char (defun_arg[0]); else if (defun_arg[0] == '&') - add_word (defun_arg); + add_word (defun_arg); else if (defun_arg[0] == COMMAND_PREFIX) - execute_string ("%s", defun_arg); + execute_string ("%s", defun_arg); else if (auto_var_p) - execute_string ("%cvar{%s}", COMMAND_PREFIX, defun_arg); + execute_string ("%cvar{%s}", COMMAND_PREFIX, defun_arg); else - add_word (defun_arg); + add_word (defun_arg); } } @@ -6891,7 +7166,7 @@ next_nonwhite_defun_arg (arg_pointer) /* Make the defun type insertion. TYPE says which insertion this is. - X_P says not to start a new insertion if non-zero. */ + X_P, if nonzero, says not to start a new insertion. */ void defun_internal (type, x_p) enum insertion_type type; @@ -6913,43 +7188,43 @@ defun_internal (type, x_p) switch (type) { case defun: - category = "Function"; + category = _("Function"); base_type = deffn; break; case defmac: - category = "Macro"; + category = _("Macro"); base_type = deffn; break; case defspec: - category = "Special Form"; + category = _("Special Form"); base_type = deffn; break; case defvar: - category = "Variable"; + category = _("Variable"); base_type = defvr; break; case defopt: - category = "User Option"; + category = _("User Option"); base_type = defvr; break; case deftypefun: - category = "Function"; + category = _("Function"); base_type = deftypefn; break; case deftypevar: - category = "Variable"; + category = _("Variable"); base_type = deftypevr; break; case defivar: - category = "Instance Variable"; + category = _("Instance Variable"); base_type = defcv; break; case defmethod: - category = "Method"; + category = _("Method"); base_type = defop; break; case deftypemethod: - category = "Method"; + category = _("Method"); base_type = deftypemethod; break; default: @@ -7015,7 +7290,7 @@ defun_internal (type, x_p) break; case deftypemethod: execute_string (" -- %s on %s: %s %s", category, type_name, type_name2, - defined_name); + defined_name); break; } current_indent += default_indentation_increment; @@ -7032,38 +7307,42 @@ defun_internal (type, x_p) case defop: process_defun_args (scan_args, 1); break; - case deftp: - case deftypefn: - case deftypemethod: + + /* Through Makeinfo 1.67 we processed remaining args only for deftp, + deftypefn, and deftypemethod. But the libc manual, for example, + needs to say: + @deftypevar {char *} tzname[2] + And simply allowing the extra text seems far simpler than trying + to invent yet more defn commands. In any case, we should either + output it or give an error, not silently ignore it. */ + default: process_defun_args (scan_args, 0); break; } current_indent -= default_indentation_increment; close_single_paragraph (); - if (!macro_expansion_output_stream) - /* Make an entry in the appropriate index unless we are just - expanding macros. */ - 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; - } + /* Make an entry in the appropriate index. */ + 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; + } /* Deallocate the token list. */ scan_args = defun_args; @@ -7071,7 +7350,7 @@ defun_internal (type, x_p) { char * arg = (*scan_args++); if (arg == NULL) - break; + break; free (arg); } free (defun_args); @@ -7085,12 +7364,12 @@ cm_defun () { int x_p; enum insertion_type type; - char *temp = strdup (command); + char *temp = xstrdup (command); x_p = (command[strlen (command) - 1] == 'x'); if (x_p) - temp[strlen (temp) - 1] = '\0'; + temp[strlen (temp) - 1] = 0; type = find_type_from_name (temp); free (temp); @@ -7100,8 +7379,8 @@ cm_defun () 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); + line_error (_("Must be in a `%s' insertion in order to use `%s'x"), + command, command); discard_until ("\n"); return; } @@ -7109,40 +7388,10 @@ cm_defun () defun_internal (type, x_p); } -/* End existing insertion block. */ -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); - canon_white (temp); - - if (strlen (temp) == 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); -} - /* **************************************************************** */ -/* */ -/* Other Random Commands */ -/* */ +/* */ +/* Other Random Commands */ +/* */ /* **************************************************************** */ /* This says to inhibit the indentation of the next paragraph, but @@ -7202,15 +7451,15 @@ cm_sp () if (sscanf (line, "%d", &lines) != 1) { - line_error ("%csp requires a positive numeric argument", COMMAND_PREFIX); + line_error (_("%csp requires a positive numeric argument"), COMMAND_PREFIX); } else { if (lines < 0) - lines = 0; + lines = 0; while (lines--) - add_char ('\n'); + add_char ('\n'); } free (line); } @@ -7221,11 +7470,11 @@ cm_sp () void cm_dircategory () { - char *line, *p; + char *line; get_rest_of_line (&line);; - if (! no_headers) + if (!no_headers) { insert_string ("INFO-DIR-SECTION "); insert_string (line); @@ -7257,7 +7506,7 @@ cm_center () i = output_paragraph_offset - 1; while (i > (start - 1) && output_paragraph[i] == '\n') - i--; + i--; output_paragraph_offset = ++i; length = output_paragraph_offset - start; @@ -7271,10 +7520,10 @@ cm_center () output_paragraph_offset = start; while (i--) - insert (' '); + insert (' '); for (i = 0; i < length; i++) - insert (line[i]); + insert (line[i]); free (line); } @@ -7357,20 +7606,6 @@ cm_exdent () close_single_paragraph (); } -#if !defined (HAVE_STRERROR) -extern char *sys_errlist[]; -extern int sys_nerr; - -char * -strerror (num) - int num; -{ - if (num >= sys_nerr) - return ("Unknown file system error"); - else - return (sys_errlist[num]); -} -#endif /* !HAVE_STRERROR */ /* Remember this file, and move onto the next. */ void @@ -7379,7 +7614,7 @@ cm_include () char *filename; #if defined (HAVE_MACROS) - if (macro_expansion_output_stream) + if (macro_expansion_output_stream && !executing_string) me_append_before_this_command (); #endif /* HAVE_MACROS */ @@ -7387,7 +7622,7 @@ cm_include () get_rest_of_line (&filename); #if defined (HAVE_MACROS) - if (macro_expansion_output_stream) + if (macro_expansion_output_stream && !executing_string) remember_itext (input_text, input_text_offset); #endif /* HAVE_MACROS */ @@ -7416,8 +7651,8 @@ cm_include () line_number--; /* Cannot "@include foo", in line 5 of "/wh/bar". */ - line_error ("`%c%s %s': %s", COMMAND_PREFIX, command, filename, - strerror (errno)); + line_error ("%c%s %s: %s", COMMAND_PREFIX, command, filename, + strerror (errno)); free (filename); return; @@ -7425,8 +7660,8 @@ cm_include () else { #if defined (HAVE_MACROS) - if (macro_expansion_output_stream) - remember_itext (input_text, input_text_offset); + if (macro_expansion_output_stream && !executing_string) + remember_itext (input_text, input_text_offset); #endif /* HAVE_MACROS */ reader_loop (); } @@ -7438,7 +7673,7 @@ cm_include () void misplaced_brace () { - line_error ("Misplaced `}'"); + line_error (_("Misplaced %c"), '}'); } /* Signals end of processing. Easy to make this happen. */ @@ -7447,11 +7682,51 @@ cm_bye () { input_text_offset = size_of_input_text; } + +/* Set the paragraph indentation variable to the value specified in STRING. + Values can be: + `asis': Don't change existing indentation. + `none': Remove existing indentation. + NUM: Indent NUM spaces at the starts of paragraphs. + If NUM is zero, we assume `none'. + Returns 0 if successful, or nonzero if STRING isn't one of the above. */ +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); +} /* **************************************************************** */ -/* */ -/* Indexing Stuff */ -/* */ +/* */ +/* Indexing Stuff */ +/* */ /* **************************************************************** */ @@ -7459,21 +7734,48 @@ cm_bye () typedef struct index_elt { struct index_elt *next; - char *entry; /* The index entry itself. */ - char *node; /* The node from whence it came. */ - int code; /* Non-zero means add `@code{...}' when - printing this element. */ - int defining_line; /* Line number where this entry was written. */ + char *entry; /* The index entry itself. */ + char *node; /* The node from whence it came. */ + int code; /* Nonzero means add `@code{...}' when + printing this element. */ + int defining_line; /* Line number where this entry was written. */ + char *defining_file; /* Source file for defining_line. */ } INDEX_ELT; -/* A list of short-names for each index, and the index to that index in our - index array, the_indices. In addition, for each index, it is remembered - whether that index is a code index or not. Code indices have @code{} - inserted around the first word when they are printed with printindex. */ +/* A list of short-names for each index. + + There are two indices into the the_indices array. + + * read_index is the index that points to the list of index + entries that we will find if we ask for the list of entries for + this name. + + * write_index is the index that points to the list of index entries + that we will add new entries to. + + Initially, read_index and write index are the same, but the + @syncodeindex and @synindex commands can change the list we add + entries to. + + For example, after the commands + + @cindex foo + @defindex ii + @synindex cp ii + @cindex bar + + the cp index will contain the entry `foo', and the new ii + index will contain the entry `bar'. This is consistent with the + way texinfo.tex handles the same situation. + + In addition, for each index, it is remembered whether that index is + a code index or not. Code indices have @code{} inserted around the + first word when they are printed with printindex. */ typedef struct { char *name; - int index; + int read_index; /* index entries for `name' */ + int write_index; /* store index entries here, @synindex can change it */ int code; } INDEX_ALIST; @@ -7487,14 +7789,6 @@ INDEX_ELT **the_indices = (INDEX_ELT **) NULL; /* The number of defined indices. */ int defined_indices = 0; -/* We predefine these. */ -#define program_index 0 -#define function_index 1 -#define concept_index 2 -#define variable_index 3 -#define datatype_index 4 -#define key_index 5 - void init_indices () { @@ -7506,26 +7800,38 @@ init_indices () if (!the_indices) { the_indices = (INDEX_ELT **) xmalloc ((1 + defined_indices) * - sizeof (INDEX_ELT *)); + sizeof (INDEX_ELT *)); the_indices[defined_indices] = (INDEX_ELT *) NULL; name_index_alist = (INDEX_ALIST **) xmalloc ((1 + defined_indices) * - sizeof (INDEX_ALIST *)); + sizeof (INDEX_ALIST *)); name_index_alist[defined_indices] = (INDEX_ALIST *) NULL; } /* If there were existing indices, get rid of them now. */ for (i = 0; i < defined_indices; i++) - undefindex (name_index_alist[i]->name); + { + undefindex (name_index_alist[i]->name); + if (name_index_alist[i]) + { /* Suppose we're called with two input files, and the first + does a @synindex pg cp. Then, when we get here to start + the second file, the "pg" element won't get freed by + undefindex (because it's pointing to "cp"). So free it + here; otherwise, when we try to define the pg index again + just below, it will still point to cp. */ + free (name_index_alist[i]->name); + free (name_index_alist[i]); + name_index_alist[i] = (INDEX_ALIST *) NULL; + } + } /* Add the default indices. */ - top_defindex ("pg", 0); - top_defindex ("fn", 1); /* "fn" is a code index. */ - top_defindex ("cp", 0); - top_defindex ("vr", 0); - top_defindex ("tp", 0); - top_defindex ("ky", 0); - + top_defindex ("cp", 0); /* cp is the only non-code index. */ + top_defindex ("fn", 1); + top_defindex ("ky", 1); + top_defindex ("pg", 1); + top_defindex ("tp", 1); + top_defindex ("vr", 1); } /* Find which element in the known list of indices has this name. @@ -7537,8 +7843,8 @@ find_index_offset (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 (name_index_alist[i]->index); + strcmp (name, name_index_alist[i]->name) == 0) + return (i); return (-1); } @@ -7564,7 +7870,7 @@ translate_index (name) INDEX_ALIST *which = find_index (name); if (which) - return (which->index); + return (which->read_index); else return (-1); } @@ -7591,13 +7897,16 @@ free_index (index) while ((temp = index) != (INDEX_ELT *) NULL) { free (temp->entry); - free (temp->node); + /* Do not free the node, because we already freed the tag table, + which freed all the node names. */ + /* free (temp->node); */ index = index->next; free (temp); } } -/* Flush an index by name. */ +/* Flush an index by name. This will delete the list of entries that + would be written by a @printindex command for this index. */ void undefindex (name) char *name; @@ -7605,10 +7914,12 @@ undefindex (name) int i; int which = find_index_offset (name); - if (which < 0) + /* The index might have already been freed if this was the target of + an @synindex. */ + if (which < 0 || !name_index_alist[which]) return; - i = name_index_alist[which]->index; + i = name_index_alist[which]->read_index; free_index (the_indices[i]); the_indices[i] = (INDEX_ELT *) NULL; @@ -7619,7 +7930,7 @@ undefindex (name) } /* Define an index known as NAME. We assign the slot number. - CODE if non-zero says to make this a code index. */ + CODE if Nonzero says to make this a code index. */ void defindex (name, code) char *name; @@ -7635,8 +7946,8 @@ defindex (name, code) for (i = 0; i < defined_indices; i++) if (!name_index_alist[i]) { - slot = i; - break; + slot = i; + break; } if (slot < 0) @@ -7646,17 +7957,18 @@ defindex (name, code) defined_indices++; name_index_alist = (INDEX_ALIST **) - xrealloc ((char *)name_index_alist, - (1 + defined_indices) * sizeof (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 *)); + xrealloc ((char *)the_indices, + (1 + defined_indices) * sizeof (INDEX_ELT *)); } /* We have a slot. Start assigning. */ name_index_alist[slot] = (INDEX_ALIST *) xmalloc (sizeof (INDEX_ALIST)); - name_index_alist[slot]->name = strdup (name); - name_index_alist[slot]->index = slot; + 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; @@ -7673,10 +7985,10 @@ index_add_arg (name) tem = find_index (name); - which = tem ? tem->index : -1; + which = tem ? tem->write_index : -1; #if defined (HAVE_MACROS) - if (macro_expansion_output_stream) + if (macro_expansion_output_stream && !executing_string) append_to_expansion_output (input_text_offset + 1); #endif /* HAVE_MACROS */ @@ -7684,7 +7996,7 @@ index_add_arg (name) ignore_blank_line (); #if defined (HAVE_MACROS) - if (macro_expansion_output_stream) + if (macro_expansion_output_stream && !executing_string) { int op_orig; @@ -7698,7 +8010,7 @@ index_add_arg (name) if (which < 0) { - line_error ("Unknown index reference `%s'", name); + line_error (_("Unknown index `%s'"), name); free (index_entry); } else @@ -7709,6 +8021,7 @@ index_add_arg (name) new->node = current_node; new->code = tem->code; new->defining_line = line_number - 1; + new->defining_file = input_filename; the_indices[which] = new; } } @@ -7719,9 +8032,9 @@ index_add_arg (name) void gen_index () { - char *name = strdup (command); + char *name = xstrdup (command); if (strlen (name) >= strlen ("index")) - name[strlen (name) - strlen ("index")] = '\0'; + name[strlen (name) - strlen ("index")] = 0; index_add_arg (name); free (name); } @@ -7762,7 +8075,7 @@ gen_defindex (code) if (find_index (name)) { - line_error ("Index `%s' already exists", name); + line_error (_("Index `%s' already exists"), name); free (name); return; } @@ -7776,96 +8089,68 @@ gen_defindex (code) } } -/* Append LIST2 to LIST1. Return the head of the list. */ -INDEX_ELT * -index_append (head, tail) - INDEX_ELT *head, *tail; -{ - register INDEX_ELT *t_head = head; - - if (!t_head) - return (tail); - - while (t_head->next) - t_head = t_head->next; - t_head->next = tail; - return (head); -} - /* Expects 2 args, on the same line. Both are index abbreviations. Make the first one be a synonym for the second one, i.e. make the first one have the same index as the second one. */ void cm_synindex () { - int redirector, redirectee; - char *temp; + int source, target; + char *abbrev1, *abbrev2; skip_whitespace (); - get_until_in_line (" ", &temp); - redirectee = find_index_offset (temp); + get_until_in_line (0, " ", &abbrev1); + target = find_index_offset (abbrev1); skip_whitespace (); - free_and_clear (&temp); - get_until_in_line (" ", &temp); - redirector = find_index_offset (temp); - free (temp); - if (redirector < 0 || redirectee < 0) + get_until_in_line (0, " ", &abbrev2); + source = find_index_offset (abbrev2); + if (source < 0 || target < 0) { - line_error ("Unknown index reference"); + line_error (_("Unknown index `%s' and/or `%s' in @synindex"), + abbrev1, abbrev2); } else { - /* I think that we should let the user make indices synonymous to - each other without any lossage of info. This means that one can - say @synindex cp dt anywhere in the file, and things that used to - be in cp will go into dt. */ - INDEX_ELT *i1 = the_indices[redirectee], *i2 = the_indices[redirector]; - - if (i1 || i2) - { - if (i1) - the_indices[redirectee] = index_append (i1, i2); - else - the_indices[redirectee] = index_append (i2, i1); - } - - name_index_alist[redirectee]->index = - name_index_alist[redirector]->index; + name_index_alist[target]->write_index + = name_index_alist[source]->write_index; } + + free (abbrev1); + free (abbrev2); } void -cm_pindex () /* Pinhead index. */ +cm_pindex () /* Pinhead index. */ { index_add_arg ("pg"); } void -cm_vindex () /* Variable index. */ +cm_vindex () /* Variable index. */ { index_add_arg ("vr"); } void -cm_kindex () /* Key index. */ +cm_kindex () /* Key index. */ { index_add_arg ("ky"); } void -cm_cindex () /* Concept index. */ +cm_cindex () /* Concept index. */ { index_add_arg ("cp"); } void -cm_findex () /* Function index. */ +cm_findex () /* Function index. */ { index_add_arg ("fn"); } void -cm_tindex () /* Data Type index. */ +cm_tindex () /* Data Type index. */ { index_add_arg ("tp"); } @@ -7893,14 +8178,14 @@ make_index_entries_unique (array, count) 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]; + (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]); - } + { + free (array[i]->entry); + free (array[i]); + } } copy[j] = (INDEX_ELT *)NULL; @@ -7913,20 +8198,20 @@ make_index_entries_unique (array, count) copy[i]->next = copy[i + 1]; /* Fix entry names which are the same. They point to different nodes, - so we make the entry name unique. */ + so we make the entry name unique. */ 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++; - } + (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; + counter = 1; array[i] = copy[i]; } @@ -7944,9 +8229,11 @@ INDEX_ELT ** sort_index (index) INDEX_ELT *index; { - INDEX_ELT *temp = 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) { @@ -7964,16 +8251,20 @@ sort_index (index) { array[count++] = temp; - /* Maybe should set line number to the defining_line? Any errors - have already been given, though, I think. */ + /* Set line number and input filename to the source line for this + index entry, as this expansion finds any errors. */ + line_number = array[count - 1]->defining_line; + input_filename = array[count - 1]->defining_file; /* If this particular entry should be printed as a "code" index, - then wrap the entry with "@code{...}". */ + then wrap the entry with "@code{...}". */ array[count - 1]->entry = expansion (temp->entry, index->code); temp = temp->next; } - array[count] = (INDEX_ELT *) NULL; /* terminate the array. */ + array[count] = (INDEX_ELT *) NULL; /* terminate the array. */ + line_number = save_line_number; + input_filename = save_input_filename; /* Sort the array. */ qsort (array, count, sizeof (INDEX_ELT *), index_element_compare); @@ -7981,7 +8272,7 @@ sort_index (index) return (array); } -/* Non-zero means that we are in the middle of printing an index. */ +/* Nonzero means that we are in the middle of printing an index. */ int printing_index = 0; /* Takes one arg, a short name of an index to print. @@ -8004,7 +8295,7 @@ cm_printindex () index = index_list (index_name); if (index == (INDEX_ELT *)-1) { - line_error ("Unknown index name `%s'", index_name); + line_error (_("Unknown index `%s' in @printindex"), index_name); free (index_name); return; } @@ -8019,7 +8310,7 @@ cm_printindex () array = sort_index (index); close_paragraph (); - add_word ("* Menu:\n\n"); + add_word (_("* Menu:\n\n")); #if defined (HAVE_MACROS) me_inhibit_expansion++; @@ -8034,11 +8325,15 @@ cm_printindex () /* A pathological document might have an index entry outside of any node. Don't crash. Perhaps should warn. */ char *index_node = index->node ? index->node : "(none)"; - unsigned new_length = strlen (index->entry) + strlen (index_node); + unsigned new_length = strlen (index->entry); + + if (new_length < 37) /* minimum length used below */ + new_length = 37; + new_length += strlen (index_node) + 7; /* * : .\n\0 */ if (new_length > line_length) { - line_length = new_length + 6; /* * : .\0 */ + line_length = new_length; line = xrealloc (line, line_length); } @@ -8066,8 +8361,8 @@ cm_printindex () filling_enabled = saved_filling_enabled; inhibit_paragraph_indentation = saved_inhibit_paragraph_indentation; } - -/* User-defined commands. */ + +/* User-defined commands, which happens only from user-defined indexes. */ void define_user_command (name, proc, needs_braces_p) @@ -8082,68 +8377,27 @@ define_user_command (name, proc, needs_braces_p) user_command_array = (COMMAND **) xmalloc (1 * sizeof (COMMAND *)); user_command_array = (COMMAND **) xrealloc (user_command_array, - (1 + user_command_array_len) * - sizeof (COMMAND *)); + (1 + user_command_array_len) * + sizeof (COMMAND *)); user_command_array[slot] = (COMMAND *) xmalloc (sizeof (COMMAND)); - user_command_array[slot]->name = strdup (name); + user_command_array[slot]->name = xstrdup (name); user_command_array[slot]->proc = proc; user_command_array[slot]->argument_in_braces = needs_braces_p; } - -/* Set the paragraph indentation variable to the value specified in STRING. - Values can be: - `asis': Don't change existing indentation. - `none': Remove existing indentation. - NUM: Indent NUM spaces at the starts of paragraphs. - Note that if NUM is zero, we assume `none'. - - Returns 0 if successful, or non-zero if STRING isn't one of the above. */ -int -set_paragraph_indent (string) - char *string; -{ - if (strcmp (string, "asis") == 0) - paragraph_start_indent = 0; - else if (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); -} - + /* Some support for footnotes. */ /* Footnotes are a new construct in Info. We don't know the best method of implementing them for sure, so we present two possiblities. SeparateNode: - Make them look like followed references, with the reference - destinations in a makeinfo manufactured node or, + Make them look like followed references, with the reference + destinations in a makeinfo manufactured node or, EndNode: - Make them appear at the bottom of the node that they originally - appeared in. */ + Make them appear at the bottom of the node that they originally + appeared in. */ #define SeparateNode 0 #define EndNode 1 @@ -8160,7 +8414,7 @@ set_footnote_style (string) (strcasecmp (string, "MN") == 0)) footnote_style = SeparateNode; else if ((strcasecmp (string, "end") == 0) || - (strcasecmp (string, "EN") == 0)) + (strcasecmp (string, "EN") == 0)) footnote_style = EndNode; else return (-1); @@ -8199,8 +8453,8 @@ remember_note (marker, note) { FN *temp = (FN *) xmalloc (sizeof (FN)); - temp->marker = strdup (marker); - temp->note = strdup (note); + temp->marker = xstrdup (marker); + temp->note = xstrdup (note); temp->next = pending_notes; pending_notes = temp; footnote_count++; @@ -8227,7 +8481,7 @@ free_pending_notes () /* Handle a "footnote". footnote *{this is a footnote} - where "*" is the marker character for this note. */ + where "*" is the (optional) marker character for this note. */ void cm_footnote () { @@ -8237,48 +8491,67 @@ cm_footnote () get_until ("{", &marker); canon_white (marker); + if (macro_expansion_output_stream && !executing_string) + append_to_expansion_output (input_text_offset + 1); /* include the { */ + /* Read the argument in braces. */ if (curchar () != '{') { - line_error ("`%c%s' expected more than just `%s'. It needs something in `{...}'", - COMMAND_PREFIX, command, marker); + line_error (_("`%c%s' needs an argument `{...}', not just `%s'"), + COMMAND_PREFIX, command, marker); free (marker); return; } else { - int braces = 1; - int temp = ++input_text_offset; int len; + int braces = 1; + int loc = ++input_text_offset; while (braces) - { - if (temp == size_of_input_text) - { - line_error ("No closing brace for footnote `%s'", marker); - return; - } - - if (input_text[temp] == '{') - braces++; - else if (input_text[temp] == '}') - braces--; - else if (input_text[temp] == '\n') - line_number ++; - - temp++; - } - - len = (temp - input_text_offset) - 1; + { + 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 = temp; + note[len] = 0; + input_text_offset = loc; + } + + /* Must write the macro-expanded argument to the macro expansion + output stream. This is like the case in index_add_arg. */ + 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); + /* Calling me_execute_string on a lone } provokes an error, since + as far as the reader knows there is no matching {. We wrote + the { above in the call to append_to_expansion_output. */ + write_region_to_macro_output ("}", 0, 1); + output_paragraph_offset = op_orig; } if (!current_node || !*current_node) { - line_error ("Footnote defined without parent node"); + line_error (_("Footnote defined without parent node")); free (marker); free (note); return; @@ -8289,13 +8562,13 @@ cm_footnote () free (marker); if (number_footnotes) - { - marker = (char *)xmalloc (10); - sprintf (marker, "%d", current_footnote_number); - current_footnote_number++; - } + { + marker = (char *)xmalloc (10); + sprintf (marker, "%d", current_footnote_number); + current_footnote_number++; + } else - marker = strdup ("*"); + marker = xstrdup ("*"); } remember_note (marker, note); @@ -8306,19 +8579,19 @@ cm_footnote () 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; - } + { + 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: @@ -8332,7 +8605,7 @@ cm_footnote () free (note); } -/* Non-zero means that we are currently in the process of outputting +/* Nonzero means that we are currently in the process of outputting footnotes. */ int already_outputting_pending_notes = 0; @@ -8349,23 +8622,23 @@ output_pending_notes () { case SeparateNode: { - char *old_current_node = current_node; - char *old_command = strdup (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; + 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"); + execute_string (_("---------- Footnotes ----------\n\n")); in_fixed_width_font--; break; } @@ -8378,24 +8651,17 @@ output_pending_notes () while (--footnote_count > -1) { - array[footnote_count] = footnote; - footnote = footnote->next; + array[footnote_count] = footnote; + footnote = footnote->next; } filling_enabled = 1; indented_fill = 1; - while (footnote = array[++footnote_count]) + while ((footnote = array[++footnote_count])) { - - switch (footnote_style) - { - case SeparateNode: - case EndNode: - execute_string ("(%s) %s", footnote->marker, footnote->note); - close_paragraph (); - break; - } + execute_string ("(%s) %s", footnote->marker, footnote->note); + close_paragraph (); } close_paragraph (); free (array); @@ -8404,7 +8670,7 @@ output_pending_notes () /* **************************************************************** */ /* */ -/* User definable Macros (text substitution) */ +/* User definable Macros (text substitution) */ /* */ /* **************************************************************** */ @@ -8413,8 +8679,8 @@ output_pending_notes () /* Array of macros and definitions. */ MACRO_DEF **macro_list = (MACRO_DEF **)NULL; -int macro_list_len = 0; /* Number of elements. */ -int macro_list_size = 0; /* Number of slots in total. */ +int macro_list_len = 0; /* Number of elements. */ +int macro_list_size = 0; /* Number of slots in total. */ /* Return the macro definition of NAME or NULL if NAME is not defined. */ MACRO_DEF * @@ -8428,7 +8694,7 @@ find_macro (name) for (i = 0; macro_list && (def = macro_list[i]); i++) { if ((!def->inhibited) && (strcmp (def->name, name) == 0)) - break; + break; } return (def); } @@ -8453,8 +8719,8 @@ add_macro (name, arglist, body, source_file, source_lineno, flags) 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_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; @@ -8468,30 +8734,29 @@ add_macro (name, arglist, body, source_file, source_lineno, flags) char *temp_filename = input_filename; int temp_line = line_number; - warning ("The macro `%s' is previously defined", name); + 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); + warning (_("here is the previous definition of `%s'"), name); input_filename = temp_filename; line_number = temp_line; if (def->arglist) - { - register int i; + { + register int i; - for (i = 0; def->arglist[i]; i++) - free (def->arglist[i]); + for (i = 0; def->arglist[i]; i++) + free (def->arglist[i]); - free (def->arglist); - } + free (def->arglist); + } free (def->source_file); free (def->body); } - def->source_file = strdup (source_file); + def->source_file = xstrdup (source_file); def->source_lineno = source_lineno; def->body = body; def->arglist = arglist; @@ -8514,9 +8779,10 @@ delete_macro (name) 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 *)); - break; + memmove (macro_list + i, macro_list + i + 1, + ((macro_list_len + 1) - i) * sizeof (MACRO_DEF *)); + macro_list_len--; + break; } return (def); } @@ -8527,7 +8793,7 @@ int braces_required_for_macro_args = 0; char ** get_macro_args (def) - MACRO_DEF *def; + MACRO_DEF *def; { register int i; char *word; @@ -8541,35 +8807,38 @@ get_macro_args (def) if (input_text[i] != '{') { if (braces_required_for_macro_args) - { - return ((char **)NULL); - } + { + return ((char **)NULL); + } else - { - /* Braces are not required to fill out the macro arguments. If - this macro takes one argument, it is considered to be the - remainder of the line, sans whitespace. */ - 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--; - /* canon_white (word); */ - arglist = (char **)xmalloc (2 * sizeof (char *)); - arglist[0] = word; - arglist[1] = (char *)NULL; - return (arglist); - } - else - { - /* The macro either took no arguments, or took more than - one argument. In that case, it must be invoked with - arguments surrounded by braces. */ - return ((char **)NULL); - } - } + { + /* Braces are not required to fill out the macro arguments. If + this macro takes one argument, it is considered to be the + remainder of the line, sans whitespace. */ + 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--; + } + /* canon_white (word); */ + arglist = (char **)xmalloc (2 * sizeof (char *)); + arglist[0] = word; + arglist[1] = (char *)NULL; + return (arglist); + } + else + { + /* The macro either took no arguments, or took more than + one argument. In that case, it must be invoked with + arguments surrounded by braces. */ + return ((char **)NULL); + } + } } return (get_brace_args (def->flags & ME_QUOTE_ARG)); } @@ -8596,66 +8865,69 @@ apply (named, actuals, body) while (1) { if (!body[i]) - break; + break; if (body[i] != '\\') - new_body[new_body_index++] = body[i++]; + new_body[new_body_index++] = body[i++]; else - { - /* Snarf parameter name, check against named parameters. */ - 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++; - - /* Now check against named parameters. */ - for (which = 0; named && named[which]; which++) - if (strcmp (named[which], param) == 0) - break; - - if (named[which]) - { - if (which < length_of_actuals) - text = actuals[which]; - else - text = (char *)NULL; - - if (!text) - text = ""; - - len = strlen (text); - } - else - { - len += 2; - text = (char *)xmalloc (1 + len); - sprintf (text, "\\%s\\", param); - } - - if ((2 + strlen (param)) < len) - new_body = (char *)xrealloc - (new_body, new_body_size += (1 + len)); - - free (param); - - strcpy (new_body + new_body_index, text); - new_body_index += len; - - if (!named[which]) - free (text); - } - } - new_body[new_body_index] = '\0'; + { + /* Snarf parameter name, check against named parameters. */ + 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]) /* move past \ */ + i++; + + /* Now check against named parameters. */ + 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 + { /* not a parameter, restore \'s */ + 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); } @@ -8664,12 +8936,11 @@ void execute_macro (def) MACRO_DEF *def; { - register int i; char **arglist; int num_args; char *execution_string = (char *)NULL; - if (macro_expansion_output_stream && !me_inhibit_expansion) + if (macro_expansion_output_stream && !executing_string && !me_inhibit_expansion) me_append_before_this_command (); /* Find out how many arguments this macro definition takes. */ @@ -8681,7 +8952,7 @@ execute_macro (def) if (num_args < array_len (arglist)) { free_array (arglist); - line_error ("Macro `%s' called with too many args", def->name); + line_error (_("Macro `%s' called with too many args"), def->name); return; } @@ -8692,13 +8963,13 @@ execute_macro (def) if (def->body) { - if (macro_expansion_output_stream && !me_inhibit_expansion) - { - remember_itext (input_text, input_text_offset); - me_execute_string (execution_string); - } + 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); + execute_string ("%s", execution_string); free (execution_string); } @@ -8720,7 +8991,7 @@ cm_macro () body_size = 0; body_index = 0; - if (macro_expansion_output_stream) + if (macro_expansion_output_stream && !executing_string) me_append_before_this_command (); skip_whitespace (); @@ -8732,15 +9003,15 @@ cm_macro () int len; for (i = start; - (i < size_of_input_text) && - (input_text[i] != '{') && - (!cr_or_whitespace (input_text[i])); - i++); + (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'; + name[len] = 0; input_text_offset = i; } @@ -8756,71 +9027,71 @@ cm_macro () int character; /* Read the words inside of the braces which determine the arglist. - These words will be replaced within the body of the macro at - execution time. */ + These words will be replaced within the body of the macro at + execution time. */ 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 '}': - /* Found the end of the current arglist word. Save it. */ - 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; - - /* Advance to the comma or close-brace that signified - the end of the argument. */ - while ((character = curchar ()) - && character != ',' - && character != '}') - { - input_text_offset++; - if (character == '\n') - line_number++; - } - - /* Add the word to our list of words. */ - 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; - } - } - } + { + int len; + + for (i = input_text_offset; + (character = input_text[i]); + i++) + { + switch (character) + { + case '\n': + line_number++; + case ' ': + case '\t': + case ',': + case '}': + /* Found the end of the current arglist word. Save it. */ + 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; + + /* Advance to the comma or close-brace that signified + the end of the argument. */ + while ((character = curchar ()) + && character != ',' + && character != '}') + { + input_text_offset++; + if (character == '\n') + line_number++; + } + + /* Add the word to our list of words. */ + 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; + } + } + } } /* Read the text carefully until we find an "@end macro" which @@ -8830,84 +9101,94 @@ cm_macro () 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; - } + { + 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); /* Handle commands only meaningful within a macro. */ 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; - } - } + (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); - } - } + (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++; + (strncmp (line + 1, "macro ", 6) == 0)) + depth++; if ((*line == COMMAND_PREFIX) && - (strncmp (line + 1, "end macro", 9) == 0)) - depth--; + (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'; - } + { + 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 it was an empty macro like + @macro foo + @end macro + create an empty body. (Otherwise, the macro is not expanded.) */ + if (!body) + { + body = (char *)malloc(1); + *body = 0; + } + /* We now have the name, the arglist, and the body. However, BODY includes the final newline which preceded the `@end macro' text. Delete it. */ if (body && strlen (body)) - body[strlen (body) - 1] = '\0'; + body[strlen (body) - 1] = 0; add_macro (name, arglist, body, input_filename, defining_line, flags); - if (macro_expansion_output_stream) + if (macro_expansion_output_stream && !executing_string) remember_itext (input_text, input_text_offset); } @@ -8918,16 +9199,15 @@ cm_unmacro () char *line, *name; MACRO_DEF *def; - if (macro_expansion_output_stream) + if (macro_expansion_output_stream && !executing_string) me_append_before_this_command (); get_rest_of_line (&line); - canon_white (line); for (i = 0; line[i] && !whitespace (line[i]); i++); - name = (char *)xmalloc (i); + name = (char *)xmalloc (i + 1); strncpy (name, line, i); - name[i] = '\0'; + name[i] = 0; def = delete_macro (name); @@ -8938,14 +9218,14 @@ cm_unmacro () free (def->body); if (def->arglist) - { - register int i; + { + register int i; - for (i = 0; def->arglist[i]; i++) - free (def->arglist[i]); + for (i = 0; def->arglist[i]; i++) + free (def->arglist[i]); - free (def->arglist); - } + free (def->arglist); + } free (def); } @@ -8953,7 +9233,7 @@ cm_unmacro () free (line); free (name); - if (macro_expansion_output_stream) + if (macro_expansion_output_stream && !executing_string) remember_itext (input_text, input_text_offset); } @@ -8973,38 +9253,38 @@ remember_itext (pointer, offset) { itext_info = (ITEXT **)xmalloc ((itext_size = 10) * sizeof (ITEXT *)); for (i = 0; i < itext_size; i++) - itext_info[i] = (ITEXT *)NULL; + itext_info[i] = (ITEXT *)NULL; } /* If the pointer is already present in the list, then set the offset. */ for (i = 0; i < itext_size; i++) if ((itext_info[i] != (ITEXT *)NULL) && - (itext_info[i]->pointer == pointer)) + (itext_info[i]->pointer == pointer)) { - itext = itext_info[i]; - itext_info[i]->offset = offset; - break; + itext = itext_info[i]; + itext_info[i]->offset = offset; + break; } if (i == itext_size) { - /* Find a blank slot, (or create a new one), and remember the - pointer and offset. */ + /* Find a blank slot (or create a new one), and remember the + pointer and offset. */ for (i = 0; i < itext_size; i++) - if (itext_info[i] == (ITEXT *)NULL) - break; + if (itext_info[i] == (ITEXT *)NULL) + break; /* If not found, then add some slots. */ if (i == itext_size) - { - register int j; + { + register int j; - itext_info = (ITEXT **)xrealloc - (itext_info, (itext_size += 10) * sizeof (ITEXT *)); + itext_info = (ITEXT **)xrealloc + (itext_info, (itext_size += 10) * sizeof (ITEXT *)); - for (j = i; j < itext_size; j++) - itext_info[j] = (ITEXT *)NULL; - } + for (j = i; j < itext_size; j++) + itext_info[j] = (ITEXT *)NULL; + } /* Now add the pointer and the offset. */ itext_info[i] = (ITEXT *)xmalloc (sizeof (ITEXT)); @@ -9025,9 +9305,9 @@ forget_itext (pointer) 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; + free (itext_info[i]); + itext_info[i] = (ITEXT *)NULL; + break; } } @@ -9051,15 +9331,15 @@ me_execute_string (execution_string) pushfile (); input_text_offset = 0; input_text = execution_string; - input_filename = strdup (input_filename); + input_filename = xstrdup (input_filename); size_of_input_text = strlen (execution_string); remember_itext (execution_string, 0); - executing_string++; + me_executing_string++; reader_loop (); popfile (); - executing_string--; + me_executing_string--; } /* Append the text which appears in input_text from the last offset to @@ -9074,17 +9354,17 @@ append_to_expansion_output (offset) for (i = 0; i < itext_size; i++) if (itext_info[i] && itext_info[i]->pointer == input_text) { - itext = itext_info[i]; - break; + itext = itext_info[i]; + break; } if (!itext) - itext = remember_itext (input_text, 0); + return; if (offset > itext->offset) { write_region_to_macro_output - (input_text, itext->offset, offset); + (input_text, itext->offset, offset); remember_itext (input_text, offset); } } @@ -9101,8 +9381,8 @@ maybe_write_itext (pointer, offset) for (i = 0; i < itext_size; i++) if (itext_info[i] && (itext_info[i]->pointer == pointer)) { - itext = itext_info[i]; - break; + itext = itext_info[i]; + break; } if (itext && (itext->offset < offset)) @@ -9145,7 +9425,7 @@ free_array (array) register int i; for (i = 0; array[i] != (char *)NULL; i++) - free (array[i]); + free (array[i]); free (array); } @@ -9174,64 +9454,64 @@ get_brace_args (quote_single) start = input_text_offset; escape_seen = 0; - while (character = curchar ()) + while ((character = curchar ())) { if (character == '\\') - { - input_text_offset += 2; - escape_seen = 1; - } + { + input_text_offset += 2; + escape_seen = 1; + } else if (character == '{') - { - depth++; - input_text_offset++; - } + { + 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'; - - /* Clean up escaped characters. */ - 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; - } + ((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; + + /* Clean up escaped characters. */ + 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++; - } + { + depth--; + input_text_offset++; + } else - { - input_text_offset++; - if (character == '\n') line_number++; - } + { + input_text_offset++; + if (character == '\n') line_number++; + } } return (arglist); } @@ -9274,10 +9554,10 @@ extract_colon_unit (string, index) if (i == start) { if (string[i]) - (*index)++; + (*index)++; /* Return "" in the case of a trailing `:'. */ - return (strdup ("")); + return (xstrdup ("")); } else { @@ -9285,7 +9565,7 @@ extract_colon_unit (string, index) value = (char *)xmalloc (1 + (i - start)); strncpy (value, &string[start], (i - start)); - value [i - start] = '\0'; + value [i - start] = 0; return (value); } @@ -9310,23 +9590,29 @@ get_file_info_in_path (filename, path, finfo) if (*filename == '/' || (*filename == '.' && (filename[1] == '/' || - (filename[1] == '.' && filename[2] == '/')))) + (filename[1] == '.' && filename[2] == '/'))) +#ifdef WIN32 + /* Handle names that look like "d:/foo/bar" */ + || (isalpha (*filename) && filename [1] == ':' + && (filename [2] == '/' || filename [2] == '\\')) +#endif + ) { if (stat (filename, finfo) == 0) - return (strdup (filename)); + return (xstrdup (filename)); else - return ((char *)NULL); + return ((char *)NULL); } - while (dir = extract_colon_unit (path, &index)) + while ((dir = extract_colon_unit (path, &index))) { char *fullpath; if (!*dir) - { - free (dir); - dir = strdup ("."); - } + { + free (dir); + dir = xstrdup ("."); + } fullpath = (char *)xmalloc (2 + strlen (dir) + strlen (filename)); sprintf (fullpath, "%s/%s", dir, filename); @@ -9335,9 +9621,9 @@ get_file_info_in_path (filename, path, finfo) result = stat (fullpath, finfo); if (result == 0) - return (fullpath); + return (fullpath); else - free (fullpath); + free (fullpath); } - return ((char *)NULL); + return NULL; } |