* parse-scan.y (interface_declaration): Call
[official-gcc.git] / texinfo / makeinfo / makeinfo.c
blobdec3a4ef34fb22f0110b471dc6037bd35757da8a
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 setlocale (LC_MESSAGES, "");
949 #endif
951 /* Set the text message domain. */
952 bindtextdomain (PACKAGE, LOCALEDIR);
953 textdomain (PACKAGE);
955 /* Parse argument flags from the input line. */
956 while ((c = getopt_long (argc, argv, "D:e:E:f:I:o:p:P:r:s:U:V",
957 long_options, &ind)) != EOF)
959 if (c == 0 && long_options[ind].flag == 0)
960 c = long_options[ind].val;
962 switch (c)
964 case 'D':
965 case 'U':
966 /* User specified variable to set or clear. */
967 handle_variable_internal ((c == 'D') ? SET : CLEAR, optarg);
968 break;
970 case 'e':
971 /* User specified error level. */
972 if (sscanf (optarg, "%d", &max_error_level) != 1)
974 fprintf (stderr,
975 _("%s: %s arg must be numeric, not `%s'.\n"),
976 "--error-limit", progname, optarg);
977 usage (stderr, FATAL);
979 break;
981 case 'E':
982 /* User specified a macro expansion output file. */
983 if (!macro_expansion_output_stream)
985 macro_expansion_filename = optarg;
986 macro_expansion_output_stream
987 = strcmp (optarg, "-") == 0 ? stdout : fopen (optarg, "w");
988 if (!macro_expansion_output_stream)
989 error (_("Couldn't open macro expansion output `%s'"), optarg);
991 else
992 error (_("Cannot specify more than one macro expansion output"));
993 break;
995 case 'f':
996 /* User specified fill_column. */
997 if (sscanf (optarg, "%d", &fill_column) != 1)
999 fprintf (stderr,
1000 _("%s: %s arg must be numeric, not `%s'.\n"),
1001 "--fill-column", progname, optarg);
1002 usage (FATAL);
1004 break;
1006 case 'F':
1007 force++; /* Do not remove erroneous output. */
1008 break;
1010 case 'h':
1011 usage (NO_ERROR);
1012 break;
1014 case 'I':
1015 /* Append user-specified dir to include file path. */
1016 if (!include_files_path)
1017 include_files_path = xstrdup (".");
1019 include_files_path = (char *)
1020 xrealloc (include_files_path,
1021 2 + strlen (include_files_path) + strlen (optarg));
1022 strcat (include_files_path, ":");
1023 strcat (include_files_path, optarg);
1024 break;
1026 case 'o':
1027 /* User specified output file. */
1028 command_output_filename = xstrdup (optarg);
1029 break;
1031 case 'p':
1032 /* User specified paragraph indent (paragraph_start_index). */
1033 if (set_paragraph_indent (optarg) < 0)
1035 fprintf (stderr,
1036 _("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"),
1037 progname, optarg);
1038 usage (FATAL);
1040 break;
1042 case 'P':
1043 /* Prepend user-specified include dir to include path. */
1044 if (!include_files_path)
1046 include_files_path = xstrdup (optarg);
1047 include_files_path = (char *) xrealloc (include_files_path,
1048 strlen (include_files_path) + 3); /* 3 for ":.\0" */
1049 strcat (include_files_path, ":.");
1051 else
1053 char *tmp = xstrdup (include_files_path);
1054 include_files_path = (char *) xrealloc (include_files_path,
1055 strlen (include_files_path) + strlen (optarg) + 2); /* 2 for ":\0" */
1056 strcpy (include_files_path, optarg);
1057 strcat (include_files_path, ":");
1058 strcat (include_files_path, tmp);
1059 free (tmp);
1061 break;
1063 case 'r':
1064 /* User specified reference warning limit. */
1065 if (sscanf (optarg, "%d", &reference_warning_limit) != 1)
1067 fprintf (stderr,
1068 _("%s: %s arg must be numeric, not `%s'.\n"),
1069 "--reference-limit", progname, optarg);
1070 usage (FATAL);
1072 break;
1074 case 's':
1075 /* User specified footnote style. */
1076 if (set_footnote_style (optarg) < 0)
1078 fprintf (stderr,
1079 _("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"),
1080 progname, optarg);
1081 usage (FATAL);
1083 footnote_style_preset = 1;
1084 break;
1086 case 'V':
1087 /* User requested version info. */
1088 print_version_info ();
1089 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
1090 There is NO warranty. You may redistribute this software\n\
1091 under the terms of the GNU General Public License.\n\
1092 For more information about these matters, see the files named COPYING.\n"),
1093 "1998");
1094 exit (NO_ERROR);
1095 break;
1097 case '?':
1098 usage (FATAL);
1099 break;
1103 if (optind == argc)
1105 /* Check to see if input is a file. If so, process that. */
1106 if (!isatty (fileno (stdin)))
1107 reading_from_stdin = 1;
1108 else
1110 fprintf (stderr, _("%s: missing file argument.\n"), progname);
1111 usage (FATAL);
1115 /* If the user has specified --no-headers, this should imply --no-split.
1116 Do that here. I think it might also imply that we should ignore the
1117 setfilename at the top of the file, but this might break some FSF things,
1118 so I will hold off on that. */
1119 if (no_headers)
1121 splitting = 0;
1123 /* If the user has not specified an output file, use stdout. */
1124 if (!command_output_filename)
1125 command_output_filename = xstrdup ("-");
1128 if (verbose_mode)
1129 print_version_info ();
1131 /* Remaining arguments are file names of texinfo files.
1132 Convert them, one by one. */
1133 if (!reading_from_stdin)
1135 while (optind != argc)
1136 convert_from_file (argv[optind++]);
1138 else
1139 convert_from_stream (stdin, "stdin");
1141 if (errors_printed)
1142 return (SYNTAX);
1143 else
1144 return (NO_ERROR);
1147 /* Display the version info of this invocation of Makeinfo. */
1148 void
1149 print_version_info ()
1151 printf ("makeinfo (GNU %s %s) %d.%d\n", PACKAGE, VERSION,
1152 major_version, minor_version);
1155 /* If EXIT_VALUE is zero, print the full usage message to stdout.
1156 Otherwise, just say to use --help for more info.
1157 Then exit with EXIT_VALUE. */
1158 void
1159 usage (exit_value)
1160 int exit_value;
1162 if (exit_value != 0)
1163 fprintf (stderr, _("Try `%s --help' for more information.\n"), progname);
1164 else
1165 printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n\
1167 Translate Texinfo source documentation to a format suitable for reading\n\
1168 with GNU Info.\n\
1170 Options:\n\
1171 -D VAR define a variable, as with @set.\n\
1172 -E MACRO-OFILE process macros only, output texinfo source.\n\
1173 -I DIR append DIR to the @include directory search path.\n\
1174 -P DIR prepend DIR to the @include directory search path.\n\
1175 -U VAR undefine a variable, as with @clear.\n\
1176 --error-limit NUM quit after NUM errors (default %d).\n\
1177 --fill-column NUM break lines at NUM characters (default %d).\n\
1178 --footnote-style STYLE output footnotes according to STYLE:\n\
1179 `separate' to place footnotes in their own node,\n\
1180 `end' to place the footnotes at the end of\n\
1181 the node in which they are defined (the default).\n\
1182 --force preserve output even if errors.\n\
1183 --help display this help and exit.\n\
1184 --no-validate suppress node cross-reference validation.\n\
1185 --no-warn suppress warnings (but not errors).\n\
1186 --no-split suppress splitting of large files.\n\
1187 --no-headers suppress node separators and Node: Foo headers.\n\
1188 --output FILE, -o FILE output to FILE, and ignore any @setfilename.\n\
1189 --paragraph-indent VAL indent paragraphs with VAL spaces (default %d).\n\
1190 if VAL is `none', do not indent; if VAL is `asis',\n\
1191 preserve any existing indentation.\n\
1192 --reference-limit NUM complain about at most NUM references (default %d).\n\
1193 --verbose report about what is being done.\n\
1194 --version display version information and exit.\n\
1196 Email bug reports to bug-texinfo@gnu.org.\n\
1198 progname, max_error_level, fill_column,
1199 paragraph_start_indent, reference_warning_limit);
1200 exit (exit_value);
1203 /* Manipulating Lists */
1205 typedef struct generic_list {
1206 struct generic_list *next;
1207 } GENERIC_LIST;
1209 /* Reverse the chain of structures in LIST. Output the new head
1210 of the chain. You should always assign the output value of this
1211 function to something, or you will lose the chain. */
1212 GENERIC_LIST *
1213 reverse_list (list)
1214 register GENERIC_LIST *list;
1216 register GENERIC_LIST *next;
1217 register GENERIC_LIST *prev = (GENERIC_LIST *) NULL;
1219 while (list)
1221 next = list->next;
1222 list->next = prev;
1223 prev = list;
1224 list = next;
1226 return (prev);
1229 /* Pushing and Popping Files */
1231 /* Find and load the file named FILENAME. Return a pointer to
1232 the loaded file, or NULL if it can't be loaded. */
1233 char *
1234 find_and_load (filename)
1235 char *filename;
1237 struct stat fileinfo;
1238 long file_size;
1239 int file = -1, count = 0;
1240 char *fullpath, *result, *get_file_info_in_path ();
1242 result = fullpath = (char *)NULL;
1244 fullpath = get_file_info_in_path (filename, include_files_path, &fileinfo);
1246 if (!fullpath)
1247 goto error_exit;
1249 filename = fullpath;
1250 file_size = (long) fileinfo.st_size;
1252 file = open (filename, O_RDONLY);
1253 if (file < 0)
1254 goto error_exit;
1256 /* Load the file, with enough room for a newline and a null. */
1257 result = xmalloc (file_size + 2);
1259 /* VMS stat lies about the st_size value. The actual number of
1260 readable bytes is always less than this value. The arcane
1261 mysteries of VMS/RMS are too much to probe, so this hack
1262 suffices to make things work. */
1263 #if defined (VMS) || defined (WIN32)
1264 #ifdef VMS
1265 while ((n = read (file, result + count, file_size)) > 0)
1266 #else /* WIN32 */
1267 while ((n = read (file, result + count, 1)) > 0)
1268 #endif /* WIN32 */
1269 count += n;
1270 if (n == -1)
1271 #else /* !VMS && !WIN32 */
1272 count = file_size;
1273 if (read (file, result, file_size) != file_size)
1274 #endif /* !VMS && !WIN32 */
1275 error_exit:
1277 if (result)
1278 free (result);
1280 if (fullpath)
1281 free (fullpath);
1283 if (file != -1)
1284 close (file);
1286 return ((char *) NULL);
1288 close (file);
1290 /* Set the globals to the new file. */
1291 input_text = result;
1292 size_of_input_text = count;
1293 input_filename = fullpath;
1294 node_filename = xstrdup (fullpath);
1295 input_text_offset = 0;
1296 line_number = 1;
1297 /* Not strictly necessary. This magic prevents read_token () from doing
1298 extra unnecessary work each time it is called (that is a lot of times).
1299 SIZE_OF_INPUT_TEXT is one past the actual end of the text. */
1300 input_text[size_of_input_text] = '\n';
1301 /* This, on the other hand, is always necessary. */
1302 input_text[size_of_input_text+1] = 0;
1303 return (result);
1306 /* Save the state of the current input file. */
1307 void
1308 pushfile ()
1310 FSTACK *newstack = (FSTACK *) xmalloc (sizeof (FSTACK));
1311 newstack->filename = input_filename;
1312 newstack->text = input_text;
1313 newstack->size = size_of_input_text;
1314 newstack->offset = input_text_offset;
1315 newstack->line_number = line_number;
1316 newstack->next = filestack;
1318 filestack = newstack;
1319 push_node_filename ();
1322 /* Make the current file globals be what is on top of the file stack. */
1323 void
1324 popfile ()
1326 FSTACK *tos = filestack;
1328 if (!tos)
1329 abort (); /* My fault. I wonder what I did? */
1331 #if defined (HAVE_MACROS)
1332 if (macro_expansion_output_stream)
1334 maybe_write_itext (input_text, input_text_offset);
1335 forget_itext (input_text);
1337 #endif /* HAVE_MACROS */
1339 /* Pop the stack. */
1340 filestack = filestack->next;
1342 /* Make sure that commands with braces have been satisfied. */
1343 if (!executing_string && !me_executing_string)
1344 discard_braces ();
1346 /* Get the top of the stack into the globals. */
1347 input_filename = tos->filename;
1348 input_text = tos->text;
1349 size_of_input_text = tos->size;
1350 input_text_offset = tos->offset;
1351 line_number = tos->line_number;
1352 free (tos);
1354 /* Go back to the (now) current node. */
1355 pop_node_filename ();
1358 /* Flush all open files on the file stack. */
1359 void
1360 flush_file_stack ()
1362 while (filestack)
1364 char *fname = input_filename;
1365 char *text = input_text;
1366 popfile ();
1367 free (fname);
1368 free (text);
1372 int node_filename_stack_index = 0;
1373 int node_filename_stack_size = 0;
1374 char **node_filename_stack = (char **)NULL;
1376 void
1377 push_node_filename ()
1379 if (node_filename_stack_index + 1 > node_filename_stack_size)
1380 node_filename_stack = (char **)xrealloc
1381 (node_filename_stack, (node_filename_stack_size += 10) * sizeof (char *));
1383 node_filename_stack[node_filename_stack_index] = node_filename;
1384 node_filename_stack_index++;
1387 void
1388 pop_node_filename ()
1390 node_filename = node_filename_stack[--node_filename_stack_index];
1393 /* Return just the simple part of the filename; i.e. the
1394 filename without the path information, or extensions.
1395 This conses up a new string. */
1396 char *
1397 filename_part (filename)
1398 char *filename;
1400 char *basename;
1402 basename = strrchr (filename, '/');
1403 if (!basename)
1404 basename = filename;
1405 else
1406 basename++;
1408 basename = xstrdup (basename);
1409 #if defined (REMOVE_OUTPUT_EXTENSIONS)
1411 /* See if there is an extension to remove. If so, remove it. */
1413 char *temp;
1415 temp = strrchr (basename, '.');
1416 if (temp)
1417 *temp = 0;
1419 #endif /* REMOVE_OUTPUT_EXTENSIONS */
1420 return (basename);
1423 /* Return the pathname part of filename. This can be NULL. */
1424 char *
1425 pathname_part (filename)
1426 char *filename;
1428 char *expand_filename ();
1429 char *result = (char *) NULL;
1430 register int i;
1432 filename = expand_filename (filename, "");
1434 i = strlen (filename) - 1;
1436 while (i && filename[i] != '/')
1437 i--;
1438 if (filename[i] == '/')
1439 i++;
1441 if (i)
1443 result = (char *)xmalloc (1 + i);
1444 strncpy (result, filename, i);
1445 result[i] = 0;
1447 free (filename);
1448 return (result);
1451 char *
1452 filename_non_directory (name)
1453 char *name;
1455 register int i;
1457 for (i = strlen (name) - 1; i; i--)
1458 if (name[i] == '/')
1459 return (xstrdup (name + i + 1));
1461 return (xstrdup (name));
1464 /* Return the expansion of FILENAME. */
1465 char *
1466 expand_filename (filename, input_name)
1467 char *filename, *input_name;
1469 register int i;
1470 char *full_pathname ();
1472 if (filename)
1473 filename = full_pathname (filename);
1474 else
1476 filename = filename_non_directory (input_name);
1478 if (!*filename)
1480 free (filename);
1481 filename = xstrdup ("noname.texi");
1484 for (i = strlen (filename) - 1; i; i--)
1485 if (filename[i] == '.')
1486 break;
1488 if (!i)
1489 i = strlen (filename);
1491 if (i + 6 > (strlen (filename)))
1492 filename = (char *)xrealloc (filename, i + 6);
1493 strcpy (filename + i, ".info");
1494 return (filename);
1497 if (filename[0] == '.' || filename[0] == '/')
1498 return (filename);
1500 if (filename[0] != '/' && input_name[0] == '/')
1502 /* Make it so that relative names work. */
1503 char *result;
1505 i = strlen (input_name) - 1;
1507 result = (char *)xmalloc (1 + strlen (input_name) + strlen (filename));
1508 strcpy (result, input_name);
1510 while (result[i] != '/' && i)
1511 i--;
1513 if (result[i] == '/')
1514 i++;
1516 strcpy (&result[i], filename);
1517 free (filename);
1518 return (result);
1520 return (filename);
1523 /* Return the full path to FILENAME. */
1524 char *
1525 full_pathname (filename)
1526 char *filename;
1528 int initial_character;
1529 char *result;
1531 /* No filename given? */
1532 if (!filename || !(initial_character = *filename))
1533 return (xstrdup (""));
1535 /* Already absolute? */
1536 if ((initial_character == '/') ||
1537 ((strncmp (filename, "./", 2) == 0) ||
1538 (strncmp (filename, "../", 3) == 0)))
1539 return (xstrdup (filename));
1541 if (initial_character != '~')
1543 char *localdir;
1545 localdir = (char *)xmalloc (1025);
1546 #if defined (HAVE_GETCWD)
1547 if (!getcwd (localdir, 1024))
1548 #else /* !HAVE_GETCWD */
1549 if (!getwd (localdir))
1550 #endif /* !HAVE_GETCWD */
1552 fprintf (stderr, _("%s: getwd: %s, %s\n"),
1553 progname, filename, localdir);
1554 exit (1);
1557 strcat (localdir, "/");
1558 strcat (localdir, filename);
1559 result = xstrdup (localdir);
1560 free (localdir);
1562 else
1564 #ifndef WIN32
1565 if (filename[1] == '/')
1567 /* Return the concatenation of the environment variable HOME
1568 and the rest of the string. */
1569 char *temp_home;
1571 temp_home = (char *) getenv ("HOME");
1572 result = (char *)xmalloc (strlen (&filename[1])
1574 + temp_home ? strlen (temp_home)
1575 : 0);
1576 *result = 0;
1578 if (temp_home)
1579 strcpy (result, temp_home);
1581 strcat (result, &filename[1]);
1583 else
1585 struct passwd *user_entry;
1586 int i, c;
1587 char *username = (char *)xmalloc (257);
1589 for (i = 1; (c = filename[i]); i++)
1591 if (c == '/')
1592 break;
1593 else
1594 username[i - 1] = c;
1596 if (c)
1597 username[i - 1] = 0;
1599 user_entry = getpwnam (username);
1601 if (!user_entry)
1602 return (xstrdup (filename));
1604 result = (char *)xmalloc (1 + strlen (user_entry->pw_dir)
1605 + strlen (&filename[i]));
1606 strcpy (result, user_entry->pw_dir);
1607 strcat (result, &filename[i]);
1610 #endif /* not WIN32 */
1611 return (result);
1614 char *
1615 output_name_from_input_name (name)
1616 char *name;
1618 return (expand_filename ((char *)NULL, name));
1621 /* **************************************************************** */
1622 /* */
1623 /* Hacking Tokens and Strings */
1624 /* */
1625 /* **************************************************************** */
1627 /* Return the next token as a string pointer. We cons the string. */
1628 char *
1629 read_token ()
1631 int i, character;
1632 char *result;
1634 /* If the first character to be read is self-delimiting, then that
1635 is the command itself. */
1636 character = curchar ();
1637 if (self_delimiting (character))
1639 input_text_offset++;
1641 if (character == '\n')
1642 line_number++;
1644 result = xstrdup (" ");
1645 *result = character;
1646 return (result);
1649 for (i = 0; ((input_text_offset != size_of_input_text)
1650 && (character = curchar ())
1651 && command_char (character));
1652 i++, input_text_offset++);
1653 result = (char *)xmalloc (i + 1);
1654 memcpy (result, &input_text[input_text_offset - i], i);
1655 result[i] = 0;
1656 return (result);
1659 /* Return nonzero if CHARACTER is self-delimiting. */
1661 self_delimiting (character)
1662 int character;
1664 /* @; and @\ are not Texinfo commands, but they are listed here
1665 anyway. I don't know why. --karl, 10aug96. */
1666 return member (character, "~{|}`^\\@?=;:.-,*\'\" !\n\t");
1669 /* Clear whitespace from the front and end of string. */
1670 void
1671 canon_white (string)
1672 char *string;
1674 int len = strlen (string);
1675 int x;
1677 if (!len)
1678 return;
1680 for (x = 0; x < len; x++)
1682 if (!cr_or_whitespace (string[x]))
1684 strcpy (string, string + x);
1685 break;
1688 len = strlen (string);
1689 if (len)
1690 len--;
1691 while (len > -1 && cr_or_whitespace (string[len]))
1692 len--;
1693 string[len + 1] = 0;
1696 /* Bash STRING, replacing all whitespace with just one space. */
1697 void
1698 fix_whitespace (string)
1699 char *string;
1701 char *temp = (char *)xmalloc (strlen (string) + 1);
1702 int string_index = 0;
1703 int temp_index = 0;
1704 int c;
1706 canon_white (string);
1708 while (string[string_index])
1710 c = temp[temp_index++] = string[string_index++];
1712 if (c == ' ' || c == '\n' || c == '\t')
1714 temp[temp_index - 1] = ' ';
1715 while ((c = string[string_index]) && (c == ' ' ||
1716 c == '\t' ||
1717 c == '\n'))
1718 string_index++;
1721 temp[temp_index] = 0;
1722 strcpy (string, temp);
1723 free (temp);
1726 /* Discard text until the desired string is found. The string is
1727 included in the discarded text. */
1728 void
1729 discard_until (string)
1730 char *string;
1732 int temp = search_forward (string, input_text_offset);
1734 int tt = (temp < 0) ? size_of_input_text : temp + strlen (string);
1735 int from = input_text_offset;
1737 /* Find out what line we are on. */
1738 while (from != tt)
1739 if (input_text[from++] == '\n')
1740 line_number++;
1742 if (temp < 0)
1744 input_text_offset = size_of_input_text - strlen (string);
1746 if (strcmp (string, "\n") != 0)
1748 line_error (_("Expected `%s'"), string);
1749 return;
1752 else
1753 input_text_offset = temp;
1755 input_text_offset += strlen (string);
1758 /* Read characters from the file until we are at MATCH.
1759 Place the characters read into STRING.
1760 On exit input_text_offset is after the match string.
1761 Return the offset where the string starts. */
1763 get_until (match, string)
1764 char *match, **string;
1766 int len, current_point, x, new_point, tem;
1768 current_point = x = input_text_offset;
1769 new_point = search_forward (match, input_text_offset);
1771 if (new_point < 0)
1772 new_point = size_of_input_text;
1773 len = new_point - current_point;
1775 /* Keep track of which line number we are at. */
1776 tem = new_point + (strlen (match) - 1);
1777 while (x != tem)
1778 if (input_text[x++] == '\n')
1779 line_number++;
1781 *string = (char *)xmalloc (len + 1);
1783 memcpy (*string, &input_text[current_point], len);
1784 (*string)[len] = 0;
1786 /* Now leave input_text_offset in a consistent state. */
1787 input_text_offset = tem;
1789 if (input_text_offset > size_of_input_text)
1790 input_text_offset = size_of_input_text;
1792 return (new_point);
1795 /* Read characters from the file until we are at MATCH or end of line.
1796 Place the characters read into STRING. */
1797 void
1798 get_until_in_line (expand, match, string)
1799 int expand;
1800 char *match, **string;
1802 int real_bottom = size_of_input_text;
1803 int limit = search_forward ("\n", input_text_offset);
1804 if (limit < 0)
1805 limit = size_of_input_text;
1807 /* Replace input_text[input_text_offset .. limit-1] with its macro
1808 expansion (actually, we expand all commands). This allows the node
1809 names themselves to be constructed via a macro, as in:
1810 @macro foo{p, q}
1811 Together: \p\ & \q\.
1812 @end macro
1814 @node @foo{A,B}, next, prev, top
1816 Otherwise, the `,' separating the macro args A and B is taken as
1817 the node argument separator, so the node name is `@foo{A'. This
1818 expansion is only necessary on the first call, since we expand the
1819 whole line then.
1821 Furthermore, if we're executing a string, don't do it -- we'll end
1822 up shrinking the execution string which is currently aliased to
1823 `input_text', so it might get moved, and not updated in the
1824 `execution_strings' array. This happens when processing the
1825 (synthetic) Overview-Footnotes node in the Texinfo manual. */
1827 if (expand && !executing_string && !me_executing_string)
1829 char *xp;
1830 unsigned xp_len, new_len;
1832 /* Get original string from input. */
1833 unsigned raw_len = limit - input_text_offset;
1834 char *str = xmalloc (raw_len + 1);
1835 strncpy (str, input_text + input_text_offset, raw_len);
1836 str[raw_len] = 0;
1838 /* Expand it. */
1839 xp = expansion (str, 0);
1840 xp_len = strlen (xp);
1841 free (str);
1843 /* Plunk the expansion into the middle of `input_text' --
1844 which is terminated by a newline, not a null. */
1845 str = xmalloc (real_bottom - limit + 1);
1846 strncpy (str, input_text + limit, real_bottom - limit + 1);
1847 new_len = input_text_offset + xp_len + real_bottom - limit + 1;
1848 input_text = xrealloc (input_text, new_len);
1849 strcpy (input_text + input_text_offset, xp);
1850 strncpy (input_text + input_text_offset + xp_len, str,
1851 real_bottom - limit + 1);
1852 free (str);
1853 free (xp);
1855 limit += xp_len - raw_len;
1856 real_bottom += xp_len - raw_len;
1859 size_of_input_text = limit;
1860 get_until (match, string);
1861 size_of_input_text = real_bottom;
1864 void
1865 get_rest_of_line (string)
1866 char **string;
1868 get_until ("\n", string);
1869 canon_white (*string);
1871 if (curchar () == '\n') /* as opposed to the end of the file... */
1873 line_number++;
1874 input_text_offset++;
1878 /* Backup the input pointer to the previous character, keeping track
1879 of the current line number. */
1880 void
1881 backup_input_pointer ()
1883 if (input_text_offset)
1885 input_text_offset--;
1886 if (curchar () == '\n')
1887 line_number--;
1891 /* Read characters from the file until we are at MATCH or closing brace.
1892 Place the characters read into STRING. */
1893 void
1894 get_until_in_braces (match, string)
1895 char *match, **string;
1897 char *temp;
1898 int i, brace = 0;
1899 int match_len = strlen (match);
1901 for (i = input_text_offset; i < size_of_input_text; i++)
1903 if (input_text[i] == '{')
1904 brace++;
1905 else if (input_text[i] == '}')
1906 brace--;
1907 else if (input_text[i] == '\n')
1908 line_number++;
1910 if (brace < 0 ||
1911 (brace == 0 && strncmp (input_text + i, match, match_len) == 0))
1912 break;
1915 match_len = i - input_text_offset;
1916 temp = (char *)xmalloc (2 + match_len);
1917 strncpy (temp, input_text + input_text_offset, match_len);
1918 temp[match_len] = 0;
1919 input_text_offset = i;
1920 *string = temp;
1923 /* **************************************************************** */
1924 /* */
1925 /* Converting the File */
1926 /* */
1927 /* **************************************************************** */
1929 /* Convert the file named by NAME. The output is saved on the file
1930 named as the argument to the @setfilename command. */
1931 static char *suffixes[] = {
1932 ".texinfo",
1933 ".texi",
1934 ".txinfo",
1936 (char *)NULL
1939 void
1940 initialize_conversion ()
1942 init_tag_table ();
1943 init_indices ();
1944 init_internals ();
1945 init_paragraph ();
1947 /* This is used for splitting the output file and for doing section
1948 headings. It was previously initialized in `init_paragraph', but its
1949 use there loses with the `init_paragraph' calls done by the
1950 multitable code; the tag indices get reset to zero. */
1951 output_position = 0;
1954 /* We read in multiples of 4k, simply because it is a typical pipe size
1955 on unix systems. */
1956 #define READ_BUFFER_GROWTH (4 * 4096)
1958 /* Convert the Texinfo file coming from the open stream STREAM. Assume the
1959 source of the stream is named NAME. */
1960 void
1961 convert_from_stream (stream, name)
1962 FILE *stream;
1963 char *name;
1965 char *buffer = (char *)NULL;
1966 int buffer_offset = 0, buffer_size = 0;
1968 initialize_conversion ();
1970 /* Read until the end of the stream. This isn't strictly correct, since
1971 the texinfo input may end before the stream ends, but it is a quick
1972 working hueristic. */
1973 while (!feof (stream))
1975 int count;
1977 if (buffer_offset + (READ_BUFFER_GROWTH + 1) >= buffer_size)
1978 buffer = (char *)
1979 xrealloc (buffer, (buffer_size += READ_BUFFER_GROWTH));
1981 count = fread (buffer + buffer_offset, 1, READ_BUFFER_GROWTH, stream);
1983 if (count < 0)
1985 perror (name);
1986 exit (FATAL);
1989 buffer_offset += count;
1990 if (count == 0)
1991 break;
1994 /* Set the globals to the new file. */
1995 input_text = buffer;
1996 size_of_input_text = buffer_offset;
1997 input_filename = xstrdup (name);
1998 node_filename = xstrdup (name);
1999 input_text_offset = 0;
2000 line_number = 1;
2002 /* Not strictly necessary. This magic prevents read_token () from doing
2003 extra unnecessary work each time it is called (that is a lot of times).
2004 The SIZE_OF_INPUT_TEXT is one past the actual end of the text. */
2005 input_text[size_of_input_text] = '\n';
2007 convert_from_loaded_file (name);
2010 void
2011 convert_from_file (name)
2012 char *name;
2014 register int i;
2015 char *filename = (char *)xmalloc (strlen (name) + 50);
2017 initialize_conversion ();
2019 /* Try to load the file specified by NAME, concatenated with our
2020 various suffixes. Prefer files like `makeinfo.texi' to
2021 `makeinfo'. */
2022 for (i = 0; suffixes[i]; i++)
2024 strcpy (filename, name);
2025 strcat (filename, suffixes[i]);
2027 if (find_and_load (filename))
2028 break;
2030 if (!suffixes[i][0] && strrchr (filename, '.'))
2032 fs_error (filename);
2033 free (filename);
2034 return;
2038 if (!suffixes[i])
2040 fs_error (name);
2041 free (filename);
2042 return;
2045 input_filename = filename;
2047 convert_from_loaded_file (name);
2050 void
2051 convert_from_loaded_file (name)
2052 char *name;
2054 char *expand_filename (), *filename_part ();
2055 char *real_output_filename = (char *)NULL;
2057 #if defined (HAVE_MACROS)
2058 remember_itext (input_text, 0);
2059 #endif /* HAVE_MACROS */
2061 /* Search this file looking for the special string which starts conversion.
2062 Once found, we may truly begin. */
2063 input_text_offset = 0;
2064 while (input_text_offset >= 0)
2066 input_text_offset =
2067 search_forward (setfilename_search, input_text_offset);
2069 if ((input_text_offset == 0) ||
2070 ((input_text_offset > 0) &&
2071 (input_text[input_text_offset -1] == '\n')))
2072 break;
2073 else if (input_text_offset > 0)
2074 input_text_offset++;
2077 if (input_text_offset < 0)
2079 if (!command_output_filename)
2081 #if defined (REQUIRE_SETFILENAME)
2082 error (_("No `%s' found in `%s'"), setfilename_search, name);
2083 goto finished;
2084 #else
2085 register int i, end_of_first_line;
2087 /* Find the end of the first line in the file. */
2088 for (i = 0; i < size_of_input_text - 1; i++)
2089 if (input_text[i] == '\n')
2090 break;
2092 end_of_first_line = i + 1;
2094 input_text_offset = 0;
2096 for (i = 0; i < end_of_first_line; i++)
2098 if ((input_text[i] == '\\') &&
2099 (strncmp (input_text + i + 1, "include", 7) == 0))
2101 input_text_offset = end_of_first_line;
2102 break;
2105 command_output_filename = output_name_from_input_name (name);
2106 #endif /* !REQUIRE_SETFILENAME */
2109 else
2110 input_text_offset += strlen (setfilename_search);
2112 if (!command_output_filename)
2113 get_until ("\n", &output_filename);
2114 else
2116 if (input_text_offset != -1)
2117 discard_until ("\n");
2118 else
2119 input_text_offset = 0;
2121 real_output_filename = output_filename = command_output_filename;
2122 command_output_filename = (char *)NULL;
2125 canon_white (output_filename);
2127 if (real_output_filename && strcmp (real_output_filename, "-") == 0)
2129 if (macro_expansion_filename
2130 && strcmp (macro_expansion_filename, "-") == 0)
2132 fprintf (stderr, _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
2133 progname);
2134 macro_expansion_output_stream = NULL;
2136 real_output_filename = xstrdup (real_output_filename);
2137 output_stream = stdout;
2138 splitting = 0; /* Cannot split when writing to stdout. */
2140 else
2142 if (!real_output_filename)
2143 real_output_filename = expand_filename (output_filename, name);
2144 else
2145 real_output_filename = xstrdup (real_output_filename);
2147 output_stream = fopen (real_output_filename, "w");
2150 if (output_stream != stdout)
2151 printf (_("Making %s file `%s' from `%s'.\n"),
2152 no_headers ? "text" : "info", output_filename, input_filename);
2154 if (output_stream == NULL)
2156 fs_error (real_output_filename);
2157 goto finished;
2160 /* Make the displayable filename from output_filename. Only the base
2161 portion of the filename need be displayed. */
2162 if (output_stream != stdout)
2163 pretty_output_filename = filename_part (output_filename);
2164 else
2165 pretty_output_filename = xstrdup ("stdout");
2167 /* For this file only, count the number of newlines from the top of
2168 the file to here. This way, we keep track of line numbers for
2169 error reporting. Line_number starts at 1, since the user isn't
2170 zero-based. */
2172 int temp = 0;
2173 line_number = 1;
2174 while (temp != input_text_offset)
2175 if (input_text[temp++] == '\n')
2176 line_number++;
2179 if (!no_headers)
2181 add_word_args (_("This is Info file %s, produced by Makeinfo version %d.%d"),
2182 output_filename, major_version, minor_version);
2183 add_word_args (_(" from the input file %s.\n"), input_filename);
2186 close_paragraph ();
2187 reader_loop ();
2189 finished:
2190 discard_insertions (0);
2191 close_paragraph ();
2192 flush_file_stack ();
2194 #if defined (HAVE_MACROS)
2195 if (macro_expansion_output_stream)
2197 fclose (macro_expansion_output_stream);
2198 if (errors_printed && !force
2199 && strcmp (macro_expansion_filename, "-") != 0
2200 && strcmp (macro_expansion_filename, "/dev/null") != 0)
2202 fprintf (stderr, _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n"),
2203 progname, macro_expansion_filename);
2204 if (unlink (macro_expansion_filename) < 0)
2205 perror (macro_expansion_filename);
2208 #endif /* HAVE_MACROS */
2210 if (output_stream)
2212 output_pending_notes ();
2213 free_pending_notes ();
2214 if (tag_table != NULL)
2216 tag_table = (TAG_ENTRY *) reverse_list (tag_table);
2217 if (!no_headers)
2218 write_tag_table ();
2221 if (output_stream != stdout)
2222 fclose (output_stream);
2224 /* If validating, then validate the entire file right now. */
2225 if (validating)
2226 validate_file (tag_table);
2228 if (splitting && (!errors_printed || force))
2229 split_file (real_output_filename, 0);
2230 else if (errors_printed && !force
2231 && strcmp (real_output_filename, "-") != 0
2232 && strcmp (real_output_filename, "/dev/null") != 0)
2233 { /* If there were errors, and no --force, remove the output. */
2234 fprintf (stderr, _("%s: Removing output file `%s' due to errors; use --force to preserve.\n"),
2235 progname, real_output_filename);
2236 if (unlink (real_output_filename) < 0)
2237 perror (real_output_filename);
2240 free (real_output_filename);
2243 void
2244 free_and_clear (pointer)
2245 char **pointer;
2247 if (*pointer)
2249 free (*pointer);
2250 *pointer = (char *) NULL;
2254 /* Initialize some state. */
2255 void
2256 init_internals ()
2258 free_and_clear (&output_filename);
2259 free_and_clear (&command);
2260 free_and_clear (&input_filename);
2261 free_node_references ();
2262 init_insertion_stack ();
2263 init_brace_stack ();
2264 current_node = NULL; /* sometimes already freed */
2265 command_index = 0;
2266 in_menu = 0;
2267 in_detailmenu = 0;
2268 top_node_seen = 0;
2269 non_top_node_seen = 0;
2272 void
2273 init_paragraph ()
2275 free_and_clear (&output_paragraph);
2276 output_paragraph = (unsigned char *)xmalloc (paragraph_buffer_len);
2277 output_paragraph[0] = 0;
2278 output_paragraph_offset = 0;
2279 output_column = 0;
2280 paragraph_is_open = 0;
2281 current_indent = 0;
2284 /* Okay, we are ready to start the conversion. Call the reader on
2285 some text, and fill the text as it is output. Handle commands by
2286 remembering things like open braces and the current file position on a
2287 stack, and when the corresponding close brace is found, you can call
2288 the function with the proper arguments. */
2289 void
2290 reader_loop ()
2292 int character;
2293 int done = 0;
2294 int dash_count = 0;
2296 while (!done)
2298 if (input_text_offset >= size_of_input_text)
2299 break;
2301 character = curchar ();
2303 if (!in_fixed_width_font &&
2304 (character == '\'' || character == '`') &&
2305 input_text[input_text_offset + 1] == character)
2307 input_text_offset++;
2308 character = '"';
2311 if (character == '-')
2313 dash_count++;
2314 if (dash_count == 2 && !in_fixed_width_font)
2316 input_text_offset++;
2317 continue;
2320 else
2322 dash_count = 0;
2325 /* If this is a whitespace character, then check to see if the line
2326 is blank. If so, advance to the carriage return. */
2327 if (whitespace (character))
2329 register int i = input_text_offset + 1;
2331 while (i < size_of_input_text && whitespace (input_text[i]))
2332 i++;
2334 if (i == size_of_input_text || input_text[i] == '\n')
2336 if (i == size_of_input_text)
2337 i--;
2339 input_text_offset = i;
2340 character = curchar ();
2344 if (character == '\n')
2346 line_number++;
2348 /* Check for a menu entry here, since the "escape sequence"
2349 that begins menu entries is "\n* ". */
2350 if (in_menu && input_text_offset + 1 < size_of_input_text)
2352 char *glean_node_from_menu (), *tem;
2354 /* Note that the value of TEM is discarded, since it is
2355 gauranteed to be NULL when glean_node_from_menu () is
2356 called with a Nonzero argument. */
2357 if (!in_detailmenu)
2358 tem = glean_node_from_menu (1);
2362 switch (character)
2364 case COMMAND_PREFIX:
2365 read_command ();
2366 break;
2368 case '{':
2369 /* Special case. I'm not supposed to see this character by itself.
2370 If I do, it means there is a syntax error in the input text.
2371 Report the error here, but remember this brace on the stack so
2372 you can ignore its partner. */
2374 line_error (_("Misplaced %c"), '{');
2375 remember_brace (misplaced_brace);
2377 /* Don't advance input_text_offset since this happens in
2378 remember_brace ().
2379 input_text_offset++;
2381 break;
2383 case '}':
2384 pop_and_call_brace ();
2385 input_text_offset++;
2386 break;
2388 default:
2389 add_char (character);
2390 input_text_offset++;
2393 #if defined (HAVE_MACROS)
2394 if (macro_expansion_output_stream)
2395 maybe_write_itext (input_text, input_text_offset);
2396 #endif /* HAVE_MACROS */
2399 /* Find the command corresponding to STRING. If the command
2400 is found, return a pointer to the data structure. Otherwise
2401 return (-1). */
2402 COMMAND *
2403 get_command_entry (string)
2404 char *string;
2406 register int i;
2408 for (i = 0; command_table[i].name; i++)
2409 if (strcmp (command_table[i].name, string) == 0)
2410 return (&command_table[i]);
2412 /* This command is not in our predefined command table. Perhaps
2413 it is a user defined command. */
2414 for (i = 0; i < user_command_array_len; i++)
2415 if (user_command_array[i] &&
2416 (strcmp (user_command_array[i]->name, string) == 0))
2417 return (user_command_array[i]);
2419 /* We never heard of this command. */
2420 return ((COMMAND *) -1);
2423 /* input_text_offset is right at the command prefix character.
2424 Read the next token to determine what to do. */
2425 void
2426 read_command ()
2428 COMMAND *entry;
2430 input_text_offset++;
2431 free_and_clear (&command);
2432 command = read_token ();
2434 #if defined (HAVE_MACROS)
2435 /* Check to see if this command is a macro. If so, execute it here. */
2437 MACRO_DEF *def;
2439 def = find_macro (command);
2441 if (def)
2443 /* We disallow recursive use of a macro call. Inhibit the expansion
2444 of this macro during the life of its execution. */
2445 if (!(def->flags & ME_RECURSE))
2446 def->inhibited = 1;
2448 execute_macro (def);
2450 if (!(def->flags & ME_RECURSE))
2451 def->inhibited = 0;
2453 return;
2456 #endif /* HAVE_MACROS */
2458 entry = get_command_entry (command);
2459 if (entry == (COMMAND *)-1)
2461 line_error (_("Unknown command `%s'"), command);
2462 return;
2465 if (entry->argument_in_braces)
2466 remember_brace (entry->proc);
2468 (*(entry->proc)) (START, output_paragraph_offset, 0);
2471 /* Return the string which invokes PROC; a pointer to a function. */
2472 char *
2473 find_proc_name (proc)
2474 COMMAND_FUNCTION *proc;
2476 register int i;
2478 for (i = 0; command_table[i].name; i++)
2479 if (proc == command_table[i].proc)
2480 return command_table[i].name;
2481 return _("NO_NAME!");
2484 void
2485 init_brace_stack ()
2487 brace_stack = (BRACE_ELEMENT *) NULL;
2490 void
2491 remember_brace (proc)
2492 COMMAND_FUNCTION *proc;
2494 if (curchar () != '{')
2495 line_error (_("%c%s expected `{...}'"), COMMAND_PREFIX, command);
2496 else
2497 input_text_offset++;
2498 remember_brace_1 (proc, output_paragraph_offset);
2501 /* Remember the current output position here. Save PROC
2502 along with it so you can call it later. */
2503 void
2504 remember_brace_1 (proc, position)
2505 COMMAND_FUNCTION *proc;
2506 int position;
2508 BRACE_ELEMENT *new = (BRACE_ELEMENT *) xmalloc (sizeof (BRACE_ELEMENT));
2509 new->next = brace_stack;
2510 new->proc = proc;
2511 new->pos = position;
2512 new->line = line_number;
2513 new->in_fixed_width_font = in_fixed_width_font;
2514 brace_stack = new;
2517 /* Pop the top of the brace stack, and call the associated function
2518 with the args END and POS. */
2519 void
2520 pop_and_call_brace ()
2522 BRACE_ELEMENT *temp;
2523 COMMAND_FUNCTION *proc;
2524 int pos;
2526 if (brace_stack == (BRACE_ELEMENT *) NULL)
2528 line_error (_("Unmatched }"));
2529 return;
2532 pos = brace_stack->pos;
2533 proc = brace_stack->proc;
2534 in_fixed_width_font = brace_stack->in_fixed_width_font;
2535 temp = brace_stack->next;
2536 free (brace_stack);
2537 brace_stack = temp;
2539 (*proc) (END, pos, output_paragraph_offset);
2542 /* Shift all of the markers in `brace_stack' by AMOUNT. */
2543 void
2544 adjust_braces_following (here, amount)
2545 int here, amount;
2547 register BRACE_ELEMENT *stack = brace_stack;
2549 while (stack)
2551 if (stack->pos >= here)
2552 stack->pos += amount;
2553 stack = stack->next;
2557 /* You call discard_braces () when you shouldn't have any braces on the stack.
2558 I used to think that this happens for commands that don't take arguments
2559 in braces, but that was wrong because of things like @code{foo @@}. So now
2560 I only detect it at the beginning of nodes. */
2561 void
2562 discard_braces ()
2564 if (!brace_stack)
2565 return;
2567 while (brace_stack)
2569 if (brace_stack->proc != misplaced_brace)
2571 char *proc_name;
2572 int temp_line_number = line_number;
2574 line_number = brace_stack->line;
2575 proc_name = find_proc_name (brace_stack->proc);
2576 line_error (_("%c%s missing close brace"), COMMAND_PREFIX, proc_name);
2577 line_number = temp_line_number;
2578 pop_and_call_brace ();
2580 else
2582 BRACE_ELEMENT *temp;
2583 temp = brace_stack->next;
2584 free (brace_stack);
2585 brace_stack = temp;
2591 get_char_len (character)
2592 int character;
2594 /* Return the printed length of the character. */
2595 int len;
2597 switch (character)
2599 case '\t':
2600 len = (output_column + 8) & 0xf7;
2601 if (len > fill_column)
2602 len = fill_column - output_column;
2603 else
2604 len = len - output_column;
2605 break;
2607 case '\n':
2608 len = fill_column - output_column;
2609 break;
2611 default:
2612 /* ASCII control characters appear as two characters in the output
2613 (e.g., ^A). But characters with the high bit set are just one
2614 on suitable terminals, so don't count them as two for line
2615 breaking purposes. */
2616 if (0 <= character && character < ' ')
2617 len = 2;
2618 else
2619 len = 1;
2621 return (len);
2624 void
2625 #if defined (VA_FPRINTF) && __STDC__
2626 add_word_args (char *format, ...)
2627 #else
2628 add_word_args (format, va_alist)
2629 char *format;
2630 va_dcl
2631 #endif
2633 char buffer[1000];
2634 #ifdef VA_FPRINTF
2635 va_list ap;
2636 #endif
2638 VA_START (ap, format);
2639 #ifdef VA_SPRINTF
2640 VA_SPRINTF (buffer, format, ap);
2641 #else
2642 sprintf (buffer, format, a1, a2, a3, a4, a5, a6, a7, a8);
2643 #endif /* not VA_SPRINTF */
2644 va_end (ap);
2645 add_word (buffer);
2648 /* Add STRING to output_paragraph. */
2649 void
2650 add_word (string)
2651 char *string;
2653 while (*string)
2654 add_char (*string++);
2657 /* Nonzero if the last character inserted has the syntax class of NEWLINE. */
2658 int last_char_was_newline = 1;
2660 /* The actual last inserted character. Note that this may be something
2661 other than NEWLINE even if last_char_was_newline is 1. */
2662 int last_inserted_character = 0;
2664 /* Nonzero means that a newline character has already been
2665 inserted, so close_paragraph () should insert one less. */
2666 int line_already_broken = 0;
2668 /* When nonzero we have finished an insertion (see `end_insertion') and we
2669 want to ignore false continued paragraph closings. */
2670 int insertion_paragraph_closed = 0;
2672 /* Nonzero means attempt to make all of the lines have fill_column width. */
2673 int do_justification = 0;
2675 /* Add the character to the current paragraph. If filling_enabled is
2676 nonzero, then do filling as well. */
2677 void
2678 add_char (character)
2679 int character;
2681 /* If we are avoiding outputting headers, and we are currently
2682 in a menu, then simply return. */
2683 if (no_headers && (in_menu || in_detailmenu))
2684 return;
2686 /* If we are adding a character now, then we don't have to
2687 ignore close_paragraph () calls any more. */
2688 if (must_start_paragraph && character != '\n')
2690 must_start_paragraph = 0;
2691 line_already_broken = 0; /* The line is no longer broken. */
2692 if (current_indent > output_column)
2694 indent (current_indent - output_column);
2695 output_column = current_indent;
2699 if (non_splitting_words && member (character, " \t\n"))
2700 character = ' ' | 0x80;
2702 insertion_paragraph_closed = 0;
2704 switch (character)
2706 case '\n':
2707 if (!filling_enabled)
2709 insert ('\n');
2711 if (force_flush_right)
2713 close_paragraph ();
2714 /* Hack to force single blank lines out in this mode. */
2715 flush_output ();
2718 output_column = 0;
2720 if (!no_indent && paragraph_is_open)
2721 indent (output_column = current_indent);
2722 break;
2724 else /* CHARACTER is newline, and filling is enabled. */
2726 if (end_of_sentence_p ())
2728 insert (' ');
2729 output_column++;
2730 last_inserted_character = character;
2734 if (last_char_was_newline)
2736 close_paragraph ();
2737 pending_indent = 0;
2739 else
2741 last_char_was_newline = 1;
2742 insert (' ');
2743 output_column++;
2745 break;
2747 default:
2749 int len = get_char_len (character);
2750 int suppress_insert = 0;
2752 if ((character == ' ') && (last_char_was_newline))
2754 if (!paragraph_is_open)
2756 pending_indent++;
2757 return;
2761 if (!paragraph_is_open)
2763 start_paragraph ();
2765 /* If the paragraph is supposed to be indented a certain way,
2766 then discard all of the pending whitespace. Otherwise, we
2767 let the whitespace stay. */
2768 if (!paragraph_start_indent)
2769 indent (pending_indent);
2770 pending_indent = 0;
2773 if ((output_column += len) > fill_column)
2775 if (filling_enabled)
2777 int temp = output_paragraph_offset;
2778 while (--temp > 0 && output_paragraph[temp] != '\n')
2780 /* If we have found a space, we have the place to break
2781 the line. */
2782 if (output_paragraph[temp] == ' ')
2784 /* Remove trailing whitespace from output. */
2785 while (temp && whitespace (output_paragraph[temp - 1]))
2786 temp--;
2788 output_paragraph[temp++] = '\n';
2790 /* We have correctly broken the line where we want
2791 to. What we don't want is spaces following where
2792 we have decided to break the line. We get rid of
2793 them. */
2795 int t1 = temp;
2797 for (;; t1++)
2799 if (t1 == output_paragraph_offset)
2801 if (whitespace (character))
2802 suppress_insert = 1;
2803 break;
2805 if (!whitespace (output_paragraph[t1]))
2806 break;
2809 if (t1 != temp)
2811 adjust_braces_following (temp, (- (t1 - temp)));
2812 strncpy ((char *) &output_paragraph[temp],
2813 (char *) &output_paragraph[t1],
2814 (output_paragraph_offset - t1));
2815 output_paragraph_offset -= (t1 - temp);
2819 /* Filled, but now indent if that is right. */
2820 if (indented_fill && current_indent)
2822 int buffer_len = ((output_paragraph_offset - temp)
2823 + current_indent);
2824 char *temp_buffer = (char *)xmalloc (buffer_len);
2825 int indentation = 0;
2827 /* We have to shift any markers that are in
2828 front of the wrap point. */
2829 adjust_braces_following (temp, current_indent);
2831 while (current_indent > 0 &&
2832 indentation != current_indent)
2833 temp_buffer[indentation++] = ' ';
2835 strncpy ((char *) &temp_buffer[current_indent],
2836 (char *) &output_paragraph[temp],
2837 buffer_len - current_indent);
2839 if (output_paragraph_offset + buffer_len
2840 >= paragraph_buffer_len)
2842 unsigned char *tt = xrealloc
2843 (output_paragraph,
2844 (paragraph_buffer_len += buffer_len));
2845 output_paragraph = tt;
2847 strncpy ((char *) &output_paragraph[temp],
2848 temp_buffer, buffer_len);
2849 output_paragraph_offset += current_indent;
2850 free (temp_buffer);
2852 output_column = 0;
2853 while (temp < output_paragraph_offset)
2854 output_column +=
2855 get_char_len (output_paragraph[temp++]);
2856 output_column += len;
2857 break;
2863 if (!suppress_insert)
2865 insert (character);
2866 last_inserted_character = character;
2868 last_char_was_newline = 0;
2869 line_already_broken = 0;
2874 /* Insert CHARACTER into `output_paragraph'. */
2875 void
2876 insert (character)
2877 int character;
2879 output_paragraph[output_paragraph_offset++] = character;
2880 if (output_paragraph_offset == paragraph_buffer_len)
2882 output_paragraph =
2883 xrealloc (output_paragraph, (paragraph_buffer_len += 100));
2887 /* Insert the null-terminated string STRING into `output_paragraph'. */
2888 void
2889 insert_string (string)
2890 char *string;
2892 while (*string)
2893 insert (*string++);
2897 /* Sentences might have these characters after the period (or whatever). */
2898 #define post_sentence(c) ((c) == ')' || (c) == '\'' || (c) == '"' \
2899 || (c) == ']')
2901 /* Return true if at an end-of-sentence character, possibly followed by
2902 post-sentence punctuation to ignore. */
2903 static int
2904 end_of_sentence_p ()
2906 int loc = output_paragraph_offset - 1;
2907 while (loc > 0 && post_sentence (output_paragraph[loc]))
2908 loc--;
2909 return sentence_ender (output_paragraph[loc]);
2913 /* Remove up to COUNT characters of whitespace from the
2914 current output line. If COUNT is less than zero,
2915 then remove until none left. */
2916 void
2917 kill_self_indent (count)
2918 int count;
2920 /* Handle infinite case first. */
2921 if (count < 0)
2923 output_column = 0;
2924 while (output_paragraph_offset)
2926 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2927 output_paragraph_offset--;
2928 else
2929 break;
2932 else
2934 while (output_paragraph_offset && count--)
2935 if (whitespace (output_paragraph[output_paragraph_offset - 1]))
2936 output_paragraph_offset--;
2937 else
2938 break;
2942 /* Nonzero means do not honor calls to flush_output (). */
2943 static int flushing_ignored = 0;
2945 /* Prevent calls to flush_output () from having any effect. */
2946 void
2947 inhibit_output_flushing ()
2949 flushing_ignored++;
2952 /* Allow calls to flush_output () to write the paragraph data. */
2953 void
2954 uninhibit_output_flushing ()
2956 flushing_ignored--;
2959 void
2960 flush_output ()
2962 register int i;
2964 if (!output_paragraph_offset || flushing_ignored)
2965 return;
2967 for (i = 0; i < output_paragraph_offset; i++)
2969 /* If we turned on the 8th bit for a space
2970 inside @w, turn it back off for output. */
2971 if (output_paragraph[i] & meta_character_bit)
2973 int temp = UNMETA (output_paragraph[i]);
2974 if (temp == ' ')
2975 output_paragraph[i] &= 0x7f;
2979 fwrite (output_paragraph, 1, output_paragraph_offset, output_stream);
2981 output_position += output_paragraph_offset;
2982 output_paragraph_offset = 0;
2985 /* How to close a paragraph controlling the number of lines between
2986 this one and the last one. */
2988 /* Paragraph spacing is controlled by this variable. It is the number of
2989 blank lines that you wish to appear between paragraphs. A value of
2990 1 creates a single blank line between paragraphs. */
2991 int paragraph_spacing = DEFAULT_PARAGRAPH_SPACING;
2993 /* Close the current paragraph, leaving no blank lines between them. */
2994 void
2995 close_single_paragraph ()
2997 close_paragraph_with_lines (0);
3000 /* Close a paragraph after an insertion has ended. */
3001 void
3002 close_insertion_paragraph ()
3004 if (!insertion_paragraph_closed)
3006 /* Close the current paragraph, breaking the line. */
3007 close_single_paragraph ();
3009 /* Start a new paragraph, with the correct indentation for the now
3010 current insertion level (one above the one that we are ending). */
3011 start_paragraph ();
3013 /* Tell `close_paragraph' that the previous line has already been
3014 broken, so it should insert one less newline. */
3015 line_already_broken = 1;
3017 /* Tell functions such as `add_char' we've already found a newline. */
3018 ignore_blank_line ();
3020 else
3022 /* If the insertion paragraph is closed already, then we are seeing
3023 two `@end' commands in a row. Note that the first one we saw was
3024 handled in the first part of this if-then-else clause, and at that
3025 time `start_paragraph' was called, partially to handle the proper
3026 indentation of the current line. However, the indentation level
3027 may have just changed again, so we may have to outdent the current
3028 line to the new indentation level. */
3029 if (current_indent < output_column)
3030 kill_self_indent (output_column - current_indent);
3033 insertion_paragraph_closed = 1;
3036 void
3037 close_paragraph_with_lines (lines)
3038 int lines;
3040 int old_spacing = paragraph_spacing;
3041 paragraph_spacing = lines;
3042 close_paragraph ();
3043 paragraph_spacing = old_spacing;
3046 /* Close the currently open paragraph. */
3047 void
3048 close_paragraph ()
3050 register int i;
3052 /* The insertion paragraph is no longer closed. */
3053 insertion_paragraph_closed = 0;
3055 if (paragraph_is_open && !must_start_paragraph)
3057 register int tindex, c;
3059 tindex = output_paragraph_offset;
3061 /* Back up to last non-newline/space character, forcing all such
3062 subsequent characters to be newlines. This isn't strictly
3063 necessary, but a couple of functions use the presence of a newline
3064 to make decisions. */
3065 for (tindex = output_paragraph_offset - 1; tindex >= 0; --tindex)
3067 c = output_paragraph[tindex];
3069 if (c == ' '|| c == '\n')
3070 output_paragraph[tindex] = '\n';
3071 else
3072 break;
3075 /* All trailing whitespace is ignored. */
3076 output_paragraph_offset = ++tindex;
3078 /* Break the line if that is appropriate. */
3079 if (paragraph_spacing >= 0)
3080 insert ('\n');
3082 /* Add as many blank lines as is specified in `paragraph_spacing'. */
3083 if (!force_flush_right)
3085 for (i = 0; i < (paragraph_spacing - line_already_broken); i++)
3086 insert ('\n');
3089 /* If we are doing flush right indentation, then do it now
3090 on the paragraph (really a single line). */
3091 if (force_flush_right)
3092 do_flush_right_indentation ();
3094 flush_output ();
3095 paragraph_is_open = 0;
3096 no_indent = 0;
3097 output_column = 0;
3099 ignore_blank_line ();
3102 /* Make the last line just read look as if it were only a newline. */
3103 void
3104 ignore_blank_line ()
3106 last_inserted_character = '\n';
3107 last_char_was_newline = 1;
3110 /* Align the end of the text in output_paragraph with fill_column. */
3111 void
3112 do_flush_right_indentation ()
3114 char *temp;
3115 int temp_len;
3117 kill_self_indent (-1);
3119 if (output_paragraph[0] != '\n')
3121 output_paragraph[output_paragraph_offset] = 0;
3123 if (output_paragraph_offset < fill_column)
3125 register int i;
3127 if (fill_column >= paragraph_buffer_len)
3128 output_paragraph =
3129 xrealloc (output_paragraph,
3130 (paragraph_buffer_len += fill_column));
3132 temp_len = strlen ((char *)output_paragraph);
3133 temp = (char *)xmalloc (temp_len + 1);
3134 memcpy (temp, (char *)output_paragraph, temp_len);
3136 for (i = 0; i < fill_column - output_paragraph_offset; i++)
3137 output_paragraph[i] = ' ';
3139 memcpy ((char *)output_paragraph + i, temp, temp_len);
3140 free (temp);
3141 output_paragraph_offset = fill_column;
3146 /* Begin a new paragraph. */
3147 void
3148 start_paragraph ()
3150 /* First close existing one. */
3151 if (paragraph_is_open)
3152 close_paragraph ();
3154 /* In either case, the insertion paragraph is no longer closed. */
3155 insertion_paragraph_closed = 0;
3157 /* However, the paragraph is open! */
3158 paragraph_is_open = 1;
3160 /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph ()
3161 had to be called before we would allow any other paragraph operations
3162 to have an effect. */
3163 if (!must_start_paragraph)
3165 int amount_to_indent = 0;
3167 /* If doing indentation, then insert the appropriate amount. */
3168 if (!no_indent)
3170 if (inhibit_paragraph_indentation)
3172 amount_to_indent = current_indent;
3173 if (inhibit_paragraph_indentation < 0)
3174 inhibit_paragraph_indentation++;
3176 else if (paragraph_start_indent < 0)
3177 amount_to_indent = current_indent;
3178 else
3179 amount_to_indent = current_indent + paragraph_start_indent;
3181 if (amount_to_indent >= output_column)
3183 amount_to_indent -= output_column;
3184 indent (amount_to_indent);
3185 output_column += amount_to_indent;
3189 else
3190 must_start_paragraph = 0;
3193 /* Insert the indentation specified by AMOUNT. */
3194 void
3195 indent (amount)
3196 int amount;
3198 register BRACE_ELEMENT *elt = brace_stack;
3200 /* For every START_POS saved within the brace stack which will be affected
3201 by this indentation, bump that start pos forward. */
3202 while (elt)
3204 if (elt->pos >= output_paragraph_offset)
3205 elt->pos += amount;
3206 elt = elt->next;
3209 while (--amount >= 0)
3210 insert (' ');
3213 /* Search forward for STRING in input_text.
3214 FROM says where to start. */
3216 search_forward (string, from)
3217 char *string;
3218 int from;
3220 int len = strlen (string);
3222 while (from < size_of_input_text)
3224 if (strncmp (input_text + from, string, len) == 0)
3225 return (from);
3226 from++;
3228 return (-1);
3231 /* Whoops, Unix doesn't have strcasecmp. */
3233 /* Case independent string compare. */
3234 #if !defined (HAVE_STRCASECMP)
3236 strcasecmp (string1, string2)
3237 char *string1, *string2;
3239 char ch1, ch2;
3241 for (;;)
3243 ch1 = *string1++;
3244 ch2 = *string2++;
3246 if (!(ch1 | ch2))
3247 return (0);
3249 ch1 = coerce_to_upper (ch1);
3250 ch2 = coerce_to_upper (ch2);
3252 if (ch1 != ch2)
3253 return (ch1 - ch2);
3256 #endif /* !HAVE_STRCASECMP */
3258 void
3259 init_insertion_stack ()
3261 insertion_stack = (INSERTION_ELT *) NULL;
3264 /* Return the type of the current insertion. */
3265 enum insertion_type
3266 current_insertion_type ()
3268 if (!insertion_level)
3269 return (bad_type);
3270 else
3271 return (insertion_stack->insertion);
3274 /* Return a pointer to the string which is the function to wrap around
3275 items. */
3276 char *
3277 current_item_function ()
3279 register int level, done;
3280 register INSERTION_ELT *elt;
3282 level = insertion_level;
3283 elt = insertion_stack;
3284 done = 0;
3286 /* Skip down through the stack until we find a non-conditional insertion. */
3287 while (!done && (elt != NULL))
3289 switch (elt->insertion)
3291 case ifinfo:
3292 case ifnothtml:
3293 case ifnottex:
3294 case ifset:
3295 case ifclear:
3296 case cartouche:
3297 elt = elt->next;
3298 level--;
3299 break;
3301 default:
3302 done = 1;
3306 if (!level)
3307 return ((char *) NULL);
3308 else
3309 return (elt->item_function);
3312 char *
3313 get_item_function ()
3315 char *item_function;
3316 get_rest_of_line (&item_function);
3317 backup_input_pointer ();
3318 return (item_function);
3321 /* Push the state of the current insertion on the stack. */
3322 void
3323 push_insertion (type, item_function)
3324 enum insertion_type type;
3325 char *item_function;
3327 INSERTION_ELT *new = (INSERTION_ELT *) xmalloc (sizeof (INSERTION_ELT));
3329 new->item_function = item_function;
3330 new->filling_enabled = filling_enabled;
3331 new->indented_fill = indented_fill;
3332 new->insertion = type;
3333 new->line_number = line_number;
3334 new->filename = xstrdup (input_filename);
3335 new->inhibited = inhibit_paragraph_indentation;
3336 new->in_fixed_width_font = in_fixed_width_font;
3337 new->next = insertion_stack;
3338 insertion_stack = new;
3339 insertion_level++;
3342 /* Pop the value on top of the insertion stack into the
3343 global variables. */
3344 void
3345 pop_insertion ()
3347 INSERTION_ELT *temp = insertion_stack;
3349 if (temp == (INSERTION_ELT *) NULL)
3350 return;
3352 in_fixed_width_font = temp->in_fixed_width_font;
3353 inhibit_paragraph_indentation = temp->inhibited;
3354 filling_enabled = temp->filling_enabled;
3355 indented_fill = temp->indented_fill;
3356 free_and_clear (&(temp->item_function));
3357 free_and_clear (&(temp->filename));
3358 insertion_stack = insertion_stack->next;
3359 free (temp);
3360 insertion_level--;
3363 /* Return a pointer to the print name of this
3364 enumerated type. */
3365 char *
3366 insertion_type_pname (type)
3367 enum insertion_type type;
3369 if ((int) type < (int) bad_type)
3370 return (insertion_type_names[(int) type]);
3371 else
3372 return (_("Broken-Type in insertion_type_pname"));
3375 /* Return the insertion_type associated with NAME.
3376 If the type is not one of the known ones, return BAD_TYPE. */
3377 enum insertion_type
3378 find_type_from_name (name)
3379 char *name;
3381 int index = 0;
3382 while (index < (int) bad_type)
3384 if (strcmp (name, insertion_type_names[index]) == 0)
3385 return (enum insertion_type) index;
3386 index++;
3388 return (bad_type);
3392 defun_insertion (type)
3393 enum insertion_type type;
3395 return
3396 ((type == deffn)
3397 || (type == defun)
3398 || (type == defmac)
3399 || (type == defspec)
3400 || (type == defvr)
3401 || (type == defvar)
3402 || (type == defopt)
3403 || (type == deftypefn)
3404 || (type == deftypefun)
3405 || (type == deftypevr)
3406 || (type == deftypevar)
3407 || (type == defcv)
3408 || (type == defivar)
3409 || (type == defop)
3410 || (type == defmethod)
3411 || (type == deftypemethod)
3412 || (type == deftp));
3415 /* MAX_NS is the maximum nesting level for enumerations. I picked 100
3416 which seemed reasonable. This doesn't control the number of items,
3417 just the number of nested lists. */
3418 #define max_stack_depth 100
3419 #define ENUM_DIGITS 1
3420 #define ENUM_ALPHA 2
3421 typedef struct {
3422 int enumtype;
3423 int enumval;
3424 } DIGIT_ALPHA;
3426 DIGIT_ALPHA enumstack[max_stack_depth];
3427 int enumstack_offset = 0;
3428 int current_enumval = 1;
3429 int current_enumtype = ENUM_DIGITS;
3430 char *enumeration_arg = (char *)NULL;
3432 void
3433 start_enumerating (at, type)
3434 int at, type;
3436 if ((enumstack_offset + 1) == max_stack_depth)
3438 line_error (_("Enumeration stack overflow"));
3439 return;
3441 enumstack[enumstack_offset].enumtype = current_enumtype;
3442 enumstack[enumstack_offset].enumval = current_enumval;
3443 enumstack_offset++;
3444 current_enumval = at;
3445 current_enumtype = type;
3448 void
3449 stop_enumerating ()
3451 --enumstack_offset;
3452 if (enumstack_offset < 0)
3453 enumstack_offset = 0;
3455 current_enumval = enumstack[enumstack_offset].enumval;
3456 current_enumtype = enumstack[enumstack_offset].enumtype;
3459 /* Place a letter or digits into the output stream. */
3460 void
3461 enumerate_item ()
3463 char temp[10];
3465 if (current_enumtype == ENUM_ALPHA)
3467 if (current_enumval == ('z' + 1) || current_enumval == ('Z' + 1))
3469 current_enumval = ((current_enumval - 1) == 'z' ? 'a' : 'A');
3470 warning (_("lettering overflow, restarting at %c"), current_enumval);
3472 sprintf (temp, "%c. ", current_enumval);
3474 else
3475 sprintf (temp, "%d. ", current_enumval);
3477 indent (output_column += (current_indent - strlen (temp)));
3478 add_word (temp);
3479 current_enumval++;
3482 /* This is where the work for all the "insertion" style
3483 commands is done. A huge switch statement handles the
3484 various setups, and generic code is on both sides. */
3485 void
3486 begin_insertion (type)
3487 enum insertion_type type;
3489 int no_discard = 0;
3491 if (defun_insertion (type))
3493 push_insertion (type, xstrdup (""));
3494 no_discard++;
3496 else
3497 push_insertion (type, get_item_function ());
3499 switch (type)
3501 case menu:
3502 if (!no_headers)
3503 close_paragraph ();
3505 filling_enabled = no_indent = 0;
3506 inhibit_paragraph_indentation = 1;
3508 if (!no_headers)
3509 add_word (_("* Menu:\n"));
3511 in_menu++;
3512 no_discard++;
3513 break;
3515 case detailmenu:
3516 if (!in_menu)
3518 if (!no_headers)
3519 close_paragraph ();
3521 filling_enabled = no_indent = 0;
3522 inhibit_paragraph_indentation = 1;
3524 no_discard++;
3527 in_detailmenu++;
3528 break;
3530 case direntry:
3531 close_single_paragraph ();
3532 filling_enabled = no_indent = 0;
3533 inhibit_paragraph_indentation = 1;
3534 insert_string ("START-INFO-DIR-ENTRY\n");
3535 break;
3537 /* I think @quotation is meant to do filling.
3538 If you don't want filling, then use @display. */
3539 case quotation:
3540 close_single_paragraph ();
3541 last_char_was_newline = no_indent = 0;
3542 indented_fill = filling_enabled = 1;
3543 inhibit_paragraph_indentation = 1;
3544 current_indent += default_indentation_increment;
3545 break;
3547 case display:
3548 case example:
3549 case smallexample:
3550 case lisp:
3551 case smalllisp:
3552 /* Just like @example, but no indentation. */
3553 case format:
3554 close_single_paragraph ();
3555 inhibit_paragraph_indentation = 1;
3556 in_fixed_width_font++;
3557 filling_enabled = 0;
3558 last_char_was_newline = 0;
3559 if (type != format)
3560 current_indent += default_indentation_increment;
3561 break;
3563 case multitable:
3564 do_multitable ();
3565 break;
3567 case table:
3568 case ftable:
3569 case vtable:
3570 case itemize:
3571 close_single_paragraph ();
3572 current_indent += default_indentation_increment;
3573 filling_enabled = indented_fill = 1;
3574 #if defined (INDENT_PARAGRAPHS_IN_TABLE)
3575 inhibit_paragraph_indentation = 0;
3576 #else
3577 inhibit_paragraph_indentation = 1;
3578 #endif /* !INDENT_PARAGRAPHS_IN_TABLE */
3580 /* Make things work for losers who forget the itemize syntax. */
3581 if (allow_lax_format && (type == itemize))
3583 if (!(*insertion_stack->item_function))
3585 free (insertion_stack->item_function);
3586 insertion_stack->item_function = xstrdup ("@bullet");
3587 insertion_stack->item_function[0] = COMMAND_PREFIX;
3591 if (!*insertion_stack->item_function)
3593 line_error (_("%s requires an argument: the formatter for %citem"),
3594 insertion_type_pname (type), COMMAND_PREFIX);
3596 break;
3598 case enumerate:
3599 close_single_paragraph ();
3600 no_indent = 0;
3601 #if defined (INDENT_PARAGRAPHS_IN_TABLE)
3602 inhibit_paragraph_indentation = 0;
3603 #else
3604 inhibit_paragraph_indentation = 1;
3605 #endif /* !INDENT_PARAGRAPHS_IN_TABLE */
3607 current_indent += default_indentation_increment;
3608 filling_enabled = indented_fill = 1;
3610 if (isdigit (*enumeration_arg))
3611 start_enumerating (atoi (enumeration_arg), ENUM_DIGITS);
3612 else
3613 start_enumerating (*enumeration_arg, ENUM_ALPHA);
3614 break;
3616 /* Does nothing special in makeinfo. */
3617 case group:
3618 /* Only close the paragraph if we are not inside of an @example. */
3619 if (!insertion_stack->next ||
3620 insertion_stack->next->insertion != example)
3621 close_single_paragraph ();
3622 break;
3624 /* Insertions that are no-ops in info, but do something in TeX. */
3625 case ifinfo:
3626 case ifnothtml:
3627 case ifnottex:
3628 case ifset:
3629 case ifclear:
3630 case cartouche:
3631 if (in_menu)
3632 no_discard++;
3633 break;
3635 case deffn:
3636 case defun:
3637 case defmac:
3638 case defspec:
3639 case defvr:
3640 case defvar:
3641 case defopt:
3642 case deftypefn:
3643 case deftypefun:
3644 case deftypevr:
3645 case deftypevar:
3646 case defcv:
3647 case defivar:
3648 case defop:
3649 case defmethod:
3650 case deftypemethod:
3651 case deftp:
3652 inhibit_paragraph_indentation = 1;
3653 filling_enabled = indented_fill = 1;
3654 current_indent += default_indentation_increment;
3655 no_indent = 0;
3656 break;
3658 case flushleft:
3659 close_single_paragraph ();
3660 inhibit_paragraph_indentation = 1;
3661 filling_enabled = indented_fill = no_indent = 0;
3662 break;
3664 case flushright:
3665 close_single_paragraph ();
3666 filling_enabled = indented_fill = no_indent = 0;
3667 inhibit_paragraph_indentation = 1;
3668 force_flush_right++;
3669 break;
3672 if (!no_discard)
3673 discard_until ("\n");
3676 /* Try to end the insertion with the specified TYPE. With a value of
3677 `bad_type', TYPE gets translated to match the value currently on top
3678 of the stack. Otherwise, if TYPE doesn't match the top of the
3679 insertion stack, give error. */
3680 void
3681 end_insertion (type)
3682 enum insertion_type type;
3684 enum insertion_type temp_type;
3686 if (!insertion_level)
3687 return;
3689 temp_type = current_insertion_type ();
3691 if (type == bad_type)
3692 type = temp_type;
3694 if (type != temp_type)
3696 line_error
3697 (_("`%cend' expected `%s', but saw `%s'"), COMMAND_PREFIX,
3698 insertion_type_pname (temp_type), insertion_type_pname (type));
3699 return;
3702 pop_insertion ();
3704 switch (type)
3706 /* Insertions which have no effect on paragraph formatting. */
3707 case ifnothtml:
3708 case ifnottex:
3709 case ifinfo:
3710 case ifset:
3711 case ifclear:
3712 break;
3714 case direntry:
3715 insert_string ("END-INFO-DIR-ENTRY\n\n");
3716 close_insertion_paragraph ();
3717 break;
3719 case detailmenu:
3720 in_detailmenu--; /* No longer hacking menus. */
3721 if (!in_menu)
3723 if (!no_headers)
3724 close_insertion_paragraph ();
3726 break;
3728 case menu:
3729 in_menu--; /* No longer hacking menus. */
3730 if (!no_headers)
3731 close_insertion_paragraph ();
3732 break;
3734 case multitable:
3735 end_multitable ();
3736 break;
3738 case enumerate:
3739 stop_enumerating ();
3740 close_insertion_paragraph ();
3741 current_indent -= default_indentation_increment;
3742 break;
3744 case flushleft:
3745 case group:
3746 case cartouche:
3747 close_insertion_paragraph ();
3748 break;
3750 case format:
3751 case display:
3752 case example:
3753 case smallexample:
3754 case lisp:
3755 case smalllisp:
3756 case quotation:
3757 /* @format is the only fixed_width insertion without a change
3758 in indentation. */
3759 if (type != format)
3760 current_indent -= default_indentation_increment;
3762 /* The ending of one of these insertions always marks the
3763 start of a new paragraph. */
3764 close_insertion_paragraph ();
3765 break;
3767 case table:
3768 case ftable:
3769 case vtable:
3770 case itemize:
3771 current_indent -= default_indentation_increment;
3772 break;
3774 case flushright:
3775 force_flush_right--;
3776 close_insertion_paragraph ();
3777 break;
3779 /* Handle the @defun style insertions with a default clause. */
3780 default:
3781 current_indent -= default_indentation_increment;
3782 close_insertion_paragraph ();
3783 break;
3787 /* Insertions cannot cross certain boundaries, such as node beginnings. In
3788 code that creates such boundaries, you should call `discard_insertions'
3789 before doing anything else. It prints the errors for you, and cleans up
3790 the insertion stack. With nonzero SPECIALS_OK, allows unmatched
3791 ifinfo, ifset, ifclear, otherwise not. */
3792 void
3793 discard_insertions (specials_ok)
3794 int specials_ok;
3796 int real_line_number = line_number;
3797 while (insertion_stack)
3799 if (specials_ok && (insertion_stack->insertion == ifinfo
3800 || insertion_stack->insertion == ifset
3801 || insertion_stack->insertion == ifclear))
3802 break;
3803 else
3805 char *offender = insertion_type_pname (insertion_stack->insertion);
3806 char *current_filename = input_filename;
3808 input_filename = insertion_stack->filename;
3809 line_number = insertion_stack->line_number;
3810 line_error (_("No matching `%cend %s'"), COMMAND_PREFIX, offender);
3811 input_filename = current_filename;
3812 pop_insertion ();
3815 line_number = real_line_number;
3818 /* The Texinfo commands. */
3820 /* Commands which insert their own names. */
3821 void
3822 insert_self (arg)
3823 int arg;
3825 if (arg == START)
3826 add_word (command);
3829 void
3830 insert_space (arg)
3831 int arg;
3833 if (arg == START)
3834 add_char (' ');
3837 /* Force a line break in the output. */
3838 void
3839 cm_asterisk ()
3841 close_single_paragraph ();
3842 cm_noindent ();
3845 /* Insert ellipsis. */
3846 void
3847 cm_dots (arg)
3848 int arg;
3850 if (arg == START)
3851 add_word ("...");
3854 /* Insert ellipsis for sentence end. */
3855 void
3856 cm_enddots (arg)
3857 int arg;
3859 if (arg == START)
3860 add_word ("....");
3863 void
3864 cm_bullet (arg)
3865 int arg;
3867 if (arg == START)
3868 add_char ('*');
3871 void
3872 cm_minus (arg)
3873 int arg;
3875 if (arg == START)
3876 add_char ('-');
3879 /* Insert "TeX". */
3880 void
3881 cm_TeX (arg)
3882 int arg;
3884 if (arg == START)
3885 add_word ("TeX");
3888 /* Copyright symbol. */
3889 void
3890 cm_copyright (arg)
3891 int arg;
3893 if (arg == START)
3894 add_word ("(C)");
3897 /* Accent commands that take explicit arguments. */
3898 void
3899 cm_accent (arg)
3900 int arg;
3902 if (arg == START)
3904 if (strcmp (command, "dotaccent") == 0) /* overdot */
3905 add_char ('.');
3906 else if (strcmp (command, "H") == 0) /* Hungarian umlaut */
3907 add_word ("''");
3908 else if (strcmp (command, "ringaccent") == 0)
3909 add_char ('*');
3910 else if (strcmp (command, "tieaccent") == 0)
3911 add_char ('[');
3912 else if (strcmp (command, "u") == 0) /* breve */
3913 add_char ('(');
3914 else if (strcmp (command, "v") == 0) /* hacek/check */
3915 add_char ('<');
3917 else if (arg == END)
3919 if (strcmp (command, "ubaraccent") == 0) /* underbar */
3920 add_char ('_');
3921 else if (strcmp (command, "udotaccent") == 0) /* underdot */
3922 add_word ("-.");
3923 else if (strcmp (command, ",") == 0) /* cedilla */
3924 add_word (",");
3928 /* Non-English letters/characters that don't insert themselves. */
3929 void
3930 cm_special_char (arg)
3932 if (arg == START)
3934 if ((*command == 'L' || *command == 'l'
3935 || *command == 'O' || *command == 'o')
3936 && command[1] == 0)
3938 /* Lslash lslash Oslash oslash */
3939 add_char (*command);
3940 add_char ('/');
3942 else if (strcmp (command, "exclamdown") == 0)
3943 add_char ('!');
3944 else if (strcmp (command, "pounds") == 0)
3945 add_char ('#');
3946 else if (strcmp (command, "questiondown") == 0)
3947 add_char ('?');
3948 else
3949 fprintf (stderr, _("How did @%s end up in cm_special_char?\n"), command);
3953 /* Dotless i or j. */
3954 void
3955 cm_dotless (arg, start, end)
3956 int arg, start, end;
3958 if (arg == END)
3960 if (output_paragraph[start] != 'i' && output_paragraph[start] != 'j')
3961 /* This error message isn't perfect if the argument is multiple
3962 characters, but it doesn't seem worth getting right. */
3963 line_error (_("%c%s expects `i' or `j' as argument, not `%c'"),
3964 COMMAND_PREFIX, command, output_paragraph[start]);
3966 else if (end - start != 1)
3967 line_error (_("%c%s expects a single character `i' or `j' as argument"),
3968 COMMAND_PREFIX, command);
3970 /* We've already inserted the `i' or `j', so nothing to do. */
3974 void
3975 cm_today (arg)
3976 int arg;
3978 static char *months [12] =
3979 { N_("January"), N_("February"), N_("March"), N_("April"), N_("May"),
3980 N_("June"), N_("July"), N_("August"), N_("September"), N_("October"),
3981 N_("November"), N_("December") };
3982 if (arg == START)
3984 time_t timer = time (0);
3985 struct tm *ts = localtime (&timer);
3986 add_word_args ("%d %s %d", ts->tm_mday, _(months[ts->tm_mon]),
3987 ts->tm_year + 1900);
3991 void
3992 cm_code (arg)
3993 int arg;
3995 extern int printing_index;
3997 if (arg == START)
3999 in_fixed_width_font++;
4001 if (!printing_index)
4002 add_char ('`');
4004 else
4006 if (!printing_index)
4007 add_char ('\'');
4011 void
4012 cm_kbd (arg)
4013 int arg;
4015 /* People use @kbd in an example to get the "user input" font.
4016 We don't want quotes in that case. */
4017 if (!in_fixed_width_font)
4018 cm_code (arg);
4021 void
4022 cm_key (arg)
4023 int arg;
4025 add_char (arg == START ? '<' : '>');
4028 /* Convert the character at position into a true control character. */
4029 void
4030 cm_ctrl (arg, start, end)
4031 int arg, start, end;
4033 /* Should we allow multiple character arguments? I think yes. */
4034 if (arg == END)
4036 register int i, character;
4037 #if defined (NO_MULTIPLE_CTRL)
4038 if ((end - start) != 1)
4039 line_error (_("%c%s expects a single character as an argument"),
4040 COMMAND_PREFIX, command);
4041 else
4042 #endif
4043 for (i = start; i < end; i++)
4045 character = output_paragraph[i];
4047 if (isletter (character))
4048 output_paragraph[i] = CTL (coerce_to_upper (character));
4053 /* Handle a command that switches to a non-fixed-width font. */
4054 void
4055 not_fixed_width (arg)
4056 int arg;
4058 if (arg == START)
4059 in_fixed_width_font = 0;
4062 /* Small caps and @var in makeinfo just uppercase the text. */
4063 void
4064 cm_var_sc (arg, start_pos, end_pos)
4065 int arg, start_pos, end_pos;
4067 not_fixed_width (arg);
4069 if (arg == END)
4071 while (start_pos < end_pos)
4073 output_paragraph[start_pos] =
4074 coerce_to_upper (output_paragraph[start_pos]);
4075 start_pos++;
4080 void
4081 cm_dfn (arg, position)
4082 int arg, position;
4084 add_char ('"');
4087 void
4088 cm_emph (arg)
4089 int arg;
4091 add_char ('*');
4094 void
4095 cm_strong (arg, position)
4096 int arg, position;
4098 cm_emph (arg);
4101 void
4102 cm_cite (arg, position)
4103 int arg, position;
4105 if (arg == START)
4106 add_word ("`");
4107 else
4108 add_word ("'");
4111 /* No highlighting, but argument switches fonts. */
4112 void
4113 cm_not_fixed_width (arg, start, end)
4114 int arg, start, end;
4116 not_fixed_width (arg);
4119 /* Various commands are no-op's. */
4120 void
4121 cm_no_op ()
4125 /* No-op that eats its argument on same line. */
4126 void
4127 cm_no_op_line_arg ()
4129 char *temp;
4130 get_rest_of_line (&temp);
4131 free (temp);
4134 /* Prevent the argument from being split across two lines. */
4135 void
4136 cm_w (arg, start, end)
4137 int arg, start, end;
4139 if (arg == START)
4140 non_splitting_words++;
4141 else
4142 non_splitting_words--;
4146 /* Explain that this command is obsolete, thus the user shouldn't
4147 do anything with it. */
4148 void
4149 cm_obsolete (arg, start, end)
4150 int arg, start, end;
4152 if (arg == START)
4153 warning (_("%c%s is obsolete"), COMMAND_PREFIX, command);
4156 /* Insert the text following input_text_offset up to the end of the line
4157 in a new, separate paragraph. Directly underneath it, insert a
4158 line of WITH_CHAR, the same length of the inserted text. */
4159 void
4160 insert_and_underscore (with_char)
4161 int with_char;
4163 register int i, len;
4164 int old_no_indent, starting_pos, ending_pos;
4165 char *temp;
4167 close_paragraph ();
4168 filling_enabled = indented_fill = 0;
4169 old_no_indent = no_indent;
4170 no_indent = 1;
4172 #if defined (HAVE_MACROS)
4173 if (macro_expansion_output_stream && !executing_string)
4174 append_to_expansion_output (input_text_offset + 1);
4175 #endif /* HAVE_MACROS */
4177 get_rest_of_line (&temp);
4179 starting_pos = output_position + output_paragraph_offset;
4180 #if defined (HAVE_MACROS)
4181 if (macro_expansion_output_stream && !executing_string)
4183 char *temp1 = (char *) xmalloc (2 + strlen (temp));
4184 sprintf (temp1, "%s\n", temp);
4185 remember_itext (input_text, input_text_offset);
4186 me_execute_string (temp1);
4187 free (temp1);
4189 else
4190 #endif /* HAVE_MACROS */
4191 execute_string ("%s\n", temp);
4193 ending_pos = output_position + output_paragraph_offset;
4194 free (temp);
4196 len = (ending_pos - starting_pos) - 1;
4197 for (i = 0; i < len; i++)
4198 add_char (with_char);
4199 insert ('\n');
4200 close_paragraph ();
4201 filling_enabled = 1;
4202 no_indent = old_no_indent;
4205 /* Here is a structure which associates sectioning commands with
4206 an integer, hopefully to reflect the `depth' of the current
4207 section. */
4208 struct {
4209 char *name;
4210 int level;
4211 } section_alist[] = {
4212 { "unnumberedsubsubsec", 5 },
4213 { "unnumberedsubsec", 4 },
4214 { "unnumberedsec", 3 },
4215 { "unnumbered", 2 },
4216 { "appendixsubsubsec", 5 },
4217 { "appendixsubsec", 4 },
4218 { "appendixsec", 3 },
4219 { "appendixsection", 3 },
4220 { "appendix", 2 },
4221 { "subsubsec", 5 },
4222 { "subsubsection", 5 },
4223 { "subsection", 4 },
4224 { "section", 3 },
4225 { "chapter", 2 },
4226 { "top", 1 },
4228 { (char *)NULL, 0 }
4231 /* Amount to offset the name of sectioning commands to levels by. */
4232 int section_alist_offset = 0;
4234 /* Shift the meaning of @section to @chapter. */
4235 void
4236 cm_raisesections ()
4238 discard_until ("\n");
4239 section_alist_offset--;
4242 /* Shift the meaning of @chapter to @section. */
4243 void
4244 cm_lowersections ()
4246 discard_until ("\n");
4247 section_alist_offset++;
4250 /* Return an integer which identifies the type section present in TEXT. */
4252 what_section (text)
4253 char *text;
4255 register int i, j;
4256 char *t;
4258 find_section_command:
4259 for (j = 0; text[j] && cr_or_whitespace (text[j]); j++);
4260 if (text[j] != COMMAND_PREFIX)
4261 return (-1);
4263 text = text + j + 1;
4265 /* We skip @c, @comment, and @?index commands. */
4266 if ((strncmp (text, "comment", strlen ("comment")) == 0) ||
4267 (text[0] == 'c' && cr_or_whitespace (text[1])) ||
4268 (strcmp (text + 1, "index") == 0))
4270 while (*text++ != '\n');
4271 goto find_section_command;
4274 /* Handle italicized sectioning commands. */
4275 if (*text == 'i')
4276 text++;
4278 for (j = 0; text[j] && !cr_or_whitespace (text[j]); j++);
4280 for (i = 0; (t = section_alist[i].name); i++)
4282 if (j == strlen (t) && strncmp (t, text, j) == 0)
4284 int return_val;
4286 return_val = (section_alist[i].level + section_alist_offset);
4288 if (return_val < 0)
4289 return_val = 0;
4290 else if (return_val > 5)
4291 return_val = 5;
4292 return (return_val);
4295 return (-1);
4298 /* Set the level of @top to LEVEL. Return the old level of @top. */
4300 set_top_section_level (level)
4301 int level;
4303 register int i, result = -1;
4305 for (i = 0; section_alist[i].name; i++)
4306 if (strcmp (section_alist[i].name, "top") == 0)
4308 result = section_alist[i].level;
4309 section_alist[i].level = level;
4310 break;
4312 return (result);
4315 /* Treat this just like @unnumbered. The only difference is
4316 in node defaulting. */
4317 void
4318 cm_top ()
4320 /* It is an error to have more than one @top. */
4321 if (top_node_seen)
4323 TAG_ENTRY *tag = tag_table;
4325 line_error (_("Node with %ctop as a section already exists"),
4326 COMMAND_PREFIX);
4328 while (tag != (TAG_ENTRY *)NULL)
4330 if ((tag->flags & IS_TOP))
4332 int old_line_number = line_number;
4333 char *old_input_filename = input_filename;
4335 line_number = tag->line_no;
4336 input_filename = tag->filename;
4337 line_error (_("Here is the %ctop node"), COMMAND_PREFIX);
4338 input_filename = old_input_filename;
4339 line_number = old_line_number;
4340 return;
4342 tag = tag->next_ent;
4345 else
4347 top_node_seen = 1;
4349 /* It is an error to use @top before you have used @node. */
4350 if (!tag_table)
4352 char *top_name;
4354 get_rest_of_line (&top_name);
4355 free (top_name);
4356 line_error (_("%ctop used before %cnode, defaulting to %s"),
4357 COMMAND_PREFIX, COMMAND_PREFIX, top_name);
4358 execute_string ("@node Top, , (dir), (dir)\n@top %s\n", top_name);
4359 return;
4362 cm_unnumbered ();
4364 /* The most recently defined node is the top node. */
4365 tag_table->flags |= IS_TOP;
4367 /* Now set the logical hierarchical level of the Top node. */
4369 int orig_offset = input_text_offset;
4371 input_text_offset = search_forward (node_search_string, orig_offset);
4373 if (input_text_offset > 0)
4375 int this_section;
4377 /* We have encountered a non-top node, so mark that one exists. */
4378 non_top_node_seen = 1;
4380 /* Move to the end of this line, and find out what the
4381 sectioning command is here. */
4382 while (input_text[input_text_offset] != '\n')
4383 input_text_offset++;
4385 if (input_text_offset < size_of_input_text)
4386 input_text_offset++;
4388 this_section = what_section (input_text + input_text_offset);
4390 /* If we found a sectioning command, then give the top section
4391 a level of this section - 1. */
4392 if (this_section != -1)
4393 set_top_section_level (this_section - 1);
4395 input_text_offset = orig_offset;
4400 /* Organized by level commands. That is, "*" == chapter, "=" == section. */
4401 char *scoring_characters = "*=-.";
4403 void
4404 sectioning_underscore (command)
4405 char *command;
4407 char character;
4408 char *temp;
4409 int level;
4411 temp = (char *)xmalloc (2 + strlen (command));
4412 temp[0] = COMMAND_PREFIX;
4413 strcpy (&temp[1], command);
4414 level = what_section (temp);
4415 free (temp);
4416 level -= 2;
4418 if (level < 0)
4419 level = 0;
4421 character = scoring_characters[level];
4423 insert_and_underscore (character);
4426 /* The command still works, but prints a warning message in addition. */
4427 void
4428 cm_ideprecated (arg, start, end)
4429 int arg, start, end;
4431 warning (_("%c%s is obsolete; use %c%s instead"),
4432 COMMAND_PREFIX, command, COMMAND_PREFIX, command + 1);
4433 sectioning_underscore (command + 1);
4436 /* The remainder of the text on this line is a chapter heading. */
4437 void
4438 cm_chapter ()
4440 sectioning_underscore ("chapter");
4443 /* The remainder of the text on this line is a section heading. */
4444 void
4445 cm_section ()
4447 sectioning_underscore ("section");
4450 /* The remainder of the text on this line is a subsection heading. */
4451 void
4452 cm_subsection ()
4454 sectioning_underscore ("subsection");
4457 /* The remainder of the text on this line is a subsubsection heading. */
4458 void
4459 cm_subsubsection ()
4461 sectioning_underscore ("subsubsection");
4464 /* The remainder of the text on this line is an unnumbered heading. */
4465 void
4466 cm_unnumbered ()
4468 cm_chapter ();
4471 /* The remainder of the text on this line is an unnumbered section heading. */
4472 void
4473 cm_unnumberedsec ()
4475 cm_section ();
4478 /* The remainder of the text on this line is an unnumbered
4479 subsection heading. */
4480 void
4481 cm_unnumberedsubsec ()
4483 cm_subsection ();
4486 /* The remainder of the text on this line is an unnumbered
4487 subsubsection heading. */
4488 void
4489 cm_unnumberedsubsubsec ()
4491 cm_subsubsection ();
4494 /* The remainder of the text on this line is an appendix heading. */
4495 void
4496 cm_appendix ()
4498 cm_chapter ();
4501 /* The remainder of the text on this line is an appendix section heading. */
4502 void
4503 cm_appendixsec ()
4505 cm_section ();
4508 /* The remainder of the text on this line is an appendix subsection heading. */
4509 void
4510 cm_appendixsubsec ()
4512 cm_subsection ();
4515 /* The remainder of the text on this line is an appendix
4516 subsubsection heading. */
4517 void
4518 cm_appendixsubsubsec ()
4520 cm_subsubsection ();
4523 /* Compatibility functions substitute for chapter, section, etc. */
4524 void
4525 cm_majorheading ()
4527 cm_chapheading ();
4530 void
4531 cm_chapheading ()
4533 cm_chapter ();
4536 void
4537 cm_heading ()
4539 cm_section ();
4542 void
4543 cm_subheading ()
4545 cm_subsection ();
4548 void
4549 cm_subsubheading ()
4551 cm_subsubsection ();
4554 /* **************************************************************** */
4555 /* */
4556 /* Adding nodes, and making tags */
4557 /* */
4558 /* **************************************************************** */
4560 /* Start a new tag table. */
4561 void
4562 init_tag_table ()
4564 while (tag_table != (TAG_ENTRY *) NULL)
4566 TAG_ENTRY *temp = tag_table;
4567 free (temp->node);
4568 free (temp->prev);
4569 free (temp->next);
4570 free (temp->up);
4571 tag_table = tag_table->next_ent;
4572 free (temp);
4576 void
4577 write_tag_table ()
4579 write_tag_table_internal (0); /* Not indirect. */
4582 void
4583 write_tag_table_indirect ()
4585 write_tag_table_internal (1);
4588 /* Write out the contents of the existing tag table.
4589 INDIRECT_P says how to format the output. */
4590 void
4591 write_tag_table_internal (indirect_p)
4592 int indirect_p;
4594 TAG_ENTRY *node = tag_table;
4595 int old_indent = no_indent;
4597 no_indent = 1;
4598 filling_enabled = 0;
4599 must_start_paragraph = 0;
4600 close_paragraph ();
4602 if (!indirect_p)
4604 no_indent = 1;
4605 insert ('\n');
4608 add_word_args ("\037\nTag Table:\n%s", indirect_p ? "(Indirect)\n" : "");
4610 while (node != (TAG_ENTRY *) NULL)
4612 execute_string ("Node: %s", node->node);
4613 add_word_args ("\177%d\n", node->position);
4614 node = node->next_ent;
4617 add_word ("\037\nEnd Tag Table\n");
4618 flush_output ();
4619 no_indent = old_indent;
4622 char *
4623 get_node_token (expand)
4624 int expand;
4626 char *string;
4628 get_until_in_line (expand, ",", &string);
4630 if (curchar () == ',')
4631 input_text_offset++;
4633 canon_white (string);
4635 /* Force all versions of "top" to be "Top". */
4636 normalize_node_name (string);
4638 return (string);
4641 /* Convert "top" and friends into "Top". */
4642 void
4643 normalize_node_name (string)
4644 char *string;
4646 if (strcasecmp (string, "Top") == 0)
4647 strcpy (string, "Top");
4650 /* Look up NAME in the tag table, and return the associated
4651 tag_entry. If the node is not in the table return NULL. */
4652 TAG_ENTRY *
4653 find_node (name)
4654 char *name;
4656 TAG_ENTRY *tag = tag_table;
4658 while (tag != (TAG_ENTRY *) NULL)
4660 if (strcmp (tag->node, name) == 0)
4661 return (tag);
4662 tag = tag->next_ent;
4664 return ((TAG_ENTRY *) NULL);
4667 /* Remember NODE and associates. */
4668 void
4669 remember_node (node, prev, next, up, position, line_no, no_warn)
4670 char *node, *prev, *next, *up;
4671 int position, line_no, no_warn;
4673 /* Check for existence of this tag already. */
4674 if (validating)
4676 register TAG_ENTRY *tag = find_node (node);
4677 if (tag)
4679 line_error (
4680 _("Node `%s' multiply defined (line %d is first definition at)"),
4681 node, tag->line_no);
4682 return;
4686 /* First, make this the current node. */
4687 current_node = node;
4689 /* Now add it to the list. */
4691 TAG_ENTRY *new = (TAG_ENTRY *) xmalloc (sizeof (TAG_ENTRY));
4692 new->node = node;
4693 new->prev = prev;
4694 new->next = next;
4695 new->up = up;
4696 new->position = position;
4697 new->line_no = line_no;
4698 new->filename = node_filename;
4699 new->touched = 0; /* not yet referenced. */
4700 new->flags = 0;
4701 if (no_warn)
4702 new->flags |= NO_WARN;
4703 new->next_ent = tag_table;
4704 tag_table = new;
4708 /* The order is: nodename, nextnode, prevnode, upnode.
4709 If all of the NEXT, PREV, and UP fields are empty, they are defaulted.
4710 You must follow a node command which has those fields defaulted
4711 with a sectioning command (e.g. @chapter) giving the "level" of that node.
4712 It is an error not to do so.
4713 The defaults come from the menu in this node's parent. */
4714 void
4715 cm_node ()
4717 char *node, *prev, *next, *up;
4718 int new_node_pos, defaulting, this_section, no_warn = 0;
4719 extern int already_outputting_pending_notes;
4721 if (strcmp (command, "nwnode") == 0)
4722 no_warn = 1;
4724 /* Get rid of unmatched brace arguments from previous commands. */
4725 discard_braces ();
4727 /* There also might be insertions left lying around that haven't been
4728 ended yet. Do that also. */
4729 discard_insertions (1);
4731 if (!already_outputting_pending_notes)
4733 close_paragraph ();
4734 output_pending_notes ();
4735 free_pending_notes ();
4738 filling_enabled = indented_fill = 0;
4739 new_node_pos = output_position;
4740 current_footnote_number = 1;
4742 #if defined (HAVE_MACROS)
4743 if (macro_expansion_output_stream && !executing_string)
4744 append_to_expansion_output (input_text_offset + 1);
4745 #endif /* HAVE_MACROS */
4747 node = get_node_token (1);
4748 next = get_node_token (0);
4749 prev = get_node_token (0);
4750 up = get_node_token (0);
4752 if (verbose_mode)
4753 printf (_("Formatting node %s...\n"), node);
4755 #if defined (HAVE_MACROS)
4756 if (macro_expansion_output_stream && !executing_string)
4757 remember_itext (input_text, input_text_offset);
4758 #endif /* HAVE_MACROS */
4760 no_indent = 1;
4761 if (!no_headers)
4763 add_word_args ("\037\nFile: %s, Node: ", pretty_output_filename);
4765 #if defined (HAVE_MACROS)
4766 if (macro_expansion_output_stream && !executing_string)
4767 me_execute_string (node);
4768 else
4769 #endif /* HAVE_MACROS */
4770 execute_string ("%s", node);
4771 filling_enabled = indented_fill = 0;
4774 /* Check for defaulting of this node's next, prev, and up fields. */
4775 defaulting = (*next == 0 && *prev == 0 && *up == 0);
4777 this_section = what_section (input_text + input_text_offset);
4779 /* If we are defaulting, then look at the immediately following
4780 sectioning command (error if none) to determine the node's
4781 level. Find the node that contains the menu mentioning this node
4782 that is one level up (error if not found). That node is the "Up"
4783 of this node. Default the "Next" and "Prev" from the menu. */
4784 if (defaulting)
4786 NODE_REF *last_ref = (NODE_REF *)NULL;
4787 NODE_REF *ref = node_references;
4789 if ((this_section < 0) && (strcmp (node, "Top") != 0))
4791 char *polite_section_name = "top";
4792 int i;
4794 for (i = 0; section_alist[i].name; i++)
4795 if (section_alist[i].level == current_section + 1)
4797 polite_section_name = section_alist[i].name;
4798 break;
4801 line_error
4802 (_("Node `%s' requires a sectioning command (e.g. %c%s)"),
4803 node, COMMAND_PREFIX, polite_section_name);
4805 else
4807 if (strcmp (node, "Top") == 0)
4809 /* Default the NEXT pointer to be the first menu item in
4810 this node, if there is a menu in this node. We have to
4811 try very hard to find the menu, as it may be obscured
4812 by execution_strings which are on the filestack. For
4813 every member of the filestack which has a FILENAME
4814 member which is identical to the current INPUT_FILENAME,
4815 search forward from that offset. */
4816 int saved_input_text_offset = input_text_offset;
4817 int saved_size_of_input_text = size_of_input_text;
4818 char *saved_input_text = input_text;
4819 FSTACK *next_file = filestack;
4821 int orig_offset, orig_size;
4822 char *glean_node_from_menu ();
4824 /* No matter what, make this file point back at `(dir)'. */
4825 free (up); up = xstrdup ("(dir)");
4827 while (1)
4829 orig_offset = input_text_offset;
4830 orig_size =
4831 search_forward (node_search_string, orig_offset);
4833 if (orig_size < 0)
4834 orig_size = size_of_input_text;
4836 input_text_offset =
4837 search_forward (menu_search_string, orig_offset);
4839 if (input_text_offset > -1)
4841 char *nodename_from_menu = (char *)NULL;
4843 input_text_offset =
4844 search_forward ("\n* ", input_text_offset);
4846 if (input_text_offset != -1)
4847 nodename_from_menu = glean_node_from_menu (0);
4849 if (nodename_from_menu)
4851 free (next); next = nodename_from_menu;
4852 break;
4856 /* We got here, so it hasn't been found yet. Try
4857 the next file on the filestack if there is one. */
4858 if (next_file &&
4859 (strcmp (next_file->filename, input_filename) == 0))
4861 input_text = next_file->text;
4862 input_text_offset = next_file->offset;
4863 size_of_input_text = next_file->size;
4864 next_file = next_file->next;
4866 else
4868 /* No more input files to check. */
4869 break;
4873 input_text = saved_input_text;
4874 input_text_offset = saved_input_text_offset;
4875 size_of_input_text = saved_size_of_input_text;
4879 /* Fix the level of the menu references in the Top node, iff it
4880 was declared with @top, and no subsequent reference was found. */
4881 if (top_node_seen && !non_top_node_seen)
4883 /* Then this is the first non-@top node seen. */
4884 int level;
4886 level = set_top_section_level (this_section - 1);
4887 non_top_node_seen = 1;
4889 while (ref)
4891 if (ref->section == level)
4892 ref->section = this_section - 1;
4893 ref = ref->next;
4896 ref = node_references;
4899 while (ref)
4901 if (ref->section == (this_section - 1) &&
4902 ref->type == menu_reference &&
4903 strcmp (ref->node, node) == 0)
4905 char *containing_node = ref->containing_node;
4907 free (up);
4908 up = xstrdup (containing_node);
4910 if (last_ref &&
4911 last_ref->type == menu_reference &&
4912 (strcmp (last_ref->containing_node,
4913 containing_node) == 0))
4915 free (next);
4916 next = xstrdup (last_ref->node);
4919 while ((ref->section == this_section - 1) &&
4920 (ref->next) &&
4921 (ref->next->type != menu_reference))
4922 ref = ref->next;
4924 if (ref->next && ref->type == menu_reference &&
4925 (strcmp (ref->next->containing_node,
4926 containing_node) == 0))
4928 free (prev);
4929 prev = xstrdup (ref->next->node);
4931 else if (!ref->next &&
4932 strcasecmp (ref->containing_node, "Top") == 0)
4934 free (prev);
4935 prev = xstrdup (ref->containing_node);
4937 break;
4939 last_ref = ref;
4940 ref = ref->next;
4944 #if defined (HAVE_MACROS)
4945 /* Insert the correct args if we are expanding macros, and the node's
4946 pointers weren't defaulted. */
4947 if (macro_expansion_output_stream && !executing_string && !defaulting)
4949 char *temp;
4950 int op_orig = output_paragraph_offset;
4952 temp = (char *)xmalloc (3 + strlen (next));
4953 sprintf (temp, ", %s", next);
4954 me_execute_string (temp);
4955 free (temp);
4957 temp = (char *)xmalloc (3 + strlen (prev));
4958 sprintf (temp, ", %s", prev);
4959 me_execute_string (temp);
4960 free (temp);
4962 temp = (char *)xmalloc (4 + strlen (up));
4963 sprintf (temp, ", %s", up);
4964 me_execute_string (temp);
4965 free (temp);
4967 output_paragraph_offset = op_orig;
4969 #endif /* HAVE_MACROS */
4971 if (!no_headers)
4973 #if defined (HAVE_MACROS)
4974 if (macro_expansion_output_stream)
4975 me_inhibit_expansion++;
4976 #endif /* HAVE_MACROS */
4978 if (*next)
4980 execute_string (", Next: %s", next);
4981 filling_enabled = indented_fill = 0;
4984 if (*prev)
4986 execute_string (", Prev: %s", prev);
4987 filling_enabled = indented_fill = 0;
4990 if (*up)
4992 execute_string (", Up: %s", up);
4993 filling_enabled = indented_fill = 0;
4995 #if defined (HAVE_MACROS)
4996 if (macro_expansion_output_stream)
4997 me_inhibit_expansion--;
4998 #endif /* HAVE_MACROS */
5001 close_paragraph ();
5002 no_indent = 0;
5004 if (!*node)
5006 line_error ("No node name specified for `%c%s' command",
5007 COMMAND_PREFIX, command);
5008 free (node);
5009 free (next);
5010 free (prev);
5011 free (up);
5013 else
5015 if (!*next) { free (next); next = (char *)NULL; }
5016 if (!*prev) { free (prev); prev = (char *)NULL; }
5017 if (!*up) { free (up); up = (char *)NULL; }
5018 remember_node (node, prev, next, up, new_node_pos, line_number, no_warn);
5021 /* Change the section only if there was a sectioning command. */
5022 if (this_section >= 0)
5023 current_section = this_section;
5025 filling_enabled = 1;
5028 /* Validation of an info file.
5029 Scan through the list of tag entries touching the Prev, Next, and Up
5030 elements of each. It is an error not to be able to touch one of them,
5031 except in the case of external node references, such as "(DIR)".
5033 If the Prev is different from the Up,
5034 then the Prev node must have a Next pointing at this node.
5036 Every node except Top must have an Up.
5037 The Up node must contain some sort of reference, other than a Next,
5038 to this node.
5040 If the Next is different from the Next of the Up,
5041 then the Next node must have a Prev pointing at this node. */
5042 void
5043 validate_file (tag_table)
5044 TAG_ENTRY *tag_table;
5046 char *old_input_filename = input_filename;
5047 TAG_ENTRY *tags = tag_table;
5049 while (tags != (TAG_ENTRY *) NULL)
5051 register TAG_ENTRY *temp_tag;
5053 input_filename = tags->filename;
5054 line_number = tags->line_no;
5056 /* If this is a "no warn" node, don't validate it in any way. */
5057 if (tags->flags & NO_WARN)
5059 tags = tags->next_ent;
5060 continue;
5063 /* If this node has a Next, then make sure that the Next exists. */
5064 if (tags->next)
5066 validate (tags->next, tags->line_no, "Next");
5068 /* If the Next node exists, and there is no Up, then make
5069 sure that the Prev of the Next points back. */
5070 temp_tag = find_node (tags->next);
5071 if (temp_tag)
5073 char *prev;
5075 if (temp_tag->flags & NO_WARN)
5077 /* Do nothing if we aren't supposed to issue warnings
5078 about this node. */
5080 else
5082 prev = temp_tag->prev;
5083 if (!prev || (strcmp (prev, tags->node) != 0))
5085 line_error (_("Node `%s''s Next field not pointed back to"),
5086 tags->node);
5087 line_number = temp_tag->line_no;
5088 input_filename = temp_tag->filename;
5089 line_error
5090 (_("This node (`%s') is the one with the bad `Prev'"),
5091 temp_tag->node);
5092 input_filename = tags->filename;
5093 line_number = tags->line_no;
5094 temp_tag->flags |= PREV_ERROR;
5100 /* Validate the Prev field if there is one, and we haven't already
5101 complained about it in some way. You don't have to have a Prev
5102 field at this stage. */
5103 if (!(tags->flags & PREV_ERROR) && tags->prev)
5105 int valid_p = validate (tags->prev, tags->line_no, "Prev");
5107 if (!valid_p)
5108 tags->flags |= PREV_ERROR;
5109 else
5111 /* If the Prev field is not the same as the Up field,
5112 then the node pointed to by the Prev field must have
5113 a Next field which points to this node. */
5114 if (tags->up && (strcmp (tags->prev, tags->up) != 0))
5116 temp_tag = find_node (tags->prev);
5118 /* If we aren't supposed to issue warnings about the
5119 target node, do nothing. */
5120 if (!temp_tag || (temp_tag->flags & NO_WARN))
5122 /* Do nothing. */
5124 else
5126 if (!temp_tag->next ||
5127 (strcmp (temp_tag->next, tags->node) != 0))
5129 line_error
5130 (_("Node `%s's Prev field not pointed back to"),
5131 tags->node);
5132 line_number = temp_tag->line_no;
5133 input_filename = temp_tag->filename;
5134 line_error (_("This node (`%s') has the bad Next"),
5135 temp_tag->node);
5136 input_filename = tags->filename;
5137 line_number = tags->line_no;
5138 temp_tag->flags |= NEXT_ERROR;
5145 if (!tags->up && (strcasecmp (tags->node, _("Top")) != 0))
5146 line_error (_("Node `%s' missing Up field"), tags->node);
5147 else if (tags->up)
5149 int valid_p = validate (tags->up, tags->line_no, "Up");
5151 /* If node X has Up: Y, then warn if Y fails to have a menu item
5152 or note pointing at X, if Y isn't of the form "(Y)". */
5153 if (valid_p && *tags->up != '(')
5155 NODE_REF *nref, *tref, *list;
5156 NODE_REF *find_node_reference ();
5158 tref = (NODE_REF *) NULL;
5159 list = node_references;
5161 for (;;)
5163 if (!(nref = find_node_reference (tags->node, list)))
5164 break;
5166 if (strcmp (nref->containing_node, tags->up) == 0)
5168 if (nref->type != menu_reference)
5170 tref = nref;
5171 list = nref->next;
5173 else
5174 break;
5176 list = nref->next;
5179 if (!nref)
5181 temp_tag = find_node (tags->up);
5182 line_number = temp_tag->line_no;
5183 input_filename = temp_tag->filename;
5184 if (!tref)
5185 line_error (
5186 _("`%s' has an Up field of `%s', but `%s' has no menu item for `%s'"),
5187 tags->node, tags->up, tags->up, tags->node);
5188 line_number = tags->line_no;
5189 input_filename = tags->filename;
5193 tags = tags->next_ent;
5196 validate_other_references (node_references);
5197 /* We have told the user about the references which didn't exist.
5198 Now tell him about the nodes which aren't referenced. */
5200 tags = tag_table;
5201 while (tags != (TAG_ENTRY *) NULL)
5203 /* If this node is a "no warn" node, do nothing. */
5204 if (tags->flags & NO_WARN)
5206 tags = tags->next_ent;
5207 continue;
5210 /* Special hack. If the node in question appears to have
5211 been referenced more than REFERENCE_WARNING_LIMIT times,
5212 give a warning. */
5213 if (tags->touched > reference_warning_limit)
5215 input_filename = tags->filename;
5216 line_number = tags->line_no;
5217 warning (_("node `%s' has been referenced %d times"),
5218 tags->node, tags->touched);
5221 if (tags->touched == 0)
5223 input_filename = tags->filename;
5224 line_number = tags->line_no;
5226 /* Notice that the node "Top" is special, and doesn't have to
5227 be referenced. */
5228 if (strcasecmp (tags->node, _("Top")) != 0)
5229 warning (_("unreferenced node `%s'"), tags->node);
5231 tags = tags->next_ent;
5233 input_filename = old_input_filename;
5236 /* Return 1 if tag correctly validated, or 0 if not. */
5238 validate (tag, line, label)
5239 char *tag;
5240 int line;
5241 char *label;
5243 TAG_ENTRY *result;
5245 /* If there isn't a tag to verify, or if the tag is in another file,
5246 then it must be okay. */
5247 if (!tag || !*tag || *tag == '(')
5248 return (1);
5250 /* Otherwise, the tag must exist. */
5251 result = find_node (tag);
5253 if (!result)
5255 line_number = line;
5256 line_error (_("%s reference to nonexistent node `%s'"), label, tag);
5257 return (0);
5259 result->touched++;
5260 return (1);
5263 /* Split large output files into a series of smaller files. Each file
5264 is pointed to in the tag table, which then gets written out as the
5265 original file. The new files have the same name as the original file
5266 with a "-num" attached. SIZE is the largest number of bytes to allow
5267 in any single split file. */
5268 void
5269 split_file (filename, size)
5270 char *filename;
5271 int size;
5273 char *root_filename, *root_pathname;
5274 char *the_file, *filename_part ();
5275 struct stat fileinfo;
5276 long file_size;
5277 char *the_header;
5278 int header_size;
5280 /* Can only do this to files with tag tables. */
5281 if (!tag_table)
5282 return;
5284 if (size == 0)
5285 size = DEFAULT_SPLIT_SIZE;
5287 if ((stat (filename, &fileinfo) != 0) ||
5288 (((long) fileinfo.st_size) < SPLIT_SIZE_THRESHOLD))
5289 return;
5290 file_size = (long) fileinfo.st_size;
5292 the_file = find_and_load (filename);
5293 if (!the_file)
5294 return;
5296 root_filename = filename_part (filename);
5297 root_pathname = pathname_part (filename);
5299 if (!root_pathname)
5300 root_pathname = xstrdup ("");
5302 /* Start splitting the file. Walk along the tag table
5303 outputting sections of the file. When we have written
5304 all of the nodes in the tag table, make the top-level
5305 pointer file, which contains indirect pointers and
5306 tags for the nodes. */
5308 int which_file = 1;
5309 TAG_ENTRY *tags = tag_table;
5310 char *indirect_info = (char *)NULL;
5312 /* Remember the `header' of this file. The first tag in the file is
5313 the bottom of the header; the top of the file is the start. */
5314 the_header = (char *)xmalloc (1 + (header_size = tags->position));
5315 memcpy (the_header, the_file, header_size);
5317 while (tags)
5319 int file_top, file_bot, limit;
5321 /* Have to include the Control-_. */
5322 file_top = file_bot = tags->position;
5323 limit = file_top + size;
5325 /* If the rest of this file is only one node, then
5326 that is the entire subfile. */
5327 if (!tags->next_ent)
5329 int i = tags->position + 1;
5330 char last_char = the_file[i];
5332 while (i < file_size)
5334 if ((the_file[i] == '\037') &&
5335 ((last_char == '\n') ||
5336 (last_char == '\014')))
5337 break;
5338 else
5339 last_char = the_file[i];
5340 i++;
5342 file_bot = i;
5343 tags = tags->next_ent;
5344 goto write_region;
5347 /* Otherwise, find the largest number of nodes that can fit in
5348 this subfile. */
5349 for (; tags; tags = tags->next_ent)
5351 if (!tags->next_ent)
5353 /* This entry is the last node. Search forward for the end
5354 of this node, and that is the end of this file. */
5355 int i = tags->position + 1;
5356 char last_char = the_file[i];
5358 while (i < file_size)
5360 if ((the_file[i] == '\037') &&
5361 ((last_char == '\n') ||
5362 (last_char == '\014')))
5363 break;
5364 else
5365 last_char = the_file[i];
5366 i++;
5368 file_bot = i;
5370 if (file_bot < limit)
5372 tags = tags->next_ent;
5373 goto write_region;
5375 else
5377 /* Here we want to write out everything before the last
5378 node, and then write the last node out in a file
5379 by itself. */
5380 file_bot = tags->position;
5381 goto write_region;
5385 if (tags->next_ent->position > limit)
5387 if (tags->position == file_top)
5388 tags = tags->next_ent;
5390 file_bot = tags->position;
5392 write_region:
5394 int fd;
5395 char *split_filename;
5397 split_filename = (char *) xmalloc
5398 (10 + strlen (root_pathname) + strlen (root_filename));
5399 sprintf
5400 (split_filename,
5401 "%s%s-%d", root_pathname, root_filename, which_file);
5403 fd = open
5404 (split_filename, O_WRONLY | O_TRUNC | O_CREAT, 0666);
5406 if ((fd < 0) ||
5407 (write (fd, the_header, header_size) != header_size) ||
5408 (write (fd, the_file + file_top, file_bot - file_top)
5409 != (file_bot - file_top)) ||
5410 ((close (fd)) < 0))
5412 perror (split_filename);
5413 if (fd != -1)
5414 close (fd);
5415 exit (FATAL);
5418 if (!indirect_info)
5420 indirect_info = the_file + file_top;
5421 sprintf (indirect_info, "\037\nIndirect:\n");
5422 indirect_info += strlen (indirect_info);
5425 sprintf (indirect_info, "%s-%d: %d\n",
5426 root_filename, which_file, file_top);
5428 free (split_filename);
5429 indirect_info += strlen (indirect_info);
5430 which_file++;
5431 break;
5437 /* We have sucessfully created the subfiles. Now write out the
5438 original again. We must use `output_stream', or
5439 write_tag_table_indirect () won't know where to place the output. */
5440 output_stream = fopen (filename, "w");
5441 if (!output_stream)
5443 perror (filename);
5444 exit (FATAL);
5448 int distance = indirect_info - the_file;
5449 fwrite (the_file, 1, distance, output_stream);
5451 /* Inhibit newlines. */
5452 paragraph_is_open = 0;
5454 write_tag_table_indirect ();
5455 fclose (output_stream);
5456 free (the_header);
5457 free (the_file);
5458 return;
5463 /* The strings here are followed in the message by `reference to...' in
5464 the `validate' routine. */
5465 char *
5466 reftype_type_string (type)
5467 enum reftype type;
5469 switch (type)
5471 case menu_reference:
5472 return ("Menu");
5473 case followed_reference:
5474 return ("Cross");
5475 default:
5476 return ("Internal-bad-reference-type");
5480 /* Remember this node name for later validation use. This is used to
5481 remember menu references while reading the input file. After the
5482 output file has been written, if validation is on, then we use the
5483 contents of `node_references' as a list of nodes to validate. */
5484 void
5485 remember_node_reference (node, line, type)
5486 char *node;
5487 int line;
5488 enum reftype type;
5490 NODE_REF *temp = (NODE_REF *) xmalloc (sizeof (NODE_REF));
5492 temp->next = node_references;
5493 temp->node = xstrdup (node);
5494 temp->line_no = line;
5495 temp->section = current_section;
5496 temp->type = type;
5497 temp->containing_node = xstrdup (current_node ? current_node : "");
5498 temp->filename = node_filename;
5500 node_references = temp;
5503 void
5504 validate_other_references (ref_list)
5505 register NODE_REF *ref_list;
5507 char *old_input_filename = input_filename;
5509 while (ref_list != (NODE_REF *) NULL)
5511 input_filename = ref_list->filename;
5512 validate (ref_list->node, ref_list->line_no,
5513 reftype_type_string (ref_list->type));
5514 ref_list = ref_list->next;
5516 input_filename = old_input_filename;
5519 /* Find NODE in REF_LIST. */
5520 NODE_REF *
5521 find_node_reference (node, ref_list)
5522 char *node;
5523 register NODE_REF *ref_list;
5525 while (ref_list)
5527 if (strcmp (node, ref_list->node) == 0)
5528 break;
5529 ref_list = ref_list->next;
5531 return (ref_list);
5534 void
5535 free_node_references ()
5537 register NODE_REF *list, *temp;
5539 list = node_references;
5541 while (list)
5543 temp = list;
5544 free (list->node);
5545 free (list->containing_node);
5546 list = list->next;
5547 free (temp);
5549 node_references = (NODE_REF *) NULL;
5552 /* This function gets called at the start of every line while inside of
5553 a menu. It checks to see if the line starts with "* ", and if so,
5554 remembers the node reference that this menu refers to.
5555 input_text_offset is at the \n just before the line start. */
5556 #define menu_starter "* "
5557 char *
5558 glean_node_from_menu (remember_reference)
5559 int remember_reference;
5561 int i, orig_offset = input_text_offset;
5562 char *nodename;
5564 if (strncmp (&input_text[input_text_offset + 1],
5565 menu_starter,
5566 strlen (menu_starter)) != 0)
5567 return ((char *)NULL);
5568 else
5569 input_text_offset += strlen (menu_starter) + 1;
5571 get_until_in_line (0, ":", &nodename);
5572 if (curchar () == ':')
5573 input_text_offset++;
5574 canon_white (nodename);
5576 if (curchar () == ':')
5577 goto save_node;
5579 free (nodename);
5580 get_rest_of_line (&nodename);
5582 /* Special hack: If the nodename follows the menu item name,
5583 then we have to read the rest of the line in order to find
5584 out what the nodename is. But we still have to read the
5585 line later, in order to process any formatting commands that
5586 might be present. So un-count the carriage return that has just
5587 been counted. */
5588 line_number--;
5590 isolate_nodename (nodename);
5592 save_node:
5593 input_text_offset = orig_offset;
5594 normalize_node_name (nodename);
5595 i = strlen (nodename);
5596 if (i && nodename[i - 1] == ':')
5597 nodename[i - 1] = 0;
5599 if (remember_reference)
5601 remember_node_reference (nodename, line_number, menu_reference);
5602 free (nodename);
5603 return ((char *)NULL);
5605 else
5606 return (nodename);
5609 static void
5610 isolate_nodename (nodename)
5611 char *nodename;
5613 register int i, c;
5614 int paren_seen, paren;
5616 if (!nodename)
5617 return;
5619 canon_white (nodename);
5620 paren_seen = paren = i = 0;
5622 if (*nodename == '.' || !*nodename)
5624 *nodename = 0;
5625 return;
5628 if (*nodename == '(')
5630 paren++;
5631 paren_seen++;
5632 i++;
5635 for (; (c = nodename[i]); i++)
5637 if (paren)
5639 if (c == '(')
5640 paren++;
5641 else if (c == ')')
5642 paren--;
5644 continue;
5647 /* If the character following the close paren is a space, then this
5648 node has no more characters associated with it. */
5649 if (c == '\t' ||
5650 c == '\n' ||
5651 c == ',' ||
5652 ((paren_seen && nodename[i - 1] == ')') &&
5653 (c == ' ' || c == '.')) ||
5654 (c == '.' &&
5655 ((!nodename[i + 1] ||
5656 (cr_or_whitespace (nodename[i + 1])) ||
5657 (nodename[i + 1] == ')')))))
5658 break;
5660 nodename[i] = 0;
5663 void
5664 cm_menu ()
5666 if (current_node == (char *)NULL)
5668 warning (_("%cmenu seen before first node"), COMMAND_PREFIX);
5669 warning (_("creating `Top' node"));
5670 execute_string ("@node Top");
5672 begin_insertion (menu);
5675 void
5676 cm_detailmenu ()
5678 if (current_node == (char *)NULL)
5680 warning (_("%cmenu seen before first node"), COMMAND_PREFIX);
5681 warning (_("creating `Top' node"));
5682 execute_string ("@node Top");
5684 begin_insertion (detailmenu);
5687 /* **************************************************************** */
5688 /* */
5689 /* Cross Reference Hacking */
5690 /* */
5691 /* **************************************************************** */
5693 /* Return next comma-delimited argument, but do not cross a close-brace
5694 boundary. Clean up whitespace, too. */
5695 char *
5696 get_xref_token ()
5698 char *string;
5700 get_until_in_braces (",", &string);
5701 if (curchar () == ',')
5702 input_text_offset++;
5703 fix_whitespace (string);
5704 return (string);
5707 int px_ref_flag = 0; /* Controls initial output string. */
5709 /* Make a cross reference. */
5710 void
5711 cm_xref (arg)
5713 if (arg == START)
5715 char *arg1, *arg2, *arg3, *arg4, *arg5;
5717 arg1 = get_xref_token ();
5718 arg2 = get_xref_token ();
5719 arg3 = get_xref_token ();
5720 arg4 = get_xref_token ();
5721 arg5 = get_xref_token ();
5723 add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
5725 if (*arg5 || *arg4)
5727 char *node_name;
5729 if (!*arg2)
5731 if (*arg3)
5732 node_name = arg3;
5733 else
5734 node_name = arg1;
5736 else
5737 node_name = arg2;
5739 execute_string ("%s: (%s)%s", node_name, arg4, arg1);
5740 /* Free all of the arguments found. */
5741 if (arg1) free (arg1);
5742 if (arg2) free (arg2);
5743 if (arg3) free (arg3);
5744 if (arg4) free (arg4);
5745 if (arg5) free (arg5);
5746 return;
5748 else
5749 remember_node_reference (arg1, line_number, followed_reference);
5751 if (*arg3)
5753 if (!*arg2)
5754 execute_string ("%s: %s", arg3, arg1);
5755 else
5756 execute_string ("%s: %s", arg2, arg1);
5758 else
5760 if (*arg2)
5761 execute_string ("%s: %s", arg2, arg1);
5762 else
5763 execute_string ("%s::", arg1);
5766 /* Free all of the arguments found. */
5767 if (arg1) free (arg1);
5768 if (arg2) free (arg2);
5769 if (arg3) free (arg3);
5770 if (arg4) free (arg4);
5771 if (arg5) free (arg5);
5773 else
5775 /* Check to make sure that the next non-whitespace character is either
5776 a period or a comma. input_text_offset is pointing at the "}" which
5777 ended the xref or pxref command. */
5778 int temp = input_text_offset + 1;
5780 if (output_paragraph[output_paragraph_offset - 2] == ':' &&
5781 output_paragraph[output_paragraph_offset - 1] == ':')
5782 return;
5783 while (temp < size_of_input_text)
5785 if (cr_or_whitespace (input_text[temp]))
5786 temp++;
5787 else
5789 if (input_text[temp] != '.'
5790 && input_text[temp] != ','
5791 && input_text[temp] != '\t')
5793 line_error (
5794 _("`.' or `,' must follow cross reference, not %c"),
5795 input_text[temp]);
5797 break;
5803 void
5804 cm_pxref (arg)
5805 int arg;
5807 if (arg == START)
5809 px_ref_flag++;
5810 cm_xref (arg);
5811 px_ref_flag--;
5813 else
5814 add_char ('.');
5817 void
5818 cm_inforef (arg)
5819 int arg;
5821 if (arg == START)
5823 char *node = get_xref_token ();
5824 char *pname = get_xref_token ();
5825 char *file = get_xref_token ();
5827 if (*pname)
5828 execute_string ("*note %s: (%s)%s", pname, file, node);
5829 else
5830 execute_string ("*note (%s)%s::", file, node);
5832 free (node);
5833 free (pname);
5834 free (file);
5838 /* A URL reference. */
5839 void
5840 cm_uref (arg, start_pos, end_pos)
5841 int arg, start_pos, end_pos;
5843 if (arg == END)
5845 char *comma;
5846 char *arg = (char *) &output_paragraph[start_pos];
5848 output_paragraph[end_pos] = 0;
5849 output_column -= end_pos - start_pos;
5850 output_paragraph_offset = start_pos;
5852 arg = xstrdup (arg);
5853 comma = strchr (arg, ','); /* let's hope for no commas in the url */
5854 if (comma)
5856 *comma = 0;
5857 /* Ignore spaces at beginning of second arg. */
5858 for (comma++; isspace (*comma); comma++)
5860 add_word (comma);
5861 add_char (' ');
5862 add_char ('(');
5863 add_word (arg);
5864 add_char (')');
5866 else
5868 extern int printing_index;
5870 if (!printing_index)
5871 add_char ('`');
5873 add_word (arg);
5875 if (!printing_index)
5876 add_char ('\'');
5878 free (arg);
5882 /* An email reference. */
5883 void
5884 cm_email (arg, start_pos, end_pos)
5885 int arg, start_pos, end_pos;
5887 if (arg == END)
5889 char *comma;
5890 char *arg = (char *) &output_paragraph[start_pos];
5892 output_paragraph[end_pos] = 0;
5893 output_column -= end_pos - start_pos;
5894 output_paragraph_offset = start_pos;
5896 arg = xstrdup (arg);
5897 comma = strchr (arg, ',');
5898 if (comma)
5900 *comma = 0;
5901 for (comma++; isspace (*comma); comma++)
5903 add_word (comma);
5904 add_char (' ');
5906 add_char ('<');
5907 add_word (arg);
5908 add_char ('>');
5909 free (arg);
5913 /* An external image is a reference, kind of. The parsing is (not
5914 coincidentally) similar, anyway. */
5915 void
5916 cm_image (arg)
5917 int arg;
5919 if (arg == START)
5921 char *name_arg = get_xref_token ();
5922 /* We don't yet care about any other args, but read them so they
5923 don't end up in the text. */
5924 char *arg = get_xref_token ();
5925 if (arg) free (arg);
5926 arg = get_xref_token ();
5927 if (arg) free (arg);
5929 if (*name_arg)
5931 /* Try to open foo.txt. */
5932 FILE *image_file;
5933 char *name = xmalloc (strlen (name_arg) + 4);
5934 strcpy (name, name_arg);
5935 strcat (name, ".txt");
5936 image_file = fopen (name, "r");
5937 if (image_file)
5939 int ch;
5940 int save_inhibit_indentation = inhibit_paragraph_indentation;
5941 int save_filling_enabled = filling_enabled;
5943 inhibit_paragraph_indentation = 1;
5944 filling_enabled = 0;
5945 last_char_was_newline = 0;
5947 /* Maybe we need to remove the final newline if the image
5948 file is only one line to allow in-line images. On the
5949 other hand, they could just make the file without a
5950 final newline. */
5951 while ((ch = getc (image_file)) != EOF)
5952 add_char (ch);
5954 inhibit_paragraph_indentation = save_inhibit_indentation;
5955 filling_enabled = save_filling_enabled;
5957 if (fclose (image_file) != 0) {
5958 perror (name);
5961 else
5962 warning (_("@image file `%s' unreadable: %s"), name,
5963 strerror (errno));
5965 else
5966 line_error (_("@image missing filename argument"));
5968 if (name_arg) free (name_arg);
5972 /* **************************************************************** */
5973 /* */
5974 /* Insertion Command Stubs */
5975 /* */
5976 /* **************************************************************** */
5978 void
5979 cm_quotation ()
5981 begin_insertion (quotation);
5984 void
5985 cm_example ()
5987 begin_insertion (example);
5990 void
5991 cm_smallexample ()
5993 begin_insertion (smallexample);
5996 void
5997 cm_lisp ()
5999 begin_insertion (lisp);
6002 void
6003 cm_smalllisp ()
6005 begin_insertion (smalllisp);
6008 /* @cartouche/@end cartouche draws box with rounded corners in
6009 TeX output. Right now, just a no-op insertion. */
6010 void
6011 cm_cartouche ()
6013 begin_insertion (cartouche);
6016 void
6017 cm_format ()
6019 begin_insertion (format);
6022 void
6023 cm_display ()
6025 begin_insertion (display);
6028 void
6029 cm_direntry ()
6031 if (no_headers)
6032 command_name_condition ();
6033 else
6034 begin_insertion (direntry);
6037 void
6038 cm_itemize ()
6040 begin_insertion (itemize);
6043 void
6044 cm_enumerate ()
6046 do_enumeration (enumerate, "1");
6049 /* Start an enumeration insertion of type TYPE. If the user supplied
6050 no argument on the line, then use DEFAULT_STRING as the initial string. */
6051 void
6052 do_enumeration (type, default_string)
6053 int type;
6054 char *default_string;
6056 get_until_in_line (0, ".", &enumeration_arg);
6057 canon_white (enumeration_arg);
6059 if (!*enumeration_arg)
6061 free (enumeration_arg);
6062 enumeration_arg = xstrdup (default_string);
6065 if (!isdigit (*enumeration_arg) && !isletter (*enumeration_arg))
6067 warning (_("%s requires letter or digit"), insertion_type_pname (type));
6069 switch (type)
6071 case enumerate:
6072 default_string = "1";
6073 break;
6075 enumeration_arg = xstrdup (default_string);
6077 begin_insertion (type);
6080 void
6081 cm_table ()
6083 begin_insertion (table);
6086 void
6087 cm_multitable ()
6089 begin_insertion (multitable); /* @@ */
6092 void
6093 cm_ftable ()
6095 begin_insertion (ftable);
6098 void
6099 cm_vtable ()
6101 begin_insertion (vtable);
6104 void
6105 cm_group ()
6107 begin_insertion (group);
6110 void
6111 cm_ifinfo ()
6113 begin_insertion (ifinfo);
6116 void
6117 cm_ifnothtml ()
6119 begin_insertion (ifnothtml);
6122 void
6123 cm_ifnottex ()
6125 begin_insertion (ifnottex);
6128 /* Begin an insertion where the lines are not filled or indented. */
6129 void
6130 cm_flushleft ()
6132 begin_insertion (flushleft);
6135 /* Begin an insertion where the lines are not filled, and each line is
6136 forced to the right-hand side of the page. */
6137 void
6138 cm_flushright ()
6140 begin_insertion (flushright);
6143 /* End existing insertion block. */
6144 void
6145 cm_end ()
6147 char *temp;
6148 enum insertion_type type;
6150 if (!insertion_level)
6152 line_error (_("Unmatched `%c%s'"), COMMAND_PREFIX, command);
6153 return;
6156 get_rest_of_line (&temp);
6158 if (temp[0] == 0)
6159 line_error (_("`%c%s' needs something after it"), COMMAND_PREFIX, command);
6161 type = find_type_from_name (temp);
6163 if (type == bad_type)
6165 line_error (_("Bad argument to `%s', `%s', using `%s'"),
6166 command, temp, insertion_type_pname (current_insertion_type ()));
6168 end_insertion (type);
6169 free (temp);
6172 /* **************************************************************** */
6173 /* */
6174 /* Conditional Handling */
6175 /* */
6176 /* **************************************************************** */
6178 /* A structure which contains `defined' variables. */
6179 typedef struct defines {
6180 struct defines *next;
6181 char *name;
6182 char *value;
6183 } DEFINE;
6185 /* The linked list of `set' defines. */
6186 DEFINE *defines = (DEFINE *)NULL;
6188 /* Add NAME to the list of `set' defines. */
6189 void
6190 set (name, value)
6191 char *name;
6192 char *value;
6194 DEFINE *temp;
6196 for (temp = defines; temp; temp = temp->next)
6197 if (strcmp (name, temp->name) == 0)
6199 free (temp->value);
6200 temp->value = xstrdup (value);
6201 return;
6204 temp = (DEFINE *)xmalloc (sizeof (DEFINE));
6205 temp->next = defines;
6206 temp->name = xstrdup (name);
6207 temp->value = xstrdup (value);
6208 defines = temp;
6211 /* Remove NAME from the list of `set' defines. */
6212 void
6213 clear (name)
6214 char *name;
6216 register DEFINE *temp, *last;
6218 last = (DEFINE *)NULL;
6219 temp = defines;
6221 while (temp)
6223 if (strcmp (temp->name, name) == 0)
6225 if (last)
6226 last->next = temp->next;
6227 else
6228 defines = temp->next;
6230 free (temp->name);
6231 free (temp->value);
6232 free (temp);
6233 break;
6235 last = temp;
6236 temp = temp->next;
6240 /* Return the value of NAME. The return value is NULL if NAME is unset. */
6241 char *
6242 set_p (name)
6243 char *name;
6245 register DEFINE *temp;
6247 for (temp = defines; temp; temp = temp->next)
6248 if (strcmp (temp->name, name) == 0)
6249 return (temp->value);
6251 return ((char *)NULL);
6254 /* Conditionally parse based on the current command name. */
6255 void
6256 command_name_condition ()
6258 char *discarder;
6260 discarder = (char *)xmalloc (8 + strlen (command));
6262 sprintf (discarder, "\n%cend %s", COMMAND_PREFIX, command);
6263 discard_until (discarder);
6264 discard_until ("\n");
6266 free (discarder);
6269 /* Create a variable whose name appears as the first word on this line. */
6270 void
6271 cm_set ()
6273 handle_variable (SET);
6276 /* Remove a variable whose name appears as the first word on this line. */
6277 void
6278 cm_clear ()
6280 handle_variable (CLEAR);
6283 void
6284 cm_ifset ()
6286 handle_variable (IFSET);
6289 void
6290 cm_ifclear ()
6292 handle_variable (IFCLEAR);
6295 /* This command takes braces, but we parse the contents specially, so we
6296 don't use the standard brace popping code.
6298 The syntax @ifeq{arg1, arg2, texinfo-commands} performs texinfo-commands
6299 if ARG1 and ARG2 caselessly string compare to the same string, otherwise,
6300 it produces no output. */
6301 void
6302 cm_ifeq ()
6304 char **arglist;
6306 arglist = get_brace_args (0);
6308 if (arglist)
6310 if (array_len (arglist) > 1)
6312 if ((strcasecmp (arglist[0], arglist[1]) == 0) &&
6313 (arglist[2] != (char *)NULL))
6314 execute_string ("%s\n", arglist[2]);
6317 free_array (arglist);
6321 void
6322 cm_value (arg, start_pos, end_pos)
6323 int arg, start_pos, end_pos;
6325 if (arg == END)
6327 char *name = (char *) &output_paragraph[start_pos];
6328 char *value;
6329 output_paragraph[end_pos] = 0;
6330 name = xstrdup (name);
6331 value = set_p (name);
6332 output_column -= end_pos - start_pos;
6333 output_paragraph_offset = start_pos;
6335 if (value)
6336 execute_string ("%s", value);
6337 else
6338 add_word_args (_("{No Value For \"%s\"}"), name);
6340 free (name);
6344 /* Set, clear, or conditionalize based on ACTION. */
6345 void
6346 handle_variable (action)
6347 int action;
6349 char *name;
6351 get_rest_of_line (&name);
6352 backup_input_pointer ();
6353 handle_variable_internal (action, name);
6354 free (name);
6357 void
6358 handle_variable_internal (action, name)
6359 int action;
6360 char *name;
6362 char *temp;
6363 int delimiter, additional_text_present = 0;
6365 /* Only the first word of NAME is a valid tag. */
6366 temp = name;
6367 delimiter = 0;
6368 while (*temp && (delimiter || !whitespace (*temp)))
6370 /* #if defined (SET_WITH_EQUAL) */
6371 if (*temp == '"' || *temp == '\'')
6373 if (*temp == delimiter)
6374 delimiter = 0;
6375 else
6376 delimiter = *temp;
6378 /* #endif SET_WITH_EQUAL */
6379 temp++;
6382 if (*temp)
6383 additional_text_present++;
6385 *temp = 0;
6387 if (!*name)
6388 line_error (_("%c%s requires a name"), COMMAND_PREFIX, command);
6389 else
6391 switch (action)
6393 case SET:
6395 char *value;
6397 #if defined (SET_WITH_EQUAL)
6398 /* Allow a value to be saved along with a variable. The value is
6399 the text following an `=' sign in NAME, if any is present. */
6401 for (value = name; *value && *value != '='; value++);
6403 if (*value)
6404 *value++ = 0;
6406 if (*value == '"' || *value == '\'')
6408 value++;
6409 value[strlen (value) - 1] = 0;
6412 #else /* !SET_WITH_EQUAL */
6413 /* The VALUE of NAME is the remainder of the line sans
6414 whitespace. */
6415 if (additional_text_present)
6417 value = temp + 1;
6418 canon_white (value);
6420 else
6421 value = "";
6422 #endif /* !SET_WITH_VALUE */
6424 set (name, value);
6426 break;
6428 case CLEAR:
6429 clear (name);
6430 break;
6432 case IFSET:
6433 case IFCLEAR:
6434 /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set,
6435 read lines from the file until we reach a matching
6436 "@end CONDITION". This means that we only take note of
6437 "@ifset/clear" and "@end" commands. */
6439 char condition[8];
6440 int condition_len;
6441 int orig_line_number = line_number;
6443 if (action == IFSET)
6444 strcpy (condition, "ifset");
6445 else
6446 strcpy (condition, "ifclear");
6448 condition_len = strlen (condition);
6450 if ((action == IFSET && !set_p (name))
6451 || (action == IFCLEAR && set_p (name)))
6453 int level = 0, done = 0;
6455 while (!done && input_text_offset < size_of_input_text)
6457 char *freeable_line, *line;
6459 get_rest_of_line (&freeable_line);
6461 for (line = freeable_line; whitespace (*line); line++);
6463 if (*line == COMMAND_PREFIX &&
6464 (strncmp (line + 1, condition, condition_len) == 0))
6465 level++;
6466 else if (strncmp (line, "@end", 4) == 0)
6468 char *cname = line + 4;
6469 char *temp;
6471 while (*cname && whitespace (*cname))
6472 cname++;
6473 temp = cname;
6475 while (*temp && !whitespace (*temp))
6476 temp++;
6477 *temp = 0;
6479 if (strcmp (cname, condition) == 0)
6481 if (!level)
6483 done = 1;
6485 else
6486 level--;
6489 free (freeable_line);
6492 if (!done)
6494 int save = line_number;
6495 line_number = orig_line_number;
6496 line_error (_("Reached eof before matching @end %s"),
6497 condition);
6498 line_number = save;
6501 /* We found the end of a false @ifset/ifclear. If we are
6502 in a menu, back up over the newline that ends the ifset,
6503 since that newline may also begin the next menu entry. */
6504 break;
6506 else
6508 if (action == IFSET)
6509 begin_insertion (ifset);
6510 else
6511 begin_insertion (ifclear);
6514 break;
6519 /* Execution of random text not in file. */
6521 typedef struct {
6522 char *string; /* The string buffer. */
6523 int size; /* The size of the buffer. */
6524 int in_use; /* Nonzero means string currently in use. */
6525 } EXECUTION_STRING;
6527 static EXECUTION_STRING **execution_strings = (EXECUTION_STRING **)NULL;
6528 static int execution_strings_index = 0;
6529 static int execution_strings_slots = 0;
6531 EXECUTION_STRING *
6532 get_execution_string (initial_size)
6533 int initial_size;
6535 register int i = 0;
6536 EXECUTION_STRING *es = (EXECUTION_STRING *)NULL;
6538 if (execution_strings)
6540 for (i = 0; i < execution_strings_index; i++)
6541 if (execution_strings[i] && (execution_strings[i]->in_use == 0))
6543 es = execution_strings[i];
6544 break;
6548 if (!es)
6550 if (execution_strings_index + 1 >= execution_strings_slots)
6552 execution_strings = (EXECUTION_STRING **)xrealloc
6553 (execution_strings,
6554 (execution_strings_slots += 3) * sizeof (EXECUTION_STRING *));
6555 for (; i < execution_strings_slots; i++)
6556 execution_strings[i] = (EXECUTION_STRING *)NULL;
6559 execution_strings[execution_strings_index] =
6560 (EXECUTION_STRING *)xmalloc (sizeof (EXECUTION_STRING));
6561 es = execution_strings[execution_strings_index];
6562 execution_strings_index++;
6564 es->size = 0;
6565 es->string = (char *)NULL;
6566 es->in_use = 0;
6569 if (initial_size > es->size)
6571 es->string = (char *) xrealloc (es->string, initial_size);
6572 es->size = initial_size;
6574 return (es);
6577 /* Execute the string produced by formatting the ARGs with FORMAT. This
6578 is like submitting a new file with @include. */
6579 void
6580 #if defined (VA_FPRINTF) && __STDC__
6581 execute_string (char *format, ...)
6582 #else
6583 execute_string (format, va_alist)
6584 char *format;
6585 va_dcl
6586 #endif
6588 EXECUTION_STRING *es;
6589 char *temp_string;
6590 #ifdef VA_FPRINTF
6591 va_list ap;
6592 #endif
6594 es = get_execution_string (4000);
6595 temp_string = es->string;
6596 es->in_use = 1;
6598 VA_START (ap, format);
6599 #ifdef VA_SPRINTF
6600 VA_SPRINTF (temp_string, format, ap);
6601 #else
6602 sprintf (temp_string, format, a1, a2, a3, a4, a5, a6, a7, a8);
6603 #endif /* not VA_SPRINTF */
6604 va_end (ap);
6606 pushfile ();
6607 input_text_offset = 0;
6608 input_text = temp_string;
6609 input_filename = xstrdup (input_filename);
6610 size_of_input_text = strlen (temp_string);
6612 executing_string++;
6613 reader_loop ();
6614 free (input_filename);
6616 popfile ();
6617 executing_string--;
6618 es->in_use = 0;
6622 /* Return what would be output for STR, i.e., expand Texinfo commands.
6623 If IMPLICIT_CODE is set, expand @code{STR}. */
6625 char *
6626 expansion (str, implicit_code)
6627 char *str;
6628 int implicit_code;
6630 int length;
6631 char *result;
6633 /* Inhibit any real output. */
6634 int start = output_paragraph_offset;
6635 int saved_paragraph_is_open = paragraph_is_open;
6637 inhibit_output_flushing ();
6638 paragraph_is_open = 1;
6639 execute_string (implicit_code ? "@code{%s}" : "%s", str);
6640 uninhibit_output_flushing ();
6642 /* Copy the expansion from the buffer. */
6643 length = output_paragraph_offset - start;
6644 result = xmalloc (1 + length);
6645 memcpy (result, (char *) (output_paragraph + start), length);
6646 result[length] = 0;
6648 /* Pretend it never happened. */
6649 output_paragraph_offset = start;
6650 paragraph_is_open = saved_paragraph_is_open;
6652 return result;
6655 /* @itemx, @item. */
6657 static int itemx_flag = 0;
6659 void
6660 cm_itemx ()
6662 itemx_flag++;
6663 cm_item ();
6664 itemx_flag--;
6667 void
6668 cm_item ()
6670 char *rest_of_line, *item_func;
6672 /* Can only hack "@item" while inside of an insertion. */
6673 if (insertion_level)
6675 INSERTION_ELT *stack = insertion_stack;
6676 int original_input_text_offset;
6678 skip_whitespace ();
6679 original_input_text_offset = input_text_offset;
6681 get_rest_of_line (&rest_of_line);
6682 item_func = current_item_function ();
6684 /* Okay, do the right thing depending on which insertion function
6685 is active. */
6687 switch_top:
6688 switch (stack->insertion)
6690 case multitable:
6691 multitable_item ();
6692 /* Ultra special hack. It appears that some people incorrectly
6693 place text directly after the @item, instead of on a new line
6694 by itself. This happens to work in TeX, so I make it work
6695 here. */
6696 if (*rest_of_line)
6698 line_number--;
6699 input_text_offset = original_input_text_offset;
6701 break;
6703 case ifinfo:
6704 case ifset:
6705 case ifclear:
6706 case cartouche:
6707 stack = stack->next;
6708 if (!stack)
6709 goto no_insertion;
6710 else
6711 goto switch_top;
6712 break;
6714 case menu:
6715 case quotation:
6716 case example:
6717 case smallexample:
6718 case lisp:
6719 case format:
6720 case display:
6721 case group:
6722 line_error (_("The `%c%s' command is meaningless within a `@%s' block"),
6723 COMMAND_PREFIX, command,
6724 insertion_type_pname (current_insertion_type ()));
6725 break;
6727 case itemize:
6728 case enumerate:
6729 if (itemx_flag)
6731 line_error (_("%citemx is not meaningful inside of a `%s' block"),
6732 COMMAND_PREFIX,
6733 insertion_type_pname (current_insertion_type ()));
6735 else
6737 start_paragraph ();
6738 kill_self_indent (-1);
6739 filling_enabled = indented_fill = 1;
6741 if (current_insertion_type () == itemize)
6743 indent (output_column = current_indent - 2);
6745 /* I need some way to determine whether this command
6746 takes braces or not. I believe the user can type
6747 either "@bullet" or "@bullet{}". Of course, they
6748 can also type "o" or "#" or whatever else they want. */
6749 if (item_func && *item_func)
6751 if (*item_func == COMMAND_PREFIX)
6752 if (item_func[strlen (item_func) - 1] != '}')
6753 execute_string ("%s{}", item_func);
6754 else
6755 execute_string ("%s", item_func);
6756 else
6757 execute_string ("%s", item_func);
6759 insert (' ');
6760 output_column++;
6762 else
6763 enumerate_item ();
6765 /* Special hack. This makes `close_paragraph' a no-op until
6766 `start_paragraph' has been called. */
6767 must_start_paragraph = 1;
6769 /* Handle text directly after the @item. */
6770 if (*rest_of_line)
6772 line_number--;
6773 input_text_offset = original_input_text_offset;
6776 break;
6778 case table:
6779 case ftable:
6780 case vtable:
6782 /* We need this to determine if we have two @item's in a row
6783 (see test just below). */
6784 static int last_item_output_position = 0;
6786 /* Get rid of extra characters. */
6787 kill_self_indent (-1);
6789 /* If we have one @item followed directly by another @item,
6790 we need to insert a blank line. This is not true for
6791 @itemx, though. */
6792 if (!itemx_flag && last_item_output_position == output_position)
6793 insert ('\n');
6795 /* `close_paragraph' almost does what we want. The problem
6796 is when paragraph_is_open, and last_char_was_newline, and
6797 the last newline has been turned into a space, because
6798 filling_enabled. I handle it here. */
6799 if (last_char_was_newline && filling_enabled && paragraph_is_open)
6800 insert ('\n');
6801 close_paragraph ();
6803 #if defined (INDENT_PARAGRAPHS_IN_TABLE)
6804 /* Indent on a new line, but back up one indentation level. */
6806 int save = inhibit_paragraph_indentation;
6807 inhibit_paragraph_indentation = 1;
6808 /* At this point, inserting any non-whitespace character will
6809 force the existing indentation to be output. */
6810 add_char ('i');
6811 inhibit_paragraph_indentation = save;
6813 #else /* !INDENT_PARAGRAPHS_IN_TABLE */
6814 add_char ('i');
6815 #endif /* !INDENT_PARAGRAPHS_IN_TABLE */
6817 output_paragraph_offset--;
6818 kill_self_indent (default_indentation_increment + 1);
6820 /* Add item's argument to the line. */
6821 filling_enabled = 0;
6822 if (item_func && *item_func)
6823 execute_string ("%s{%s}", item_func, rest_of_line);
6824 else
6825 execute_string ("%s", rest_of_line);
6827 if (current_insertion_type () == ftable)
6828 execute_string ("%cfindex %s\n", COMMAND_PREFIX, rest_of_line);
6829 else if (current_insertion_type () == vtable)
6830 execute_string ("%cvindex %s\n", COMMAND_PREFIX, rest_of_line);
6832 /* Start a new line, and let start_paragraph ()
6833 do the indenting of it for you. */
6834 close_single_paragraph ();
6835 indented_fill = filling_enabled = 1;
6836 last_item_output_position = output_position;
6839 free (rest_of_line);
6841 else
6843 no_insertion:
6844 line_error (_("%c%s found outside of an insertion block"),
6845 COMMAND_PREFIX, command);
6849 /* **************************************************************** */
6850 /* */
6851 /* Defun and Friends */
6852 /* */
6853 /* **************************************************************** */
6855 #define DEFUN_SELF_DELIMITING(c) \
6856 (((c) == '(') \
6857 || ((c) == ')') \
6858 || ((c) == '[') \
6859 || ((c) == ']'))
6861 struct token_accumulator
6863 unsigned int length;
6864 unsigned int index;
6865 char **tokens;
6868 void
6869 initialize_token_accumulator (accumulator)
6870 struct token_accumulator *accumulator;
6872 (accumulator->length) = 0;
6873 (accumulator->index) = 0;
6874 (accumulator->tokens) = NULL;
6877 void
6878 accumulate_token (accumulator, token)
6879 struct token_accumulator *accumulator;
6880 char *token;
6882 if ((accumulator->index) >= (accumulator->length))
6884 (accumulator->length) += 10;
6885 (accumulator->tokens) = (char **) xrealloc
6886 (accumulator->tokens, (accumulator->length * sizeof (char *)));
6888 accumulator->tokens[accumulator->index] = token;
6889 accumulator->index += 1;
6892 char *
6893 copy_substring (start, end)
6894 char *start;
6895 char *end;
6897 char *result, *scan, *scan_result;
6899 result = (char *) xmalloc ((end - start) + 1);
6900 scan_result = result;
6901 scan = start;
6903 while (scan < end)
6904 *scan_result++ = *scan++;
6906 *scan_result = 0;
6907 return (result);
6910 /* Given `string' pointing at an open brace, skip forward and return a
6911 pointer to just past the matching close brace. */
6913 scan_group_in_string (string_pointer)
6914 char **string_pointer;
6916 register int c;
6917 register char *scan_string;
6918 register unsigned int level = 1;
6920 scan_string = (*string_pointer) + 1;
6922 while (1)
6924 if (level == 0)
6926 (*string_pointer) = scan_string;
6927 return (1);
6929 c = (*scan_string++);
6930 if (c == 0)
6932 /* Tweak line_number to compensate for fact that
6933 we gobbled the whole line before coming here. */
6934 line_number -= 1;
6935 line_error (_("Missing `}' in %cdef arg"), COMMAND_PREFIX);
6936 line_number += 1;
6937 (*string_pointer) = (scan_string - 1);
6938 return (0);
6940 if (c == '{')
6941 level += 1;
6942 if (c == '}')
6943 level -= 1;
6947 /* Return a list of tokens from the contents of `string'.
6948 Commands and brace-delimited groups count as single tokens.
6949 Contiguous whitespace characters are converted to a token
6950 consisting of a single space. */
6951 char **
6952 args_from_string (string)
6953 char *string;
6955 struct token_accumulator accumulator;
6956 register char *scan_string = string;
6957 char *token_start, *token_end;
6959 initialize_token_accumulator (&accumulator);
6961 while ((*scan_string) != 0)
6963 /* Replace arbitrary whitespace by a single space. */
6964 if (whitespace (*scan_string))
6966 scan_string += 1;
6967 while (whitespace (*scan_string))
6968 scan_string += 1;
6969 accumulate_token ((&accumulator), (xstrdup (" ")));
6970 continue;
6973 /* Commands count as single tokens. */
6974 if ((*scan_string) == COMMAND_PREFIX)
6976 token_start = scan_string;
6977 scan_string += 1;
6978 if (self_delimiting (*scan_string))
6979 scan_string += 1;
6980 else
6982 register int c;
6983 while (1)
6985 c = *scan_string++;
6987 if ((c == 0) || (c == '{') || (whitespace (c)))
6989 scan_string -= 1;
6990 break;
6994 if (*scan_string == '{')
6996 char *s = scan_string;
6997 (void) scan_group_in_string (&s);
6998 scan_string = s;
7001 token_end = scan_string;
7004 /* Parentheses and brackets are self-delimiting. */
7005 else if (DEFUN_SELF_DELIMITING (*scan_string))
7007 token_start = scan_string;
7008 scan_string += 1;
7009 token_end = scan_string;
7012 /* Open brace introduces a group that is a single token. */
7013 else if (*scan_string == '{')
7015 char *s = scan_string;
7016 int balanced = scan_group_in_string (&s);
7018 token_start = scan_string + 1;
7019 scan_string = s;
7020 token_end = balanced ? (scan_string - 1) : scan_string;
7023 /* Otherwise a token is delimited by whitespace, parentheses,
7024 brackets, or braces. A token is also ended by a command. */
7025 else
7027 token_start = scan_string;
7029 while (1)
7031 register int c;
7033 c = *scan_string++;
7035 /* Do not back up if we're looking at a }; since the only
7036 valid }'s are those matched with {'s, we want to give
7037 an error. If we back up, we go into an infinite loop. */
7038 if (!c || whitespace (c) || DEFUN_SELF_DELIMITING (c)
7039 || c == '{')
7041 scan_string--;
7042 break;
7045 /* If we encounter a command embedded within a token,
7046 then end the token. */
7047 if (c == COMMAND_PREFIX)
7049 scan_string--;
7050 break;
7053 token_end = scan_string;
7056 accumulate_token
7057 (&accumulator, copy_substring (token_start, token_end));
7059 accumulate_token (&accumulator, NULL);
7060 return (accumulator.tokens);
7063 void
7064 process_defun_args (defun_args, auto_var_p)
7065 char **defun_args;
7066 int auto_var_p;
7068 int pending_space = 0;
7070 while (1)
7072 char *defun_arg = *defun_args++;
7074 if (defun_arg == NULL)
7075 break;
7077 if (defun_arg[0] == ' ')
7079 pending_space = 1;
7080 continue;
7083 if (pending_space)
7085 add_char (' ');
7086 pending_space = 0;
7089 if (DEFUN_SELF_DELIMITING (defun_arg[0]))
7090 add_char (defun_arg[0]);
7091 else if (defun_arg[0] == '&')
7092 add_word (defun_arg);
7093 else if (defun_arg[0] == COMMAND_PREFIX)
7094 execute_string ("%s", defun_arg);
7095 else if (auto_var_p)
7096 execute_string ("%cvar{%s}", COMMAND_PREFIX, defun_arg);
7097 else
7098 add_word (defun_arg);
7102 char *
7103 next_nonwhite_defun_arg (arg_pointer)
7104 char ***arg_pointer;
7106 char **scan = (*arg_pointer);
7107 char *arg = (*scan++);
7109 if ((arg != 0) && (*arg == ' '))
7110 arg = *scan++;
7112 if (arg == 0)
7113 scan -= 1;
7115 *arg_pointer = scan;
7117 return ((arg == 0) ? "" : arg);
7120 /* Make the defun type insertion.
7121 TYPE says which insertion this is.
7122 X_P, if nonzero, says not to start a new insertion. */
7123 void
7124 defun_internal (type, x_p)
7125 enum insertion_type type;
7126 int x_p;
7128 enum insertion_type base_type;
7129 char **defun_args, **scan_args;
7130 char *category, *defined_name, *type_name, *type_name2;
7133 char *line;
7134 get_rest_of_line (&line);
7135 defun_args = (args_from_string (line));
7136 free (line);
7139 scan_args = defun_args;
7141 switch (type)
7143 case defun:
7144 category = _("Function");
7145 base_type = deffn;
7146 break;
7147 case defmac:
7148 category = _("Macro");
7149 base_type = deffn;
7150 break;
7151 case defspec:
7152 category = _("Special Form");
7153 base_type = deffn;
7154 break;
7155 case defvar:
7156 category = _("Variable");
7157 base_type = defvr;
7158 break;
7159 case defopt:
7160 category = _("User Option");
7161 base_type = defvr;
7162 break;
7163 case deftypefun:
7164 category = _("Function");
7165 base_type = deftypefn;
7166 break;
7167 case deftypevar:
7168 category = _("Variable");
7169 base_type = deftypevr;
7170 break;
7171 case defivar:
7172 category = _("Instance Variable");
7173 base_type = defcv;
7174 break;
7175 case defmethod:
7176 category = _("Method");
7177 base_type = defop;
7178 break;
7179 case deftypemethod:
7180 category = _("Method");
7181 base_type = deftypemethod;
7182 break;
7183 default:
7184 category = next_nonwhite_defun_arg (&scan_args);
7185 base_type = type;
7186 break;
7189 if ((base_type == deftypefn)
7190 || (base_type == deftypevr)
7191 || (base_type == defcv)
7192 || (base_type == defop)
7193 || (base_type == deftypemethod))
7194 type_name = next_nonwhite_defun_arg (&scan_args);
7196 if (base_type == deftypemethod)
7197 type_name2 = next_nonwhite_defun_arg (&scan_args);
7199 defined_name = next_nonwhite_defun_arg (&scan_args);
7201 /* This hack exists solely for the purposes of formatting the texinfo
7202 manual. I couldn't think of a better way. The token might be
7203 a simple @@ followed immediately by more text. If this is the case,
7204 then the next defun arg is part of this one, and we should concatenate
7205 them. */
7206 if (*scan_args && **scan_args && !whitespace (**scan_args) &&
7207 (strcmp (defined_name, "@@") == 0))
7209 char *tem = (char *)xmalloc (3 + strlen (scan_args[0]));
7211 sprintf (tem, "@@%s", scan_args[0]);
7213 free (scan_args[0]);
7214 scan_args[0] = tem;
7215 scan_args++;
7216 defined_name = tem;
7219 if (!x_p)
7220 begin_insertion (type);
7222 /* Write the definition header line.
7223 This should start at the normal indentation. */
7224 current_indent -= default_indentation_increment;
7225 start_paragraph ();
7227 switch (base_type)
7229 case deffn:
7230 case defvr:
7231 case deftp:
7232 execute_string (" -- %s: %s", category, defined_name);
7233 break;
7234 case deftypefn:
7235 case deftypevr:
7236 execute_string (" -- %s: %s %s", category, type_name, defined_name);
7237 break;
7238 case defcv:
7239 execute_string (" -- %s of %s: %s", category, type_name, defined_name);
7240 break;
7241 case defop:
7242 execute_string (" -- %s on %s: %s", category, type_name, defined_name);
7243 break;
7244 case deftypemethod:
7245 execute_string (" -- %s on %s: %s %s", category, type_name, type_name2,
7246 defined_name);
7247 break;
7249 current_indent += default_indentation_increment;
7251 /* Now process the function arguments, if any.
7252 If these carry onto the next line, they should be indented by two
7253 increments to distinguish them from the body of the definition,
7254 which is indented by one increment. */
7255 current_indent += default_indentation_increment;
7257 switch (base_type)
7259 case deffn:
7260 case defop:
7261 process_defun_args (scan_args, 1);
7262 break;
7264 /* Through Makeinfo 1.67 we processed remaining args only for deftp,
7265 deftypefn, and deftypemethod. But the libc manual, for example,
7266 needs to say:
7267 @deftypevar {char *} tzname[2]
7268 And simply allowing the extra text seems far simpler than trying
7269 to invent yet more defn commands. In any case, we should either
7270 output it or give an error, not silently ignore it. */
7271 default:
7272 process_defun_args (scan_args, 0);
7273 break;
7275 current_indent -= default_indentation_increment;
7276 close_single_paragraph ();
7278 /* Make an entry in the appropriate index. */
7279 switch (base_type)
7281 case deffn:
7282 case deftypefn:
7283 execute_string ("%cfindex %s\n", COMMAND_PREFIX, defined_name);
7284 break;
7285 case defvr:
7286 case deftypevr:
7287 case defcv:
7288 execute_string ("%cvindex %s\n", COMMAND_PREFIX, defined_name);
7289 break;
7290 case defop:
7291 case deftypemethod:
7292 execute_string ("%cfindex %s on %s\n",
7293 COMMAND_PREFIX, defined_name, type_name);
7294 break;
7295 case deftp:
7296 execute_string ("%ctindex %s\n", COMMAND_PREFIX, defined_name);
7297 break;
7300 /* Deallocate the token list. */
7301 scan_args = defun_args;
7302 while (1)
7304 char * arg = (*scan_args++);
7305 if (arg == NULL)
7306 break;
7307 free (arg);
7309 free (defun_args);
7312 /* Add an entry for a function, macro, special form, variable, or option.
7313 If the name of the calling command ends in `x', then this is an extra
7314 entry included in the body of an insertion of the same type. */
7315 void
7316 cm_defun ()
7318 int x_p;
7319 enum insertion_type type;
7320 char *temp = xstrdup (command);
7322 x_p = (command[strlen (command) - 1] == 'x');
7324 if (x_p)
7325 temp[strlen (temp) - 1] = 0;
7327 type = find_type_from_name (temp);
7328 free (temp);
7330 /* If we are adding to an already existing insertion, then make sure
7331 that we are already in an insertion of type TYPE. */
7332 if (x_p &&
7333 (!insertion_level || insertion_stack->insertion != type))
7335 line_error (_("Must be in a `%s' insertion in order to use `%s'x"),
7336 command, command);
7337 discard_until ("\n");
7338 return;
7341 defun_internal (type, x_p);
7344 /* **************************************************************** */
7345 /* */
7346 /* Other Random Commands */
7347 /* */
7348 /* **************************************************************** */
7350 /* This says to inhibit the indentation of the next paragraph, but
7351 not of following paragraphs. */
7352 void
7353 cm_noindent ()
7355 if (!inhibit_paragraph_indentation)
7356 inhibit_paragraph_indentation = -1;
7359 /* I don't know exactly what to do with this. Should I allow
7360 someone to switch filenames in the middle of output? Since the
7361 file could be partially written, this doesn't seem to make sense.
7362 Another option: ignore it, since they don't *really* want to
7363 switch files. Finally, complain, or at least warn. */
7364 void
7365 cm_setfilename ()
7367 char *filename;
7368 get_rest_of_line (&filename);
7369 /* warning ("`@%s %s' encountered and ignored", command, filename); */
7370 free (filename);
7373 void
7374 cm_ignore_line ()
7376 discard_until ("\n");
7379 /* @br can be immediately followed by `{}', so we have to read those here.
7380 It should simply close the paragraph. */
7381 void
7382 cm_br ()
7384 if (looking_at ("{}"))
7385 input_text_offset += 2;
7387 if (curchar () == '\n')
7389 input_text_offset++;
7390 line_number++;
7393 close_paragraph ();
7396 /* Insert the number of blank lines passed as argument. */
7397 void
7398 cm_sp ()
7400 int lines;
7401 char *line;
7403 get_rest_of_line (&line);
7405 if (sscanf (line, "%d", &lines) != 1)
7407 line_error (_("%csp requires a positive numeric argument"), COMMAND_PREFIX);
7409 else
7411 if (lines < 0)
7412 lines = 0;
7414 while (lines--)
7415 add_char ('\n');
7417 free (line);
7420 /* @dircategory LINE outputs INFO-DIR-SECTION LINE,
7421 but not if --no-headers. */
7423 void
7424 cm_dircategory ()
7426 char *line;
7428 get_rest_of_line (&line);;
7430 if (!no_headers)
7432 insert_string ("INFO-DIR-SECTION ");
7433 insert_string (line);
7434 insert ('\n');
7437 free (line);
7440 /* Start a new line with just this text on it.
7441 Then center the line of text.
7442 This always ends the current paragraph. */
7443 void
7444 cm_center ()
7446 register int i, start, length;
7447 int fudge_factor = 1;
7448 unsigned char *line;
7450 close_paragraph ();
7451 filling_enabled = indented_fill = 0;
7452 cm_noindent ();
7453 start = output_paragraph_offset;
7454 inhibit_output_flushing ();
7455 get_rest_of_line ((char **)&line);
7456 execute_string ("%s", (char *)line);
7457 free (line);
7458 uninhibit_output_flushing ();
7460 i = output_paragraph_offset - 1;
7461 while (i > (start - 1) && output_paragraph[i] == '\n')
7462 i--;
7464 output_paragraph_offset = ++i;
7465 length = output_paragraph_offset - start;
7467 if (length < (fill_column - fudge_factor))
7469 line = (unsigned char *)xmalloc (1 + length);
7470 memcpy (line, (char *)(output_paragraph + start), length);
7472 i = (fill_column - fudge_factor - length) / 2;
7473 output_paragraph_offset = start;
7475 while (i--)
7476 insert (' ');
7478 for (i = 0; i < length; i++)
7479 insert (line[i]);
7481 free (line);
7484 insert ('\n');
7485 close_paragraph ();
7486 filling_enabled = 1;
7489 /* Show what an expression returns. */
7490 void
7491 cm_result (arg)
7492 int arg;
7494 if (arg == END)
7495 add_word ("=>");
7498 /* What an expression expands to. */
7499 void
7500 cm_expansion (arg)
7501 int arg;
7503 if (arg == END)
7504 add_word ("==>");
7507 /* Indicates two expressions are equivalent. */
7508 void
7509 cm_equiv (arg)
7510 int arg;
7512 if (arg == END)
7513 add_word ("==");
7516 /* What an expression may print. */
7517 void
7518 cm_print (arg)
7519 int arg;
7521 if (arg == END)
7522 add_word ("-|");
7525 /* An error signaled. */
7526 void
7527 cm_error (arg)
7528 int arg;
7530 if (arg == END)
7531 add_word ("error-->");
7534 /* The location of point in an example of a buffer. */
7535 void
7536 cm_point (arg)
7537 int arg;
7539 if (arg == END)
7540 add_word ("-!-");
7543 /* Start a new line with just this text on it.
7544 The text is outdented one level if possible. */
7545 void
7546 cm_exdent ()
7548 char *line;
7549 int i = current_indent;
7551 if (current_indent)
7552 current_indent -= default_indentation_increment;
7554 get_rest_of_line (&line);
7555 close_single_paragraph ();
7556 execute_string ("%s", line);
7557 current_indent = i;
7558 free (line);
7559 close_single_paragraph ();
7563 /* Remember this file, and move onto the next. */
7564 void
7565 cm_include ()
7567 char *filename;
7569 #if defined (HAVE_MACROS)
7570 if (macro_expansion_output_stream && !executing_string)
7571 me_append_before_this_command ();
7572 #endif /* HAVE_MACROS */
7574 close_paragraph ();
7575 get_rest_of_line (&filename);
7577 #if defined (HAVE_MACROS)
7578 if (macro_expansion_output_stream && !executing_string)
7579 remember_itext (input_text, input_text_offset);
7580 #endif /* HAVE_MACROS */
7582 pushfile ();
7584 /* In verbose mode we print info about including another file. */
7585 if (verbose_mode)
7587 register int i = 0;
7588 register FSTACK *stack = filestack;
7590 for (i = 0, stack = filestack; stack; stack = stack->next, i++);
7592 i *= 2;
7594 printf ("%*s", i, "");
7595 printf ("%c%s %s\n", COMMAND_PREFIX, command, filename);
7596 fflush (stdout);
7599 if (!find_and_load (filename))
7601 extern int errno;
7603 popfile ();
7604 line_number--;
7606 /* Cannot "@include foo", in line 5 of "/wh/bar". */
7607 line_error ("%c%s %s: %s", COMMAND_PREFIX, command, filename,
7608 strerror (errno));
7610 free (filename);
7611 return;
7613 else
7615 #if defined (HAVE_MACROS)
7616 if (macro_expansion_output_stream && !executing_string)
7617 remember_itext (input_text, input_text_offset);
7618 #endif /* HAVE_MACROS */
7619 reader_loop ();
7621 free (filename);
7622 popfile ();
7625 /* The other side of a malformed expression. */
7626 void
7627 misplaced_brace ()
7629 line_error (_("Misplaced %c"), '}');
7632 /* Signals end of processing. Easy to make this happen. */
7633 void
7634 cm_bye ()
7636 input_text_offset = size_of_input_text;
7639 /* Set the paragraph indentation variable to the value specified in STRING.
7640 Values can be:
7641 `asis': Don't change existing indentation.
7642 `none': Remove existing indentation.
7643 NUM: Indent NUM spaces at the starts of paragraphs.
7644 If NUM is zero, we assume `none'.
7645 Returns 0 if successful, or nonzero if STRING isn't one of the above. */
7647 set_paragraph_indent (string)
7648 char *string;
7650 if (strcmp (string, "asis") == 0 || strcmp (string, _("asis")) == 0)
7651 paragraph_start_indent = 0;
7652 else if (strcmp (string, "none") == 0 || strcmp (string, _("none")) == 0)
7653 paragraph_start_indent = -1;
7654 else
7656 if (sscanf (string, "%d", &paragraph_start_indent) != 1)
7657 return (-1);
7658 else
7660 if (paragraph_start_indent == 0)
7661 paragraph_start_indent = -1;
7664 return (0);
7667 void
7668 cm_paragraphindent ()
7670 char *arg;
7672 get_rest_of_line (&arg);
7673 if (set_paragraph_indent (arg) != 0)
7674 line_error (_("Bad argument to %c%s"), COMMAND_PREFIX, command);
7676 free (arg);
7679 /* **************************************************************** */
7680 /* */
7681 /* Indexing Stuff */
7682 /* */
7683 /* **************************************************************** */
7686 /* An index element... */
7687 typedef struct index_elt
7689 struct index_elt *next;
7690 char *entry; /* The index entry itself. */
7691 char *node; /* The node from whence it came. */
7692 int code; /* Nonzero means add `@code{...}' when
7693 printing this element. */
7694 int defining_line; /* Line number where this entry was written. */
7695 char *defining_file; /* Source file for defining_line. */
7696 } INDEX_ELT;
7698 /* A list of short-names for each index.
7700 There are two indices into the the_indices array.
7702 * read_index is the index that points to the list of index
7703 entries that we will find if we ask for the list of entries for
7704 this name.
7706 * write_index is the index that points to the list of index entries
7707 that we will add new entries to.
7709 Initially, read_index and write index are the same, but the
7710 @syncodeindex and @synindex commands can change the list we add
7711 entries to.
7713 For example, after the commands
7715 @cindex foo
7716 @defindex ii
7717 @synindex cp ii
7718 @cindex bar
7720 the cp index will contain the entry `foo', and the new ii
7721 index will contain the entry `bar'. This is consistent with the
7722 way texinfo.tex handles the same situation.
7724 In addition, for each index, it is remembered whether that index is
7725 a code index or not. Code indices have @code{} inserted around the
7726 first word when they are printed with printindex. */
7727 typedef struct
7729 char *name;
7730 int read_index; /* index entries for `name' */
7731 int write_index; /* store index entries here, @synindex can change it */
7732 int code;
7733 } INDEX_ALIST;
7735 INDEX_ALIST **name_index_alist = (INDEX_ALIST **) NULL;
7737 /* An array of pointers. Each one is for a different index. The
7738 "synindex" command changes which array slot is pointed to by a
7739 given "index". */
7740 INDEX_ELT **the_indices = (INDEX_ELT **) NULL;
7742 /* The number of defined indices. */
7743 int defined_indices = 0;
7745 void
7746 init_indices ()
7748 int i;
7750 /* Create the default data structures. */
7752 /* Initialize data space. */
7753 if (!the_indices)
7755 the_indices = (INDEX_ELT **) xmalloc ((1 + defined_indices) *
7756 sizeof (INDEX_ELT *));
7757 the_indices[defined_indices] = (INDEX_ELT *) NULL;
7759 name_index_alist = (INDEX_ALIST **) xmalloc ((1 + defined_indices) *
7760 sizeof (INDEX_ALIST *));
7761 name_index_alist[defined_indices] = (INDEX_ALIST *) NULL;
7764 /* If there were existing indices, get rid of them now. */
7765 for (i = 0; i < defined_indices; i++)
7767 undefindex (name_index_alist[i]->name);
7768 if (name_index_alist[i])
7769 { /* Suppose we're called with two input files, and the first
7770 does a @synindex pg cp. Then, when we get here to start
7771 the second file, the "pg" element won't get freed by
7772 undefindex (because it's pointing to "cp"). So free it
7773 here; otherwise, when we try to define the pg index again
7774 just below, it will still point to cp. */
7775 free (name_index_alist[i]->name);
7776 free (name_index_alist[i]);
7777 name_index_alist[i] = (INDEX_ALIST *) NULL;
7781 /* Add the default indices. */
7782 top_defindex ("cp", 0); /* cp is the only non-code index. */
7783 top_defindex ("fn", 1);
7784 top_defindex ("ky", 1);
7785 top_defindex ("pg", 1);
7786 top_defindex ("tp", 1);
7787 top_defindex ("vr", 1);
7790 /* Find which element in the known list of indices has this name.
7791 Returns -1 if NAME isn't found. */
7793 find_index_offset (name)
7794 char *name;
7796 register int i;
7797 for (i = 0; i < defined_indices; i++)
7798 if (name_index_alist[i] &&
7799 strcmp (name, name_index_alist[i]->name) == 0)
7800 return (i);
7801 return (-1);
7804 /* Return a pointer to the entry of (name . index) for this name.
7805 Return NULL if the index doesn't exist. */
7806 INDEX_ALIST *
7807 find_index (name)
7808 char *name;
7810 int offset = find_index_offset (name);
7811 if (offset > -1)
7812 return (name_index_alist[offset]);
7813 else
7814 return ((INDEX_ALIST *) NULL);
7817 /* Given an index name, return the offset in the_indices of this index,
7818 or -1 if there is no such index. */
7820 translate_index (name)
7821 char *name;
7823 INDEX_ALIST *which = find_index (name);
7825 if (which)
7826 return (which->read_index);
7827 else
7828 return (-1);
7831 /* Return the index list which belongs to NAME. */
7832 INDEX_ELT *
7833 index_list (name)
7834 char *name;
7836 int which = translate_index (name);
7837 if (which < 0)
7838 return ((INDEX_ELT *) -1);
7839 else
7840 return (the_indices[which]);
7843 /* Please release me, let me go... */
7844 void
7845 free_index (index)
7846 INDEX_ELT *index;
7848 INDEX_ELT *temp;
7850 while ((temp = index) != (INDEX_ELT *) NULL)
7852 free (temp->entry);
7853 /* Do not free the node, because we already freed the tag table,
7854 which freed all the node names. */
7855 /* free (temp->node); */
7856 index = index->next;
7857 free (temp);
7861 /* Flush an index by name. This will delete the list of entries that
7862 would be written by a @printindex command for this index. */
7863 void
7864 undefindex (name)
7865 char *name;
7867 int i;
7868 int which = find_index_offset (name);
7870 /* The index might have already been freed if this was the target of
7871 an @synindex. */
7872 if (which < 0 || !name_index_alist[which])
7873 return;
7875 i = name_index_alist[which]->read_index;
7877 free_index (the_indices[i]);
7878 the_indices[i] = (INDEX_ELT *) NULL;
7880 free (name_index_alist[which]->name);
7881 free (name_index_alist[which]);
7882 name_index_alist[which] = (INDEX_ALIST *) NULL;
7885 /* Define an index known as NAME. We assign the slot number.
7886 CODE if Nonzero says to make this a code index. */
7887 void
7888 defindex (name, code)
7889 char *name;
7890 int code;
7892 register int i, slot;
7894 /* If it already exists, flush it. */
7895 undefindex (name);
7897 /* Try to find an empty slot. */
7898 slot = -1;
7899 for (i = 0; i < defined_indices; i++)
7900 if (!name_index_alist[i])
7902 slot = i;
7903 break;
7906 if (slot < 0)
7908 /* No such luck. Make space for another index. */
7909 slot = defined_indices;
7910 defined_indices++;
7912 name_index_alist = (INDEX_ALIST **)
7913 xrealloc ((char *)name_index_alist,
7914 (1 + defined_indices) * sizeof (INDEX_ALIST *));
7915 the_indices = (INDEX_ELT **)
7916 xrealloc ((char *)the_indices,
7917 (1 + defined_indices) * sizeof (INDEX_ELT *));
7920 /* We have a slot. Start assigning. */
7921 name_index_alist[slot] = (INDEX_ALIST *) xmalloc (sizeof (INDEX_ALIST));
7922 name_index_alist[slot]->name = xstrdup (name);
7923 name_index_alist[slot]->read_index = slot;
7924 name_index_alist[slot]->write_index = slot;
7925 name_index_alist[slot]->code = code;
7927 the_indices[slot] = (INDEX_ELT *) NULL;
7930 /* Add the arguments to the current index command to the index NAME. */
7931 void
7932 index_add_arg (name)
7933 char *name;
7935 int which;
7936 char *index_entry;
7937 INDEX_ALIST *tem;
7939 tem = find_index (name);
7941 which = tem ? tem->write_index : -1;
7943 #if defined (HAVE_MACROS)
7944 if (macro_expansion_output_stream && !executing_string)
7945 append_to_expansion_output (input_text_offset + 1);
7946 #endif /* HAVE_MACROS */
7948 get_rest_of_line (&index_entry);
7949 ignore_blank_line ();
7951 #if defined (HAVE_MACROS)
7952 if (macro_expansion_output_stream && !executing_string)
7954 int op_orig;
7956 remember_itext (input_text, input_text_offset);
7957 op_orig = output_paragraph_offset;
7958 me_execute_string (index_entry);
7959 me_execute_string ("\n");
7960 output_paragraph_offset = op_orig;
7962 #endif /* HAVE_MACROS */
7964 if (which < 0)
7966 line_error (_("Unknown index `%s'"), name);
7967 free (index_entry);
7969 else
7971 INDEX_ELT *new = (INDEX_ELT *) xmalloc (sizeof (INDEX_ELT));
7972 new->next = the_indices[which];
7973 new->entry = index_entry;
7974 new->node = current_node;
7975 new->code = tem->code;
7976 new->defining_line = line_number - 1;
7977 new->defining_file = input_filename;
7978 the_indices[which] = new;
7982 #define INDEX_COMMAND_SUFFIX "index"
7984 /* The function which user defined index commands call. */
7985 void
7986 gen_index ()
7988 char *name = xstrdup (command);
7989 if (strlen (name) >= strlen ("index"))
7990 name[strlen (name) - strlen ("index")] = 0;
7991 index_add_arg (name);
7992 free (name);
7995 void
7996 top_defindex (name, code)
7997 char *name;
7998 int code;
8000 char *temp;
8002 temp = (char *) xmalloc (1 + strlen (name) + strlen ("index"));
8003 sprintf (temp, "%sindex", name);
8004 define_user_command (temp, gen_index, 0);
8005 defindex (name, code);
8006 free (temp);
8009 /* Define a new index command. Arg is name of index. */
8010 void
8011 cm_defindex ()
8013 gen_defindex (0);
8016 void
8017 cm_defcodeindex ()
8019 gen_defindex (1);
8022 void
8023 gen_defindex (code)
8024 int code;
8026 char *name;
8027 get_rest_of_line (&name);
8029 if (find_index (name))
8031 line_error (_("Index `%s' already exists"), name);
8032 free (name);
8033 return;
8035 else
8037 char *temp = (char *) alloca (1 + strlen (name) + strlen ("index"));
8038 sprintf (temp, "%sindex", name);
8039 define_user_command (temp, gen_index, 0);
8040 defindex (name, code);
8041 free (name);
8045 /* Expects 2 args, on the same line. Both are index abbreviations.
8046 Make the first one be a synonym for the second one, i.e. make the
8047 first one have the same index as the second one. */
8048 void
8049 cm_synindex ()
8051 int source, target;
8052 char *abbrev1, *abbrev2;
8054 skip_whitespace ();
8055 get_until_in_line (0, " ", &abbrev1);
8056 target = find_index_offset (abbrev1);
8057 skip_whitespace ();
8058 get_until_in_line (0, " ", &abbrev2);
8059 source = find_index_offset (abbrev2);
8060 if (source < 0 || target < 0)
8062 line_error (_("Unknown index `%s' and/or `%s' in @synindex"),
8063 abbrev1, abbrev2);
8065 else
8067 name_index_alist[target]->write_index
8068 = name_index_alist[source]->write_index;
8071 free (abbrev1);
8072 free (abbrev2);
8075 void
8076 cm_pindex () /* Pinhead index. */
8078 index_add_arg ("pg");
8081 void
8082 cm_vindex () /* Variable index. */
8084 index_add_arg ("vr");
8087 void
8088 cm_kindex () /* Key index. */
8090 index_add_arg ("ky");
8093 void
8094 cm_cindex () /* Concept index. */
8096 index_add_arg ("cp");
8099 void
8100 cm_findex () /* Function index. */
8102 index_add_arg ("fn");
8105 void
8106 cm_tindex () /* Data Type index. */
8108 index_add_arg ("tp");
8111 /* Sorting the index. */
8113 index_element_compare (element1, element2)
8114 INDEX_ELT **element1, **element2;
8116 return (strcasecmp ((*element1)->entry, (*element2)->entry));
8119 /* Force all index entries to be unique. */
8120 void
8121 make_index_entries_unique (array, count)
8122 INDEX_ELT **array;
8123 int count;
8125 register int i, j;
8126 INDEX_ELT **copy;
8127 int counter = 1;
8129 copy = (INDEX_ELT **)xmalloc ((1 + count) * sizeof (INDEX_ELT *));
8131 for (i = 0, j = 0; i < count; i++)
8133 if ((i == (count - 1)) ||
8134 (array[i]->node != array[i + 1]->node) ||
8135 (strcmp (array[i]->entry, array[i + 1]->entry) != 0))
8136 copy[j++] = array[i];
8137 else
8139 free (array[i]->entry);
8140 free (array[i]);
8143 copy[j] = (INDEX_ELT *)NULL;
8145 /* Now COPY contains only unique entries. Duplicated entries in the
8146 original array have been freed. Replace the current array with
8147 the copy, fixing the NEXT pointers. */
8148 for (i = 0; copy[i] != (INDEX_ELT *)NULL; i++)
8151 copy[i]->next = copy[i + 1];
8153 /* Fix entry names which are the same. They point to different nodes,
8154 so we make the entry name unique. */
8155 if ((copy[i + 1] != (INDEX_ELT *)NULL) &&
8156 (strcmp (copy[i]->entry, copy[i + 1]->entry) == 0))
8158 char *new_entry_name;
8160 new_entry_name = (char *)xmalloc (10 + strlen (copy[i]->entry));
8161 sprintf (new_entry_name, "%s <%d>", copy[i]->entry, counter);
8162 free (copy[i]->entry);
8163 copy[i]->entry = new_entry_name;
8164 counter++;
8166 else
8167 counter = 1;
8169 array[i] = copy[i];
8171 array[i] = (INDEX_ELT *)NULL;
8173 /* Free the storage used only by COPY. */
8174 free (copy);
8177 /* Sort the index passed in INDEX, returning an array of
8178 pointers to elements. The array is terminated with a NULL
8179 pointer. We call qsort because it's supposed to be fast.
8180 I think this looks bad. */
8181 INDEX_ELT **
8182 sort_index (index)
8183 INDEX_ELT *index;
8185 INDEX_ELT **array;
8186 INDEX_ELT *temp = index;
8187 int count = 0;
8188 int save_line_number = line_number;
8189 char *save_input_filename = input_filename;
8191 while (temp != (INDEX_ELT *) NULL)
8193 count++;
8194 temp = temp->next;
8197 /* We have the length. Make an array. */
8199 array = (INDEX_ELT **) xmalloc ((count + 1) * sizeof (INDEX_ELT *));
8200 count = 0;
8201 temp = index;
8203 while (temp != (INDEX_ELT *) NULL)
8205 array[count++] = temp;
8207 /* Set line number and input filename to the source line for this
8208 index entry, as this expansion finds any errors. */
8209 line_number = array[count - 1]->defining_line;
8210 input_filename = array[count - 1]->defining_file;
8212 /* If this particular entry should be printed as a "code" index,
8213 then wrap the entry with "@code{...}". */
8214 array[count - 1]->entry = expansion (temp->entry, index->code);
8216 temp = temp->next;
8218 array[count] = (INDEX_ELT *) NULL; /* terminate the array. */
8219 line_number = save_line_number;
8220 input_filename = save_input_filename;
8222 /* Sort the array. */
8223 qsort (array, count, sizeof (INDEX_ELT *), index_element_compare);
8224 make_index_entries_unique (array, count);
8225 return (array);
8228 /* Nonzero means that we are in the middle of printing an index. */
8229 int printing_index = 0;
8231 /* Takes one arg, a short name of an index to print.
8232 Outputs a menu of the sorted elements of the index. */
8233 void
8234 cm_printindex ()
8236 int item;
8237 INDEX_ELT *index;
8238 INDEX_ELT **array;
8239 char *index_name;
8240 unsigned line_length;
8241 char *line;
8242 int saved_inhibit_paragraph_indentation = inhibit_paragraph_indentation;
8243 int saved_filling_enabled = filling_enabled;
8245 close_paragraph ();
8246 get_rest_of_line (&index_name);
8248 index = index_list (index_name);
8249 if (index == (INDEX_ELT *)-1)
8251 line_error (_("Unknown index `%s' in @printindex"), index_name);
8252 free (index_name);
8253 return;
8255 else
8256 free (index_name);
8258 /* Do this before sorting, so execute_string in index_element_compare
8259 will give the same results as when we actually print. */
8260 printing_index = 1;
8261 filling_enabled = 0;
8262 inhibit_paragraph_indentation = 1;
8263 array = sort_index (index);
8265 close_paragraph ();
8266 add_word (_("* Menu:\n\n"));
8268 #if defined (HAVE_MACROS)
8269 me_inhibit_expansion++;
8270 #endif /* HAVE_MACROS */
8272 /* This will probably be enough. */
8273 line_length = 100;
8274 line = xmalloc (line_length);
8276 for (item = 0; (index = array[item]); item++)
8278 /* A pathological document might have an index entry outside of any
8279 node. Don't crash. Perhaps should warn. */
8280 char *index_node = index->node ? index->node : "(none)";
8281 unsigned new_length = strlen (index->entry);
8283 if (new_length < 37) /* minimum length used below */
8284 new_length = 37;
8285 new_length += strlen (index_node) + 7; /* * : .\n\0 */
8287 if (new_length > line_length)
8289 line_length = new_length;
8290 line = xrealloc (line, line_length);
8293 /* Print the entry, nicely formatted. We've already expanded any
8294 commands, including any implicit @code. Thus, can't call
8295 execute_string, since @@ has turned into @. */
8296 sprintf (line, "* %-37s %s.\n", index->entry, index_node);
8297 line[2 + strlen (index->entry)] = ':';
8298 insert_string (line);
8300 /* Previous `output_paragraph' from growing to the size of the
8301 whole index. */
8302 flush_output ();
8305 free (line);
8307 #if defined (HAVE_MACROS)
8308 me_inhibit_expansion--;
8309 #endif /* HAVE_MACROS */
8311 printing_index = 0;
8312 free (array);
8313 close_single_paragraph ();
8314 filling_enabled = saved_filling_enabled;
8315 inhibit_paragraph_indentation = saved_inhibit_paragraph_indentation;
8318 /* User-defined commands, which happens only from user-defined indexes. */
8320 void
8321 define_user_command (name, proc, needs_braces_p)
8322 char *name;
8323 COMMAND_FUNCTION *proc;
8324 int needs_braces_p;
8326 int slot = user_command_array_len;
8327 user_command_array_len++;
8329 if (!user_command_array)
8330 user_command_array = (COMMAND **) xmalloc (1 * sizeof (COMMAND *));
8332 user_command_array = (COMMAND **) xrealloc (user_command_array,
8333 (1 + user_command_array_len) *
8334 sizeof (COMMAND *));
8336 user_command_array[slot] = (COMMAND *) xmalloc (sizeof (COMMAND));
8337 user_command_array[slot]->name = xstrdup (name);
8338 user_command_array[slot]->proc = proc;
8339 user_command_array[slot]->argument_in_braces = needs_braces_p;
8342 /* Some support for footnotes. */
8344 /* Footnotes are a new construct in Info. We don't know the best method
8345 of implementing them for sure, so we present two possiblities.
8347 SeparateNode:
8348 Make them look like followed references, with the reference
8349 destinations in a makeinfo manufactured node or,
8351 EndNode:
8352 Make them appear at the bottom of the node that they originally
8353 appeared in. */
8354 #define SeparateNode 0
8355 #define EndNode 1
8357 int footnote_style = EndNode;
8358 int first_footnote_this_node = 1;
8359 int footnote_count = 0;
8361 /* Set the footnote style based on he style identifier in STRING. */
8363 set_footnote_style (string)
8364 char *string;
8366 if ((strcasecmp (string, "separate") == 0) ||
8367 (strcasecmp (string, "MN") == 0))
8368 footnote_style = SeparateNode;
8369 else if ((strcasecmp (string, "end") == 0) ||
8370 (strcasecmp (string, "EN") == 0))
8371 footnote_style = EndNode;
8372 else
8373 return (-1);
8375 return (0);
8378 void
8379 cm_footnotestyle ()
8381 char *arg;
8383 get_rest_of_line (&arg);
8385 /* If set on command line, do not change the footnote style. */
8386 if (!footnote_style_preset && set_footnote_style (arg) != 0)
8387 line_error ("Bad argument to %c%s", COMMAND_PREFIX, command);
8389 free (arg);
8392 typedef struct fn
8394 struct fn *next;
8395 char *marker;
8396 char *note;
8397 } FN;
8399 FN *pending_notes = (FN *) NULL;
8401 /* A method for remembering footnotes. Note that this list gets output
8402 at the end of the current node. */
8403 void
8404 remember_note (marker, note)
8405 char *marker, *note;
8407 FN *temp = (FN *) xmalloc (sizeof (FN));
8409 temp->marker = xstrdup (marker);
8410 temp->note = xstrdup (note);
8411 temp->next = pending_notes;
8412 pending_notes = temp;
8413 footnote_count++;
8416 /* How to get rid of existing footnotes. */
8417 void
8418 free_pending_notes ()
8420 FN *temp;
8422 while ((temp = pending_notes) != (FN *) NULL)
8424 free (temp->marker);
8425 free (temp->note);
8426 pending_notes = pending_notes->next;
8427 free (temp);
8429 first_footnote_this_node = 1;
8430 footnote_count = 0;
8433 /* What to do when you see a @footnote construct. */
8435 /* Handle a "footnote".
8436 footnote *{this is a footnote}
8437 where "*" is the (optional) marker character for this note. */
8438 void
8439 cm_footnote ()
8441 char *marker;
8442 char *note;
8444 get_until ("{", &marker);
8445 canon_white (marker);
8447 if (macro_expansion_output_stream && !executing_string)
8448 append_to_expansion_output (input_text_offset + 1); /* include the { */
8450 /* Read the argument in braces. */
8451 if (curchar () != '{')
8453 line_error (_("`%c%s' needs an argument `{...}', not just `%s'"),
8454 COMMAND_PREFIX, command, marker);
8455 free (marker);
8456 return;
8458 else
8460 int len;
8461 int braces = 1;
8462 int loc = ++input_text_offset;
8464 while (braces)
8466 if (loc == size_of_input_text)
8468 line_error (_("No closing brace for footnote `%s'"), marker);
8469 return;
8472 if (input_text[loc] == '{')
8473 braces++;
8474 else if (input_text[loc] == '}')
8475 braces--;
8476 else if (input_text[loc] == '\n')
8477 line_number++;
8479 loc++;
8482 len = (loc - input_text_offset) - 1;
8483 note = (char *)xmalloc (len + 1);
8484 strncpy (note, &input_text[input_text_offset], len);
8485 note[len] = 0;
8486 input_text_offset = loc;
8489 /* Must write the macro-expanded argument to the macro expansion
8490 output stream. This is like the case in index_add_arg. */
8491 if (macro_expansion_output_stream && !executing_string)
8493 int op_orig;
8495 remember_itext (input_text, input_text_offset);
8496 op_orig = output_paragraph_offset;
8497 me_execute_string (note);
8498 /* Calling me_execute_string on a lone } provokes an error, since
8499 as far as the reader knows there is no matching {. We wrote
8500 the { above in the call to append_to_expansion_output. */
8501 write_region_to_macro_output ("}", 0, 1);
8502 output_paragraph_offset = op_orig;
8505 if (!current_node || !*current_node)
8507 line_error (_("Footnote defined without parent node"));
8508 free (marker);
8509 free (note);
8510 return;
8513 if (!*marker)
8515 free (marker);
8517 if (number_footnotes)
8519 marker = (char *)xmalloc (10);
8520 sprintf (marker, "%d", current_footnote_number);
8521 current_footnote_number++;
8523 else
8524 marker = xstrdup ("*");
8527 remember_note (marker, note);
8529 /* Your method should at least insert MARKER. */
8530 switch (footnote_style)
8532 case SeparateNode:
8533 add_word_args ("(%s)", marker);
8534 if (first_footnote_this_node)
8536 char *temp_string;
8538 temp_string = (char *)
8539 xmalloc ((strlen (current_node)) + (strlen (_("-Footnotes"))) + 1);
8541 add_word_args (" (*note %s-Footnotes::)", current_node);
8542 strcpy (temp_string, current_node);
8543 strcat (temp_string, "-Footnotes");
8544 remember_node_reference (temp_string, line_number, followed_reference);
8545 free (temp_string);
8546 first_footnote_this_node = 0;
8548 break;
8550 case EndNode:
8551 add_word_args ("(%s)", marker);
8552 break;
8554 default:
8555 break;
8557 free (marker);
8558 free (note);
8561 /* Nonzero means that we are currently in the process of outputting
8562 footnotes. */
8563 int already_outputting_pending_notes = 0;
8565 /* Output the footnotes. We are at the end of the current node. */
8566 void
8567 output_pending_notes ()
8569 FN *footnote = pending_notes;
8571 if (!pending_notes)
8572 return;
8574 switch (footnote_style)
8576 case SeparateNode:
8578 char *old_current_node = current_node;
8579 char *old_command = xstrdup (command);
8581 already_outputting_pending_notes++;
8582 execute_string ("%cnode %s-Footnotes,,,%s\n",
8583 COMMAND_PREFIX, current_node, current_node);
8584 already_outputting_pending_notes--;
8585 current_node = old_current_node;
8586 free (command);
8587 command = old_command;
8589 break;
8591 case EndNode:
8592 close_paragraph ();
8593 in_fixed_width_font++;
8594 execute_string (_("---------- Footnotes ----------\n\n"));
8595 in_fixed_width_font--;
8596 break;
8599 /* Handle the footnotes in reverse order. */
8601 FN **array = (FN **) xmalloc ((footnote_count + 1) * sizeof (FN *));
8603 array[footnote_count] = (FN *) NULL;
8605 while (--footnote_count > -1)
8607 array[footnote_count] = footnote;
8608 footnote = footnote->next;
8611 filling_enabled = 1;
8612 indented_fill = 1;
8614 while ((footnote = array[++footnote_count]))
8616 execute_string ("(%s) %s", footnote->marker, footnote->note);
8617 close_paragraph ();
8619 close_paragraph ();
8620 free (array);
8624 /* **************************************************************** */
8625 /* */
8626 /* User definable Macros (text substitution) */
8627 /* */
8628 /* **************************************************************** */
8630 #if defined (HAVE_MACROS)
8632 /* Array of macros and definitions. */
8633 MACRO_DEF **macro_list = (MACRO_DEF **)NULL;
8635 int macro_list_len = 0; /* Number of elements. */
8636 int macro_list_size = 0; /* Number of slots in total. */
8638 /* Return the macro definition of NAME or NULL if NAME is not defined. */
8639 MACRO_DEF *
8640 find_macro (name)
8641 char *name;
8643 register int i;
8644 register MACRO_DEF *def;
8646 def = (MACRO_DEF *)NULL;
8647 for (i = 0; macro_list && (def = macro_list[i]); i++)
8649 if ((!def->inhibited) && (strcmp (def->name, name) == 0))
8650 break;
8652 return (def);
8655 /* Add the macro NAME with ARGLIST and BODY to the list of defined macros.
8656 SOURCE_FILE is the name of the file where this definition can be found,
8657 and SOURCE_LINENO is the line number within that file. If a macro already
8658 exists with NAME, then a warning is produced, and that previous
8659 definition is overwritten. */
8660 void
8661 add_macro (name, arglist, body, source_file, source_lineno, flags)
8662 char *name;
8663 char **arglist;
8664 char *body;
8665 char *source_file;
8666 int source_lineno, flags;
8668 register MACRO_DEF *def;
8670 def = find_macro (name);
8672 if (!def)
8674 if (macro_list_len + 2 >= macro_list_size)
8675 macro_list = (MACRO_DEF **)xrealloc
8676 (macro_list, ((macro_list_size += 10) * sizeof (MACRO_DEF *)));
8678 macro_list[macro_list_len] = (MACRO_DEF *)xmalloc (sizeof (MACRO_DEF));
8679 macro_list[macro_list_len + 1] = (MACRO_DEF *)NULL;
8681 def = macro_list[macro_list_len];
8682 macro_list_len += 1;
8683 def->name = name;
8685 else
8687 char *temp_filename = input_filename;
8688 int temp_line = line_number;
8690 warning (_("macro `%s' previously defined"), name);
8692 input_filename = def->source_file;
8693 line_number = def->source_lineno;
8694 warning (_("here is the previous definition of `%s'"), name);
8696 input_filename = temp_filename;
8697 line_number = temp_line;
8699 if (def->arglist)
8701 register int i;
8703 for (i = 0; def->arglist[i]; i++)
8704 free (def->arglist[i]);
8706 free (def->arglist);
8708 free (def->source_file);
8709 free (def->body);
8712 def->source_file = xstrdup (source_file);
8713 def->source_lineno = source_lineno;
8714 def->body = body;
8715 def->arglist = arglist;
8716 def->inhibited = 0;
8717 def->flags = flags;
8720 /* Delete the macro with name NAME. The macro is deleted from the list,
8721 but it is also returned. If there was no macro defined, NULL is
8722 returned. */
8723 MACRO_DEF *
8724 delete_macro (name)
8725 char *name;
8727 register int i;
8728 register MACRO_DEF *def;
8730 def = (MACRO_DEF *)NULL;
8732 for (i = 0; macro_list && (def = macro_list[i]); i++)
8733 if (strcmp (def->name, name) == 0)
8735 memmove (macro_list + i, macro_list + i + 1,
8736 ((macro_list_len + 1) - i) * sizeof (MACRO_DEF *));
8737 macro_list_len--;
8738 break;
8740 return (def);
8743 /* Return the arglist on the current line. This can behave in two different
8744 ways, depending on the variable BRACES_REQUIRED_FOR_MACRO_ARGS. */
8745 int braces_required_for_macro_args = 0;
8747 char **
8748 get_macro_args (def)
8749 MACRO_DEF *def;
8751 register int i;
8752 char *word;
8754 /* Quickly check to see if this macro has been invoked with any arguments.
8755 If not, then don't skip any of the following whitespace. */
8756 for (i = input_text_offset; i < size_of_input_text; i++)
8757 if (!cr_or_whitespace (input_text[i]))
8758 break;
8760 if (input_text[i] != '{')
8762 if (braces_required_for_macro_args)
8764 return ((char **)NULL);
8766 else
8768 /* Braces are not required to fill out the macro arguments. If
8769 this macro takes one argument, it is considered to be the
8770 remainder of the line, sans whitespace. */
8771 if (def->arglist && def->arglist[0] && !def->arglist[1])
8773 char **arglist;
8775 get_rest_of_line (&word);
8776 if (input_text[input_text_offset - 1] == '\n')
8778 input_text_offset--;
8779 line_number--;
8781 /* canon_white (word); */
8782 arglist = (char **)xmalloc (2 * sizeof (char *));
8783 arglist[0] = word;
8784 arglist[1] = (char *)NULL;
8785 return (arglist);
8787 else
8789 /* The macro either took no arguments, or took more than
8790 one argument. In that case, it must be invoked with
8791 arguments surrounded by braces. */
8792 return ((char **)NULL);
8796 return (get_brace_args (def->flags & ME_QUOTE_ARG));
8799 /* Substitute actual parameters for named parameters in body.
8800 The named parameters which appear in BODY must by surrounded
8801 reverse slashes, as in \foo\. */
8802 char *
8803 apply (named, actuals, body)
8804 char **named, **actuals, *body;
8806 register int i;
8807 int new_body_index, new_body_size;
8808 char *new_body, *text;
8809 int length_of_actuals;
8811 length_of_actuals = array_len (actuals);
8812 new_body_size = strlen (body);
8813 new_body = (char *)xmalloc (1 + new_body_size);
8815 /* Copy chars from BODY into NEW_BODY. */
8816 i = 0; new_body_index = 0;
8818 while (1)
8820 if (!body[i])
8821 break;
8823 if (body[i] != '\\')
8824 new_body[new_body_index++] = body[i++];
8825 else
8827 /* Snarf parameter name, check against named parameters. */
8828 char *param;
8829 int param_start, which, len;
8831 param_start = ++i;
8832 while ((body[i]) && (body[i] != '\\'))
8833 i++;
8835 len = i - param_start;
8836 param = (char *)xmalloc (1 + len);
8837 memcpy (param, body + param_start, len);
8838 param[len] = 0;
8840 if (body[i]) /* move past \ */
8841 i++;
8843 /* Now check against named parameters. */
8844 for (which = 0; named && named[which]; which++)
8845 if (strcmp (named[which], param) == 0)
8846 break;
8848 if (named && named[which])
8850 if (which < length_of_actuals)
8851 text = actuals[which];
8852 else
8853 text = (char *)NULL;
8855 if (!text)
8856 text = "";
8858 len = strlen (text);
8860 else
8861 { /* not a parameter, restore \'s */
8862 i = body[i] ? (i - 1) : i;
8863 len++;
8864 text = xmalloc (1 + len);
8865 sprintf (text, "\\%s", param);
8868 if ((2 + strlen (param)) < len)
8870 new_body_size += len + 1;
8871 new_body = xrealloc (new_body, new_body_size);
8874 free (param);
8876 strcpy (new_body + new_body_index, text);
8877 new_body_index += len;
8879 if (!named || !named[which])
8880 free (text);
8883 new_body[new_body_index] = 0;
8884 return (new_body);
8887 /* Execute the macro passed in DEF, a pointer to a MACRO_DEF. */
8888 void
8889 execute_macro (def)
8890 MACRO_DEF *def;
8892 char **arglist;
8893 int num_args;
8894 char *execution_string = (char *)NULL;
8896 if (macro_expansion_output_stream && !executing_string && !me_inhibit_expansion)
8897 me_append_before_this_command ();
8899 /* Find out how many arguments this macro definition takes. */
8900 num_args = array_len (def->arglist);
8902 /* Gather the arguments present on the line if there are any. */
8903 arglist = get_macro_args (def);
8905 if (num_args < array_len (arglist))
8907 free_array (arglist);
8908 line_error (_("Macro `%s' called with too many args"), def->name);
8909 return;
8912 if (def->body)
8913 execution_string = apply (def->arglist, arglist, def->body);
8915 free_array (arglist);
8917 if (def->body)
8919 if (macro_expansion_output_stream && !executing_string && !me_inhibit_expansion)
8921 remember_itext (input_text, input_text_offset);
8922 me_execute_string (execution_string);
8924 else
8925 execute_string ("%s", execution_string);
8927 free (execution_string);
8931 /* Read and remember the definition of a macro. */
8932 void
8933 cm_macro ()
8935 register int i;
8936 char *name, **arglist, *body, *line;
8937 int body_size, body_index;
8938 int depth = 1;
8939 int defining_line = line_number;
8940 int flags = 0;
8942 arglist = (char **)NULL;
8943 body = (char *)NULL;
8944 body_size = 0;
8945 body_index = 0;
8947 if (macro_expansion_output_stream && !executing_string)
8948 me_append_before_this_command ();
8950 skip_whitespace ();
8952 /* Get the name of the macro. This is the set of characters which are
8953 not whitespace and are not `{' immediately following the @macro. */
8955 int start = input_text_offset;
8956 int len;
8958 for (i = start;
8959 (i < size_of_input_text) &&
8960 (input_text[i] != '{') &&
8961 (!cr_or_whitespace (input_text[i]));
8962 i++);
8964 len = i - start;
8965 name = (char *)xmalloc (1 + len);
8966 strncpy (name, input_text + start, len);
8967 name[len] = 0;
8968 input_text_offset = i;
8971 skip_whitespace ();
8973 /* It is not required that the definition of a macro includes an arglist.
8974 If not, don't try to get the named parameters, just use a null list. */
8975 if (curchar () == '{')
8977 int arglist_index = 0, arglist_size = 0;
8978 int gathering_words = 1;
8979 char *word = (char *)NULL;
8980 int character;
8982 /* Read the words inside of the braces which determine the arglist.
8983 These words will be replaced within the body of the macro at
8984 execution time. */
8986 input_text_offset++;
8987 skip_whitespace_and_newlines ();
8989 while (gathering_words)
8991 int len;
8993 for (i = input_text_offset;
8994 (character = input_text[i]);
8995 i++)
8997 switch (character)
8999 case '\n':
9000 line_number++;
9001 case ' ':
9002 case '\t':
9003 case ',':
9004 case '}':
9005 /* Found the end of the current arglist word. Save it. */
9006 len = i - input_text_offset;
9007 word = (char *)xmalloc (1 + len);
9008 strncpy (word, input_text + input_text_offset, len);
9009 word[len] = 0;
9010 input_text_offset = i;
9012 /* Advance to the comma or close-brace that signified
9013 the end of the argument. */
9014 while ((character = curchar ())
9015 && character != ','
9016 && character != '}')
9018 input_text_offset++;
9019 if (character == '\n')
9020 line_number++;
9023 /* Add the word to our list of words. */
9024 if ((arglist_index + 2) >= arglist_size)
9025 arglist = (char **)xrealloc
9026 (arglist, (arglist_size += 10) * sizeof (char *));
9028 arglist[arglist_index++] = word;
9029 arglist[arglist_index] = (char *)NULL;
9030 break;
9033 if (character == '}')
9035 input_text_offset++;
9036 gathering_words = 0;
9037 break;
9040 if (character == ',')
9042 input_text_offset++;
9043 skip_whitespace_and_newlines ();
9044 i = input_text_offset - 1;
9050 /* Read the text carefully until we find an "@end macro" which
9051 matches this one. The text in between is the body of the macro. */
9052 skip_whitespace_and_newlines ();
9054 while (depth)
9056 if ((input_text_offset + 9) > size_of_input_text)
9058 int temp_line = line_number;
9059 line_number = defining_line;
9060 line_error (_("%cend macro not found"), COMMAND_PREFIX);
9061 line_number = temp_line;
9062 return;
9065 get_rest_of_line (&line);
9067 /* Handle commands only meaningful within a macro. */
9068 if ((*line == COMMAND_PREFIX) && (depth == 1) &&
9069 (strncmp (line + 1, "allow-recursion", 15) == 0) &&
9070 (line[16] == 0 || whitespace (line[16])))
9072 for (i = 16; whitespace (line[i]); i++);
9073 strcpy (line, line + i);
9074 flags |= ME_RECURSE;
9075 if (!*line)
9077 free (line);
9078 continue;
9082 if ((*line == COMMAND_PREFIX) && (depth == 1) &&
9083 (strncmp (line + 1, "quote-arg", 9) == 0) &&
9084 (line[10] == 0 || whitespace (line[10])))
9086 for (i = 10; whitespace (line[i]); i++);
9087 strcpy (line, line + i);
9089 if (arglist && arglist[0] && !arglist[1])
9091 flags |= ME_QUOTE_ARG;
9092 if (!*line)
9094 free (line);
9095 continue;
9098 else
9100 line_error (_("%cquote-arg only useful when the macro takes a single argument"),
9101 COMMAND_PREFIX);
9105 if ((*line == COMMAND_PREFIX) &&
9106 (strncmp (line + 1, "macro ", 6) == 0))
9107 depth++;
9109 if ((*line == COMMAND_PREFIX) &&
9110 (strncmp (line + 1, "end macro", 9) == 0))
9111 depth--;
9113 if (depth)
9115 if ((body_index + strlen (line) + 3) >= body_size)
9116 body = (char *)xrealloc
9117 (body, body_size += 3 + strlen (line));
9118 strcpy (body + body_index, line);
9119 body_index += strlen (line);
9120 body[body_index++] = '\n';
9121 body[body_index] = 0;
9123 free (line);
9126 /* If it was an empty macro like
9127 @macro foo
9128 @end macro
9129 create an empty body. (Otherwise, the macro is not expanded.) */
9130 if (!body)
9132 body = (char *)malloc(1);
9133 *body = 0;
9136 /* We now have the name, the arglist, and the body. However, BODY
9137 includes the final newline which preceded the `@end macro' text.
9138 Delete it. */
9139 if (body && strlen (body))
9140 body[strlen (body) - 1] = 0;
9142 add_macro (name, arglist, body, input_filename, defining_line, flags);
9144 if (macro_expansion_output_stream && !executing_string)
9145 remember_itext (input_text, input_text_offset);
9148 void
9149 cm_unmacro ()
9151 register int i;
9152 char *line, *name;
9153 MACRO_DEF *def;
9155 if (macro_expansion_output_stream && !executing_string)
9156 me_append_before_this_command ();
9158 get_rest_of_line (&line);
9160 for (i = 0; line[i] && !whitespace (line[i]); i++);
9161 name = (char *)xmalloc (i + 1);
9162 strncpy (name, line, i);
9163 name[i] = 0;
9165 def = delete_macro (name);
9167 if (def)
9169 free (def->source_file);
9170 free (def->name);
9171 free (def->body);
9173 if (def->arglist)
9175 register int i;
9177 for (i = 0; def->arglist[i]; i++)
9178 free (def->arglist[i]);
9180 free (def->arglist);
9183 free (def);
9186 free (line);
9187 free (name);
9189 if (macro_expansion_output_stream && !executing_string)
9190 remember_itext (input_text, input_text_offset);
9193 /* How to output sections of the input file verbatim. */
9195 /* Set the value of POINTER's offset to OFFSET. */
9196 ITEXT *
9197 remember_itext (pointer, offset)
9198 char *pointer;
9199 int offset;
9201 register int i;
9202 ITEXT *itext = (ITEXT *)NULL;
9204 /* If we have no info, initialize a blank list. */
9205 if (!itext_info)
9207 itext_info = (ITEXT **)xmalloc ((itext_size = 10) * sizeof (ITEXT *));
9208 for (i = 0; i < itext_size; i++)
9209 itext_info[i] = (ITEXT *)NULL;
9212 /* If the pointer is already present in the list, then set the offset. */
9213 for (i = 0; i < itext_size; i++)
9214 if ((itext_info[i] != (ITEXT *)NULL) &&
9215 (itext_info[i]->pointer == pointer))
9217 itext = itext_info[i];
9218 itext_info[i]->offset = offset;
9219 break;
9222 if (i == itext_size)
9224 /* Find a blank slot (or create a new one), and remember the
9225 pointer and offset. */
9226 for (i = 0; i < itext_size; i++)
9227 if (itext_info[i] == (ITEXT *)NULL)
9228 break;
9230 /* If not found, then add some slots. */
9231 if (i == itext_size)
9233 register int j;
9235 itext_info = (ITEXT **)xrealloc
9236 (itext_info, (itext_size += 10) * sizeof (ITEXT *));
9238 for (j = i; j < itext_size; j++)
9239 itext_info[j] = (ITEXT *)NULL;
9242 /* Now add the pointer and the offset. */
9243 itext_info[i] = (ITEXT *)xmalloc (sizeof (ITEXT));
9244 itext_info[i]->pointer = pointer;
9245 itext_info[i]->offset = offset;
9246 itext = itext_info[i];
9248 return (itext);
9251 /* Forget the input text associated with POINTER. */
9252 void
9253 forget_itext (pointer)
9254 char *pointer;
9256 register int i;
9258 for (i = 0; i < itext_size; i++)
9259 if (itext_info[i] && (itext_info[i]->pointer == pointer))
9261 free (itext_info[i]);
9262 itext_info[i] = (ITEXT *)NULL;
9263 break;
9267 /* Append the text which appeared in input_text from the last offset to
9268 the character just before the command that we are currently executing. */
9269 void
9270 me_append_before_this_command ()
9272 register int i;
9274 for (i = input_text_offset; i && (input_text[i] != COMMAND_PREFIX); i--);
9275 maybe_write_itext (input_text, i);
9278 /* Similar to execute_string (), but only takes a single string argument,
9279 and remembers the input text location, etc. */
9280 void
9281 me_execute_string (execution_string)
9282 char *execution_string;
9284 pushfile ();
9285 input_text_offset = 0;
9286 input_text = execution_string;
9287 input_filename = xstrdup (input_filename);
9288 size_of_input_text = strlen (execution_string);
9290 remember_itext (execution_string, 0);
9292 me_executing_string++;
9293 reader_loop ();
9294 popfile ();
9295 me_executing_string--;
9298 /* Append the text which appears in input_text from the last offset to
9299 the current OFFSET. */
9300 void
9301 append_to_expansion_output (offset)
9302 int offset;
9304 register int i;
9305 ITEXT *itext = (ITEXT *)NULL;
9307 for (i = 0; i < itext_size; i++)
9308 if (itext_info[i] && itext_info[i]->pointer == input_text)
9310 itext = itext_info[i];
9311 break;
9314 if (!itext)
9315 return;
9317 if (offset > itext->offset)
9319 write_region_to_macro_output
9320 (input_text, itext->offset, offset);
9321 remember_itext (input_text, offset);
9325 /* Only write this input text iff it appears in our itext list. */
9326 void
9327 maybe_write_itext (pointer, offset)
9328 char *pointer;
9329 int offset;
9331 register int i;
9332 ITEXT *itext = (ITEXT *)NULL;
9334 for (i = 0; i < itext_size; i++)
9335 if (itext_info[i] && (itext_info[i]->pointer == pointer))
9337 itext = itext_info[i];
9338 break;
9341 if (itext && (itext->offset < offset))
9343 write_region_to_macro_output (itext->pointer, itext->offset, offset);
9344 remember_itext (pointer, offset);
9348 void
9349 write_region_to_macro_output (string, start, end)
9350 char *string;
9351 int start, end;
9353 if (macro_expansion_output_stream)
9354 fwrite (string + start, 1, end - start, macro_expansion_output_stream);
9357 #endif /* HAVE_MACROS */
9359 /* Return the length of the array in ARRAY. */
9361 array_len (array)
9362 char **array;
9364 register int i = 0;
9366 if (array)
9367 for (i = 0; array[i] != (char *)NULL; i++);
9369 return (i);
9372 void
9373 free_array (array)
9374 char **array;
9376 if (array)
9378 register int i;
9380 for (i = 0; array[i] != (char *)NULL; i++)
9381 free (array[i]);
9383 free (array);
9387 /* Function is used even when we don't have macros. Although, I have
9388 to admit, it is unlikely that you would have a use for it if you
9389 aren't using macros. */
9390 char **
9391 get_brace_args (quote_single)
9392 int quote_single;
9394 char **arglist, *word;
9395 int arglist_index, arglist_size;
9396 int character, escape_seen, start;
9397 int depth = 1;
9399 /* There is an arglist in braces here, so gather the args inside of it. */
9400 skip_whitespace_and_newlines ();
9401 input_text_offset++;
9402 arglist = (char **)NULL;
9403 arglist_index = arglist_size = 0;
9405 get_arg:
9406 skip_whitespace_and_newlines ();
9407 start = input_text_offset;
9408 escape_seen = 0;
9410 while ((character = curchar ()))
9412 if (character == '\\')
9414 input_text_offset += 2;
9415 escape_seen = 1;
9417 else if (character == '{')
9419 depth++;
9420 input_text_offset++;
9422 else if ((character == ',' && !quote_single) ||
9423 ((character == '}') && depth == 1))
9425 int len = input_text_offset - start;
9427 if (len || (character != '}'))
9429 word = (char *)xmalloc (1 + len);
9430 strncpy (word, input_text + start, len);
9431 word[len] = 0;
9433 /* Clean up escaped characters. */
9434 if (escape_seen)
9436 register int i;
9438 for (i = 0; word[i]; i++)
9439 if (word[i] == '\\')
9440 memmove (word + i, word + i + 1,
9441 1 + strlen (word + i + 1));
9444 if (arglist_index + 2 >= arglist_size)
9445 arglist = (char **)xrealloc
9446 (arglist, (arglist_size += 10) * sizeof (char *));
9448 arglist[arglist_index++] = word;
9449 arglist[arglist_index] = (char *)NULL;
9452 input_text_offset++;
9453 if (character == '}')
9454 break;
9455 else
9456 goto get_arg;
9458 else if (character == '}')
9460 depth--;
9461 input_text_offset++;
9463 else
9465 input_text_offset++;
9466 if (character == '\n') line_number++;
9469 return (arglist);
9472 /* **************************************************************** */
9473 /* */
9474 /* Looking For Include Files */
9475 /* */
9476 /* **************************************************************** */
9478 /* Given a string containing units of information separated by colons,
9479 return the next one pointed to by INDEX, or NULL if there are no more.
9480 Advance INDEX to the character after the colon. */
9481 char *
9482 extract_colon_unit (string, index)
9483 char *string;
9484 int *index;
9486 int i, start;
9488 i = *index;
9490 if (!string || (i >= strlen (string)))
9491 return ((char *)NULL);
9493 /* Each call to this routine leaves the index pointing at a colon if
9494 there is more to the path. If I is > 0, then increment past the
9495 `:'. If I is 0, then the path has a leading colon. Trailing colons
9496 are handled OK by the `else' part of the if statement; an empty
9497 string is returned in that case. */
9498 if (i && string[i] == ':')
9499 i++;
9501 start = i;
9503 while (string[i] && string[i] != ':') i++;
9505 *index = i;
9507 if (i == start)
9509 if (string[i])
9510 (*index)++;
9512 /* Return "" in the case of a trailing `:'. */
9513 return (xstrdup (""));
9515 else
9517 char *value;
9519 value = (char *)xmalloc (1 + (i - start));
9520 strncpy (value, &string[start], (i - start));
9521 value [i - start] = 0;
9523 return (value);
9527 /* Return the full pathname for FILENAME by searching along PATH.
9528 When found, return the stat () info for FILENAME in FINFO.
9529 If PATH is NULL, only the current directory is searched.
9530 If the file could not be found, return a NULL pointer. */
9531 char *
9532 get_file_info_in_path (filename, path, finfo)
9533 char *filename, *path;
9534 struct stat *finfo;
9536 char *dir;
9537 int result, index = 0;
9539 if (path == (char *)NULL)
9540 path = ".";
9542 /* Handle absolute pathnames. "./foo", "/foo", "../foo". */
9543 if (*filename == '/' ||
9544 (*filename == '.' &&
9545 (filename[1] == '/' ||
9546 (filename[1] == '.' && filename[2] == '/')))
9547 #ifdef WIN32
9548 /* Handle names that look like "d:/foo/bar" */
9549 || (isalpha (*filename) && filename [1] == ':'
9550 && (filename [2] == '/' || filename [2] == '\\'))
9551 #endif
9554 if (stat (filename, finfo) == 0)
9555 return (xstrdup (filename));
9556 else
9557 return ((char *)NULL);
9560 while ((dir = extract_colon_unit (path, &index)))
9562 char *fullpath;
9564 if (!*dir)
9566 free (dir);
9567 dir = xstrdup (".");
9570 fullpath = (char *)xmalloc (2 + strlen (dir) + strlen (filename));
9571 sprintf (fullpath, "%s/%s", dir, filename);
9572 free (dir);
9574 result = stat (fullpath, finfo);
9576 if (result == 0)
9577 return (fullpath);
9578 else
9579 free (fullpath);
9581 return NULL;