Fix spec %v3
[official-gcc.git] / texinfo / makeinfo / makeinfo.c
blob3094a650d61b0c3c10eb3330ed1ed9b48958decc
1 /* Makeinfo -- convert Texinfo source files into Info files.
2 $Id: makeinfo.c,v 1.11 1998/07/06 21:58:00 law Exp $
4 Copyright (C) 1987, 92, 93, 94, 95, 96, 97, 98
5 Free Software Foundation, Inc.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 Makeinfo was authored by Brian Fox (bfox@ai.mit.edu). */
23 /* Indent #pragma so that older Cpp's don't try to parse it. */
24 #ifdef _AIX
25 #pragma alloca
26 #endif /* _AIX */
28 int major_version = 1;
29 int minor_version = 68;
31 #include "system.h"
32 #include "getopt.h"
34 #ifdef TM_IN_SYS_TIME
35 #include <sys/time.h>
36 #else
37 #include <time.h>
38 #endif /* !TM_IN_SYS_TIME */
40 #ifdef __GNUC__
41 # undef alloca
42 # define alloca __builtin_alloca
43 #else
44 # ifdef HAVE_ALLOCA_H
45 # include <alloca.h>
46 # else
47 # ifndef _AIX
48 char *alloca ();
49 # endif
50 # endif
51 #endif
53 /* We'd like to take advantage of _doprnt if it's around, a la error.c,
54 but then we'd have no VA_SPRINTF. */
55 #if HAVE_VPRINTF
56 # if __STDC__
57 # include <stdarg.h>
58 # define VA_START(args, lastarg) va_start(args, lastarg)
59 # else
60 # include <varargs.h>
61 # define VA_START(args, lastarg) va_start(args)
62 # endif
63 # define VA_FPRINTF(file, fmt, ap) vfprintf (file, fmt, ap)
64 # define VA_SPRINTF(str, fmt, ap) vsprintf (str, fmt, ap)
65 #else /* not HAVE_VPRINTF */
66 # define VA_START(args, lastarg)
67 # define va_alist a1, a2, a3, a4, a5, a6, a7, a8
68 # define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
69 # define va_end(args)
70 #endif
72 /* You can change some of the behavior of Makeinfo by changing the
73 following defines: */
75 /* Define INDENT_PARAGRAPHS_IN_TABLE if you want the paragraphs which
76 appear within an @table, @ftable, or @itemize environment to have
77 standard paragraph indentation. Without this, such paragraphs have
78 no starting indentation. */
79 /* #define INDENT_PARAGRAPHS_IN_TABLE */
81 /* Define DEFAULT_INDENTATION_INCREMENT as an integer which is the amount
82 that @example should increase indentation by. This incremement is used
83 for all insertions which indent the enclosed text. */
84 #define DEFAULT_INDENTATION_INCREMENT 5
86 /* Define PARAGRAPH_START_INDENT to be the amount of indentation that
87 the first lines of paragraphs receive by default, where no other
88 value has been specified. Users can change this value on the command
89 line, with the --paragraph-indent option, or within the texinfo file,
90 with the @paragraphindent command. */
91 #define PARAGRAPH_START_INDENT 3
93 /* Define DEFAULT_PARAGRAPH_SPACING as the number of blank lines that you
94 wish to appear between paragraphs. A value of 1 creates a single blank
95 line between paragraphs. Paragraphs are defined by 2 or more consecutive
96 newlines in the input file (i.e., one or more blank lines). */
97 #define DEFAULT_PARAGRAPH_SPACING 1
99 /* Define HAVE_MACROS to enable the macro facility of Texinfo. Using this
100 facility, users can create their own command procedures with
101 arguments. Must always be defined. */
102 #define HAVE_MACROS
105 #define COMPILING_MAKEINFO
106 #include "makeinfo.h"
108 /* Nonzero means that we are currently hacking the insides of an
109 insertion which would use a fixed width font. */
110 static int in_fixed_width_font = 0;
112 /* Nonzero means that start_paragraph () MUST be called before we pay
113 any attention to close_paragraph () calls. */
114 int must_start_paragraph = 0;
116 /* Nonzero means a string is in execution, as opposed to a file. */
117 static int executing_string = 0;
119 /* Nonzero means a macro string is in execution, as opposed to a file. */
120 static int me_executing_string = 0;
122 #if defined (HAVE_MACROS)
123 /* If non-NULL, this is an output stream to write the full macro expansion
124 of the input text to. The result is another texinfo file, but
125 missing @include, @infoinclude, @macro, and macro invocations. Instead,
126 all of the text is placed within the file. */
127 FILE *macro_expansion_output_stream = (FILE *)NULL;
128 char *macro_expansion_filename;
130 /* Here is a structure used to remember input text strings and offsets
131 within them. */
132 typedef struct {
133 char *pointer; /* Pointer to the input text. */
134 int offset; /* Offset of the last character output. */
135 } ITEXT;
137 static ITEXT **itext_info = (ITEXT **)NULL;
138 static int itext_size = 0;
140 /* Nonzero means to inhibit writing macro expansions to the output
141 stream, because it has already been written. */
142 int me_inhibit_expansion = 0;
144 ITEXT *remember_itext ();
145 void forget_itext (), me_append_before_this_command ();
146 void append_to_expansion_output (), write_region_to_macro_output ();
147 void maybe_write_itext (), me_execute_string ();
148 #endif /* HAVE_MACROS */
151 /* **************************************************************** */
152 /* */
153 /* Global Variables */
154 /* */
155 /* **************************************************************** */
157 /* Global pointer to argv[0]. */
158 char *progname;
160 /* Return nonzero if STRING is the text at input_text + input_text_offset,
161 else zero. */
162 #define looking_at(string) \
163 (strncmp (input_text + input_text_offset, string, strlen (string)) == 0)
165 /* And writing to the output. */
167 /* The output file name. */
168 char *output_filename = (char *)NULL;
169 char *pretty_output_filename;
171 /* Name of the output file that the user elected to pass on the command line.
172 Such a name overrides any name found with the @setfilename command. */
173 char *command_output_filename = (char *)NULL;
175 /* A colon separated list of directories to search for files included
176 with @include. This can be controlled with the `-I' option to makeinfo. */
177 char *include_files_path = (char *)NULL;
179 /* Position in the output file. */
180 int output_position;
182 #define INITIAL_PARAGRAPH_SPACE 5000
183 int paragraph_buffer_len = INITIAL_PARAGRAPH_SPACE;
185 /* Nonzero indicates that filling will take place on long lines. */
186 int filling_enabled = 1;
188 /* Nonzero means that words are not to be split, even in long lines. This
189 gets changed for cm_w (). */
190 int non_splitting_words = 0;
192 /* Nonzero indicates that filling a line also indents the new line. */
193 int indented_fill = 0;
195 /* The amount of indentation to add at the starts of paragraphs.
196 0 means don't change existing indentation at paragraph starts.
197 > 0 is amount to indent new paragraphs by.
198 < 0 means indent to column zero by removing indentation if necessary.
200 This is normally zero, but some people prefer paragraph starts to be
201 somewhat more indented than paragraph bodies. A pretty value for
202 this is 3. */
203 int paragraph_start_indent = PARAGRAPH_START_INDENT;
205 /* Nonzero means that the use of paragraph_start_indent is inhibited.
206 @example uses this to line up the left columns of the example text.
207 A negative value for this variable is incremented each time it is used.
208 @noindent uses this to inhibit indentation for a single paragraph. */
209 int inhibit_paragraph_indentation = 0;
211 /* Indentation that is pending insertion. We have this for hacking lines
212 which look blank, but contain whitespace. We want to treat those as
213 blank lines. */
214 int pending_indent = 0;
216 /* The amount that indentation increases/decreases by. */
217 int default_indentation_increment = DEFAULT_INDENTATION_INCREMENT;
219 /* Nonzero indicates that indentation is temporarily turned off. */
220 int no_indent = 1;
222 /* Nonzero means forcing output text to be flushright. */
223 int force_flush_right = 0;
225 /* Nonzero means that the footnote style for this document was set on
226 the command line, which overrides any other settings. */
227 int footnote_style_preset = 0;
229 /* Nonzero means that we automatically number footnotes that have no
230 specified marker. */
231 int number_footnotes = 1;
233 /* The current footnote number in this node. Each time a new node is
234 started this is reset to 1. */
235 int current_footnote_number = 1;
237 /* Command name in the process of being hacked. */
238 char *command;
240 /* The index in our internal command table of the currently
241 executing command. */
242 int command_index;
244 /* A search string which is used to find a line defining a node. */
245 char node_search_string[] =
246 { '\n', COMMAND_PREFIX, 'n', 'o', 'd', 'e', ' ', 0 };
248 /* A search string which is used to find a line defining a menu. */
249 char menu_search_string[] =
250 { '\n', COMMAND_PREFIX, 'm', 'e', 'n', 'u', 0 };
252 /* A search string which is used to find the first @setfilename. */
253 char setfilename_search[] =
254 { COMMAND_PREFIX,
255 's', 'e', 't', 'f', 'i', 'l', 'e', 'n', 'a', 'm', 'e', 0 };
257 /* A stack of file information records. If a new file is read in with
258 "@input", we remember the old input file state on this stack. */
259 typedef struct fstack
261 struct fstack *next;
262 char *filename;
263 char *text;
264 int size;
265 int offset;
266 int line_number;
267 } FSTACK;
269 FSTACK *filestack = (FSTACK *) NULL;
271 /* Stuff for nodes. */
272 /* The current nodes node name. */
273 char *current_node = (char *)NULL;
275 /* The current nodes section level. */
276 int current_section = 0;
278 /* The filename of the current input file. This is never freed. */
279 char *node_filename = (char *)NULL;
281 /* What we remember for each node. */
282 typedef struct tentry
284 struct tentry *next_ent;
285 char *node; /* name of this node. */
286 char *prev; /* name of "Prev:" for this node. */
287 char *next; /* name of "Next:" for this node. */
288 char *up; /* name of "Up:" for this node. */
289 int position; /* output file position of this node. */
290 int line_no; /* defining line in source file. */
291 char *filename; /* The file that this node was found in. */
292 int touched; /* Nonzero means this node has been referenced. */
293 int flags; /* Room for growth. Right now, contains 1 bit. */
294 } TAG_ENTRY;
296 /* If node-a has a "Next" for node-b, but node-b has no "Prev" for node-a,
297 we turn on this flag bit in node-b's tag entry. This means that when
298 it is time to validate node-b, we don't report an additional error
299 if there was no "Prev" field. */
300 #define PREV_ERROR 0x1
301 #define NEXT_ERROR 0x2
302 #define UP_ERROR 0x4
303 #define NO_WARN 0x8
304 #define IS_TOP 0x10
306 TAG_ENTRY *tag_table = (TAG_ENTRY *) NULL;
308 /* Values for calling handle_variable_internal (). */
309 #define SET 1
310 #define CLEAR 2
311 #define IFSET 3
312 #define IFCLEAR 4
314 #if defined (HAVE_MACROS)
315 #define ME_RECURSE 0x01
316 #define ME_QUOTE_ARG 0x02
318 /* Macro definitions for user-defined commands. */
319 typedef struct {
320 char *name; /* Name of the macro. */
321 char **arglist; /* Args to replace when executing. */
322 char *body; /* Macro body. */
323 char *source_file; /* File where this macro is defined. */
324 int source_lineno; /* Line number within FILENAME. */
325 int inhibited; /* Nonzero means make find_macro () fail. */
326 int flags; /* ME_RECURSE, ME_QUOTE_ARG, etc. */
327 } MACRO_DEF;
329 void add_macro (), execute_macro ();
330 MACRO_DEF *find_macro (), *delete_macro ();
331 #endif /* HAVE_MACROS */
333 /* Menu reference, *note reference, and validation hacking. */
335 /* The various references that we know about. */
336 enum reftype
338 menu_reference, followed_reference
341 /* A structure to remember references with. A reference to a node is
342 either an entry in a menu, or a cross-reference made with [px]ref. */
343 typedef struct node_ref
345 struct node_ref *next;
346 char *node; /* Name of node referred to. */
347 char *containing_node; /* Name of node containing this reference. */
348 int line_no; /* Line number where the reference occurs. */
349 int section; /* Section level where the reference occurs. */
350 char *filename; /* Name of file where the reference occurs. */
351 enum reftype type; /* Type of reference, either menu or note. */
352 } NODE_REF;
354 /* The linked list of such structures. */
355 NODE_REF *node_references = (NODE_REF *) NULL;
357 /* Flag which tells us whether to examine menu lines or not. */
358 int in_menu = 0;
360 /* Flag which tells us how to examine menu lines. */
361 int in_detailmenu = 0;
363 /* Nonzero means that we have seen "@top" once already. */
364 int top_node_seen = 0;
366 /* Nonzero means that we have seen a non-"@top" node already. */
367 int non_top_node_seen = 0;
369 /* Flags controlling the operation of the program. */
371 /* Default is to remove output if there were errors. */
372 int force = 0;
374 /* Default is to notify users of bad choices. */
375 int print_warnings = 1;
377 /* Default is to check node references. */
378 int validating = 1;
380 /* Nonzero means do not output "Node: Foo" for node separations. */
381 int no_headers = 0;
383 /* Number of errors that we tolerate on a given fileset. */
384 int max_error_level = 100;
386 /* Maximum number of references to a single node before complaining. */
387 int reference_warning_limit = 1000;
389 /* Nonzero means print out information about what is going on when it
390 is going on. */
391 int verbose_mode = 0;
393 /* Nonzero means to be relaxed about the input file. This is useful when
394 we can successfully format the input, but it doesn't strictly match our
395 somewhat pedantic ideas of correctness. Right now, it affects what
396 @table and @itemize do without arguments. */
397 int allow_lax_format = 0;
399 /* The list of commands that we hack in texinfo. Each one
400 has an associated function. When the command is encountered in the
401 text, the associated function is called with START as the argument.
402 If the function expects arguments in braces, it remembers itself on
403 the stack. When the corresponding close brace is encountered, the
404 function is called with END as the argument. */
406 #define START 0
407 #define END 1
409 typedef struct brace_element
411 struct brace_element *next;
412 COMMAND_FUNCTION *proc;
413 int pos, line;
414 int in_fixed_width_font;
415 } BRACE_ELEMENT;
417 BRACE_ELEMENT *brace_stack = (BRACE_ELEMENT *) NULL;
419 extern void do_multitable ();
421 void print_version_info ();
422 void usage ();
423 void push_node_filename (), pop_node_filename ();
424 void remember_error (), flush_file_stack ();
425 void convert_from_stream (), convert_from_file (), convert_from_loaded_file ();
426 void init_internals (), init_paragraph (), init_brace_stack ();
427 void init_insertion_stack (), init_indices ();
428 void init_tag_table (), write_tag_table (), write_tag_table_internal ();
429 void validate_file (), validate_other_references (), split_file ();
430 void free_node_references (), do_enumeration (), handle_variable ();
431 void handle_variable_internal ();
432 void normalize_node_name ();
433 void undefindex (), top_defindex (), gen_defindex ();
434 void define_user_command ();
435 void free_pending_notes (), output_pending_notes ();
437 char **get_brace_args ();
438 char *expansion ();
439 int array_len ();
440 void free_array ();
441 static int end_of_sentence_p ();
442 static void isolate_nodename ();
443 void reader_loop (), read_command ();
444 void remember_brace (), remember_brace_1 ();
445 void pop_and_call_brace (), discard_braces ();
446 void add_word (), add_char (), insert (), flush_output ();
447 void insert_string ();
448 void close_paragraph_with_lines (), close_paragraph ();
449 void ignore_blank_line ();
450 void do_flush_right_indentation (), discard_insertions ();
451 void start_paragraph (), indent ();
452 #if defined (VA_FPRINTF) && __STDC__
453 /* Unfortunately we must use prototypes if we are to use <stdarg.h>. */
454 void add_word_args (char *, ...);
455 void execute_string (char *, ...);
456 #else
457 void add_word_args ();
458 void execute_string ();
459 #endif /* will not use prototypes */
461 void insert_self (), insert_space (), cm_ignore_line ();
463 void
464 cm_TeX (), cm_asterisk (), cm_bullet (), cm_cite (),
465 cm_code (), cm_copyright (), cm_ctrl (), cm_dfn (), cm_dircategory (),
466 cm_direntry (), cm_dots (), cm_emph (), cm_enddots (),
467 cm_kbd (), cm_key (), cm_no_op (), cm_no_op_line_arg (),
468 cm_not_fixed_width (), cm_strong (), cm_var_sc (), cm_w (), cm_image ();
470 /* Sectioning. */
471 void
472 cm_chapter (), cm_unnumbered (), cm_appendix (), cm_top (),
473 cm_section (), cm_unnumberedsec (), cm_appendixsec (),
474 cm_subsection (), cm_unnumberedsubsec (), cm_appendixsubsec (),
475 cm_subsubsection (), cm_unnumberedsubsubsec (), cm_appendixsubsubsec (),
476 cm_heading (), cm_chapheading (), cm_subheading (), cm_subsubheading (),
477 cm_majorheading (), cm_raisesections (), cm_lowersections ();
479 /* All @def... commands map to cm_defun, most accent commands map to
480 cm_accent, most non-English letters map to cm_special_char. */
481 void cm_defun (), cm_accent (), cm_special_char (), cm_dotless ();
483 void
484 cm_node (), cm_menu (), cm_xref (), cm_ftable (), cm_vtable (), cm_pxref (),
485 cm_inforef (), cm_uref (), cm_email (), cm_quotation (),
486 cm_display (), cm_itemize (),
487 cm_enumerate (), cm_tab (), cm_table (), cm_itemx (), cm_noindent (),
488 cm_setfilename (), cm_br (), cm_sp (), cm_page (), cm_group (),
489 cm_center (), cm_include (), cm_bye (), cm_item (), cm_end (),
490 cm_ifinfo (), cm_ifnothtml (), cm_ifnottex (), cm_kindex (), cm_cindex (),
491 cm_findex (), cm_pindex (), cm_vindex (), cm_tindex (),
492 cm_synindex (), cm_printindex (), cm_minus (), cm_footnote (),
493 cm_example (), cm_smallexample (), cm_lisp (), cm_format (), cm_exdent (),
494 cm_defindex (), cm_defcodeindex (), cm_result (), cm_expansion (),
495 cm_equiv (), cm_print (), cm_error (), cm_point (), cm_today (),
496 cm_flushleft (), cm_flushright (), cm_smalllisp (), cm_finalout (),
497 cm_cartouche (), cm_detailmenu (), cm_multitable ();
499 /* Conditionals. */
500 void cm_set (), cm_clear (), cm_ifset (), cm_ifclear ();
501 void cm_value (), cm_ifeq ();
503 #if defined (HAVE_MACROS)
504 /* Define a user-defined command which is simple substitution. */
505 void cm_macro (), cm_unmacro ();
506 #endif /* HAVE_MACROS */
508 /* Options. */
509 void cm_paragraphindent (), cm_footnotestyle ();
511 /* Internals. */
512 void command_name_condition (), misplaced_brace (), cm_obsolete (),
513 cm_ideprecated ();
515 typedef struct
517 char *name;
518 COMMAND_FUNCTION *proc;
519 int argument_in_braces;
520 } COMMAND;
522 /* Stuff for defining commands on the fly. */
523 COMMAND **user_command_array = (COMMAND **) NULL;
524 int user_command_array_len = 0;
526 #define NO_BRACE_ARGS 0
527 #define BRACE_ARGS 1
529 static COMMAND command_table[] = {
530 { "\t", insert_space, NO_BRACE_ARGS },
531 { "\n", insert_space, NO_BRACE_ARGS },
532 { " ", insert_self, NO_BRACE_ARGS },
533 { "!", insert_self, NO_BRACE_ARGS },
534 { "\"", insert_self, NO_BRACE_ARGS },
535 { "'", insert_self, NO_BRACE_ARGS },
536 { "*", cm_asterisk, NO_BRACE_ARGS },
537 { ",", cm_accent, BRACE_ARGS },
538 { "-", cm_no_op, NO_BRACE_ARGS },
539 { ".", insert_self, NO_BRACE_ARGS },
540 { ":", cm_no_op, NO_BRACE_ARGS },
541 { "=", insert_self, NO_BRACE_ARGS },
542 { "?", insert_self, NO_BRACE_ARGS },
543 { "@", insert_self, NO_BRACE_ARGS },
544 { "^", insert_self, NO_BRACE_ARGS },
545 { "`", insert_self, NO_BRACE_ARGS },
546 { "{", insert_self, NO_BRACE_ARGS },
547 { "|", cm_no_op, NO_BRACE_ARGS },
548 { "}", insert_self, NO_BRACE_ARGS },
549 { "~", insert_self, NO_BRACE_ARGS },
550 { "AA", insert_self, BRACE_ARGS },
551 { "AE", insert_self, BRACE_ARGS },
552 { "H", cm_accent, BRACE_ARGS },
553 { "L", cm_special_char, BRACE_ARGS },
554 { "O", cm_special_char, BRACE_ARGS },
555 { "OE", insert_self, BRACE_ARGS },
556 { "TeX", cm_TeX, BRACE_ARGS },
557 { "aa", insert_self, BRACE_ARGS },
558 { "ae", insert_self, BRACE_ARGS },
559 { "appendix", cm_appendix, NO_BRACE_ARGS },
560 { "appendixsection", cm_appendixsec, NO_BRACE_ARGS },
561 { "appendixsec", cm_appendixsec, NO_BRACE_ARGS },
562 { "appendixsubsec", cm_appendixsubsec, NO_BRACE_ARGS },
563 { "appendixsubsubsec", cm_appendixsubsubsec, NO_BRACE_ARGS },
564 { "asis", cm_no_op, BRACE_ARGS },
565 { "b", cm_not_fixed_width, BRACE_ARGS },
566 { "bullet", cm_bullet, BRACE_ARGS },
567 { "bye", cm_bye, NO_BRACE_ARGS },
568 { "c", cm_ignore_line, NO_BRACE_ARGS },
569 { "cartouche", cm_cartouche, NO_BRACE_ARGS },
570 { "center", cm_center, NO_BRACE_ARGS },
571 { "centerchap", cm_unnumbered, NO_BRACE_ARGS },
572 { "chapheading", cm_chapheading, NO_BRACE_ARGS },
573 { "chapter", cm_chapter, NO_BRACE_ARGS },
574 { "cindex", cm_cindex, NO_BRACE_ARGS },
575 { "cite", cm_cite, BRACE_ARGS },
576 { "clear", cm_clear, NO_BRACE_ARGS },
577 { "code", cm_code, BRACE_ARGS },
578 { "comment", cm_ignore_line, NO_BRACE_ARGS },
579 { "contents", cm_no_op, NO_BRACE_ARGS },
580 { "copyright", cm_copyright, BRACE_ARGS },
581 { "ctrl", cm_obsolete, BRACE_ARGS },
582 { "defcodeindex", cm_defcodeindex, NO_BRACE_ARGS },
583 { "defindex", cm_defindex, NO_BRACE_ARGS },
584 /* The `def' commands. */
585 { "defcv", cm_defun, NO_BRACE_ARGS },
586 { "defcvx", cm_defun, NO_BRACE_ARGS },
587 { "deffn", cm_defun, NO_BRACE_ARGS },
588 { "deffnx", cm_defun, NO_BRACE_ARGS },
589 { "defivar", cm_defun, NO_BRACE_ARGS },
590 { "defivarx", cm_defun, NO_BRACE_ARGS },
591 { "defmac", cm_defun, NO_BRACE_ARGS },
592 { "defmacx", cm_defun, NO_BRACE_ARGS },
593 { "defmethod", cm_defun, NO_BRACE_ARGS },
594 { "defmethodx", cm_defun, NO_BRACE_ARGS },
595 { "defop", cm_defun, NO_BRACE_ARGS },
596 { "defopt", cm_defun, NO_BRACE_ARGS },
597 { "defoptx", cm_defun, NO_BRACE_ARGS },
598 { "defopx", cm_defun, NO_BRACE_ARGS },
599 { "defspec", cm_defun, NO_BRACE_ARGS },
600 { "defspecx", cm_defun, NO_BRACE_ARGS },
601 { "deftp", cm_defun, NO_BRACE_ARGS },
602 { "deftpx", cm_defun, NO_BRACE_ARGS },
603 { "deftypefn", cm_defun, NO_BRACE_ARGS },
604 { "deftypefnx", cm_defun, NO_BRACE_ARGS },
605 { "deftypefun", cm_defun, NO_BRACE_ARGS },
606 { "deftypefunx", cm_defun, NO_BRACE_ARGS },
607 { "deftypemethod", cm_defun, NO_BRACE_ARGS },
608 { "deftypemethodx", cm_defun, NO_BRACE_ARGS },
609 { "deftypevar", cm_defun, NO_BRACE_ARGS },
610 { "deftypevarx", cm_defun, NO_BRACE_ARGS },
611 { "deftypevr", cm_defun, NO_BRACE_ARGS },
612 { "deftypevrx", cm_defun, NO_BRACE_ARGS },
613 { "defun", cm_defun, NO_BRACE_ARGS },
614 { "defunx", cm_defun, NO_BRACE_ARGS },
615 { "defvar", cm_defun, NO_BRACE_ARGS },
616 { "defvarx", cm_defun, NO_BRACE_ARGS },
617 { "defvr", cm_defun, NO_BRACE_ARGS },
618 { "defvrx", cm_defun, NO_BRACE_ARGS },
619 /* The end of the `def' commands. */
620 { "detailmenu", cm_detailmenu, NO_BRACE_ARGS },
621 { "dfn", cm_dfn, BRACE_ARGS },
622 { "dircategory", cm_dircategory, NO_BRACE_ARGS },
623 { "direntry", cm_direntry, NO_BRACE_ARGS },
624 { "display", cm_display, NO_BRACE_ARGS },
625 { "dmn", cm_no_op, BRACE_ARGS },
626 { "dotaccent", cm_accent, BRACE_ARGS },
627 { "dotless", cm_dotless, BRACE_ARGS },
628 { "dots", cm_dots, BRACE_ARGS },
629 { "email", cm_email, BRACE_ARGS },
630 { "emph", cm_emph, BRACE_ARGS },
631 { "end", cm_end, NO_BRACE_ARGS },
632 { "enddots", cm_enddots, BRACE_ARGS },
633 { "enumerate", cm_enumerate, NO_BRACE_ARGS },
634 { "equiv", cm_equiv, BRACE_ARGS },
635 { "error", cm_error, BRACE_ARGS },
636 { "example", cm_example, NO_BRACE_ARGS },
637 { "exclamdown", cm_special_char, BRACE_ARGS },
638 { "exdent", cm_exdent, NO_BRACE_ARGS },
639 { "expansion", cm_expansion, BRACE_ARGS },
640 { "file", cm_code, BRACE_ARGS },
641 { "finalout", cm_no_op, NO_BRACE_ARGS },
642 { "findex", cm_findex, NO_BRACE_ARGS },
643 { "flushleft", cm_flushleft, NO_BRACE_ARGS },
644 { "flushright", cm_flushright, NO_BRACE_ARGS },
645 { "footnote", cm_footnote, NO_BRACE_ARGS}, /* self-arg eater */
646 { "footnotestyle", cm_footnotestyle, NO_BRACE_ARGS },
647 { "format", cm_format, NO_BRACE_ARGS },
648 { "ftable", cm_ftable, NO_BRACE_ARGS },
649 { "group", cm_group, NO_BRACE_ARGS },
650 { "heading", cm_heading, NO_BRACE_ARGS },
651 { "headings", cm_ignore_line, NO_BRACE_ARGS },
652 { "html", command_name_condition, NO_BRACE_ARGS },
653 { "hyphenation", cm_no_op, BRACE_ARGS },
654 { "i", cm_not_fixed_width, BRACE_ARGS },
655 { "ifclear", cm_ifclear, NO_BRACE_ARGS },
656 { "ifeq", cm_ifeq, NO_BRACE_ARGS },
657 { "ifhtml", command_name_condition, NO_BRACE_ARGS },
658 { "ifinfo", cm_ifinfo, NO_BRACE_ARGS },
659 { "ifnothtml", cm_ifnothtml, NO_BRACE_ARGS },
660 { "ifnotinfo", command_name_condition, NO_BRACE_ARGS },
661 { "ifnottex", cm_ifnottex, NO_BRACE_ARGS },
662 { "ifset", cm_ifset, NO_BRACE_ARGS },
663 { "iftex", command_name_condition, NO_BRACE_ARGS },
664 { "ignore", command_name_condition, NO_BRACE_ARGS },
665 { "image", cm_image, BRACE_ARGS },
666 { "include", cm_include, NO_BRACE_ARGS },
667 { "inforef", cm_inforef, BRACE_ARGS },
668 { "item", cm_item, NO_BRACE_ARGS },
669 { "itemize", cm_itemize, NO_BRACE_ARGS },
670 { "itemx", cm_itemx, NO_BRACE_ARGS },
671 { "kbd", cm_kbd, BRACE_ARGS },
672 { "kbdinputstyle", cm_no_op_line_arg, NO_BRACE_ARGS },
673 { "key", cm_key, BRACE_ARGS },
674 { "kindex", cm_kindex, NO_BRACE_ARGS },
675 { "l", cm_special_char, BRACE_ARGS },
676 { "lisp", cm_lisp, NO_BRACE_ARGS },
677 { "lowersections", cm_lowersections, NO_BRACE_ARGS },
678 { "macro", cm_macro, NO_BRACE_ARGS },
679 { "majorheading", cm_majorheading, NO_BRACE_ARGS },
680 { "math", cm_no_op, BRACE_ARGS },
681 { "menu", cm_menu, NO_BRACE_ARGS },
682 { "minus", cm_minus, BRACE_ARGS },
683 { "multitable", cm_multitable, NO_BRACE_ARGS },
684 { "need", cm_ignore_line, NO_BRACE_ARGS },
685 { "node", cm_node, NO_BRACE_ARGS },
686 { "noindent", cm_noindent, NO_BRACE_ARGS },
687 { "nwnode", cm_node, NO_BRACE_ARGS },
688 { "o", cm_special_char, BRACE_ARGS },
689 { "oe", insert_self, BRACE_ARGS },
690 { "page", cm_no_op, NO_BRACE_ARGS },
691 { "paragraphindent", cm_paragraphindent, NO_BRACE_ARGS },
692 { "pindex", cm_pindex, NO_BRACE_ARGS },
693 { "point", cm_point, BRACE_ARGS },
694 { "pounds", cm_special_char, BRACE_ARGS },
695 { "print", cm_print, BRACE_ARGS },
696 { "printindex", cm_printindex, NO_BRACE_ARGS },
697 { "pxref", cm_pxref, BRACE_ARGS },
698 { "questiondown", cm_special_char, BRACE_ARGS },
699 { "quotation", cm_quotation, NO_BRACE_ARGS },
700 { "r", cm_not_fixed_width, BRACE_ARGS },
701 { "raisesections", cm_raisesections, NO_BRACE_ARGS },
702 { "ref", cm_xref, BRACE_ARGS },
703 { "refill", cm_no_op, NO_BRACE_ARGS },
704 { "result", cm_result, BRACE_ARGS },
705 { "ringaccent", cm_accent, BRACE_ARGS },
706 { "samp", cm_code, BRACE_ARGS },
707 { "sc", cm_var_sc, BRACE_ARGS },
708 { "section", cm_section, NO_BRACE_ARGS },
709 { "set", cm_set, NO_BRACE_ARGS },
710 { "setchapternewpage", cm_ignore_line, NO_BRACE_ARGS },
711 { "setchapterstyle", cm_obsolete, NO_BRACE_ARGS },
712 { "setfilename", cm_setfilename, NO_BRACE_ARGS },
713 { "settitle", cm_ignore_line, NO_BRACE_ARGS },
714 { "shortcontents", cm_no_op, NO_BRACE_ARGS },
715 { "shorttitlepage", cm_ignore_line, NO_BRACE_ARGS },
716 { "smallbook", cm_ignore_line, NO_BRACE_ARGS },
717 { "smallexample", cm_smallexample, NO_BRACE_ARGS },
718 { "smalllisp", cm_smalllisp, NO_BRACE_ARGS },
719 { "sp", cm_sp, NO_BRACE_ARGS },
720 { "ss", insert_self, BRACE_ARGS },
721 { "strong", cm_strong, BRACE_ARGS },
722 { "subheading", cm_subheading, NO_BRACE_ARGS },
723 { "subsection", cm_subsection, NO_BRACE_ARGS },
724 { "subsubheading", cm_subsubheading, NO_BRACE_ARGS },
725 { "subsubsection", cm_subsubsection, NO_BRACE_ARGS },
726 { "summarycontents", cm_no_op, NO_BRACE_ARGS },
727 { "syncodeindex", cm_synindex, NO_BRACE_ARGS },
728 { "synindex", cm_synindex, NO_BRACE_ARGS },
729 { "t", cm_no_op, BRACE_ARGS },
730 { "tab", cm_tab, NO_BRACE_ARGS },
731 { "table", cm_table, NO_BRACE_ARGS },
732 { "tex", command_name_condition, NO_BRACE_ARGS },
733 { "tieaccent", cm_accent, BRACE_ARGS },
734 { "tindex", cm_tindex, NO_BRACE_ARGS },
735 { "titlefont", cm_not_fixed_width, BRACE_ARGS },
736 { "titlepage", command_name_condition, NO_BRACE_ARGS },
737 { "today", cm_today, BRACE_ARGS },
738 { "top", cm_top, NO_BRACE_ARGS },
739 { "u", cm_accent, BRACE_ARGS },
740 { "ubaraccent", cm_accent, BRACE_ARGS },
741 { "udotaccent", cm_accent, BRACE_ARGS },
742 #if defined (HAVE_MACROS)
743 { "unmacro", cm_unmacro, NO_BRACE_ARGS },
744 #endif
745 { "unnumbered", cm_unnumbered, NO_BRACE_ARGS },
746 { "unnumberedsec", cm_unnumberedsec, NO_BRACE_ARGS },
747 { "unnumberedsubsec", cm_unnumberedsubsec, NO_BRACE_ARGS },
748 { "unnumberedsubsubsec", cm_unnumberedsubsubsec, NO_BRACE_ARGS },
749 { "uref", cm_uref, BRACE_ARGS },
750 { "url", cm_code, BRACE_ARGS },
751 { "v", cm_accent, BRACE_ARGS },
752 { "value", cm_value, BRACE_ARGS },
753 { "var", cm_var_sc, BRACE_ARGS },
754 { "vindex", cm_vindex, NO_BRACE_ARGS },
755 { "vtable", cm_vtable, NO_BRACE_ARGS },
756 { "w", cm_w, BRACE_ARGS },
757 { "xref", cm_xref, BRACE_ARGS },
759 /* Deprecated commands. These used to be for italics. */
760 { "iappendix", cm_ideprecated, NO_BRACE_ARGS },
761 { "iappendixsec", cm_ideprecated, NO_BRACE_ARGS },
762 { "iappendixsection", cm_ideprecated, NO_BRACE_ARGS },
763 { "iappendixsubsec", cm_ideprecated, NO_BRACE_ARGS },
764 { "iappendixsubsubsec", cm_ideprecated, NO_BRACE_ARGS },
765 { "ichapter", cm_ideprecated, NO_BRACE_ARGS },
766 { "isection", cm_ideprecated, NO_BRACE_ARGS },
767 { "isubsection", cm_ideprecated, NO_BRACE_ARGS },
768 { "isubsubsection", cm_ideprecated, NO_BRACE_ARGS },
769 { "iunnumbered", cm_ideprecated, NO_BRACE_ARGS },
770 { "iunnumberedsec", cm_ideprecated, NO_BRACE_ARGS },
771 { "iunnumberedsubsec", cm_ideprecated, NO_BRACE_ARGS },
772 { "iunnumberedsubsubsec", cm_ideprecated, NO_BRACE_ARGS },
774 /* Now @include does what this was used to. */
775 { "infoinclude", cm_obsolete, NO_BRACE_ARGS },
776 { "titlespec", cm_obsolete, NO_BRACE_ARGS },
778 { NULL, NULL, NO_BRACE_ARGS }
781 struct option long_options[] =
783 { "error-limit", 1, 0, 'e' }, /* formerly -el */
784 { "fill-column", 1, 0, 'f' }, /* formerly -fc */
785 { "footnote-style", 1, 0, 's' }, /* formerly -ft */
786 { "force", 0, 0, 'F' }, /* do not remove output */
787 { "no-headers", 0, &no_headers, 1 }, /* do not output Node: foo */
788 { "no-pointer-validate", 0, &validating, 0 }, /* formerly -nv */
789 { "no-validate", 0, &validating, 0 }, /* formerly -nv */
790 { "no-split", 0, &splitting, 0 }, /* formerly -ns */
791 { "no-warn", 0, &print_warnings, 0 }, /* formerly -nw */
792 { "macro-expand", 1, 0, 'E' },
793 { "number-footnotes", 0, &number_footnotes, 1 },
794 { "no-number-footnotes", 0, &number_footnotes, 0 },
795 { "output", 1, 0, 'o' },
796 { "paragraph-indent", 1, 0, 'p' }, /* formerly -pi */
797 { "reference-limit", 1, 0, 'r' }, /* formerly -rl */
798 { "verbose", 0, &verbose_mode, 1 }, /* formerly -verbose */
799 { "help", 0, 0, 'h' },
800 { "version", 0, 0, 'V' },
801 {NULL, 0, NULL, 0}
804 /* **************************************************************** */
805 /* */
806 /* Error Handling */
807 /* */
808 /* **************************************************************** */
810 /* Number of errors encountered. */
811 int errors_printed = 0;
813 /* Print the last error gotten from the file system. */
815 fs_error (filename)
816 char *filename;
818 remember_error ();
819 perror (filename);
820 return (0);
823 /* Print an error message, and return false. */
824 void
825 #if defined (VA_FPRINTF) && __STDC__
826 error (char *format, ...)
827 #else
828 error (format, va_alist)
829 char *format;
830 va_dcl
831 #endif
833 #ifdef VA_FPRINTF
834 va_list ap;
835 #endif
837 remember_error ();
839 VA_START (ap, format);
840 #ifdef VA_FPRINTF
841 VA_FPRINTF (stderr, format, ap);
842 #else
843 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
844 #endif /* not VA_FPRINTF */
845 va_end (ap);
847 putc ('\n', stderr);
850 /* Just like error (), but print the line number as well. */
851 void
852 #if defined (VA_FPRINTF) && __STDC__
853 line_error (char *format, ...)
854 #else
855 line_error (format, va_alist)
856 char *format;
857 va_dcl
858 #endif
860 #ifdef VA_FPRINTF
861 va_list ap;
862 #endif
864 remember_error ();
865 fprintf (stderr, "%s:%d: ", input_filename, line_number);
867 VA_START (ap, format);
868 #ifdef VA_FPRINTF
869 VA_FPRINTF (stderr, format, ap);
870 #else
871 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
872 #endif /* not VA_FPRINTF */
873 va_end (ap);
875 fprintf (stderr, ".\n");
878 void
879 #if defined (VA_FPRINTF) && __STDC__
880 warning (char *format, ...)
881 #else
882 warning (format, va_alist)
883 char *format;
884 va_dcl
885 #endif
887 #ifdef VA_FPRINTF
888 va_list ap;
889 #endif
891 if (print_warnings)
893 fprintf (stderr, _("%s:%d: warning: "), input_filename, line_number);
895 VA_START (ap, format);
896 #ifdef VA_FPRINTF
897 VA_FPRINTF (stderr, format, ap);
898 #else
899 fprintf (stderr, format, a1, a2, a3, a4, a5, a6, a7, a8);
900 #endif /* not VA_FPRINTF */
901 va_end (ap);
903 fprintf (stderr, ".\n");
908 /* Remember that an error has been printed. If more than
909 max_error_level have been printed, then exit the program. */
910 void
911 remember_error ()
913 errors_printed++;
914 if (max_error_level && (errors_printed > max_error_level))
916 fprintf (stderr, _("Too many errors! Gave up.\n"));
917 flush_file_stack ();
918 cm_bye ();
919 exit (FATAL);
923 /* **************************************************************** */
924 /* */
925 /* Main () Start of code */
926 /* */
927 /* **************************************************************** */
929 /* For each file mentioned in the command line, process it, turning
930 Texinfo commands into wonderfully formatted output text. */
932 main (argc, argv)
933 int argc;
934 char **argv;
936 extern int errors_printed;
937 char *filename_part ();
938 int c, ind;
939 int reading_from_stdin = 0;
941 /* The name of this program is the last filename in argv[0]. */
942 progname = filename_part (argv[0]);
944 #ifdef HAVE_SETLOCALE
945 /* Do not use LC_ALL, because LC_NUMERIC screws up the scanf parsing
946 of the argument to @multicolumn. */
947 setlocale (LC_TIME, "");
948 #ifdef HAVE_LC_MESSAGES
949 setlocale (LC_MESSAGES, "");
950 #endif
951 #endif
953 /* Set the text message domain. */
954 bindtextdomain (PACKAGE, LOCALEDIR);
955 textdomain (PACKAGE);
957 /* Parse argument flags from the input line. */
958 while ((c = getopt_long (argc, argv, "D:e:E:f:I:o:p:P:r:s:U:V",
959 long_options, &ind)) != EOF)
961 if (c == 0 && long_options[ind].flag == 0)
962 c = long_options[ind].val;
964 switch (c)
966 case 'D':
967 case 'U':
968 /* User specified variable to set or clear. */
969 handle_variable_internal ((c == 'D') ? SET : CLEAR, optarg);
970 break;
972 case 'e':
973 /* User specified error level. */
974 if (sscanf (optarg, "%d", &max_error_level) != 1)
976 fprintf (stderr,
977 _("%s: %s arg must be numeric, not `%s'.\n"),
978 "--error-limit", progname, optarg);
979 usage (stderr, FATAL);
981 break;
983 case 'E':
984 /* User specified a macro expansion output file. */
985 if (!macro_expansion_output_stream)
987 macro_expansion_filename = optarg;
988 macro_expansion_output_stream
989 = strcmp (optarg, "-") == 0 ? stdout : fopen (optarg, "w");
990 if (!macro_expansion_output_stream)
991 error (_("Couldn't open macro expansion output `%s'"), optarg);
993 else
994 error (_("Cannot specify more than one macro expansion output"));
995 break;
997 case 'f':
998 /* User specified fill_column. */
999 if (sscanf (optarg, "%d", &fill_column) != 1)
1001 fprintf (stderr,
1002 _("%s: %s arg must be numeric, not `%s'.\n"),
1003 "--fill-column", progname, optarg);
1004 usage (FATAL);
1006 break;
1008 case 'F':
1009 force++; /* Do not remove erroneous output. */
1010 break;
1012 case 'h':
1013 usage (NO_ERROR);
1014 break;
1016 case 'I':
1017 /* Append user-specified dir to include file path. */
1018 if (!include_files_path)
1019 include_files_path = xstrdup (".");
1021 include_files_path = (char *)
1022 xrealloc (include_files_path,
1023 2 + strlen (include_files_path) + strlen (optarg));
1024 strcat (include_files_path, ":");
1025 strcat (include_files_path, optarg);
1026 break;
1028 case 'o':
1029 /* User specified output file. */
1030 command_output_filename = xstrdup (optarg);
1031 break;
1033 case 'p':
1034 /* User specified paragraph indent (paragraph_start_index). */
1035 if (set_paragraph_indent (optarg) < 0)
1037 fprintf (stderr,
1038 _("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"),
1039 progname, optarg);
1040 usage (FATAL);
1042 break;
1044 case 'P':
1045 /* Prepend user-specified include dir to include path. */
1046 if (!include_files_path)
1048 include_files_path = xstrdup (optarg);
1049 include_files_path = (char *) xrealloc (include_files_path,
1050 strlen (include_files_path) + 3); /* 3 for ":.\0" */
1051 strcat (include_files_path, ":.");
1053 else
1055 char *tmp = xstrdup (include_files_path);
1056 include_files_path = (char *) xrealloc (include_files_path,
1057 strlen (include_files_path) + strlen (optarg) + 2); /* 2 for ":\0" */
1058 strcpy (include_files_path, optarg);
1059 strcat (include_files_path, ":");
1060 strcat (include_files_path, tmp);
1061 free (tmp);
1063 break;
1065 case 'r':
1066 /* User specified reference warning limit. */
1067 if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
1069 fprintf (stderr,
1070 _("%s: %s arg must be numeric, not `%s'.\n"),
1071 "--reference-limit", progname, optarg);
1072 usage (FATAL);
1074 break;
1076 case 's':
1077 /* User specified footnote style. */
1078 if (set_footnote_style (optarg) < 0)
1080 fprintf (stderr,
1081 _("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"),
1082 progname, optarg);
1083 usage (FATAL);
1085 footnote_style_preset = 1;
1086 break;
1088 case 'V':
1089 /* User requested version info. */
1090 print_version_info ();
1091 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
1092 There is NO warranty. You may redistribute this software\n\
1093 under the terms of the GNU General Public License.\n\
1094 For more information about these matters, see the files named COPYING.\n"),
1095 "1998");
1096 exit (NO_ERROR);
1097 break;
1099 case '?':
1100 usage (FATAL);
1101 break;
1105 if (optind == argc)
1107 /* Check to see if input is a file. If so, process that. */
1108 if (!isatty (fileno (stdin)))
1109 reading_from_stdin = 1;
1110 else
1112 fprintf (stderr, _("%s: missing file argument.\n"), progname);
1113 usage (FATAL);
1117 /* If the user has specified --no-headers, this should imply --no-split.
1118 Do that here. I think it might also imply that we should ignore the
1119 setfilename at the top of the file, but this might break some FSF things,
1120 so I will hold off on that. */
1121 if (no_headers)
1123 splitting = 0;
1125 /* If the user has not specified an output file, use stdout. */
1126 if (!command_output_filename)
1127 command_output_filename = xstrdup ("-");
1130 if (verbose_mode)
1131 print_version_info ();
1133 /* Remaining arguments are file names of texinfo files.
1134 Convert them, one by one. */
1135 if (!reading_from_stdin)
1137 while (optind != argc)
1138 convert_from_file (argv[optind++]);
1140 else
1141 convert_from_stream (stdin, "stdin");
1143 if (errors_printed)
1144 return (SYNTAX);
1145 else
1146 return (NO_ERROR);
1149 /* Display the version info of this invocation of Makeinfo. */
1150 void
1151 print_version_info ()
1153 printf ("makeinfo (GNU %s %s) %d.%d\n", PACKAGE, VERSION,
1154 major_version, minor_version);
1157 /* If EXIT_VALUE is zero, print the full usage message to stdout.
1158 Otherwise, just say to use --help for more info.
1159 Then exit with EXIT_VALUE. */
1160 void
1161 usage (exit_value)
1162 int exit_value;
1164 if (exit_value != 0)
1165 fprintf (stderr, _("Try `%s --help' for more information.\n"), progname);
1166 else
1167 printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n\
1169 Translate Texinfo source documentation to a format suitable for reading\n\
1170 with GNU Info.\n\
1172 Options:\n\
1173 -D VAR define a variable, as with @set.\n\
1174 -E MACRO-OFILE process macros only, output texinfo source.\n\
1175 -I DIR append DIR to the @include directory search path.\n\
1176 -P DIR prepend DIR to the @include directory search path.\n\
1177 -U VAR undefine a variable, as with @clear.\n\
1178 --error-limit NUM quit after NUM errors (default %d).\n\
1179 --fill-column NUM break lines at NUM characters (default %d).\n\
1180 --footnote-style STYLE output footnotes according to STYLE:\n\
1181 `separate' to place footnotes in their own node,\n\
1182 `end' to place the footnotes at the end of\n\
1183 the node in which they are defined (the default).\n\
1184 --force preserve output even if errors.\n\
1185 --help display this help and exit.\n\
1186 --no-validate suppress node cross-reference validation.\n\
1187 --no-warn suppress warnings (but not errors).\n\
1188 --no-split suppress splitting of large files.\n\
1189 --no-headers suppress node separators and Node: Foo headers.\n\
1190 --output FILE, -o FILE output to FILE, and ignore any @setfilename.\n\
1191 --paragraph-indent VAL indent paragraphs with VAL spaces (default %d).\n\
1192 if VAL is `none', do not indent; if VAL is `asis',\n\
1193 preserve any existing indentation.\n\
1194 --reference-limit NUM complain about at most NUM references (default %d).\n\
1195 --verbose report about what is being done.\n\
1196 --version display version information and exit.\n\
1198 Email bug reports to bug-texinfo@gnu.org.\n\
1200 progname, max_error_level, fill_column,
1201 paragraph_start_indent, reference_warning_limit);
1202 exit (exit_value);
1205 /* Manipulating Lists */
1207 typedef struct generic_list {
1208 struct generic_list *next;
1209 } GENERIC_LIST;
1211 /* Reverse the chain of structures in LIST. Output the new head
1212 of the chain. You should always assign the output value of this
1213 function to something, or you will lose the chain. */
1214 GENERIC_LIST *
1215 reverse_list (list)
1216 register GENERIC_LIST *list;
1218 register GENERIC_LIST *next;
1219 register GENERIC_LIST *prev = (GENERIC_LIST *) NULL;
1221 while (list)
1223 next = list->next;
1224 list->next = prev;
1225 prev = list;
1226 list = next;
1228 return (prev);
1231 /* Pushing and Popping Files */
1233 /* Find and load the file named FILENAME. Return a pointer to
1234 the loaded file, or NULL if it can't be loaded. */
1235 char *
1236 find_and_load (filename)
1237 char *filename;
1239 struct stat fileinfo;
1240 long file_size;
1241 int file = -1, count = 0;
1242 char *fullpath, *result, *get_file_info_in_path ();
1244 result = fullpath = (char *)NULL;
1246 fullpath = get_file_info_in_path (filename, include_files_path, &fileinfo);
1248 if (!fullpath)
1249 goto error_exit;
1251 filename = fullpath;
1252 file_size = (long) fileinfo.st_size;
1254 file = open (filename, O_RDONLY);
1255 if (file < 0)
1256 goto error_exit;
1258 /* Load the file, with enough room for a newline and a null. */
1259 result = xmalloc (file_size + 2);
1261 /* VMS stat lies about the st_size value. The actual number of
1262 readable bytes is always less than this value. The arcane
1263 mysteries of VMS/RMS are too much to probe, so this hack
1264 suffices to make things work. */
1265 #if defined (VMS) || defined (WIN32)
1266 #ifdef VMS
1267 while ((n = read (file, result + count, file_size)) > 0)
1268 #else /* WIN32 */
1269 while ((n = read (file, result + count, 1)) > 0)
1270 #endif /* WIN32 */
1271 count += n;
1272 if (n == -1)
1273 #else /* !VMS && !WIN32 */
1274 count = file_size;
1275 if (read (file, result, file_size) != file_size)
1276 #endif /* !VMS && !WIN32 */
1277 error_exit:
1279 if (result)
1280 free (result);
1282 if (fullpath)
1283 free (fullpath);
1285 if (file != -1)
1286 close (file);
1288 return ((char *) NULL);
1290 close (file);
1292 /* Set the globals to the new file. */
1293 input_text = result;
1294 size_of_input_text = count;
1295 input_filename = fullpath;
1296 node_filename = xstrdup (fullpath);
1297 input_text_offset = 0;
1298 line_number = 1;
1299 /* Not strictly necessary. This magic prevents read_token () from doing
1300 extra unnecessary work each time it is called (that is a lot of times).
1301 SIZE_OF_INPUT_TEXT is one past the actual end of the text. */
1302 input_text[size_of_input_text] = '\n';
1303 /* This, on the other hand, is always necessary. */
1304 input_text[size_of_input_text+1] = 0;
1305 return (result);
1308 /* Save the state of the current input file. */
1309 void
1310 pushfile ()
1312 FSTACK *newstack = (FSTACK *) xmalloc (sizeof (FSTACK));
1313 newstack->filename = input_filename;
1314 newstack->text = input_text;
1315 newstack->size = size_of_input_text;
1316 newstack->offset = input_text_offset;
1317 newstack->line_number = line_number;
1318 newstack->next = filestack;
1320 filestack = newstack;
1321 push_node_filename ();
1324 /* Make the current file globals be what is on top of the file stack. */
1325 void
1326 popfile ()
1328 FSTACK *tos = filestack;
1330 if (!tos)
1331 abort (); /* My fault. I wonder what I did? */
1333 #if defined (HAVE_MACROS)
1334 if (macro_expansion_output_stream)
1336 maybe_write_itext (input_text, input_text_offset);
1337 forget_itext (input_text);
1339 #endif /* HAVE_MACROS */
1341 /* Pop the stack. */
1342 filestack = filestack->next;
1344 /* Make sure that commands with braces have been satisfied. */
1345 if (!executing_string && !me_executing_string)
1346 discard_braces ();
1348 /* Get the top of the stack into the globals. */
1349 input_filename = tos->filename;
1350 input_text = tos->text;
1351 size_of_input_text = tos->size;
1352 input_text_offset = tos->offset;
1353 line_number = tos->line_number;
1354 free (tos);
1356 /* Go back to the (now) current node. */
1357 pop_node_filename ();
1360 /* Flush all open files on the file stack. */
1361 void
1362 flush_file_stack ()
1364 while (filestack)
1366 char *fname = input_filename;
1367 char *text = input_text;
1368 popfile ();
1369 free (fname);
1370 free (text);
1374 int node_filename_stack_index = 0;
1375 int node_filename_stack_size = 0;
1376 char **node_filename_stack = (char **)NULL;
1378 void
1379 push_node_filename ()
1381 if (node_filename_stack_index + 1 > node_filename_stack_size)
1382 node_filename_stack = (char **)xrealloc
1383 (node_filename_stack, (node_filename_stack_size += 10) * sizeof (char *));
1385 node_filename_stack[node_filename_stack_index] = node_filename;
1386 node_filename_stack_index++;
1389 void
1390 pop_node_filename ()
1392 node_filename = node_filename_stack[--node_filename_stack_index];
1395 /* Return just the simple part of the filename; i.e. the
1396 filename without the path information, or extensions.
1397 This conses up a new string. */
1398 char *
1399 filename_part (filename)
1400 char *filename;
1402 char *basename;
1404 basename = strrchr (filename, '/');
1405 if (!basename)
1406 basename = filename;
1407 else
1408 basename++;
1410 basename = xstrdup (basename);
1411 #if defined (REMOVE_OUTPUT_EXTENSIONS)
1413 /* See if there is an extension to remove. If so, remove it. */
1415 char *temp;
1417 temp = strrchr (basename, '.');
1418 if (temp)
1419 *temp = 0;
1421 #endif /* REMOVE_OUTPUT_EXTENSIONS */
1422 return (basename);
1425 /* Return the pathname part of filename. This can be NULL. */
1426 char *
1427 pathname_part (filename)
1428 char *filename;
1430 char *expand_filename ();
1431 char *result = (char *) NULL;
1432 register int i;
1434 filename = expand_filename (filename, "");
1436 i = strlen (filename) - 1;
1438 while (i && filename[i] != '/')
1439 i--;
1440 if (filename[i] == '/')
1441 i++;
1443 if (i)
1445 result = (char *)xmalloc (1 + i);
1446 strncpy (result, filename, i);
1447 result[i] = 0;
1449 free (filename);
1450 return (result);
1453 char *
1454 filename_non_directory (name)
1455 char *name;
1457 register int i;
1459 for (i = strlen (name) - 1; i; i--)
1460 if (name[i] == '/')
1461 return (xstrdup (name + i + 1));
1463 return (xstrdup (name));
1466 /* Return the expansion of FILENAME. */
1467 char *
1468 expand_filename (filename, input_name)
1469 char *filename, *input_name;
1471 register int i;
1472 char *full_pathname ();
1474 if (filename)
1475 filename = full_pathname (filename);
1476 else
1478 filename = filename_non_directory (input_name);
1480 if (!*filename)
1482 free (filename);
1483 filename = xstrdup ("noname.texi");
1486 for (i = strlen (filename) - 1; i; i--)
1487 if (filename[i] == '.')
1488 break;
1490 if (!i)
1491 i = strlen (filename);
1493 if (i + 6 > (strlen (filename)))
1494 filename = (char *)xrealloc (filename, i + 6);
1495 strcpy (filename + i, ".info");
1496 return (filename);
1499 if (filename[0] == '.' || filename[0] == '/')
1500 return (filename);
1502 if (filename[0] != '/' && input_name[0] == '/')
1504 /* Make it so that relative names work. */
1505 char *result;
1507 i = strlen (input_name) - 1;
1509 result = (char *)xmalloc (1 + strlen (input_name) + strlen (filename));
1510 strcpy (result, input_name);
1512 while (result[i] != '/' && i)
1513 i--;
1515 if (result[i] == '/')
1516 i++;
1518 strcpy (&result[i], filename);
1519 free (filename);
1520 return (result);
1522 return (filename);
1525 /* Return the full path to FILENAME. */
1526 char *
1527 full_pathname (filename)
1528 char *filename;
1530 int initial_character;
1531 char *result;
1533 /* No filename given? */
1534 if (!filename || !(initial_character = *filename))
1535 return (xstrdup (""));
1537 /* Already absolute? */
1538 if ((initial_character == '/') ||
1539 ((strncmp (filename, "./", 2) == 0) ||
1540 (strncmp (filename, "../", 3) == 0)))
1541 return (xstrdup (filename));
1543 if (initial_character != '~')
1545 char *localdir;
1547 localdir = (char *)xmalloc (1025);
1548 #if defined (HAVE_GETCWD)
1549 if (!getcwd (localdir, 1024))
1550 #else /* !HAVE_GETCWD */
1551 if (!getwd (localdir))
1552 #endif /* !HAVE_GETCWD */
1554 fprintf (stderr, _("%s: getwd: %s, %s\n"),
1555 progname, filename, localdir);
1556 exit (1);
1559 strcat (localdir, "/");
1560 strcat (localdir, filename);
1561 result = xstrdup (localdir);
1562 free (localdir);
1564 else
1566 #ifndef WIN32
1567 if (filename[1] == '/')
1569 /* Return the concatenation of the environment variable HOME
1570 and the rest of the string. */
1571 char *temp_home;
1573 temp_home = (char *) getenv ("HOME");
1574 result = (char *)xmalloc (strlen (&filename[1])
1576 + temp_home ? strlen (temp_home)
1577 : 0);
1578 *result = 0;
1580 if (temp_home)
1581 strcpy (result, temp_home);
1583 strcat (result, &filename[1]);
1585 else
1587 struct passwd *user_entry;
1588 int i, c;
1589 char *username = (char *)xmalloc (257);
1591 for (i = 1; (c = filename[i]); i++)
1593 if (c == '/')
1594 break;
1595 else
1596 username[i - 1] = c;
1598 if (c)
1599 username[i - 1] = 0;
1601 user_entry = getpwnam (username);
1603 if (!user_entry)
1604 return (xstrdup (filename));
1606 result = (char *)xmalloc (1 + strlen (user_entry->pw_dir)
1607 + strlen (&filename[i]));
1608 strcpy (result, user_entry->pw_dir);
1609 strcat (result, &filename[i]);
1612 #endif /* not WIN32 */
1613 return (result);
1616 char *
1617 output_name_from_input_name (name)
1618 char *name;
1620 return (expand_filename ((char *)NULL, name));
1623 /* **************************************************************** */
1624 /* */
1625 /* Hacking Tokens and Strings */
1626 /* */
1627 /* **************************************************************** */
1629 /* Return the next token as a string pointer. We cons the string. */
1630 char *
1631 read_token ()
1633 int i, character;
1634 char *result;
1636 /* If the first character to be read is self-delimiting, then that
1637 is the command itself. */
1638 character = curchar ();
1639 if (self_delimiting (character))
1641 input_text_offset++;
1643 if (character == '\n')
1644 line_number++;
1646 result = xstrdup (" ");
1647 *result = character;
1648 return (result);
1651 for (i = 0; ((input_text_offset != size_of_input_text)
1652 && (character = curchar ())
1653 && command_char (character));
1654 i++, input_text_offset++);
1655 result = (char *)xmalloc (i + 1);
1656 memcpy (result, &input_text[input_text_offset - i], i);
1657 result[i] = 0;
1658 return (result);
1661 /* Return nonzero if CHARACTER is self-delimiting. */
1663 self_delimiting (character)
1664 int character;
1666 /* @; and @\ are not Texinfo commands, but they are listed here
1667 anyway. I don't know why. --karl, 10aug96. */
1668 return member (character, "~{|}`^\\@?=;:.-,*\'\" !\n\t");
1671 /* Clear whitespace from the front and end of string. */
1672 void
1673 canon_white (string)
1674 char *string;
1676 int len = strlen (string);
1677 int x;
1679 if (!len)
1680 return;
1682 for (x = 0; x < len; x++)
1684 if (!cr_or_whitespace (string[x]))
1686 strcpy (string, string + x);
1687 break;
1690 len = strlen (string);
1691 if (len)
1692 len--;
1693 while (len > -1 && cr_or_whitespace (string[len]))
1694 len--;
1695 string[len + 1] = 0;
1698 /* Bash STRING, replacing all whitespace with just one space. */
1699 void
1700 fix_whitespace (string)
1701 char *string;
1703 char *temp = (char *)xmalloc (strlen (string) + 1);
1704 int string_index = 0;
1705 int temp_index = 0;
1706 int c;
1708 canon_white (string);
1710 while (string[string_index])
1712 c = temp[temp_index++] = string[string_index++];
1714 if (c == ' ' || c == '\n' || c == '\t')
1716 temp[temp_index - 1] = ' ';
1717 while ((c = string[string_index]) && (c == ' ' ||
1718 c == '\t' ||
1719 c == '\n'))
1720 string_index++;
1723 temp[temp_index] = 0;
1724 strcpy (string, temp);
1725 free (temp);
1728 /* Discard text until the desired string is found. The string is
1729 included in the discarded text. */
1730 void
1731 discard_until (string)
1732 char *string;
1734 int temp = search_forward (string, input_text_offset);
1736 int tt = (temp < 0) ? size_of_input_text : temp + strlen (string);
1737 int from = input_text_offset;
1739 /* Find out what line we are on. */
1740 while (from != tt)
1741 if (input_text[from++] == '\n')
1742 line_number++;
1744 if (temp < 0)
1746 input_text_offset = size_of_input_text - strlen (string);
1748 if (strcmp (string, "\n") != 0)
1750 line_error (_("Expected `%s'"), string);
1751 return;
1754 else
1755 input_text_offset = temp;
1757 input_text_offset += strlen (string);
1760 /* Read characters from the file until we are at MATCH.
1761 Place the characters read into STRING.
1762 On exit input_text_offset is after the match string.
1763 Return the offset where the string starts. */
1765 get_until (match, string)
1766 char *match, **string;
1768 int len, current_point, x, new_point, tem;
1770 current_point = x = input_text_offset;
1771 new_point = search_forward (match, input_text_offset);
1773 if (new_point < 0)
1774 new_point = size_of_input_text;
1775 len = new_point - current_point;
1777 /* Keep track of which line number we are at. */
1778 tem = new_point + (strlen (match) - 1);
1779 while (x != tem)
1780 if (input_text[x++] == '\n')
1781 line_number++;
1783 *string = (char *)xmalloc (len + 1);
1785 memcpy (*string, &input_text[current_point], len);
1786 (*string)[len] = 0;
1788 /* Now leave input_text_offset in a consistent state. */
1789 input_text_offset = tem;
1791 if (input_text_offset > size_of_input_text)
1792 input_text_offset = size_of_input_text;
1794 return (new_point);
1797 /* Read characters from the file until we are at MATCH or end of line.
1798 Place the characters read into STRING. */
1799 void
1800 get_until_in_line (expand, match, string)
1801 int expand;
1802 char *match, **string;
1804 int real_bottom = size_of_input_text;
1805 int limit = search_forward ("\n", input_text_offset);
1806 if (limit < 0)
1807 limit = size_of_input_text;
1809 /* Replace input_text[input_text_offset .. limit-1] with its macro
1810 expansion (actually, we expand all commands). This allows the node
1811 names themselves to be constructed via a macro, as in:
1812 @macro foo{p, q}
1813 Together: \p\ & \q\.
1814 @end macro
1816 @node @foo{A,B}, next, prev, top
1818 Otherwise, the `,' separating the macro args A and B is taken as
1819 the node argument separator, so the node name is `@foo{A'. This
1820 expansion is only necessary on the first call, since we expand the
1821 whole line then.
1823 Furthermore, if we're executing a string, don't do it -- we'll end
1824 up shrinking the execution string which is currently aliased to
1825 `input_text', so it might get moved, and not updated in the
1826 `execution_strings' array. This happens when processing the
1827 (synthetic) Overview-Footnotes node in the Texinfo manual. */
1829 if (expand && !executing_string && !me_executing_string)
1831 char *xp;
1832 unsigned xp_len, new_len;
1834 /* Get original string from input. */
1835 unsigned raw_len = limit - input_text_offset;
1836 char *str = xmalloc (raw_len + 1);
1837 strncpy (str, input_text + input_text_offset, raw_len);
1838 str[raw_len] = 0;
1840 /* Expand it. */
1841 xp = expansion (str, 0);
1842 xp_len = strlen (xp);
1843 free (str);
1845 /* Plunk the expansion into the middle of `input_text' --
1846 which is terminated by a newline, not a null. */
1847 str = xmalloc (real_bottom - limit + 1);
1848 strncpy (str, input_text + limit, real_bottom - limit + 1);
1849 new_len = input_text_offset + xp_len + real_bottom - limit + 1;
1850 input_text = xrealloc (input_text, new_len);
1851 strcpy (input_text + input_text_offset, xp);
1852 strncpy (input_text + input_text_offset + xp_len, str,
1853 real_bottom - limit + 1);
1854 free (str);
1855 free (xp);
1857 limit += xp_len - raw_len;
1858 real_bottom += xp_len - raw_len;
1861 size_of_input_text = limit;
1862 get_until (match, string);
1863 size_of_input_text = real_bottom;
1866 void
1867 get_rest_of_line (string)
1868 char **string;
1870 get_until ("\n", string);
1871 canon_white (*string);
1873 if (curchar () == '\n') /* as opposed to the end of the file... */
1875 line_number++;
1876 input_text_offset++;
1880 /* Backup the input pointer to the previous character, keeping track
1881 of the current line number. */
1882 void
1883 backup_input_pointer ()
1885 if (input_text_offset)
1887 input_text_offset--;
1888 if (curchar () == '\n')
1889 line_number--;
1893 /* Read characters from the file until we are at MATCH or closing brace.
1894 Place the characters read into STRING. */
1895 void
1896 get_until_in_braces (match, string)
1897 char *match, **string;
1899 char *temp;
1900 int i, brace = 0;
1901 int match_len = strlen (match);
1903 for (i = input_text_offset; i < size_of_input_text; i++)
1905 if (input_text[i] == '{')
1906 brace++;
1907 else if (input_text[i] == '}')
1908 brace--;
1909 else if (input_text[i] == '\n')
1910 line_number++;
1912 if (brace < 0 ||
1913 (brace == 0 && strncmp (input_text + i, match, match_len) == 0))
1914 break;
1917 match_len = i - input_text_offset;
1918 temp = (char *)xmalloc (2 + match_len);
1919 strncpy (temp, input_text + input_text_offset, match_len);
1920 temp[match_len] = 0;
1921 input_text_offset = i;
1922 *string = temp;
1925 /* **************************************************************** */
1926 /* */
1927 /* Converting the File */
1928 /* */
1929 /* **************************************************************** */
1931 /* Convert the file named by NAME. The output is saved on the file
1932 named as the argument to the @setfilename command. */
1933 static char *suffixes[] = {
1934 ".texinfo",
1935 ".texi",
1936 ".txinfo",
1938 (char *)NULL
1941 void
1942 initialize_conversion ()
1944 init_tag_table ();
1945 init_indices ();
1946 init_internals ();
1947 init_paragraph ();
1949 /* This is used for splitting the output file and for doing section
1950 headings. It was previously initialized in `init_paragraph', but its
1951 use there loses with the `init_paragraph' calls done by the
1952 multitable code; the tag indices get reset to zero. */
1953 output_position = 0;
1956 /* We read in multiples of 4k, simply because it is a typical pipe size
1957 on unix systems. */
1958 #define READ_BUFFER_GROWTH (4 * 4096)
1960 /* Convert the Texinfo file coming from the open stream STREAM. Assume the
1961 source of the stream is named NAME. */
1962 void
1963 convert_from_stream (stream, name)
1964 FILE *stream;
1965 char *name;
1967 char *buffer = (char *)NULL;
1968 int buffer_offset = 0, buffer_size = 0;
1970 initialize_conversion ();
1972 /* Read until the end of the stream. This isn't strictly correct, since
1973 the texinfo input may end before the stream ends, but it is a quick
1974 working hueristic. */
1975 while (!feof (stream))
1977 int count;
1979 if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size)
1980 buffer = (char *)
1981 xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH));
1983 count = fread (buffer + buffer_offset, 1, READ_BUFFER_GROWTH, stream);
1985 if (count < 0)
1987 perror (name);
1988 exit (FATAL);
1991 buffer_offset += count;
1992 if (count == 0)
1993 break;
1996 /* Set the globals to the new file. */
1997 input_text = buffer;
1998 size_of_input_text = buffer_offset;
1999 input_filename = xstrdup (name);
2000 node_filename = xstrdup (name);
2001 input_text_offset = 0;
2002 line_number = 1;
2004 /* Not strictly necessary. This magic prevents read_token () from doing
2005 extra unnecessary work each time it is called (that is a lot of times).
2006 The SIZE_OF_INPUT_TEXT is one past the actual end of the text. */
2007 input_text[size_of_input_text] = '\n';
2009 convert_from_loaded_file (name);
2012 void
2013 convert_from_file (name)
2014 char *name;
2016 register int i;
2017 char *filename = (char *)xmalloc (strlen (name) + 50);
2019 initialize_conversion ();
2021 /* Try to load the file specified by NAME, concatenated with our
2022 various suffixes. Prefer files like `makeinfo.texi' to
2023 `makeinfo'. */
2024 for (i = 0; suffixes[i]; i++)
2026 strcpy (filename, name);
2027 strcat (filename, suffixes[i]);
2029 if (find_and_load (filename))
2030 break;
2032 if (!suffixes[i][0] && strrchr (filename, '.'))
2034 fs_error (filename);
2035 free (filename);
2036 return;
2040 if (!suffixes[i])
2042 fs_error (name);
2043 free (filename);
2044 return;
2047 input_filename = filename;
2049 convert_from_loaded_file (name);
2052 void
2053 convert_from_loaded_file (name)
2054 char *name;
2056 char *expand_filename (), *filename_part ();
2057 char *real_output_filename = (char *)NULL;
2059 #if defined (HAVE_MACROS)
2060 remember_itext (input_text, 0);
2061 #endif /* HAVE_MACROS */
2063 /* Search this file looking for the special string which starts conversion.
2064 Once found, we may truly begin. */
2065 input_text_offset = 0;
2066 while (input_text_offset >= 0)
2068 input_text_offset =
2069 search_forward (setfilename_search, input_text_offset);
2071 if ((input_text_offset == 0) ||
2072 ((input_text_offset > 0) &&
2073 (input_text[input_text_offset -1] == '\n')))
2074 break;
2075 else if (input_text_offset > 0)
2076 input_text_offset++;
2079 if (input_text_offset < 0)
2081 if (!command_output_filename)
2083 #if defined (REQUIRE_SETFILENAME)
2084 error (_("No `%s' found in `%s'"), setfilename_search, name);
2085 goto finished;
2086 #else
2087 register int i, end_of_first_line;
2089 /* Find the end of the first line in the file. */
2090 for (i = 0; i < size_of_input_text - 1; i++)
2091 if (input_text[i] == '\n')
2092 break;
2094 end_of_first_line = i + 1;
2096 input_text_offset = 0;
2098 for (i = 0; i < end_of_first_line; i++)
2100 if ((input_text[i] == '\\') &&
2101 (strncmp (input_text + i + 1, "include", 7) == 0))
2103 input_text_offset = end_of_first_line;
2104 break;
2107 command_output_filename = output_name_from_input_name (name);
2108 #endif /* !REQUIRE_SETFILENAME */
2111 else
2112 input_text_offset += strlen (setfilename_search);
2114 if (!command_output_filename)
2115 get_until ("\n", &output_filename);
2116 else
2118 if (input_text_offset != -1)
2119 discard_until ("\n");
2120 else
2121 input_text_offset = 0;
2123 real_output_filename = output_filename = command_output_filename;
2124 command_output_filename = (char *)NULL;
2127 canon_white (output_filename);
2129 if (real_output_filename && strcmp (real_output_filename, "-") == 0)
2131 if (macro_expansion_filename
2132 && strcmp (macro_expansion_filename, "-") == 0)
2134 fprintf (stderr, _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
2135 progname);
2136 macro_expansion_output_stream = NULL;
2138 real_output_filename = xstrdup (real_output_filename);
2139 output_stream = stdout;
2140 splitting = 0; /* Cannot split when writing to stdout. */
2142 else
2144 if (!real_output_filename)
2145 real_output_filename = expand_filename (output_filename, name);
2146 else
2147 real_output_filename = xstrdup (real_output_filename);
2149 output_stream = fopen (real_output_filename, "w");
2152 if (output_stream != stdout)
2153 printf (_("Making %s file `%s' from `%s'.\n"),
2154 no_headers ? "text" : "info", output_filename, input_filename);
2156 if (output_stream == NULL)
2158 fs_error (real_output_filename);
2159 goto finished;
2162 /* Make the displayable filename from output_filename. Only the base
2163 portion of the filename need be displayed. */
2164 if (output_stream != stdout)
2165 pretty_output_filename = filename_part (output_filename);
2166 else
2167 pretty_output_filename = xstrdup ("stdout");
2169 /* For this file only, count the number of newlines from the top of
2170 the file to here. This way, we keep track of line numbers for
2171 error reporting. Line_number starts at 1, since the user isn't
2172 zero-based. */
2174 int temp = 0;
2175 line_number = 1;
2176 while (temp != input_text_offset)
2177 if (input_text[temp++] == '\n')
2178 line_number++;
2181 if (!no_headers)
2183 add_word_args (_("This is Info file %s, produced by Makeinfo version %d.%d"),
2184 output_filename, major_version, minor_version);
2185 add_word_args (_(" from the input file %s.\n"), input_filename);
2188 close_paragraph ();
2189 reader_loop ();
2191 finished:
2192 discard_insertions (0);
2193 close_paragraph ();
2194 flush_file_stack ();
2196 #if defined (HAVE_MACROS)
2197 if (macro_expansion_output_stream)
2199 fclose (macro_expansion_output_stream);
2200 if (errors_printed && !force
2201 && strcmp (macro_expansion_filename, "-") != 0
2202 && strcmp (macro_expansion_filename, "/dev/null") != 0)
2204 fprintf (stderr, _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n"),
2205 progname, macro_expansion_filename);
2206 if (unlink (macro_expansion_filename) < 0)
2207 perror (macro_expansion_filename);
2210 #endif /* HAVE_MACROS */
2212 if (output_stream)
2214 output_pending_notes ();
2215 free_pending_notes ();
2216 if (tag_table != NULL)
2218 tag_table = (TAG_ENTRY *) reverse_list (tag_table);
2219 if (!no_headers)
2220 write_tag_table ();
2223 if (output_stream != stdout)
2224 fclose (output_stream);
2226 /* If validating, then validate the entire file right now. */
2227 if (validating)
2228 validate_file (tag_table);
2230 if (splitting && (!errors_printed || force))
2231 split_file (real_output_filename, 0);
2232 else if (errors_printed && !force
2233 && strcmp (real_output_filename, "-") != 0
2234 && strcmp (real_output_filename, "/dev/null") != 0)
2235 { /* If there were errors, and no --force, remove the output. */
2236 fprintf (stderr, _("%s: Removing output file `%s' due to errors; use --force to preserve.\n"),
2237 progname, real_output_filename);
2238 if (unlink (real_output_filename) < 0)
2239 perror (real_output_filename);
2242 free (real_output_filename);
2245 void
2246 free_and_clear (pointer)
2247 char **pointer;
2249 if (*pointer)
2251 free (*pointer);
2252 *pointer = (char *) NULL;
2256 /* Initialize some state. */
2257 void
2258 init_internals ()
2260 free_and_clear (&output_filename);
2261 free_and_clear (&command);
2262 free_and_clear (&input_filename);
2263 free_node_references ();
2264 init_insertion_stack ();
2265 init_brace_stack ();
2266 current_node = NULL; /* sometimes already freed */
2267 command_index = 0;
2268 in_menu = 0;
2269 in_detailmenu = 0;
2270 top_node_seen = 0;
2271 non_top_node_seen = 0;
2274 void
2275 init_paragraph ()
2277 free_and_clear (&output_paragraph);
2278 output_paragraph = (unsigned char *)xmalloc (paragraph_buffer_len);
2279 output_paragraph[0] = 0;
2280 output_paragraph_offset = 0;
2281 output_column = 0;
2282 paragraph_is_open = 0;
2283 current_indent = 0;
2286 /* Okay, we are ready to start the conversion. Call the reader on
2287 some text, and fill the text as it is output. Handle commands by
2288 remembering things like open braces and the current file position on a
2289 stack, and when the corresponding close brace is found, you can call
2290 the function with the proper arguments. */
2291 void
2292 reader_loop ()
2294 int character;
2295 int done = 0;
2296 int dash_count = 0;
2298 while (!done)
2300 if (input_text_offset >= size_of_input_text)
2301 break;
2303 character = curchar ();
2305 if (!in_fixed_width_font &&
2306 (character == '\'' || character == '`') &&
2307 input_text[input_text_offset + 1] == character)
2309 input_text_offset++;
2310 character = '"';
2313 if (character == '-')
2315 dash_count++;
2316 if (dash_count == 2 && !in_fixed_width_font)
2318 input_text_offset++;
2319 continue;
2322 else
2324 dash_count = 0;
2327 /* If this is a whitespace character, then check to see if the line
2328 is blank. If so, advance to the carriage return. */
2329 if (whitespace (character))
2331 register int i = input_text_offset + 1;
2333 while (i < size_of_input_text && whitespace (input_text[i]))
2334 i++;
2336 if (i == size_of_input_text || input_text[i] == '\n')
2338 if (i == size_of_input_text)
2339 i--;
2341 input_text_offset = i;
2342 character = curchar ();
2346 if (character == '\n')
2348 line_number++;
2350 /* Check for a menu entry here, since the "escape sequence"
2351 that begins menu entries is "\n* ". */
2352 if (in_menu && input_text_offset + 1 < size_of_input_text)
2354 char *glean_node_from_menu (), *tem;
2356 /* Note that the value of TEM is discarded, since it is
2357 gauranteed to be NULL when glean_node_from_menu () is
2358 called with a Nonzero argument. */
2359 if (!in_detailmenu)
2360 tem = glean_node_from_menu (1);
2364 switch (character)
2366 case COMMAND_PREFIX:
2367 read_command ();
2368 break;
2370 case '{':
2371 /* Special case. I'm not supposed to see this character by itself.
2372 If I do, it means there is a syntax error in the input text.
2373 Report the error here, but remember this brace on the stack so
2374 you can ignore its partner. */
2376 line_error (_("Misplaced %c"), '{');
2377 remember_brace (misplaced_brace);
2379 /* Don't advance input_text_offset since this happens in
2380 remember_brace ().
2381 input_text_offset++;
2383 break;
2385 case '}':
2386 pop_and_call_brace ();
2387 input_text_offset++;
2388 break;
2390 default:
2391 add_char (character);
2392 input_text_offset++;
2395 #if defined (HAVE_MACROS)
2396 if (macro_expansion_output_stream)
2397 maybe_write_itext (input_text, input_text_offset);
2398 #endif /* HAVE_MACROS */
2401 /* Find the command corresponding to STRING. If the command
2402 is found, return a pointer to the data structure. Otherwise
2403 return (-1). */
2404 COMMAND *
2405 get_command_entry (string)
2406 char *string;
2408 register int i;
2410 for (i = 0; command_table[i].name; i++)
2411 if (strcmp (command_table[i].name, string) == 0)
2412 return (&command_table[i]);
2414 /* This command is not in our predefined command table. Perhaps
2415 it is a user defined command. */
2416 for (i = 0; i < user_command_array_len; i++)
2417 if (user_command_array[i] &&
2418 (strcmp (user_command_array[i]->name, string) == 0))
2419 return (user_command_array[i]);
2421 /* We never heard of this command. */
2422 return ((COMMAND *) -1);
2425 /* input_text_offset is right at the command prefix character.
2426 Read the next token to determine what to do. */
2427 void
2428 read_command ()
2430 COMMAND *entry;
2432 input_text_offset++;
2433 free_and_clear (&command);
2434 command = read_token ();
2436 #if defined (HAVE_MACROS)
2437 /* Check to see if this command is a macro. If so, execute it here. */
2439 MACRO_DEF *def;
2441 def = find_macro (command);
2443 if (def)
2445 /* We disallow recursive use of a macro call. Inhibit the expansion
2446 of this macro during the life of its execution. */
2447 if (!(def->flags & ME_RECURSE))
2448 def->inhibited = 1;
2450 execute_macro (def);
2452 if (!(def->flags & ME_RECURSE))
2453 def->inhibited = 0;
2455 return;
2458 #endif /* HAVE_MACROS */
2460 entry = get_command_entry (command);
2461 if (entry == (COMMAND *)-1)
2463 line_error (_("Unknown command `%s'"), command);
2464 return;
2467 if (entry->argument_in_braces)
2468 remember_brace (entry->proc);
2470 (*(entry->proc)) (START, output_paragraph_offset, 0);
2473 /* Return the string which invokes PROC; a pointer to a function. */
2474 char *
2475 find_proc_name (proc)
2476 COMMAND_FUNCTION *proc;
2478 register int i;
2480 for (i = 0; command_table[i].name; i++)
2481 if (proc == command_table[i].proc)
2482 return command_table[i].name;
2483 return _("NO_NAME!");
2486 void
2487 init_brace_stack ()
2489 brace_stack = (BRACE_ELEMENT *) NULL;
2492 void
2493 remember_brace (proc)
2494 COMMAND_FUNCTION *proc;
2496 if (curchar () != '{')
2497 line_error (_("%c%s expected `{...}'"), COMMAND_PREFIX, command);
2498 else
2499 input_text_offset++;
2500 remember_brace_1 (proc, output_paragraph_offset);
2503 /* Remember the current output position here. Save PROC
2504 along with it so you can call it later. */
2505 void
2506 remember_brace_1 (proc, position)
2507 COMMAND_FUNCTION *proc;
2508 int position;
2510 BRACE_ELEMENT *new = (BRACE_ELEMENT *) xmalloc (sizeof (BRACE_ELEMENT));
2511 new->next = brace_stack;
2512 new->proc = proc;
2513 new->pos = position;
2514 new->line = line_number;
2515 new->in_fixed_width_font = in_fixed_width_font;
2516 brace_stack = new;
2519 /* Pop the top of the brace stack, and call the associated function
2520 with the args END and POS. */
2521 void
2522 pop_and_call_brace ()
2524 BRACE_ELEMENT *temp;
2525 COMMAND_FUNCTION *proc;
2526 int pos;
2528 if (brace_stack == (BRACE_ELEMENT *) NULL)
2530 line_error (_("Unmatched }"));
2531 return;
2534 pos = brace_stack->pos;
2535 proc = brace_stack->proc;
2536 in_fixed_width_font = brace_stack->in_fixed_width_font;
2537 temp = brace_stack->next;
2538 free (brace_stack);
2539 brace_stack = temp;
2541 (*proc) (END, pos, output_paragraph_offset);
2544 /* Shift all of the markers in `brace_stack' by AMOUNT. */
2545 void
2546 adjust_braces_following (here, amount)
2547 int here, amount;
2549 register BRACE_ELEMENT *stack = brace_stack;
2551 while (stack)
2553 if (stack->pos >= here)
2554 stack->pos += amount;
2555 stack = stack->next;
2559 /* You call discard_braces () when you shouldn't have any braces on the stack.
2560 I used to think that this happens for commands that don't take arguments
2561 in braces, but that was wrong because of things like @code{foo @@}. So now
2562 I only detect it at the beginning of nodes. */
2563 void
2564 discard_braces ()
2566 if (!brace_stack)
2567 return;
2569 while (brace_stack)
2571 if (brace_stack->proc != misplaced_brace)
2573 char *proc_name;
2574 int temp_line_number = line_number;
2576 line_number = brace_stack->line;
2577 proc_name = find_proc_name (brace_stack->proc);
2578 line_error (_("%c%s missing close brace"), COMMAND_PREFIX, proc_name);
2579 line_number = temp_line_number;
2580 pop_and_call_brace ();
2582 else
2584 BRACE_ELEMENT *temp;
2585 temp = brace_stack->next;
2586 free (brace_stack);
2587 brace_stack = temp;
2593 get_char_len (character)
2594 int character;
2596 /* Return the printed length of the character. */
2597 int len;
2599 switch (character)
2601 case '\t':
2602 len = (output_column + 8) & 0xf7;
2603 if (len > fill_column)
2604 len = fill_column - output_column;
2605 else
2606 len = len - output_column;
2607 break;
2609 case '\n':
2610 len = fill_column - output_column;
2611 break;
2613 default:
2614 /* ASCII control characters appear as two characters in the output
2615 (e.g., ^A). But characters with the high bit set are just one
2616 on suitable terminals, so don't count them as two for line
2617 breaking purposes. */
2618 if (0 <= character && character < ' ')
2619 len = 2;
2620 else
2621 len = 1;
2623 return (len);
2626 void
2627 #if defined (VA_FPRINTF) && __STDC__
2628 add_word_args (char *format, ...)
2629 #else
2630 add_word_args (format, va_alist)
2631 char *format;
2632 va_dcl
2633 #endif
2635 char buffer[1000];
2636 #ifdef VA_FPRINTF
2637 va_list ap;
2638 #endif
2640 VA_START (ap, format);
2641 #ifdef VA_SPRINTF
2642 VA_SPRINTF (buffer, format, ap);
2643 #else
2644 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2645 #endif /* not VA_SPRINTF */
2646 va_end (ap);
2647 add_word (buffer);
2650 /* Add STRING to output_paragraph. */
2651 void
2652 add_word (string)
2653 char *string;
2655 while (*string)
2656 add_char (*string++);
2659 /* Nonzero if the last character inserted has the syntax class of NEWLINE. */
2660 int last_char_was_newline = 1;
2662 /* The actual last inserted character. Note that this may be something
2663 other than NEWLINE even if last_char_was_newline is 1. */
2664 int last_inserted_character = 0;
2666 /* Nonzero means that a newline character has already been
2667 inserted, so close_paragraph () should insert one less. */
2668 int line_already_broken = 0;
2670 /* When nonzero we have finished an insertion (see `end_insertion') and we
2671 want to ignore false continued paragraph closings. */
2672 int insertion_paragraph_closed = 0;
2674 /* Nonzero means attempt to make all of the lines have fill_column width. */
2675 int do_justification = 0;
2677 /* Add the character to the current paragraph. If filling_enabled is
2678 nonzero, then do filling as well. */
2679 void
2680 add_char (character)
2681 int character;
2683 /* If we are avoiding outputting headers, and we are currently
2684 in a menu, then simply return. */
2685 if (no_headers && (in_menu || in_detailmenu))
2686 return;
2688 /* If we are adding a character now, then we don't have to
2689 ignore close_paragraph () calls any more. */
2690 if (must_start_paragraph && character != '\n')
2692 must_start_paragraph = 0;
2693 line_already_broken = 0; /* The line is no longer broken. */
2694 if (current_indent > output_column)
2696 indent (current_indent - output_column);
2697 output_column = current_indent;
2701 if (non_splitting_words && member (character, " \t\n"))
2702 character = ' ' | 0x80;
2704 insertion_paragraph_closed = 0;
2706 switch (character)
2708 case '\n':
2709 if (!filling_enabled)
2711 insert ('\n');
2713 if (force_flush_right)
2715 close_paragraph ();
2716 /* Hack to force single blank lines out in this mode. */
2717 flush_output ();
2720 output_column = 0;
2722 if (!no_indent && paragraph_is_open)
2723 indent (output_column = current_indent);
2724 break;
2726 else /* CHARACTER is newline, and filling is enabled. */
2728 if (end_of_sentence_p ())
2730 insert (' ');
2731 output_column++;
2732 last_inserted_character = character;
2736 if (last_char_was_newline)
2738 close_paragraph ();
2739 pending_indent = 0;
2741 else
2743 last_char_was_newline = 1;
2744 insert (' ');
2745 output_column++;
2747 break;
2749 default:
2751 int len = get_char_len (character);
2752 int suppress_insert = 0;
2754 if ((character == ' ') && (last_char_was_newline))
2756 if (!paragraph_is_open)
2758 pending_indent++;
2759 return;
2763 if (!paragraph_is_open)
2765 start_paragraph ();
2767 /* If the paragraph is supposed to be indented a certain way,
2768 then discard all of the pending whitespace. Otherwise, we
2769 let the whitespace stay. */
2770 if (!paragraph_start_indent)
2771 indent (pending_indent);
2772 pending_indent = 0;
2775 if ((output_column += len) > fill_column)
2777 if (filling_enabled)
2779 int temp = output_paragraph_offset;
2780 while (--temp > 0 && output_paragraph[temp] != '\n')
2782 /* If we have found a space, we have the place to break
2783 the line. */
2784 if (output_paragraph[temp] == ' ')
2786 /* Remove trailing whitespace from output. */
2787 while (temp && whitespace (output_paragraph[temp - 1]))
2788 temp--;
2790 output_paragraph[temp++] = '\n';
2792 /* We have correctly broken the line where we want
2793 to. What we don't want is spaces following where
2794 we have decided to break the line. We get rid of
2795 them. */
2797 int t1 = temp;
2799 for (;; t1++)
2801 if (t1 == output_paragraph_offset)
2803 if (whitespace (character))
2804 suppress_insert = 1;
2805 break;
2807 if (!whitespace (output_paragraph[t1]))
2808 break;
2811 if (t1 != temp)
2813 adjust_braces_following (temp, (- (t1 - temp)));
2814 strncpy ((char *) &output_paragraph[temp],
2815 (char *) &output_paragraph[t1],
2816 (output_paragraph_offset - t1));
2817 output_paragraph_offset -= (t1 - temp);
2821 /* Filled, but now indent if that is right. */
2822 if (indented_fill && current_indent)
2824 int buffer_len = ((output_paragraph_offset - temp)
2825 + current_indent);
2826 char *temp_buffer = (char *)xmalloc (buffer_len);
2827 int indentation = 0;
2829 /* We have to shift any markers that are in
2830 front of the wrap point. */
2831 adjust_braces_following (temp, current_indent);
2833 while (current_indent > 0 &&
2834 indentation != current_indent)
2835 temp_buffer[indentation++] = ' ';
2837 strncpy ((char *) &temp_buffer[current_indent],
2838 (char *) &output_paragraph[temp],
2839 buffer_len - current_indent);
2841 if (output_paragraph_offset + buffer_len
2842 >= paragraph_buffer_len)
2844 unsigned char *tt = xrealloc
2845 (output_paragraph,
2846 (paragraph_buffer_len += buffer_len));
2847 output_paragraph = tt;
2849 strncpy ((char *) &output_paragraph[temp],
2850 temp_buffer, buffer_len);
2851 output_paragraph_offset += current_indent;
2852 free (temp_buffer);
2854 output_column = 0;
2855 while (temp < output_paragraph_offset)
2856 output_column +=
2857 get_char_len (output_paragraph[temp++]);
2858 output_column += len;
2859 break;
2865 if (!suppress_insert)
2867 insert (character);
2868 last_inserted_character = character;
2870 last_char_was_newline = 0;
2871 line_already_broken = 0;
2876 /* Insert CHARACTER into `output_paragraph'. */
2877 void
2878 insert (character)
2879 int character;
2881 output_paragraph[output_paragraph_offset++] = character;
2882 if (output_paragraph_offset == paragraph_buffer_len)
2884 output_paragraph =
2885 xrealloc (output_paragraph, (paragraph_buffer_len += 100));
2889 /* Insert the null-terminated string STRING into `output_paragraph'. */
2890 void
2891 insert_string (string)
2892 char *string;
2894 while (*string)
2895 insert (*string++);
2899 /* Sentences might have these characters after the period (or whatever). */
2900 #define post_sentence(c) ((c) == ')' || (c) == '\'' || (c) == '"' \
2901 || (c) == ']')
2903 /* Return true if at an end-of-sentence character, possibly followed by
2904 post-sentence punctuation to ignore. */
2905 static int
2906 end_of_sentence_p ()
2908 int loc = output_paragraph_offset - 1;
2909 while (loc > 0 && post_sentence (output_paragraph[loc]))
2910 loc--;
2911 return sentence_ender (output_paragraph[loc]);
2915 /* Remove up to COUNT characters of whitespace from the
2916 current output line. If COUNT is less than zero,
2917 then remove until none left. */
2918 void
2919 kill_self_indent (count)
2920 int count;
2922 /* Handle infinite case first. */
2923 if (count < 0)
2925 output_column = 0;
2926 while (output_paragraph_offset)
2928 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2929 output_paragraph_offset--;
2930 else
2931 break;
2934 else
2936 while (output_paragraph_offset && count--)
2937 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2938 output_paragraph_offset--;
2939 else
2940 break;
2944 /* Nonzero means do not honor calls to flush_output (). */
2945 static int flushing_ignored = 0;
2947 /* Prevent calls to flush_output () from having any effect. */
2948 void
2949 inhibit_output_flushing ()
2951 flushing_ignored++;
2954 /* Allow calls to flush_output () to write the paragraph data. */
2955 void
2956 uninhibit_output_flushing ()
2958 flushing_ignored--;
2961 void
2962 flush_output ()
2964 register int i;
2966 if (!output_paragraph_offset || flushing_ignored)
2967 return;
2969 for (i = 0; i < output_paragraph_offset; i++)
2971 /* If we turned on the 8th bit for a space
2972 inside @w, turn it back off for output. */
2973 if (output_paragraph[i] & meta_character_bit)
2975 int temp = UNMETA (output_paragraph[i]);
2976 if (temp == ' ')
2977 output_paragraph[i] &= 0x7f;
2981 fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
2983 output_position += output_paragraph_offset;
2984 output_paragraph_offset = 0;
2987 /* How to close a paragraph controlling the number of lines between
2988 this one and the last one. */
2990 /* Paragraph spacing is controlled by this variable. It is the number of
2991 blank lines that you wish to appear between paragraphs. A value of
2992 1 creates a single blank line between paragraphs. */
2993 int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING;
2995 /* Close the current paragraph, leaving no blank lines between them. */
2996 void
2997 close_single_paragraph ()
2999 close_paragraph_with_lines (0);
3002 /* Close a paragraph after an insertion has ended. */
3003 void
3004 close_insertion_paragraph ()
3006 if (!insertion_paragraph_closed)
3008 /* Close the current paragraph, breaking the line. */
3009 close_single_paragraph ();
3011 /* Start a new paragraph, with the correct indentation for the now
3012 current insertion level (one above the one that we are ending). */
3013 start_paragraph ();
3015 /* Tell `close_paragraph' that the previous line has already been
3016 broken, so it should insert one less newline. */
3017 line_already_broken = 1;
3019 /* Tell functions such as `add_char' we've already found a newline. */
3020 ignore_blank_line ();
3022 else
3024 /* If the insertion paragraph is closed already, then we are seeing
3025 two `@end' commands in a row. Note that the first one we saw was
3026 handled in the first part of this if-then-else clause, and at that
3027 time `start_paragraph' was called, partially to handle the proper
3028 indentation of the current line. However, the indentation level
3029 may have just changed again, so we may have to outdent the current
3030 line to the new indentation level. */
3031 if (current_indent < output_column)
3032 kill_self_indent (output_column - current_indent);
3035 insertion_paragraph_closed = 1;
3038 void
3039 close_paragraph_with_lines (lines)
3040 int lines;
3042 int old_spacing = paragraph_spacing;
3043 paragraph_spacing = lines;
3044 close_paragraph ();
3045 paragraph_spacing = old_spacing;
3048 /* Close the currently open paragraph. */
3049 void
3050 close_paragraph ()
3052 register int i;
3054 /* The insertion paragraph is no longer closed. */
3055 insertion_paragraph_closed = 0;
3057 if (paragraph_is_open && !must_start_paragraph)
3059 register int tindex, c;
3061 tindex = output_paragraph_offset;
3063 /* Back up to last non-newline/space character, forcing all such
3064 subsequent characters to be newlines. This isn't strictly
3065 necessary, but a couple of functions use the presence of a newline
3066 to make decisions. */
3067 for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex)
3069 c = output_paragraph[tindex];
3071 if (c == ' '|| c == '\n')
3072 output_paragraph[tindex] = '\n';
3073 else
3074 break;
3077 /* All trailing whitespace is ignored. */
3078 output_paragraph_offset = ++tindex;
3080 /* Break the line if that is appropriate. */
3081 if (paragraph_spacing >= 0)
3082 insert ('\n');
3084 /* Add as many blank lines as is specified in `paragraph_spacing'. */
3085 if (!force_flush_right)
3087 for (i = 0; i < (paragraph_spacing - line_already_broken); i++)
3088 insert ('\n');
3091 /* If we are doing flush right indentation, then do it now
3092 on the paragraph (really a single line). */
3093 if (force_flush_right)
3094 do_flush_right_indentation ();
3096 flush_output ();
3097 paragraph_is_open = 0;
3098 no_indent = 0;
3099 output_column = 0;
3101 ignore_blank_line ();
3104 /* Make the last line just read look as if it were only a newline. */
3105 void
3106 ignore_blank_line ()
3108 last_inserted_character = '\n';
3109 last_char_was_newline = 1;
3112 /* Align the end of the text in output_paragraph with fill_column. */
3113 void
3114 do_flush_right_indentation ()
3116 char *temp;
3117 int temp_len;
3119 kill_self_indent (-1);
3121 if (output_paragraph[0] != '\n')
3123 output_paragraph[output_paragraph_offset] = 0;
3125 if (output_paragraph_offset < fill_column)
3127 register int i;
3129 if (fill_column >= paragraph_buffer_len)
3130 output_paragraph =
3131 xrealloc (output_paragraph,
3132 (paragraph_buffer_len += fill_column));
3134 temp_len = strlen ((char *)output_paragraph);
3135 temp = (char *)xmalloc (temp_len + 1);
3136 memcpy (temp, (char *)output_paragraph, temp_len);
3138 for (i = 0; i < fill_column - output_paragraph_offset; i++)
3139 output_paragraph[i] = ' ';
3141 memcpy ((char *)output_paragraph + i, temp, temp_len);
3142 free (temp);
3143 output_paragraph_offset = fill_column;
3148 /* Begin a new paragraph. */
3149 void
3150 start_paragraph ()
3152 /* First close existing one. */
3153 if (paragraph_is_open)
3154 close_paragraph ();
3156 /* In either case, the insertion paragraph is no longer closed. */
3157 insertion_paragraph_closed = 0;
3159 /* However, the paragraph is open! */
3160 paragraph_is_open = 1;
3162 /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph ()
3163 had to be called before we would allow any other paragraph operations
3164 to have an effect. */
3165 if (!must_start_paragraph)
3167 int amount_to_indent = 0;
3169 /* If doing indentation, then insert the appropriate amount. */
3170 if (!no_indent)
3172 if (inhibit_paragraph_indentation)
3174 amount_to_indent = current_indent;
3175 if (inhibit_paragraph_indentation < 0)
3176 inhibit_paragraph_indentation++;
3178 else if (paragraph_start_indent < 0)
3179 amount_to_indent = current_indent;
3180 else
3181 amount_to_indent = current_indent + paragraph_start_indent;
3183 if (amount_to_indent >= output_column)
3185 amount_to_indent -= output_column;
3186 indent (amount_to_indent);
3187 output_column += amount_to_indent;
3191 else
3192 must_start_paragraph = 0;
3195 /* Insert the indentation specified by AMOUNT. */
3196 void
3197 indent (amount)
3198 int amount;
3200 register BRACE_ELEMENT *elt = brace_stack;
3202 /* For every START_POS saved within the brace stack which will be affected
3203 by this indentation, bump that start pos forward. */
3204 while (elt)
3206 if (elt->pos >= output_paragraph_offset)
3207 elt->pos += amount;
3208 elt = elt->next;
3211 while (--amount >= 0)
3212 insert (' ');
3215 /* Search forward for STRING in input_text.
3216 FROM says where to start. */
3218 search_forward (string, from)
3219 char *string;
3220 int from;
3222 int len = strlen (string);
3224 while (from < size_of_input_text)
3226 if (strncmp (input_text + from, string, len) == 0)
3227 return (from);
3228 from++;
3230 return (-1);
3233 /* Whoops, Unix doesn't have strcasecmp. */
3235 /* Case independent string compare. */
3236 #if !defined (HAVE_STRCASECMP)
3238 strcasecmp (string1, string2)
3239 char *string1, *string2;
3241 char ch1, ch2;
3243 for (;;)
3245 ch1 = *string1++;
3246 ch2 = *string2++;
3248 if (!(ch1 | ch2))
3249 return (0);
3251 ch1 = coerce_to_upper (ch1);
3252 ch2 = coerce_to_upper (ch2);
3254 if (ch1 != ch2)
3255 return (ch1 - ch2);
3258 #endif /* !HAVE_STRCASECMP */
3260 void
3261 init_insertion_stack ()
3263 insertion_stack = (INSERTION_ELT *) NULL;
3266 /* Return the type of the current insertion. */
3267 enum insertion_type
3268 current_insertion_type ()
3270 if (!insertion_level)
3271 return (bad_type);
3272 else
3273 return (insertion_stack->insertion);
3276 /* Return a pointer to the string which is the function to wrap around
3277 items. */
3278 char *
3279 current_item_function ()
3281 register int level, done;
3282 register INSERTION_ELT *elt;
3284 level = insertion_level;
3285 elt = insertion_stack;
3286 done = 0;
3288 /* Skip down through the stack until we find a non-conditional insertion. */
3289 while (!done && (elt != NULL))
3291 switch (elt->insertion)
3293 case ifinfo:
3294 case ifnothtml:
3295 case ifnottex:
3296 case ifset:
3297 case ifclear:
3298 case cartouche:
3299 elt = elt->next;
3300 level--;
3301 break;
3303 default:
3304 done = 1;
3308 if (!level)
3309 return ((char *) NULL);
3310 else
3311 return (elt->item_function);
3314 char *
3315 get_item_function ()
3317 char *item_function;
3318 get_rest_of_line (&item_function);
3319 backup_input_pointer ();
3320 return (item_function);
3323 /* Push the state of the current insertion on the stack. */
3324 void
3325 push_insertion (type, item_function)
3326 enum insertion_type type;
3327 char *item_function;
3329 INSERTION_ELT *new = (INSERTION_ELT *) xmalloc (sizeof (INSERTION_ELT));
3331 new->item_function = item_function;
3332 new->filling_enabled = filling_enabled;
3333 new->indented_fill = indented_fill;
3334 new->insertion = type;
3335 new->line_number = line_number;
3336 new->filename = xstrdup (input_filename);
3337 new->inhibited = inhibit_paragraph_indentation;
3338 new->in_fixed_width_font = in_fixed_width_font;
3339 new->next = insertion_stack;
3340 insertion_stack = new;
3341 insertion_level++;
3344 /* Pop the value on top of the insertion stack into the
3345 global variables. */
3346 void
3347 pop_insertion ()
3349 INSERTION_ELT *temp = insertion_stack;
3351 if (temp == (INSERTION_ELT *) NULL)
3352 return;
3354 in_fixed_width_font = temp->in_fixed_width_font;
3355 inhibit_paragraph_indentation = temp->inhibited;
3356 filling_enabled = temp->filling_enabled;
3357 indented_fill = temp->indented_fill;
3358 free_and_clear (&(temp->item_function));
3359 free_and_clear (&(temp->filename));
3360 insertion_stack = insertion_stack->next;
3361 free (temp);
3362 insertion_level--;
3365 /* Return a pointer to the print name of this
3366 enumerated type. */
3367 char *
3368 insertion_type_pname (type)
3369 enum insertion_type type;
3371 if ((int) type < (int) bad_type)
3372 return (insertion_type_names[(int) type]);
3373 else
3374 return (_("Broken-Type in insertion_type_pname"));
3377 /* Return the insertion_type associated with NAME.
3378 If the type is not one of the known ones, return BAD_TYPE. */
3379 enum insertion_type
3380 find_type_from_name (name)
3381 char *name;
3383 int index = 0;
3384 while (index < (int) bad_type)
3386 if (strcmp (name, insertion_type_names[index]) == 0)
3387 return (enum insertion_type) index;
3388 index++;
3390 return (bad_type);
3394 defun_insertion (type)
3395 enum insertion_type type;
3397 return
3398 ((type == deffn)
3399 || (type == defun)
3400 || (type == defmac)
3401 || (type == defspec)
3402 || (type == defvr)
3403 || (type == defvar)
3404 || (type == defopt)
3405 || (type == deftypefn)
3406 || (type == deftypefun)
3407 || (type == deftypevr)
3408 || (type == deftypevar)
3409 || (type == defcv)
3410 || (type == defivar)
3411 || (type == defop)
3412 || (type == defmethod)
3413 || (type == deftypemethod)
3414 || (type == deftp));
3417 /* MAX_NS is the maximum nesting level for enumerations. I picked 100
3418 which seemed reasonable. This doesn't control the number of items,
3419 just the number of nested lists. */
3420 #define max_stack_depth 100
3421 #define ENUM_DIGITS 1
3422 #define ENUM_ALPHA 2
3423 typedef struct {
3424 int enumtype;
3425 int enumval;
3426 } DIGIT_ALPHA;
3428 DIGIT_ALPHA enumstack[max_stack_depth];
3429 int enumstack_offset = 0;
3430 int current_enumval = 1;
3431 int current_enumtype = ENUM_DIGITS;
3432 char *enumeration_arg = (char *)NULL;
3434 void
3435 start_enumerating (at, type)
3436 int at, type;
3438 if ((enumstack_offset + 1) == max_stack_depth)
3440 line_error (_("Enumeration stack overflow"));
3441 return;
3443 enumstack[enumstack_offset].enumtype = current_enumtype;
3444 enumstack[enumstack_offset].enumval = current_enumval;
3445 enumstack_offset++;
3446 current_enumval = at;
3447 current_enumtype = type;
3450 void
3451 stop_enumerating ()
3453 --enumstack_offset;
3454 if (enumstack_offset < 0)
3455 enumstack_offset = 0;
3457 current_enumval = enumstack[enumstack_offset].enumval;
3458 current_enumtype = enumstack[enumstack_offset].enumtype;
3461 /* Place a letter or digits into the output stream. */
3462 void
3463 enumerate_item ()
3465 char temp[10];
3467 if (current_enumtype == ENUM_ALPHA)
3469 if (current_enumval == ('z' + 1) || current_enumval == ('Z' + 1))
3471 current_enumval = ((current_enumval - 1) == 'z' ? 'a' : 'A');
3472 warning (_("lettering overflow, restarting at %c"), current_enumval);
3474 sprintf (temp, "%c. ", current_enumval);
3476 else
3477 sprintf (temp, "%d. ", current_enumval);
3479 indent (output_column += (current_indent - strlen (temp)));
3480 add_word (temp);
3481 current_enumval++;
3484 /* This is where the work for all the "insertion" style
3485 commands is done. A huge switch statement handles the
3486 various setups, and generic code is on both sides. */
3487 void
3488 begin_insertion (type)
3489 enum insertion_type type;
3491 int no_discard = 0;
3493 if (defun_insertion (type))
3495 push_insertion (type, xstrdup (""));
3496 no_discard++;
3498 else
3499 push_insertion (type, get_item_function ());
3501 switch (type)
3503 case menu:
3504 if (!no_headers)
3505 close_paragraph ();
3507 filling_enabled = no_indent = 0;
3508 inhibit_paragraph_indentation = 1;
3510 if (!no_headers)
3511 add_word (_("* Menu:\n"));
3513 in_menu++;
3514 no_discard++;
3515 break;
3517 case detailmenu:
3518 if (!in_menu)
3520 if (!no_headers)
3521 close_paragraph ();
3523 filling_enabled = no_indent = 0;
3524 inhibit_paragraph_indentation = 1;
3526 no_discard++;
3529 in_detailmenu++;
3530 break;
3532 case direntry:
3533 close_single_paragraph ();
3534 filling_enabled = no_indent = 0;
3535 inhibit_paragraph_indentation = 1;
3536 insert_string ("START-INFO-DIR-ENTRY\n");
3537 break;
3539 /* I think @quotation is meant to do filling.
3540 If you don't want filling, then use @display. */
3541 case quotation:
3542 close_single_paragraph ();
3543 last_char_was_newline = no_indent = 0;
3544 indented_fill = filling_enabled = 1;
3545 inhibit_paragraph_indentation = 1;
3546 current_indent += default_indentation_increment;
3547 break;
3549 case display:
3550 case example:
3551 case smallexample:
3552 case lisp:
3553 case smalllisp:
3554 /* Just like @example, but no indentation. */
3555 case format:
3556 close_single_paragraph ();
3557 inhibit_paragraph_indentation = 1;
3558 in_fixed_width_font++;
3559 filling_enabled = 0;
3560 last_char_was_newline = 0;
3561 if (type != format)
3562 current_indent += default_indentation_increment;
3563 break;
3565 case multitable:
3566 do_multitable ();
3567 break;
3569 case table:
3570 case ftable:
3571 case vtable:
3572 case itemize:
3573 close_single_paragraph ();
3574 current_indent += default_indentation_increment;
3575 filling_enabled = indented_fill = 1;
3576 #if defined (INDENT_PARAGRAPHS_IN_TABLE)
3577 inhibit_paragraph_indentation = 0;
3578 #else
3579 inhibit_paragraph_indentation = 1;
3580 #endif /* !INDENT_PARAGRAPHS_IN_TABLE */
3582 /* Make things work for losers who forget the itemize syntax. */
3583 if (allow_lax_format && (type == itemize))
3585 if (!(*insertion_stack->item_function))
3587 free (insertion_stack->item_function);
3588 insertion_stack->item_function = xstrdup ("@bullet");
3589 insertion_stack->item_function[0] = COMMAND_PREFIX;
3593 if (!*insertion_stack->item_function)
3595 line_error (_("%s requires an argument: the formatter for %citem"),
3596 insertion_type_pname (type), COMMAND_PREFIX);
3598 break;
3600 case enumerate:
3601 close_single_paragraph ();
3602 no_indent = 0;
3603 #if defined (INDENT_PARAGRAPHS_IN_TABLE)
3604 inhibit_paragraph_indentation = 0;
3605 #else
3606 inhibit_paragraph_indentation = 1;
3607 #endif /* !INDENT_PARAGRAPHS_IN_TABLE */
3609 current_indent += default_indentation_increment;
3610 filling_enabled = indented_fill = 1;
3612 if (isdigit (*enumeration_arg))
3613 start_enumerating (atoi (enumeration_arg), ENUM_DIGITS);
3614 else
3615 start_enumerating (*enumeration_arg, ENUM_ALPHA);
3616 break;
3618 /* Does nothing special in makeinfo. */
3619 case group:
3620 /* Only close the paragraph if we are not inside of an @example. */
3621 if (!insertion_stack->next ||
3622 insertion_stack->next->insertion != example)
3623 close_single_paragraph ();
3624 break;
3626 /* Insertions that are no-ops in info, but do something in TeX. */
3627 case ifinfo:
3628 case ifnothtml:
3629 case ifnottex:
3630 case ifset:
3631 case ifclear:
3632 case cartouche:
3633 if (in_menu)
3634 no_discard++;
3635 break;
3637 case deffn:
3638 case defun:
3639 case defmac:
3640 case defspec:
3641 case defvr:
3642 case defvar:
3643 case defopt:
3644 case deftypefn:
3645 case deftypefun:
3646 case deftypevr:
3647 case deftypevar:
3648 case defcv:
3649 case defivar:
3650 case defop:
3651 case defmethod:
3652 case deftypemethod:
3653 case deftp:
3654 inhibit_paragraph_indentation = 1;
3655 filling_enabled = indented_fill = 1;
3656 current_indent += default_indentation_increment;
3657 no_indent = 0;
3658 break;
3660 case flushleft:
3661 close_single_paragraph ();
3662 inhibit_paragraph_indentation = 1;
3663 filling_enabled = indented_fill = no_indent = 0;
3664 break;
3666 case flushright:
3667 close_single_paragraph ();
3668 filling_enabled = indented_fill = no_indent = 0;
3669 inhibit_paragraph_indentation = 1;
3670 force_flush_right++;
3671 break;
3674 if (!no_discard)
3675 discard_until ("\n");
3678 /* Try to end the insertion with the specified TYPE. With a value of
3679 `bad_type', TYPE gets translated to match the value currently on top
3680 of the stack. Otherwise, if TYPE doesn't match the top of the
3681 insertion stack, give error. */
3682 void
3683 end_insertion (type)
3684 enum insertion_type type;
3686 enum insertion_type temp_type;
3688 if (!insertion_level)
3689 return;
3691 temp_type = current_insertion_type ();
3693 if (type == bad_type)
3694 type = temp_type;
3696 if (type != temp_type)
3698 line_error
3699 (_("`%cend' expected `%s', but saw `%s'"), COMMAND_PREFIX,
3700 insertion_type_pname (temp_type), insertion_type_pname (type));
3701 return;
3704 pop_insertion ();
3706 switch (type)
3708 /* Insertions which have no effect on paragraph formatting. */
3709 case ifnothtml:
3710 case ifnottex:
3711 case ifinfo:
3712 case ifset:
3713 case ifclear:
3714 break;
3716 case direntry:
3717 insert_string ("END-INFO-DIR-ENTRY\n\n");
3718 close_insertion_paragraph ();
3719 break;
3721 case detailmenu:
3722 in_detailmenu--; /* No longer hacking menus. */
3723 if (!in_menu)
3725 if (!no_headers)
3726 close_insertion_paragraph ();
3728 break;
3730 case menu:
3731 in_menu--; /* No longer hacking menus. */
3732 if (!no_headers)
3733 close_insertion_paragraph ();
3734 break;
3736 case multitable:
3737 end_multitable ();
3738 break;
3740 case enumerate:
3741 stop_enumerating ();
3742 close_insertion_paragraph ();
3743 current_indent -= default_indentation_increment;
3744 break;
3746 case flushleft:
3747 case group:
3748 case cartouche:
3749 close_insertion_paragraph ();
3750 break;
3752 case format:
3753 case display:
3754 case example:
3755 case smallexample:
3756 case lisp:
3757 case smalllisp:
3758 case quotation:
3759 /* @format is the only fixed_width insertion without a change
3760 in indentation. */
3761 if (type != format)
3762 current_indent -= default_indentation_increment;
3764 /* The ending of one of these insertions always marks the
3765 start of a new paragraph. */
3766 close_insertion_paragraph ();
3767 break;
3769 case table:
3770 case ftable:
3771 case vtable:
3772 case itemize:
3773 current_indent -= default_indentation_increment;
3774 break;
3776 case flushright:
3777 force_flush_right--;
3778 close_insertion_paragraph ();
3779 break;
3781 /* Handle the @defun style insertions with a default clause. */
3782 default:
3783 current_indent -= default_indentation_increment;
3784 close_insertion_paragraph ();
3785 break;
3789 /* Insertions cannot cross certain boundaries, such as node beginnings. In
3790 code that creates such boundaries, you should call `discard_insertions'
3791 before doing anything else. It prints the errors for you, and cleans up
3792 the insertion stack. With nonzero SPECIALS_OK, allows unmatched
3793 ifinfo, ifset, ifclear, otherwise not. */
3794 void
3795 discard_insertions (specials_ok)
3796 int specials_ok;
3798 int real_line_number = line_number;
3799 while (insertion_stack)
3801 if (specials_ok && (insertion_stack->insertion == ifinfo
3802 || insertion_stack->insertion == ifset
3803 || insertion_stack->insertion == ifclear))
3804 break;
3805 else
3807 char *offender = insertion_type_pname (insertion_stack->insertion);
3808 char *current_filename = input_filename;
3810 input_filename = insertion_stack->filename;
3811 line_number = insertion_stack->line_number;
3812 line_error (_("No matching `%cend %s'"), COMMAND_PREFIX, offender);
3813 input_filename = current_filename;
3814 pop_insertion ();
3817 line_number = real_line_number;
3820 /* The Texinfo commands. */
3822 /* Commands which insert their own names. */
3823 void
3824 insert_self (arg)
3825 int arg;
3827 if (arg == START)
3828 add_word (command);
3831 void
3832 insert_space (arg)
3833 int arg;
3835 if (arg == START)
3836 add_char (' ');
3839 /* Force a line break in the output. */
3840 void
3841 cm_asterisk ()
3843 close_single_paragraph ();
3844 cm_noindent ();
3847 /* Insert ellipsis. */
3848 void
3849 cm_dots (arg)
3850 int arg;
3852 if (arg == START)
3853 add_word ("...");
3856 /* Insert ellipsis for sentence end. */
3857 void
3858 cm_enddots (arg)
3859 int arg;
3861 if (arg == START)
3862 add_word ("....");
3865 void
3866 cm_bullet (arg)
3867 int arg;
3869 if (arg == START)
3870 add_char ('*');
3873 void
3874 cm_minus (arg)
3875 int arg;
3877 if (arg == START)
3878 add_char ('-');
3881 /* Insert "TeX". */
3882 void
3883 cm_TeX (arg)
3884 int arg;
3886 if (arg == START)
3887 add_word ("TeX");
3890 /* Copyright symbol. */
3891 void
3892 cm_copyright (arg)
3893 int arg;
3895 if (arg == START)
3896 add_word ("(C)");
3899 /* Accent commands that take explicit arguments. */
3900 void
3901 cm_accent (arg)
3902 int arg;
3904 if (arg == START)
3906 if (strcmp (command, "dotaccent") == 0) /* overdot */
3907 add_char ('.');
3908 else if (strcmp (command, "H") == 0) /* Hungarian umlaut */
3909 add_word ("''");
3910 else if (strcmp (command, "ringaccent") == 0)
3911 add_char ('*');
3912 else if (strcmp (command, "tieaccent") == 0)
3913 add_char ('[');
3914 else if (strcmp (command, "u") == 0) /* breve */
3915 add_char ('(');
3916 else if (strcmp (command, "v") == 0) /* hacek/check */
3917 add_char ('<');
3919 else if (arg == END)
3921 if (strcmp (command, "ubaraccent") == 0) /* underbar */
3922 add_char ('_');
3923 else if (strcmp (command, "udotaccent") == 0) /* underdot */
3924 add_word ("-.");
3925 else if (strcmp (command, ",") == 0) /* cedilla */
3926 add_word (",");
3930 /* Non-English letters/characters that don't insert themselves. */
3931 void
3932 cm_special_char (arg)
3934 if (arg == START)
3936 if ((*command == 'L' || *command == 'l'
3937 || *command == 'O' || *command == 'o')
3938 && command[1] == 0)
3940 /* Lslash lslash Oslash oslash */
3941 add_char (*command);
3942 add_char ('/');
3944 else if (strcmp (command, "exclamdown") == 0)
3945 add_char ('!');
3946 else if (strcmp (command, "pounds") == 0)
3947 add_char ('#');
3948 else if (strcmp (command, "questiondown") == 0)
3949 add_char ('?');
3950 else
3951 fprintf (stderr, _("How did @%s end up in cm_special_char?\n"), command);
3955 /* Dotless i or j. */
3956 void
3957 cm_dotless (arg, start, end)
3958 int arg, start, end;
3960 if (arg == END)
3962 if (output_paragraph[start] != 'i' && output_paragraph[start] != 'j')
3963 /* This error message isn't perfect if the argument is multiple
3964 characters, but it doesn't seem worth getting right. */
3965 line_error (_("%c%s expects `i' or `j' as argument, not `%c'"),
3966 COMMAND_PREFIX, command, output_paragraph[start]);
3968 else if (end - start != 1)
3969 line_error (_("%c%s expects a single character `i' or `j' as argument"),
3970 COMMAND_PREFIX, command);
3972 /* We've already inserted the `i' or `j', so nothing to do. */
3976 void
3977 cm_today (arg)
3978 int arg;
3980 static char *months [12] =
3981 { N_("January"), N_("February"), N_("March"), N_("April"), N_("May"),
3982 N_("June"), N_("July"), N_("August"), N_("September"), N_("October"),
3983 N_("November"), N_("December") };
3984 if (arg == START)
3986 time_t timer = time (0);
3987 struct tm *ts = localtime (&timer);
3988 add_word_args ("%d %s %d", ts->tm_mday, _(months[ts->tm_mon]),
3989 ts->tm_year + 1900);
3993 void
3994 cm_code (arg)
3995 int arg;
3997 extern int printing_index;
3999 if (arg == START)
4001 in_fixed_width_font++;
4003 if (!printing_index)
4004 add_char ('`');
4006 else
4008 if (!printing_index)
4009 add_char ('\'');
4013 void
4014 cm_kbd (arg)
4015 int arg;
4017 /* People use @kbd in an example to get the "user input" font.
4018 We don't want quotes in that case. */
4019 if (!in_fixed_width_font)
4020 cm_code (arg);
4023 void
4024 cm_key (arg)
4025 int arg;
4027 add_char (arg == START ? '<' : '>');
4030 /* Convert the character at position into a true control character. */
4031 void
4032 cm_ctrl (arg, start, end)
4033 int arg, start, end;
4035 /* Should we allow multiple character arguments? I think yes. */
4036 if (arg == END)
4038 register int i, character;
4039 #if defined (NO_MULTIPLE_CTRL)
4040 if ((end - start) != 1)
4041 line_error (_("%c%s expects a single character as an argument"),
4042 COMMAND_PREFIX, command);
4043 else
4044 #endif
4045 for (i = start; i < end; i++)
4047 character = output_paragraph[i];
4049 if (isletter (character))
4050 output_paragraph[i] = CTL (coerce_to_upper (character));
4055 /* Handle a command that switches to a non-fixed-width font. */
4056 void
4057 not_fixed_width (arg)
4058 int arg;
4060 if (arg == START)
4061 in_fixed_width_font = 0;
4064 /* Small caps and @var in makeinfo just uppercase the text. */
4065 void
4066 cm_var_sc (arg, start_pos, end_pos)
4067 int arg, start_pos, end_pos;
4069 not_fixed_width (arg);
4071 if (arg == END)
4073 while (start_pos < end_pos)
4075 output_paragraph[start_pos] =
4076 coerce_to_upper (output_paragraph[start_pos]);
4077 start_pos++;
4082 void
4083 cm_dfn (arg, position)
4084 int arg, position;
4086 add_char ('"');
4089 void
4090 cm_emph (arg)
4091 int arg;
4093 add_char ('*');
4096 void
4097 cm_strong (arg, position)
4098 int arg, position;
4100 cm_emph (arg);
4103 void
4104 cm_cite (arg, position)
4105 int arg, position;
4107 if (arg == START)
4108 add_word ("`");
4109 else
4110 add_word ("'");
4113 /* No highlighting, but argument switches fonts. */
4114 void
4115 cm_not_fixed_width (arg, start, end)
4116 int arg, start, end;
4118 not_fixed_width (arg);
4121 /* Various commands are no-op's. */
4122 void
4123 cm_no_op ()
4127 /* No-op that eats its argument on same line. */
4128 void
4129 cm_no_op_line_arg ()
4131 char *temp;
4132 get_rest_of_line (&temp);
4133 free (temp);
4136 /* Prevent the argument from being split across two lines. */
4137 void
4138 cm_w (arg, start, end)
4139 int arg, start, end;
4141 if (arg == START)
4142 non_splitting_words++;
4143 else
4144 non_splitting_words--;
4148 /* Explain that this command is obsolete, thus the user shouldn't
4149 do anything with it. */
4150 void
4151 cm_obsolete (arg, start, end)
4152 int arg, start, end;
4154 if (arg == START)
4155 warning (_("%c%s is obsolete"), COMMAND_PREFIX, command);
4158 /* Insert the text following input_text_offset up to the end of the line
4159 in a new, separate paragraph. Directly underneath it, insert a
4160 line of WITH_CHAR, the same length of the inserted text. */
4161 void
4162 insert_and_underscore (with_char)
4163 int with_char;
4165 register int i, len;
4166 int old_no_indent, starting_pos, ending_pos;
4167 char *temp;
4169 close_paragraph ();
4170 filling_enabled = indented_fill = 0;
4171 old_no_indent = no_indent;
4172 no_indent = 1;
4174 #if defined (HAVE_MACROS)
4175 if (macro_expansion_output_stream && !executing_string)
4176 append_to_expansion_output (input_text_offset + 1);
4177 #endif /* HAVE_MACROS */
4179 get_rest_of_line (&temp);
4181 starting_pos = output_position + output_paragraph_offset;
4182 #if defined (HAVE_MACROS)
4183 if (macro_expansion_output_stream && !executing_string)
4185 char *temp1 = (char *) xmalloc (2 + strlen (temp));
4186 sprintf (temp1, "%s\n", temp);
4187 remember_itext (input_text, input_text_offset);
4188 me_execute_string (temp1);
4189 free (temp1);
4191 else
4192 #endif /* HAVE_MACROS */
4193 execute_string ("%s\n", temp);
4195 ending_pos = output_position + output_paragraph_offset;
4196 free (temp);
4198 len = (ending_pos - starting_pos) - 1;
4199 for (i = 0; i < len; i++)
4200 add_char (with_char);
4201 insert ('\n');
4202 close_paragraph ();
4203 filling_enabled = 1;
4204 no_indent = old_no_indent;
4207 /* Here is a structure which associates sectioning commands with
4208 an integer, hopefully to reflect the `depth' of the current
4209 section. */
4210 struct {
4211 char *name;
4212 int level;
4213 } section_alist[] = {
4214 { "unnumberedsubsubsec", 5 },
4215 { "unnumberedsubsec", 4 },
4216 { "unnumberedsec", 3 },
4217 { "unnumbered", 2 },
4218 { "appendixsubsubsec", 5 },
4219 { "appendixsubsec", 4 },
4220 { "appendixsec", 3 },
4221 { "appendixsection", 3 },
4222 { "appendix", 2 },
4223 { "subsubsec", 5 },
4224 { "subsubsection", 5 },
4225 { "subsection", 4 },
4226 { "section", 3 },
4227 { "chapter", 2 },
4228 { "top", 1 },
4230 { (char *)NULL, 0 }
4233 /* Amount to offset the name of sectioning commands to levels by. */
4234 int section_alist_offset = 0;
4236 /* Shift the meaning of @section to @chapter. */
4237 void
4238 cm_raisesections ()
4240 discard_until ("\n");
4241 section_alist_offset--;
4244 /* Shift the meaning of @chapter to @section. */
4245 void
4246 cm_lowersections ()
4248 discard_until ("\n");
4249 section_alist_offset++;
4252 /* Return an integer which identifies the type section present in TEXT. */
4254 what_section (text)
4255 char *text;
4257 register int i, j;
4258 char *t;
4260 find_section_command:
4261 for (j = 0; text[j] && cr_or_whitespace (text[j]); j++);
4262 if (text[j] != COMMAND_PREFIX)
4263 return (-1);
4265 text = text + j + 1;
4267 /* We skip @c, @comment, and @?index commands. */
4268 if ((strncmp (text, "comment", strlen ("comment")) == 0) ||
4269 (text[0] == 'c' && cr_or_whitespace (text[1])) ||
4270 (strcmp (text + 1, "index") == 0))
4272 while (*text++ != '\n');
4273 goto find_section_command;
4276 /* Handle italicized sectioning commands. */
4277 if (*text == 'i')
4278 text++;
4280 for (j = 0; text[j] && !cr_or_whitespace (text[j]); j++);
4282 for (i = 0; (t = section_alist[i].name); i++)
4284 if (j == strlen (t) && strncmp (t, text, j) == 0)
4286 int return_val;
4288 return_val = (section_alist[i].level + section_alist_offset);
4290 if (return_val < 0)
4291 return_val = 0;
4292 else if (return_val > 5)
4293 return_val = 5;
4294 return (return_val);
4297 return (-1);
4300 /* Set the level of @top to LEVEL. Return the old level of @top. */
4302 set_top_section_level (level)
4303 int level;
4305 register int i, result = -1;
4307 for (i = 0; section_alist[i].name; i++)
4308 if (strcmp (section_alist[i].name, "top") == 0)
4310 result = section_alist[i].level;
4311 section_alist[i].level = level;
4312 break;
4314 return (result);
4317 /* Treat this just like @unnumbered. The only difference is
4318 in node defaulting. */
4319 void
4320 cm_top ()
4322 /* It is an error to have more than one @top. */
4323 if (top_node_seen)
4325 TAG_ENTRY *tag = tag_table;
4327 line_error (_("Node with %ctop as a section already exists"),
4328 COMMAND_PREFIX);
4330 while (tag != (TAG_ENTRY *)NULL)
4332 if ((tag->flags & IS_TOP))
4334 int old_line_number = line_number;
4335 char *old_input_filename = input_filename;
4337 line_number = tag->line_no;
4338 input_filename = tag->filename;
4339 line_error (_("Here is the %ctop node"), COMMAND_PREFIX);
4340 input_filename = old_input_filename;
4341 line_number = old_line_number;
4342 return;
4344 tag = tag->next_ent;
4347 else
4349 top_node_seen = 1;
4351 /* It is an error to use @top before you have used @node. */
4352 if (!tag_table)
4354 char *top_name;
4356 get_rest_of_line (&top_name);
4357 free (top_name);
4358 line_error (_("%ctop used before %cnode, defaulting to %s"),
4359 COMMAND_PREFIX, COMMAND_PREFIX, top_name);
4360 execute_string ("@node Top, , (dir), (dir)\n@top %s\n", top_name);
4361 return;
4364 cm_unnumbered ();
4366 /* The most recently defined node is the top node. */
4367 tag_table->flags |= IS_TOP;
4369 /* Now set the logical hierarchical level of the Top node. */
4371 int orig_offset = input_text_offset;
4373 input_text_offset = search_forward (node_search_string, orig_offset);
4375 if (input_text_offset > 0)
4377 int this_section;
4379 /* We have encountered a non-top node, so mark that one exists. */
4380 non_top_node_seen = 1;
4382 /* Move to the end of this line, and find out what the
4383 sectioning command is here. */
4384 while (input_text[input_text_offset] != '\n')
4385 input_text_offset++;
4387 if (input_text_offset < size_of_input_text)
4388 input_text_offset++;
4390 this_section = what_section (input_text + input_text_offset);
4392 /* If we found a sectioning command, then give the top section
4393 a level of this section - 1. */
4394 if (this_section != -1)
4395 set_top_section_level (this_section - 1);
4397 input_text_offset = orig_offset;
4402 /* Organized by level commands. That is, "*" == chapter, "=" == section. */
4403 char *scoring_characters = "*=-.";
4405 void
4406 sectioning_underscore (command)
4407 char *command;
4409 char character;
4410 char *temp;
4411 int level;
4413 temp = (char *)xmalloc (2 + strlen (command));
4414 temp[0] = COMMAND_PREFIX;
4415 strcpy (&temp[1], command);
4416 level = what_section (temp);
4417 free (temp);
4418 level -= 2;
4420 if (level < 0)
4421 level = 0;
4423 character = scoring_characters[level];
4425 insert_and_underscore (character);
4428 /* The command still works, but prints a warning message in addition. */
4429 void
4430 cm_ideprecated (arg, start, end)
4431 int arg, start, end;
4433 warning (_("%c%s is obsolete; use %c%s instead"),
4434 COMMAND_PREFIX, command, COMMAND_PREFIX, command + 1);
4435 sectioning_underscore (command + 1);
4438 /* The remainder of the text on this line is a chapter heading. */
4439 void
4440 cm_chapter ()
4442 sectioning_underscore ("chapter");
4445 /* The remainder of the text on this line is a section heading. */
4446 void
4447 cm_section ()
4449 sectioning_underscore ("section");
4452 /* The remainder of the text on this line is a subsection heading. */
4453 void
4454 cm_subsection ()
4456 sectioning_underscore ("subsection");
4459 /* The remainder of the text on this line is a subsubsection heading. */
4460 void
4461 cm_subsubsection ()
4463 sectioning_underscore ("subsubsection");
4466 /* The remainder of the text on this line is an unnumbered heading. */
4467 void
4468 cm_unnumbered ()
4470 cm_chapter ();
4473 /* The remainder of the text on this line is an unnumbered section heading. */
4474 void
4475 cm_unnumberedsec ()
4477 cm_section ();
4480 /* The remainder of the text on this line is an unnumbered
4481 subsection heading. */
4482 void
4483 cm_unnumberedsubsec ()
4485 cm_subsection ();
4488 /* The remainder of the text on this line is an unnumbered
4489 subsubsection heading. */
4490 void
4491 cm_unnumberedsubsubsec ()
4493 cm_subsubsection ();
4496 /* The remainder of the text on this line is an appendix heading. */
4497 void
4498 cm_appendix ()
4500 cm_chapter ();
4503 /* The remainder of the text on this line is an appendix section heading. */
4504 void
4505 cm_appendixsec ()
4507 cm_section ();
4510 /* The remainder of the text on this line is an appendix subsection heading. */
4511 void
4512 cm_appendixsubsec ()
4514 cm_subsection ();
4517 /* The remainder of the text on this line is an appendix
4518 subsubsection heading. */
4519 void
4520 cm_appendixsubsubsec ()
4522 cm_subsubsection ();
4525 /* Compatibility functions substitute for chapter, section, etc. */
4526 void
4527 cm_majorheading ()
4529 cm_chapheading ();
4532 void
4533 cm_chapheading ()
4535 cm_chapter ();
4538 void
4539 cm_heading ()
4541 cm_section ();
4544 void
4545 cm_subheading ()
4547 cm_subsection ();
4550 void
4551 cm_subsubheading ()
4553 cm_subsubsection ();
4556 /* **************************************************************** */
4557 /* */
4558 /* Adding nodes, and making tags */
4559 /* */
4560 /* **************************************************************** */
4562 /* Start a new tag table. */
4563 void
4564 init_tag_table ()
4566 while (tag_table != (TAG_ENTRY *) NULL)
4568 TAG_ENTRY *temp = tag_table;
4569 free (temp->node);
4570 free (temp->prev);
4571 free (temp->next);
4572 free (temp->up);
4573 tag_table = tag_table->next_ent;
4574 free (temp);
4578 void
4579 write_tag_table ()
4581 write_tag_table_internal (0); /* Not indirect. */
4584 void
4585 write_tag_table_indirect ()
4587 write_tag_table_internal (1);
4590 /* Write out the contents of the existing tag table.
4591 INDIRECT_P says how to format the output. */
4592 void
4593 write_tag_table_internal (indirect_p)
4594 int indirect_p;
4596 TAG_ENTRY *node = tag_table;
4597 int old_indent = no_indent;
4599 no_indent = 1;
4600 filling_enabled = 0;
4601 must_start_paragraph = 0;
4602 close_paragraph ();
4604 if (!indirect_p)
4606 no_indent = 1;
4607 insert ('\n');
4610 add_word_args ("\037\nTag Table:\n%s", indirect_p ? "(Indirect)\n" : "");
4612 while (node != (TAG_ENTRY *) NULL)
4614 execute_string ("Node: %s", node->node);
4615 add_word_args ("\177%d\n", node->position);
4616 node = node->next_ent;
4619 add_word ("\037\nEnd Tag Table\n");
4620 flush_output ();
4621 no_indent = old_indent;
4624 char *
4625 get_node_token (expand)
4626 int expand;
4628 char *string;
4630 get_until_in_line (expand, ",", &string);
4632 if (curchar () == ',')
4633 input_text_offset++;
4635 canon_white (string);
4637 /* Force all versions of "top" to be "Top". */
4638 normalize_node_name (string);
4640 return (string);
4643 /* Convert "top" and friends into "Top". */
4644 void
4645 normalize_node_name (string)
4646 char *string;
4648 if (strcasecmp (string, "Top") == 0)
4649 strcpy (string, "Top");
4652 /* Look up NAME in the tag table, and return the associated
4653 tag_entry. If the node is not in the table return NULL. */
4654 TAG_ENTRY *
4655 find_node (name)
4656 char *name;
4658 TAG_ENTRY *tag = tag_table;
4660 while (tag != (TAG_ENTRY *) NULL)
4662 if (strcmp (tag->node, name) == 0)
4663 return (tag);
4664 tag = tag->next_ent;
4666 return ((TAG_ENTRY *) NULL);
4669 /* Remember NODE and associates. */
4670 void
4671 remember_node (node, prev, next, up, position, line_no, no_warn)
4672 char *node, *prev, *next, *up;
4673 int position, line_no, no_warn;
4675 /* Check for existence of this tag already. */
4676 if (validating)
4678 register TAG_ENTRY *tag = find_node (node);
4679 if (tag)
4681 line_error (
4682 _("Node `%s' multiply defined (line %d is first definition at)"),
4683 node, tag->line_no);
4684 return;
4688 /* First, make this the current node. */
4689 current_node = node;
4691 /* Now add it to the list. */
4693 TAG_ENTRY *new = (TAG_ENTRY *) xmalloc (sizeof (TAG_ENTRY));
4694 new->node = node;
4695 new->prev = prev;
4696 new->next = next;
4697 new->up = up;
4698 new->position = position;
4699 new->line_no = line_no;
4700 new->filename = node_filename;
4701 new->touched = 0; /* not yet referenced. */
4702 new->flags = 0;
4703 if (no_warn)
4704 new->flags |= NO_WARN;
4705 new->next_ent = tag_table;
4706 tag_table = new;
4710 /* The order is: nodename, nextnode, prevnode, upnode.
4711 If all of the NEXT, PREV, and UP fields are empty, they are defaulted.
4712 You must follow a node command which has those fields defaulted
4713 with a sectioning command (e.g. @chapter) giving the "level" of that node.
4714 It is an error not to do so.
4715 The defaults come from the menu in this node's parent. */
4716 void
4717 cm_node ()
4719 char *node, *prev, *next, *up;
4720 int new_node_pos, defaulting, this_section, no_warn = 0;
4721 extern int already_outputting_pending_notes;
4723 if (strcmp (command, "nwnode") == 0)
4724 no_warn = 1;
4726 /* Get rid of unmatched brace arguments from previous commands. */
4727 discard_braces ();
4729 /* There also might be insertions left lying around that haven't been
4730 ended yet. Do that also. */
4731 discard_insertions (1);
4733 if (!already_outputting_pending_notes)
4735 close_paragraph ();
4736 output_pending_notes ();
4737 free_pending_notes ();
4740 filling_enabled = indented_fill = 0;
4741 new_node_pos = output_position;
4742 current_footnote_number = 1;
4744 #if defined (HAVE_MACROS)
4745 if (macro_expansion_output_stream && !executing_string)
4746 append_to_expansion_output (input_text_offset + 1);
4747 #endif /* HAVE_MACROS */
4749 node = get_node_token (1);
4750 next = get_node_token (0);
4751 prev = get_node_token (0);
4752 up = get_node_token (0);
4754 if (verbose_mode)
4755 printf (_("Formatting node %s...\n"), node);
4757 #if defined (HAVE_MACROS)
4758 if (macro_expansion_output_stream && !executing_string)
4759 remember_itext (input_text, input_text_offset);
4760 #endif /* HAVE_MACROS */
4762 no_indent = 1;
4763 if (!no_headers)
4765 add_word_args ("\037\nFile: %s, Node: ", pretty_output_filename);
4767 #if defined (HAVE_MACROS)
4768 if (macro_expansion_output_stream && !executing_string)
4769 me_execute_string (node);
4770 else
4771 #endif /* HAVE_MACROS */
4772 execute_string ("%s", node);
4773 filling_enabled = indented_fill = 0;
4776 /* Check for defaulting of this node's next, prev, and up fields. */
4777 defaulting = (*next == 0 && *prev == 0 && *up == 0);
4779 this_section = what_section (input_text + input_text_offset);
4781 /* If we are defaulting, then look at the immediately following
4782 sectioning command (error if none) to determine the node's
4783 level. Find the node that contains the menu mentioning this node
4784 that is one level up (error if not found). That node is the "Up"
4785 of this node. Default the "Next" and "Prev" from the menu. */
4786 if (defaulting)
4788 NODE_REF *last_ref = (NODE_REF *)NULL;
4789 NODE_REF *ref = node_references;
4791 if ((this_section < 0) && (strcmp (node, "Top") != 0))
4793 char *polite_section_name = "top";
4794 int i;
4796 for (i = 0; section_alist[i].name; i++)
4797 if (section_alist[i].level == current_section + 1)
4799 polite_section_name = section_alist[i].name;
4800 break;
4803 line_error
4804 (_("Node `%s' requires a sectioning command (e.g. %c%s)"),
4805 node, COMMAND_PREFIX, polite_section_name);
4807 else
4809 if (strcmp (node, "Top") == 0)
4811 /* Default the NEXT pointer to be the first menu item in
4812 this node, if there is a menu in this node. We have to
4813 try very hard to find the menu, as it may be obscured
4814 by execution_strings which are on the filestack. For
4815 every member of the filestack which has a FILENAME
4816 member which is identical to the current INPUT_FILENAME,
4817 search forward from that offset. */
4818 int saved_input_text_offset = input_text_offset;
4819 int saved_size_of_input_text = size_of_input_text;
4820 char *saved_input_text = input_text;
4821 FSTACK *next_file = filestack;
4823 int orig_offset, orig_size;
4824 char *glean_node_from_menu ();
4826 /* No matter what, make this file point back at `(dir)'. */
4827 free (up); up = xstrdup ("(dir)");
4829 while (1)
4831 orig_offset = input_text_offset;
4832 orig_size =
4833 search_forward (node_search_string, orig_offset);
4835 if (orig_size < 0)
4836 orig_size = size_of_input_text;
4838 input_text_offset =
4839 search_forward (menu_search_string, orig_offset);
4841 if (input_text_offset > -1)
4843 char *nodename_from_menu = (char *)NULL;
4845 input_text_offset =
4846 search_forward ("\n* ", input_text_offset);
4848 if (input_text_offset != -1)
4849 nodename_from_menu = glean_node_from_menu (0);
4851 if (nodename_from_menu)
4853 free (next); next = nodename_from_menu;
4854 break;
4858 /* We got here, so it hasn't been found yet. Try
4859 the next file on the filestack if there is one. */
4860 if (next_file &&
4861 (strcmp (next_file->filename, input_filename) == 0))
4863 input_text = next_file->text;
4864 input_text_offset = next_file->offset;
4865 size_of_input_text = next_file->size;
4866 next_file = next_file->next;
4868 else
4870 /* No more input files to check. */
4871 break;
4875 input_text = saved_input_text;
4876 input_text_offset = saved_input_text_offset;
4877 size_of_input_text = saved_size_of_input_text;
4881 /* Fix the level of the menu references in the Top node, iff it
4882 was declared with @top, and no subsequent reference was found. */
4883 if (top_node_seen && !non_top_node_seen)
4885 /* Then this is the first non-@top node seen. */
4886 int level;
4888 level = set_top_section_level (this_section - 1);
4889 non_top_node_seen = 1;
4891 while (ref)
4893 if (ref->section == level)
4894 ref->section = this_section - 1;
4895 ref = ref->next;
4898 ref = node_references;
4901 while (ref)
4903 if (ref->section == (this_section - 1) &&
4904 ref->type == menu_reference &&
4905 strcmp (ref->node, node) == 0)
4907 char *containing_node = ref->containing_node;
4909 free (up);
4910 up = xstrdup (containing_node);
4912 if (last_ref &&
4913 last_ref->type == menu_reference &&
4914 (strcmp (last_ref->containing_node,
4915 containing_node) == 0))
4917 free (next);
4918 next = xstrdup (last_ref->node);
4921 while ((ref->section == this_section - 1) &&
4922 (ref->next) &&
4923 (ref->next->type != menu_reference))
4924 ref = ref->next;
4926 if (ref->next && ref->type == menu_reference &&
4927 (strcmp (ref->next->containing_node,
4928 containing_node) == 0))
4930 free (prev);
4931 prev = xstrdup (ref->next->node);
4933 else if (!ref->next &&
4934 strcasecmp (ref->containing_node, "Top") == 0)
4936 free (prev);
4937 prev = xstrdup (ref->containing_node);
4939 break;
4941 last_ref = ref;
4942 ref = ref->next;
4946 #if defined (HAVE_MACROS)
4947 /* Insert the correct args if we are expanding macros, and the node's
4948 pointers weren't defaulted. */
4949 if (macro_expansion_output_stream && !executing_string && !defaulting)
4951 char *temp;
4952 int op_orig = output_paragraph_offset;
4954 temp = (char *)xmalloc (3 + strlen (next));
4955 sprintf (temp, ", %s", next);
4956 me_execute_string (temp);
4957 free (temp);
4959 temp = (char *)xmalloc (3 + strlen (prev));
4960 sprintf (temp, ", %s", prev);
4961 me_execute_string (temp);
4962 free (temp);
4964 temp = (char *)xmalloc (4 + strlen (up));
4965 sprintf (temp, ", %s", up);
4966 me_execute_string (temp);
4967 free (temp);
4969 output_paragraph_offset = op_orig;
4971 #endif /* HAVE_MACROS */
4973 if (!no_headers)
4975 #if defined (HAVE_MACROS)
4976 if (macro_expansion_output_stream)
4977 me_inhibit_expansion++;
4978 #endif /* HAVE_MACROS */
4980 if (*next)
4982 execute_string (", Next: %s", next);
4983 filling_enabled = indented_fill = 0;
4986 if (*prev)
4988 execute_string (", Prev: %s", prev);
4989 filling_enabled = indented_fill = 0;
4992 if (*up)
4994 execute_string (", Up: %s", up);
4995 filling_enabled = indented_fill = 0;
4997 #if defined (HAVE_MACROS)
4998 if (macro_expansion_output_stream)
4999 me_inhibit_expansion--;
5000 #endif /* HAVE_MACROS */
5003 close_paragraph ();
5004 no_indent = 0;
5006 if (!*node)
5008 line_error ("No node name specified for `%c%s' command",
5009 COMMAND_PREFIX, command);
5010 free (node);
5011 free (next);
5012 free (prev);
5013 free (up);
5015 else
5017 if (!*next) { free (next); next = (char *)NULL; }
5018 if (!*prev) { free (prev); prev = (char *)NULL; }
5019 if (!*up) { free (up); up = (char *)NULL; }
5020 remember_node (node, prev, next, up, new_node_pos, line_number, no_warn);
5023 /* Change the section only if there was a sectioning command. */
5024 if (this_section >= 0)
5025 current_section = this_section;
5027 filling_enabled = 1;
5030 /* Validation of an info file.
5031 Scan through the list of tag entries touching the Prev, Next, and Up
5032 elements of each. It is an error not to be able to touch one of them,
5033 except in the case of external node references, such as "(DIR)".
5035 If the Prev is different from the Up,
5036 then the Prev node must have a Next pointing at this node.
5038 Every node except Top must have an Up.
5039 The Up node must contain some sort of reference, other than a Next,
5040 to this node.
5042 If the Next is different from the Next of the Up,
5043 then the Next node must have a Prev pointing at this node. */
5044 void
5045 validate_file (tag_table)
5046 TAG_ENTRY *tag_table;
5048 char *old_input_filename = input_filename;
5049 TAG_ENTRY *tags = tag_table;
5051 while (tags != (TAG_ENTRY *) NULL)
5053 register TAG_ENTRY *temp_tag;
5055 input_filename = tags->filename;
5056 line_number = tags->line_no;
5058 /* If this is a "no warn" node, don't validate it in any way. */
5059 if (tags->flags & NO_WARN)
5061 tags = tags->next_ent;
5062 continue;
5065 /* If this node has a Next, then make sure that the Next exists. */
5066 if (tags->next)
5068 validate (tags->next, tags->line_no, "Next");
5070 /* If the Next node exists, and there is no Up, then make
5071 sure that the Prev of the Next points back. */
5072 temp_tag = find_node (tags->next);
5073 if (temp_tag)
5075 char *prev;
5077 if (temp_tag->flags & NO_WARN)
5079 /* Do nothing if we aren't supposed to issue warnings
5080 about this node. */
5082 else
5084 prev = temp_tag->prev;
5085 if (!prev || (strcmp (prev, tags->node) != 0))
5087 line_error (_("Node `%s''s Next field not pointed back to"),
5088 tags->node);
5089 line_number = temp_tag->line_no;
5090 input_filename = temp_tag->filename;
5091 line_error
5092 (_("This node (`%s') is the one with the bad `Prev'"),
5093 temp_tag->node);
5094 input_filename = tags->filename;
5095 line_number = tags->line_no;
5096 temp_tag->flags |= PREV_ERROR;
5102 /* Validate the Prev field if there is one, and we haven't already
5103 complained about it in some way. You don't have to have a Prev
5104 field at this stage. */
5105 if (!(tags->flags & PREV_ERROR) && tags->prev)
5107 int valid_p = validate (tags->prev, tags->line_no, "Prev");
5109 if (!valid_p)
5110 tags->flags |= PREV_ERROR;
5111 else
5113 /* If the Prev field is not the same as the Up field,
5114 then the node pointed to by the Prev field must have
5115 a Next field which points to this node. */
5116 if (tags->up && (strcmp (tags->prev, tags->up) != 0))
5118 temp_tag = find_node (tags->prev);
5120 /* If we aren't supposed to issue warnings about the
5121 target node, do nothing. */
5122 if (!temp_tag || (temp_tag->flags & NO_WARN))
5124 /* Do nothing. */
5126 else
5128 if (!temp_tag->next ||
5129 (strcmp (temp_tag->next, tags->node) != 0))
5131 line_error
5132 (_("Node `%s's Prev field not pointed back to"),
5133 tags->node);
5134 line_number = temp_tag->line_no;
5135 input_filename = temp_tag->filename;
5136 line_error (_("This node (`%s') has the bad Next"),
5137 temp_tag->node);
5138 input_filename = tags->filename;
5139 line_number = tags->line_no;
5140 temp_tag->flags |= NEXT_ERROR;
5147 if (!tags->up && (strcasecmp (tags->node, _("Top")) != 0))
5148 line_error (_("Node `%s' missing Up field"), tags->node);
5149 else if (tags->up)
5151 int valid_p = validate (tags->up, tags->line_no, "Up");
5153 /* If node X has Up: Y, then warn if Y fails to have a menu item
5154 or note pointing at X, if Y isn't of the form "(Y)". */
5155 if (valid_p && *tags->up != '(')
5157 NODE_REF *nref, *tref, *list;
5158 NODE_REF *find_node_reference ();
5160 tref = (NODE_REF *) NULL;
5161 list = node_references;
5163 for (;;)
5165 if (!(nref = find_node_reference (tags->node, list)))
5166 break;
5168 if (strcmp (nref->containing_node, tags->up) == 0)
5170 if (nref->type != menu_reference)
5172 tref = nref;
5173 list = nref->next;
5175 else
5176 break;
5178 list = nref->next;
5181 if (!nref)
5183 temp_tag = find_node (tags->up);
5184 line_number = temp_tag->line_no;
5185 input_filename = temp_tag->filename;
5186 if (!tref)
5187 line_error (
5188 _("`%s' has an Up field of `%s', but `%s' has no menu item for `%s'"),
5189 tags->node, tags->up, tags->up, tags->node);
5190 line_number = tags->line_no;
5191 input_filename = tags->filename;
5195 tags = tags->next_ent;
5198 validate_other_references (node_references);
5199 /* We have told the user about the references which didn't exist.
5200 Now tell him about the nodes which aren't referenced. */
5202 tags = tag_table;
5203 while (tags != (TAG_ENTRY *) NULL)
5205 /* If this node is a "no warn" node, do nothing. */
5206 if (tags->flags & NO_WARN)
5208 tags = tags->next_ent;
5209 continue;
5212 /* Special hack. If the node in question appears to have
5213 been referenced more than REFERENCE_WARNING_LIMIT times,
5214 give a warning. */
5215 if (tags->touched > reference_warning_limit)
5217 input_filename = tags->filename;
5218 line_number = tags->line_no;
5219 warning (_("node `%s' has been referenced %d times"),
5220 tags->node, tags->touched);
5223 if (tags->touched == 0)
5225 input_filename = tags->filename;
5226 line_number = tags->line_no;
5228 /* Notice that the node "Top" is special, and doesn't have to
5229 be referenced. */
5230 if (strcasecmp (tags->node, _("Top")) != 0)
5231 warning (_("unreferenced node `%s'"), tags->node);
5233 tags = tags->next_ent;
5235 input_filename = old_input_filename;
5238 /* Return 1 if tag correctly validated, or 0 if not. */
5240 validate (tag, line, label)
5241 char *tag;
5242 int line;
5243 char *label;
5245 TAG_ENTRY *result;
5247 /* If there isn't a tag to verify, or if the tag is in another file,
5248 then it must be okay. */
5249 if (!tag || !*tag || *tag == '(')
5250 return (1);
5252 /* Otherwise, the tag must exist. */
5253 result = find_node (tag);
5255 if (!result)
5257 line_number = line;
5258 line_error (_("%s reference to nonexistent node `%s'"), label, tag);
5259 return (0);
5261 result->touched++;
5262 return (1);
5265 /* Split large output files into a series of smaller files. Each file
5266 is pointed to in the tag table, which then gets written out as the
5267 original file. The new files have the same name as the original file
5268 with a "-num" attached. SIZE is the largest number of bytes to allow
5269 in any single split file. */
5270 void
5271 split_file (filename, size)
5272 char *filename;
5273 int size;
5275 char *root_filename, *root_pathname;
5276 char *the_file, *filename_part ();
5277 struct stat fileinfo;
5278 long file_size;
5279 char *the_header;
5280 int header_size;
5282 /* Can only do this to files with tag tables. */
5283 if (!tag_table)
5284 return;
5286 if (size == 0)
5287 size = DEFAULT_SPLIT_SIZE;
5289 if ((stat (filename, &fileinfo) != 0) ||
5290 (((long) fileinfo.st_size) < SPLIT_SIZE_THRESHOLD))
5291 return;
5292 file_size = (long) fileinfo.st_size;
5294 the_file = find_and_load (filename);
5295 if (!the_file)
5296 return;
5298 root_filename = filename_part (filename);
5299 root_pathname = pathname_part (filename);
5301 if (!root_pathname)
5302 root_pathname = xstrdup ("");
5304 /* Start splitting the file. Walk along the tag table
5305 outputting sections of the file. When we have written
5306 all of the nodes in the tag table, make the top-level
5307 pointer file, which contains indirect pointers and
5308 tags for the nodes. */
5310 int which_file = 1;
5311 TAG_ENTRY *tags = tag_table;
5312 char *indirect_info = (char *)NULL;
5314 /* Remember the `header' of this file. The first tag in the file is
5315 the bottom of the header; the top of the file is the start. */
5316 the_header = (char *)xmalloc (1 + (header_size = tags->position));
5317 memcpy (the_header, the_file, header_size);
5319 while (tags)
5321 int file_top, file_bot, limit;
5323 /* Have to include the Control-_. */
5324 file_top = file_bot = tags->position;
5325 limit = file_top + size;
5327 /* If the rest of this file is only one node, then
5328 that is the entire subfile. */
5329 if (!tags->next_ent)
5331 int i = tags->position + 1;
5332 char last_char = the_file[i];
5334 while (i < file_size)
5336 if ((the_file[i] == '\037') &&
5337 ((last_char == '\n') ||
5338 (last_char == '\014')))
5339 break;
5340 else
5341 last_char = the_file[i];
5342 i++;
5344 file_bot = i;
5345 tags = tags->next_ent;
5346 goto write_region;
5349 /* Otherwise, find the largest number of nodes that can fit in
5350 this subfile. */
5351 for (; tags; tags = tags->next_ent)
5353 if (!tags->next_ent)
5355 /* This entry is the last node. Search forward for the end
5356 of this node, and that is the end of this file. */
5357 int i = tags->position + 1;
5358 char last_char = the_file[i];
5360 while (i < file_size)
5362 if ((the_file[i] == '\037') &&
5363 ((last_char == '\n') ||
5364 (last_char == '\014')))
5365 break;
5366 else
5367 last_char = the_file[i];
5368 i++;
5370 file_bot = i;
5372 if (file_bot < limit)
5374 tags = tags->next_ent;
5375 goto write_region;
5377 else
5379 /* Here we want to write out everything before the last
5380 node, and then write the last node out in a file
5381 by itself. */
5382 file_bot = tags->position;
5383 goto write_region;
5387 if (tags->next_ent->position > limit)
5389 if (tags->position == file_top)
5390 tags = tags->next_ent;
5392 file_bot = tags->position;
5394 write_region:
5396 int fd;
5397 char *split_filename;
5399 split_filename = (char *) xmalloc
5400 (10 + strlen (root_pathname) + strlen (root_filename));
5401 sprintf
5402 (split_filename,
5403 "%s%s-%d", root_pathname, root_filename, which_file);
5405 fd = open
5406 (split_filename, O_WRONLY | O_TRUNC | O_CREAT, 0666);
5408 if ((fd < 0) ||
5409 (write (fd, the_header, header_size) != header_size) ||
5410 (write (fd, the_file + file_top, file_bot - file_top)
5411 != (file_bot - file_top)) ||
5412 ((close (fd)) < 0))
5414 perror (split_filename);
5415 if (fd != -1)
5416 close (fd);
5417 exit (FATAL);
5420 if (!indirect_info)
5422 indirect_info = the_file + file_top;
5423 sprintf (indirect_info, "\037\nIndirect:\n");
5424 indirect_info += strlen (indirect_info);
5427 sprintf (indirect_info, "%s-%d: %d\n",
5428 root_filename, which_file, file_top);
5430 free (split_filename);
5431 indirect_info += strlen (indirect_info);
5432 which_file++;
5433 break;
5439 /* We have sucessfully created the subfiles. Now write out the
5440 original again. We must use `output_stream', or
5441 write_tag_table_indirect () won't know where to place the output. */
5442 output_stream = fopen (filename, "w");
5443 if (!output_stream)
5445 perror (filename);
5446 exit (FATAL);
5450 int distance = indirect_info - the_file;
5451 fwrite (the_file, 1, distance, output_stream);
5453 /* Inhibit newlines. */
5454 paragraph_is_open = 0;
5456 write_tag_table_indirect ();
5457 fclose (output_stream);
5458 free (the_header);
5459 free (the_file);
5460 return;
5465 /* The strings here are followed in the message by `reference to...' in
5466 the `validate' routine. */
5467 char *
5468 reftype_type_string (type)
5469 enum reftype type;
5471 switch (type)
5473 case menu_reference:
5474 return ("Menu");
5475 case followed_reference:
5476 return ("Cross");
5477 default:
5478 return ("Internal-bad-reference-type");
5482 /* Remember this node name for later validation use. This is used to
5483 remember menu references while reading the input file. After the
5484 output file has been written, if validation is on, then we use the
5485 contents of `node_references' as a list of nodes to validate. */
5486 void
5487 remember_node_reference (node, line, type)
5488 char *node;
5489 int line;
5490 enum reftype type;
5492 NODE_REF *temp = (NODE_REF *) xmalloc (sizeof (NODE_REF));
5494 temp->next = node_references;
5495 temp->node = xstrdup (node);
5496 temp->line_no = line;
5497 temp->section = current_section;
5498 temp->type = type;
5499 temp->containing_node = xstrdup (current_node ? current_node : "");
5500 temp->filename = node_filename;
5502 node_references = temp;
5505 void
5506 validate_other_references (ref_list)
5507 register NODE_REF *ref_list;
5509 char *old_input_filename = input_filename;
5511 while (ref_list != (NODE_REF *) NULL)
5513 input_filename = ref_list->filename;
5514 validate (ref_list->node, ref_list->line_no,
5515 reftype_type_string (ref_list->type));
5516 ref_list = ref_list->next;
5518 input_filename = old_input_filename;
5521 /* Find NODE in REF_LIST. */
5522 NODE_REF *
5523 find_node_reference (node, ref_list)
5524 char *node;
5525 register NODE_REF *ref_list;
5527 while (ref_list)
5529 if (strcmp (node, ref_list->node) == 0)
5530 break;
5531 ref_list = ref_list->next;
5533 return (ref_list);
5536 void
5537 free_node_references ()
5539 register NODE_REF *list, *temp;
5541 list = node_references;
5543 while (list)
5545 temp = list;
5546 free (list->node);
5547 free (list->containing_node);
5548 list = list->next;
5549 free (temp);
5551 node_references = (NODE_REF *) NULL;
5554 /* This function gets called at the start of every line while inside of
5555 a menu. It checks to see if the line starts with "* ", and if so,
5556 remembers the node reference that this menu refers to.
5557 input_text_offset is at the \n just before the line start. */
5558 #define menu_starter "* "
5559 char *
5560 glean_node_from_menu (remember_reference)
5561 int remember_reference;
5563 int i, orig_offset = input_text_offset;
5564 char *nodename;
5566 if (strncmp (&input_text[input_text_offset + 1],
5567 menu_starter,
5568 strlen (menu_starter)) != 0)
5569 return ((char *)NULL);
5570 else
5571 input_text_offset += strlen (menu_starter) + 1;
5573 get_until_in_line (0, ":", &nodename);
5574 if (curchar () == ':')
5575 input_text_offset++;
5576 canon_white (nodename);
5578 if (curchar () == ':')
5579 goto save_node;
5581 free (nodename);
5582 get_rest_of_line (&nodename);
5584 /* Special hack: If the nodename follows the menu item name,
5585 then we have to read the rest of the line in order to find
5586 out what the nodename is. But we still have to read the
5587 line later, in order to process any formatting commands that
5588 might be present. So un-count the carriage return that has just
5589 been counted. */
5590 line_number--;
5592 isolate_nodename (nodename);
5594 save_node:
5595 input_text_offset = orig_offset;
5596 normalize_node_name (nodename);
5597 i = strlen (nodename);
5598 if (i && nodename[i - 1] == ':')
5599 nodename[i - 1] = 0;
5601 if (remember_reference)
5603 remember_node_reference (nodename, line_number, menu_reference);
5604 free (nodename);
5605 return ((char *)NULL);
5607 else
5608 return (nodename);
5611 static void
5612 isolate_nodename (nodename)
5613 char *nodename;
5615 register int i, c;
5616 int paren_seen, paren;
5618 if (!nodename)
5619 return;
5621 canon_white (nodename);
5622 paren_seen = paren = i = 0;
5624 if (*nodename == '.' || !*nodename)
5626 *nodename = 0;
5627 return;
5630 if (*nodename == '(')
5632 paren++;
5633 paren_seen++;
5634 i++;
5637 for (; (c = nodename[i]); i++)
5639 if (paren)
5641 if (c == '(')
5642 paren++;
5643 else if (c == ')')
5644 paren--;
5646 continue;
5649 /* If the character following the close paren is a space, then this
5650 node has no more characters associated with it. */
5651 if (c == '\t' ||
5652 c == '\n' ||
5653 c == ',' ||
5654 ((paren_seen && nodename[i - 1] == ')') &&
5655 (c == ' ' || c == '.')) ||
5656 (c == '.' &&
5657 ((!nodename[i + 1] ||
5658 (cr_or_whitespace (nodename[i + 1])) ||
5659 (nodename[i + 1] == ')')))))
5660 break;
5662 nodename[i] = 0;
5665 void
5666 cm_menu ()
5668 if (current_node == (char *)NULL)
5670 warning (_("%cmenu seen before first node"), COMMAND_PREFIX);
5671 warning (_("creating `Top' node"));
5672 execute_string ("@node Top");
5674 begin_insertion (menu);
5677 void
5678 cm_detailmenu ()
5680 if (current_node == (char *)NULL)
5682 warning (_("%cmenu seen before first node"), COMMAND_PREFIX);
5683 warning (_("creating `Top' node"));
5684 execute_string ("@node Top");
5686 begin_insertion (detailmenu);
5689 /* **************************************************************** */
5690 /* */
5691 /* Cross Reference Hacking */
5692 /* */
5693 /* **************************************************************** */
5695 /* Return next comma-delimited argument, but do not cross a close-brace
5696 boundary. Clean up whitespace, too. */
5697 char *
5698 get_xref_token ()
5700 char *string;
5702 get_until_in_braces (",", &string);
5703 if (curchar () == ',')
5704 input_text_offset++;
5705 fix_whitespace (string);
5706 return (string);
5709 int px_ref_flag = 0; /* Controls initial output string. */
5711 /* Make a cross reference. */
5712 void
5713 cm_xref (arg)
5715 if (arg == START)
5717 char *arg1, *arg2, *arg3, *arg4, *arg5;
5719 arg1 = get_xref_token ();
5720 arg2 = get_xref_token ();
5721 arg3 = get_xref_token ();
5722 arg4 = get_xref_token ();
5723 arg5 = get_xref_token ();
5725 add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
5727 if (*arg5 || *arg4)
5729 char *node_name;
5731 if (!*arg2)
5733 if (*arg3)
5734 node_name = arg3;
5735 else
5736 node_name = arg1;
5738 else
5739 node_name = arg2;
5741 execute_string ("%s: (%s)%s", node_name, arg4, arg1);
5742 /* Free all of the arguments found. */
5743 if (arg1) free (arg1);
5744 if (arg2) free (arg2);
5745 if (arg3) free (arg3);
5746 if (arg4) free (arg4);
5747 if (arg5) free (arg5);
5748 return;
5750 else
5751 remember_node_reference (arg1, line_number, followed_reference);
5753 if (*arg3)
5755 if (!*arg2)
5756 execute_string ("%s: %s", arg3, arg1);
5757 else
5758 execute_string ("%s: %s", arg2, arg1);
5760 else
5762 if (*arg2)
5763 execute_string ("%s: %s", arg2, arg1);
5764 else
5765 execute_string ("%s::", arg1);
5768 /* Free all of the arguments found. */
5769 if (arg1) free (arg1);
5770 if (arg2) free (arg2);
5771 if (arg3) free (arg3);
5772 if (arg4) free (arg4);
5773 if (arg5) free (arg5);
5775 else
5777 /* Check to make sure that the next non-whitespace character is either
5778 a period or a comma. input_text_offset is pointing at the "}" which
5779 ended the xref or pxref command. */
5780 int temp = input_text_offset + 1;
5782 if (output_paragraph[output_paragraph_offset - 2] == ':' &&
5783 output_paragraph[output_paragraph_offset - 1] == ':')
5784 return;
5785 while (temp < size_of_input_text)
5787 if (cr_or_whitespace (input_text[temp]))
5788 temp++;
5789 else
5791 if (input_text[temp] != '.'
5792 && input_text[temp] != ','
5793 && input_text[temp] != '\t')
5795 line_error (
5796 _("`.' or `,' must follow cross reference, not %c"),
5797 input_text[temp]);
5799 break;
5805 void
5806 cm_pxref (arg)
5807 int arg;
5809 if (arg == START)
5811 px_ref_flag++;
5812 cm_xref (arg);
5813 px_ref_flag--;
5815 else
5816 add_char ('.');
5819 void
5820 cm_inforef (arg)
5821 int arg;
5823 if (arg == START)
5825 char *node = get_xref_token ();
5826 char *pname = get_xref_token ();
5827 char *file = get_xref_token ();
5829 if (*pname)
5830 execute_string ("*note %s: (%s)%s", pname, file, node);
5831 else
5832 execute_string ("*note (%s)%s::", file, node);
5834 free (node);
5835 free (pname);
5836 free (file);
5840 /* A URL reference. */
5841 void
5842 cm_uref (arg, start_pos, end_pos)
5843 int arg, start_pos, end_pos;
5845 if (arg == END)
5847 char *comma;
5848 char *arg = (char *) &output_paragraph[start_pos];
5850 output_paragraph[end_pos] = 0;
5851 output_column -= end_pos - start_pos;
5852 output_paragraph_offset = start_pos;
5854 arg = xstrdup (arg);
5855 comma = strchr (arg, ','); /* let's hope for no commas in the url */
5856 if (comma)
5858 *comma = 0;
5859 /* Ignore spaces at beginning of second arg. */
5860 for (comma++; isspace (*comma); comma++)
5862 add_word (comma);
5863 add_char (' ');
5864 add_char ('(');
5865 add_word (arg);
5866 add_char (')');
5868 else
5870 extern int printing_index;
5872 if (!printing_index)
5873 add_char ('`');
5875 add_word (arg);
5877 if (!printing_index)
5878 add_char ('\'');
5880 free (arg);
5884 /* An email reference. */
5885 void
5886 cm_email (arg, start_pos, end_pos)
5887 int arg, start_pos, end_pos;
5889 if (arg == END)
5891 char *comma;
5892 char *arg = (char *) &output_paragraph[start_pos];
5894 output_paragraph[end_pos] = 0;
5895 output_column -= end_pos - start_pos;
5896 output_paragraph_offset = start_pos;
5898 arg = xstrdup (arg);
5899 comma = strchr (arg, ',');
5900 if (comma)
5902 *comma = 0;
5903 for (comma++; isspace (*comma); comma++)
5905 add_word (comma);
5906 add_char (' ');
5908 add_char ('<');
5909 add_word (arg);
5910 add_char ('>');
5911 free (arg);
5915 /* An external image is a reference, kind of. The parsing is (not
5916 coincidentally) similar, anyway. */
5917 void
5918 cm_image (arg)
5919 int arg;
5921 if (arg == START)
5923 char *name_arg = get_xref_token ();
5924 /* We don't yet care about any other args, but read them so they
5925 don't end up in the text. */
5926 char *arg = get_xref_token ();
5927 if (arg) free (arg);
5928 arg = get_xref_token ();
5929 if (arg) free (arg);
5931 if (*name_arg)
5933 /* Try to open foo.txt. */
5934 FILE *image_file;
5935 char *name = xmalloc (strlen (name_arg) + 4);
5936 strcpy (name, name_arg);
5937 strcat (name, ".txt");
5938 image_file = fopen (name, "r");
5939 if (image_file)
5941 int ch;
5942 int save_inhibit_indentation = inhibit_paragraph_indentation;
5943 int save_filling_enabled = filling_enabled;
5945 inhibit_paragraph_indentation = 1;
5946 filling_enabled = 0;
5947 last_char_was_newline = 0;
5949 /* Maybe we need to remove the final newline if the image
5950 file is only one line to allow in-line images. On the
5951 other hand, they could just make the file without a
5952 final newline. */
5953 while ((ch = getc (image_file)) != EOF)
5954 add_char (ch);
5956 inhibit_paragraph_indentation = save_inhibit_indentation;
5957 filling_enabled = save_filling_enabled;
5959 if (fclose (image_file) != 0) {
5960 perror (name);
5963 else
5964 warning (_("@image file `%s' unreadable: %s"), name,
5965 strerror (errno));
5967 else
5968 line_error (_("@image missing filename argument"));
5970 if (name_arg) free (name_arg);
5974 /* **************************************************************** */
5975 /* */
5976 /* Insertion Command Stubs */
5977 /* */
5978 /* **************************************************************** */
5980 void
5981 cm_quotation ()
5983 begin_insertion (quotation);
5986 void
5987 cm_example ()
5989 begin_insertion (example);
5992 void
5993 cm_smallexample ()
5995 begin_insertion (smallexample);
5998 void
5999 cm_lisp ()
6001 begin_insertion (lisp);
6004 void
6005 cm_smalllisp ()
6007 begin_insertion (smalllisp);
6010 /* @cartouche/@end cartouche draws box with rounded corners in
6011 TeX output. Right now, just a no-op insertion. */
6012 void
6013 cm_cartouche ()
6015 begin_insertion (cartouche);
6018 void
6019 cm_format ()
6021 begin_insertion (format);
6024 void
6025 cm_display ()
6027 begin_insertion (display);
6030 void
6031 cm_direntry ()
6033 if (no_headers)
6034 command_name_condition ();
6035 else
6036 begin_insertion (direntry);
6039 void
6040 cm_itemize ()
6042 begin_insertion (itemize);
6045 void
6046 cm_enumerate ()
6048 do_enumeration (enumerate, "1");
6051 /* Start an enumeration insertion of type TYPE. If the user supplied
6052 no argument on the line, then use DEFAULT_STRING as the initial string. */
6053 void
6054 do_enumeration (type, default_string)
6055 int type;
6056 char *default_string;
6058 get_until_in_line (0, ".", &enumeration_arg);
6059 canon_white (enumeration_arg);
6061 if (!*enumeration_arg)
6063 free (enumeration_arg);
6064 enumeration_arg = xstrdup (default_string);
6067 if (!isdigit (*enumeration_arg) && !isletter (*enumeration_arg))
6069 warning (_("%s requires letter or digit"), insertion_type_pname (type));
6071 switch (type)
6073 case enumerate:
6074 default_string = "1";
6075 break;
6077 enumeration_arg = xstrdup (default_string);
6079 begin_insertion (type);
6082 void
6083 cm_table ()
6085 begin_insertion (table);
6088 void
6089 cm_multitable ()
6091 begin_insertion (multitable); /* @@ */
6094 void
6095 cm_ftable ()
6097 begin_insertion (ftable);
6100 void
6101 cm_vtable ()
6103 begin_insertion (vtable);
6106 void
6107 cm_group ()
6109 begin_insertion (group);
6112 void
6113 cm_ifinfo ()
6115 begin_insertion (ifinfo);
6118 void
6119 cm_ifnothtml ()
6121 begin_insertion (ifnothtml);
6124 void
6125 cm_ifnottex ()
6127 begin_insertion (ifnottex);
6130 /* Begin an insertion where the lines are not filled or indented. */
6131 void
6132 cm_flushleft ()
6134 begin_insertion (flushleft);
6137 /* Begin an insertion where the lines are not filled, and each line is
6138 forced to the right-hand side of the page. */
6139 void
6140 cm_flushright ()
6142 begin_insertion (flushright);
6145 /* End existing insertion block. */
6146 void
6147 cm_end ()
6149 char *temp;
6150 enum insertion_type type;
6152 if (!insertion_level)
6154 line_error (_("Unmatched `%c%s'"), COMMAND_PREFIX, command);
6155 return;
6158 get_rest_of_line (&temp);
6160 if (temp[0] == 0)
6161 line_error (_("`%c%s' needs something after it"), COMMAND_PREFIX, command);
6163 type = find_type_from_name (temp);
6165 if (type == bad_type)
6167 line_error (_("Bad argument to `%s', `%s', using `%s'"),
6168 command, temp, insertion_type_pname (current_insertion_type ()));
6170 end_insertion (type);
6171 free (temp);
6174 /* **************************************************************** */
6175 /* */
6176 /* Conditional Handling */
6177 /* */
6178 /* **************************************************************** */
6180 /* A structure which contains `defined' variables. */
6181 typedef struct defines {
6182 struct defines *next;
6183 char *name;
6184 char *value;
6185 } DEFINE;
6187 /* The linked list of `set' defines. */
6188 DEFINE *defines = (DEFINE *)NULL;
6190 /* Add NAME to the list of `set' defines. */
6191 void
6192 set (name, value)
6193 char *name;
6194 char *value;
6196 DEFINE *temp;
6198 for (temp = defines; temp; temp = temp->next)
6199 if (strcmp (name, temp->name) == 0)
6201 free (temp->value);
6202 temp->value = xstrdup (value);
6203 return;
6206 temp = (DEFINE *)xmalloc (sizeof (DEFINE));
6207 temp->next = defines;
6208 temp->name = xstrdup (name);
6209 temp->value = xstrdup (value);
6210 defines = temp;
6213 /* Remove NAME from the list of `set' defines. */
6214 void
6215 clear (name)
6216 char *name;
6218 register DEFINE *temp, *last;
6220 last = (DEFINE *)NULL;
6221 temp = defines;
6223 while (temp)
6225 if (strcmp (temp->name, name) == 0)
6227 if (last)
6228 last->next = temp->next;
6229 else
6230 defines = temp->next;
6232 free (temp->name);
6233 free (temp->value);
6234 free (temp);
6235 break;
6237 last = temp;
6238 temp = temp->next;
6242 /* Return the value of NAME. The return value is NULL if NAME is unset. */
6243 char *
6244 set_p (name)
6245 char *name;
6247 register DEFINE *temp;
6249 for (temp = defines; temp; temp = temp->next)
6250 if (strcmp (temp->name, name) == 0)
6251 return (temp->value);
6253 return ((char *)NULL);
6256 /* Conditionally parse based on the current command name. */
6257 void
6258 command_name_condition ()
6260 char *discarder;
6262 discarder = (char *)xmalloc (8 + strlen (command));
6264 sprintf (discarder, "\n%cend %s", COMMAND_PREFIX, command);
6265 discard_until (discarder);
6266 discard_until ("\n");
6268 free (discarder);
6271 /* Create a variable whose name appears as the first word on this line. */
6272 void
6273 cm_set ()
6275 handle_variable (SET);
6278 /* Remove a variable whose name appears as the first word on this line. */
6279 void
6280 cm_clear ()
6282 handle_variable (CLEAR);
6285 void
6286 cm_ifset ()
6288 handle_variable (IFSET);
6291 void
6292 cm_ifclear ()
6294 handle_variable (IFCLEAR);
6297 /* This command takes braces, but we parse the contents specially, so we
6298 don't use the standard brace popping code.
6300 The syntax @ifeq{arg1, arg2, texinfo-commands} performs texinfo-commands
6301 if ARG1 and ARG2 caselessly string compare to the same string, otherwise,
6302 it produces no output. */
6303 void
6304 cm_ifeq ()
6306 char **arglist;
6308 arglist = get_brace_args (0);
6310 if (arglist)
6312 if (array_len (arglist) > 1)
6314 if ((strcasecmp (arglist[0], arglist[1]) == 0) &&
6315 (arglist[2] != (char *)NULL))
6316 execute_string ("%s\n", arglist[2]);
6319 free_array (arglist);
6323 void
6324 cm_value (arg, start_pos, end_pos)
6325 int arg, start_pos, end_pos;
6327 if (arg == END)
6329 char *name = (char *) &output_paragraph[start_pos];
6330 char *value;
6331 output_paragraph[end_pos] = 0;
6332 name = xstrdup (name);
6333 value = set_p (name);
6334 output_column -= end_pos - start_pos;
6335 output_paragraph_offset = start_pos;
6337 if (value)
6338 execute_string ("%s", value);
6339 else
6340 add_word_args (_("{No Value For \"%s\"}"), name);
6342 free (name);
6346 /* Set, clear, or conditionalize based on ACTION. */
6347 void
6348 handle_variable (action)
6349 int action;
6351 char *name;
6353 get_rest_of_line (&name);
6354 backup_input_pointer ();
6355 handle_variable_internal (action, name);
6356 free (name);
6359 void
6360 handle_variable_internal (action, name)
6361 int action;
6362 char *name;
6364 char *temp;
6365 int delimiter, additional_text_present = 0;
6367 /* Only the first word of NAME is a valid tag. */
6368 temp = name;
6369 delimiter = 0;
6370 while (*temp && (delimiter || !whitespace (*temp)))
6372 /* #if defined (SET_WITH_EQUAL) */
6373 if (*temp == '"' || *temp == '\'')
6375 if (*temp == delimiter)
6376 delimiter = 0;
6377 else
6378 delimiter = *temp;
6380 /* #endif SET_WITH_EQUAL */
6381 temp++;
6384 if (*temp)
6385 additional_text_present++;
6387 *temp = 0;
6389 if (!*name)
6390 line_error (_("%c%s requires a name"), COMMAND_PREFIX, command);
6391 else
6393 switch (action)
6395 case SET:
6397 char *value;
6399 #if defined (SET_WITH_EQUAL)
6400 /* Allow a value to be saved along with a variable. The value is
6401 the text following an `=' sign in NAME, if any is present. */
6403 for (value = name; *value && *value != '='; value++);
6405 if (*value)
6406 *value++ = 0;
6408 if (*value == '"' || *value == '\'')
6410 value++;
6411 value[strlen (value) - 1] = 0;
6414 #else /* !SET_WITH_EQUAL */
6415 /* The VALUE of NAME is the remainder of the line sans
6416 whitespace. */
6417 if (additional_text_present)
6419 value = temp + 1;
6420 canon_white (value);
6422 else
6423 value = "";
6424 #endif /* !SET_WITH_VALUE */
6426 set (name, value);
6428 break;
6430 case CLEAR:
6431 clear (name);
6432 break;
6434 case IFSET:
6435 case IFCLEAR:
6436 /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set,
6437 read lines from the file until we reach a matching
6438 "@end CONDITION". This means that we only take note of
6439 "@ifset/clear" and "@end" commands. */
6441 char condition[8];
6442 int condition_len;
6443 int orig_line_number = line_number;
6445 if (action == IFSET)
6446 strcpy (condition, "ifset");
6447 else
6448 strcpy (condition, "ifclear");
6450 condition_len = strlen (condition);
6452 if ((action == IFSET && !set_p (name))
6453 || (action == IFCLEAR && set_p (name)))
6455 int level = 0, done = 0;
6457 while (!done && input_text_offset < size_of_input_text)
6459 char *freeable_line, *line;
6461 get_rest_of_line (&freeable_line);
6463 for (line = freeable_line; whitespace (*line); line++);
6465 if (*line == COMMAND_PREFIX &&
6466 (strncmp (line + 1, condition, condition_len) == 0))
6467 level++;
6468 else if (strncmp (line, "@end", 4) == 0)
6470 char *cname = line + 4;
6471 char *temp;
6473 while (*cname && whitespace (*cname))
6474 cname++;
6475 temp = cname;
6477 while (*temp && !whitespace (*temp))
6478 temp++;
6479 *temp = 0;
6481 if (strcmp (cname, condition) == 0)
6483 if (!level)
6485 done = 1;
6487 else
6488 level--;
6491 free (freeable_line);
6494 if (!done)
6496 int save = line_number;
6497 line_number = orig_line_number;
6498 line_error (_("Reached eof before matching @end %s"),
6499 condition);
6500 line_number = save;
6503 /* We found the end of a false @ifset/ifclear. If we are
6504 in a menu, back up over the newline that ends the ifset,
6505 since that newline may also begin the next menu entry. */
6506 break;
6508 else
6510 if (action == IFSET)
6511 begin_insertion (ifset);
6512 else
6513 begin_insertion (ifclear);
6516 break;
6521 /* Execution of random text not in file. */
6523 typedef struct {
6524 char *string; /* The string buffer. */
6525 int size; /* The size of the buffer. */
6526 int in_use; /* Nonzero means string currently in use. */
6527 } EXECUTION_STRING;
6529 static EXECUTION_STRING **execution_strings = (EXECUTION_STRING **)NULL;
6530 static int execution_strings_index = 0;
6531 static int execution_strings_slots = 0;
6533 EXECUTION_STRING *
6534 get_execution_string (initial_size)
6535 int initial_size;
6537 register int i = 0;
6538 EXECUTION_STRING *es = (EXECUTION_STRING *)NULL;
6540 if (execution_strings)
6542 for (i = 0; i < execution_strings_index; i++)
6543 if (execution_strings[i] && (execution_strings[i]->in_use == 0))
6545 es = execution_strings[i];
6546 break;
6550 if (!es)
6552 if (execution_strings_index + 1 >= execution_strings_slots)
6554 execution_strings = (EXECUTION_STRING **)xrealloc
6555 (execution_strings,
6556 (execution_strings_slots += 3) * sizeof (EXECUTION_STRING *));
6557 for (; i < execution_strings_slots; i++)
6558 execution_strings[i] = (EXECUTION_STRING *)NULL;
6561 execution_strings[execution_strings_index] =
6562 (EXECUTION_STRING *)xmalloc (sizeof (EXECUTION_STRING));
6563 es = execution_strings[execution_strings_index];
6564 execution_strings_index++;
6566 es->size = 0;
6567 es->string = (char *)NULL;
6568 es->in_use = 0;
6571 if (initial_size > es->size)
6573 es->string = (char *) xrealloc (es->string, initial_size);
6574 es->size = initial_size;
6576 return (es);
6579 /* Execute the string produced by formatting the ARGs with FORMAT. This
6580 is like submitting a new file with @include. */
6581 void
6582 #if defined (VA_FPRINTF) && __STDC__
6583 execute_string (char *format, ...)
6584 #else
6585 execute_string (format, va_alist)
6586 char *format;
6587 va_dcl
6588 #endif
6590 EXECUTION_STRING *es;
6591 char *temp_string;
6592 #ifdef VA_FPRINTF
6593 va_list ap;
6594 #endif
6596 es = get_execution_string (4000);
6597 temp_string = es->string;
6598 es->in_use = 1;
6600 VA_START (ap, format);
6601 #ifdef VA_SPRINTF
6602 VA_SPRINTF (temp_string, format, ap);
6603 #else
6604 sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
6605 #endif /* not VA_SPRINTF */
6606 va_end (ap);
6608 pushfile ();
6609 input_text_offset = 0;
6610 input_text = temp_string;
6611 input_filename = xstrdup (input_filename);
6612 size_of_input_text = strlen (temp_string);
6614 executing_string++;
6615 reader_loop ();
6616 free (input_filename);
6618 popfile ();
6619 executing_string--;
6620 es->in_use = 0;
6624 /* Return what would be output for STR, i.e., expand Texinfo commands.
6625 If IMPLICIT_CODE is set, expand @code{STR}. */
6627 char *
6628 expansion (str, implicit_code)
6629 char *str;
6630 int implicit_code;
6632 int length;
6633 char *result;
6635 /* Inhibit any real output. */
6636 int start = output_paragraph_offset;
6637 int saved_paragraph_is_open = paragraph_is_open;
6639 inhibit_output_flushing ();
6640 paragraph_is_open = 1;
6641 execute_string (implicit_code ? "@code{%s}" : "%s", str);
6642 uninhibit_output_flushing ();
6644 /* Copy the expansion from the buffer. */
6645 length = output_paragraph_offset - start;
6646 result = xmalloc (1 + length);
6647 memcpy (result, (char *) (output_paragraph + start), length);
6648 result[length] = 0;
6650 /* Pretend it never happened. */
6651 output_paragraph_offset = start;
6652 paragraph_is_open = saved_paragraph_is_open;
6654 return result;
6657 /* @itemx, @item. */
6659 static int itemx_flag = 0;
6661 void
6662 cm_itemx ()
6664 itemx_flag++;
6665 cm_item ();
6666 itemx_flag--;
6669 void
6670 cm_item ()
6672 char *rest_of_line, *item_func;
6674 /* Can only hack "@item" while inside of an insertion. */
6675 if (insertion_level)
6677 INSERTION_ELT *stack = insertion_stack;
6678 int original_input_text_offset;
6680 skip_whitespace ();
6681 original_input_text_offset = input_text_offset;
6683 get_rest_of_line (&rest_of_line);
6684 item_func = current_item_function ();
6686 /* Okay, do the right thing depending on which insertion function
6687 is active. */
6689 switch_top:
6690 switch (stack->insertion)
6692 case multitable:
6693 multitable_item ();
6694 /* Ultra special hack. It appears that some people incorrectly
6695 place text directly after the @item, instead of on a new line
6696 by itself. This happens to work in TeX, so I make it work
6697 here. */
6698 if (*rest_of_line)
6700 line_number--;
6701 input_text_offset = original_input_text_offset;
6703 break;
6705 case ifinfo:
6706 case ifset:
6707 case ifclear:
6708 case cartouche:
6709 stack = stack->next;
6710 if (!stack)
6711 goto no_insertion;
6712 else
6713 goto switch_top;
6714 break;
6716 case menu:
6717 case quotation:
6718 case example:
6719 case smallexample:
6720 case lisp:
6721 case format:
6722 case display:
6723 case group:
6724 line_error (_("The `%c%s' command is meaningless within a `@%s' block"),
6725 COMMAND_PREFIX, command,
6726 insertion_type_pname (current_insertion_type ()));
6727 break;
6729 case itemize:
6730 case enumerate:
6731 if (itemx_flag)
6733 line_error (_("%citemx is not meaningful inside of a `%s' block"),
6734 COMMAND_PREFIX,
6735 insertion_type_pname (current_insertion_type ()));
6737 else
6739 start_paragraph ();
6740 kill_self_indent (-1);
6741 filling_enabled = indented_fill = 1;
6743 if (current_insertion_type () == itemize)
6745 indent (output_column = current_indent - 2);
6747 /* I need some way to determine whether this command
6748 takes braces or not. I believe the user can type
6749 either "@bullet" or "@bullet{}". Of course, they
6750 can also type "o" or "#" or whatever else they want. */
6751 if (item_func && *item_func)
6753 if (*item_func == COMMAND_PREFIX)
6754 if (item_func[strlen (item_func) - 1] != '}')
6755 execute_string ("%s{}", item_func);
6756 else
6757 execute_string ("%s", item_func);
6758 else
6759 execute_string ("%s", item_func);
6761 insert (' ');
6762 output_column++;
6764 else
6765 enumerate_item ();
6767 /* Special hack. This makes `close_paragraph' a no-op until
6768 `start_paragraph' has been called. */
6769 must_start_paragraph = 1;
6771 /* Handle text directly after the @item. */
6772 if (*rest_of_line)
6774 line_number--;
6775 input_text_offset = original_input_text_offset;
6778 break;
6780 case table:
6781 case ftable:
6782 case vtable:
6784 /* We need this to determine if we have two @item's in a row
6785 (see test just below). */
6786 static int last_item_output_position = 0;
6788 /* Get rid of extra characters. */
6789 kill_self_indent (-1);
6791 /* If we have one @item followed directly by another @item,
6792 we need to insert a blank line. This is not true for
6793 @itemx, though. */
6794 if (!itemx_flag && last_item_output_position == output_position)
6795 insert ('\n');
6797 /* `close_paragraph' almost does what we want. The problem
6798 is when paragraph_is_open, and last_char_was_newline, and
6799 the last newline has been turned into a space, because
6800 filling_enabled. I handle it here. */
6801 if (last_char_was_newline && filling_enabled && paragraph_is_open)
6802 insert ('\n');
6803 close_paragraph ();
6805 #if defined (INDENT_PARAGRAPHS_IN_TABLE)
6806 /* Indent on a new line, but back up one indentation level. */
6808 int save = inhibit_paragraph_indentation;
6809 inhibit_paragraph_indentation = 1;
6810 /* At this point, inserting any non-whitespace character will
6811 force the existing indentation to be output. */
6812 add_char ('i');
6813 inhibit_paragraph_indentation = save;
6815 #else /* !INDENT_PARAGRAPHS_IN_TABLE */
6816 add_char ('i');
6817 #endif /* !INDENT_PARAGRAPHS_IN_TABLE */
6819 output_paragraph_offset--;
6820 kill_self_indent (default_indentation_increment + 1);
6822 /* Add item's argument to the line. */
6823 filling_enabled = 0;
6824 if (item_func && *item_func)
6825 execute_string ("%s{%s}", item_func, rest_of_line);
6826 else
6827 execute_string ("%s", rest_of_line);
6829 if (current_insertion_type () == ftable)
6830 execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line);
6831 else if (current_insertion_type () == vtable)
6832 execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line);
6834 /* Start a new line, and let start_paragraph ()
6835 do the indenting of it for you. */
6836 close_single_paragraph ();
6837 indented_fill = filling_enabled = 1;
6838 last_item_output_position = output_position;
6841 free (rest_of_line);
6843 else
6845 no_insertion:
6846 line_error (_("%c%s found outside of an insertion block"),
6847 COMMAND_PREFIX, command);
6851 /* **************************************************************** */
6852 /* */
6853 /* Defun and Friends */
6854 /* */
6855 /* **************************************************************** */
6857 #define DEFUN_SELF_DELIMITING(c) \
6858 (((c) == '(') \
6859 || ((c) == ')') \
6860 || ((c) == '[') \
6861 || ((c) == ']'))
6863 struct token_accumulator
6865 unsigned int length;
6866 unsigned int index;
6867 char **tokens;
6870 void
6871 initialize_token_accumulator (accumulator)
6872 struct token_accumulator *accumulator;
6874 (accumulator->length) = 0;
6875 (accumulator->index) = 0;
6876 (accumulator->tokens) = NULL;
6879 void
6880 accumulate_token (accumulator, token)
6881 struct token_accumulator *accumulator;
6882 char *token;
6884 if ((accumulator->index) >= (accumulator->length))
6886 (accumulator->length) += 10;
6887 (accumulator->tokens) = (char **) xrealloc
6888 (accumulator->tokens, (accumulator->length * sizeof (char *)));
6890 accumulator->tokens[accumulator->index] = token;
6891 accumulator->index += 1;
6894 char *
6895 copy_substring (start, end)
6896 char *start;
6897 char *end;
6899 char *result, *scan, *scan_result;
6901 result = (char *) xmalloc ((end - start) + 1);
6902 scan_result = result;
6903 scan = start;
6905 while (scan < end)
6906 *scan_result++ = *scan++;
6908 *scan_result = 0;
6909 return (result);
6912 /* Given `string' pointing at an open brace, skip forward and return a
6913 pointer to just past the matching close brace. */
6915 scan_group_in_string (string_pointer)
6916 char **string_pointer;
6918 register int c;
6919 register char *scan_string;
6920 register unsigned int level = 1;
6922 scan_string = (*string_pointer) + 1;
6924 while (1)
6926 if (level == 0)
6928 (*string_pointer) = scan_string;
6929 return (1);
6931 c = (*scan_string++);
6932 if (c == 0)
6934 /* Tweak line_number to compensate for fact that
6935 we gobbled the whole line before coming here. */
6936 line_number -= 1;
6937 line_error (_("Missing `}' in %cdef arg"), COMMAND_PREFIX);
6938 line_number += 1;
6939 (*string_pointer) = (scan_string - 1);
6940 return (0);
6942 if (c == '{')
6943 level += 1;
6944 if (c == '}')
6945 level -= 1;
6949 /* Return a list of tokens from the contents of `string'.
6950 Commands and brace-delimited groups count as single tokens.
6951 Contiguous whitespace characters are converted to a token
6952 consisting of a single space. */
6953 char **
6954 args_from_string (string)
6955 char *string;
6957 struct token_accumulator accumulator;
6958 register char *scan_string = string;
6959 char *token_start, *token_end;
6961 initialize_token_accumulator (&accumulator);
6963 while ((*scan_string) != 0)
6965 /* Replace arbitrary whitespace by a single space. */
6966 if (whitespace (*scan_string))
6968 scan_string += 1;
6969 while (whitespace (*scan_string))
6970 scan_string += 1;
6971 accumulate_token ((&accumulator), (xstrdup (" ")));
6972 continue;
6975 /* Commands count as single tokens. */
6976 if ((*scan_string) == COMMAND_PREFIX)
6978 token_start = scan_string;
6979 scan_string += 1;
6980 if (self_delimiting (*scan_string))
6981 scan_string += 1;
6982 else
6984 register int c;
6985 while (1)
6987 c = *scan_string++;
6989 if ((c == 0) || (c == '{') || (whitespace (c)))
6991 scan_string -= 1;
6992 break;
6996 if (*scan_string == '{')
6998 char *s = scan_string;
6999 (void) scan_group_in_string (&s);
7000 scan_string = s;
7003 token_end = scan_string;
7006 /* Parentheses and brackets are self-delimiting. */
7007 else if (DEFUN_SELF_DELIMITING (*scan_string))
7009 token_start = scan_string;
7010 scan_string += 1;
7011 token_end = scan_string;
7014 /* Open brace introduces a group that is a single token. */
7015 else if (*scan_string == '{')
7017 char *s = scan_string;
7018 int balanced = scan_group_in_string (&s);
7020 token_start = scan_string + 1;
7021 scan_string = s;
7022 token_end = balanced ? (scan_string - 1) : scan_string;
7025 /* Otherwise a token is delimited by whitespace, parentheses,
7026 brackets, or braces. A token is also ended by a command. */
7027 else
7029 token_start = scan_string;
7031 while (1)
7033 register int c;
7035 c = *scan_string++;
7037 /* Do not back up if we're looking at a }; since the only
7038 valid }'s are those matched with {'s, we want to give
7039 an error. If we back up, we go into an infinite loop. */
7040 if (!c || whitespace (c) || DEFUN_SELF_DELIMITING (c)
7041 || c == '{')
7043 scan_string--;
7044 break;
7047 /* If we encounter a command embedded within a token,
7048 then end the token. */
7049 if (c == COMMAND_PREFIX)
7051 scan_string--;
7052 break;
7055 token_end = scan_string;
7058 accumulate_token
7059 (&accumulator, copy_substring (token_start, token_end));
7061 accumulate_token (&accumulator, NULL);
7062 return (accumulator.tokens);
7065 void
7066 process_defun_args (defun_args, auto_var_p)
7067 char **defun_args;
7068 int auto_var_p;
7070 int pending_space = 0;
7072 while (1)
7074 char *defun_arg = *defun_args++;
7076 if (defun_arg == NULL)
7077 break;
7079 if (defun_arg[0] == ' ')
7081 pending_space = 1;
7082 continue;
7085 if (pending_space)
7087 add_char (' ');
7088 pending_space = 0;
7091 if (DEFUN_SELF_DELIMITING (defun_arg[0]))
7092 add_char (defun_arg[0]);
7093 else if (defun_arg[0] == '&')
7094 add_word (defun_arg);
7095 else if (defun_arg[0] == COMMAND_PREFIX)
7096 execute_string ("%s", defun_arg);
7097 else if (auto_var_p)
7098 execute_string ("%cvar{%s}", COMMAND_PREFIX, defun_arg);
7099 else
7100 add_word (defun_arg);
7104 char *
7105 next_nonwhite_defun_arg (arg_pointer)
7106 char ***arg_pointer;
7108 char **scan = (*arg_pointer);
7109 char *arg = (*scan++);
7111 if ((arg != 0) && (*arg == ' '))
7112 arg = *scan++;
7114 if (arg == 0)
7115 scan -= 1;
7117 *arg_pointer = scan;
7119 return ((arg == 0) ? "" : arg);
7122 /* Make the defun type insertion.
7123 TYPE says which insertion this is.
7124 X_P, if nonzero, says not to start a new insertion. */
7125 void
7126 defun_internal (type, x_p)
7127 enum insertion_type type;
7128 int x_p;
7130 enum insertion_type base_type;
7131 char **defun_args, **scan_args;
7132 char *category, *defined_name, *type_name, *type_name2;
7135 char *line;
7136 get_rest_of_line (&line);
7137 defun_args = (args_from_string (line));
7138 free (line);
7141 scan_args = defun_args;
7143 switch (type)
7145 case defun:
7146 category = _("Function");
7147 base_type = deffn;
7148 break;
7149 case defmac:
7150 category = _("Macro");
7151 base_type = deffn;
7152 break;
7153 case defspec:
7154 category = _("Special Form");
7155 base_type = deffn;
7156 break;
7157 case defvar:
7158 category = _("Variable");
7159 base_type = defvr;
7160 break;
7161 case defopt:
7162 category = _("User Option");
7163 base_type = defvr;
7164 break;
7165 case deftypefun:
7166 category = _("Function");
7167 base_type = deftypefn;
7168 break;
7169 case deftypevar:
7170 category = _("Variable");
7171 base_type = deftypevr;
7172 break;
7173 case defivar:
7174 category = _("Instance Variable");
7175 base_type = defcv;
7176 break;
7177 case defmethod:
7178 category = _("Method");
7179 base_type = defop;
7180 break;
7181 case deftypemethod:
7182 category = _("Method");
7183 base_type = deftypemethod;
7184 break;
7185 default:
7186 category = next_nonwhite_defun_arg (&scan_args);
7187 base_type = type;
7188 break;
7191 if ((base_type == deftypefn)
7192 || (base_type == deftypevr)
7193 || (base_type == defcv)
7194 || (base_type == defop)
7195 || (base_type == deftypemethod))
7196 type_name = next_nonwhite_defun_arg (&scan_args);
7198 if (base_type == deftypemethod)
7199 type_name2 = next_nonwhite_defun_arg (&scan_args);
7201 defined_name = next_nonwhite_defun_arg (&scan_args);
7203 /* This hack exists solely for the purposes of formatting the texinfo
7204 manual. I couldn't think of a better way. The token might be
7205 a simple @@ followed immediately by more text. If this is the case,
7206 then the next defun arg is part of this one, and we should concatenate
7207 them. */
7208 if (*scan_args && **scan_args && !whitespace (**scan_args) &&
7209 (strcmp (defined_name, "@@") == 0))
7211 char *tem = (char *)xmalloc (3 + strlen (scan_args[0]));
7213 sprintf (tem, "@@%s", scan_args[0]);
7215 free (scan_args[0]);
7216 scan_args[0] = tem;
7217 scan_args++;
7218 defined_name = tem;
7221 if (!x_p)
7222 begin_insertion (type);
7224 /* Write the definition header line.
7225 This should start at the normal indentation. */
7226 current_indent -= default_indentation_increment;
7227 start_paragraph ();
7229 switch (base_type)
7231 case deffn:
7232 case defvr:
7233 case deftp:
7234 execute_string (" -- %s: %s", category, defined_name);
7235 break;
7236 case deftypefn:
7237 case deftypevr:
7238 execute_string (" -- %s: %s %s", category, type_name, defined_name);
7239 break;
7240 case defcv:
7241 execute_string (" -- %s of %s: %s", category, type_name, defined_name);
7242 break;
7243 case defop:
7244 execute_string (" -- %s on %s: %s", category, type_name, defined_name);
7245 break;
7246 case deftypemethod:
7247 execute_string (" -- %s on %s: %s %s", category, type_name, type_name2,
7248 defined_name);
7249 break;
7251 current_indent += default_indentation_increment;
7253 /* Now process the function arguments, if any.
7254 If these carry onto the next line, they should be indented by two
7255 increments to distinguish them from the body of the definition,
7256 which is indented by one increment. */
7257 current_indent += default_indentation_increment;
7259 switch (base_type)
7261 case deffn:
7262 case defop:
7263 process_defun_args (scan_args, 1);
7264 break;
7266 /* Through Makeinfo 1.67 we processed remaining args only for deftp,
7267 deftypefn, and deftypemethod. But the libc manual, for example,
7268 needs to say:
7269 @deftypevar {char *} tzname[2]
7270 And simply allowing the extra text seems far simpler than trying
7271 to invent yet more defn commands. In any case, we should either
7272 output it or give an error, not silently ignore it. */
7273 default:
7274 process_defun_args (scan_args, 0);
7275 break;
7277 current_indent -= default_indentation_increment;
7278 close_single_paragraph ();
7280 /* Make an entry in the appropriate index. */
7281 switch (base_type)
7283 case deffn:
7284 case deftypefn:
7285 execute_string ("%cfindex %s\n", COMMAND_PREFIX, defined_name);
7286 break;
7287 case defvr:
7288 case deftypevr:
7289 case defcv:
7290 execute_string ("%cvindex %s\n", COMMAND_PREFIX, defined_name);
7291 break;
7292 case defop:
7293 case deftypemethod:
7294 execute_string ("%cfindex %s on %s\n",
7295 COMMAND_PREFIX, defined_name, type_name);
7296 break;
7297 case deftp:
7298 execute_string ("%ctindex %s\n", COMMAND_PREFIX, defined_name);
7299 break;
7302 /* Deallocate the token list. */
7303 scan_args = defun_args;
7304 while (1)
7306 char * arg = (*scan_args++);
7307 if (arg == NULL)
7308 break;
7309 free (arg);
7311 free (defun_args);
7314 /* Add an entry for a function, macro, special form, variable, or option.
7315 If the name of the calling command ends in `x', then this is an extra
7316 entry included in the body of an insertion of the same type. */
7317 void
7318 cm_defun ()
7320 int x_p;
7321 enum insertion_type type;
7322 char *temp = xstrdup (command);
7324 x_p = (command[strlen (command) - 1] == 'x');
7326 if (x_p)
7327 temp[strlen (temp) - 1] = 0;
7329 type = find_type_from_name (temp);
7330 free (temp);
7332 /* If we are adding to an already existing insertion, then make sure
7333 that we are already in an insertion of type TYPE. */
7334 if (x_p &&
7335 (!insertion_level || insertion_stack->insertion != type))
7337 line_error (_("Must be in a `%s' insertion in order to use `%s'x"),
7338 command, command);
7339 discard_until ("\n");
7340 return;
7343 defun_internal (type, x_p);
7346 /* **************************************************************** */
7347 /* */
7348 /* Other Random Commands */
7349 /* */
7350 /* **************************************************************** */
7352 /* This says to inhibit the indentation of the next paragraph, but
7353 not of following paragraphs. */
7354 void
7355 cm_noindent ()
7357 if (!inhibit_paragraph_indentation)
7358 inhibit_paragraph_indentation = -1;
7361 /* I don't know exactly what to do with this. Should I allow
7362 someone to switch filenames in the middle of output? Since the
7363 file could be partially written, this doesn't seem to make sense.
7364 Another option: ignore it, since they don't *really* want to
7365 switch files. Finally, complain, or at least warn. */
7366 void
7367 cm_setfilename ()
7369 char *filename;
7370 get_rest_of_line (&filename);
7371 /* warning ("`@%s %s' encountered and ignored", command, filename); */
7372 free (filename);
7375 void
7376 cm_ignore_line ()
7378 discard_until ("\n");
7381 /* @br can be immediately followed by `{}', so we have to read those here.
7382 It should simply close the paragraph. */
7383 void
7384 cm_br ()
7386 if (looking_at ("{}"))
7387 input_text_offset += 2;
7389 if (curchar () == '\n')
7391 input_text_offset++;
7392 line_number++;
7395 close_paragraph ();
7398 /* Insert the number of blank lines passed as argument. */
7399 void
7400 cm_sp ()
7402 int lines;
7403 char *line;
7405 get_rest_of_line (&line);
7407 if (sscanf (line, "%d", &lines) != 1)
7409 line_error (_("%csp requires a positive numeric argument"), COMMAND_PREFIX);
7411 else
7413 if (lines < 0)
7414 lines = 0;
7416 while (lines--)
7417 add_char ('\n');
7419 free (line);
7422 /* @dircategory LINE outputs INFO-DIR-SECTION LINE,
7423 but not if --no-headers. */
7425 void
7426 cm_dircategory ()
7428 char *line;
7430 get_rest_of_line (&line);;
7432 if (!no_headers)
7434 insert_string ("INFO-DIR-SECTION ");
7435 insert_string (line);
7436 insert ('\n');
7439 free (line);
7442 /* Start a new line with just this text on it.
7443 Then center the line of text.
7444 This always ends the current paragraph. */
7445 void
7446 cm_center ()
7448 register int i, start, length;
7449 int fudge_factor = 1;
7450 unsigned char *line;
7452 close_paragraph ();
7453 filling_enabled = indented_fill = 0;
7454 cm_noindent ();
7455 start = output_paragraph_offset;
7456 inhibit_output_flushing ();
7457 get_rest_of_line ((char **)&line);
7458 execute_string ("%s", (char *)line);
7459 free (line);
7460 uninhibit_output_flushing ();
7462 i = output_paragraph_offset - 1;
7463 while (i > (start - 1) && output_paragraph[i] == '\n')
7464 i--;
7466 output_paragraph_offset = ++i;
7467 length = output_paragraph_offset - start;
7469 if (length < (fill_column - fudge_factor))
7471 line = (unsigned char *)xmalloc (1 + length);
7472 memcpy (line, (char *)(output_paragraph + start), length);
7474 i = (fill_column - fudge_factor - length) / 2;
7475 output_paragraph_offset = start;
7477 while (i--)
7478 insert (' ');
7480 for (i = 0; i < length; i++)
7481 insert (line[i]);
7483 free (line);
7486 insert ('\n');
7487 close_paragraph ();
7488 filling_enabled = 1;
7491 /* Show what an expression returns. */
7492 void
7493 cm_result (arg)
7494 int arg;
7496 if (arg == END)
7497 add_word ("=>");
7500 /* What an expression expands to. */
7501 void
7502 cm_expansion (arg)
7503 int arg;
7505 if (arg == END)
7506 add_word ("==>");
7509 /* Indicates two expressions are equivalent. */
7510 void
7511 cm_equiv (arg)
7512 int arg;
7514 if (arg == END)
7515 add_word ("==");
7518 /* What an expression may print. */
7519 void
7520 cm_print (arg)
7521 int arg;
7523 if (arg == END)
7524 add_word ("-|");
7527 /* An error signaled. */
7528 void
7529 cm_error (arg)
7530 int arg;
7532 if (arg == END)
7533 add_word ("error-->");
7536 /* The location of point in an example of a buffer. */
7537 void
7538 cm_point (arg)
7539 int arg;
7541 if (arg == END)
7542 add_word ("-!-");
7545 /* Start a new line with just this text on it.
7546 The text is outdented one level if possible. */
7547 void
7548 cm_exdent ()
7550 char *line;
7551 int i = current_indent;
7553 if (current_indent)
7554 current_indent -= default_indentation_increment;
7556 get_rest_of_line (&line);
7557 close_single_paragraph ();
7558 execute_string ("%s", line);
7559 current_indent = i;
7560 free (line);
7561 close_single_paragraph ();
7565 /* Remember this file, and move onto the next. */
7566 void
7567 cm_include ()
7569 char *filename;
7571 #if defined (HAVE_MACROS)
7572 if (macro_expansion_output_stream && !executing_string)
7573 me_append_before_this_command ();
7574 #endif /* HAVE_MACROS */
7576 close_paragraph ();
7577 get_rest_of_line (&filename);
7579 #if defined (HAVE_MACROS)
7580 if (macro_expansion_output_stream && !executing_string)
7581 remember_itext (input_text, input_text_offset);
7582 #endif /* HAVE_MACROS */
7584 pushfile ();
7586 /* In verbose mode we print info about including another file. */
7587 if (verbose_mode)
7589 register int i = 0;
7590 register FSTACK *stack = filestack;
7592 for (i = 0, stack = filestack; stack; stack = stack->next, i++);
7594 i *= 2;
7596 printf ("%*s", i, "");
7597 printf ("%c%s %s\n", COMMAND_PREFIX, command, filename);
7598 fflush (stdout);
7601 if (!find_and_load (filename))
7603 extern int errno;
7605 popfile ();
7606 line_number--;
7608 /* Cannot "@include foo", in line 5 of "/wh/bar". */
7609 line_error ("%c%s %s: %s", COMMAND_PREFIX, command, filename,
7610 strerror (errno));
7612 free (filename);
7613 return;
7615 else
7617 #if defined (HAVE_MACROS)
7618 if (macro_expansion_output_stream && !executing_string)
7619 remember_itext (input_text, input_text_offset);
7620 #endif /* HAVE_MACROS */
7621 reader_loop ();
7623 free (filename);
7624 popfile ();
7627 /* The other side of a malformed expression. */
7628 void
7629 misplaced_brace ()
7631 line_error (_("Misplaced %c"), '}');
7634 /* Signals end of processing. Easy to make this happen. */
7635 void
7636 cm_bye ()
7638 input_text_offset = size_of_input_text;
7641 /* Set the paragraph indentation variable to the value specified in STRING.
7642 Values can be:
7643 `asis': Don't change existing indentation.
7644 `none': Remove existing indentation.
7645 NUM: Indent NUM spaces at the starts of paragraphs.
7646 If NUM is zero, we assume `none'.
7647 Returns 0 if successful, or nonzero if STRING isn't one of the above. */
7649 set_paragraph_indent (string)
7650 char *string;
7652 if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
7653 paragraph_start_indent = 0;
7654 else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
7655 paragraph_start_indent = -1;
7656 else
7658 if (sscanf (string, "%d", &paragraph_start_indent) != 1)
7659 return (-1);
7660 else
7662 if (paragraph_start_indent == 0)
7663 paragraph_start_indent = -1;
7666 return (0);
7669 void
7670 cm_paragraphindent ()
7672 char *arg;
7674 get_rest_of_line (&arg);
7675 if (set_paragraph_indent (arg) != 0)
7676 line_error (_("Bad argument to %c%s"), COMMAND_PREFIX, command);
7678 free (arg);
7681 /* **************************************************************** */
7682 /* */
7683 /* Indexing Stuff */
7684 /* */
7685 /* **************************************************************** */
7688 /* An index element... */
7689 typedef struct index_elt
7691 struct index_elt *next;
7692 char *entry; /* The index entry itself. */
7693 char *node; /* The node from whence it came. */
7694 int code; /* Nonzero means add `@code{...}' when
7695 printing this element. */
7696 int defining_line; /* Line number where this entry was written. */
7697 char *defining_file; /* Source file for defining_line. */
7698 } INDEX_ELT;
7700 /* A list of short-names for each index.
7702 There are two indices into the the_indices array.
7704 * read_index is the index that points to the list of index
7705 entries that we will find if we ask for the list of entries for
7706 this name.
7708 * write_index is the index that points to the list of index entries
7709 that we will add new entries to.
7711 Initially, read_index and write index are the same, but the
7712 @syncodeindex and @synindex commands can change the list we add
7713 entries to.
7715 For example, after the commands
7717 @cindex foo
7718 @defindex ii
7719 @synindex cp ii
7720 @cindex bar
7722 the cp index will contain the entry `foo', and the new ii
7723 index will contain the entry `bar'. This is consistent with the
7724 way texinfo.tex handles the same situation.
7726 In addition, for each index, it is remembered whether that index is
7727 a code index or not. Code indices have @code{} inserted around the
7728 first word when they are printed with printindex. */
7729 typedef struct
7731 char *name;
7732 int read_index; /* index entries for `name' */
7733 int write_index; /* store index entries here, @synindex can change it */
7734 int code;
7735 } INDEX_ALIST;
7737 INDEX_ALIST **name_index_alist = (INDEX_ALIST **) NULL;
7739 /* An array of pointers. Each one is for a different index. The
7740 "synindex" command changes which array slot is pointed to by a
7741 given "index". */
7742 INDEX_ELT **the_indices = (INDEX_ELT **) NULL;
7744 /* The number of defined indices. */
7745 int defined_indices = 0;
7747 void
7748 init_indices ()
7750 int i;
7752 /* Create the default data structures. */
7754 /* Initialize data space. */
7755 if (!the_indices)
7757 the_indices = (INDEX_ELT **) xmalloc ((1 + defined_indices) *
7758 sizeof (INDEX_ELT *));
7759 the_indices[defined_indices] = (INDEX_ELT *) NULL;
7761 name_index_alist = (INDEX_ALIST **) xmalloc ((1 + defined_indices) *
7762 sizeof (INDEX_ALIST *));
7763 name_index_alist[defined_indices] = (INDEX_ALIST *) NULL;
7766 /* If there were existing indices, get rid of them now. */
7767 for (i = 0; i < defined_indices; i++)
7769 undefindex (name_index_alist[i]->name);
7770 if (name_index_alist[i])
7771 { /* Suppose we're called with two input files, and the first
7772 does a @synindex pg cp. Then, when we get here to start
7773 the second file, the "pg" element won't get freed by
7774 undefindex (because it's pointing to "cp"). So free it
7775 here; otherwise, when we try to define the pg index again
7776 just below, it will still point to cp. */
7777 free (name_index_alist[i]->name);
7778 free (name_index_alist[i]);
7779 name_index_alist[i] = (INDEX_ALIST *) NULL;
7783 /* Add the default indices. */
7784 top_defindex ("cp", 0); /* cp is the only non-code index. */
7785 top_defindex ("fn", 1);
7786 top_defindex ("ky", 1);
7787 top_defindex ("pg", 1);
7788 top_defindex ("tp", 1);
7789 top_defindex ("vr", 1);
7792 /* Find which element in the known list of indices has this name.
7793 Returns -1 if NAME isn't found. */
7795 find_index_offset (name)
7796 char *name;
7798 register int i;
7799 for (i = 0; i < defined_indices; i++)
7800 if (name_index_alist[i] &&
7801 strcmp (name, name_index_alist[i]->name) == 0)
7802 return (i);
7803 return (-1);
7806 /* Return a pointer to the entry of (name . index) for this name.
7807 Return NULL if the index doesn't exist. */
7808 INDEX_ALIST *
7809 find_index (name)
7810 char *name;
7812 int offset = find_index_offset (name);
7813 if (offset > -1)
7814 return (name_index_alist[offset]);
7815 else
7816 return ((INDEX_ALIST *) NULL);
7819 /* Given an index name, return the offset in the_indices of this index,
7820 or -1 if there is no such index. */
7822 translate_index (name)
7823 char *name;
7825 INDEX_ALIST *which = find_index (name);
7827 if (which)
7828 return (which->read_index);
7829 else
7830 return (-1);
7833 /* Return the index list which belongs to NAME. */
7834 INDEX_ELT *
7835 index_list (name)
7836 char *name;
7838 int which = translate_index (name);
7839 if (which < 0)
7840 return ((INDEX_ELT *) -1);
7841 else
7842 return (the_indices[which]);
7845 /* Please release me, let me go... */
7846 void
7847 free_index (index)
7848 INDEX_ELT *index;
7850 INDEX_ELT *temp;
7852 while ((temp = index) != (INDEX_ELT *) NULL)
7854 free (temp->entry);
7855 /* Do not free the node, because we already freed the tag table,
7856 which freed all the node names. */
7857 /* free (temp->node); */
7858 index = index->next;
7859 free (temp);
7863 /* Flush an index by name. This will delete the list of entries that
7864 would be written by a @printindex command for this index. */
7865 void
7866 undefindex (name)
7867 char *name;
7869 int i;
7870 int which = find_index_offset (name);
7872 /* The index might have already been freed if this was the target of
7873 an @synindex. */
7874 if (which < 0 || !name_index_alist[which])
7875 return;
7877 i = name_index_alist[which]->read_index;
7879 free_index (the_indices[i]);
7880 the_indices[i] = (INDEX_ELT *) NULL;
7882 free (name_index_alist[which]->name);
7883 free (name_index_alist[which]);
7884 name_index_alist[which] = (INDEX_ALIST *) NULL;
7887 /* Define an index known as NAME. We assign the slot number.
7888 CODE if Nonzero says to make this a code index. */
7889 void
7890 defindex (name, code)
7891 char *name;
7892 int code;
7894 register int i, slot;
7896 /* If it already exists, flush it. */
7897 undefindex (name);
7899 /* Try to find an empty slot. */
7900 slot = -1;
7901 for (i = 0; i < defined_indices; i++)
7902 if (!name_index_alist[i])
7904 slot = i;
7905 break;
7908 if (slot < 0)
7910 /* No such luck. Make space for another index. */
7911 slot = defined_indices;
7912 defined_indices++;
7914 name_index_alist = (INDEX_ALIST **)
7915 xrealloc ((char *)name_index_alist,
7916 (1 + defined_indices) * sizeof (INDEX_ALIST *));
7917 the_indices = (INDEX_ELT **)
7918 xrealloc ((char *)the_indices,
7919 (1 + defined_indices) * sizeof (INDEX_ELT *));
7922 /* We have a slot. Start assigning. */
7923 name_index_alist[slot] = (INDEX_ALIST *) xmalloc (sizeof (INDEX_ALIST));
7924 name_index_alist[slot]->name = xstrdup (name);
7925 name_index_alist[slot]->read_index = slot;
7926 name_index_alist[slot]->write_index = slot;
7927 name_index_alist[slot]->code = code;
7929 the_indices[slot] = (INDEX_ELT *) NULL;
7932 /* Add the arguments to the current index command to the index NAME. */
7933 void
7934 index_add_arg (name)
7935 char *name;
7937 int which;
7938 char *index_entry;
7939 INDEX_ALIST *tem;
7941 tem = find_index (name);
7943 which = tem ? tem->write_index : -1;
7945 #if defined (HAVE_MACROS)
7946 if (macro_expansion_output_stream && !executing_string)
7947 append_to_expansion_output (input_text_offset + 1);
7948 #endif /* HAVE_MACROS */
7950 get_rest_of_line (&index_entry);
7951 ignore_blank_line ();
7953 #if defined (HAVE_MACROS)
7954 if (macro_expansion_output_stream && !executing_string)
7956 int op_orig;
7958 remember_itext (input_text, input_text_offset);
7959 op_orig = output_paragraph_offset;
7960 me_execute_string (index_entry);
7961 me_execute_string ("\n");
7962 output_paragraph_offset = op_orig;
7964 #endif /* HAVE_MACROS */
7966 if (which < 0)
7968 line_error (_("Unknown index `%s'"), name);
7969 free (index_entry);
7971 else
7973 INDEX_ELT *new = (INDEX_ELT *) xmalloc (sizeof (INDEX_ELT));
7974 new->next = the_indices[which];
7975 new->entry = index_entry;
7976 new->node = current_node;
7977 new->code = tem->code;
7978 new->defining_line = line_number - 1;
7979 new->defining_file = input_filename;
7980 the_indices[which] = new;
7984 #define INDEX_COMMAND_SUFFIX "index"
7986 /* The function which user defined index commands call. */
7987 void
7988 gen_index ()
7990 char *name = xstrdup (command);
7991 if (strlen (name) >= strlen ("index"))
7992 name[strlen (name) - strlen ("index")] = 0;
7993 index_add_arg (name);
7994 free (name);
7997 void
7998 top_defindex (name, code)
7999 char *name;
8000 int code;
8002 char *temp;
8004 temp = (char *) xmalloc (1 + strlen (name) + strlen ("index"));
8005 sprintf (temp, "%sindex", name);
8006 define_user_command (temp, gen_index, 0);
8007 defindex (name, code);
8008 free (temp);
8011 /* Define a new index command. Arg is name of index. */
8012 void
8013 cm_defindex ()
8015 gen_defindex (0);
8018 void
8019 cm_defcodeindex ()
8021 gen_defindex (1);
8024 void
8025 gen_defindex (code)
8026 int code;
8028 char *name;
8029 get_rest_of_line (&name);
8031 if (find_index (name))
8033 line_error (_("Index `%s' already exists"), name);
8034 free (name);
8035 return;
8037 else
8039 char *temp = (char *) alloca (1 + strlen (name) + strlen ("index"));
8040 sprintf (temp, "%sindex", name);
8041 define_user_command (temp, gen_index, 0);
8042 defindex (name, code);
8043 free (name);
8047 /* Expects 2 args, on the same line. Both are index abbreviations.
8048 Make the first one be a synonym for the second one, i.e. make the
8049 first one have the same index as the second one. */
8050 void
8051 cm_synindex ()
8053 int source, target;
8054 char *abbrev1, *abbrev2;
8056 skip_whitespace ();
8057 get_until_in_line (0, " ", &abbrev1);
8058 target = find_index_offset (abbrev1);
8059 skip_whitespace ();
8060 get_until_in_line (0, " ", &abbrev2);
8061 source = find_index_offset (abbrev2);
8062 if (source < 0 || target < 0)
8064 line_error (_("Unknown index `%s' and/or `%s' in @synindex"),
8065 abbrev1, abbrev2);
8067 else
8069 name_index_alist[target]->write_index
8070 = name_index_alist[source]->write_index;
8073 free (abbrev1);
8074 free (abbrev2);
8077 void
8078 cm_pindex () /* Pinhead index. */
8080 index_add_arg ("pg");
8083 void
8084 cm_vindex () /* Variable index. */
8086 index_add_arg ("vr");
8089 void
8090 cm_kindex () /* Key index. */
8092 index_add_arg ("ky");
8095 void
8096 cm_cindex () /* Concept index. */
8098 index_add_arg ("cp");
8101 void
8102 cm_findex () /* Function index. */
8104 index_add_arg ("fn");
8107 void
8108 cm_tindex () /* Data Type index. */
8110 index_add_arg ("tp");
8113 /* Sorting the index. */
8115 index_element_compare (element1, element2)
8116 INDEX_ELT **element1, **element2;
8118 return (strcasecmp ((*element1)->entry, (*element2)->entry));
8121 /* Force all index entries to be unique. */
8122 void
8123 make_index_entries_unique (array, count)
8124 INDEX_ELT **array;
8125 int count;
8127 register int i, j;
8128 INDEX_ELT **copy;
8129 int counter = 1;
8131 copy = (INDEX_ELT **)xmalloc ((1 + count) * sizeof (INDEX_ELT *));
8133 for (i = 0, j = 0; i < count; i++)
8135 if ((i == (count - 1)) ||
8136 (array[i]->node != array[i + 1]->node) ||
8137 (strcmp (array[i]->entry, array[i + 1]->entry) != 0))
8138 copy[j++] = array[i];
8139 else
8141 free (array[i]->entry);
8142 free (array[i]);
8145 copy[j] = (INDEX_ELT *)NULL;
8147 /* Now COPY contains only unique entries. Duplicated entries in the
8148 original array have been freed. Replace the current array with
8149 the copy, fixing the NEXT pointers. */
8150 for (i = 0; copy[i] != (INDEX_ELT *)NULL; i++)
8153 copy[i]->next = copy[i + 1];
8155 /* Fix entry names which are the same. They point to different nodes,
8156 so we make the entry name unique. */
8157 if ((copy[i + 1] != (INDEX_ELT *)NULL) &&
8158 (strcmp (copy[i]->entry, copy[i + 1]->entry) == 0))
8160 char *new_entry_name;
8162 new_entry_name = (char *)xmalloc (10 + strlen (copy[i]->entry));
8163 sprintf (new_entry_name, "%s <%d>", copy[i]->entry, counter);
8164 free (copy[i]->entry);
8165 copy[i]->entry = new_entry_name;
8166 counter++;
8168 else
8169 counter = 1;
8171 array[i] = copy[i];
8173 array[i] = (INDEX_ELT *)NULL;
8175 /* Free the storage used only by COPY. */
8176 free (copy);
8179 /* Sort the index passed in INDEX, returning an array of
8180 pointers to elements. The array is terminated with a NULL
8181 pointer. We call qsort because it's supposed to be fast.
8182 I think this looks bad. */
8183 INDEX_ELT **
8184 sort_index (index)
8185 INDEX_ELT *index;
8187 INDEX_ELT **array;
8188 INDEX_ELT *temp = index;
8189 int count = 0;
8190 int save_line_number = line_number;
8191 char *save_input_filename = input_filename;
8193 while (temp != (INDEX_ELT *) NULL)
8195 count++;
8196 temp = temp->next;
8199 /* We have the length. Make an array. */
8201 array = (INDEX_ELT **) xmalloc ((count + 1) * sizeof (INDEX_ELT *));
8202 count = 0;
8203 temp = index;
8205 while (temp != (INDEX_ELT *) NULL)
8207 array[count++] = temp;
8209 /* Set line number and input filename to the source line for this
8210 index entry, as this expansion finds any errors. */
8211 line_number = array[count - 1]->defining_line;
8212 input_filename = array[count - 1]->defining_file;
8214 /* If this particular entry should be printed as a "code" index,
8215 then wrap the entry with "@code{...}". */
8216 array[count - 1]->entry = expansion (temp->entry, index->code);
8218 temp = temp->next;
8220 array[count] = (INDEX_ELT *) NULL; /* terminate the array. */
8221 line_number = save_line_number;
8222 input_filename = save_input_filename;
8224 /* Sort the array. */
8225 qsort (array, count, sizeof (INDEX_ELT *), index_element_compare);
8226 make_index_entries_unique (array, count);
8227 return (array);
8230 /* Nonzero means that we are in the middle of printing an index. */
8231 int printing_index = 0;
8233 /* Takes one arg, a short name of an index to print.
8234 Outputs a menu of the sorted elements of the index. */
8235 void
8236 cm_printindex ()
8238 int item;
8239 INDEX_ELT *index;
8240 INDEX_ELT **array;
8241 char *index_name;
8242 unsigned line_length;
8243 char *line;
8244 int saved_inhibit_paragraph_indentation = inhibit_paragraph_indentation;
8245 int saved_filling_enabled = filling_enabled;
8247 close_paragraph ();
8248 get_rest_of_line (&index_name);
8250 index = index_list (index_name);
8251 if (index == (INDEX_ELT *)-1)
8253 line_error (_("Unknown index `%s' in @printindex"), index_name);
8254 free (index_name);
8255 return;
8257 else
8258 free (index_name);
8260 /* Do this before sorting, so execute_string in index_element_compare
8261 will give the same results as when we actually print. */
8262 printing_index = 1;
8263 filling_enabled = 0;
8264 inhibit_paragraph_indentation = 1;
8265 array = sort_index (index);
8267 close_paragraph ();
8268 add_word (_("* Menu:\n\n"));
8270 #if defined (HAVE_MACROS)
8271 me_inhibit_expansion++;
8272 #endif /* HAVE_MACROS */
8274 /* This will probably be enough. */
8275 line_length = 100;
8276 line = xmalloc (line_length);
8278 for (item = 0; (index = array[item]); item++)
8280 /* A pathological document might have an index entry outside of any
8281 node. Don't crash. Perhaps should warn. */
8282 char *index_node = index->node ? index->node : "(none)";
8283 unsigned new_length = strlen (index->entry);
8285 if (new_length < 37) /* minimum length used below */
8286 new_length = 37;
8287 new_length += strlen (index_node) + 7; /* * : .\n\0 */
8289 if (new_length > line_length)
8291 line_length = new_length;
8292 line = xrealloc (line, line_length);
8295 /* Print the entry, nicely formatted. We've already expanded any
8296 commands, including any implicit @code. Thus, can't call
8297 execute_string, since @@ has turned into @. */
8298 sprintf (line, "* %-37s %s.\n", index->entry, index_node);
8299 line[2 + strlen (index->entry)] = ':';
8300 insert_string (line);
8302 /* Previous `output_paragraph' from growing to the size of the
8303 whole index. */
8304 flush_output ();
8307 free (line);
8309 #if defined (HAVE_MACROS)
8310 me_inhibit_expansion--;
8311 #endif /* HAVE_MACROS */
8313 printing_index = 0;
8314 free (array);
8315 close_single_paragraph ();
8316 filling_enabled = saved_filling_enabled;
8317 inhibit_paragraph_indentation = saved_inhibit_paragraph_indentation;
8320 /* User-defined commands, which happens only from user-defined indexes. */
8322 void
8323 define_user_command (name, proc, needs_braces_p)
8324 char *name;
8325 COMMAND_FUNCTION *proc;
8326 int needs_braces_p;
8328 int slot = user_command_array_len;
8329 user_command_array_len++;
8331 if (!user_command_array)
8332 user_command_array = (COMMAND **) xmalloc (1 * sizeof (COMMAND *));
8334 user_command_array = (COMMAND **) xrealloc (user_command_array,
8335 (1 + user_command_array_len) *
8336 sizeof (COMMAND *));
8338 user_command_array[slot] = (COMMAND *) xmalloc (sizeof (COMMAND));
8339 user_command_array[slot]->name = xstrdup (name);
8340 user_command_array[slot]->proc = proc;
8341 user_command_array[slot]->argument_in_braces = needs_braces_p;
8344 /* Some support for footnotes. */
8346 /* Footnotes are a new construct in Info. We don't know the best method
8347 of implementing them for sure, so we present two possiblities.
8349 SeparateNode:
8350 Make them look like followed references, with the reference
8351 destinations in a makeinfo manufactured node or,
8353 EndNode:
8354 Make them appear at the bottom of the node that they originally
8355 appeared in. */
8356 #define SeparateNode 0
8357 #define EndNode 1
8359 int footnote_style = EndNode;
8360 int first_footnote_this_node = 1;
8361 int footnote_count = 0;
8363 /* Set the footnote style based on he style identifier in STRING. */
8365 set_footnote_style (string)
8366 char *string;
8368 if ((strcasecmp (string, "separate") == 0) ||
8369 (strcasecmp (string, "MN") == 0))
8370 footnote_style = SeparateNode;
8371 else if ((strcasecmp (string, "end") == 0) ||
8372 (strcasecmp (string, "EN") == 0))
8373 footnote_style = EndNode;
8374 else
8375 return (-1);
8377 return (0);
8380 void
8381 cm_footnotestyle ()
8383 char *arg;
8385 get_rest_of_line (&arg);
8387 /* If set on command line, do not change the footnote style. */
8388 if (!footnote_style_preset && set_footnote_style (arg) != 0)
8389 line_error ("Bad argument to %c%s", COMMAND_PREFIX, command);
8391 free (arg);
8394 typedef struct fn
8396 struct fn *next;
8397 char *marker;
8398 char *note;
8399 } FN;
8401 FN *pending_notes = (FN *) NULL;
8403 /* A method for remembering footnotes. Note that this list gets output
8404 at the end of the current node. */
8405 void
8406 remember_note (marker, note)
8407 char *marker, *note;
8409 FN *temp = (FN *) xmalloc (sizeof (FN));
8411 temp->marker = xstrdup (marker);
8412 temp->note = xstrdup (note);
8413 temp->next = pending_notes;
8414 pending_notes = temp;
8415 footnote_count++;
8418 /* How to get rid of existing footnotes. */
8419 void
8420 free_pending_notes ()
8422 FN *temp;
8424 while ((temp = pending_notes) != (FN *) NULL)
8426 free (temp->marker);
8427 free (temp->note);
8428 pending_notes = pending_notes->next;
8429 free (temp);
8431 first_footnote_this_node = 1;
8432 footnote_count = 0;
8435 /* What to do when you see a @footnote construct. */
8437 /* Handle a "footnote".
8438 footnote *{this is a footnote}
8439 where "*" is the (optional) marker character for this note. */
8440 void
8441 cm_footnote ()
8443 char *marker;
8444 char *note;
8446 get_until ("{", &marker);
8447 canon_white (marker);
8449 if (macro_expansion_output_stream && !executing_string)
8450 append_to_expansion_output (input_text_offset + 1); /* include the { */
8452 /* Read the argument in braces. */
8453 if (curchar () != '{')
8455 line_error (_("`%c%s' needs an argument `{...}', not just `%s'"),
8456 COMMAND_PREFIX, command, marker);
8457 free (marker);
8458 return;
8460 else
8462 int len;
8463 int braces = 1;
8464 int loc = ++input_text_offset;
8466 while (braces)
8468 if (loc == size_of_input_text)
8470 line_error (_("No closing brace for footnote `%s'"), marker);
8471 return;
8474 if (input_text[loc] == '{')
8475 braces++;
8476 else if (input_text[loc] == '}')
8477 braces--;
8478 else if (input_text[loc] == '\n')
8479 line_number++;
8481 loc++;
8484 len = (loc - input_text_offset) - 1;
8485 note = (char *)xmalloc (len + 1);
8486 strncpy (note, &input_text[input_text_offset], len);
8487 note[len] = 0;
8488 input_text_offset = loc;
8491 /* Must write the macro-expanded argument to the macro expansion
8492 output stream. This is like the case in index_add_arg. */
8493 if (macro_expansion_output_stream && !executing_string)
8495 int op_orig;
8497 remember_itext (input_text, input_text_offset);
8498 op_orig = output_paragraph_offset;
8499 me_execute_string (note);
8500 /* Calling me_execute_string on a lone } provokes an error, since
8501 as far as the reader knows there is no matching {. We wrote
8502 the { above in the call to append_to_expansion_output. */
8503 write_region_to_macro_output ("}", 0, 1);
8504 output_paragraph_offset = op_orig;
8507 if (!current_node || !*current_node)
8509 line_error (_("Footnote defined without parent node"));
8510 free (marker);
8511 free (note);
8512 return;
8515 if (!*marker)
8517 free (marker);
8519 if (number_footnotes)
8521 marker = (char *)xmalloc (10);
8522 sprintf (marker, "%d", current_footnote_number);
8523 current_footnote_number++;
8525 else
8526 marker = xstrdup ("*");
8529 remember_note (marker, note);
8531 /* Your method should at least insert MARKER. */
8532 switch (footnote_style)
8534 case SeparateNode:
8535 add_word_args ("(%s)", marker);
8536 if (first_footnote_this_node)
8538 char *temp_string;
8540 temp_string = (char *)
8541 xmalloc ((strlen (current_node)) + (strlen (_("-Footnotes"))) + 1);
8543 add_word_args (" (*note %s-Footnotes::)", current_node);
8544 strcpy (temp_string, current_node);
8545 strcat (temp_string, "-Footnotes");
8546 remember_node_reference (temp_string, line_number, followed_reference);
8547 free (temp_string);
8548 first_footnote_this_node = 0;
8550 break;
8552 case EndNode:
8553 add_word_args ("(%s)", marker);
8554 break;
8556 default:
8557 break;
8559 free (marker);
8560 free (note);
8563 /* Nonzero means that we are currently in the process of outputting
8564 footnotes. */
8565 int already_outputting_pending_notes = 0;
8567 /* Output the footnotes. We are at the end of the current node. */
8568 void
8569 output_pending_notes ()
8571 FN *footnote = pending_notes;
8573 if (!pending_notes)
8574 return;
8576 switch (footnote_style)
8578 case SeparateNode:
8580 char *old_current_node = current_node;
8581 char *old_command = xstrdup (command);
8583 already_outputting_pending_notes++;
8584 execute_string ("%cnode %s-Footnotes,,,%s\n",
8585 COMMAND_PREFIX, current_node, current_node);
8586 already_outputting_pending_notes--;
8587 current_node = old_current_node;
8588 free (command);
8589 command = old_command;
8591 break;
8593 case EndNode:
8594 close_paragraph ();
8595 in_fixed_width_font++;
8596 execute_string (_("---------- Footnotes ----------\n\n"));
8597 in_fixed_width_font--;
8598 break;
8601 /* Handle the footnotes in reverse order. */
8603 FN **array = (FN **) xmalloc ((footnote_count + 1) * sizeof (FN *));
8605 array[footnote_count] = (FN *) NULL;
8607 while (--footnote_count > -1)
8609 array[footnote_count] = footnote;
8610 footnote = footnote->next;
8613 filling_enabled = 1;
8614 indented_fill = 1;
8616 while ((footnote = array[++footnote_count]))
8618 execute_string ("(%s) %s", footnote->marker, footnote->note);
8619 close_paragraph ();
8621 close_paragraph ();
8622 free (array);
8626 /* **************************************************************** */
8627 /* */
8628 /* User definable Macros (text substitution) */
8629 /* */
8630 /* **************************************************************** */
8632 #if defined (HAVE_MACROS)
8634 /* Array of macros and definitions. */
8635 MACRO_DEF **macro_list = (MACRO_DEF **)NULL;
8637 int macro_list_len = 0; /* Number of elements. */
8638 int macro_list_size = 0; /* Number of slots in total. */
8640 /* Return the macro definition of NAME or NULL if NAME is not defined. */
8641 MACRO_DEF *
8642 find_macro (name)
8643 char *name;
8645 register int i;
8646 register MACRO_DEF *def;
8648 def = (MACRO_DEF *)NULL;
8649 for (i = 0; macro_list && (def = macro_list[i]); i++)
8651 if ((!def->inhibited) && (strcmp (def->name, name) == 0))
8652 break;
8654 return (def);
8657 /* Add the macro NAME with ARGLIST and BODY to the list of defined macros.
8658 SOURCE_FILE is the name of the file where this definition can be found,
8659 and SOURCE_LINENO is the line number within that file. If a macro already
8660 exists with NAME, then a warning is produced, and that previous
8661 definition is overwritten. */
8662 void
8663 add_macro (name, arglist, body, source_file, source_lineno, flags)
8664 char *name;
8665 char **arglist;
8666 char *body;
8667 char *source_file;
8668 int source_lineno, flags;
8670 register MACRO_DEF *def;
8672 def = find_macro (name);
8674 if (!def)
8676 if (macro_list_len + 2 >= macro_list_size)
8677 macro_list = (MACRO_DEF **)xrealloc
8678 (macro_list, ((macro_list_size += 10) * sizeof (MACRO_DEF *)));
8680 macro_list[macro_list_len] = (MACRO_DEF *)xmalloc (sizeof (MACRO_DEF));
8681 macro_list[macro_list_len + 1] = (MACRO_DEF *)NULL;
8683 def = macro_list[macro_list_len];
8684 macro_list_len += 1;
8685 def->name = name;
8687 else
8689 char *temp_filename = input_filename;
8690 int temp_line = line_number;
8692 warning (_("macro `%s' previously defined"), name);
8694 input_filename = def->source_file;
8695 line_number = def->source_lineno;
8696 warning (_("here is the previous definition of `%s'"), name);
8698 input_filename = temp_filename;
8699 line_number = temp_line;
8701 if (def->arglist)
8703 register int i;
8705 for (i = 0; def->arglist[i]; i++)
8706 free (def->arglist[i]);
8708 free (def->arglist);
8710 free (def->source_file);
8711 free (def->body);
8714 def->source_file = xstrdup (source_file);
8715 def->source_lineno = source_lineno;
8716 def->body = body;
8717 def->arglist = arglist;
8718 def->inhibited = 0;
8719 def->flags = flags;
8722 /* Delete the macro with name NAME. The macro is deleted from the list,
8723 but it is also returned. If there was no macro defined, NULL is
8724 returned. */
8725 MACRO_DEF *
8726 delete_macro (name)
8727 char *name;
8729 register int i;
8730 register MACRO_DEF *def;
8732 def = (MACRO_DEF *)NULL;
8734 for (i = 0; macro_list && (def = macro_list[i]); i++)
8735 if (strcmp (def->name, name) == 0)
8737 memmove (macro_list + i, macro_list + i + 1,
8738 ((macro_list_len + 1) - i) * sizeof (MACRO_DEF *));
8739 macro_list_len--;
8740 break;
8742 return (def);
8745 /* Return the arglist on the current line. This can behave in two different
8746 ways, depending on the variable BRACES_REQUIRED_FOR_MACRO_ARGS. */
8747 int braces_required_for_macro_args = 0;
8749 char **
8750 get_macro_args (def)
8751 MACRO_DEF *def;
8753 register int i;
8754 char *word;
8756 /* Quickly check to see if this macro has been invoked with any arguments.
8757 If not, then don't skip any of the following whitespace. */
8758 for (i = input_text_offset; i < size_of_input_text; i++)
8759 if (!cr_or_whitespace (input_text[i]))
8760 break;
8762 if (input_text[i] != '{')
8764 if (braces_required_for_macro_args)
8766 return ((char **)NULL);
8768 else
8770 /* Braces are not required to fill out the macro arguments. If
8771 this macro takes one argument, it is considered to be the
8772 remainder of the line, sans whitespace. */
8773 if (def->arglist && def->arglist[0] && !def->arglist[1])
8775 char **arglist;
8777 get_rest_of_line (&word);
8778 if (input_text[input_text_offset - 1] == '\n')
8780 input_text_offset--;
8781 line_number--;
8783 /* canon_white (word); */
8784 arglist = (char **)xmalloc (2 * sizeof (char *));
8785 arglist[0] = word;
8786 arglist[1] = (char *)NULL;
8787 return (arglist);
8789 else
8791 /* The macro either took no arguments, or took more than
8792 one argument. In that case, it must be invoked with
8793 arguments surrounded by braces. */
8794 return ((char **)NULL);
8798 return (get_brace_args (def->flags & ME_QUOTE_ARG));
8801 /* Substitute actual parameters for named parameters in body.
8802 The named parameters which appear in BODY must by surrounded
8803 reverse slashes, as in \foo\. */
8804 char *
8805 apply (named, actuals, body)
8806 char **named, **actuals, *body;
8808 register int i;
8809 int new_body_index, new_body_size;
8810 char *new_body, *text;
8811 int length_of_actuals;
8813 length_of_actuals = array_len (actuals);
8814 new_body_size = strlen (body);
8815 new_body = (char *)xmalloc (1 + new_body_size);
8817 /* Copy chars from BODY into NEW_BODY. */
8818 i = 0; new_body_index = 0;
8820 while (1)
8822 if (!body[i])
8823 break;
8825 if (body[i] != '\\')
8826 new_body[new_body_index++] = body[i++];
8827 else
8829 /* Snarf parameter name, check against named parameters. */
8830 char *param;
8831 int param_start, which, len;
8833 param_start = ++i;
8834 while ((body[i]) && (body[i] != '\\'))
8835 i++;
8837 len = i - param_start;
8838 param = (char *)xmalloc (1 + len);
8839 memcpy (param, body + param_start, len);
8840 param[len] = 0;
8842 if (body[i]) /* move past \ */
8843 i++;
8845 /* Now check against named parameters. */
8846 for (which = 0; named && named[which]; which++)
8847 if (strcmp (named[which], param) == 0)
8848 break;
8850 if (named && named[which])
8852 if (which < length_of_actuals)
8853 text = actuals[which];
8854 else
8855 text = (char *)NULL;
8857 if (!text)
8858 text = "";
8860 len = strlen (text);
8862 else
8863 { /* not a parameter, restore \'s */
8864 i = body[i] ? (i - 1) : i;
8865 len++;
8866 text = xmalloc (1 + len);
8867 sprintf (text, "\\%s", param);
8870 if ((2 + strlen (param)) < len)
8872 new_body_size += len + 1;
8873 new_body = xrealloc (new_body, new_body_size);
8876 free (param);
8878 strcpy (new_body + new_body_index, text);
8879 new_body_index += len;
8881 if (!named || !named[which])
8882 free (text);
8885 new_body[new_body_index] = 0;
8886 return (new_body);
8889 /* Execute the macro passed in DEF, a pointer to a MACRO_DEF. */
8890 void
8891 execute_macro (def)
8892 MACRO_DEF *def;
8894 char **arglist;
8895 int num_args;
8896 char *execution_string = (char *)NULL;
8898 if (macro_expansion_output_stream && !executing_string && !me_inhibit_expansion)
8899 me_append_before_this_command ();
8901 /* Find out how many arguments this macro definition takes. */
8902 num_args = array_len (def->arglist);
8904 /* Gather the arguments present on the line if there are any. */
8905 arglist = get_macro_args (def);
8907 if (num_args < array_len (arglist))
8909 free_array (arglist);
8910 line_error (_("Macro `%s' called with too many args"), def->name);
8911 return;
8914 if (def->body)
8915 execution_string = apply (def->arglist, arglist, def->body);
8917 free_array (arglist);
8919 if (def->body)
8921 if (macro_expansion_output_stream && !executing_string && !me_inhibit_expansion)
8923 remember_itext (input_text, input_text_offset);
8924 me_execute_string (execution_string);
8926 else
8927 execute_string ("%s", execution_string);
8929 free (execution_string);
8933 /* Read and remember the definition of a macro. */
8934 void
8935 cm_macro ()
8937 register int i;
8938 char *name, **arglist, *body, *line;
8939 int body_size, body_index;
8940 int depth = 1;
8941 int defining_line = line_number;
8942 int flags = 0;
8944 arglist = (char **)NULL;
8945 body = (char *)NULL;
8946 body_size = 0;
8947 body_index = 0;
8949 if (macro_expansion_output_stream && !executing_string)
8950 me_append_before_this_command ();
8952 skip_whitespace ();
8954 /* Get the name of the macro. This is the set of characters which are
8955 not whitespace and are not `{' immediately following the @macro. */
8957 int start = input_text_offset;
8958 int len;
8960 for (i = start;
8961 (i < size_of_input_text) &&
8962 (input_text[i] != '{') &&
8963 (!cr_or_whitespace (input_text[i]));
8964 i++);
8966 len = i - start;
8967 name = (char *)xmalloc (1 + len);
8968 strncpy (name, input_text + start, len);
8969 name[len] = 0;
8970 input_text_offset = i;
8973 skip_whitespace ();
8975 /* It is not required that the definition of a macro includes an arglist.
8976 If not, don't try to get the named parameters, just use a null list. */
8977 if (curchar () == '{')
8979 int arglist_index = 0, arglist_size = 0;
8980 int gathering_words = 1;
8981 char *word = (char *)NULL;
8982 int character;
8984 /* Read the words inside of the braces which determine the arglist.
8985 These words will be replaced within the body of the macro at
8986 execution time. */
8988 input_text_offset++;
8989 skip_whitespace_and_newlines ();
8991 while (gathering_words)
8993 int len;
8995 for (i = input_text_offset;
8996 (character = input_text[i]);
8997 i++)
8999 switch (character)
9001 case '\n':
9002 line_number++;
9003 case ' ':
9004 case '\t':
9005 case ',':
9006 case '}':
9007 /* Found the end of the current arglist word. Save it. */
9008 len = i - input_text_offset;
9009 word = (char *)xmalloc (1 + len);
9010 strncpy (word, input_text + input_text_offset, len);
9011 word[len] = 0;
9012 input_text_offset = i;
9014 /* Advance to the comma or close-brace that signified
9015 the end of the argument. */
9016 while ((character = curchar ())
9017 && character != ','
9018 && character != '}')
9020 input_text_offset++;
9021 if (character == '\n')
9022 line_number++;
9025 /* Add the word to our list of words. */
9026 if ((arglist_index + 2) >= arglist_size)
9027 arglist = (char **)xrealloc
9028 (arglist, (arglist_size += 10) * sizeof (char *));
9030 arglist[arglist_index++] = word;
9031 arglist[arglist_index] = (char *)NULL;
9032 break;
9035 if (character == '}')
9037 input_text_offset++;
9038 gathering_words = 0;
9039 break;
9042 if (character == ',')
9044 input_text_offset++;
9045 skip_whitespace_and_newlines ();
9046 i = input_text_offset - 1;
9052 /* Read the text carefully until we find an "@end macro" which
9053 matches this one. The text in between is the body of the macro. */
9054 skip_whitespace_and_newlines ();
9056 while (depth)
9058 if ((input_text_offset + 9) > size_of_input_text)
9060 int temp_line = line_number;
9061 line_number = defining_line;
9062 line_error (_("%cend macro not found"), COMMAND_PREFIX);
9063 line_number = temp_line;
9064 return;
9067 get_rest_of_line (&line);
9069 /* Handle commands only meaningful within a macro. */
9070 if ((*line == COMMAND_PREFIX) && (depth == 1) &&
9071 (strncmp (line + 1, "allow-recursion", 15) == 0) &&
9072 (line[16] == 0 || whitespace (line[16])))
9074 for (i = 16; whitespace (line[i]); i++);
9075 strcpy (line, line + i);
9076 flags |= ME_RECURSE;
9077 if (!*line)
9079 free (line);
9080 continue;
9084 if ((*line == COMMAND_PREFIX) && (depth == 1) &&
9085 (strncmp (line + 1, "quote-arg", 9) == 0) &&
9086 (line[10] == 0 || whitespace (line[10])))
9088 for (i = 10; whitespace (line[i]); i++);
9089 strcpy (line, line + i);
9091 if (arglist && arglist[0] && !arglist[1])
9093 flags |= ME_QUOTE_ARG;
9094 if (!*line)
9096 free (line);
9097 continue;
9100 else
9102 line_error (_("%cquote-arg only useful when the macro takes a single argument"),
9103 COMMAND_PREFIX);
9107 if ((*line == COMMAND_PREFIX) &&
9108 (strncmp (line + 1, "macro ", 6) == 0))
9109 depth++;
9111 if ((*line == COMMAND_PREFIX) &&
9112 (strncmp (line + 1, "end macro", 9) == 0))
9113 depth--;
9115 if (depth)
9117 if ((body_index + strlen (line) + 3) >= body_size)
9118 body = (char *)xrealloc
9119 (body, body_size += 3 + strlen (line));
9120 strcpy (body + body_index, line);
9121 body_index += strlen (line);
9122 body[body_index++] = '\n';
9123 body[body_index] = 0;
9125 free (line);
9128 /* If it was an empty macro like
9129 @macro foo
9130 @end macro
9131 create an empty body. (Otherwise, the macro is not expanded.) */
9132 if (!body)
9134 body = (char *)malloc(1);
9135 *body = 0;
9138 /* We now have the name, the arglist, and the body. However, BODY
9139 includes the final newline which preceded the `@end macro' text.
9140 Delete it. */
9141 if (body && strlen (body))
9142 body[strlen (body) - 1] = 0;
9144 add_macro (name, arglist, body, input_filename, defining_line, flags);
9146 if (macro_expansion_output_stream && !executing_string)
9147 remember_itext (input_text, input_text_offset);
9150 void
9151 cm_unmacro ()
9153 register int i;
9154 char *line, *name;
9155 MACRO_DEF *def;
9157 if (macro_expansion_output_stream && !executing_string)
9158 me_append_before_this_command ();
9160 get_rest_of_line (&line);
9162 for (i = 0; line[i] && !whitespace (line[i]); i++);
9163 name = (char *)xmalloc (i + 1);
9164 strncpy (name, line, i);
9165 name[i] = 0;
9167 def = delete_macro (name);
9169 if (def)
9171 free (def->source_file);
9172 free (def->name);
9173 free (def->body);
9175 if (def->arglist)
9177 register int i;
9179 for (i = 0; def->arglist[i]; i++)
9180 free (def->arglist[i]);
9182 free (def->arglist);
9185 free (def);
9188 free (line);
9189 free (name);
9191 if (macro_expansion_output_stream && !executing_string)
9192 remember_itext (input_text, input_text_offset);
9195 /* How to output sections of the input file verbatim. */
9197 /* Set the value of POINTER's offset to OFFSET. */
9198 ITEXT *
9199 remember_itext (pointer, offset)
9200 char *pointer;
9201 int offset;
9203 register int i;
9204 ITEXT *itext = (ITEXT *)NULL;
9206 /* If we have no info, initialize a blank list. */
9207 if (!itext_info)
9209 itext_info = (ITEXT **)xmalloc ((itext_size = 10) * sizeof (ITEXT *));
9210 for (i = 0; i < itext_size; i++)
9211 itext_info[i] = (ITEXT *)NULL;
9214 /* If the pointer is already present in the list, then set the offset. */
9215 for (i = 0; i < itext_size; i++)
9216 if ((itext_info[i] != (ITEXT *)NULL) &&
9217 (itext_info[i]->pointer == pointer))
9219 itext = itext_info[i];
9220 itext_info[i]->offset = offset;
9221 break;
9224 if (i == itext_size)
9226 /* Find a blank slot (or create a new one), and remember the
9227 pointer and offset. */
9228 for (i = 0; i < itext_size; i++)
9229 if (itext_info[i] == (ITEXT *)NULL)
9230 break;
9232 /* If not found, then add some slots. */
9233 if (i == itext_size)
9235 register int j;
9237 itext_info = (ITEXT **)xrealloc
9238 (itext_info, (itext_size += 10) * sizeof (ITEXT *));
9240 for (j = i; j < itext_size; j++)
9241 itext_info[j] = (ITEXT *)NULL;
9244 /* Now add the pointer and the offset. */
9245 itext_info[i] = (ITEXT *)xmalloc (sizeof (ITEXT));
9246 itext_info[i]->pointer = pointer;
9247 itext_info[i]->offset = offset;
9248 itext = itext_info[i];
9250 return (itext);
9253 /* Forget the input text associated with POINTER. */
9254 void
9255 forget_itext (pointer)
9256 char *pointer;
9258 register int i;
9260 for (i = 0; i < itext_size; i++)
9261 if (itext_info[i] && (itext_info[i]->pointer == pointer))
9263 free (itext_info[i]);
9264 itext_info[i] = (ITEXT *)NULL;
9265 break;
9269 /* Append the text which appeared in input_text from the last offset to
9270 the character just before the command that we are currently executing. */
9271 void
9272 me_append_before_this_command ()
9274 register int i;
9276 for (i = input_text_offset; i && (input_text[i] != COMMAND_PREFIX); i--);
9277 maybe_write_itext (input_text, i);
9280 /* Similar to execute_string (), but only takes a single string argument,
9281 and remembers the input text location, etc. */
9282 void
9283 me_execute_string (execution_string)
9284 char *execution_string;
9286 pushfile ();
9287 input_text_offset = 0;
9288 input_text = execution_string;
9289 input_filename = xstrdup (input_filename);
9290 size_of_input_text = strlen (execution_string);
9292 remember_itext (execution_string, 0);
9294 me_executing_string++;
9295 reader_loop ();
9296 popfile ();
9297 me_executing_string--;
9300 /* Append the text which appears in input_text from the last offset to
9301 the current OFFSET. */
9302 void
9303 append_to_expansion_output (offset)
9304 int offset;
9306 register int i;
9307 ITEXT *itext = (ITEXT *)NULL;
9309 for (i = 0; i < itext_size; i++)
9310 if (itext_info[i] && itext_info[i]->pointer == input_text)
9312 itext = itext_info[i];
9313 break;
9316 if (!itext)
9317 return;
9319 if (offset > itext->offset)
9321 write_region_to_macro_output
9322 (input_text, itext->offset, offset);
9323 remember_itext (input_text, offset);
9327 /* Only write this input text iff it appears in our itext list. */
9328 void
9329 maybe_write_itext (pointer, offset)
9330 char *pointer;
9331 int offset;
9333 register int i;
9334 ITEXT *itext = (ITEXT *)NULL;
9336 for (i = 0; i < itext_size; i++)
9337 if (itext_info[i] && (itext_info[i]->pointer == pointer))
9339 itext = itext_info[i];
9340 break;
9343 if (itext && (itext->offset < offset))
9345 write_region_to_macro_output (itext->pointer, itext->offset, offset);
9346 remember_itext (pointer, offset);
9350 void
9351 write_region_to_macro_output (string, start, end)
9352 char *string;
9353 int start, end;
9355 if (macro_expansion_output_stream)
9356 fwrite (string + start, 1, end - start, macro_expansion_output_stream);
9359 #endif /* HAVE_MACROS */
9361 /* Return the length of the array in ARRAY. */
9363 array_len (array)
9364 char **array;
9366 register int i = 0;
9368 if (array)
9369 for (i = 0; array[i] != (char *)NULL; i++);
9371 return (i);
9374 void
9375 free_array (array)
9376 char **array;
9378 if (array)
9380 register int i;
9382 for (i = 0; array[i] != (char *)NULL; i++)
9383 free (array[i]);
9385 free (array);
9389 /* Function is used even when we don't have macros. Although, I have
9390 to admit, it is unlikely that you would have a use for it if you
9391 aren't using macros. */
9392 char **
9393 get_brace_args (quote_single)
9394 int quote_single;
9396 char **arglist, *word;
9397 int arglist_index, arglist_size;
9398 int character, escape_seen, start;
9399 int depth = 1;
9401 /* There is an arglist in braces here, so gather the args inside of it. */
9402 skip_whitespace_and_newlines ();
9403 input_text_offset++;
9404 arglist = (char **)NULL;
9405 arglist_index = arglist_size = 0;
9407 get_arg:
9408 skip_whitespace_and_newlines ();
9409 start = input_text_offset;
9410 escape_seen = 0;
9412 while ((character = curchar ()))
9414 if (character == '\\')
9416 input_text_offset += 2;
9417 escape_seen = 1;
9419 else if (character == '{')
9421 depth++;
9422 input_text_offset++;
9424 else if ((character == ',' && !quote_single) ||
9425 ((character == '}') && depth == 1))
9427 int len = input_text_offset - start;
9429 if (len || (character != '}'))
9431 word = (char *)xmalloc (1 + len);
9432 strncpy (word, input_text + start, len);
9433 word[len] = 0;
9435 /* Clean up escaped characters. */
9436 if (escape_seen)
9438 register int i;
9440 for (i = 0; word[i]; i++)
9441 if (word[i] == '\\')
9442 memmove (word + i, word + i + 1,
9443 1 + strlen (word + i + 1));
9446 if (arglist_index + 2 >= arglist_size)
9447 arglist = (char **)xrealloc
9448 (arglist, (arglist_size += 10) * sizeof (char *));
9450 arglist[arglist_index++] = word;
9451 arglist[arglist_index] = (char *)NULL;
9454 input_text_offset++;
9455 if (character == '}')
9456 break;
9457 else
9458 goto get_arg;
9460 else if (character == '}')
9462 depth--;
9463 input_text_offset++;
9465 else
9467 input_text_offset++;
9468 if (character == '\n') line_number++;
9471 return (arglist);
9474 /* **************************************************************** */
9475 /* */
9476 /* Looking For Include Files */
9477 /* */
9478 /* **************************************************************** */
9480 /* Given a string containing units of information separated by colons,
9481 return the next one pointed to by INDEX, or NULL if there are no more.
9482 Advance INDEX to the character after the colon. */
9483 char *
9484 extract_colon_unit (string, index)
9485 char *string;
9486 int *index;
9488 int i, start;
9490 i = *index;
9492 if (!string || (i >= strlen (string)))
9493 return ((char *)NULL);
9495 /* Each call to this routine leaves the index pointing at a colon if
9496 there is more to the path. If I is > 0, then increment past the
9497 `:'. If I is 0, then the path has a leading colon. Trailing colons
9498 are handled OK by the `else' part of the if statement; an empty
9499 string is returned in that case. */
9500 if (i && string[i] == ':')
9501 i++;
9503 start = i;
9505 while (string[i] && string[i] != ':') i++;
9507 *index = i;
9509 if (i == start)
9511 if (string[i])
9512 (*index)++;
9514 /* Return "" in the case of a trailing `:'. */
9515 return (xstrdup (""));
9517 else
9519 char *value;
9521 value = (char *)xmalloc (1 + (i - start));
9522 strncpy (value, &string[start], (i - start));
9523 value [i - start] = 0;
9525 return (value);
9529 /* Return the full pathname for FILENAME by searching along PATH.
9530 When found, return the stat () info for FILENAME in FINFO.
9531 If PATH is NULL, only the current directory is searched.
9532 If the file could not be found, return a NULL pointer. */
9533 char *
9534 get_file_info_in_path (filename, path, finfo)
9535 char *filename, *path;
9536 struct stat *finfo;
9538 char *dir;
9539 int result, index = 0;
9541 if (path == (char *)NULL)
9542 path = ".";
9544 /* Handle absolute pathnames. "./foo", "/foo", "../foo". */
9545 if (*filename == '/' ||
9546 (*filename == '.' &&
9547 (filename[1] == '/' ||
9548 (filename[1] == '.' && filename[2] == '/')))
9549 #ifdef WIN32
9550 /* Handle names that look like "d:/foo/bar" */
9551 || (isalpha (*filename) && filename [1] == ':'
9552 && (filename [2] == '/' || filename [2] == '\\'))
9553 #endif
9556 if (stat (filename, finfo) == 0)
9557 return (xstrdup (filename));
9558 else
9559 return ((char *)NULL);
9562 while ((dir = extract_colon_unit (path, &index)))
9564 char *fullpath;
9566 if (!*dir)
9568 free (dir);
9569 dir = xstrdup (".");
9572 fullpath = (char *)xmalloc (2 + strlen (dir) + strlen (filename));
9573 sprintf (fullpath, "%s/%s", dir, filename);
9574 free (dir);
9576 result = stat (fullpath, finfo);
9578 if (result == 0)
9579 return (fullpath);
9580 else
9581 free (fullpath);
9583 return NULL;