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)
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. */
28 int major_version
= 1;
29 int minor_version
= 68;
38 #endif /* !TM_IN_SYS_TIME */
42 # define alloca __builtin_alloca
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. */
58 # define VA_START(args, lastarg) va_start(args, lastarg)
61 # define VA_START(args, lastarg) va_start(args)
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;
72 /* You can change some of the behavior of Makeinfo by changing the
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. */
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
133 char *pointer
; /* Pointer to the input text. */
134 int offset
; /* Offset of the last character output. */
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 /* **************************************************************** */
153 /* Global Variables */
155 /* **************************************************************** */
157 /* Global pointer to argv[0]. */
160 /* Return nonzero if STRING is the text at input_text + input_text_offset,
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. */
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
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
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. */
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
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. */
240 /* The index in our internal command table of the currently
241 executing command. */
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
[] =
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
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. */
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
306 TAG_ENTRY
*tag_table
= (TAG_ENTRY
*) NULL
;
308 /* Values for calling handle_variable_internal (). */
314 #if defined (HAVE_MACROS)
315 #define ME_RECURSE 0x01
316 #define ME_QUOTE_ARG 0x02
318 /* Macro definitions for user-defined commands. */
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. */
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. */
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. */
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. */
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. */
374 /* Default is to notify users of bad choices. */
375 int print_warnings
= 1;
377 /* Default is to check node references. */
380 /* Nonzero means do not output "Node: Foo" for node separations. */
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
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. */
409 typedef struct brace_element
411 struct brace_element
*next
;
412 COMMAND_FUNCTION
*proc
;
414 int in_fixed_width_font
;
417 BRACE_ELEMENT
*brace_stack
= (BRACE_ELEMENT
*) NULL
;
419 extern void do_multitable ();
421 void print_version_info ();
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 ();
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 *, ...);
457 void add_word_args ();
458 void execute_string ();
459 #endif /* will not use prototypes */
461 void insert_self (), insert_space (), cm_ignore_line ();
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 ();
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 ();
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 ();
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 */
509 void cm_paragraphindent (), cm_footnotestyle ();
512 void command_name_condition (), misplaced_brace (), cm_obsolete (),
518 COMMAND_FUNCTION
*proc
;
519 int argument_in_braces
;
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
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
},
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' },
804 /* **************************************************************** */
808 /* **************************************************************** */
810 /* Number of errors encountered. */
811 int errors_printed
= 0;
813 /* Print the last error gotten from the file system. */
823 /* Print an error message, and return false. */
825 #if defined (VA_FPRINTF) && __STDC__
826 error (char *format
, ...)
828 error (format
, va_alist
)
839 VA_START (ap
, format
);
841 VA_FPRINTF (stderr
, format
, ap
);
843 fprintf (stderr
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
);
844 #endif /* not VA_FPRINTF */
850 /* Just like error (), but print the line number as well. */
852 #if defined (VA_FPRINTF) && __STDC__
853 line_error (char *format
, ...)
855 line_error (format
, va_alist
)
865 fprintf (stderr
, "%s:%d: ", input_filename
, line_number
);
867 VA_START (ap
, format
);
869 VA_FPRINTF (stderr
, format
, ap
);
871 fprintf (stderr
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
);
872 #endif /* not VA_FPRINTF */
875 fprintf (stderr
, ".\n");
879 #if defined (VA_FPRINTF) && __STDC__
880 warning (char *format
, ...)
882 warning (format
, va_alist
)
893 fprintf (stderr
, _("%s:%d: warning: "), input_filename
, line_number
);
895 VA_START (ap
, format
);
897 VA_FPRINTF (stderr
, format
, ap
);
899 fprintf (stderr
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
);
900 #endif /* not VA_FPRINTF */
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. */
914 if (max_error_level
&& (errors_printed
> max_error_level
))
916 fprintf (stderr
, _("Too many errors! Gave up.\n"));
923 /* **************************************************************** */
925 /* Main () Start of code */
927 /* **************************************************************** */
929 /* For each file mentioned in the command line, process it, turning
930 Texinfo commands into wonderfully formatted output text. */
936 extern int errors_printed
;
937 char *filename_part ();
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
, "");
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
;
966 /* User specified variable to set or clear. */
967 handle_variable_internal ((c
== 'D') ? SET
: CLEAR
, optarg
);
971 /* User specified error level. */
972 if (sscanf (optarg
, "%d", &max_error_level
) != 1)
975 _("%s: %s arg must be numeric, not `%s'.\n"),
976 "--error-limit", progname
, optarg
);
977 usage (stderr
, FATAL
);
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
);
992 error (_("Cannot specify more than one macro expansion output"));
996 /* User specified fill_column. */
997 if (sscanf (optarg
, "%d", &fill_column
) != 1)
1000 _("%s: %s arg must be numeric, not `%s'.\n"),
1001 "--fill-column", progname
, optarg
);
1007 force
++; /* Do not remove erroneous output. */
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
);
1027 /* User specified output file. */
1028 command_output_filename
= xstrdup (optarg
);
1032 /* User specified paragraph indent (paragraph_start_index). */
1033 if (set_paragraph_indent (optarg
) < 0)
1036 _("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"),
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
, ":.");
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
);
1064 /* User specified reference warning limit. */
1065 if (sscanf (optarg
, "%d", &reference_warning_limit
) != 1)
1068 _("%s: %s arg must be numeric, not `%s'.\n"),
1069 "--reference-limit", progname
, optarg
);
1075 /* User specified footnote style. */
1076 if (set_footnote_style (optarg
) < 0)
1079 _("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"),
1083 footnote_style_preset
= 1;
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"),
1105 /* Check to see if input is a file. If so, process that. */
1106 if (!isatty (fileno (stdin
)))
1107 reading_from_stdin
= 1;
1110 fprintf (stderr
, _("%s: missing file argument.\n"), progname
);
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. */
1123 /* If the user has not specified an output file, use stdout. */
1124 if (!command_output_filename
)
1125 command_output_filename
= xstrdup ("-");
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
++]);
1139 convert_from_stream (stdin
, "stdin");
1147 /* Display the version info of this invocation of Makeinfo. */
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. */
1162 if (exit_value
!= 0)
1163 fprintf (stderr
, _("Try `%s --help' for more information.\n"), progname
);
1165 printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n\
1167 Translate Texinfo source documentation to a format suitable for reading\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
);
1203 /* Manipulating Lists */
1205 typedef struct generic_list
{
1206 struct generic_list
*next
;
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. */
1214 register GENERIC_LIST
*list
;
1216 register GENERIC_LIST
*next
;
1217 register GENERIC_LIST
*prev
= (GENERIC_LIST
*) NULL
;
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. */
1234 find_and_load (filename
)
1237 struct stat fileinfo
;
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
);
1249 filename
= fullpath
;
1250 file_size
= (long) fileinfo
.st_size
;
1252 file
= open (filename
, O_RDONLY
);
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)
1265 while ((n
= read (file
, result
+ count
, file_size
)) > 0)
1267 while ((n
= read (file
, result
+ count
, 1)) > 0)
1271 #else /* !VMS && !WIN32 */
1273 if (read (file
, result
, file_size
) != file_size
)
1274 #endif /* !VMS && !WIN32 */
1286 return ((char *) NULL
);
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;
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;
1306 /* Save the state of the current input file. */
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. */
1326 FSTACK
*tos
= filestack
;
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
)
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
;
1354 /* Go back to the (now) current node. */
1355 pop_node_filename ();
1358 /* Flush all open files on the file stack. */
1364 char *fname
= input_filename
;
1365 char *text
= input_text
;
1372 int node_filename_stack_index
= 0;
1373 int node_filename_stack_size
= 0;
1374 char **node_filename_stack
= (char **)NULL
;
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
++;
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. */
1397 filename_part (filename
)
1402 basename
= strrchr (filename
, '/');
1404 basename
= filename
;
1408 basename
= xstrdup (basename
);
1409 #if defined (REMOVE_OUTPUT_EXTENSIONS)
1411 /* See if there is an extension to remove. If so, remove it. */
1415 temp
= strrchr (basename
, '.');
1419 #endif /* REMOVE_OUTPUT_EXTENSIONS */
1423 /* Return the pathname part of filename. This can be NULL. */
1425 pathname_part (filename
)
1428 char *expand_filename ();
1429 char *result
= (char *) NULL
;
1432 filename
= expand_filename (filename
, "");
1434 i
= strlen (filename
) - 1;
1436 while (i
&& filename
[i
] != '/')
1438 if (filename
[i
] == '/')
1443 result
= (char *)xmalloc (1 + i
);
1444 strncpy (result
, filename
, i
);
1452 filename_non_directory (name
)
1457 for (i
= strlen (name
) - 1; i
; i
--)
1459 return (xstrdup (name
+ i
+ 1));
1461 return (xstrdup (name
));
1464 /* Return the expansion of FILENAME. */
1466 expand_filename (filename
, input_name
)
1467 char *filename
, *input_name
;
1470 char *full_pathname ();
1473 filename
= full_pathname (filename
);
1476 filename
= filename_non_directory (input_name
);
1481 filename
= xstrdup ("noname.texi");
1484 for (i
= strlen (filename
) - 1; i
; i
--)
1485 if (filename
[i
] == '.')
1489 i
= strlen (filename
);
1491 if (i
+ 6 > (strlen (filename
)))
1492 filename
= (char *)xrealloc (filename
, i
+ 6);
1493 strcpy (filename
+ i
, ".info");
1497 if (filename
[0] == '.' || filename
[0] == '/')
1500 if (filename
[0] != '/' && input_name
[0] == '/')
1502 /* Make it so that relative names work. */
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
)
1513 if (result
[i
] == '/')
1516 strcpy (&result
[i
], filename
);
1523 /* Return the full path to FILENAME. */
1525 full_pathname (filename
)
1528 int initial_character
;
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
!= '~')
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
);
1557 strcat (localdir
, "/");
1558 strcat (localdir
, filename
);
1559 result
= xstrdup (localdir
);
1565 if (filename
[1] == '/')
1567 /* Return the concatenation of the environment variable HOME
1568 and the rest of the string. */
1571 temp_home
= (char *) getenv ("HOME");
1572 result
= (char *)xmalloc (strlen (&filename
[1])
1574 + temp_home
? strlen (temp_home
)
1579 strcpy (result
, temp_home
);
1581 strcat (result
, &filename
[1]);
1585 struct passwd
*user_entry
;
1587 char *username
= (char *)xmalloc (257);
1589 for (i
= 1; (c
= filename
[i
]); i
++)
1594 username
[i
- 1] = c
;
1597 username
[i
- 1] = 0;
1599 user_entry
= getpwnam (username
);
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 */
1615 output_name_from_input_name (name
)
1618 return (expand_filename ((char *)NULL
, name
));
1621 /* **************************************************************** */
1623 /* Hacking Tokens and Strings */
1625 /* **************************************************************** */
1627 /* Return the next token as a string pointer. We cons the string. */
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')
1644 result
= xstrdup (" ");
1645 *result
= character
;
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
);
1659 /* Return nonzero if CHARACTER is self-delimiting. */
1661 self_delimiting (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. */
1671 canon_white (string
)
1674 int len
= strlen (string
);
1680 for (x
= 0; x
< len
; x
++)
1682 if (!cr_or_whitespace (string
[x
]))
1684 strcpy (string
, string
+ x
);
1688 len
= strlen (string
);
1691 while (len
> -1 && cr_or_whitespace (string
[len
]))
1693 string
[len
+ 1] = 0;
1696 /* Bash STRING, replacing all whitespace with just one space. */
1698 fix_whitespace (string
)
1701 char *temp
= (char *)xmalloc (strlen (string
) + 1);
1702 int string_index
= 0;
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
== ' ' ||
1721 temp
[temp_index
] = 0;
1722 strcpy (string
, temp
);
1726 /* Discard text until the desired string is found. The string is
1727 included in the discarded text. */
1729 discard_until (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. */
1739 if (input_text
[from
++] == '\n')
1744 input_text_offset
= size_of_input_text
- strlen (string
);
1746 if (strcmp (string
, "\n") != 0)
1748 line_error (_("Expected `%s'"), string
);
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
);
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);
1778 if (input_text
[x
++] == '\n')
1781 *string
= (char *)xmalloc (len
+ 1);
1783 memcpy (*string
, &input_text
[current_point
], len
);
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
;
1795 /* Read characters from the file until we are at MATCH or end of line.
1796 Place the characters read into STRING. */
1798 get_until_in_line (expand
, match
, string
)
1800 char *match
, **string
;
1802 int real_bottom
= size_of_input_text
;
1803 int limit
= search_forward ("\n", input_text_offset
);
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:
1811 Together: \p\ & \q\.
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
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
)
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
);
1839 xp
= expansion (str
, 0);
1840 xp_len
= strlen (xp
);
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);
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
;
1865 get_rest_of_line (string
)
1868 get_until ("\n", string
);
1869 canon_white (*string
);
1871 if (curchar () == '\n') /* as opposed to the end of the file... */
1874 input_text_offset
++;
1878 /* Backup the input pointer to the previous character, keeping track
1879 of the current line number. */
1881 backup_input_pointer ()
1883 if (input_text_offset
)
1885 input_text_offset
--;
1886 if (curchar () == '\n')
1891 /* Read characters from the file until we are at MATCH or closing brace.
1892 Place the characters read into STRING. */
1894 get_until_in_braces (match
, string
)
1895 char *match
, **string
;
1899 int match_len
= strlen (match
);
1901 for (i
= input_text_offset
; i
< size_of_input_text
; i
++)
1903 if (input_text
[i
] == '{')
1905 else if (input_text
[i
] == '}')
1907 else if (input_text
[i
] == '\n')
1911 (brace
== 0 && strncmp (input_text
+ i
, match
, match_len
) == 0))
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
;
1923 /* **************************************************************** */
1925 /* Converting the File */
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
[] = {
1940 initialize_conversion ()
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
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. */
1961 convert_from_stream (stream
, 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
))
1977 if (buffer_offset
+ (READ_BUFFER_GROWTH
+ 1) >= buffer_size
)
1979 xrealloc (buffer
, (buffer_size
+= READ_BUFFER_GROWTH
));
1981 count
= fread (buffer
+ buffer_offset
, 1, READ_BUFFER_GROWTH
, stream
);
1989 buffer_offset
+= count
;
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;
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
);
2011 convert_from_file (name
)
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
2022 for (i
= 0; suffixes
[i
]; i
++)
2024 strcpy (filename
, name
);
2025 strcat (filename
, suffixes
[i
]);
2027 if (find_and_load (filename
))
2030 if (!suffixes
[i
][0] && strrchr (filename
, '.'))
2032 fs_error (filename
);
2045 input_filename
= filename
;
2047 convert_from_loaded_file (name
);
2051 convert_from_loaded_file (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)
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')))
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
);
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')
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
;
2105 command_output_filename
= output_name_from_input_name (name
);
2106 #endif /* !REQUIRE_SETFILENAME */
2110 input_text_offset
+= strlen (setfilename_search
);
2112 if (!command_output_filename
)
2113 get_until ("\n", &output_filename
);
2116 if (input_text_offset
!= -1)
2117 discard_until ("\n");
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"),
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. */
2142 if (!real_output_filename
)
2143 real_output_filename
= expand_filename (output_filename
, name
);
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
);
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
);
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
2174 while (temp
!= input_text_offset
)
2175 if (input_text
[temp
++] == '\n')
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
);
2190 discard_insertions (0);
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 */
2212 output_pending_notes ();
2213 free_pending_notes ();
2214 if (tag_table
!= NULL
)
2216 tag_table
= (TAG_ENTRY
*) reverse_list (tag_table
);
2221 if (output_stream
!= stdout
)
2222 fclose (output_stream
);
2224 /* If validating, then validate the entire file right now. */
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
);
2244 free_and_clear (pointer
)
2250 *pointer
= (char *) NULL
;
2254 /* Initialize some state. */
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 */
2269 non_top_node_seen
= 0;
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;
2280 paragraph_is_open
= 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. */
2298 if (input_text_offset
>= size_of_input_text
)
2301 character
= curchar ();
2303 if (!in_fixed_width_font
&&
2304 (character
== '\'' || character
== '`') &&
2305 input_text
[input_text_offset
+ 1] == character
)
2307 input_text_offset
++;
2311 if (character
== '-')
2314 if (dash_count
== 2 && !in_fixed_width_font
)
2316 input_text_offset
++;
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
]))
2334 if (i
== size_of_input_text
|| input_text
[i
] == '\n')
2336 if (i
== size_of_input_text
)
2339 input_text_offset
= i
;
2340 character
= curchar ();
2344 if (character
== '\n')
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. */
2358 tem
= glean_node_from_menu (1);
2364 case COMMAND_PREFIX
:
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
2379 input_text_offset++;
2384 pop_and_call_brace ();
2385 input_text_offset
++;
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
2403 get_command_entry (string
)
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. */
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. */
2439 def
= find_macro (command
);
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
))
2448 execute_macro (def
);
2450 if (!(def
->flags
& ME_RECURSE
))
2456 #endif /* HAVE_MACROS */
2458 entry
= get_command_entry (command
);
2459 if (entry
== (COMMAND
*)-1)
2461 line_error (_("Unknown command `%s'"), command
);
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. */
2473 find_proc_name (proc
)
2474 COMMAND_FUNCTION
*proc
;
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!");
2487 brace_stack
= (BRACE_ELEMENT
*) NULL
;
2491 remember_brace (proc
)
2492 COMMAND_FUNCTION
*proc
;
2494 if (curchar () != '{')
2495 line_error (_("%c%s expected `{...}'"), COMMAND_PREFIX
, command
);
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. */
2504 remember_brace_1 (proc
, position
)
2505 COMMAND_FUNCTION
*proc
;
2508 BRACE_ELEMENT
*new = (BRACE_ELEMENT
*) xmalloc (sizeof (BRACE_ELEMENT
));
2509 new->next
= brace_stack
;
2511 new->pos
= position
;
2512 new->line
= line_number
;
2513 new->in_fixed_width_font
= in_fixed_width_font
;
2517 /* Pop the top of the brace stack, and call the associated function
2518 with the args END and POS. */
2520 pop_and_call_brace ()
2522 BRACE_ELEMENT
*temp
;
2523 COMMAND_FUNCTION
*proc
;
2526 if (brace_stack
== (BRACE_ELEMENT
*) NULL
)
2528 line_error (_("Unmatched }"));
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
;
2539 (*proc
) (END
, pos
, output_paragraph_offset
);
2542 /* Shift all of the markers in `brace_stack' by AMOUNT. */
2544 adjust_braces_following (here
, amount
)
2547 register BRACE_ELEMENT
*stack
= brace_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. */
2569 if (brace_stack
->proc
!= misplaced_brace
)
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 ();
2582 BRACE_ELEMENT
*temp
;
2583 temp
= brace_stack
->next
;
2591 get_char_len (character
)
2594 /* Return the printed length of the character. */
2600 len
= (output_column
+ 8) & 0xf7;
2601 if (len
> fill_column
)
2602 len
= fill_column
- output_column
;
2604 len
= len
- output_column
;
2608 len
= fill_column
- output_column
;
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
< ' ')
2625 #if defined (VA_FPRINTF) && __STDC__
2626 add_word_args (char *format
, ...)
2628 add_word_args (format
, va_alist
)
2638 VA_START (ap
, format
);
2640 VA_SPRINTF (buffer
, format
, ap
);
2642 sprintf (buffer
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
);
2643 #endif /* not VA_SPRINTF */
2648 /* Add STRING to output_paragraph. */
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. */
2678 add_char (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
))
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;
2707 if (!filling_enabled
)
2711 if (force_flush_right
)
2714 /* Hack to force single blank lines out in this mode. */
2720 if (!no_indent
&& paragraph_is_open
)
2721 indent (output_column
= current_indent
);
2724 else /* CHARACTER is newline, and filling is enabled. */
2726 if (end_of_sentence_p ())
2730 last_inserted_character
= character
;
2734 if (last_char_was_newline
)
2741 last_char_was_newline
= 1;
2749 int len
= get_char_len (character
);
2750 int suppress_insert
= 0;
2752 if ((character
== ' ') && (last_char_was_newline
))
2754 if (!paragraph_is_open
)
2761 if (!paragraph_is_open
)
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
);
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
2782 if (output_paragraph
[temp
] == ' ')
2784 /* Remove trailing whitespace from output. */
2785 while (temp
&& whitespace (output_paragraph
[temp
- 1]))
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
2799 if (t1
== output_paragraph_offset
)
2801 if (whitespace (character
))
2802 suppress_insert
= 1;
2805 if (!whitespace (output_paragraph
[t1
]))
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
)
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
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
;
2853 while (temp
< output_paragraph_offset
)
2855 get_char_len (output_paragraph
[temp
++]);
2856 output_column
+= len
;
2863 if (!suppress_insert
)
2866 last_inserted_character
= character
;
2868 last_char_was_newline
= 0;
2869 line_already_broken
= 0;
2874 /* Insert CHARACTER into `output_paragraph'. */
2879 output_paragraph
[output_paragraph_offset
++] = character
;
2880 if (output_paragraph_offset
== paragraph_buffer_len
)
2883 xrealloc (output_paragraph
, (paragraph_buffer_len
+= 100));
2887 /* Insert the null-terminated string STRING into `output_paragraph'. */
2889 insert_string (string
)
2897 /* Sentences might have these characters after the period (or whatever). */
2898 #define post_sentence(c) ((c) == ')' || (c) == '\'' || (c) == '"' \
2901 /* Return true if at an end-of-sentence character, possibly followed by
2902 post-sentence punctuation to ignore. */
2904 end_of_sentence_p ()
2906 int loc
= output_paragraph_offset
- 1;
2907 while (loc
> 0 && post_sentence (output_paragraph
[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. */
2917 kill_self_indent (count
)
2920 /* Handle infinite case first. */
2924 while (output_paragraph_offset
)
2926 if (whitespace (output_paragraph
[output_paragraph_offset
- 1]))
2927 output_paragraph_offset
--;
2934 while (output_paragraph_offset
&& count
--)
2935 if (whitespace (output_paragraph
[output_paragraph_offset
- 1]))
2936 output_paragraph_offset
--;
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. */
2947 inhibit_output_flushing ()
2952 /* Allow calls to flush_output () to write the paragraph data. */
2954 uninhibit_output_flushing ()
2964 if (!output_paragraph_offset
|| flushing_ignored
)
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
]);
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. */
2995 close_single_paragraph ()
2997 close_paragraph_with_lines (0);
3000 /* Close a paragraph after an insertion has ended. */
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). */
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 ();
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;
3037 close_paragraph_with_lines (lines
)
3040 int old_spacing
= paragraph_spacing
;
3041 paragraph_spacing
= lines
;
3043 paragraph_spacing
= old_spacing
;
3046 /* Close the currently open paragraph. */
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';
3075 /* All trailing whitespace is ignored. */
3076 output_paragraph_offset
= ++tindex
;
3078 /* Break the line if that is appropriate. */
3079 if (paragraph_spacing
>= 0)
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
++)
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 ();
3095 paragraph_is_open
= 0;
3099 ignore_blank_line ();
3102 /* Make the last line just read look as if it were only a newline. */
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. */
3112 do_flush_right_indentation ()
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
)
3127 if (fill_column
>= paragraph_buffer_len
)
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
);
3141 output_paragraph_offset
= fill_column
;
3146 /* Begin a new paragraph. */
3150 /* First close existing one. */
3151 if (paragraph_is_open
)
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. */
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
;
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
;
3190 must_start_paragraph
= 0;
3193 /* Insert the indentation specified by 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. */
3204 if (elt
->pos
>= output_paragraph_offset
)
3209 while (--amount
>= 0)
3213 /* Search forward for STRING in input_text.
3214 FROM says where to start. */
3216 search_forward (string
, from
)
3220 int len
= strlen (string
);
3222 while (from
< size_of_input_text
)
3224 if (strncmp (input_text
+ from
, string
, len
) == 0)
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
;
3249 ch1
= coerce_to_upper (ch1
);
3250 ch2
= coerce_to_upper (ch2
);
3256 #endif /* !HAVE_STRCASECMP */
3259 init_insertion_stack ()
3261 insertion_stack
= (INSERTION_ELT
*) NULL
;
3264 /* Return the type of the current insertion. */
3266 current_insertion_type ()
3268 if (!insertion_level
)
3271 return (insertion_stack
->insertion
);
3274 /* Return a pointer to the string which is the function to wrap around
3277 current_item_function ()
3279 register int level
, done
;
3280 register INSERTION_ELT
*elt
;
3282 level
= insertion_level
;
3283 elt
= insertion_stack
;
3286 /* Skip down through the stack until we find a non-conditional insertion. */
3287 while (!done
&& (elt
!= NULL
))
3289 switch (elt
->insertion
)
3307 return ((char *) NULL
);
3309 return (elt
->item_function
);
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. */
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;
3342 /* Pop the value on top of the insertion stack into the
3343 global variables. */
3347 INSERTION_ELT
*temp
= insertion_stack
;
3349 if (temp
== (INSERTION_ELT
*) NULL
)
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
;
3363 /* Return a pointer to the print name of this
3366 insertion_type_pname (type
)
3367 enum insertion_type type
;
3369 if ((int) type
< (int) bad_type
)
3370 return (insertion_type_names
[(int) type
]);
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. */
3378 find_type_from_name (name
)
3382 while (index
< (int) bad_type
)
3384 if (strcmp (name
, insertion_type_names
[index
]) == 0)
3385 return (enum insertion_type
) index
;
3392 defun_insertion (type
)
3393 enum insertion_type type
;
3399 || (type
== defspec
)
3403 || (type
== deftypefn
)
3404 || (type
== deftypefun
)
3405 || (type
== deftypevr
)
3406 || (type
== deftypevar
)
3408 || (type
== defivar
)
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
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
;
3433 start_enumerating (at
, type
)
3436 if ((enumstack_offset
+ 1) == max_stack_depth
)
3438 line_error (_("Enumeration stack overflow"));
3441 enumstack
[enumstack_offset
].enumtype
= current_enumtype
;
3442 enumstack
[enumstack_offset
].enumval
= current_enumval
;
3444 current_enumval
= at
;
3445 current_enumtype
= type
;
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. */
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
);
3475 sprintf (temp
, "%d. ", current_enumval
);
3477 indent (output_column
+= (current_indent
- strlen (temp
)));
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. */
3486 begin_insertion (type
)
3487 enum insertion_type type
;
3491 if (defun_insertion (type
))
3493 push_insertion (type
, xstrdup (""));
3497 push_insertion (type
, get_item_function ());
3505 filling_enabled
= no_indent
= 0;
3506 inhibit_paragraph_indentation
= 1;
3509 add_word (_("* Menu:\n"));
3521 filling_enabled
= no_indent
= 0;
3522 inhibit_paragraph_indentation
= 1;
3531 close_single_paragraph ();
3532 filling_enabled
= no_indent
= 0;
3533 inhibit_paragraph_indentation
= 1;
3534 insert_string ("START-INFO-DIR-ENTRY\n");
3537 /* I think @quotation is meant to do filling.
3538 If you don't want filling, then use @display. */
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
;
3552 /* Just like @example, but no indentation. */
3554 close_single_paragraph ();
3555 inhibit_paragraph_indentation
= 1;
3556 in_fixed_width_font
++;
3557 filling_enabled
= 0;
3558 last_char_was_newline
= 0;
3560 current_indent
+= default_indentation_increment
;
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;
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
);
3599 close_single_paragraph ();
3601 #if defined (INDENT_PARAGRAPHS_IN_TABLE)
3602 inhibit_paragraph_indentation
= 0;
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
);
3613 start_enumerating (*enumeration_arg
, ENUM_ALPHA
);
3616 /* Does nothing special in makeinfo. */
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 ();
3624 /* Insertions that are no-ops in info, but do something in TeX. */
3652 inhibit_paragraph_indentation
= 1;
3653 filling_enabled
= indented_fill
= 1;
3654 current_indent
+= default_indentation_increment
;
3659 close_single_paragraph ();
3660 inhibit_paragraph_indentation
= 1;
3661 filling_enabled
= indented_fill
= no_indent
= 0;
3665 close_single_paragraph ();
3666 filling_enabled
= indented_fill
= no_indent
= 0;
3667 inhibit_paragraph_indentation
= 1;
3668 force_flush_right
++;
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. */
3681 end_insertion (type
)
3682 enum insertion_type type
;
3684 enum insertion_type temp_type
;
3686 if (!insertion_level
)
3689 temp_type
= current_insertion_type ();
3691 if (type
== bad_type
)
3694 if (type
!= temp_type
)
3697 (_("`%cend' expected `%s', but saw `%s'"), COMMAND_PREFIX
,
3698 insertion_type_pname (temp_type
), insertion_type_pname (type
));
3706 /* Insertions which have no effect on paragraph formatting. */
3715 insert_string ("END-INFO-DIR-ENTRY\n\n");
3716 close_insertion_paragraph ();
3720 in_detailmenu
--; /* No longer hacking menus. */
3724 close_insertion_paragraph ();
3729 in_menu
--; /* No longer hacking menus. */
3731 close_insertion_paragraph ();
3739 stop_enumerating ();
3740 close_insertion_paragraph ();
3741 current_indent
-= default_indentation_increment
;
3747 close_insertion_paragraph ();
3757 /* @format is the only fixed_width insertion without a change
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 ();
3771 current_indent
-= default_indentation_increment
;
3775 force_flush_right
--;
3776 close_insertion_paragraph ();
3779 /* Handle the @defun style insertions with a default clause. */
3781 current_indent
-= default_indentation_increment
;
3782 close_insertion_paragraph ();
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. */
3793 discard_insertions (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
))
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
;
3815 line_number
= real_line_number
;
3818 /* The Texinfo commands. */
3820 /* Commands which insert their own names. */
3837 /* Force a line break in the output. */
3841 close_single_paragraph ();
3845 /* Insert ellipsis. */
3854 /* Insert ellipsis for sentence end. */
3888 /* Copyright symbol. */
3897 /* Accent commands that take explicit arguments. */
3904 if (strcmp (command
, "dotaccent") == 0) /* overdot */
3906 else if (strcmp (command
, "H") == 0) /* Hungarian umlaut */
3908 else if (strcmp (command
, "ringaccent") == 0)
3910 else if (strcmp (command
, "tieaccent") == 0)
3912 else if (strcmp (command
, "u") == 0) /* breve */
3914 else if (strcmp (command
, "v") == 0) /* hacek/check */
3917 else if (arg
== END
)
3919 if (strcmp (command
, "ubaraccent") == 0) /* underbar */
3921 else if (strcmp (command
, "udotaccent") == 0) /* underdot */
3923 else if (strcmp (command
, ",") == 0) /* cedilla */
3928 /* Non-English letters/characters that don't insert themselves. */
3930 cm_special_char (arg
)
3934 if ((*command
== 'L' || *command
== 'l'
3935 || *command
== 'O' || *command
== 'o')
3938 /* Lslash lslash Oslash oslash */
3939 add_char (*command
);
3942 else if (strcmp (command
, "exclamdown") == 0)
3944 else if (strcmp (command
, "pounds") == 0)
3946 else if (strcmp (command
, "questiondown") == 0)
3949 fprintf (stderr
, _("How did @%s end up in cm_special_char?\n"), command
);
3953 /* Dotless i or j. */
3955 cm_dotless (arg
, start
, end
)
3956 int arg
, start
, 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. */
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") };
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);
3995 extern int printing_index
;
3999 in_fixed_width_font
++;
4001 if (!printing_index
)
4006 if (!printing_index
)
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
)
4025 add_char (arg
== START
? '<' : '>');
4028 /* Convert the character at position into a true control character. */
4030 cm_ctrl (arg
, start
, end
)
4031 int arg
, start
, end
;
4033 /* Should we allow multiple character arguments? I think yes. */
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
);
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. */
4055 not_fixed_width (arg
)
4059 in_fixed_width_font
= 0;
4062 /* Small caps and @var in makeinfo just uppercase the text. */
4064 cm_var_sc (arg
, start_pos
, end_pos
)
4065 int arg
, start_pos
, end_pos
;
4067 not_fixed_width (arg
);
4071 while (start_pos
< end_pos
)
4073 output_paragraph
[start_pos
] =
4074 coerce_to_upper (output_paragraph
[start_pos
]);
4081 cm_dfn (arg
, position
)
4095 cm_strong (arg
, position
)
4102 cm_cite (arg
, position
)
4111 /* No highlighting, but argument switches fonts. */
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. */
4125 /* No-op that eats its argument on same line. */
4127 cm_no_op_line_arg ()
4130 get_rest_of_line (&temp
);
4134 /* Prevent the argument from being split across two lines. */
4136 cm_w (arg
, start
, end
)
4137 int arg
, start
, end
;
4140 non_splitting_words
++;
4142 non_splitting_words
--;
4146 /* Explain that this command is obsolete, thus the user shouldn't
4147 do anything with it. */
4149 cm_obsolete (arg
, start
, end
)
4150 int arg
, start
, end
;
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. */
4160 insert_and_underscore (with_char
)
4163 register int i
, len
;
4164 int old_no_indent
, starting_pos
, ending_pos
;
4168 filling_enabled
= indented_fill
= 0;
4169 old_no_indent
= no_indent
;
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
);
4190 #endif /* HAVE_MACROS */
4191 execute_string ("%s\n", temp
);
4193 ending_pos
= output_position
+ output_paragraph_offset
;
4196 len
= (ending_pos
- starting_pos
) - 1;
4197 for (i
= 0; i
< len
; i
++)
4198 add_char (with_char
);
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
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 },
4222 { "subsubsection", 5 },
4223 { "subsection", 4 },
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. */
4238 discard_until ("\n");
4239 section_alist_offset
--;
4242 /* Shift the meaning of @chapter to @section. */
4246 discard_until ("\n");
4247 section_alist_offset
++;
4250 /* Return an integer which identifies the type section present in TEXT. */
4258 find_section_command
:
4259 for (j
= 0; text
[j
] && cr_or_whitespace (text
[j
]); j
++);
4260 if (text
[j
] != COMMAND_PREFIX
)
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. */
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)
4286 return_val
= (section_alist
[i
].level
+ section_alist_offset
);
4290 else if (return_val
> 5)
4292 return (return_val
);
4298 /* Set the level of @top to LEVEL. Return the old level of @top. */
4300 set_top_section_level (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
;
4315 /* Treat this just like @unnumbered. The only difference is
4316 in node defaulting. */
4320 /* It is an error to have more than one @top. */
4323 TAG_ENTRY
*tag
= tag_table
;
4325 line_error (_("Node with %ctop as a section already exists"),
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
;
4342 tag
= tag
->next_ent
;
4349 /* It is an error to use @top before you have used @node. */
4354 get_rest_of_line (&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
);
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)
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
= "*=-.";
4404 sectioning_underscore (command
)
4411 temp
= (char *)xmalloc (2 + strlen (command
));
4412 temp
[0] = COMMAND_PREFIX
;
4413 strcpy (&temp
[1], command
);
4414 level
= what_section (temp
);
4421 character
= scoring_characters
[level
];
4423 insert_and_underscore (character
);
4426 /* The command still works, but prints a warning message in addition. */
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. */
4440 sectioning_underscore ("chapter");
4443 /* The remainder of the text on this line is a section heading. */
4447 sectioning_underscore ("section");
4450 /* The remainder of the text on this line is a subsection heading. */
4454 sectioning_underscore ("subsection");
4457 /* The remainder of the text on this line is a subsubsection heading. */
4461 sectioning_underscore ("subsubsection");
4464 /* The remainder of the text on this line is an unnumbered heading. */
4471 /* The remainder of the text on this line is an unnumbered section heading. */
4478 /* The remainder of the text on this line is an unnumbered
4479 subsection heading. */
4481 cm_unnumberedsubsec ()
4486 /* The remainder of the text on this line is an unnumbered
4487 subsubsection heading. */
4489 cm_unnumberedsubsubsec ()
4491 cm_subsubsection ();
4494 /* The remainder of the text on this line is an appendix heading. */
4501 /* The remainder of the text on this line is an appendix section heading. */
4508 /* The remainder of the text on this line is an appendix subsection heading. */
4510 cm_appendixsubsec ()
4515 /* The remainder of the text on this line is an appendix
4516 subsubsection heading. */
4518 cm_appendixsubsubsec ()
4520 cm_subsubsection ();
4523 /* Compatibility functions substitute for chapter, section, etc. */
4551 cm_subsubsection ();
4554 /* **************************************************************** */
4556 /* Adding nodes, and making tags */
4558 /* **************************************************************** */
4560 /* Start a new tag table. */
4564 while (tag_table
!= (TAG_ENTRY
*) NULL
)
4566 TAG_ENTRY
*temp
= tag_table
;
4571 tag_table
= tag_table
->next_ent
;
4579 write_tag_table_internal (0); /* Not indirect. */
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. */
4591 write_tag_table_internal (indirect_p
)
4594 TAG_ENTRY
*node
= tag_table
;
4595 int old_indent
= no_indent
;
4598 filling_enabled
= 0;
4599 must_start_paragraph
= 0;
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");
4619 no_indent
= old_indent
;
4623 get_node_token (expand
)
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
);
4641 /* Convert "top" and friends into "Top". */
4643 normalize_node_name (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. */
4656 TAG_ENTRY
*tag
= tag_table
;
4658 while (tag
!= (TAG_ENTRY
*) NULL
)
4660 if (strcmp (tag
->node
, name
) == 0)
4662 tag
= tag
->next_ent
;
4664 return ((TAG_ENTRY
*) NULL
);
4667 /* Remember NODE and associates. */
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. */
4676 register TAG_ENTRY
*tag
= find_node (node
);
4680 _("Node `%s' multiply defined (line %d is first definition at)"),
4681 node
, tag
->line_no
);
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
));
4696 new->position
= position
;
4697 new->line_no
= line_no
;
4698 new->filename
= node_filename
;
4699 new->touched
= 0; /* not yet referenced. */
4702 new->flags
|= NO_WARN
;
4703 new->next_ent
= tag_table
;
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. */
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)
4724 /* Get rid of unmatched brace arguments from previous commands. */
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
)
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);
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 */
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
);
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. */
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";
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
;
4802 (_("Node `%s' requires a sectioning command (e.g. %c%s)"),
4803 node
, COMMAND_PREFIX
, polite_section_name
);
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)");
4829 orig_offset
= input_text_offset
;
4831 search_forward (node_search_string
, orig_offset
);
4834 orig_size
= size_of_input_text
;
4837 search_forward (menu_search_string
, orig_offset
);
4839 if (input_text_offset
> -1)
4841 char *nodename_from_menu
= (char *)NULL
;
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
;
4856 /* We got here, so it hasn't been found yet. Try
4857 the next file on the filestack if there is one. */
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
;
4868 /* No more input files to check. */
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. */
4886 level
= set_top_section_level (this_section
- 1);
4887 non_top_node_seen
= 1;
4891 if (ref
->section
== level
)
4892 ref
->section
= this_section
- 1;
4896 ref
= node_references
;
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
;
4908 up
= xstrdup (containing_node
);
4911 last_ref
->type
== menu_reference
&&
4912 (strcmp (last_ref
->containing_node
,
4913 containing_node
) == 0))
4916 next
= xstrdup (last_ref
->node
);
4919 while ((ref
->section
== this_section
- 1) &&
4921 (ref
->next
->type
!= menu_reference
))
4924 if (ref
->next
&& ref
->type
== menu_reference
&&
4925 (strcmp (ref
->next
->containing_node
,
4926 containing_node
) == 0))
4929 prev
= xstrdup (ref
->next
->node
);
4931 else if (!ref
->next
&&
4932 strcasecmp (ref
->containing_node
, "Top") == 0)
4935 prev
= xstrdup (ref
->containing_node
);
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
)
4950 int op_orig
= output_paragraph_offset
;
4952 temp
= (char *)xmalloc (3 + strlen (next
));
4953 sprintf (temp
, ", %s", next
);
4954 me_execute_string (temp
);
4957 temp
= (char *)xmalloc (3 + strlen (prev
));
4958 sprintf (temp
, ", %s", prev
);
4959 me_execute_string (temp
);
4962 temp
= (char *)xmalloc (4 + strlen (up
));
4963 sprintf (temp
, ", %s", up
);
4964 me_execute_string (temp
);
4967 output_paragraph_offset
= op_orig
;
4969 #endif /* HAVE_MACROS */
4973 #if defined (HAVE_MACROS)
4974 if (macro_expansion_output_stream
)
4975 me_inhibit_expansion
++;
4976 #endif /* HAVE_MACROS */
4980 execute_string (", Next: %s", next
);
4981 filling_enabled
= indented_fill
= 0;
4986 execute_string (", Prev: %s", prev
);
4987 filling_enabled
= indented_fill
= 0;
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 */
5006 line_error ("No node name specified for `%c%s' command",
5007 COMMAND_PREFIX
, command
);
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,
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. */
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
;
5063 /* If this node has a Next, then make sure that the Next exists. */
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
);
5075 if (temp_tag
->flags
& NO_WARN
)
5077 /* Do nothing if we aren't supposed to issue warnings
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"),
5087 line_number
= temp_tag
->line_no
;
5088 input_filename
= temp_tag
->filename
;
5090 (_("This node (`%s') is the one with the bad `Prev'"),
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");
5108 tags
->flags
|= PREV_ERROR
;
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
))
5126 if (!temp_tag
->next
||
5127 (strcmp (temp_tag
->next
, tags
->node
) != 0))
5130 (_("Node `%s's Prev field not pointed back to"),
5132 line_number
= temp_tag
->line_no
;
5133 input_filename
= temp_tag
->filename
;
5134 line_error (_("This node (`%s') has the bad Next"),
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
);
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
;
5163 if (!(nref
= find_node_reference (tags
->node
, list
)))
5166 if (strcmp (nref
->containing_node
, tags
->up
) == 0)
5168 if (nref
->type
!= menu_reference
)
5181 temp_tag
= find_node (tags
->up
);
5182 line_number
= temp_tag
->line_no
;
5183 input_filename
= temp_tag
->filename
;
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. */
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
;
5210 /* Special hack. If the node in question appears to have
5211 been referenced more than REFERENCE_WARNING_LIMIT times,
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
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
)
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
== '(')
5250 /* Otherwise, the tag must exist. */
5251 result
= find_node (tag
);
5256 line_error (_("%s reference to nonexistent node `%s'"), label
, tag
);
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. */
5269 split_file (filename
, size
)
5273 char *root_filename
, *root_pathname
;
5274 char *the_file
, *filename_part ();
5275 struct stat fileinfo
;
5280 /* Can only do this to files with tag tables. */
5285 size
= DEFAULT_SPLIT_SIZE
;
5287 if ((stat (filename
, &fileinfo
) != 0) ||
5288 (((long) fileinfo
.st_size
) < SPLIT_SIZE_THRESHOLD
))
5290 file_size
= (long) fileinfo
.st_size
;
5292 the_file
= find_and_load (filename
);
5296 root_filename
= filename_part (filename
);
5297 root_pathname
= pathname_part (filename
);
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. */
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
);
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')))
5339 last_char
= the_file
[i
];
5343 tags
= tags
->next_ent
;
5347 /* Otherwise, find the largest number of nodes that can fit in
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')))
5365 last_char
= the_file
[i
];
5370 if (file_bot
< limit
)
5372 tags
= tags
->next_ent
;
5377 /* Here we want to write out everything before the last
5378 node, and then write the last node out in a file
5380 file_bot
= tags
->position
;
5385 if (tags
->next_ent
->position
> limit
)
5387 if (tags
->position
== file_top
)
5388 tags
= tags
->next_ent
;
5390 file_bot
= tags
->position
;
5395 char *split_filename
;
5397 split_filename
= (char *) xmalloc
5398 (10 + strlen (root_pathname
) + strlen (root_filename
));
5401 "%s%s-%d", root_pathname
, root_filename
, which_file
);
5404 (split_filename
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
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
)) ||
5412 perror (split_filename
);
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
);
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");
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
);
5463 /* The strings here are followed in the message by `reference to...' in
5464 the `validate' routine. */
5466 reftype_type_string (type
)
5471 case menu_reference
:
5473 case followed_reference
:
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. */
5485 remember_node_reference (node
, line
, 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
;
5497 temp
->containing_node
= xstrdup (current_node
? current_node
: "");
5498 temp
->filename
= node_filename
;
5500 node_references
= temp
;
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. */
5521 find_node_reference (node
, ref_list
)
5523 register NODE_REF
*ref_list
;
5527 if (strcmp (node
, ref_list
->node
) == 0)
5529 ref_list
= ref_list
->next
;
5535 free_node_references ()
5537 register NODE_REF
*list
, *temp
;
5539 list
= node_references
;
5545 free (list
->containing_node
);
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 "* "
5558 glean_node_from_menu (remember_reference
)
5559 int remember_reference
;
5561 int i
, orig_offset
= input_text_offset
;
5564 if (strncmp (&input_text
[input_text_offset
+ 1],
5566 strlen (menu_starter
)) != 0)
5567 return ((char *)NULL
);
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 () == ':')
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
5590 isolate_nodename (nodename
);
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
);
5603 return ((char *)NULL
);
5610 isolate_nodename (nodename
)
5614 int paren_seen
, paren
;
5619 canon_white (nodename
);
5620 paren_seen
= paren
= i
= 0;
5622 if (*nodename
== '.' || !*nodename
)
5628 if (*nodename
== '(')
5635 for (; (c
= nodename
[i
]); i
++)
5647 /* If the character following the close paren is a space, then this
5648 node has no more characters associated with it. */
5652 ((paren_seen
&& nodename
[i
- 1] == ')') &&
5653 (c
== ' ' || c
== '.')) ||
5655 ((!nodename
[i
+ 1] ||
5656 (cr_or_whitespace (nodename
[i
+ 1])) ||
5657 (nodename
[i
+ 1] == ')')))))
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
);
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 /* **************************************************************** */
5689 /* Cross Reference Hacking */
5691 /* **************************************************************** */
5693 /* Return next comma-delimited argument, but do not cross a close-brace
5694 boundary. Clean up whitespace, too. */
5700 get_until_in_braces (",", &string
);
5701 if (curchar () == ',')
5702 input_text_offset
++;
5703 fix_whitespace (string
);
5707 int px_ref_flag
= 0; /* Controls initial output string. */
5709 /* Make a cross reference. */
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 ");
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
);
5749 remember_node_reference (arg1
, line_number
, followed_reference
);
5754 execute_string ("%s: %s", arg3
, arg1
);
5756 execute_string ("%s: %s", arg2
, arg1
);
5761 execute_string ("%s: %s", arg2
, arg1
);
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
);
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] == ':')
5783 while (temp
< size_of_input_text
)
5785 if (cr_or_whitespace (input_text
[temp
]))
5789 if (input_text
[temp
] != '.'
5790 && input_text
[temp
] != ','
5791 && input_text
[temp
] != '\t')
5794 _("`.' or `,' must follow cross reference, not %c"),
5823 char *node
= get_xref_token ();
5824 char *pname
= get_xref_token ();
5825 char *file
= get_xref_token ();
5828 execute_string ("*note %s: (%s)%s", pname
, file
, node
);
5830 execute_string ("*note (%s)%s::", file
, node
);
5838 /* A URL reference. */
5840 cm_uref (arg
, start_pos
, end_pos
)
5841 int arg
, start_pos
, end_pos
;
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 */
5857 /* Ignore spaces at beginning of second arg. */
5858 for (comma
++; isspace (*comma
); comma
++)
5868 extern int printing_index
;
5870 if (!printing_index
)
5875 if (!printing_index
)
5882 /* An email reference. */
5884 cm_email (arg
, start_pos
, end_pos
)
5885 int arg
, start_pos
, end_pos
;
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
, ',');
5901 for (comma
++; isspace (*comma
); comma
++)
5913 /* An external image is a reference, kind of. The parsing is (not
5914 coincidentally) similar, anyway. */
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
);
5931 /* Try to open foo.txt. */
5933 char *name
= xmalloc (strlen (name_arg
) + 4);
5934 strcpy (name
, name_arg
);
5935 strcat (name
, ".txt");
5936 image_file
= fopen (name
, "r");
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
5951 while ((ch
= getc (image_file
)) != EOF
)
5954 inhibit_paragraph_indentation
= save_inhibit_indentation
;
5955 filling_enabled
= save_filling_enabled
;
5957 if (fclose (image_file
) != 0) {
5962 warning (_("@image file `%s' unreadable: %s"), name
,
5966 line_error (_("@image missing filename argument"));
5968 if (name_arg
) free (name_arg
);
5972 /* **************************************************************** */
5974 /* Insertion Command Stubs */
5976 /* **************************************************************** */
5981 begin_insertion (quotation
);
5987 begin_insertion (example
);
5993 begin_insertion (smallexample
);
5999 begin_insertion (lisp
);
6005 begin_insertion (smalllisp
);
6008 /* @cartouche/@end cartouche draws box with rounded corners in
6009 TeX output. Right now, just a no-op insertion. */
6013 begin_insertion (cartouche
);
6019 begin_insertion (format
);
6025 begin_insertion (display
);
6032 command_name_condition ();
6034 begin_insertion (direntry
);
6040 begin_insertion (itemize
);
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. */
6052 do_enumeration (type
, default_string
)
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
));
6072 default_string
= "1";
6075 enumeration_arg
= xstrdup (default_string
);
6077 begin_insertion (type
);
6083 begin_insertion (table
);
6089 begin_insertion (multitable
); /* @@ */
6095 begin_insertion (ftable
);
6101 begin_insertion (vtable
);
6107 begin_insertion (group
);
6113 begin_insertion (ifinfo
);
6119 begin_insertion (ifnothtml
);
6125 begin_insertion (ifnottex
);
6128 /* Begin an insertion where the lines are not filled or indented. */
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. */
6140 begin_insertion (flushright
);
6143 /* End existing insertion block. */
6148 enum insertion_type type
;
6150 if (!insertion_level
)
6152 line_error (_("Unmatched `%c%s'"), COMMAND_PREFIX
, command
);
6156 get_rest_of_line (&temp
);
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
);
6172 /* **************************************************************** */
6174 /* Conditional Handling */
6176 /* **************************************************************** */
6178 /* A structure which contains `defined' variables. */
6179 typedef struct defines
{
6180 struct defines
*next
;
6185 /* The linked list of `set' defines. */
6186 DEFINE
*defines
= (DEFINE
*)NULL
;
6188 /* Add NAME to the list of `set' defines. */
6196 for (temp
= defines
; temp
; temp
= temp
->next
)
6197 if (strcmp (name
, temp
->name
) == 0)
6200 temp
->value
= xstrdup (value
);
6204 temp
= (DEFINE
*)xmalloc (sizeof (DEFINE
));
6205 temp
->next
= defines
;
6206 temp
->name
= xstrdup (name
);
6207 temp
->value
= xstrdup (value
);
6211 /* Remove NAME from the list of `set' defines. */
6216 register DEFINE
*temp
, *last
;
6218 last
= (DEFINE
*)NULL
;
6223 if (strcmp (temp
->name
, name
) == 0)
6226 last
->next
= temp
->next
;
6228 defines
= temp
->next
;
6240 /* Return the value of NAME. The return value is NULL if NAME is unset. */
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. */
6256 command_name_condition ()
6260 discarder
= (char *)xmalloc (8 + strlen (command
));
6262 sprintf (discarder
, "\n%cend %s", COMMAND_PREFIX
, command
);
6263 discard_until (discarder
);
6264 discard_until ("\n");
6269 /* Create a variable whose name appears as the first word on this line. */
6273 handle_variable (SET
);
6276 /* Remove a variable whose name appears as the first word on this line. */
6280 handle_variable (CLEAR
);
6286 handle_variable (IFSET
);
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. */
6306 arglist
= get_brace_args (0);
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
);
6322 cm_value (arg
, start_pos
, end_pos
)
6323 int arg
, start_pos
, end_pos
;
6327 char *name
= (char *) &output_paragraph
[start_pos
];
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
;
6336 execute_string ("%s", value
);
6338 add_word_args (_("{No Value For \"%s\"}"), name
);
6344 /* Set, clear, or conditionalize based on ACTION. */
6346 handle_variable (action
)
6351 get_rest_of_line (&name
);
6352 backup_input_pointer ();
6353 handle_variable_internal (action
, name
);
6358 handle_variable_internal (action
, name
)
6363 int delimiter
, additional_text_present
= 0;
6365 /* Only the first word of NAME is a valid tag. */
6368 while (*temp
&& (delimiter
|| !whitespace (*temp
)))
6370 /* #if defined (SET_WITH_EQUAL) */
6371 if (*temp
== '"' || *temp
== '\'')
6373 if (*temp
== delimiter
)
6378 /* #endif SET_WITH_EQUAL */
6383 additional_text_present
++;
6388 line_error (_("%c%s requires a name"), COMMAND_PREFIX
, command
);
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
++);
6406 if (*value
== '"' || *value
== '\'')
6409 value
[strlen (value
) - 1] = 0;
6412 #else /* !SET_WITH_EQUAL */
6413 /* The VALUE of NAME is the remainder of the line sans
6415 if (additional_text_present
)
6418 canon_white (value
);
6422 #endif /* !SET_WITH_VALUE */
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. */
6441 int orig_line_number
= line_number
;
6443 if (action
== IFSET
)
6444 strcpy (condition
, "ifset");
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))
6466 else if (strncmp (line
, "@end", 4) == 0)
6468 char *cname
= line
+ 4;
6471 while (*cname
&& whitespace (*cname
))
6475 while (*temp
&& !whitespace (*temp
))
6479 if (strcmp (cname
, condition
) == 0)
6489 free (freeable_line
);
6494 int save
= line_number
;
6495 line_number
= orig_line_number
;
6496 line_error (_("Reached eof before matching @end %s"),
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. */
6508 if (action
== IFSET
)
6509 begin_insertion (ifset
);
6511 begin_insertion (ifclear
);
6519 /* Execution of random text not in file. */
6522 char *string
; /* The string buffer. */
6523 int size
; /* The size of the buffer. */
6524 int in_use
; /* Nonzero means string currently in use. */
6527 static EXECUTION_STRING
**execution_strings
= (EXECUTION_STRING
**)NULL
;
6528 static int execution_strings_index
= 0;
6529 static int execution_strings_slots
= 0;
6532 get_execution_string (initial_size
)
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
];
6550 if (execution_strings_index
+ 1 >= execution_strings_slots
)
6552 execution_strings
= (EXECUTION_STRING
**)xrealloc
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
++;
6565 es
->string
= (char *)NULL
;
6569 if (initial_size
> es
->size
)
6571 es
->string
= (char *) xrealloc (es
->string
, initial_size
);
6572 es
->size
= initial_size
;
6577 /* Execute the string produced by formatting the ARGs with FORMAT. This
6578 is like submitting a new file with @include. */
6580 #if defined (VA_FPRINTF) && __STDC__
6581 execute_string (char *format
, ...)
6583 execute_string (format
, va_alist
)
6588 EXECUTION_STRING
*es
;
6594 es
= get_execution_string (4000);
6595 temp_string
= es
->string
;
6598 VA_START (ap
, format
);
6600 VA_SPRINTF (temp_string
, format
, ap
);
6602 sprintf (temp_string
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
);
6603 #endif /* not VA_SPRINTF */
6607 input_text_offset
= 0;
6608 input_text
= temp_string
;
6609 input_filename
= xstrdup (input_filename
);
6610 size_of_input_text
= strlen (temp_string
);
6614 free (input_filename
);
6622 /* Return what would be output for STR, i.e., expand Texinfo commands.
6623 If IMPLICIT_CODE is set, expand @code{STR}. */
6626 expansion (str
, implicit_code
)
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
);
6648 /* Pretend it never happened. */
6649 output_paragraph_offset
= start
;
6650 paragraph_is_open
= saved_paragraph_is_open
;
6655 /* @itemx, @item. */
6657 static int itemx_flag
= 0;
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
;
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
6688 switch (stack
->insertion
)
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
6699 input_text_offset
= original_input_text_offset
;
6707 stack
= stack
->next
;
6722 line_error (_("The `%c%s' command is meaningless within a `@%s' block"),
6723 COMMAND_PREFIX
, command
,
6724 insertion_type_pname (current_insertion_type ()));
6731 line_error (_("%citemx is not meaningful inside of a `%s' block"),
6733 insertion_type_pname (current_insertion_type ()));
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
);
6755 execute_string ("%s", item_func
);
6757 execute_string ("%s", item_func
);
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. */
6773 input_text_offset
= original_input_text_offset
;
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
6792 if (!itemx_flag
&& last_item_output_position
== output_position
)
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
)
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. */
6811 inhibit_paragraph_indentation
= save
;
6813 #else /* !INDENT_PARAGRAPHS_IN_TABLE */
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
);
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
);
6844 line_error (_("%c%s found outside of an insertion block"),
6845 COMMAND_PREFIX
, command
);
6849 /* **************************************************************** */
6851 /* Defun and Friends */
6853 /* **************************************************************** */
6855 #define DEFUN_SELF_DELIMITING(c) \
6861 struct token_accumulator
6863 unsigned int length
;
6869 initialize_token_accumulator (accumulator
)
6870 struct token_accumulator
*accumulator
;
6872 (accumulator
->length
) = 0;
6873 (accumulator
->index
) = 0;
6874 (accumulator
->tokens
) = NULL
;
6878 accumulate_token (accumulator
, token
)
6879 struct token_accumulator
*accumulator
;
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;
6893 copy_substring (start
, end
)
6897 char *result
, *scan
, *scan_result
;
6899 result
= (char *) xmalloc ((end
- start
) + 1);
6900 scan_result
= result
;
6904 *scan_result
++ = *scan
++;
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
;
6917 register char *scan_string
;
6918 register unsigned int level
= 1;
6920 scan_string
= (*string_pointer
) + 1;
6926 (*string_pointer
) = scan_string
;
6929 c
= (*scan_string
++);
6932 /* Tweak line_number to compensate for fact that
6933 we gobbled the whole line before coming here. */
6935 line_error (_("Missing `}' in %cdef arg"), COMMAND_PREFIX
);
6937 (*string_pointer
) = (scan_string
- 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. */
6952 args_from_string (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
))
6967 while (whitespace (*scan_string
))
6969 accumulate_token ((&accumulator
), (xstrdup (" ")));
6973 /* Commands count as single tokens. */
6974 if ((*scan_string
) == COMMAND_PREFIX
)
6976 token_start
= scan_string
;
6978 if (self_delimiting (*scan_string
))
6987 if ((c
== 0) || (c
== '{') || (whitespace (c
)))
6994 if (*scan_string
== '{')
6996 char *s
= scan_string
;
6997 (void) scan_group_in_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
;
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;
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. */
7027 token_start
= 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
)
7045 /* If we encounter a command embedded within a token,
7046 then end the token. */
7047 if (c
== COMMAND_PREFIX
)
7053 token_end
= scan_string
;
7057 (&accumulator
, copy_substring (token_start
, token_end
));
7059 accumulate_token (&accumulator
, NULL
);
7060 return (accumulator
.tokens
);
7064 process_defun_args (defun_args
, auto_var_p
)
7068 int pending_space
= 0;
7072 char *defun_arg
= *defun_args
++;
7074 if (defun_arg
== NULL
)
7077 if (defun_arg
[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
);
7098 add_word (defun_arg
);
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
== ' '))
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. */
7124 defun_internal (type
, x_p
)
7125 enum insertion_type type
;
7128 enum insertion_type base_type
;
7129 char **defun_args
, **scan_args
;
7130 char *category
, *defined_name
, *type_name
, *type_name2
;
7134 get_rest_of_line (&line
);
7135 defun_args
= (args_from_string (line
));
7139 scan_args
= defun_args
;
7144 category
= _("Function");
7148 category
= _("Macro");
7152 category
= _("Special Form");
7156 category
= _("Variable");
7160 category
= _("User Option");
7164 category
= _("Function");
7165 base_type
= deftypefn
;
7168 category
= _("Variable");
7169 base_type
= deftypevr
;
7172 category
= _("Instance Variable");
7176 category
= _("Method");
7180 category
= _("Method");
7181 base_type
= deftypemethod
;
7184 category
= next_nonwhite_defun_arg (&scan_args
);
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
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]);
7220 begin_insertion (type
);
7222 /* Write the definition header line.
7223 This should start at the normal indentation. */
7224 current_indent
-= default_indentation_increment
;
7232 execute_string (" -- %s: %s", category
, defined_name
);
7236 execute_string (" -- %s: %s %s", category
, type_name
, defined_name
);
7239 execute_string (" -- %s of %s: %s", category
, type_name
, defined_name
);
7242 execute_string (" -- %s on %s: %s", category
, type_name
, defined_name
);
7245 execute_string (" -- %s on %s: %s %s", category
, type_name
, type_name2
,
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
;
7261 process_defun_args (scan_args
, 1);
7264 /* Through Makeinfo 1.67 we processed remaining args only for deftp,
7265 deftypefn, and deftypemethod. But the libc manual, for example,
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. */
7272 process_defun_args (scan_args
, 0);
7275 current_indent
-= default_indentation_increment
;
7276 close_single_paragraph ();
7278 /* Make an entry in the appropriate index. */
7283 execute_string ("%cfindex %s\n", COMMAND_PREFIX
, defined_name
);
7288 execute_string ("%cvindex %s\n", COMMAND_PREFIX
, defined_name
);
7292 execute_string ("%cfindex %s on %s\n",
7293 COMMAND_PREFIX
, defined_name
, type_name
);
7296 execute_string ("%ctindex %s\n", COMMAND_PREFIX
, defined_name
);
7300 /* Deallocate the token list. */
7301 scan_args
= defun_args
;
7304 char * arg
= (*scan_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. */
7319 enum insertion_type type
;
7320 char *temp
= xstrdup (command
);
7322 x_p
= (command
[strlen (command
) - 1] == 'x');
7325 temp
[strlen (temp
) - 1] = 0;
7327 type
= find_type_from_name (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. */
7333 (!insertion_level
|| insertion_stack
->insertion
!= type
))
7335 line_error (_("Must be in a `%s' insertion in order to use `%s'x"),
7337 discard_until ("\n");
7341 defun_internal (type
, x_p
);
7344 /* **************************************************************** */
7346 /* Other Random Commands */
7348 /* **************************************************************** */
7350 /* This says to inhibit the indentation of the next paragraph, but
7351 not of following paragraphs. */
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. */
7368 get_rest_of_line (&filename
);
7369 /* warning ("`@%s %s' encountered and ignored", command, filename); */
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. */
7384 if (looking_at ("{}"))
7385 input_text_offset
+= 2;
7387 if (curchar () == '\n')
7389 input_text_offset
++;
7396 /* Insert the number of blank lines passed as argument. */
7403 get_rest_of_line (&line
);
7405 if (sscanf (line
, "%d", &lines
) != 1)
7407 line_error (_("%csp requires a positive numeric argument"), COMMAND_PREFIX
);
7420 /* @dircategory LINE outputs INFO-DIR-SECTION LINE,
7421 but not if --no-headers. */
7428 get_rest_of_line (&line
);;
7432 insert_string ("INFO-DIR-SECTION ");
7433 insert_string (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. */
7446 register int i
, start
, length
;
7447 int fudge_factor
= 1;
7448 unsigned char *line
;
7451 filling_enabled
= indented_fill
= 0;
7453 start
= output_paragraph_offset
;
7454 inhibit_output_flushing ();
7455 get_rest_of_line ((char **)&line
);
7456 execute_string ("%s", (char *)line
);
7458 uninhibit_output_flushing ();
7460 i
= output_paragraph_offset
- 1;
7461 while (i
> (start
- 1) && output_paragraph
[i
] == '\n')
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
;
7478 for (i
= 0; i
< length
; i
++)
7486 filling_enabled
= 1;
7489 /* Show what an expression returns. */
7498 /* What an expression expands to. */
7507 /* Indicates two expressions are equivalent. */
7516 /* What an expression may print. */
7525 /* An error signaled. */
7531 add_word ("error-->");
7534 /* The location of point in an example of a buffer. */
7543 /* Start a new line with just this text on it.
7544 The text is outdented one level if possible. */
7549 int i
= current_indent
;
7552 current_indent
-= default_indentation_increment
;
7554 get_rest_of_line (&line
);
7555 close_single_paragraph ();
7556 execute_string ("%s", line
);
7559 close_single_paragraph ();
7563 /* Remember this file, and move onto the next. */
7569 #if defined (HAVE_MACROS)
7570 if (macro_expansion_output_stream
&& !executing_string
)
7571 me_append_before_this_command ();
7572 #endif /* HAVE_MACROS */
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 */
7584 /* In verbose mode we print info about including another file. */
7588 register FSTACK
*stack
= filestack
;
7590 for (i
= 0, stack
= filestack
; stack
; stack
= stack
->next
, i
++);
7594 printf ("%*s", i
, "");
7595 printf ("%c%s %s\n", COMMAND_PREFIX
, command
, filename
);
7599 if (!find_and_load (filename
))
7606 /* Cannot "@include foo", in line 5 of "/wh/bar". */
7607 line_error ("%c%s %s: %s", COMMAND_PREFIX
, command
, filename
,
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 */
7625 /* The other side of a malformed expression. */
7629 line_error (_("Misplaced %c"), '}');
7632 /* Signals end of processing. Easy to make this happen. */
7636 input_text_offset
= size_of_input_text
;
7639 /* Set the paragraph indentation variable to the value specified in STRING.
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
)
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;
7656 if (sscanf (string
, "%d", ¶graph_start_indent
) != 1)
7660 if (paragraph_start_indent
== 0)
7661 paragraph_start_indent
= -1;
7668 cm_paragraphindent ()
7672 get_rest_of_line (&arg
);
7673 if (set_paragraph_indent (arg
) != 0)
7674 line_error (_("Bad argument to %c%s"), COMMAND_PREFIX
, command
);
7679 /* **************************************************************** */
7681 /* Indexing Stuff */
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. */
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
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
7713 For example, after the commands
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. */
7730 int read_index
; /* index entries for `name' */
7731 int write_index
; /* store index entries here, @synindex can change it */
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
7740 INDEX_ELT
**the_indices
= (INDEX_ELT
**) NULL
;
7742 /* The number of defined indices. */
7743 int defined_indices
= 0;
7750 /* Create the default data structures. */
7752 /* Initialize data space. */
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
)
7797 for (i
= 0; i
< defined_indices
; i
++)
7798 if (name_index_alist
[i
] &&
7799 strcmp (name
, name_index_alist
[i
]->name
) == 0)
7804 /* Return a pointer to the entry of (name . index) for this name.
7805 Return NULL if the index doesn't exist. */
7810 int offset
= find_index_offset (name
);
7812 return (name_index_alist
[offset
]);
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
)
7823 INDEX_ALIST
*which
= find_index (name
);
7826 return (which
->read_index
);
7831 /* Return the index list which belongs to NAME. */
7836 int which
= translate_index (name
);
7838 return ((INDEX_ELT
*) -1);
7840 return (the_indices
[which
]);
7843 /* Please release me, let me go... */
7850 while ((temp
= index
) != (INDEX_ELT
*) NULL
)
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
;
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. */
7868 int which
= find_index_offset (name
);
7870 /* The index might have already been freed if this was the target of
7872 if (which
< 0 || !name_index_alist
[which
])
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. */
7888 defindex (name
, code
)
7892 register int i
, slot
;
7894 /* If it already exists, flush it. */
7897 /* Try to find an empty slot. */
7899 for (i
= 0; i
< defined_indices
; i
++)
7900 if (!name_index_alist
[i
])
7908 /* No such luck. Make space for another index. */
7909 slot
= 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. */
7932 index_add_arg (name
)
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
)
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 */
7966 line_error (_("Unknown index `%s'"), name
);
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. */
7988 char *name
= xstrdup (command
);
7989 if (strlen (name
) >= strlen ("index"))
7990 name
[strlen (name
) - strlen ("index")] = 0;
7991 index_add_arg (name
);
7996 top_defindex (name
, code
)
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
);
8009 /* Define a new index command. Arg is name of index. */
8027 get_rest_of_line (&name
);
8029 if (find_index (name
))
8031 line_error (_("Index `%s' already exists"), name
);
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
);
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. */
8052 char *abbrev1
, *abbrev2
;
8055 get_until_in_line (0, " ", &abbrev1
);
8056 target
= find_index_offset (abbrev1
);
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"),
8067 name_index_alist
[target
]->write_index
8068 = name_index_alist
[source
]->write_index
;
8076 cm_pindex () /* Pinhead index. */
8078 index_add_arg ("pg");
8082 cm_vindex () /* Variable index. */
8084 index_add_arg ("vr");
8088 cm_kindex () /* Key index. */
8090 index_add_arg ("ky");
8094 cm_cindex () /* Concept index. */
8096 index_add_arg ("cp");
8100 cm_findex () /* Function index. */
8102 index_add_arg ("fn");
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. */
8121 make_index_entries_unique (array
, count
)
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
];
8139 free (array
[i
]->entry
);
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
;
8171 array
[i
] = (INDEX_ELT
*)NULL
;
8173 /* Free the storage used only by 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. */
8186 INDEX_ELT
*temp
= index
;
8188 int save_line_number
= line_number
;
8189 char *save_input_filename
= input_filename
;
8191 while (temp
!= (INDEX_ELT
*) NULL
)
8197 /* We have the length. Make an array. */
8199 array
= (INDEX_ELT
**) xmalloc ((count
+ 1) * sizeof (INDEX_ELT
*));
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
);
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
);
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. */
8240 unsigned line_length
;
8242 int saved_inhibit_paragraph_indentation
= inhibit_paragraph_indentation
;
8243 int saved_filling_enabled
= filling_enabled
;
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
);
8258 /* Do this before sorting, so execute_string in index_element_compare
8259 will give the same results as when we actually print. */
8261 filling_enabled
= 0;
8262 inhibit_paragraph_indentation
= 1;
8263 array
= sort_index (index
);
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. */
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 */
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
8307 #if defined (HAVE_MACROS)
8308 me_inhibit_expansion
--;
8309 #endif /* HAVE_MACROS */
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. */
8321 define_user_command (name
, proc
, needs_braces_p
)
8323 COMMAND_FUNCTION
*proc
;
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.
8348 Make them look like followed references, with the reference
8349 destinations in a makeinfo manufactured node or,
8352 Make them appear at the bottom of the node that they originally
8354 #define SeparateNode 0
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
)
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
;
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
);
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. */
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
;
8416 /* How to get rid of existing footnotes. */
8418 free_pending_notes ()
8422 while ((temp
= pending_notes
) != (FN
*) NULL
)
8424 free (temp
->marker
);
8426 pending_notes
= pending_notes
->next
;
8429 first_footnote_this_node
= 1;
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. */
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
);
8462 int loc
= ++input_text_offset
;
8466 if (loc
== size_of_input_text
)
8468 line_error (_("No closing brace for footnote `%s'"), marker
);
8472 if (input_text
[loc
] == '{')
8474 else if (input_text
[loc
] == '}')
8476 else if (input_text
[loc
] == '\n')
8482 len
= (loc
- input_text_offset
) - 1;
8483 note
= (char *)xmalloc (len
+ 1);
8484 strncpy (note
, &input_text
[input_text_offset
], len
);
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
)
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"));
8517 if (number_footnotes
)
8519 marker
= (char *)xmalloc (10);
8520 sprintf (marker
, "%d", current_footnote_number
);
8521 current_footnote_number
++;
8524 marker
= xstrdup ("*");
8527 remember_note (marker
, note
);
8529 /* Your method should at least insert MARKER. */
8530 switch (footnote_style
)
8533 add_word_args ("(%s)", marker
);
8534 if (first_footnote_this_node
)
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
);
8546 first_footnote_this_node
= 0;
8551 add_word_args ("(%s)", marker
);
8561 /* Nonzero means that we are currently in the process of outputting
8563 int already_outputting_pending_notes
= 0;
8565 /* Output the footnotes. We are at the end of the current node. */
8567 output_pending_notes ()
8569 FN
*footnote
= pending_notes
;
8574 switch (footnote_style
)
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
;
8587 command
= old_command
;
8593 in_fixed_width_font
++;
8594 execute_string (_("---------- Footnotes ----------\n\n"));
8595 in_fixed_width_font
--;
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;
8614 while ((footnote
= array
[++footnote_count
]))
8616 execute_string ("(%s) %s", footnote
->marker
, footnote
->note
);
8624 /* **************************************************************** */
8626 /* User definable Macros (text substitution) */
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. */
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))
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. */
8661 add_macro (name
, arglist
, body
, source_file
, source_lineno
, flags
)
8666 int source_lineno
, flags
;
8668 register MACRO_DEF
*def
;
8670 def
= find_macro (name
);
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;
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
;
8703 for (i
= 0; def
->arglist
[i
]; i
++)
8704 free (def
->arglist
[i
]);
8706 free (def
->arglist
);
8708 free (def
->source_file
);
8712 def
->source_file
= xstrdup (source_file
);
8713 def
->source_lineno
= source_lineno
;
8715 def
->arglist
= arglist
;
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
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
*));
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;
8748 get_macro_args (def
)
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
]))
8760 if (input_text
[i
] != '{')
8762 if (braces_required_for_macro_args
)
8764 return ((char **)NULL
);
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])
8775 get_rest_of_line (&word
);
8776 if (input_text
[input_text_offset
- 1] == '\n')
8778 input_text_offset
--;
8781 /* canon_white (word); */
8782 arglist
= (char **)xmalloc (2 * sizeof (char *));
8784 arglist
[1] = (char *)NULL
;
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\. */
8803 apply (named
, actuals
, body
)
8804 char **named
, **actuals
, *body
;
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;
8823 if (body
[i
] != '\\')
8824 new_body
[new_body_index
++] = body
[i
++];
8827 /* Snarf parameter name, check against named parameters. */
8829 int param_start
, which
, len
;
8832 while ((body
[i
]) && (body
[i
] != '\\'))
8835 len
= i
- param_start
;
8836 param
= (char *)xmalloc (1 + len
);
8837 memcpy (param
, body
+ param_start
, len
);
8840 if (body
[i
]) /* move past \ */
8843 /* Now check against named parameters. */
8844 for (which
= 0; named
&& named
[which
]; which
++)
8845 if (strcmp (named
[which
], param
) == 0)
8848 if (named
&& named
[which
])
8850 if (which
< length_of_actuals
)
8851 text
= actuals
[which
];
8853 text
= (char *)NULL
;
8858 len
= strlen (text
);
8861 { /* not a parameter, restore \'s */
8862 i
= body
[i
] ? (i
- 1) : i
;
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
);
8876 strcpy (new_body
+ new_body_index
, text
);
8877 new_body_index
+= len
;
8879 if (!named
|| !named
[which
])
8883 new_body
[new_body_index
] = 0;
8887 /* Execute the macro passed in DEF, a pointer to a MACRO_DEF. */
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
);
8913 execution_string
= apply (def
->arglist
, arglist
, def
->body
);
8915 free_array (arglist
);
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
);
8925 execute_string ("%s", execution_string
);
8927 free (execution_string
);
8931 /* Read and remember the definition of a macro. */
8936 char *name
, **arglist
, *body
, *line
;
8937 int body_size
, body_index
;
8939 int defining_line
= line_number
;
8942 arglist
= (char **)NULL
;
8943 body
= (char *)NULL
;
8947 if (macro_expansion_output_stream
&& !executing_string
)
8948 me_append_before_this_command ();
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
;
8959 (i
< size_of_input_text
) &&
8960 (input_text
[i
] != '{') &&
8961 (!cr_or_whitespace (input_text
[i
]));
8965 name
= (char *)xmalloc (1 + len
);
8966 strncpy (name
, input_text
+ start
, len
);
8968 input_text_offset
= i
;
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
;
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
8986 input_text_offset
++;
8987 skip_whitespace_and_newlines ();
8989 while (gathering_words
)
8993 for (i
= input_text_offset
;
8994 (character
= input_text
[i
]);
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
);
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 ())
9016 && character
!= '}')
9018 input_text_offset
++;
9019 if (character
== '\n')
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
;
9033 if (character
== '}')
9035 input_text_offset
++;
9036 gathering_words
= 0;
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 ();
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
;
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
;
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
;
9100 line_error (_("%cquote-arg only useful when the macro takes a single argument"),
9105 if ((*line
== COMMAND_PREFIX
) &&
9106 (strncmp (line
+ 1, "macro ", 6) == 0))
9109 if ((*line
== COMMAND_PREFIX
) &&
9110 (strncmp (line
+ 1, "end macro", 9) == 0))
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;
9126 /* If it was an empty macro like
9129 create an empty body. (Otherwise, the macro is not expanded.) */
9132 body
= (char *)malloc(1);
9136 /* We now have the name, the arglist, and the body. However, BODY
9137 includes the final newline which preceded the `@end macro' text.
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
);
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
);
9165 def
= delete_macro (name
);
9169 free (def
->source_file
);
9177 for (i
= 0; def
->arglist
[i
]; i
++)
9178 free (def
->arglist
[i
]);
9180 free (def
->arglist
);
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. */
9197 remember_itext (pointer
, offset
)
9202 ITEXT
*itext
= (ITEXT
*)NULL
;
9204 /* If we have no info, initialize a blank list. */
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
;
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
)
9230 /* If not found, then add some slots. */
9231 if (i
== itext_size
)
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
];
9251 /* Forget the input text associated with POINTER. */
9253 forget_itext (pointer
)
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
;
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. */
9270 me_append_before_this_command ()
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. */
9281 me_execute_string (execution_string
)
9282 char *execution_string
;
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
++;
9295 me_executing_string
--;
9298 /* Append the text which appears in input_text from the last offset to
9299 the current OFFSET. */
9301 append_to_expansion_output (offset
)
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
];
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. */
9327 maybe_write_itext (pointer
, offset
)
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
];
9341 if (itext
&& (itext
->offset
< offset
))
9343 write_region_to_macro_output (itext
->pointer
, itext
->offset
, offset
);
9344 remember_itext (pointer
, offset
);
9349 write_region_to_macro_output (string
, 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. */
9367 for (i
= 0; array
[i
] != (char *)NULL
; i
++);
9380 for (i
= 0; array
[i
] != (char *)NULL
; i
++)
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. */
9391 get_brace_args (quote_single
)
9394 char **arglist
, *word
;
9395 int arglist_index
, arglist_size
;
9396 int character
, escape_seen
, start
;
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;
9406 skip_whitespace_and_newlines ();
9407 start
= input_text_offset
;
9410 while ((character
= curchar ()))
9412 if (character
== '\\')
9414 input_text_offset
+= 2;
9417 else if (character
== '{')
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
);
9433 /* Clean up escaped characters. */
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
== '}')
9458 else if (character
== '}')
9461 input_text_offset
++;
9465 input_text_offset
++;
9466 if (character
== '\n') line_number
++;
9472 /* **************************************************************** */
9474 /* Looking For Include Files */
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. */
9482 extract_colon_unit (string
, 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
] == ':')
9503 while (string
[i
] && string
[i
] != ':') i
++;
9512 /* Return "" in the case of a trailing `:'. */
9513 return (xstrdup (""));
9519 value
= (char *)xmalloc (1 + (i
- start
));
9520 strncpy (value
, &string
[start
], (i
- start
));
9521 value
[i
- start
] = 0;
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. */
9532 get_file_info_in_path (filename
, path
, finfo
)
9533 char *filename
, *path
;
9537 int result
, index
= 0;
9539 if (path
== (char *)NULL
)
9542 /* Handle absolute pathnames. "./foo", "/foo", "../foo". */
9543 if (*filename
== '/' ||
9544 (*filename
== '.' &&
9545 (filename
[1] == '/' ||
9546 (filename
[1] == '.' && filename
[2] == '/')))
9548 /* Handle names that look like "d:/foo/bar" */
9549 || (isalpha (*filename
) && filename
[1] == ':'
9550 && (filename
[2] == '/' || filename
[2] == '\\'))
9554 if (stat (filename
, finfo
) == 0)
9555 return (xstrdup (filename
));
9557 return ((char *)NULL
);
9560 while ((dir
= extract_colon_unit (path
, &index
)))
9567 dir
= xstrdup (".");
9570 fullpath
= (char *)xmalloc (2 + strlen (dir
) + strlen (filename
));
9571 sprintf (fullpath
, "%s/%s", dir
, filename
);
9574 result
= stat (fullpath
, finfo
);