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 #ifdef HAVE_LC_MESSAGES
949 setlocale (LC_MESSAGES
, "");
953 /* Set the text message domain. */
954 bindtextdomain (PACKAGE
, LOCALEDIR
);
955 textdomain (PACKAGE
);
957 /* Parse argument flags from the input line. */
958 while ((c
= getopt_long (argc
, argv
, "D:e:E:f:I:o:p:P:r:s:U:V",
959 long_options
, &ind
)) != EOF
)
961 if (c
== 0 && long_options
[ind
].flag
== 0)
962 c
= long_options
[ind
].val
;
968 /* User specified variable to set or clear. */
969 handle_variable_internal ((c
== 'D') ? SET
: CLEAR
, optarg
);
973 /* User specified error level. */
974 if (sscanf (optarg
, "%d", &max_error_level
) != 1)
977 _("%s: %s arg must be numeric, not `%s'.\n"),
978 "--error-limit", progname
, optarg
);
979 usage (stderr
, FATAL
);
984 /* User specified a macro expansion output file. */
985 if (!macro_expansion_output_stream
)
987 macro_expansion_filename
= optarg
;
988 macro_expansion_output_stream
989 = strcmp (optarg
, "-") == 0 ? stdout
: fopen (optarg
, "w");
990 if (!macro_expansion_output_stream
)
991 error (_("Couldn't open macro expansion output `%s'"), optarg
);
994 error (_("Cannot specify more than one macro expansion output"));
998 /* User specified fill_column. */
999 if (sscanf (optarg
, "%d", &fill_column
) != 1)
1002 _("%s: %s arg must be numeric, not `%s'.\n"),
1003 "--fill-column", progname
, optarg
);
1009 force
++; /* Do not remove erroneous output. */
1017 /* Append user-specified dir to include file path. */
1018 if (!include_files_path
)
1019 include_files_path
= xstrdup (".");
1021 include_files_path
= (char *)
1022 xrealloc (include_files_path
,
1023 2 + strlen (include_files_path
) + strlen (optarg
));
1024 strcat (include_files_path
, ":");
1025 strcat (include_files_path
, optarg
);
1029 /* User specified output file. */
1030 command_output_filename
= xstrdup (optarg
);
1034 /* User specified paragraph indent (paragraph_start_index). */
1035 if (set_paragraph_indent (optarg
) < 0)
1038 _("%s: --paragraph-indent arg must be numeric/`none'/`asis', not `%s'.\n"),
1045 /* Prepend user-specified include dir to include path. */
1046 if (!include_files_path
)
1048 include_files_path
= xstrdup (optarg
);
1049 include_files_path
= (char *) xrealloc (include_files_path
,
1050 strlen (include_files_path
) + 3); /* 3 for ":.\0" */
1051 strcat (include_files_path
, ":.");
1055 char *tmp
= xstrdup (include_files_path
);
1056 include_files_path
= (char *) xrealloc (include_files_path
,
1057 strlen (include_files_path
) + strlen (optarg
) + 2); /* 2 for ":\0" */
1058 strcpy (include_files_path
, optarg
);
1059 strcat (include_files_path
, ":");
1060 strcat (include_files_path
, tmp
);
1066 /* User specified reference warning limit. */
1067 if (sscanf (optarg
, "%d", &reference_warning_limit
) != 1)
1070 _("%s: %s arg must be numeric, not `%s'.\n"),
1071 "--reference-limit", progname
, optarg
);
1077 /* User specified footnote style. */
1078 if (set_footnote_style (optarg
) < 0)
1081 _("%s: --footnote-style arg must be `separate' or `end', not `%s'.\n"),
1085 footnote_style_preset
= 1;
1089 /* User requested version info. */
1090 print_version_info ();
1091 printf (_("Copyright (C) %s Free Software Foundation, Inc.\n\
1092 There is NO warranty. You may redistribute this software\n\
1093 under the terms of the GNU General Public License.\n\
1094 For more information about these matters, see the files named COPYING.\n"),
1107 /* Check to see if input is a file. If so, process that. */
1108 if (!isatty (fileno (stdin
)))
1109 reading_from_stdin
= 1;
1112 fprintf (stderr
, _("%s: missing file argument.\n"), progname
);
1117 /* If the user has specified --no-headers, this should imply --no-split.
1118 Do that here. I think it might also imply that we should ignore the
1119 setfilename at the top of the file, but this might break some FSF things,
1120 so I will hold off on that. */
1125 /* If the user has not specified an output file, use stdout. */
1126 if (!command_output_filename
)
1127 command_output_filename
= xstrdup ("-");
1131 print_version_info ();
1133 /* Remaining arguments are file names of texinfo files.
1134 Convert them, one by one. */
1135 if (!reading_from_stdin
)
1137 while (optind
!= argc
)
1138 convert_from_file (argv
[optind
++]);
1141 convert_from_stream (stdin
, "stdin");
1149 /* Display the version info of this invocation of Makeinfo. */
1151 print_version_info ()
1153 printf ("makeinfo (GNU %s %s) %d.%d\n", PACKAGE
, VERSION
,
1154 major_version
, minor_version
);
1157 /* If EXIT_VALUE is zero, print the full usage message to stdout.
1158 Otherwise, just say to use --help for more info.
1159 Then exit with EXIT_VALUE. */
1164 if (exit_value
!= 0)
1165 fprintf (stderr
, _("Try `%s --help' for more information.\n"), progname
);
1167 printf (_("Usage: %s [OPTION]... TEXINFO-FILE...\n\
1169 Translate Texinfo source documentation to a format suitable for reading\n\
1173 -D VAR define a variable, as with @set.\n\
1174 -E MACRO-OFILE process macros only, output texinfo source.\n\
1175 -I DIR append DIR to the @include directory search path.\n\
1176 -P DIR prepend DIR to the @include directory search path.\n\
1177 -U VAR undefine a variable, as with @clear.\n\
1178 --error-limit NUM quit after NUM errors (default %d).\n\
1179 --fill-column NUM break lines at NUM characters (default %d).\n\
1180 --footnote-style STYLE output footnotes according to STYLE:\n\
1181 `separate' to place footnotes in their own node,\n\
1182 `end' to place the footnotes at the end of\n\
1183 the node in which they are defined (the default).\n\
1184 --force preserve output even if errors.\n\
1185 --help display this help and exit.\n\
1186 --no-validate suppress node cross-reference validation.\n\
1187 --no-warn suppress warnings (but not errors).\n\
1188 --no-split suppress splitting of large files.\n\
1189 --no-headers suppress node separators and Node: Foo headers.\n\
1190 --output FILE, -o FILE output to FILE, and ignore any @setfilename.\n\
1191 --paragraph-indent VAL indent paragraphs with VAL spaces (default %d).\n\
1192 if VAL is `none', do not indent; if VAL is `asis',\n\
1193 preserve any existing indentation.\n\
1194 --reference-limit NUM complain about at most NUM references (default %d).\n\
1195 --verbose report about what is being done.\n\
1196 --version display version information and exit.\n\
1198 Email bug reports to bug-texinfo@gnu.org.\n\
1200 progname
, max_error_level
, fill_column
,
1201 paragraph_start_indent
, reference_warning_limit
);
1205 /* Manipulating Lists */
1207 typedef struct generic_list
{
1208 struct generic_list
*next
;
1211 /* Reverse the chain of structures in LIST. Output the new head
1212 of the chain. You should always assign the output value of this
1213 function to something, or you will lose the chain. */
1216 register GENERIC_LIST
*list
;
1218 register GENERIC_LIST
*next
;
1219 register GENERIC_LIST
*prev
= (GENERIC_LIST
*) NULL
;
1231 /* Pushing and Popping Files */
1233 /* Find and load the file named FILENAME. Return a pointer to
1234 the loaded file, or NULL if it can't be loaded. */
1236 find_and_load (filename
)
1239 struct stat fileinfo
;
1241 int file
= -1, count
= 0;
1242 char *fullpath
, *result
, *get_file_info_in_path ();
1244 result
= fullpath
= (char *)NULL
;
1246 fullpath
= get_file_info_in_path (filename
, include_files_path
, &fileinfo
);
1251 filename
= fullpath
;
1252 file_size
= (long) fileinfo
.st_size
;
1254 file
= open (filename
, O_RDONLY
);
1258 /* Load the file, with enough room for a newline and a null. */
1259 result
= xmalloc (file_size
+ 2);
1261 /* VMS stat lies about the st_size value. The actual number of
1262 readable bytes is always less than this value. The arcane
1263 mysteries of VMS/RMS are too much to probe, so this hack
1264 suffices to make things work. */
1265 #if defined (VMS) || defined (WIN32)
1267 while ((n
= read (file
, result
+ count
, file_size
)) > 0)
1269 while ((n
= read (file
, result
+ count
, 1)) > 0)
1273 #else /* !VMS && !WIN32 */
1275 if (read (file
, result
, file_size
) != file_size
)
1276 #endif /* !VMS && !WIN32 */
1288 return ((char *) NULL
);
1292 /* Set the globals to the new file. */
1293 input_text
= result
;
1294 size_of_input_text
= count
;
1295 input_filename
= fullpath
;
1296 node_filename
= xstrdup (fullpath
);
1297 input_text_offset
= 0;
1299 /* Not strictly necessary. This magic prevents read_token () from doing
1300 extra unnecessary work each time it is called (that is a lot of times).
1301 SIZE_OF_INPUT_TEXT is one past the actual end of the text. */
1302 input_text
[size_of_input_text
] = '\n';
1303 /* This, on the other hand, is always necessary. */
1304 input_text
[size_of_input_text
+1] = 0;
1308 /* Save the state of the current input file. */
1312 FSTACK
*newstack
= (FSTACK
*) xmalloc (sizeof (FSTACK
));
1313 newstack
->filename
= input_filename
;
1314 newstack
->text
= input_text
;
1315 newstack
->size
= size_of_input_text
;
1316 newstack
->offset
= input_text_offset
;
1317 newstack
->line_number
= line_number
;
1318 newstack
->next
= filestack
;
1320 filestack
= newstack
;
1321 push_node_filename ();
1324 /* Make the current file globals be what is on top of the file stack. */
1328 FSTACK
*tos
= filestack
;
1331 abort (); /* My fault. I wonder what I did? */
1333 #if defined (HAVE_MACROS)
1334 if (macro_expansion_output_stream
)
1336 maybe_write_itext (input_text
, input_text_offset
);
1337 forget_itext (input_text
);
1339 #endif /* HAVE_MACROS */
1341 /* Pop the stack. */
1342 filestack
= filestack
->next
;
1344 /* Make sure that commands with braces have been satisfied. */
1345 if (!executing_string
&& !me_executing_string
)
1348 /* Get the top of the stack into the globals. */
1349 input_filename
= tos
->filename
;
1350 input_text
= tos
->text
;
1351 size_of_input_text
= tos
->size
;
1352 input_text_offset
= tos
->offset
;
1353 line_number
= tos
->line_number
;
1356 /* Go back to the (now) current node. */
1357 pop_node_filename ();
1360 /* Flush all open files on the file stack. */
1366 char *fname
= input_filename
;
1367 char *text
= input_text
;
1374 int node_filename_stack_index
= 0;
1375 int node_filename_stack_size
= 0;
1376 char **node_filename_stack
= (char **)NULL
;
1379 push_node_filename ()
1381 if (node_filename_stack_index
+ 1 > node_filename_stack_size
)
1382 node_filename_stack
= (char **)xrealloc
1383 (node_filename_stack
, (node_filename_stack_size
+= 10) * sizeof (char *));
1385 node_filename_stack
[node_filename_stack_index
] = node_filename
;
1386 node_filename_stack_index
++;
1390 pop_node_filename ()
1392 node_filename
= node_filename_stack
[--node_filename_stack_index
];
1395 /* Return just the simple part of the filename; i.e. the
1396 filename without the path information, or extensions.
1397 This conses up a new string. */
1399 filename_part (filename
)
1404 basename
= strrchr (filename
, '/');
1406 basename
= filename
;
1410 basename
= xstrdup (basename
);
1411 #if defined (REMOVE_OUTPUT_EXTENSIONS)
1413 /* See if there is an extension to remove. If so, remove it. */
1417 temp
= strrchr (basename
, '.');
1421 #endif /* REMOVE_OUTPUT_EXTENSIONS */
1425 /* Return the pathname part of filename. This can be NULL. */
1427 pathname_part (filename
)
1430 char *expand_filename ();
1431 char *result
= (char *) NULL
;
1434 filename
= expand_filename (filename
, "");
1436 i
= strlen (filename
) - 1;
1438 while (i
&& filename
[i
] != '/')
1440 if (filename
[i
] == '/')
1445 result
= (char *)xmalloc (1 + i
);
1446 strncpy (result
, filename
, i
);
1454 filename_non_directory (name
)
1459 for (i
= strlen (name
) - 1; i
; i
--)
1461 return (xstrdup (name
+ i
+ 1));
1463 return (xstrdup (name
));
1466 /* Return the expansion of FILENAME. */
1468 expand_filename (filename
, input_name
)
1469 char *filename
, *input_name
;
1472 char *full_pathname ();
1475 filename
= full_pathname (filename
);
1478 filename
= filename_non_directory (input_name
);
1483 filename
= xstrdup ("noname.texi");
1486 for (i
= strlen (filename
) - 1; i
; i
--)
1487 if (filename
[i
] == '.')
1491 i
= strlen (filename
);
1493 if (i
+ 6 > (strlen (filename
)))
1494 filename
= (char *)xrealloc (filename
, i
+ 6);
1495 strcpy (filename
+ i
, ".info");
1499 if (filename
[0] == '.' || filename
[0] == '/')
1502 if (filename
[0] != '/' && input_name
[0] == '/')
1504 /* Make it so that relative names work. */
1507 i
= strlen (input_name
) - 1;
1509 result
= (char *)xmalloc (1 + strlen (input_name
) + strlen (filename
));
1510 strcpy (result
, input_name
);
1512 while (result
[i
] != '/' && i
)
1515 if (result
[i
] == '/')
1518 strcpy (&result
[i
], filename
);
1525 /* Return the full path to FILENAME. */
1527 full_pathname (filename
)
1530 int initial_character
;
1533 /* No filename given? */
1534 if (!filename
|| !(initial_character
= *filename
))
1535 return (xstrdup (""));
1537 /* Already absolute? */
1538 if ((initial_character
== '/') ||
1539 ((strncmp (filename
, "./", 2) == 0) ||
1540 (strncmp (filename
, "../", 3) == 0)))
1541 return (xstrdup (filename
));
1543 if (initial_character
!= '~')
1547 localdir
= (char *)xmalloc (1025);
1548 #if defined (HAVE_GETCWD)
1549 if (!getcwd (localdir
, 1024))
1550 #else /* !HAVE_GETCWD */
1551 if (!getwd (localdir
))
1552 #endif /* !HAVE_GETCWD */
1554 fprintf (stderr
, _("%s: getwd: %s, %s\n"),
1555 progname
, filename
, localdir
);
1559 strcat (localdir
, "/");
1560 strcat (localdir
, filename
);
1561 result
= xstrdup (localdir
);
1567 if (filename
[1] == '/')
1569 /* Return the concatenation of the environment variable HOME
1570 and the rest of the string. */
1573 temp_home
= (char *) getenv ("HOME");
1574 result
= (char *)xmalloc (strlen (&filename
[1])
1576 + temp_home
? strlen (temp_home
)
1581 strcpy (result
, temp_home
);
1583 strcat (result
, &filename
[1]);
1587 struct passwd
*user_entry
;
1589 char *username
= (char *)xmalloc (257);
1591 for (i
= 1; (c
= filename
[i
]); i
++)
1596 username
[i
- 1] = c
;
1599 username
[i
- 1] = 0;
1601 user_entry
= getpwnam (username
);
1604 return (xstrdup (filename
));
1606 result
= (char *)xmalloc (1 + strlen (user_entry
->pw_dir
)
1607 + strlen (&filename
[i
]));
1608 strcpy (result
, user_entry
->pw_dir
);
1609 strcat (result
, &filename
[i
]);
1612 #endif /* not WIN32 */
1617 output_name_from_input_name (name
)
1620 return (expand_filename ((char *)NULL
, name
));
1623 /* **************************************************************** */
1625 /* Hacking Tokens and Strings */
1627 /* **************************************************************** */
1629 /* Return the next token as a string pointer. We cons the string. */
1636 /* If the first character to be read is self-delimiting, then that
1637 is the command itself. */
1638 character
= curchar ();
1639 if (self_delimiting (character
))
1641 input_text_offset
++;
1643 if (character
== '\n')
1646 result
= xstrdup (" ");
1647 *result
= character
;
1651 for (i
= 0; ((input_text_offset
!= size_of_input_text
)
1652 && (character
= curchar ())
1653 && command_char (character
));
1654 i
++, input_text_offset
++);
1655 result
= (char *)xmalloc (i
+ 1);
1656 memcpy (result
, &input_text
[input_text_offset
- i
], i
);
1661 /* Return nonzero if CHARACTER is self-delimiting. */
1663 self_delimiting (character
)
1666 /* @; and @\ are not Texinfo commands, but they are listed here
1667 anyway. I don't know why. --karl, 10aug96. */
1668 return member (character
, "~{|}`^\\@?=;:.-,*\'\" !\n\t");
1671 /* Clear whitespace from the front and end of string. */
1673 canon_white (string
)
1676 int len
= strlen (string
);
1682 for (x
= 0; x
< len
; x
++)
1684 if (!cr_or_whitespace (string
[x
]))
1686 strcpy (string
, string
+ x
);
1690 len
= strlen (string
);
1693 while (len
> -1 && cr_or_whitespace (string
[len
]))
1695 string
[len
+ 1] = 0;
1698 /* Bash STRING, replacing all whitespace with just one space. */
1700 fix_whitespace (string
)
1703 char *temp
= (char *)xmalloc (strlen (string
) + 1);
1704 int string_index
= 0;
1708 canon_white (string
);
1710 while (string
[string_index
])
1712 c
= temp
[temp_index
++] = string
[string_index
++];
1714 if (c
== ' ' || c
== '\n' || c
== '\t')
1716 temp
[temp_index
- 1] = ' ';
1717 while ((c
= string
[string_index
]) && (c
== ' ' ||
1723 temp
[temp_index
] = 0;
1724 strcpy (string
, temp
);
1728 /* Discard text until the desired string is found. The string is
1729 included in the discarded text. */
1731 discard_until (string
)
1734 int temp
= search_forward (string
, input_text_offset
);
1736 int tt
= (temp
< 0) ? size_of_input_text
: temp
+ strlen (string
);
1737 int from
= input_text_offset
;
1739 /* Find out what line we are on. */
1741 if (input_text
[from
++] == '\n')
1746 input_text_offset
= size_of_input_text
- strlen (string
);
1748 if (strcmp (string
, "\n") != 0)
1750 line_error (_("Expected `%s'"), string
);
1755 input_text_offset
= temp
;
1757 input_text_offset
+= strlen (string
);
1760 /* Read characters from the file until we are at MATCH.
1761 Place the characters read into STRING.
1762 On exit input_text_offset is after the match string.
1763 Return the offset where the string starts. */
1765 get_until (match
, string
)
1766 char *match
, **string
;
1768 int len
, current_point
, x
, new_point
, tem
;
1770 current_point
= x
= input_text_offset
;
1771 new_point
= search_forward (match
, input_text_offset
);
1774 new_point
= size_of_input_text
;
1775 len
= new_point
- current_point
;
1777 /* Keep track of which line number we are at. */
1778 tem
= new_point
+ (strlen (match
) - 1);
1780 if (input_text
[x
++] == '\n')
1783 *string
= (char *)xmalloc (len
+ 1);
1785 memcpy (*string
, &input_text
[current_point
], len
);
1788 /* Now leave input_text_offset in a consistent state. */
1789 input_text_offset
= tem
;
1791 if (input_text_offset
> size_of_input_text
)
1792 input_text_offset
= size_of_input_text
;
1797 /* Read characters from the file until we are at MATCH or end of line.
1798 Place the characters read into STRING. */
1800 get_until_in_line (expand
, match
, string
)
1802 char *match
, **string
;
1804 int real_bottom
= size_of_input_text
;
1805 int limit
= search_forward ("\n", input_text_offset
);
1807 limit
= size_of_input_text
;
1809 /* Replace input_text[input_text_offset .. limit-1] with its macro
1810 expansion (actually, we expand all commands). This allows the node
1811 names themselves to be constructed via a macro, as in:
1813 Together: \p\ & \q\.
1816 @node @foo{A,B}, next, prev, top
1818 Otherwise, the `,' separating the macro args A and B is taken as
1819 the node argument separator, so the node name is `@foo{A'. This
1820 expansion is only necessary on the first call, since we expand the
1823 Furthermore, if we're executing a string, don't do it -- we'll end
1824 up shrinking the execution string which is currently aliased to
1825 `input_text', so it might get moved, and not updated in the
1826 `execution_strings' array. This happens when processing the
1827 (synthetic) Overview-Footnotes node in the Texinfo manual. */
1829 if (expand
&& !executing_string
&& !me_executing_string
)
1832 unsigned xp_len
, new_len
;
1834 /* Get original string from input. */
1835 unsigned raw_len
= limit
- input_text_offset
;
1836 char *str
= xmalloc (raw_len
+ 1);
1837 strncpy (str
, input_text
+ input_text_offset
, raw_len
);
1841 xp
= expansion (str
, 0);
1842 xp_len
= strlen (xp
);
1845 /* Plunk the expansion into the middle of `input_text' --
1846 which is terminated by a newline, not a null. */
1847 str
= xmalloc (real_bottom
- limit
+ 1);
1848 strncpy (str
, input_text
+ limit
, real_bottom
- limit
+ 1);
1849 new_len
= input_text_offset
+ xp_len
+ real_bottom
- limit
+ 1;
1850 input_text
= xrealloc (input_text
, new_len
);
1851 strcpy (input_text
+ input_text_offset
, xp
);
1852 strncpy (input_text
+ input_text_offset
+ xp_len
, str
,
1853 real_bottom
- limit
+ 1);
1857 limit
+= xp_len
- raw_len
;
1858 real_bottom
+= xp_len
- raw_len
;
1861 size_of_input_text
= limit
;
1862 get_until (match
, string
);
1863 size_of_input_text
= real_bottom
;
1867 get_rest_of_line (string
)
1870 get_until ("\n", string
);
1871 canon_white (*string
);
1873 if (curchar () == '\n') /* as opposed to the end of the file... */
1876 input_text_offset
++;
1880 /* Backup the input pointer to the previous character, keeping track
1881 of the current line number. */
1883 backup_input_pointer ()
1885 if (input_text_offset
)
1887 input_text_offset
--;
1888 if (curchar () == '\n')
1893 /* Read characters from the file until we are at MATCH or closing brace.
1894 Place the characters read into STRING. */
1896 get_until_in_braces (match
, string
)
1897 char *match
, **string
;
1901 int match_len
= strlen (match
);
1903 for (i
= input_text_offset
; i
< size_of_input_text
; i
++)
1905 if (input_text
[i
] == '{')
1907 else if (input_text
[i
] == '}')
1909 else if (input_text
[i
] == '\n')
1913 (brace
== 0 && strncmp (input_text
+ i
, match
, match_len
) == 0))
1917 match_len
= i
- input_text_offset
;
1918 temp
= (char *)xmalloc (2 + match_len
);
1919 strncpy (temp
, input_text
+ input_text_offset
, match_len
);
1920 temp
[match_len
] = 0;
1921 input_text_offset
= i
;
1925 /* **************************************************************** */
1927 /* Converting the File */
1929 /* **************************************************************** */
1931 /* Convert the file named by NAME. The output is saved on the file
1932 named as the argument to the @setfilename command. */
1933 static char *suffixes
[] = {
1942 initialize_conversion ()
1949 /* This is used for splitting the output file and for doing section
1950 headings. It was previously initialized in `init_paragraph', but its
1951 use there loses with the `init_paragraph' calls done by the
1952 multitable code; the tag indices get reset to zero. */
1953 output_position
= 0;
1956 /* We read in multiples of 4k, simply because it is a typical pipe size
1958 #define READ_BUFFER_GROWTH (4 * 4096)
1960 /* Convert the Texinfo file coming from the open stream STREAM. Assume the
1961 source of the stream is named NAME. */
1963 convert_from_stream (stream
, name
)
1967 char *buffer
= (char *)NULL
;
1968 int buffer_offset
= 0, buffer_size
= 0;
1970 initialize_conversion ();
1972 /* Read until the end of the stream. This isn't strictly correct, since
1973 the texinfo input may end before the stream ends, but it is a quick
1974 working hueristic. */
1975 while (!feof (stream
))
1979 if (buffer_offset
+ (READ_BUFFER_GROWTH
+ 1) >= buffer_size
)
1981 xrealloc (buffer
, (buffer_size
+= READ_BUFFER_GROWTH
));
1983 count
= fread (buffer
+ buffer_offset
, 1, READ_BUFFER_GROWTH
, stream
);
1991 buffer_offset
+= count
;
1996 /* Set the globals to the new file. */
1997 input_text
= buffer
;
1998 size_of_input_text
= buffer_offset
;
1999 input_filename
= xstrdup (name
);
2000 node_filename
= xstrdup (name
);
2001 input_text_offset
= 0;
2004 /* Not strictly necessary. This magic prevents read_token () from doing
2005 extra unnecessary work each time it is called (that is a lot of times).
2006 The SIZE_OF_INPUT_TEXT is one past the actual end of the text. */
2007 input_text
[size_of_input_text
] = '\n';
2009 convert_from_loaded_file (name
);
2013 convert_from_file (name
)
2017 char *filename
= (char *)xmalloc (strlen (name
) + 50);
2019 initialize_conversion ();
2021 /* Try to load the file specified by NAME, concatenated with our
2022 various suffixes. Prefer files like `makeinfo.texi' to
2024 for (i
= 0; suffixes
[i
]; i
++)
2026 strcpy (filename
, name
);
2027 strcat (filename
, suffixes
[i
]);
2029 if (find_and_load (filename
))
2032 if (!suffixes
[i
][0] && strrchr (filename
, '.'))
2034 fs_error (filename
);
2047 input_filename
= filename
;
2049 convert_from_loaded_file (name
);
2053 convert_from_loaded_file (name
)
2056 char *expand_filename (), *filename_part ();
2057 char *real_output_filename
= (char *)NULL
;
2059 #if defined (HAVE_MACROS)
2060 remember_itext (input_text
, 0);
2061 #endif /* HAVE_MACROS */
2063 /* Search this file looking for the special string which starts conversion.
2064 Once found, we may truly begin. */
2065 input_text_offset
= 0;
2066 while (input_text_offset
>= 0)
2069 search_forward (setfilename_search
, input_text_offset
);
2071 if ((input_text_offset
== 0) ||
2072 ((input_text_offset
> 0) &&
2073 (input_text
[input_text_offset
-1] == '\n')))
2075 else if (input_text_offset
> 0)
2076 input_text_offset
++;
2079 if (input_text_offset
< 0)
2081 if (!command_output_filename
)
2083 #if defined (REQUIRE_SETFILENAME)
2084 error (_("No `%s' found in `%s'"), setfilename_search
, name
);
2087 register int i
, end_of_first_line
;
2089 /* Find the end of the first line in the file. */
2090 for (i
= 0; i
< size_of_input_text
- 1; i
++)
2091 if (input_text
[i
] == '\n')
2094 end_of_first_line
= i
+ 1;
2096 input_text_offset
= 0;
2098 for (i
= 0; i
< end_of_first_line
; i
++)
2100 if ((input_text
[i
] == '\\') &&
2101 (strncmp (input_text
+ i
+ 1, "include", 7) == 0))
2103 input_text_offset
= end_of_first_line
;
2107 command_output_filename
= output_name_from_input_name (name
);
2108 #endif /* !REQUIRE_SETFILENAME */
2112 input_text_offset
+= strlen (setfilename_search
);
2114 if (!command_output_filename
)
2115 get_until ("\n", &output_filename
);
2118 if (input_text_offset
!= -1)
2119 discard_until ("\n");
2121 input_text_offset
= 0;
2123 real_output_filename
= output_filename
= command_output_filename
;
2124 command_output_filename
= (char *)NULL
;
2127 canon_white (output_filename
);
2129 if (real_output_filename
&& strcmp (real_output_filename
, "-") == 0)
2131 if (macro_expansion_filename
2132 && strcmp (macro_expansion_filename
, "-") == 0)
2134 fprintf (stderr
, _("%s: Skipping macro expansion to stdout as Info output is going there.\n"),
2136 macro_expansion_output_stream
= NULL
;
2138 real_output_filename
= xstrdup (real_output_filename
);
2139 output_stream
= stdout
;
2140 splitting
= 0; /* Cannot split when writing to stdout. */
2144 if (!real_output_filename
)
2145 real_output_filename
= expand_filename (output_filename
, name
);
2147 real_output_filename
= xstrdup (real_output_filename
);
2149 output_stream
= fopen (real_output_filename
, "w");
2152 if (output_stream
!= stdout
)
2153 printf (_("Making %s file `%s' from `%s'.\n"),
2154 no_headers
? "text" : "info", output_filename
, input_filename
);
2156 if (output_stream
== NULL
)
2158 fs_error (real_output_filename
);
2162 /* Make the displayable filename from output_filename. Only the base
2163 portion of the filename need be displayed. */
2164 if (output_stream
!= stdout
)
2165 pretty_output_filename
= filename_part (output_filename
);
2167 pretty_output_filename
= xstrdup ("stdout");
2169 /* For this file only, count the number of newlines from the top of
2170 the file to here. This way, we keep track of line numbers for
2171 error reporting. Line_number starts at 1, since the user isn't
2176 while (temp
!= input_text_offset
)
2177 if (input_text
[temp
++] == '\n')
2183 add_word_args (_("This is Info file %s, produced by Makeinfo version %d.%d"),
2184 output_filename
, major_version
, minor_version
);
2185 add_word_args (_(" from the input file %s.\n"), input_filename
);
2192 discard_insertions (0);
2194 flush_file_stack ();
2196 #if defined (HAVE_MACROS)
2197 if (macro_expansion_output_stream
)
2199 fclose (macro_expansion_output_stream
);
2200 if (errors_printed
&& !force
2201 && strcmp (macro_expansion_filename
, "-") != 0
2202 && strcmp (macro_expansion_filename
, "/dev/null") != 0)
2204 fprintf (stderr
, _("%s: Removing macro output file `%s' due to errors; use --force to preserve.\n"),
2205 progname
, macro_expansion_filename
);
2206 if (unlink (macro_expansion_filename
) < 0)
2207 perror (macro_expansion_filename
);
2210 #endif /* HAVE_MACROS */
2214 output_pending_notes ();
2215 free_pending_notes ();
2216 if (tag_table
!= NULL
)
2218 tag_table
= (TAG_ENTRY
*) reverse_list (tag_table
);
2223 if (output_stream
!= stdout
)
2224 fclose (output_stream
);
2226 /* If validating, then validate the entire file right now. */
2228 validate_file (tag_table
);
2230 if (splitting
&& (!errors_printed
|| force
))
2231 split_file (real_output_filename
, 0);
2232 else if (errors_printed
&& !force
2233 && strcmp (real_output_filename
, "-") != 0
2234 && strcmp (real_output_filename
, "/dev/null") != 0)
2235 { /* If there were errors, and no --force, remove the output. */
2236 fprintf (stderr
, _("%s: Removing output file `%s' due to errors; use --force to preserve.\n"),
2237 progname
, real_output_filename
);
2238 if (unlink (real_output_filename
) < 0)
2239 perror (real_output_filename
);
2242 free (real_output_filename
);
2246 free_and_clear (pointer
)
2252 *pointer
= (char *) NULL
;
2256 /* Initialize some state. */
2260 free_and_clear (&output_filename
);
2261 free_and_clear (&command
);
2262 free_and_clear (&input_filename
);
2263 free_node_references ();
2264 init_insertion_stack ();
2265 init_brace_stack ();
2266 current_node
= NULL
; /* sometimes already freed */
2271 non_top_node_seen
= 0;
2277 free_and_clear (&output_paragraph
);
2278 output_paragraph
= (unsigned char *)xmalloc (paragraph_buffer_len
);
2279 output_paragraph
[0] = 0;
2280 output_paragraph_offset
= 0;
2282 paragraph_is_open
= 0;
2286 /* Okay, we are ready to start the conversion. Call the reader on
2287 some text, and fill the text as it is output. Handle commands by
2288 remembering things like open braces and the current file position on a
2289 stack, and when the corresponding close brace is found, you can call
2290 the function with the proper arguments. */
2300 if (input_text_offset
>= size_of_input_text
)
2303 character
= curchar ();
2305 if (!in_fixed_width_font
&&
2306 (character
== '\'' || character
== '`') &&
2307 input_text
[input_text_offset
+ 1] == character
)
2309 input_text_offset
++;
2313 if (character
== '-')
2316 if (dash_count
== 2 && !in_fixed_width_font
)
2318 input_text_offset
++;
2327 /* If this is a whitespace character, then check to see if the line
2328 is blank. If so, advance to the carriage return. */
2329 if (whitespace (character
))
2331 register int i
= input_text_offset
+ 1;
2333 while (i
< size_of_input_text
&& whitespace (input_text
[i
]))
2336 if (i
== size_of_input_text
|| input_text
[i
] == '\n')
2338 if (i
== size_of_input_text
)
2341 input_text_offset
= i
;
2342 character
= curchar ();
2346 if (character
== '\n')
2350 /* Check for a menu entry here, since the "escape sequence"
2351 that begins menu entries is "\n* ". */
2352 if (in_menu
&& input_text_offset
+ 1 < size_of_input_text
)
2354 char *glean_node_from_menu (), *tem
;
2356 /* Note that the value of TEM is discarded, since it is
2357 gauranteed to be NULL when glean_node_from_menu () is
2358 called with a Nonzero argument. */
2360 tem
= glean_node_from_menu (1);
2366 case COMMAND_PREFIX
:
2371 /* Special case. I'm not supposed to see this character by itself.
2372 If I do, it means there is a syntax error in the input text.
2373 Report the error here, but remember this brace on the stack so
2374 you can ignore its partner. */
2376 line_error (_("Misplaced %c"), '{');
2377 remember_brace (misplaced_brace
);
2379 /* Don't advance input_text_offset since this happens in
2381 input_text_offset++;
2386 pop_and_call_brace ();
2387 input_text_offset
++;
2391 add_char (character
);
2392 input_text_offset
++;
2395 #if defined (HAVE_MACROS)
2396 if (macro_expansion_output_stream
)
2397 maybe_write_itext (input_text
, input_text_offset
);
2398 #endif /* HAVE_MACROS */
2401 /* Find the command corresponding to STRING. If the command
2402 is found, return a pointer to the data structure. Otherwise
2405 get_command_entry (string
)
2410 for (i
= 0; command_table
[i
].name
; i
++)
2411 if (strcmp (command_table
[i
].name
, string
) == 0)
2412 return (&command_table
[i
]);
2414 /* This command is not in our predefined command table. Perhaps
2415 it is a user defined command. */
2416 for (i
= 0; i
< user_command_array_len
; i
++)
2417 if (user_command_array
[i
] &&
2418 (strcmp (user_command_array
[i
]->name
, string
) == 0))
2419 return (user_command_array
[i
]);
2421 /* We never heard of this command. */
2422 return ((COMMAND
*) -1);
2425 /* input_text_offset is right at the command prefix character.
2426 Read the next token to determine what to do. */
2432 input_text_offset
++;
2433 free_and_clear (&command
);
2434 command
= read_token ();
2436 #if defined (HAVE_MACROS)
2437 /* Check to see if this command is a macro. If so, execute it here. */
2441 def
= find_macro (command
);
2445 /* We disallow recursive use of a macro call. Inhibit the expansion
2446 of this macro during the life of its execution. */
2447 if (!(def
->flags
& ME_RECURSE
))
2450 execute_macro (def
);
2452 if (!(def
->flags
& ME_RECURSE
))
2458 #endif /* HAVE_MACROS */
2460 entry
= get_command_entry (command
);
2461 if (entry
== (COMMAND
*)-1)
2463 line_error (_("Unknown command `%s'"), command
);
2467 if (entry
->argument_in_braces
)
2468 remember_brace (entry
->proc
);
2470 (*(entry
->proc
)) (START
, output_paragraph_offset
, 0);
2473 /* Return the string which invokes PROC; a pointer to a function. */
2475 find_proc_name (proc
)
2476 COMMAND_FUNCTION
*proc
;
2480 for (i
= 0; command_table
[i
].name
; i
++)
2481 if (proc
== command_table
[i
].proc
)
2482 return command_table
[i
].name
;
2483 return _("NO_NAME!");
2489 brace_stack
= (BRACE_ELEMENT
*) NULL
;
2493 remember_brace (proc
)
2494 COMMAND_FUNCTION
*proc
;
2496 if (curchar () != '{')
2497 line_error (_("%c%s expected `{...}'"), COMMAND_PREFIX
, command
);
2499 input_text_offset
++;
2500 remember_brace_1 (proc
, output_paragraph_offset
);
2503 /* Remember the current output position here. Save PROC
2504 along with it so you can call it later. */
2506 remember_brace_1 (proc
, position
)
2507 COMMAND_FUNCTION
*proc
;
2510 BRACE_ELEMENT
*new = (BRACE_ELEMENT
*) xmalloc (sizeof (BRACE_ELEMENT
));
2511 new->next
= brace_stack
;
2513 new->pos
= position
;
2514 new->line
= line_number
;
2515 new->in_fixed_width_font
= in_fixed_width_font
;
2519 /* Pop the top of the brace stack, and call the associated function
2520 with the args END and POS. */
2522 pop_and_call_brace ()
2524 BRACE_ELEMENT
*temp
;
2525 COMMAND_FUNCTION
*proc
;
2528 if (brace_stack
== (BRACE_ELEMENT
*) NULL
)
2530 line_error (_("Unmatched }"));
2534 pos
= brace_stack
->pos
;
2535 proc
= brace_stack
->proc
;
2536 in_fixed_width_font
= brace_stack
->in_fixed_width_font
;
2537 temp
= brace_stack
->next
;
2541 (*proc
) (END
, pos
, output_paragraph_offset
);
2544 /* Shift all of the markers in `brace_stack' by AMOUNT. */
2546 adjust_braces_following (here
, amount
)
2549 register BRACE_ELEMENT
*stack
= brace_stack
;
2553 if (stack
->pos
>= here
)
2554 stack
->pos
+= amount
;
2555 stack
= stack
->next
;
2559 /* You call discard_braces () when you shouldn't have any braces on the stack.
2560 I used to think that this happens for commands that don't take arguments
2561 in braces, but that was wrong because of things like @code{foo @@}. So now
2562 I only detect it at the beginning of nodes. */
2571 if (brace_stack
->proc
!= misplaced_brace
)
2574 int temp_line_number
= line_number
;
2576 line_number
= brace_stack
->line
;
2577 proc_name
= find_proc_name (brace_stack
->proc
);
2578 line_error (_("%c%s missing close brace"), COMMAND_PREFIX
, proc_name
);
2579 line_number
= temp_line_number
;
2580 pop_and_call_brace ();
2584 BRACE_ELEMENT
*temp
;
2585 temp
= brace_stack
->next
;
2593 get_char_len (character
)
2596 /* Return the printed length of the character. */
2602 len
= (output_column
+ 8) & 0xf7;
2603 if (len
> fill_column
)
2604 len
= fill_column
- output_column
;
2606 len
= len
- output_column
;
2610 len
= fill_column
- output_column
;
2614 /* ASCII control characters appear as two characters in the output
2615 (e.g., ^A). But characters with the high bit set are just one
2616 on suitable terminals, so don't count them as two for line
2617 breaking purposes. */
2618 if (0 <= character
&& character
< ' ')
2627 #if defined (VA_FPRINTF) && __STDC__
2628 add_word_args (char *format
, ...)
2630 add_word_args (format
, va_alist
)
2640 VA_START (ap
, format
);
2642 VA_SPRINTF (buffer
, format
, ap
);
2644 sprintf (buffer
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
);
2645 #endif /* not VA_SPRINTF */
2650 /* Add STRING to output_paragraph. */
2656 add_char (*string
++);
2659 /* Nonzero if the last character inserted has the syntax class of NEWLINE. */
2660 int last_char_was_newline
= 1;
2662 /* The actual last inserted character. Note that this may be something
2663 other than NEWLINE even if last_char_was_newline is 1. */
2664 int last_inserted_character
= 0;
2666 /* Nonzero means that a newline character has already been
2667 inserted, so close_paragraph () should insert one less. */
2668 int line_already_broken
= 0;
2670 /* When nonzero we have finished an insertion (see `end_insertion') and we
2671 want to ignore false continued paragraph closings. */
2672 int insertion_paragraph_closed
= 0;
2674 /* Nonzero means attempt to make all of the lines have fill_column width. */
2675 int do_justification
= 0;
2677 /* Add the character to the current paragraph. If filling_enabled is
2678 nonzero, then do filling as well. */
2680 add_char (character
)
2683 /* If we are avoiding outputting headers, and we are currently
2684 in a menu, then simply return. */
2685 if (no_headers
&& (in_menu
|| in_detailmenu
))
2688 /* If we are adding a character now, then we don't have to
2689 ignore close_paragraph () calls any more. */
2690 if (must_start_paragraph
&& character
!= '\n')
2692 must_start_paragraph
= 0;
2693 line_already_broken
= 0; /* The line is no longer broken. */
2694 if (current_indent
> output_column
)
2696 indent (current_indent
- output_column
);
2697 output_column
= current_indent
;
2701 if (non_splitting_words
&& member (character
, " \t\n"))
2702 character
= ' ' | 0x80;
2704 insertion_paragraph_closed
= 0;
2709 if (!filling_enabled
)
2713 if (force_flush_right
)
2716 /* Hack to force single blank lines out in this mode. */
2722 if (!no_indent
&& paragraph_is_open
)
2723 indent (output_column
= current_indent
);
2726 else /* CHARACTER is newline, and filling is enabled. */
2728 if (end_of_sentence_p ())
2732 last_inserted_character
= character
;
2736 if (last_char_was_newline
)
2743 last_char_was_newline
= 1;
2751 int len
= get_char_len (character
);
2752 int suppress_insert
= 0;
2754 if ((character
== ' ') && (last_char_was_newline
))
2756 if (!paragraph_is_open
)
2763 if (!paragraph_is_open
)
2767 /* If the paragraph is supposed to be indented a certain way,
2768 then discard all of the pending whitespace. Otherwise, we
2769 let the whitespace stay. */
2770 if (!paragraph_start_indent
)
2771 indent (pending_indent
);
2775 if ((output_column
+= len
) > fill_column
)
2777 if (filling_enabled
)
2779 int temp
= output_paragraph_offset
;
2780 while (--temp
> 0 && output_paragraph
[temp
] != '\n')
2782 /* If we have found a space, we have the place to break
2784 if (output_paragraph
[temp
] == ' ')
2786 /* Remove trailing whitespace from output. */
2787 while (temp
&& whitespace (output_paragraph
[temp
- 1]))
2790 output_paragraph
[temp
++] = '\n';
2792 /* We have correctly broken the line where we want
2793 to. What we don't want is spaces following where
2794 we have decided to break the line. We get rid of
2801 if (t1
== output_paragraph_offset
)
2803 if (whitespace (character
))
2804 suppress_insert
= 1;
2807 if (!whitespace (output_paragraph
[t1
]))
2813 adjust_braces_following (temp
, (- (t1
- temp
)));
2814 strncpy ((char *) &output_paragraph
[temp
],
2815 (char *) &output_paragraph
[t1
],
2816 (output_paragraph_offset
- t1
));
2817 output_paragraph_offset
-= (t1
- temp
);
2821 /* Filled, but now indent if that is right. */
2822 if (indented_fill
&& current_indent
)
2824 int buffer_len
= ((output_paragraph_offset
- temp
)
2826 char *temp_buffer
= (char *)xmalloc (buffer_len
);
2827 int indentation
= 0;
2829 /* We have to shift any markers that are in
2830 front of the wrap point. */
2831 adjust_braces_following (temp
, current_indent
);
2833 while (current_indent
> 0 &&
2834 indentation
!= current_indent
)
2835 temp_buffer
[indentation
++] = ' ';
2837 strncpy ((char *) &temp_buffer
[current_indent
],
2838 (char *) &output_paragraph
[temp
],
2839 buffer_len
- current_indent
);
2841 if (output_paragraph_offset
+ buffer_len
2842 >= paragraph_buffer_len
)
2844 unsigned char *tt
= xrealloc
2846 (paragraph_buffer_len
+= buffer_len
));
2847 output_paragraph
= tt
;
2849 strncpy ((char *) &output_paragraph
[temp
],
2850 temp_buffer
, buffer_len
);
2851 output_paragraph_offset
+= current_indent
;
2855 while (temp
< output_paragraph_offset
)
2857 get_char_len (output_paragraph
[temp
++]);
2858 output_column
+= len
;
2865 if (!suppress_insert
)
2868 last_inserted_character
= character
;
2870 last_char_was_newline
= 0;
2871 line_already_broken
= 0;
2876 /* Insert CHARACTER into `output_paragraph'. */
2881 output_paragraph
[output_paragraph_offset
++] = character
;
2882 if (output_paragraph_offset
== paragraph_buffer_len
)
2885 xrealloc (output_paragraph
, (paragraph_buffer_len
+= 100));
2889 /* Insert the null-terminated string STRING into `output_paragraph'. */
2891 insert_string (string
)
2899 /* Sentences might have these characters after the period (or whatever). */
2900 #define post_sentence(c) ((c) == ')' || (c) == '\'' || (c) == '"' \
2903 /* Return true if at an end-of-sentence character, possibly followed by
2904 post-sentence punctuation to ignore. */
2906 end_of_sentence_p ()
2908 int loc
= output_paragraph_offset
- 1;
2909 while (loc
> 0 && post_sentence (output_paragraph
[loc
]))
2911 return sentence_ender (output_paragraph
[loc
]);
2915 /* Remove up to COUNT characters of whitespace from the
2916 current output line. If COUNT is less than zero,
2917 then remove until none left. */
2919 kill_self_indent (count
)
2922 /* Handle infinite case first. */
2926 while (output_paragraph_offset
)
2928 if (whitespace (output_paragraph
[output_paragraph_offset
- 1]))
2929 output_paragraph_offset
--;
2936 while (output_paragraph_offset
&& count
--)
2937 if (whitespace (output_paragraph
[output_paragraph_offset
- 1]))
2938 output_paragraph_offset
--;
2944 /* Nonzero means do not honor calls to flush_output (). */
2945 static int flushing_ignored
= 0;
2947 /* Prevent calls to flush_output () from having any effect. */
2949 inhibit_output_flushing ()
2954 /* Allow calls to flush_output () to write the paragraph data. */
2956 uninhibit_output_flushing ()
2966 if (!output_paragraph_offset
|| flushing_ignored
)
2969 for (i
= 0; i
< output_paragraph_offset
; i
++)
2971 /* If we turned on the 8th bit for a space
2972 inside @w, turn it back off for output. */
2973 if (output_paragraph
[i
] & meta_character_bit
)
2975 int temp
= UNMETA (output_paragraph
[i
]);
2977 output_paragraph
[i
] &= 0x7f;
2981 fwrite (output_paragraph
, 1, output_paragraph_offset
, output_stream
);
2983 output_position
+= output_paragraph_offset
;
2984 output_paragraph_offset
= 0;
2987 /* How to close a paragraph controlling the number of lines between
2988 this one and the last one. */
2990 /* Paragraph spacing is controlled by this variable. It is the number of
2991 blank lines that you wish to appear between paragraphs. A value of
2992 1 creates a single blank line between paragraphs. */
2993 int paragraph_spacing
= DEFAULT_PARAGRAPH_SPACING
;
2995 /* Close the current paragraph, leaving no blank lines between them. */
2997 close_single_paragraph ()
2999 close_paragraph_with_lines (0);
3002 /* Close a paragraph after an insertion has ended. */
3004 close_insertion_paragraph ()
3006 if (!insertion_paragraph_closed
)
3008 /* Close the current paragraph, breaking the line. */
3009 close_single_paragraph ();
3011 /* Start a new paragraph, with the correct indentation for the now
3012 current insertion level (one above the one that we are ending). */
3015 /* Tell `close_paragraph' that the previous line has already been
3016 broken, so it should insert one less newline. */
3017 line_already_broken
= 1;
3019 /* Tell functions such as `add_char' we've already found a newline. */
3020 ignore_blank_line ();
3024 /* If the insertion paragraph is closed already, then we are seeing
3025 two `@end' commands in a row. Note that the first one we saw was
3026 handled in the first part of this if-then-else clause, and at that
3027 time `start_paragraph' was called, partially to handle the proper
3028 indentation of the current line. However, the indentation level
3029 may have just changed again, so we may have to outdent the current
3030 line to the new indentation level. */
3031 if (current_indent
< output_column
)
3032 kill_self_indent (output_column
- current_indent
);
3035 insertion_paragraph_closed
= 1;
3039 close_paragraph_with_lines (lines
)
3042 int old_spacing
= paragraph_spacing
;
3043 paragraph_spacing
= lines
;
3045 paragraph_spacing
= old_spacing
;
3048 /* Close the currently open paragraph. */
3054 /* The insertion paragraph is no longer closed. */
3055 insertion_paragraph_closed
= 0;
3057 if (paragraph_is_open
&& !must_start_paragraph
)
3059 register int tindex
, c
;
3061 tindex
= output_paragraph_offset
;
3063 /* Back up to last non-newline/space character, forcing all such
3064 subsequent characters to be newlines. This isn't strictly
3065 necessary, but a couple of functions use the presence of a newline
3066 to make decisions. */
3067 for (tindex
= output_paragraph_offset
- 1; tindex
>= 0; --tindex
)
3069 c
= output_paragraph
[tindex
];
3071 if (c
== ' '|| c
== '\n')
3072 output_paragraph
[tindex
] = '\n';
3077 /* All trailing whitespace is ignored. */
3078 output_paragraph_offset
= ++tindex
;
3080 /* Break the line if that is appropriate. */
3081 if (paragraph_spacing
>= 0)
3084 /* Add as many blank lines as is specified in `paragraph_spacing'. */
3085 if (!force_flush_right
)
3087 for (i
= 0; i
< (paragraph_spacing
- line_already_broken
); i
++)
3091 /* If we are doing flush right indentation, then do it now
3092 on the paragraph (really a single line). */
3093 if (force_flush_right
)
3094 do_flush_right_indentation ();
3097 paragraph_is_open
= 0;
3101 ignore_blank_line ();
3104 /* Make the last line just read look as if it were only a newline. */
3106 ignore_blank_line ()
3108 last_inserted_character
= '\n';
3109 last_char_was_newline
= 1;
3112 /* Align the end of the text in output_paragraph with fill_column. */
3114 do_flush_right_indentation ()
3119 kill_self_indent (-1);
3121 if (output_paragraph
[0] != '\n')
3123 output_paragraph
[output_paragraph_offset
] = 0;
3125 if (output_paragraph_offset
< fill_column
)
3129 if (fill_column
>= paragraph_buffer_len
)
3131 xrealloc (output_paragraph
,
3132 (paragraph_buffer_len
+= fill_column
));
3134 temp_len
= strlen ((char *)output_paragraph
);
3135 temp
= (char *)xmalloc (temp_len
+ 1);
3136 memcpy (temp
, (char *)output_paragraph
, temp_len
);
3138 for (i
= 0; i
< fill_column
- output_paragraph_offset
; i
++)
3139 output_paragraph
[i
] = ' ';
3141 memcpy ((char *)output_paragraph
+ i
, temp
, temp_len
);
3143 output_paragraph_offset
= fill_column
;
3148 /* Begin a new paragraph. */
3152 /* First close existing one. */
3153 if (paragraph_is_open
)
3156 /* In either case, the insertion paragraph is no longer closed. */
3157 insertion_paragraph_closed
= 0;
3159 /* However, the paragraph is open! */
3160 paragraph_is_open
= 1;
3162 /* If we MUST_START_PARAGRAPH, that simply means that start_paragraph ()
3163 had to be called before we would allow any other paragraph operations
3164 to have an effect. */
3165 if (!must_start_paragraph
)
3167 int amount_to_indent
= 0;
3169 /* If doing indentation, then insert the appropriate amount. */
3172 if (inhibit_paragraph_indentation
)
3174 amount_to_indent
= current_indent
;
3175 if (inhibit_paragraph_indentation
< 0)
3176 inhibit_paragraph_indentation
++;
3178 else if (paragraph_start_indent
< 0)
3179 amount_to_indent
= current_indent
;
3181 amount_to_indent
= current_indent
+ paragraph_start_indent
;
3183 if (amount_to_indent
>= output_column
)
3185 amount_to_indent
-= output_column
;
3186 indent (amount_to_indent
);
3187 output_column
+= amount_to_indent
;
3192 must_start_paragraph
= 0;
3195 /* Insert the indentation specified by AMOUNT. */
3200 register BRACE_ELEMENT
*elt
= brace_stack
;
3202 /* For every START_POS saved within the brace stack which will be affected
3203 by this indentation, bump that start pos forward. */
3206 if (elt
->pos
>= output_paragraph_offset
)
3211 while (--amount
>= 0)
3215 /* Search forward for STRING in input_text.
3216 FROM says where to start. */
3218 search_forward (string
, from
)
3222 int len
= strlen (string
);
3224 while (from
< size_of_input_text
)
3226 if (strncmp (input_text
+ from
, string
, len
) == 0)
3233 /* Whoops, Unix doesn't have strcasecmp. */
3235 /* Case independent string compare. */
3236 #if !defined (HAVE_STRCASECMP)
3238 strcasecmp (string1
, string2
)
3239 char *string1
, *string2
;
3251 ch1
= coerce_to_upper (ch1
);
3252 ch2
= coerce_to_upper (ch2
);
3258 #endif /* !HAVE_STRCASECMP */
3261 init_insertion_stack ()
3263 insertion_stack
= (INSERTION_ELT
*) NULL
;
3266 /* Return the type of the current insertion. */
3268 current_insertion_type ()
3270 if (!insertion_level
)
3273 return (insertion_stack
->insertion
);
3276 /* Return a pointer to the string which is the function to wrap around
3279 current_item_function ()
3281 register int level
, done
;
3282 register INSERTION_ELT
*elt
;
3284 level
= insertion_level
;
3285 elt
= insertion_stack
;
3288 /* Skip down through the stack until we find a non-conditional insertion. */
3289 while (!done
&& (elt
!= NULL
))
3291 switch (elt
->insertion
)
3309 return ((char *) NULL
);
3311 return (elt
->item_function
);
3315 get_item_function ()
3317 char *item_function
;
3318 get_rest_of_line (&item_function
);
3319 backup_input_pointer ();
3320 return (item_function
);
3323 /* Push the state of the current insertion on the stack. */
3325 push_insertion (type
, item_function
)
3326 enum insertion_type type
;
3327 char *item_function
;
3329 INSERTION_ELT
*new = (INSERTION_ELT
*) xmalloc (sizeof (INSERTION_ELT
));
3331 new->item_function
= item_function
;
3332 new->filling_enabled
= filling_enabled
;
3333 new->indented_fill
= indented_fill
;
3334 new->insertion
= type
;
3335 new->line_number
= line_number
;
3336 new->filename
= xstrdup (input_filename
);
3337 new->inhibited
= inhibit_paragraph_indentation
;
3338 new->in_fixed_width_font
= in_fixed_width_font
;
3339 new->next
= insertion_stack
;
3340 insertion_stack
= new;
3344 /* Pop the value on top of the insertion stack into the
3345 global variables. */
3349 INSERTION_ELT
*temp
= insertion_stack
;
3351 if (temp
== (INSERTION_ELT
*) NULL
)
3354 in_fixed_width_font
= temp
->in_fixed_width_font
;
3355 inhibit_paragraph_indentation
= temp
->inhibited
;
3356 filling_enabled
= temp
->filling_enabled
;
3357 indented_fill
= temp
->indented_fill
;
3358 free_and_clear (&(temp
->item_function
));
3359 free_and_clear (&(temp
->filename
));
3360 insertion_stack
= insertion_stack
->next
;
3365 /* Return a pointer to the print name of this
3368 insertion_type_pname (type
)
3369 enum insertion_type type
;
3371 if ((int) type
< (int) bad_type
)
3372 return (insertion_type_names
[(int) type
]);
3374 return (_("Broken-Type in insertion_type_pname"));
3377 /* Return the insertion_type associated with NAME.
3378 If the type is not one of the known ones, return BAD_TYPE. */
3380 find_type_from_name (name
)
3384 while (index
< (int) bad_type
)
3386 if (strcmp (name
, insertion_type_names
[index
]) == 0)
3387 return (enum insertion_type
) index
;
3394 defun_insertion (type
)
3395 enum insertion_type type
;
3401 || (type
== defspec
)
3405 || (type
== deftypefn
)
3406 || (type
== deftypefun
)
3407 || (type
== deftypevr
)
3408 || (type
== deftypevar
)
3410 || (type
== defivar
)
3412 || (type
== defmethod
)
3413 || (type
== deftypemethod
)
3414 || (type
== deftp
));
3417 /* MAX_NS is the maximum nesting level for enumerations. I picked 100
3418 which seemed reasonable. This doesn't control the number of items,
3419 just the number of nested lists. */
3420 #define max_stack_depth 100
3421 #define ENUM_DIGITS 1
3422 #define ENUM_ALPHA 2
3428 DIGIT_ALPHA enumstack
[max_stack_depth
];
3429 int enumstack_offset
= 0;
3430 int current_enumval
= 1;
3431 int current_enumtype
= ENUM_DIGITS
;
3432 char *enumeration_arg
= (char *)NULL
;
3435 start_enumerating (at
, type
)
3438 if ((enumstack_offset
+ 1) == max_stack_depth
)
3440 line_error (_("Enumeration stack overflow"));
3443 enumstack
[enumstack_offset
].enumtype
= current_enumtype
;
3444 enumstack
[enumstack_offset
].enumval
= current_enumval
;
3446 current_enumval
= at
;
3447 current_enumtype
= type
;
3454 if (enumstack_offset
< 0)
3455 enumstack_offset
= 0;
3457 current_enumval
= enumstack
[enumstack_offset
].enumval
;
3458 current_enumtype
= enumstack
[enumstack_offset
].enumtype
;
3461 /* Place a letter or digits into the output stream. */
3467 if (current_enumtype
== ENUM_ALPHA
)
3469 if (current_enumval
== ('z' + 1) || current_enumval
== ('Z' + 1))
3471 current_enumval
= ((current_enumval
- 1) == 'z' ? 'a' : 'A');
3472 warning (_("lettering overflow, restarting at %c"), current_enumval
);
3474 sprintf (temp
, "%c. ", current_enumval
);
3477 sprintf (temp
, "%d. ", current_enumval
);
3479 indent (output_column
+= (current_indent
- strlen (temp
)));
3484 /* This is where the work for all the "insertion" style
3485 commands is done. A huge switch statement handles the
3486 various setups, and generic code is on both sides. */
3488 begin_insertion (type
)
3489 enum insertion_type type
;
3493 if (defun_insertion (type
))
3495 push_insertion (type
, xstrdup (""));
3499 push_insertion (type
, get_item_function ());
3507 filling_enabled
= no_indent
= 0;
3508 inhibit_paragraph_indentation
= 1;
3511 add_word (_("* Menu:\n"));
3523 filling_enabled
= no_indent
= 0;
3524 inhibit_paragraph_indentation
= 1;
3533 close_single_paragraph ();
3534 filling_enabled
= no_indent
= 0;
3535 inhibit_paragraph_indentation
= 1;
3536 insert_string ("START-INFO-DIR-ENTRY\n");
3539 /* I think @quotation is meant to do filling.
3540 If you don't want filling, then use @display. */
3542 close_single_paragraph ();
3543 last_char_was_newline
= no_indent
= 0;
3544 indented_fill
= filling_enabled
= 1;
3545 inhibit_paragraph_indentation
= 1;
3546 current_indent
+= default_indentation_increment
;
3554 /* Just like @example, but no indentation. */
3556 close_single_paragraph ();
3557 inhibit_paragraph_indentation
= 1;
3558 in_fixed_width_font
++;
3559 filling_enabled
= 0;
3560 last_char_was_newline
= 0;
3562 current_indent
+= default_indentation_increment
;
3573 close_single_paragraph ();
3574 current_indent
+= default_indentation_increment
;
3575 filling_enabled
= indented_fill
= 1;
3576 #if defined (INDENT_PARAGRAPHS_IN_TABLE)
3577 inhibit_paragraph_indentation
= 0;
3579 inhibit_paragraph_indentation
= 1;
3580 #endif /* !INDENT_PARAGRAPHS_IN_TABLE */
3582 /* Make things work for losers who forget the itemize syntax. */
3583 if (allow_lax_format
&& (type
== itemize
))
3585 if (!(*insertion_stack
->item_function
))
3587 free (insertion_stack
->item_function
);
3588 insertion_stack
->item_function
= xstrdup ("@bullet");
3589 insertion_stack
->item_function
[0] = COMMAND_PREFIX
;
3593 if (!*insertion_stack
->item_function
)
3595 line_error (_("%s requires an argument: the formatter for %citem"),
3596 insertion_type_pname (type
), COMMAND_PREFIX
);
3601 close_single_paragraph ();
3603 #if defined (INDENT_PARAGRAPHS_IN_TABLE)
3604 inhibit_paragraph_indentation
= 0;
3606 inhibit_paragraph_indentation
= 1;
3607 #endif /* !INDENT_PARAGRAPHS_IN_TABLE */
3609 current_indent
+= default_indentation_increment
;
3610 filling_enabled
= indented_fill
= 1;
3612 if (isdigit (*enumeration_arg
))
3613 start_enumerating (atoi (enumeration_arg
), ENUM_DIGITS
);
3615 start_enumerating (*enumeration_arg
, ENUM_ALPHA
);
3618 /* Does nothing special in makeinfo. */
3620 /* Only close the paragraph if we are not inside of an @example. */
3621 if (!insertion_stack
->next
||
3622 insertion_stack
->next
->insertion
!= example
)
3623 close_single_paragraph ();
3626 /* Insertions that are no-ops in info, but do something in TeX. */
3654 inhibit_paragraph_indentation
= 1;
3655 filling_enabled
= indented_fill
= 1;
3656 current_indent
+= default_indentation_increment
;
3661 close_single_paragraph ();
3662 inhibit_paragraph_indentation
= 1;
3663 filling_enabled
= indented_fill
= no_indent
= 0;
3667 close_single_paragraph ();
3668 filling_enabled
= indented_fill
= no_indent
= 0;
3669 inhibit_paragraph_indentation
= 1;
3670 force_flush_right
++;
3675 discard_until ("\n");
3678 /* Try to end the insertion with the specified TYPE. With a value of
3679 `bad_type', TYPE gets translated to match the value currently on top
3680 of the stack. Otherwise, if TYPE doesn't match the top of the
3681 insertion stack, give error. */
3683 end_insertion (type
)
3684 enum insertion_type type
;
3686 enum insertion_type temp_type
;
3688 if (!insertion_level
)
3691 temp_type
= current_insertion_type ();
3693 if (type
== bad_type
)
3696 if (type
!= temp_type
)
3699 (_("`%cend' expected `%s', but saw `%s'"), COMMAND_PREFIX
,
3700 insertion_type_pname (temp_type
), insertion_type_pname (type
));
3708 /* Insertions which have no effect on paragraph formatting. */
3717 insert_string ("END-INFO-DIR-ENTRY\n\n");
3718 close_insertion_paragraph ();
3722 in_detailmenu
--; /* No longer hacking menus. */
3726 close_insertion_paragraph ();
3731 in_menu
--; /* No longer hacking menus. */
3733 close_insertion_paragraph ();
3741 stop_enumerating ();
3742 close_insertion_paragraph ();
3743 current_indent
-= default_indentation_increment
;
3749 close_insertion_paragraph ();
3759 /* @format is the only fixed_width insertion without a change
3762 current_indent
-= default_indentation_increment
;
3764 /* The ending of one of these insertions always marks the
3765 start of a new paragraph. */
3766 close_insertion_paragraph ();
3773 current_indent
-= default_indentation_increment
;
3777 force_flush_right
--;
3778 close_insertion_paragraph ();
3781 /* Handle the @defun style insertions with a default clause. */
3783 current_indent
-= default_indentation_increment
;
3784 close_insertion_paragraph ();
3789 /* Insertions cannot cross certain boundaries, such as node beginnings. In
3790 code that creates such boundaries, you should call `discard_insertions'
3791 before doing anything else. It prints the errors for you, and cleans up
3792 the insertion stack. With nonzero SPECIALS_OK, allows unmatched
3793 ifinfo, ifset, ifclear, otherwise not. */
3795 discard_insertions (specials_ok
)
3798 int real_line_number
= line_number
;
3799 while (insertion_stack
)
3801 if (specials_ok
&& (insertion_stack
->insertion
== ifinfo
3802 || insertion_stack
->insertion
== ifset
3803 || insertion_stack
->insertion
== ifclear
))
3807 char *offender
= insertion_type_pname (insertion_stack
->insertion
);
3808 char *current_filename
= input_filename
;
3810 input_filename
= insertion_stack
->filename
;
3811 line_number
= insertion_stack
->line_number
;
3812 line_error (_("No matching `%cend %s'"), COMMAND_PREFIX
, offender
);
3813 input_filename
= current_filename
;
3817 line_number
= real_line_number
;
3820 /* The Texinfo commands. */
3822 /* Commands which insert their own names. */
3839 /* Force a line break in the output. */
3843 close_single_paragraph ();
3847 /* Insert ellipsis. */
3856 /* Insert ellipsis for sentence end. */
3890 /* Copyright symbol. */
3899 /* Accent commands that take explicit arguments. */
3906 if (strcmp (command
, "dotaccent") == 0) /* overdot */
3908 else if (strcmp (command
, "H") == 0) /* Hungarian umlaut */
3910 else if (strcmp (command
, "ringaccent") == 0)
3912 else if (strcmp (command
, "tieaccent") == 0)
3914 else if (strcmp (command
, "u") == 0) /* breve */
3916 else if (strcmp (command
, "v") == 0) /* hacek/check */
3919 else if (arg
== END
)
3921 if (strcmp (command
, "ubaraccent") == 0) /* underbar */
3923 else if (strcmp (command
, "udotaccent") == 0) /* underdot */
3925 else if (strcmp (command
, ",") == 0) /* cedilla */
3930 /* Non-English letters/characters that don't insert themselves. */
3932 cm_special_char (arg
)
3936 if ((*command
== 'L' || *command
== 'l'
3937 || *command
== 'O' || *command
== 'o')
3940 /* Lslash lslash Oslash oslash */
3941 add_char (*command
);
3944 else if (strcmp (command
, "exclamdown") == 0)
3946 else if (strcmp (command
, "pounds") == 0)
3948 else if (strcmp (command
, "questiondown") == 0)
3951 fprintf (stderr
, _("How did @%s end up in cm_special_char?\n"), command
);
3955 /* Dotless i or j. */
3957 cm_dotless (arg
, start
, end
)
3958 int arg
, start
, end
;
3962 if (output_paragraph
[start
] != 'i' && output_paragraph
[start
] != 'j')
3963 /* This error message isn't perfect if the argument is multiple
3964 characters, but it doesn't seem worth getting right. */
3965 line_error (_("%c%s expects `i' or `j' as argument, not `%c'"),
3966 COMMAND_PREFIX
, command
, output_paragraph
[start
]);
3968 else if (end
- start
!= 1)
3969 line_error (_("%c%s expects a single character `i' or `j' as argument"),
3970 COMMAND_PREFIX
, command
);
3972 /* We've already inserted the `i' or `j', so nothing to do. */
3980 static char *months
[12] =
3981 { N_("January"), N_("February"), N_("March"), N_("April"), N_("May"),
3982 N_("June"), N_("July"), N_("August"), N_("September"), N_("October"),
3983 N_("November"), N_("December") };
3986 time_t timer
= time (0);
3987 struct tm
*ts
= localtime (&timer
);
3988 add_word_args ("%d %s %d", ts
->tm_mday
, _(months
[ts
->tm_mon
]),
3989 ts
->tm_year
+ 1900);
3997 extern int printing_index
;
4001 in_fixed_width_font
++;
4003 if (!printing_index
)
4008 if (!printing_index
)
4017 /* People use @kbd in an example to get the "user input" font.
4018 We don't want quotes in that case. */
4019 if (!in_fixed_width_font
)
4027 add_char (arg
== START
? '<' : '>');
4030 /* Convert the character at position into a true control character. */
4032 cm_ctrl (arg
, start
, end
)
4033 int arg
, start
, end
;
4035 /* Should we allow multiple character arguments? I think yes. */
4038 register int i
, character
;
4039 #if defined (NO_MULTIPLE_CTRL)
4040 if ((end
- start
) != 1)
4041 line_error (_("%c%s expects a single character as an argument"),
4042 COMMAND_PREFIX
, command
);
4045 for (i
= start
; i
< end
; i
++)
4047 character
= output_paragraph
[i
];
4049 if (isletter (character
))
4050 output_paragraph
[i
] = CTL (coerce_to_upper (character
));
4055 /* Handle a command that switches to a non-fixed-width font. */
4057 not_fixed_width (arg
)
4061 in_fixed_width_font
= 0;
4064 /* Small caps and @var in makeinfo just uppercase the text. */
4066 cm_var_sc (arg
, start_pos
, end_pos
)
4067 int arg
, start_pos
, end_pos
;
4069 not_fixed_width (arg
);
4073 while (start_pos
< end_pos
)
4075 output_paragraph
[start_pos
] =
4076 coerce_to_upper (output_paragraph
[start_pos
]);
4083 cm_dfn (arg
, position
)
4097 cm_strong (arg
, position
)
4104 cm_cite (arg
, position
)
4113 /* No highlighting, but argument switches fonts. */
4115 cm_not_fixed_width (arg
, start
, end
)
4116 int arg
, start
, end
;
4118 not_fixed_width (arg
);
4121 /* Various commands are no-op's. */
4127 /* No-op that eats its argument on same line. */
4129 cm_no_op_line_arg ()
4132 get_rest_of_line (&temp
);
4136 /* Prevent the argument from being split across two lines. */
4138 cm_w (arg
, start
, end
)
4139 int arg
, start
, end
;
4142 non_splitting_words
++;
4144 non_splitting_words
--;
4148 /* Explain that this command is obsolete, thus the user shouldn't
4149 do anything with it. */
4151 cm_obsolete (arg
, start
, end
)
4152 int arg
, start
, end
;
4155 warning (_("%c%s is obsolete"), COMMAND_PREFIX
, command
);
4158 /* Insert the text following input_text_offset up to the end of the line
4159 in a new, separate paragraph. Directly underneath it, insert a
4160 line of WITH_CHAR, the same length of the inserted text. */
4162 insert_and_underscore (with_char
)
4165 register int i
, len
;
4166 int old_no_indent
, starting_pos
, ending_pos
;
4170 filling_enabled
= indented_fill
= 0;
4171 old_no_indent
= no_indent
;
4174 #if defined (HAVE_MACROS)
4175 if (macro_expansion_output_stream
&& !executing_string
)
4176 append_to_expansion_output (input_text_offset
+ 1);
4177 #endif /* HAVE_MACROS */
4179 get_rest_of_line (&temp
);
4181 starting_pos
= output_position
+ output_paragraph_offset
;
4182 #if defined (HAVE_MACROS)
4183 if (macro_expansion_output_stream
&& !executing_string
)
4185 char *temp1
= (char *) xmalloc (2 + strlen (temp
));
4186 sprintf (temp1
, "%s\n", temp
);
4187 remember_itext (input_text
, input_text_offset
);
4188 me_execute_string (temp1
);
4192 #endif /* HAVE_MACROS */
4193 execute_string ("%s\n", temp
);
4195 ending_pos
= output_position
+ output_paragraph_offset
;
4198 len
= (ending_pos
- starting_pos
) - 1;
4199 for (i
= 0; i
< len
; i
++)
4200 add_char (with_char
);
4203 filling_enabled
= 1;
4204 no_indent
= old_no_indent
;
4207 /* Here is a structure which associates sectioning commands with
4208 an integer, hopefully to reflect the `depth' of the current
4213 } section_alist
[] = {
4214 { "unnumberedsubsubsec", 5 },
4215 { "unnumberedsubsec", 4 },
4216 { "unnumberedsec", 3 },
4217 { "unnumbered", 2 },
4218 { "appendixsubsubsec", 5 },
4219 { "appendixsubsec", 4 },
4220 { "appendixsec", 3 },
4221 { "appendixsection", 3 },
4224 { "subsubsection", 5 },
4225 { "subsection", 4 },
4233 /* Amount to offset the name of sectioning commands to levels by. */
4234 int section_alist_offset
= 0;
4236 /* Shift the meaning of @section to @chapter. */
4240 discard_until ("\n");
4241 section_alist_offset
--;
4244 /* Shift the meaning of @chapter to @section. */
4248 discard_until ("\n");
4249 section_alist_offset
++;
4252 /* Return an integer which identifies the type section present in TEXT. */
4260 find_section_command
:
4261 for (j
= 0; text
[j
] && cr_or_whitespace (text
[j
]); j
++);
4262 if (text
[j
] != COMMAND_PREFIX
)
4265 text
= text
+ j
+ 1;
4267 /* We skip @c, @comment, and @?index commands. */
4268 if ((strncmp (text
, "comment", strlen ("comment")) == 0) ||
4269 (text
[0] == 'c' && cr_or_whitespace (text
[1])) ||
4270 (strcmp (text
+ 1, "index") == 0))
4272 while (*text
++ != '\n');
4273 goto find_section_command
;
4276 /* Handle italicized sectioning commands. */
4280 for (j
= 0; text
[j
] && !cr_or_whitespace (text
[j
]); j
++);
4282 for (i
= 0; (t
= section_alist
[i
].name
); i
++)
4284 if (j
== strlen (t
) && strncmp (t
, text
, j
) == 0)
4288 return_val
= (section_alist
[i
].level
+ section_alist_offset
);
4292 else if (return_val
> 5)
4294 return (return_val
);
4300 /* Set the level of @top to LEVEL. Return the old level of @top. */
4302 set_top_section_level (level
)
4305 register int i
, result
= -1;
4307 for (i
= 0; section_alist
[i
].name
; i
++)
4308 if (strcmp (section_alist
[i
].name
, "top") == 0)
4310 result
= section_alist
[i
].level
;
4311 section_alist
[i
].level
= level
;
4317 /* Treat this just like @unnumbered. The only difference is
4318 in node defaulting. */
4322 /* It is an error to have more than one @top. */
4325 TAG_ENTRY
*tag
= tag_table
;
4327 line_error (_("Node with %ctop as a section already exists"),
4330 while (tag
!= (TAG_ENTRY
*)NULL
)
4332 if ((tag
->flags
& IS_TOP
))
4334 int old_line_number
= line_number
;
4335 char *old_input_filename
= input_filename
;
4337 line_number
= tag
->line_no
;
4338 input_filename
= tag
->filename
;
4339 line_error (_("Here is the %ctop node"), COMMAND_PREFIX
);
4340 input_filename
= old_input_filename
;
4341 line_number
= old_line_number
;
4344 tag
= tag
->next_ent
;
4351 /* It is an error to use @top before you have used @node. */
4356 get_rest_of_line (&top_name
);
4358 line_error (_("%ctop used before %cnode, defaulting to %s"),
4359 COMMAND_PREFIX
, COMMAND_PREFIX
, top_name
);
4360 execute_string ("@node Top, , (dir), (dir)\n@top %s\n", top_name
);
4366 /* The most recently defined node is the top node. */
4367 tag_table
->flags
|= IS_TOP
;
4369 /* Now set the logical hierarchical level of the Top node. */
4371 int orig_offset
= input_text_offset
;
4373 input_text_offset
= search_forward (node_search_string
, orig_offset
);
4375 if (input_text_offset
> 0)
4379 /* We have encountered a non-top node, so mark that one exists. */
4380 non_top_node_seen
= 1;
4382 /* Move to the end of this line, and find out what the
4383 sectioning command is here. */
4384 while (input_text
[input_text_offset
] != '\n')
4385 input_text_offset
++;
4387 if (input_text_offset
< size_of_input_text
)
4388 input_text_offset
++;
4390 this_section
= what_section (input_text
+ input_text_offset
);
4392 /* If we found a sectioning command, then give the top section
4393 a level of this section - 1. */
4394 if (this_section
!= -1)
4395 set_top_section_level (this_section
- 1);
4397 input_text_offset
= orig_offset
;
4402 /* Organized by level commands. That is, "*" == chapter, "=" == section. */
4403 char *scoring_characters
= "*=-.";
4406 sectioning_underscore (command
)
4413 temp
= (char *)xmalloc (2 + strlen (command
));
4414 temp
[0] = COMMAND_PREFIX
;
4415 strcpy (&temp
[1], command
);
4416 level
= what_section (temp
);
4423 character
= scoring_characters
[level
];
4425 insert_and_underscore (character
);
4428 /* The command still works, but prints a warning message in addition. */
4430 cm_ideprecated (arg
, start
, end
)
4431 int arg
, start
, end
;
4433 warning (_("%c%s is obsolete; use %c%s instead"),
4434 COMMAND_PREFIX
, command
, COMMAND_PREFIX
, command
+ 1);
4435 sectioning_underscore (command
+ 1);
4438 /* The remainder of the text on this line is a chapter heading. */
4442 sectioning_underscore ("chapter");
4445 /* The remainder of the text on this line is a section heading. */
4449 sectioning_underscore ("section");
4452 /* The remainder of the text on this line is a subsection heading. */
4456 sectioning_underscore ("subsection");
4459 /* The remainder of the text on this line is a subsubsection heading. */
4463 sectioning_underscore ("subsubsection");
4466 /* The remainder of the text on this line is an unnumbered heading. */
4473 /* The remainder of the text on this line is an unnumbered section heading. */
4480 /* The remainder of the text on this line is an unnumbered
4481 subsection heading. */
4483 cm_unnumberedsubsec ()
4488 /* The remainder of the text on this line is an unnumbered
4489 subsubsection heading. */
4491 cm_unnumberedsubsubsec ()
4493 cm_subsubsection ();
4496 /* The remainder of the text on this line is an appendix heading. */
4503 /* The remainder of the text on this line is an appendix section heading. */
4510 /* The remainder of the text on this line is an appendix subsection heading. */
4512 cm_appendixsubsec ()
4517 /* The remainder of the text on this line is an appendix
4518 subsubsection heading. */
4520 cm_appendixsubsubsec ()
4522 cm_subsubsection ();
4525 /* Compatibility functions substitute for chapter, section, etc. */
4553 cm_subsubsection ();
4556 /* **************************************************************** */
4558 /* Adding nodes, and making tags */
4560 /* **************************************************************** */
4562 /* Start a new tag table. */
4566 while (tag_table
!= (TAG_ENTRY
*) NULL
)
4568 TAG_ENTRY
*temp
= tag_table
;
4573 tag_table
= tag_table
->next_ent
;
4581 write_tag_table_internal (0); /* Not indirect. */
4585 write_tag_table_indirect ()
4587 write_tag_table_internal (1);
4590 /* Write out the contents of the existing tag table.
4591 INDIRECT_P says how to format the output. */
4593 write_tag_table_internal (indirect_p
)
4596 TAG_ENTRY
*node
= tag_table
;
4597 int old_indent
= no_indent
;
4600 filling_enabled
= 0;
4601 must_start_paragraph
= 0;
4610 add_word_args ("\037\nTag Table:\n%s", indirect_p
? "(Indirect)\n" : "");
4612 while (node
!= (TAG_ENTRY
*) NULL
)
4614 execute_string ("Node: %s", node
->node
);
4615 add_word_args ("\177%d\n", node
->position
);
4616 node
= node
->next_ent
;
4619 add_word ("\037\nEnd Tag Table\n");
4621 no_indent
= old_indent
;
4625 get_node_token (expand
)
4630 get_until_in_line (expand
, ",", &string
);
4632 if (curchar () == ',')
4633 input_text_offset
++;
4635 canon_white (string
);
4637 /* Force all versions of "top" to be "Top". */
4638 normalize_node_name (string
);
4643 /* Convert "top" and friends into "Top". */
4645 normalize_node_name (string
)
4648 if (strcasecmp (string
, "Top") == 0)
4649 strcpy (string
, "Top");
4652 /* Look up NAME in the tag table, and return the associated
4653 tag_entry. If the node is not in the table return NULL. */
4658 TAG_ENTRY
*tag
= tag_table
;
4660 while (tag
!= (TAG_ENTRY
*) NULL
)
4662 if (strcmp (tag
->node
, name
) == 0)
4664 tag
= tag
->next_ent
;
4666 return ((TAG_ENTRY
*) NULL
);
4669 /* Remember NODE and associates. */
4671 remember_node (node
, prev
, next
, up
, position
, line_no
, no_warn
)
4672 char *node
, *prev
, *next
, *up
;
4673 int position
, line_no
, no_warn
;
4675 /* Check for existence of this tag already. */
4678 register TAG_ENTRY
*tag
= find_node (node
);
4682 _("Node `%s' multiply defined (line %d is first definition at)"),
4683 node
, tag
->line_no
);
4688 /* First, make this the current node. */
4689 current_node
= node
;
4691 /* Now add it to the list. */
4693 TAG_ENTRY
*new = (TAG_ENTRY
*) xmalloc (sizeof (TAG_ENTRY
));
4698 new->position
= position
;
4699 new->line_no
= line_no
;
4700 new->filename
= node_filename
;
4701 new->touched
= 0; /* not yet referenced. */
4704 new->flags
|= NO_WARN
;
4705 new->next_ent
= tag_table
;
4710 /* The order is: nodename, nextnode, prevnode, upnode.
4711 If all of the NEXT, PREV, and UP fields are empty, they are defaulted.
4712 You must follow a node command which has those fields defaulted
4713 with a sectioning command (e.g. @chapter) giving the "level" of that node.
4714 It is an error not to do so.
4715 The defaults come from the menu in this node's parent. */
4719 char *node
, *prev
, *next
, *up
;
4720 int new_node_pos
, defaulting
, this_section
, no_warn
= 0;
4721 extern int already_outputting_pending_notes
;
4723 if (strcmp (command
, "nwnode") == 0)
4726 /* Get rid of unmatched brace arguments from previous commands. */
4729 /* There also might be insertions left lying around that haven't been
4730 ended yet. Do that also. */
4731 discard_insertions (1);
4733 if (!already_outputting_pending_notes
)
4736 output_pending_notes ();
4737 free_pending_notes ();
4740 filling_enabled
= indented_fill
= 0;
4741 new_node_pos
= output_position
;
4742 current_footnote_number
= 1;
4744 #if defined (HAVE_MACROS)
4745 if (macro_expansion_output_stream
&& !executing_string
)
4746 append_to_expansion_output (input_text_offset
+ 1);
4747 #endif /* HAVE_MACROS */
4749 node
= get_node_token (1);
4750 next
= get_node_token (0);
4751 prev
= get_node_token (0);
4752 up
= get_node_token (0);
4755 printf (_("Formatting node %s...\n"), node
);
4757 #if defined (HAVE_MACROS)
4758 if (macro_expansion_output_stream
&& !executing_string
)
4759 remember_itext (input_text
, input_text_offset
);
4760 #endif /* HAVE_MACROS */
4765 add_word_args ("\037\nFile: %s, Node: ", pretty_output_filename
);
4767 #if defined (HAVE_MACROS)
4768 if (macro_expansion_output_stream
&& !executing_string
)
4769 me_execute_string (node
);
4771 #endif /* HAVE_MACROS */
4772 execute_string ("%s", node
);
4773 filling_enabled
= indented_fill
= 0;
4776 /* Check for defaulting of this node's next, prev, and up fields. */
4777 defaulting
= (*next
== 0 && *prev
== 0 && *up
== 0);
4779 this_section
= what_section (input_text
+ input_text_offset
);
4781 /* If we are defaulting, then look at the immediately following
4782 sectioning command (error if none) to determine the node's
4783 level. Find the node that contains the menu mentioning this node
4784 that is one level up (error if not found). That node is the "Up"
4785 of this node. Default the "Next" and "Prev" from the menu. */
4788 NODE_REF
*last_ref
= (NODE_REF
*)NULL
;
4789 NODE_REF
*ref
= node_references
;
4791 if ((this_section
< 0) && (strcmp (node
, "Top") != 0))
4793 char *polite_section_name
= "top";
4796 for (i
= 0; section_alist
[i
].name
; i
++)
4797 if (section_alist
[i
].level
== current_section
+ 1)
4799 polite_section_name
= section_alist
[i
].name
;
4804 (_("Node `%s' requires a sectioning command (e.g. %c%s)"),
4805 node
, COMMAND_PREFIX
, polite_section_name
);
4809 if (strcmp (node
, "Top") == 0)
4811 /* Default the NEXT pointer to be the first menu item in
4812 this node, if there is a menu in this node. We have to
4813 try very hard to find the menu, as it may be obscured
4814 by execution_strings which are on the filestack. For
4815 every member of the filestack which has a FILENAME
4816 member which is identical to the current INPUT_FILENAME,
4817 search forward from that offset. */
4818 int saved_input_text_offset
= input_text_offset
;
4819 int saved_size_of_input_text
= size_of_input_text
;
4820 char *saved_input_text
= input_text
;
4821 FSTACK
*next_file
= filestack
;
4823 int orig_offset
, orig_size
;
4824 char *glean_node_from_menu ();
4826 /* No matter what, make this file point back at `(dir)'. */
4827 free (up
); up
= xstrdup ("(dir)");
4831 orig_offset
= input_text_offset
;
4833 search_forward (node_search_string
, orig_offset
);
4836 orig_size
= size_of_input_text
;
4839 search_forward (menu_search_string
, orig_offset
);
4841 if (input_text_offset
> -1)
4843 char *nodename_from_menu
= (char *)NULL
;
4846 search_forward ("\n* ", input_text_offset
);
4848 if (input_text_offset
!= -1)
4849 nodename_from_menu
= glean_node_from_menu (0);
4851 if (nodename_from_menu
)
4853 free (next
); next
= nodename_from_menu
;
4858 /* We got here, so it hasn't been found yet. Try
4859 the next file on the filestack if there is one. */
4861 (strcmp (next_file
->filename
, input_filename
) == 0))
4863 input_text
= next_file
->text
;
4864 input_text_offset
= next_file
->offset
;
4865 size_of_input_text
= next_file
->size
;
4866 next_file
= next_file
->next
;
4870 /* No more input files to check. */
4875 input_text
= saved_input_text
;
4876 input_text_offset
= saved_input_text_offset
;
4877 size_of_input_text
= saved_size_of_input_text
;
4881 /* Fix the level of the menu references in the Top node, iff it
4882 was declared with @top, and no subsequent reference was found. */
4883 if (top_node_seen
&& !non_top_node_seen
)
4885 /* Then this is the first non-@top node seen. */
4888 level
= set_top_section_level (this_section
- 1);
4889 non_top_node_seen
= 1;
4893 if (ref
->section
== level
)
4894 ref
->section
= this_section
- 1;
4898 ref
= node_references
;
4903 if (ref
->section
== (this_section
- 1) &&
4904 ref
->type
== menu_reference
&&
4905 strcmp (ref
->node
, node
) == 0)
4907 char *containing_node
= ref
->containing_node
;
4910 up
= xstrdup (containing_node
);
4913 last_ref
->type
== menu_reference
&&
4914 (strcmp (last_ref
->containing_node
,
4915 containing_node
) == 0))
4918 next
= xstrdup (last_ref
->node
);
4921 while ((ref
->section
== this_section
- 1) &&
4923 (ref
->next
->type
!= menu_reference
))
4926 if (ref
->next
&& ref
->type
== menu_reference
&&
4927 (strcmp (ref
->next
->containing_node
,
4928 containing_node
) == 0))
4931 prev
= xstrdup (ref
->next
->node
);
4933 else if (!ref
->next
&&
4934 strcasecmp (ref
->containing_node
, "Top") == 0)
4937 prev
= xstrdup (ref
->containing_node
);
4946 #if defined (HAVE_MACROS)
4947 /* Insert the correct args if we are expanding macros, and the node's
4948 pointers weren't defaulted. */
4949 if (macro_expansion_output_stream
&& !executing_string
&& !defaulting
)
4952 int op_orig
= output_paragraph_offset
;
4954 temp
= (char *)xmalloc (3 + strlen (next
));
4955 sprintf (temp
, ", %s", next
);
4956 me_execute_string (temp
);
4959 temp
= (char *)xmalloc (3 + strlen (prev
));
4960 sprintf (temp
, ", %s", prev
);
4961 me_execute_string (temp
);
4964 temp
= (char *)xmalloc (4 + strlen (up
));
4965 sprintf (temp
, ", %s", up
);
4966 me_execute_string (temp
);
4969 output_paragraph_offset
= op_orig
;
4971 #endif /* HAVE_MACROS */
4975 #if defined (HAVE_MACROS)
4976 if (macro_expansion_output_stream
)
4977 me_inhibit_expansion
++;
4978 #endif /* HAVE_MACROS */
4982 execute_string (", Next: %s", next
);
4983 filling_enabled
= indented_fill
= 0;
4988 execute_string (", Prev: %s", prev
);
4989 filling_enabled
= indented_fill
= 0;
4994 execute_string (", Up: %s", up
);
4995 filling_enabled
= indented_fill
= 0;
4997 #if defined (HAVE_MACROS)
4998 if (macro_expansion_output_stream
)
4999 me_inhibit_expansion
--;
5000 #endif /* HAVE_MACROS */
5008 line_error ("No node name specified for `%c%s' command",
5009 COMMAND_PREFIX
, command
);
5017 if (!*next
) { free (next
); next
= (char *)NULL
; }
5018 if (!*prev
) { free (prev
); prev
= (char *)NULL
; }
5019 if (!*up
) { free (up
); up
= (char *)NULL
; }
5020 remember_node (node
, prev
, next
, up
, new_node_pos
, line_number
, no_warn
);
5023 /* Change the section only if there was a sectioning command. */
5024 if (this_section
>= 0)
5025 current_section
= this_section
;
5027 filling_enabled
= 1;
5030 /* Validation of an info file.
5031 Scan through the list of tag entries touching the Prev, Next, and Up
5032 elements of each. It is an error not to be able to touch one of them,
5033 except in the case of external node references, such as "(DIR)".
5035 If the Prev is different from the Up,
5036 then the Prev node must have a Next pointing at this node.
5038 Every node except Top must have an Up.
5039 The Up node must contain some sort of reference, other than a Next,
5042 If the Next is different from the Next of the Up,
5043 then the Next node must have a Prev pointing at this node. */
5045 validate_file (tag_table
)
5046 TAG_ENTRY
*tag_table
;
5048 char *old_input_filename
= input_filename
;
5049 TAG_ENTRY
*tags
= tag_table
;
5051 while (tags
!= (TAG_ENTRY
*) NULL
)
5053 register TAG_ENTRY
*temp_tag
;
5055 input_filename
= tags
->filename
;
5056 line_number
= tags
->line_no
;
5058 /* If this is a "no warn" node, don't validate it in any way. */
5059 if (tags
->flags
& NO_WARN
)
5061 tags
= tags
->next_ent
;
5065 /* If this node has a Next, then make sure that the Next exists. */
5068 validate (tags
->next
, tags
->line_no
, "Next");
5070 /* If the Next node exists, and there is no Up, then make
5071 sure that the Prev of the Next points back. */
5072 temp_tag
= find_node (tags
->next
);
5077 if (temp_tag
->flags
& NO_WARN
)
5079 /* Do nothing if we aren't supposed to issue warnings
5084 prev
= temp_tag
->prev
;
5085 if (!prev
|| (strcmp (prev
, tags
->node
) != 0))
5087 line_error (_("Node `%s''s Next field not pointed back to"),
5089 line_number
= temp_tag
->line_no
;
5090 input_filename
= temp_tag
->filename
;
5092 (_("This node (`%s') is the one with the bad `Prev'"),
5094 input_filename
= tags
->filename
;
5095 line_number
= tags
->line_no
;
5096 temp_tag
->flags
|= PREV_ERROR
;
5102 /* Validate the Prev field if there is one, and we haven't already
5103 complained about it in some way. You don't have to have a Prev
5104 field at this stage. */
5105 if (!(tags
->flags
& PREV_ERROR
) && tags
->prev
)
5107 int valid_p
= validate (tags
->prev
, tags
->line_no
, "Prev");
5110 tags
->flags
|= PREV_ERROR
;
5113 /* If the Prev field is not the same as the Up field,
5114 then the node pointed to by the Prev field must have
5115 a Next field which points to this node. */
5116 if (tags
->up
&& (strcmp (tags
->prev
, tags
->up
) != 0))
5118 temp_tag
= find_node (tags
->prev
);
5120 /* If we aren't supposed to issue warnings about the
5121 target node, do nothing. */
5122 if (!temp_tag
|| (temp_tag
->flags
& NO_WARN
))
5128 if (!temp_tag
->next
||
5129 (strcmp (temp_tag
->next
, tags
->node
) != 0))
5132 (_("Node `%s's Prev field not pointed back to"),
5134 line_number
= temp_tag
->line_no
;
5135 input_filename
= temp_tag
->filename
;
5136 line_error (_("This node (`%s') has the bad Next"),
5138 input_filename
= tags
->filename
;
5139 line_number
= tags
->line_no
;
5140 temp_tag
->flags
|= NEXT_ERROR
;
5147 if (!tags
->up
&& (strcasecmp (tags
->node
, _("Top")) != 0))
5148 line_error (_("Node `%s' missing Up field"), tags
->node
);
5151 int valid_p
= validate (tags
->up
, tags
->line_no
, "Up");
5153 /* If node X has Up: Y, then warn if Y fails to have a menu item
5154 or note pointing at X, if Y isn't of the form "(Y)". */
5155 if (valid_p
&& *tags
->up
!= '(')
5157 NODE_REF
*nref
, *tref
, *list
;
5158 NODE_REF
*find_node_reference ();
5160 tref
= (NODE_REF
*) NULL
;
5161 list
= node_references
;
5165 if (!(nref
= find_node_reference (tags
->node
, list
)))
5168 if (strcmp (nref
->containing_node
, tags
->up
) == 0)
5170 if (nref
->type
!= menu_reference
)
5183 temp_tag
= find_node (tags
->up
);
5184 line_number
= temp_tag
->line_no
;
5185 input_filename
= temp_tag
->filename
;
5188 _("`%s' has an Up field of `%s', but `%s' has no menu item for `%s'"),
5189 tags
->node
, tags
->up
, tags
->up
, tags
->node
);
5190 line_number
= tags
->line_no
;
5191 input_filename
= tags
->filename
;
5195 tags
= tags
->next_ent
;
5198 validate_other_references (node_references
);
5199 /* We have told the user about the references which didn't exist.
5200 Now tell him about the nodes which aren't referenced. */
5203 while (tags
!= (TAG_ENTRY
*) NULL
)
5205 /* If this node is a "no warn" node, do nothing. */
5206 if (tags
->flags
& NO_WARN
)
5208 tags
= tags
->next_ent
;
5212 /* Special hack. If the node in question appears to have
5213 been referenced more than REFERENCE_WARNING_LIMIT times,
5215 if (tags
->touched
> reference_warning_limit
)
5217 input_filename
= tags
->filename
;
5218 line_number
= tags
->line_no
;
5219 warning (_("node `%s' has been referenced %d times"),
5220 tags
->node
, tags
->touched
);
5223 if (tags
->touched
== 0)
5225 input_filename
= tags
->filename
;
5226 line_number
= tags
->line_no
;
5228 /* Notice that the node "Top" is special, and doesn't have to
5230 if (strcasecmp (tags
->node
, _("Top")) != 0)
5231 warning (_("unreferenced node `%s'"), tags
->node
);
5233 tags
= tags
->next_ent
;
5235 input_filename
= old_input_filename
;
5238 /* Return 1 if tag correctly validated, or 0 if not. */
5240 validate (tag
, line
, label
)
5247 /* If there isn't a tag to verify, or if the tag is in another file,
5248 then it must be okay. */
5249 if (!tag
|| !*tag
|| *tag
== '(')
5252 /* Otherwise, the tag must exist. */
5253 result
= find_node (tag
);
5258 line_error (_("%s reference to nonexistent node `%s'"), label
, tag
);
5265 /* Split large output files into a series of smaller files. Each file
5266 is pointed to in the tag table, which then gets written out as the
5267 original file. The new files have the same name as the original file
5268 with a "-num" attached. SIZE is the largest number of bytes to allow
5269 in any single split file. */
5271 split_file (filename
, size
)
5275 char *root_filename
, *root_pathname
;
5276 char *the_file
, *filename_part ();
5277 struct stat fileinfo
;
5282 /* Can only do this to files with tag tables. */
5287 size
= DEFAULT_SPLIT_SIZE
;
5289 if ((stat (filename
, &fileinfo
) != 0) ||
5290 (((long) fileinfo
.st_size
) < SPLIT_SIZE_THRESHOLD
))
5292 file_size
= (long) fileinfo
.st_size
;
5294 the_file
= find_and_load (filename
);
5298 root_filename
= filename_part (filename
);
5299 root_pathname
= pathname_part (filename
);
5302 root_pathname
= xstrdup ("");
5304 /* Start splitting the file. Walk along the tag table
5305 outputting sections of the file. When we have written
5306 all of the nodes in the tag table, make the top-level
5307 pointer file, which contains indirect pointers and
5308 tags for the nodes. */
5311 TAG_ENTRY
*tags
= tag_table
;
5312 char *indirect_info
= (char *)NULL
;
5314 /* Remember the `header' of this file. The first tag in the file is
5315 the bottom of the header; the top of the file is the start. */
5316 the_header
= (char *)xmalloc (1 + (header_size
= tags
->position
));
5317 memcpy (the_header
, the_file
, header_size
);
5321 int file_top
, file_bot
, limit
;
5323 /* Have to include the Control-_. */
5324 file_top
= file_bot
= tags
->position
;
5325 limit
= file_top
+ size
;
5327 /* If the rest of this file is only one node, then
5328 that is the entire subfile. */
5329 if (!tags
->next_ent
)
5331 int i
= tags
->position
+ 1;
5332 char last_char
= the_file
[i
];
5334 while (i
< file_size
)
5336 if ((the_file
[i
] == '\037') &&
5337 ((last_char
== '\n') ||
5338 (last_char
== '\014')))
5341 last_char
= the_file
[i
];
5345 tags
= tags
->next_ent
;
5349 /* Otherwise, find the largest number of nodes that can fit in
5351 for (; tags
; tags
= tags
->next_ent
)
5353 if (!tags
->next_ent
)
5355 /* This entry is the last node. Search forward for the end
5356 of this node, and that is the end of this file. */
5357 int i
= tags
->position
+ 1;
5358 char last_char
= the_file
[i
];
5360 while (i
< file_size
)
5362 if ((the_file
[i
] == '\037') &&
5363 ((last_char
== '\n') ||
5364 (last_char
== '\014')))
5367 last_char
= the_file
[i
];
5372 if (file_bot
< limit
)
5374 tags
= tags
->next_ent
;
5379 /* Here we want to write out everything before the last
5380 node, and then write the last node out in a file
5382 file_bot
= tags
->position
;
5387 if (tags
->next_ent
->position
> limit
)
5389 if (tags
->position
== file_top
)
5390 tags
= tags
->next_ent
;
5392 file_bot
= tags
->position
;
5397 char *split_filename
;
5399 split_filename
= (char *) xmalloc
5400 (10 + strlen (root_pathname
) + strlen (root_filename
));
5403 "%s%s-%d", root_pathname
, root_filename
, which_file
);
5406 (split_filename
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
5409 (write (fd
, the_header
, header_size
) != header_size
) ||
5410 (write (fd
, the_file
+ file_top
, file_bot
- file_top
)
5411 != (file_bot
- file_top
)) ||
5414 perror (split_filename
);
5422 indirect_info
= the_file
+ file_top
;
5423 sprintf (indirect_info
, "\037\nIndirect:\n");
5424 indirect_info
+= strlen (indirect_info
);
5427 sprintf (indirect_info
, "%s-%d: %d\n",
5428 root_filename
, which_file
, file_top
);
5430 free (split_filename
);
5431 indirect_info
+= strlen (indirect_info
);
5439 /* We have sucessfully created the subfiles. Now write out the
5440 original again. We must use `output_stream', or
5441 write_tag_table_indirect () won't know where to place the output. */
5442 output_stream
= fopen (filename
, "w");
5450 int distance
= indirect_info
- the_file
;
5451 fwrite (the_file
, 1, distance
, output_stream
);
5453 /* Inhibit newlines. */
5454 paragraph_is_open
= 0;
5456 write_tag_table_indirect ();
5457 fclose (output_stream
);
5465 /* The strings here are followed in the message by `reference to...' in
5466 the `validate' routine. */
5468 reftype_type_string (type
)
5473 case menu_reference
:
5475 case followed_reference
:
5478 return ("Internal-bad-reference-type");
5482 /* Remember this node name for later validation use. This is used to
5483 remember menu references while reading the input file. After the
5484 output file has been written, if validation is on, then we use the
5485 contents of `node_references' as a list of nodes to validate. */
5487 remember_node_reference (node
, line
, type
)
5492 NODE_REF
*temp
= (NODE_REF
*) xmalloc (sizeof (NODE_REF
));
5494 temp
->next
= node_references
;
5495 temp
->node
= xstrdup (node
);
5496 temp
->line_no
= line
;
5497 temp
->section
= current_section
;
5499 temp
->containing_node
= xstrdup (current_node
? current_node
: "");
5500 temp
->filename
= node_filename
;
5502 node_references
= temp
;
5506 validate_other_references (ref_list
)
5507 register NODE_REF
*ref_list
;
5509 char *old_input_filename
= input_filename
;
5511 while (ref_list
!= (NODE_REF
*) NULL
)
5513 input_filename
= ref_list
->filename
;
5514 validate (ref_list
->node
, ref_list
->line_no
,
5515 reftype_type_string (ref_list
->type
));
5516 ref_list
= ref_list
->next
;
5518 input_filename
= old_input_filename
;
5521 /* Find NODE in REF_LIST. */
5523 find_node_reference (node
, ref_list
)
5525 register NODE_REF
*ref_list
;
5529 if (strcmp (node
, ref_list
->node
) == 0)
5531 ref_list
= ref_list
->next
;
5537 free_node_references ()
5539 register NODE_REF
*list
, *temp
;
5541 list
= node_references
;
5547 free (list
->containing_node
);
5551 node_references
= (NODE_REF
*) NULL
;
5554 /* This function gets called at the start of every line while inside of
5555 a menu. It checks to see if the line starts with "* ", and if so,
5556 remembers the node reference that this menu refers to.
5557 input_text_offset is at the \n just before the line start. */
5558 #define menu_starter "* "
5560 glean_node_from_menu (remember_reference
)
5561 int remember_reference
;
5563 int i
, orig_offset
= input_text_offset
;
5566 if (strncmp (&input_text
[input_text_offset
+ 1],
5568 strlen (menu_starter
)) != 0)
5569 return ((char *)NULL
);
5571 input_text_offset
+= strlen (menu_starter
) + 1;
5573 get_until_in_line (0, ":", &nodename
);
5574 if (curchar () == ':')
5575 input_text_offset
++;
5576 canon_white (nodename
);
5578 if (curchar () == ':')
5582 get_rest_of_line (&nodename
);
5584 /* Special hack: If the nodename follows the menu item name,
5585 then we have to read the rest of the line in order to find
5586 out what the nodename is. But we still have to read the
5587 line later, in order to process any formatting commands that
5588 might be present. So un-count the carriage return that has just
5592 isolate_nodename (nodename
);
5595 input_text_offset
= orig_offset
;
5596 normalize_node_name (nodename
);
5597 i
= strlen (nodename
);
5598 if (i
&& nodename
[i
- 1] == ':')
5599 nodename
[i
- 1] = 0;
5601 if (remember_reference
)
5603 remember_node_reference (nodename
, line_number
, menu_reference
);
5605 return ((char *)NULL
);
5612 isolate_nodename (nodename
)
5616 int paren_seen
, paren
;
5621 canon_white (nodename
);
5622 paren_seen
= paren
= i
= 0;
5624 if (*nodename
== '.' || !*nodename
)
5630 if (*nodename
== '(')
5637 for (; (c
= nodename
[i
]); i
++)
5649 /* If the character following the close paren is a space, then this
5650 node has no more characters associated with it. */
5654 ((paren_seen
&& nodename
[i
- 1] == ')') &&
5655 (c
== ' ' || c
== '.')) ||
5657 ((!nodename
[i
+ 1] ||
5658 (cr_or_whitespace (nodename
[i
+ 1])) ||
5659 (nodename
[i
+ 1] == ')')))))
5668 if (current_node
== (char *)NULL
)
5670 warning (_("%cmenu seen before first node"), COMMAND_PREFIX
);
5671 warning (_("creating `Top' node"));
5672 execute_string ("@node Top");
5674 begin_insertion (menu
);
5680 if (current_node
== (char *)NULL
)
5682 warning (_("%cmenu seen before first node"), COMMAND_PREFIX
);
5683 warning (_("creating `Top' node"));
5684 execute_string ("@node Top");
5686 begin_insertion (detailmenu
);
5689 /* **************************************************************** */
5691 /* Cross Reference Hacking */
5693 /* **************************************************************** */
5695 /* Return next comma-delimited argument, but do not cross a close-brace
5696 boundary. Clean up whitespace, too. */
5702 get_until_in_braces (",", &string
);
5703 if (curchar () == ',')
5704 input_text_offset
++;
5705 fix_whitespace (string
);
5709 int px_ref_flag
= 0; /* Controls initial output string. */
5711 /* Make a cross reference. */
5717 char *arg1
, *arg2
, *arg3
, *arg4
, *arg5
;
5719 arg1
= get_xref_token ();
5720 arg2
= get_xref_token ();
5721 arg3
= get_xref_token ();
5722 arg4
= get_xref_token ();
5723 arg5
= get_xref_token ();
5725 add_word_args ("%s", px_ref_flag
? "*note " : "*Note ");
5741 execute_string ("%s: (%s)%s", node_name
, arg4
, arg1
);
5742 /* Free all of the arguments found. */
5743 if (arg1
) free (arg1
);
5744 if (arg2
) free (arg2
);
5745 if (arg3
) free (arg3
);
5746 if (arg4
) free (arg4
);
5747 if (arg5
) free (arg5
);
5751 remember_node_reference (arg1
, line_number
, followed_reference
);
5756 execute_string ("%s: %s", arg3
, arg1
);
5758 execute_string ("%s: %s", arg2
, arg1
);
5763 execute_string ("%s: %s", arg2
, arg1
);
5765 execute_string ("%s::", arg1
);
5768 /* Free all of the arguments found. */
5769 if (arg1
) free (arg1
);
5770 if (arg2
) free (arg2
);
5771 if (arg3
) free (arg3
);
5772 if (arg4
) free (arg4
);
5773 if (arg5
) free (arg5
);
5777 /* Check to make sure that the next non-whitespace character is either
5778 a period or a comma. input_text_offset is pointing at the "}" which
5779 ended the xref or pxref command. */
5780 int temp
= input_text_offset
+ 1;
5782 if (output_paragraph
[output_paragraph_offset
- 2] == ':' &&
5783 output_paragraph
[output_paragraph_offset
- 1] == ':')
5785 while (temp
< size_of_input_text
)
5787 if (cr_or_whitespace (input_text
[temp
]))
5791 if (input_text
[temp
] != '.'
5792 && input_text
[temp
] != ','
5793 && input_text
[temp
] != '\t')
5796 _("`.' or `,' must follow cross reference, not %c"),
5825 char *node
= get_xref_token ();
5826 char *pname
= get_xref_token ();
5827 char *file
= get_xref_token ();
5830 execute_string ("*note %s: (%s)%s", pname
, file
, node
);
5832 execute_string ("*note (%s)%s::", file
, node
);
5840 /* A URL reference. */
5842 cm_uref (arg
, start_pos
, end_pos
)
5843 int arg
, start_pos
, end_pos
;
5848 char *arg
= (char *) &output_paragraph
[start_pos
];
5850 output_paragraph
[end_pos
] = 0;
5851 output_column
-= end_pos
- start_pos
;
5852 output_paragraph_offset
= start_pos
;
5854 arg
= xstrdup (arg
);
5855 comma
= strchr (arg
, ','); /* let's hope for no commas in the url */
5859 /* Ignore spaces at beginning of second arg. */
5860 for (comma
++; isspace (*comma
); comma
++)
5870 extern int printing_index
;
5872 if (!printing_index
)
5877 if (!printing_index
)
5884 /* An email reference. */
5886 cm_email (arg
, start_pos
, end_pos
)
5887 int arg
, start_pos
, end_pos
;
5892 char *arg
= (char *) &output_paragraph
[start_pos
];
5894 output_paragraph
[end_pos
] = 0;
5895 output_column
-= end_pos
- start_pos
;
5896 output_paragraph_offset
= start_pos
;
5898 arg
= xstrdup (arg
);
5899 comma
= strchr (arg
, ',');
5903 for (comma
++; isspace (*comma
); comma
++)
5915 /* An external image is a reference, kind of. The parsing is (not
5916 coincidentally) similar, anyway. */
5923 char *name_arg
= get_xref_token ();
5924 /* We don't yet care about any other args, but read them so they
5925 don't end up in the text. */
5926 char *arg
= get_xref_token ();
5927 if (arg
) free (arg
);
5928 arg
= get_xref_token ();
5929 if (arg
) free (arg
);
5933 /* Try to open foo.txt. */
5935 char *name
= xmalloc (strlen (name_arg
) + 4);
5936 strcpy (name
, name_arg
);
5937 strcat (name
, ".txt");
5938 image_file
= fopen (name
, "r");
5942 int save_inhibit_indentation
= inhibit_paragraph_indentation
;
5943 int save_filling_enabled
= filling_enabled
;
5945 inhibit_paragraph_indentation
= 1;
5946 filling_enabled
= 0;
5947 last_char_was_newline
= 0;
5949 /* Maybe we need to remove the final newline if the image
5950 file is only one line to allow in-line images. On the
5951 other hand, they could just make the file without a
5953 while ((ch
= getc (image_file
)) != EOF
)
5956 inhibit_paragraph_indentation
= save_inhibit_indentation
;
5957 filling_enabled
= save_filling_enabled
;
5959 if (fclose (image_file
) != 0) {
5964 warning (_("@image file `%s' unreadable: %s"), name
,
5968 line_error (_("@image missing filename argument"));
5970 if (name_arg
) free (name_arg
);
5974 /* **************************************************************** */
5976 /* Insertion Command Stubs */
5978 /* **************************************************************** */
5983 begin_insertion (quotation
);
5989 begin_insertion (example
);
5995 begin_insertion (smallexample
);
6001 begin_insertion (lisp
);
6007 begin_insertion (smalllisp
);
6010 /* @cartouche/@end cartouche draws box with rounded corners in
6011 TeX output. Right now, just a no-op insertion. */
6015 begin_insertion (cartouche
);
6021 begin_insertion (format
);
6027 begin_insertion (display
);
6034 command_name_condition ();
6036 begin_insertion (direntry
);
6042 begin_insertion (itemize
);
6048 do_enumeration (enumerate
, "1");
6051 /* Start an enumeration insertion of type TYPE. If the user supplied
6052 no argument on the line, then use DEFAULT_STRING as the initial string. */
6054 do_enumeration (type
, default_string
)
6056 char *default_string
;
6058 get_until_in_line (0, ".", &enumeration_arg
);
6059 canon_white (enumeration_arg
);
6061 if (!*enumeration_arg
)
6063 free (enumeration_arg
);
6064 enumeration_arg
= xstrdup (default_string
);
6067 if (!isdigit (*enumeration_arg
) && !isletter (*enumeration_arg
))
6069 warning (_("%s requires letter or digit"), insertion_type_pname (type
));
6074 default_string
= "1";
6077 enumeration_arg
= xstrdup (default_string
);
6079 begin_insertion (type
);
6085 begin_insertion (table
);
6091 begin_insertion (multitable
); /* @@ */
6097 begin_insertion (ftable
);
6103 begin_insertion (vtable
);
6109 begin_insertion (group
);
6115 begin_insertion (ifinfo
);
6121 begin_insertion (ifnothtml
);
6127 begin_insertion (ifnottex
);
6130 /* Begin an insertion where the lines are not filled or indented. */
6134 begin_insertion (flushleft
);
6137 /* Begin an insertion where the lines are not filled, and each line is
6138 forced to the right-hand side of the page. */
6142 begin_insertion (flushright
);
6145 /* End existing insertion block. */
6150 enum insertion_type type
;
6152 if (!insertion_level
)
6154 line_error (_("Unmatched `%c%s'"), COMMAND_PREFIX
, command
);
6158 get_rest_of_line (&temp
);
6161 line_error (_("`%c%s' needs something after it"), COMMAND_PREFIX
, command
);
6163 type
= find_type_from_name (temp
);
6165 if (type
== bad_type
)
6167 line_error (_("Bad argument to `%s', `%s', using `%s'"),
6168 command
, temp
, insertion_type_pname (current_insertion_type ()));
6170 end_insertion (type
);
6174 /* **************************************************************** */
6176 /* Conditional Handling */
6178 /* **************************************************************** */
6180 /* A structure which contains `defined' variables. */
6181 typedef struct defines
{
6182 struct defines
*next
;
6187 /* The linked list of `set' defines. */
6188 DEFINE
*defines
= (DEFINE
*)NULL
;
6190 /* Add NAME to the list of `set' defines. */
6198 for (temp
= defines
; temp
; temp
= temp
->next
)
6199 if (strcmp (name
, temp
->name
) == 0)
6202 temp
->value
= xstrdup (value
);
6206 temp
= (DEFINE
*)xmalloc (sizeof (DEFINE
));
6207 temp
->next
= defines
;
6208 temp
->name
= xstrdup (name
);
6209 temp
->value
= xstrdup (value
);
6213 /* Remove NAME from the list of `set' defines. */
6218 register DEFINE
*temp
, *last
;
6220 last
= (DEFINE
*)NULL
;
6225 if (strcmp (temp
->name
, name
) == 0)
6228 last
->next
= temp
->next
;
6230 defines
= temp
->next
;
6242 /* Return the value of NAME. The return value is NULL if NAME is unset. */
6247 register DEFINE
*temp
;
6249 for (temp
= defines
; temp
; temp
= temp
->next
)
6250 if (strcmp (temp
->name
, name
) == 0)
6251 return (temp
->value
);
6253 return ((char *)NULL
);
6256 /* Conditionally parse based on the current command name. */
6258 command_name_condition ()
6262 discarder
= (char *)xmalloc (8 + strlen (command
));
6264 sprintf (discarder
, "\n%cend %s", COMMAND_PREFIX
, command
);
6265 discard_until (discarder
);
6266 discard_until ("\n");
6271 /* Create a variable whose name appears as the first word on this line. */
6275 handle_variable (SET
);
6278 /* Remove a variable whose name appears as the first word on this line. */
6282 handle_variable (CLEAR
);
6288 handle_variable (IFSET
);
6294 handle_variable (IFCLEAR
);
6297 /* This command takes braces, but we parse the contents specially, so we
6298 don't use the standard brace popping code.
6300 The syntax @ifeq{arg1, arg2, texinfo-commands} performs texinfo-commands
6301 if ARG1 and ARG2 caselessly string compare to the same string, otherwise,
6302 it produces no output. */
6308 arglist
= get_brace_args (0);
6312 if (array_len (arglist
) > 1)
6314 if ((strcasecmp (arglist
[0], arglist
[1]) == 0) &&
6315 (arglist
[2] != (char *)NULL
))
6316 execute_string ("%s\n", arglist
[2]);
6319 free_array (arglist
);
6324 cm_value (arg
, start_pos
, end_pos
)
6325 int arg
, start_pos
, end_pos
;
6329 char *name
= (char *) &output_paragraph
[start_pos
];
6331 output_paragraph
[end_pos
] = 0;
6332 name
= xstrdup (name
);
6333 value
= set_p (name
);
6334 output_column
-= end_pos
- start_pos
;
6335 output_paragraph_offset
= start_pos
;
6338 execute_string ("%s", value
);
6340 add_word_args (_("{No Value For \"%s\"}"), name
);
6346 /* Set, clear, or conditionalize based on ACTION. */
6348 handle_variable (action
)
6353 get_rest_of_line (&name
);
6354 backup_input_pointer ();
6355 handle_variable_internal (action
, name
);
6360 handle_variable_internal (action
, name
)
6365 int delimiter
, additional_text_present
= 0;
6367 /* Only the first word of NAME is a valid tag. */
6370 while (*temp
&& (delimiter
|| !whitespace (*temp
)))
6372 /* #if defined (SET_WITH_EQUAL) */
6373 if (*temp
== '"' || *temp
== '\'')
6375 if (*temp
== delimiter
)
6380 /* #endif SET_WITH_EQUAL */
6385 additional_text_present
++;
6390 line_error (_("%c%s requires a name"), COMMAND_PREFIX
, command
);
6399 #if defined (SET_WITH_EQUAL)
6400 /* Allow a value to be saved along with a variable. The value is
6401 the text following an `=' sign in NAME, if any is present. */
6403 for (value
= name
; *value
&& *value
!= '='; value
++);
6408 if (*value
== '"' || *value
== '\'')
6411 value
[strlen (value
) - 1] = 0;
6414 #else /* !SET_WITH_EQUAL */
6415 /* The VALUE of NAME is the remainder of the line sans
6417 if (additional_text_present
)
6420 canon_white (value
);
6424 #endif /* !SET_WITH_VALUE */
6436 /* If IFSET and NAME is not set, or if IFCLEAR and NAME is set,
6437 read lines from the file until we reach a matching
6438 "@end CONDITION". This means that we only take note of
6439 "@ifset/clear" and "@end" commands. */
6443 int orig_line_number
= line_number
;
6445 if (action
== IFSET
)
6446 strcpy (condition
, "ifset");
6448 strcpy (condition
, "ifclear");
6450 condition_len
= strlen (condition
);
6452 if ((action
== IFSET
&& !set_p (name
))
6453 || (action
== IFCLEAR
&& set_p (name
)))
6455 int level
= 0, done
= 0;
6457 while (!done
&& input_text_offset
< size_of_input_text
)
6459 char *freeable_line
, *line
;
6461 get_rest_of_line (&freeable_line
);
6463 for (line
= freeable_line
; whitespace (*line
); line
++);
6465 if (*line
== COMMAND_PREFIX
&&
6466 (strncmp (line
+ 1, condition
, condition_len
) == 0))
6468 else if (strncmp (line
, "@end", 4) == 0)
6470 char *cname
= line
+ 4;
6473 while (*cname
&& whitespace (*cname
))
6477 while (*temp
&& !whitespace (*temp
))
6481 if (strcmp (cname
, condition
) == 0)
6491 free (freeable_line
);
6496 int save
= line_number
;
6497 line_number
= orig_line_number
;
6498 line_error (_("Reached eof before matching @end %s"),
6503 /* We found the end of a false @ifset/ifclear. If we are
6504 in a menu, back up over the newline that ends the ifset,
6505 since that newline may also begin the next menu entry. */
6510 if (action
== IFSET
)
6511 begin_insertion (ifset
);
6513 begin_insertion (ifclear
);
6521 /* Execution of random text not in file. */
6524 char *string
; /* The string buffer. */
6525 int size
; /* The size of the buffer. */
6526 int in_use
; /* Nonzero means string currently in use. */
6529 static EXECUTION_STRING
**execution_strings
= (EXECUTION_STRING
**)NULL
;
6530 static int execution_strings_index
= 0;
6531 static int execution_strings_slots
= 0;
6534 get_execution_string (initial_size
)
6538 EXECUTION_STRING
*es
= (EXECUTION_STRING
*)NULL
;
6540 if (execution_strings
)
6542 for (i
= 0; i
< execution_strings_index
; i
++)
6543 if (execution_strings
[i
] && (execution_strings
[i
]->in_use
== 0))
6545 es
= execution_strings
[i
];
6552 if (execution_strings_index
+ 1 >= execution_strings_slots
)
6554 execution_strings
= (EXECUTION_STRING
**)xrealloc
6556 (execution_strings_slots
+= 3) * sizeof (EXECUTION_STRING
*));
6557 for (; i
< execution_strings_slots
; i
++)
6558 execution_strings
[i
] = (EXECUTION_STRING
*)NULL
;
6561 execution_strings
[execution_strings_index
] =
6562 (EXECUTION_STRING
*)xmalloc (sizeof (EXECUTION_STRING
));
6563 es
= execution_strings
[execution_strings_index
];
6564 execution_strings_index
++;
6567 es
->string
= (char *)NULL
;
6571 if (initial_size
> es
->size
)
6573 es
->string
= (char *) xrealloc (es
->string
, initial_size
);
6574 es
->size
= initial_size
;
6579 /* Execute the string produced by formatting the ARGs with FORMAT. This
6580 is like submitting a new file with @include. */
6582 #if defined (VA_FPRINTF) && __STDC__
6583 execute_string (char *format
, ...)
6585 execute_string (format
, va_alist
)
6590 EXECUTION_STRING
*es
;
6596 es
= get_execution_string (4000);
6597 temp_string
= es
->string
;
6600 VA_START (ap
, format
);
6602 VA_SPRINTF (temp_string
, format
, ap
);
6604 sprintf (temp_string
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
);
6605 #endif /* not VA_SPRINTF */
6609 input_text_offset
= 0;
6610 input_text
= temp_string
;
6611 input_filename
= xstrdup (input_filename
);
6612 size_of_input_text
= strlen (temp_string
);
6616 free (input_filename
);
6624 /* Return what would be output for STR, i.e., expand Texinfo commands.
6625 If IMPLICIT_CODE is set, expand @code{STR}. */
6628 expansion (str
, implicit_code
)
6635 /* Inhibit any real output. */
6636 int start
= output_paragraph_offset
;
6637 int saved_paragraph_is_open
= paragraph_is_open
;
6639 inhibit_output_flushing ();
6640 paragraph_is_open
= 1;
6641 execute_string (implicit_code
? "@code{%s}" : "%s", str
);
6642 uninhibit_output_flushing ();
6644 /* Copy the expansion from the buffer. */
6645 length
= output_paragraph_offset
- start
;
6646 result
= xmalloc (1 + length
);
6647 memcpy (result
, (char *) (output_paragraph
+ start
), length
);
6650 /* Pretend it never happened. */
6651 output_paragraph_offset
= start
;
6652 paragraph_is_open
= saved_paragraph_is_open
;
6657 /* @itemx, @item. */
6659 static int itemx_flag
= 0;
6672 char *rest_of_line
, *item_func
;
6674 /* Can only hack "@item" while inside of an insertion. */
6675 if (insertion_level
)
6677 INSERTION_ELT
*stack
= insertion_stack
;
6678 int original_input_text_offset
;
6681 original_input_text_offset
= input_text_offset
;
6683 get_rest_of_line (&rest_of_line
);
6684 item_func
= current_item_function ();
6686 /* Okay, do the right thing depending on which insertion function
6690 switch (stack
->insertion
)
6694 /* Ultra special hack. It appears that some people incorrectly
6695 place text directly after the @item, instead of on a new line
6696 by itself. This happens to work in TeX, so I make it work
6701 input_text_offset
= original_input_text_offset
;
6709 stack
= stack
->next
;
6724 line_error (_("The `%c%s' command is meaningless within a `@%s' block"),
6725 COMMAND_PREFIX
, command
,
6726 insertion_type_pname (current_insertion_type ()));
6733 line_error (_("%citemx is not meaningful inside of a `%s' block"),
6735 insertion_type_pname (current_insertion_type ()));
6740 kill_self_indent (-1);
6741 filling_enabled
= indented_fill
= 1;
6743 if (current_insertion_type () == itemize
)
6745 indent (output_column
= current_indent
- 2);
6747 /* I need some way to determine whether this command
6748 takes braces or not. I believe the user can type
6749 either "@bullet" or "@bullet{}". Of course, they
6750 can also type "o" or "#" or whatever else they want. */
6751 if (item_func
&& *item_func
)
6753 if (*item_func
== COMMAND_PREFIX
)
6754 if (item_func
[strlen (item_func
) - 1] != '}')
6755 execute_string ("%s{}", item_func
);
6757 execute_string ("%s", item_func
);
6759 execute_string ("%s", item_func
);
6767 /* Special hack. This makes `close_paragraph' a no-op until
6768 `start_paragraph' has been called. */
6769 must_start_paragraph
= 1;
6771 /* Handle text directly after the @item. */
6775 input_text_offset
= original_input_text_offset
;
6784 /* We need this to determine if we have two @item's in a row
6785 (see test just below). */
6786 static int last_item_output_position
= 0;
6788 /* Get rid of extra characters. */
6789 kill_self_indent (-1);
6791 /* If we have one @item followed directly by another @item,
6792 we need to insert a blank line. This is not true for
6794 if (!itemx_flag
&& last_item_output_position
== output_position
)
6797 /* `close_paragraph' almost does what we want. The problem
6798 is when paragraph_is_open, and last_char_was_newline, and
6799 the last newline has been turned into a space, because
6800 filling_enabled. I handle it here. */
6801 if (last_char_was_newline
&& filling_enabled
&& paragraph_is_open
)
6805 #if defined (INDENT_PARAGRAPHS_IN_TABLE)
6806 /* Indent on a new line, but back up one indentation level. */
6808 int save
= inhibit_paragraph_indentation
;
6809 inhibit_paragraph_indentation
= 1;
6810 /* At this point, inserting any non-whitespace character will
6811 force the existing indentation to be output. */
6813 inhibit_paragraph_indentation
= save
;
6815 #else /* !INDENT_PARAGRAPHS_IN_TABLE */
6817 #endif /* !INDENT_PARAGRAPHS_IN_TABLE */
6819 output_paragraph_offset
--;
6820 kill_self_indent (default_indentation_increment
+ 1);
6822 /* Add item's argument to the line. */
6823 filling_enabled
= 0;
6824 if (item_func
&& *item_func
)
6825 execute_string ("%s{%s}", item_func
, rest_of_line
);
6827 execute_string ("%s", rest_of_line
);
6829 if (current_insertion_type () == ftable
)
6830 execute_string ("%cfindex %s\n", COMMAND_PREFIX
, rest_of_line
);
6831 else if (current_insertion_type () == vtable
)
6832 execute_string ("%cvindex %s\n", COMMAND_PREFIX
, rest_of_line
);
6834 /* Start a new line, and let start_paragraph ()
6835 do the indenting of it for you. */
6836 close_single_paragraph ();
6837 indented_fill
= filling_enabled
= 1;
6838 last_item_output_position
= output_position
;
6841 free (rest_of_line
);
6846 line_error (_("%c%s found outside of an insertion block"),
6847 COMMAND_PREFIX
, command
);
6851 /* **************************************************************** */
6853 /* Defun and Friends */
6855 /* **************************************************************** */
6857 #define DEFUN_SELF_DELIMITING(c) \
6863 struct token_accumulator
6865 unsigned int length
;
6871 initialize_token_accumulator (accumulator
)
6872 struct token_accumulator
*accumulator
;
6874 (accumulator
->length
) = 0;
6875 (accumulator
->index
) = 0;
6876 (accumulator
->tokens
) = NULL
;
6880 accumulate_token (accumulator
, token
)
6881 struct token_accumulator
*accumulator
;
6884 if ((accumulator
->index
) >= (accumulator
->length
))
6886 (accumulator
->length
) += 10;
6887 (accumulator
->tokens
) = (char **) xrealloc
6888 (accumulator
->tokens
, (accumulator
->length
* sizeof (char *)));
6890 accumulator
->tokens
[accumulator
->index
] = token
;
6891 accumulator
->index
+= 1;
6895 copy_substring (start
, end
)
6899 char *result
, *scan
, *scan_result
;
6901 result
= (char *) xmalloc ((end
- start
) + 1);
6902 scan_result
= result
;
6906 *scan_result
++ = *scan
++;
6912 /* Given `string' pointing at an open brace, skip forward and return a
6913 pointer to just past the matching close brace. */
6915 scan_group_in_string (string_pointer
)
6916 char **string_pointer
;
6919 register char *scan_string
;
6920 register unsigned int level
= 1;
6922 scan_string
= (*string_pointer
) + 1;
6928 (*string_pointer
) = scan_string
;
6931 c
= (*scan_string
++);
6934 /* Tweak line_number to compensate for fact that
6935 we gobbled the whole line before coming here. */
6937 line_error (_("Missing `}' in %cdef arg"), COMMAND_PREFIX
);
6939 (*string_pointer
) = (scan_string
- 1);
6949 /* Return a list of tokens from the contents of `string'.
6950 Commands and brace-delimited groups count as single tokens.
6951 Contiguous whitespace characters are converted to a token
6952 consisting of a single space. */
6954 args_from_string (string
)
6957 struct token_accumulator accumulator
;
6958 register char *scan_string
= string
;
6959 char *token_start
, *token_end
;
6961 initialize_token_accumulator (&accumulator
);
6963 while ((*scan_string
) != 0)
6965 /* Replace arbitrary whitespace by a single space. */
6966 if (whitespace (*scan_string
))
6969 while (whitespace (*scan_string
))
6971 accumulate_token ((&accumulator
), (xstrdup (" ")));
6975 /* Commands count as single tokens. */
6976 if ((*scan_string
) == COMMAND_PREFIX
)
6978 token_start
= scan_string
;
6980 if (self_delimiting (*scan_string
))
6989 if ((c
== 0) || (c
== '{') || (whitespace (c
)))
6996 if (*scan_string
== '{')
6998 char *s
= scan_string
;
6999 (void) scan_group_in_string (&s
);
7003 token_end
= scan_string
;
7006 /* Parentheses and brackets are self-delimiting. */
7007 else if (DEFUN_SELF_DELIMITING (*scan_string
))
7009 token_start
= scan_string
;
7011 token_end
= scan_string
;
7014 /* Open brace introduces a group that is a single token. */
7015 else if (*scan_string
== '{')
7017 char *s
= scan_string
;
7018 int balanced
= scan_group_in_string (&s
);
7020 token_start
= scan_string
+ 1;
7022 token_end
= balanced
? (scan_string
- 1) : scan_string
;
7025 /* Otherwise a token is delimited by whitespace, parentheses,
7026 brackets, or braces. A token is also ended by a command. */
7029 token_start
= scan_string
;
7037 /* Do not back up if we're looking at a }; since the only
7038 valid }'s are those matched with {'s, we want to give
7039 an error. If we back up, we go into an infinite loop. */
7040 if (!c
|| whitespace (c
) || DEFUN_SELF_DELIMITING (c
)
7047 /* If we encounter a command embedded within a token,
7048 then end the token. */
7049 if (c
== COMMAND_PREFIX
)
7055 token_end
= scan_string
;
7059 (&accumulator
, copy_substring (token_start
, token_end
));
7061 accumulate_token (&accumulator
, NULL
);
7062 return (accumulator
.tokens
);
7066 process_defun_args (defun_args
, auto_var_p
)
7070 int pending_space
= 0;
7074 char *defun_arg
= *defun_args
++;
7076 if (defun_arg
== NULL
)
7079 if (defun_arg
[0] == ' ')
7091 if (DEFUN_SELF_DELIMITING (defun_arg
[0]))
7092 add_char (defun_arg
[0]);
7093 else if (defun_arg
[0] == '&')
7094 add_word (defun_arg
);
7095 else if (defun_arg
[0] == COMMAND_PREFIX
)
7096 execute_string ("%s", defun_arg
);
7097 else if (auto_var_p
)
7098 execute_string ("%cvar{%s}", COMMAND_PREFIX
, defun_arg
);
7100 add_word (defun_arg
);
7105 next_nonwhite_defun_arg (arg_pointer
)
7106 char ***arg_pointer
;
7108 char **scan
= (*arg_pointer
);
7109 char *arg
= (*scan
++);
7111 if ((arg
!= 0) && (*arg
== ' '))
7117 *arg_pointer
= scan
;
7119 return ((arg
== 0) ? "" : arg
);
7122 /* Make the defun type insertion.
7123 TYPE says which insertion this is.
7124 X_P, if nonzero, says not to start a new insertion. */
7126 defun_internal (type
, x_p
)
7127 enum insertion_type type
;
7130 enum insertion_type base_type
;
7131 char **defun_args
, **scan_args
;
7132 char *category
, *defined_name
, *type_name
, *type_name2
;
7136 get_rest_of_line (&line
);
7137 defun_args
= (args_from_string (line
));
7141 scan_args
= defun_args
;
7146 category
= _("Function");
7150 category
= _("Macro");
7154 category
= _("Special Form");
7158 category
= _("Variable");
7162 category
= _("User Option");
7166 category
= _("Function");
7167 base_type
= deftypefn
;
7170 category
= _("Variable");
7171 base_type
= deftypevr
;
7174 category
= _("Instance Variable");
7178 category
= _("Method");
7182 category
= _("Method");
7183 base_type
= deftypemethod
;
7186 category
= next_nonwhite_defun_arg (&scan_args
);
7191 if ((base_type
== deftypefn
)
7192 || (base_type
== deftypevr
)
7193 || (base_type
== defcv
)
7194 || (base_type
== defop
)
7195 || (base_type
== deftypemethod
))
7196 type_name
= next_nonwhite_defun_arg (&scan_args
);
7198 if (base_type
== deftypemethod
)
7199 type_name2
= next_nonwhite_defun_arg (&scan_args
);
7201 defined_name
= next_nonwhite_defun_arg (&scan_args
);
7203 /* This hack exists solely for the purposes of formatting the texinfo
7204 manual. I couldn't think of a better way. The token might be
7205 a simple @@ followed immediately by more text. If this is the case,
7206 then the next defun arg is part of this one, and we should concatenate
7208 if (*scan_args
&& **scan_args
&& !whitespace (**scan_args
) &&
7209 (strcmp (defined_name
, "@@") == 0))
7211 char *tem
= (char *)xmalloc (3 + strlen (scan_args
[0]));
7213 sprintf (tem
, "@@%s", scan_args
[0]);
7215 free (scan_args
[0]);
7222 begin_insertion (type
);
7224 /* Write the definition header line.
7225 This should start at the normal indentation. */
7226 current_indent
-= default_indentation_increment
;
7234 execute_string (" -- %s: %s", category
, defined_name
);
7238 execute_string (" -- %s: %s %s", category
, type_name
, defined_name
);
7241 execute_string (" -- %s of %s: %s", category
, type_name
, defined_name
);
7244 execute_string (" -- %s on %s: %s", category
, type_name
, defined_name
);
7247 execute_string (" -- %s on %s: %s %s", category
, type_name
, type_name2
,
7251 current_indent
+= default_indentation_increment
;
7253 /* Now process the function arguments, if any.
7254 If these carry onto the next line, they should be indented by two
7255 increments to distinguish them from the body of the definition,
7256 which is indented by one increment. */
7257 current_indent
+= default_indentation_increment
;
7263 process_defun_args (scan_args
, 1);
7266 /* Through Makeinfo 1.67 we processed remaining args only for deftp,
7267 deftypefn, and deftypemethod. But the libc manual, for example,
7269 @deftypevar {char *} tzname[2]
7270 And simply allowing the extra text seems far simpler than trying
7271 to invent yet more defn commands. In any case, we should either
7272 output it or give an error, not silently ignore it. */
7274 process_defun_args (scan_args
, 0);
7277 current_indent
-= default_indentation_increment
;
7278 close_single_paragraph ();
7280 /* Make an entry in the appropriate index. */
7285 execute_string ("%cfindex %s\n", COMMAND_PREFIX
, defined_name
);
7290 execute_string ("%cvindex %s\n", COMMAND_PREFIX
, defined_name
);
7294 execute_string ("%cfindex %s on %s\n",
7295 COMMAND_PREFIX
, defined_name
, type_name
);
7298 execute_string ("%ctindex %s\n", COMMAND_PREFIX
, defined_name
);
7302 /* Deallocate the token list. */
7303 scan_args
= defun_args
;
7306 char * arg
= (*scan_args
++);
7314 /* Add an entry for a function, macro, special form, variable, or option.
7315 If the name of the calling command ends in `x', then this is an extra
7316 entry included in the body of an insertion of the same type. */
7321 enum insertion_type type
;
7322 char *temp
= xstrdup (command
);
7324 x_p
= (command
[strlen (command
) - 1] == 'x');
7327 temp
[strlen (temp
) - 1] = 0;
7329 type
= find_type_from_name (temp
);
7332 /* If we are adding to an already existing insertion, then make sure
7333 that we are already in an insertion of type TYPE. */
7335 (!insertion_level
|| insertion_stack
->insertion
!= type
))
7337 line_error (_("Must be in a `%s' insertion in order to use `%s'x"),
7339 discard_until ("\n");
7343 defun_internal (type
, x_p
);
7346 /* **************************************************************** */
7348 /* Other Random Commands */
7350 /* **************************************************************** */
7352 /* This says to inhibit the indentation of the next paragraph, but
7353 not of following paragraphs. */
7357 if (!inhibit_paragraph_indentation
)
7358 inhibit_paragraph_indentation
= -1;
7361 /* I don't know exactly what to do with this. Should I allow
7362 someone to switch filenames in the middle of output? Since the
7363 file could be partially written, this doesn't seem to make sense.
7364 Another option: ignore it, since they don't *really* want to
7365 switch files. Finally, complain, or at least warn. */
7370 get_rest_of_line (&filename
);
7371 /* warning ("`@%s %s' encountered and ignored", command, filename); */
7378 discard_until ("\n");
7381 /* @br can be immediately followed by `{}', so we have to read those here.
7382 It should simply close the paragraph. */
7386 if (looking_at ("{}"))
7387 input_text_offset
+= 2;
7389 if (curchar () == '\n')
7391 input_text_offset
++;
7398 /* Insert the number of blank lines passed as argument. */
7405 get_rest_of_line (&line
);
7407 if (sscanf (line
, "%d", &lines
) != 1)
7409 line_error (_("%csp requires a positive numeric argument"), COMMAND_PREFIX
);
7422 /* @dircategory LINE outputs INFO-DIR-SECTION LINE,
7423 but not if --no-headers. */
7430 get_rest_of_line (&line
);;
7434 insert_string ("INFO-DIR-SECTION ");
7435 insert_string (line
);
7442 /* Start a new line with just this text on it.
7443 Then center the line of text.
7444 This always ends the current paragraph. */
7448 register int i
, start
, length
;
7449 int fudge_factor
= 1;
7450 unsigned char *line
;
7453 filling_enabled
= indented_fill
= 0;
7455 start
= output_paragraph_offset
;
7456 inhibit_output_flushing ();
7457 get_rest_of_line ((char **)&line
);
7458 execute_string ("%s", (char *)line
);
7460 uninhibit_output_flushing ();
7462 i
= output_paragraph_offset
- 1;
7463 while (i
> (start
- 1) && output_paragraph
[i
] == '\n')
7466 output_paragraph_offset
= ++i
;
7467 length
= output_paragraph_offset
- start
;
7469 if (length
< (fill_column
- fudge_factor
))
7471 line
= (unsigned char *)xmalloc (1 + length
);
7472 memcpy (line
, (char *)(output_paragraph
+ start
), length
);
7474 i
= (fill_column
- fudge_factor
- length
) / 2;
7475 output_paragraph_offset
= start
;
7480 for (i
= 0; i
< length
; i
++)
7488 filling_enabled
= 1;
7491 /* Show what an expression returns. */
7500 /* What an expression expands to. */
7509 /* Indicates two expressions are equivalent. */
7518 /* What an expression may print. */
7527 /* An error signaled. */
7533 add_word ("error-->");
7536 /* The location of point in an example of a buffer. */
7545 /* Start a new line with just this text on it.
7546 The text is outdented one level if possible. */
7551 int i
= current_indent
;
7554 current_indent
-= default_indentation_increment
;
7556 get_rest_of_line (&line
);
7557 close_single_paragraph ();
7558 execute_string ("%s", line
);
7561 close_single_paragraph ();
7565 /* Remember this file, and move onto the next. */
7571 #if defined (HAVE_MACROS)
7572 if (macro_expansion_output_stream
&& !executing_string
)
7573 me_append_before_this_command ();
7574 #endif /* HAVE_MACROS */
7577 get_rest_of_line (&filename
);
7579 #if defined (HAVE_MACROS)
7580 if (macro_expansion_output_stream
&& !executing_string
)
7581 remember_itext (input_text
, input_text_offset
);
7582 #endif /* HAVE_MACROS */
7586 /* In verbose mode we print info about including another file. */
7590 register FSTACK
*stack
= filestack
;
7592 for (i
= 0, stack
= filestack
; stack
; stack
= stack
->next
, i
++);
7596 printf ("%*s", i
, "");
7597 printf ("%c%s %s\n", COMMAND_PREFIX
, command
, filename
);
7601 if (!find_and_load (filename
))
7608 /* Cannot "@include foo", in line 5 of "/wh/bar". */
7609 line_error ("%c%s %s: %s", COMMAND_PREFIX
, command
, filename
,
7617 #if defined (HAVE_MACROS)
7618 if (macro_expansion_output_stream
&& !executing_string
)
7619 remember_itext (input_text
, input_text_offset
);
7620 #endif /* HAVE_MACROS */
7627 /* The other side of a malformed expression. */
7631 line_error (_("Misplaced %c"), '}');
7634 /* Signals end of processing. Easy to make this happen. */
7638 input_text_offset
= size_of_input_text
;
7641 /* Set the paragraph indentation variable to the value specified in STRING.
7643 `asis': Don't change existing indentation.
7644 `none': Remove existing indentation.
7645 NUM: Indent NUM spaces at the starts of paragraphs.
7646 If NUM is zero, we assume `none'.
7647 Returns 0 if successful, or nonzero if STRING isn't one of the above. */
7649 set_paragraph_indent (string
)
7652 if (strcmp (string
, "asis") == 0 || strcmp (string
, _("asis")) == 0)
7653 paragraph_start_indent
= 0;
7654 else if (strcmp (string
, "none") == 0 || strcmp (string
, _("none")) == 0)
7655 paragraph_start_indent
= -1;
7658 if (sscanf (string
, "%d", ¶graph_start_indent
) != 1)
7662 if (paragraph_start_indent
== 0)
7663 paragraph_start_indent
= -1;
7670 cm_paragraphindent ()
7674 get_rest_of_line (&arg
);
7675 if (set_paragraph_indent (arg
) != 0)
7676 line_error (_("Bad argument to %c%s"), COMMAND_PREFIX
, command
);
7681 /* **************************************************************** */
7683 /* Indexing Stuff */
7685 /* **************************************************************** */
7688 /* An index element... */
7689 typedef struct index_elt
7691 struct index_elt
*next
;
7692 char *entry
; /* The index entry itself. */
7693 char *node
; /* The node from whence it came. */
7694 int code
; /* Nonzero means add `@code{...}' when
7695 printing this element. */
7696 int defining_line
; /* Line number where this entry was written. */
7697 char *defining_file
; /* Source file for defining_line. */
7700 /* A list of short-names for each index.
7702 There are two indices into the the_indices array.
7704 * read_index is the index that points to the list of index
7705 entries that we will find if we ask for the list of entries for
7708 * write_index is the index that points to the list of index entries
7709 that we will add new entries to.
7711 Initially, read_index and write index are the same, but the
7712 @syncodeindex and @synindex commands can change the list we add
7715 For example, after the commands
7722 the cp index will contain the entry `foo', and the new ii
7723 index will contain the entry `bar'. This is consistent with the
7724 way texinfo.tex handles the same situation.
7726 In addition, for each index, it is remembered whether that index is
7727 a code index or not. Code indices have @code{} inserted around the
7728 first word when they are printed with printindex. */
7732 int read_index
; /* index entries for `name' */
7733 int write_index
; /* store index entries here, @synindex can change it */
7737 INDEX_ALIST
**name_index_alist
= (INDEX_ALIST
**) NULL
;
7739 /* An array of pointers. Each one is for a different index. The
7740 "synindex" command changes which array slot is pointed to by a
7742 INDEX_ELT
**the_indices
= (INDEX_ELT
**) NULL
;
7744 /* The number of defined indices. */
7745 int defined_indices
= 0;
7752 /* Create the default data structures. */
7754 /* Initialize data space. */
7757 the_indices
= (INDEX_ELT
**) xmalloc ((1 + defined_indices
) *
7758 sizeof (INDEX_ELT
*));
7759 the_indices
[defined_indices
] = (INDEX_ELT
*) NULL
;
7761 name_index_alist
= (INDEX_ALIST
**) xmalloc ((1 + defined_indices
) *
7762 sizeof (INDEX_ALIST
*));
7763 name_index_alist
[defined_indices
] = (INDEX_ALIST
*) NULL
;
7766 /* If there were existing indices, get rid of them now. */
7767 for (i
= 0; i
< defined_indices
; i
++)
7769 undefindex (name_index_alist
[i
]->name
);
7770 if (name_index_alist
[i
])
7771 { /* Suppose we're called with two input files, and the first
7772 does a @synindex pg cp. Then, when we get here to start
7773 the second file, the "pg" element won't get freed by
7774 undefindex (because it's pointing to "cp"). So free it
7775 here; otherwise, when we try to define the pg index again
7776 just below, it will still point to cp. */
7777 free (name_index_alist
[i
]->name
);
7778 free (name_index_alist
[i
]);
7779 name_index_alist
[i
] = (INDEX_ALIST
*) NULL
;
7783 /* Add the default indices. */
7784 top_defindex ("cp", 0); /* cp is the only non-code index. */
7785 top_defindex ("fn", 1);
7786 top_defindex ("ky", 1);
7787 top_defindex ("pg", 1);
7788 top_defindex ("tp", 1);
7789 top_defindex ("vr", 1);
7792 /* Find which element in the known list of indices has this name.
7793 Returns -1 if NAME isn't found. */
7795 find_index_offset (name
)
7799 for (i
= 0; i
< defined_indices
; i
++)
7800 if (name_index_alist
[i
] &&
7801 strcmp (name
, name_index_alist
[i
]->name
) == 0)
7806 /* Return a pointer to the entry of (name . index) for this name.
7807 Return NULL if the index doesn't exist. */
7812 int offset
= find_index_offset (name
);
7814 return (name_index_alist
[offset
]);
7816 return ((INDEX_ALIST
*) NULL
);
7819 /* Given an index name, return the offset in the_indices of this index,
7820 or -1 if there is no such index. */
7822 translate_index (name
)
7825 INDEX_ALIST
*which
= find_index (name
);
7828 return (which
->read_index
);
7833 /* Return the index list which belongs to NAME. */
7838 int which
= translate_index (name
);
7840 return ((INDEX_ELT
*) -1);
7842 return (the_indices
[which
]);
7845 /* Please release me, let me go... */
7852 while ((temp
= index
) != (INDEX_ELT
*) NULL
)
7855 /* Do not free the node, because we already freed the tag table,
7856 which freed all the node names. */
7857 /* free (temp->node); */
7858 index
= index
->next
;
7863 /* Flush an index by name. This will delete the list of entries that
7864 would be written by a @printindex command for this index. */
7870 int which
= find_index_offset (name
);
7872 /* The index might have already been freed if this was the target of
7874 if (which
< 0 || !name_index_alist
[which
])
7877 i
= name_index_alist
[which
]->read_index
;
7879 free_index (the_indices
[i
]);
7880 the_indices
[i
] = (INDEX_ELT
*) NULL
;
7882 free (name_index_alist
[which
]->name
);
7883 free (name_index_alist
[which
]);
7884 name_index_alist
[which
] = (INDEX_ALIST
*) NULL
;
7887 /* Define an index known as NAME. We assign the slot number.
7888 CODE if Nonzero says to make this a code index. */
7890 defindex (name
, code
)
7894 register int i
, slot
;
7896 /* If it already exists, flush it. */
7899 /* Try to find an empty slot. */
7901 for (i
= 0; i
< defined_indices
; i
++)
7902 if (!name_index_alist
[i
])
7910 /* No such luck. Make space for another index. */
7911 slot
= defined_indices
;
7914 name_index_alist
= (INDEX_ALIST
**)
7915 xrealloc ((char *)name_index_alist
,
7916 (1 + defined_indices
) * sizeof (INDEX_ALIST
*));
7917 the_indices
= (INDEX_ELT
**)
7918 xrealloc ((char *)the_indices
,
7919 (1 + defined_indices
) * sizeof (INDEX_ELT
*));
7922 /* We have a slot. Start assigning. */
7923 name_index_alist
[slot
] = (INDEX_ALIST
*) xmalloc (sizeof (INDEX_ALIST
));
7924 name_index_alist
[slot
]->name
= xstrdup (name
);
7925 name_index_alist
[slot
]->read_index
= slot
;
7926 name_index_alist
[slot
]->write_index
= slot
;
7927 name_index_alist
[slot
]->code
= code
;
7929 the_indices
[slot
] = (INDEX_ELT
*) NULL
;
7932 /* Add the arguments to the current index command to the index NAME. */
7934 index_add_arg (name
)
7941 tem
= find_index (name
);
7943 which
= tem
? tem
->write_index
: -1;
7945 #if defined (HAVE_MACROS)
7946 if (macro_expansion_output_stream
&& !executing_string
)
7947 append_to_expansion_output (input_text_offset
+ 1);
7948 #endif /* HAVE_MACROS */
7950 get_rest_of_line (&index_entry
);
7951 ignore_blank_line ();
7953 #if defined (HAVE_MACROS)
7954 if (macro_expansion_output_stream
&& !executing_string
)
7958 remember_itext (input_text
, input_text_offset
);
7959 op_orig
= output_paragraph_offset
;
7960 me_execute_string (index_entry
);
7961 me_execute_string ("\n");
7962 output_paragraph_offset
= op_orig
;
7964 #endif /* HAVE_MACROS */
7968 line_error (_("Unknown index `%s'"), name
);
7973 INDEX_ELT
*new = (INDEX_ELT
*) xmalloc (sizeof (INDEX_ELT
));
7974 new->next
= the_indices
[which
];
7975 new->entry
= index_entry
;
7976 new->node
= current_node
;
7977 new->code
= tem
->code
;
7978 new->defining_line
= line_number
- 1;
7979 new->defining_file
= input_filename
;
7980 the_indices
[which
] = new;
7984 #define INDEX_COMMAND_SUFFIX "index"
7986 /* The function which user defined index commands call. */
7990 char *name
= xstrdup (command
);
7991 if (strlen (name
) >= strlen ("index"))
7992 name
[strlen (name
) - strlen ("index")] = 0;
7993 index_add_arg (name
);
7998 top_defindex (name
, code
)
8004 temp
= (char *) xmalloc (1 + strlen (name
) + strlen ("index"));
8005 sprintf (temp
, "%sindex", name
);
8006 define_user_command (temp
, gen_index
, 0);
8007 defindex (name
, code
);
8011 /* Define a new index command. Arg is name of index. */
8029 get_rest_of_line (&name
);
8031 if (find_index (name
))
8033 line_error (_("Index `%s' already exists"), name
);
8039 char *temp
= (char *) alloca (1 + strlen (name
) + strlen ("index"));
8040 sprintf (temp
, "%sindex", name
);
8041 define_user_command (temp
, gen_index
, 0);
8042 defindex (name
, code
);
8047 /* Expects 2 args, on the same line. Both are index abbreviations.
8048 Make the first one be a synonym for the second one, i.e. make the
8049 first one have the same index as the second one. */
8054 char *abbrev1
, *abbrev2
;
8057 get_until_in_line (0, " ", &abbrev1
);
8058 target
= find_index_offset (abbrev1
);
8060 get_until_in_line (0, " ", &abbrev2
);
8061 source
= find_index_offset (abbrev2
);
8062 if (source
< 0 || target
< 0)
8064 line_error (_("Unknown index `%s' and/or `%s' in @synindex"),
8069 name_index_alist
[target
]->write_index
8070 = name_index_alist
[source
]->write_index
;
8078 cm_pindex () /* Pinhead index. */
8080 index_add_arg ("pg");
8084 cm_vindex () /* Variable index. */
8086 index_add_arg ("vr");
8090 cm_kindex () /* Key index. */
8092 index_add_arg ("ky");
8096 cm_cindex () /* Concept index. */
8098 index_add_arg ("cp");
8102 cm_findex () /* Function index. */
8104 index_add_arg ("fn");
8108 cm_tindex () /* Data Type index. */
8110 index_add_arg ("tp");
8113 /* Sorting the index. */
8115 index_element_compare (element1
, element2
)
8116 INDEX_ELT
**element1
, **element2
;
8118 return (strcasecmp ((*element1
)->entry
, (*element2
)->entry
));
8121 /* Force all index entries to be unique. */
8123 make_index_entries_unique (array
, count
)
8131 copy
= (INDEX_ELT
**)xmalloc ((1 + count
) * sizeof (INDEX_ELT
*));
8133 for (i
= 0, j
= 0; i
< count
; i
++)
8135 if ((i
== (count
- 1)) ||
8136 (array
[i
]->node
!= array
[i
+ 1]->node
) ||
8137 (strcmp (array
[i
]->entry
, array
[i
+ 1]->entry
) != 0))
8138 copy
[j
++] = array
[i
];
8141 free (array
[i
]->entry
);
8145 copy
[j
] = (INDEX_ELT
*)NULL
;
8147 /* Now COPY contains only unique entries. Duplicated entries in the
8148 original array have been freed. Replace the current array with
8149 the copy, fixing the NEXT pointers. */
8150 for (i
= 0; copy
[i
] != (INDEX_ELT
*)NULL
; i
++)
8153 copy
[i
]->next
= copy
[i
+ 1];
8155 /* Fix entry names which are the same. They point to different nodes,
8156 so we make the entry name unique. */
8157 if ((copy
[i
+ 1] != (INDEX_ELT
*)NULL
) &&
8158 (strcmp (copy
[i
]->entry
, copy
[i
+ 1]->entry
) == 0))
8160 char *new_entry_name
;
8162 new_entry_name
= (char *)xmalloc (10 + strlen (copy
[i
]->entry
));
8163 sprintf (new_entry_name
, "%s <%d>", copy
[i
]->entry
, counter
);
8164 free (copy
[i
]->entry
);
8165 copy
[i
]->entry
= new_entry_name
;
8173 array
[i
] = (INDEX_ELT
*)NULL
;
8175 /* Free the storage used only by COPY. */
8179 /* Sort the index passed in INDEX, returning an array of
8180 pointers to elements. The array is terminated with a NULL
8181 pointer. We call qsort because it's supposed to be fast.
8182 I think this looks bad. */
8188 INDEX_ELT
*temp
= index
;
8190 int save_line_number
= line_number
;
8191 char *save_input_filename
= input_filename
;
8193 while (temp
!= (INDEX_ELT
*) NULL
)
8199 /* We have the length. Make an array. */
8201 array
= (INDEX_ELT
**) xmalloc ((count
+ 1) * sizeof (INDEX_ELT
*));
8205 while (temp
!= (INDEX_ELT
*) NULL
)
8207 array
[count
++] = temp
;
8209 /* Set line number and input filename to the source line for this
8210 index entry, as this expansion finds any errors. */
8211 line_number
= array
[count
- 1]->defining_line
;
8212 input_filename
= array
[count
- 1]->defining_file
;
8214 /* If this particular entry should be printed as a "code" index,
8215 then wrap the entry with "@code{...}". */
8216 array
[count
- 1]->entry
= expansion (temp
->entry
, index
->code
);
8220 array
[count
] = (INDEX_ELT
*) NULL
; /* terminate the array. */
8221 line_number
= save_line_number
;
8222 input_filename
= save_input_filename
;
8224 /* Sort the array. */
8225 qsort (array
, count
, sizeof (INDEX_ELT
*), index_element_compare
);
8226 make_index_entries_unique (array
, count
);
8230 /* Nonzero means that we are in the middle of printing an index. */
8231 int printing_index
= 0;
8233 /* Takes one arg, a short name of an index to print.
8234 Outputs a menu of the sorted elements of the index. */
8242 unsigned line_length
;
8244 int saved_inhibit_paragraph_indentation
= inhibit_paragraph_indentation
;
8245 int saved_filling_enabled
= filling_enabled
;
8248 get_rest_of_line (&index_name
);
8250 index
= index_list (index_name
);
8251 if (index
== (INDEX_ELT
*)-1)
8253 line_error (_("Unknown index `%s' in @printindex"), index_name
);
8260 /* Do this before sorting, so execute_string in index_element_compare
8261 will give the same results as when we actually print. */
8263 filling_enabled
= 0;
8264 inhibit_paragraph_indentation
= 1;
8265 array
= sort_index (index
);
8268 add_word (_("* Menu:\n\n"));
8270 #if defined (HAVE_MACROS)
8271 me_inhibit_expansion
++;
8272 #endif /* HAVE_MACROS */
8274 /* This will probably be enough. */
8276 line
= xmalloc (line_length
);
8278 for (item
= 0; (index
= array
[item
]); item
++)
8280 /* A pathological document might have an index entry outside of any
8281 node. Don't crash. Perhaps should warn. */
8282 char *index_node
= index
->node
? index
->node
: "(none)";
8283 unsigned new_length
= strlen (index
->entry
);
8285 if (new_length
< 37) /* minimum length used below */
8287 new_length
+= strlen (index_node
) + 7; /* * : .\n\0 */
8289 if (new_length
> line_length
)
8291 line_length
= new_length
;
8292 line
= xrealloc (line
, line_length
);
8295 /* Print the entry, nicely formatted. We've already expanded any
8296 commands, including any implicit @code. Thus, can't call
8297 execute_string, since @@ has turned into @. */
8298 sprintf (line
, "* %-37s %s.\n", index
->entry
, index_node
);
8299 line
[2 + strlen (index
->entry
)] = ':';
8300 insert_string (line
);
8302 /* Previous `output_paragraph' from growing to the size of the
8309 #if defined (HAVE_MACROS)
8310 me_inhibit_expansion
--;
8311 #endif /* HAVE_MACROS */
8315 close_single_paragraph ();
8316 filling_enabled
= saved_filling_enabled
;
8317 inhibit_paragraph_indentation
= saved_inhibit_paragraph_indentation
;
8320 /* User-defined commands, which happens only from user-defined indexes. */
8323 define_user_command (name
, proc
, needs_braces_p
)
8325 COMMAND_FUNCTION
*proc
;
8328 int slot
= user_command_array_len
;
8329 user_command_array_len
++;
8331 if (!user_command_array
)
8332 user_command_array
= (COMMAND
**) xmalloc (1 * sizeof (COMMAND
*));
8334 user_command_array
= (COMMAND
**) xrealloc (user_command_array
,
8335 (1 + user_command_array_len
) *
8336 sizeof (COMMAND
*));
8338 user_command_array
[slot
] = (COMMAND
*) xmalloc (sizeof (COMMAND
));
8339 user_command_array
[slot
]->name
= xstrdup (name
);
8340 user_command_array
[slot
]->proc
= proc
;
8341 user_command_array
[slot
]->argument_in_braces
= needs_braces_p
;
8344 /* Some support for footnotes. */
8346 /* Footnotes are a new construct in Info. We don't know the best method
8347 of implementing them for sure, so we present two possiblities.
8350 Make them look like followed references, with the reference
8351 destinations in a makeinfo manufactured node or,
8354 Make them appear at the bottom of the node that they originally
8356 #define SeparateNode 0
8359 int footnote_style
= EndNode
;
8360 int first_footnote_this_node
= 1;
8361 int footnote_count
= 0;
8363 /* Set the footnote style based on he style identifier in STRING. */
8365 set_footnote_style (string
)
8368 if ((strcasecmp (string
, "separate") == 0) ||
8369 (strcasecmp (string
, "MN") == 0))
8370 footnote_style
= SeparateNode
;
8371 else if ((strcasecmp (string
, "end") == 0) ||
8372 (strcasecmp (string
, "EN") == 0))
8373 footnote_style
= EndNode
;
8385 get_rest_of_line (&arg
);
8387 /* If set on command line, do not change the footnote style. */
8388 if (!footnote_style_preset
&& set_footnote_style (arg
) != 0)
8389 line_error ("Bad argument to %c%s", COMMAND_PREFIX
, command
);
8401 FN
*pending_notes
= (FN
*) NULL
;
8403 /* A method for remembering footnotes. Note that this list gets output
8404 at the end of the current node. */
8406 remember_note (marker
, note
)
8407 char *marker
, *note
;
8409 FN
*temp
= (FN
*) xmalloc (sizeof (FN
));
8411 temp
->marker
= xstrdup (marker
);
8412 temp
->note
= xstrdup (note
);
8413 temp
->next
= pending_notes
;
8414 pending_notes
= temp
;
8418 /* How to get rid of existing footnotes. */
8420 free_pending_notes ()
8424 while ((temp
= pending_notes
) != (FN
*) NULL
)
8426 free (temp
->marker
);
8428 pending_notes
= pending_notes
->next
;
8431 first_footnote_this_node
= 1;
8435 /* What to do when you see a @footnote construct. */
8437 /* Handle a "footnote".
8438 footnote *{this is a footnote}
8439 where "*" is the (optional) marker character for this note. */
8446 get_until ("{", &marker
);
8447 canon_white (marker
);
8449 if (macro_expansion_output_stream
&& !executing_string
)
8450 append_to_expansion_output (input_text_offset
+ 1); /* include the { */
8452 /* Read the argument in braces. */
8453 if (curchar () != '{')
8455 line_error (_("`%c%s' needs an argument `{...}', not just `%s'"),
8456 COMMAND_PREFIX
, command
, marker
);
8464 int loc
= ++input_text_offset
;
8468 if (loc
== size_of_input_text
)
8470 line_error (_("No closing brace for footnote `%s'"), marker
);
8474 if (input_text
[loc
] == '{')
8476 else if (input_text
[loc
] == '}')
8478 else if (input_text
[loc
] == '\n')
8484 len
= (loc
- input_text_offset
) - 1;
8485 note
= (char *)xmalloc (len
+ 1);
8486 strncpy (note
, &input_text
[input_text_offset
], len
);
8488 input_text_offset
= loc
;
8491 /* Must write the macro-expanded argument to the macro expansion
8492 output stream. This is like the case in index_add_arg. */
8493 if (macro_expansion_output_stream
&& !executing_string
)
8497 remember_itext (input_text
, input_text_offset
);
8498 op_orig
= output_paragraph_offset
;
8499 me_execute_string (note
);
8500 /* Calling me_execute_string on a lone } provokes an error, since
8501 as far as the reader knows there is no matching {. We wrote
8502 the { above in the call to append_to_expansion_output. */
8503 write_region_to_macro_output ("}", 0, 1);
8504 output_paragraph_offset
= op_orig
;
8507 if (!current_node
|| !*current_node
)
8509 line_error (_("Footnote defined without parent node"));
8519 if (number_footnotes
)
8521 marker
= (char *)xmalloc (10);
8522 sprintf (marker
, "%d", current_footnote_number
);
8523 current_footnote_number
++;
8526 marker
= xstrdup ("*");
8529 remember_note (marker
, note
);
8531 /* Your method should at least insert MARKER. */
8532 switch (footnote_style
)
8535 add_word_args ("(%s)", marker
);
8536 if (first_footnote_this_node
)
8540 temp_string
= (char *)
8541 xmalloc ((strlen (current_node
)) + (strlen (_("-Footnotes"))) + 1);
8543 add_word_args (" (*note %s-Footnotes::)", current_node
);
8544 strcpy (temp_string
, current_node
);
8545 strcat (temp_string
, "-Footnotes");
8546 remember_node_reference (temp_string
, line_number
, followed_reference
);
8548 first_footnote_this_node
= 0;
8553 add_word_args ("(%s)", marker
);
8563 /* Nonzero means that we are currently in the process of outputting
8565 int already_outputting_pending_notes
= 0;
8567 /* Output the footnotes. We are at the end of the current node. */
8569 output_pending_notes ()
8571 FN
*footnote
= pending_notes
;
8576 switch (footnote_style
)
8580 char *old_current_node
= current_node
;
8581 char *old_command
= xstrdup (command
);
8583 already_outputting_pending_notes
++;
8584 execute_string ("%cnode %s-Footnotes,,,%s\n",
8585 COMMAND_PREFIX
, current_node
, current_node
);
8586 already_outputting_pending_notes
--;
8587 current_node
= old_current_node
;
8589 command
= old_command
;
8595 in_fixed_width_font
++;
8596 execute_string (_("---------- Footnotes ----------\n\n"));
8597 in_fixed_width_font
--;
8601 /* Handle the footnotes in reverse order. */
8603 FN
**array
= (FN
**) xmalloc ((footnote_count
+ 1) * sizeof (FN
*));
8605 array
[footnote_count
] = (FN
*) NULL
;
8607 while (--footnote_count
> -1)
8609 array
[footnote_count
] = footnote
;
8610 footnote
= footnote
->next
;
8613 filling_enabled
= 1;
8616 while ((footnote
= array
[++footnote_count
]))
8618 execute_string ("(%s) %s", footnote
->marker
, footnote
->note
);
8626 /* **************************************************************** */
8628 /* User definable Macros (text substitution) */
8630 /* **************************************************************** */
8632 #if defined (HAVE_MACROS)
8634 /* Array of macros and definitions. */
8635 MACRO_DEF
**macro_list
= (MACRO_DEF
**)NULL
;
8637 int macro_list_len
= 0; /* Number of elements. */
8638 int macro_list_size
= 0; /* Number of slots in total. */
8640 /* Return the macro definition of NAME or NULL if NAME is not defined. */
8646 register MACRO_DEF
*def
;
8648 def
= (MACRO_DEF
*)NULL
;
8649 for (i
= 0; macro_list
&& (def
= macro_list
[i
]); i
++)
8651 if ((!def
->inhibited
) && (strcmp (def
->name
, name
) == 0))
8657 /* Add the macro NAME with ARGLIST and BODY to the list of defined macros.
8658 SOURCE_FILE is the name of the file where this definition can be found,
8659 and SOURCE_LINENO is the line number within that file. If a macro already
8660 exists with NAME, then a warning is produced, and that previous
8661 definition is overwritten. */
8663 add_macro (name
, arglist
, body
, source_file
, source_lineno
, flags
)
8668 int source_lineno
, flags
;
8670 register MACRO_DEF
*def
;
8672 def
= find_macro (name
);
8676 if (macro_list_len
+ 2 >= macro_list_size
)
8677 macro_list
= (MACRO_DEF
**)xrealloc
8678 (macro_list
, ((macro_list_size
+= 10) * sizeof (MACRO_DEF
*)));
8680 macro_list
[macro_list_len
] = (MACRO_DEF
*)xmalloc (sizeof (MACRO_DEF
));
8681 macro_list
[macro_list_len
+ 1] = (MACRO_DEF
*)NULL
;
8683 def
= macro_list
[macro_list_len
];
8684 macro_list_len
+= 1;
8689 char *temp_filename
= input_filename
;
8690 int temp_line
= line_number
;
8692 warning (_("macro `%s' previously defined"), name
);
8694 input_filename
= def
->source_file
;
8695 line_number
= def
->source_lineno
;
8696 warning (_("here is the previous definition of `%s'"), name
);
8698 input_filename
= temp_filename
;
8699 line_number
= temp_line
;
8705 for (i
= 0; def
->arglist
[i
]; i
++)
8706 free (def
->arglist
[i
]);
8708 free (def
->arglist
);
8710 free (def
->source_file
);
8714 def
->source_file
= xstrdup (source_file
);
8715 def
->source_lineno
= source_lineno
;
8717 def
->arglist
= arglist
;
8722 /* Delete the macro with name NAME. The macro is deleted from the list,
8723 but it is also returned. If there was no macro defined, NULL is
8730 register MACRO_DEF
*def
;
8732 def
= (MACRO_DEF
*)NULL
;
8734 for (i
= 0; macro_list
&& (def
= macro_list
[i
]); i
++)
8735 if (strcmp (def
->name
, name
) == 0)
8737 memmove (macro_list
+ i
, macro_list
+ i
+ 1,
8738 ((macro_list_len
+ 1) - i
) * sizeof (MACRO_DEF
*));
8745 /* Return the arglist on the current line. This can behave in two different
8746 ways, depending on the variable BRACES_REQUIRED_FOR_MACRO_ARGS. */
8747 int braces_required_for_macro_args
= 0;
8750 get_macro_args (def
)
8756 /* Quickly check to see if this macro has been invoked with any arguments.
8757 If not, then don't skip any of the following whitespace. */
8758 for (i
= input_text_offset
; i
< size_of_input_text
; i
++)
8759 if (!cr_or_whitespace (input_text
[i
]))
8762 if (input_text
[i
] != '{')
8764 if (braces_required_for_macro_args
)
8766 return ((char **)NULL
);
8770 /* Braces are not required to fill out the macro arguments. If
8771 this macro takes one argument, it is considered to be the
8772 remainder of the line, sans whitespace. */
8773 if (def
->arglist
&& def
->arglist
[0] && !def
->arglist
[1])
8777 get_rest_of_line (&word
);
8778 if (input_text
[input_text_offset
- 1] == '\n')
8780 input_text_offset
--;
8783 /* canon_white (word); */
8784 arglist
= (char **)xmalloc (2 * sizeof (char *));
8786 arglist
[1] = (char *)NULL
;
8791 /* The macro either took no arguments, or took more than
8792 one argument. In that case, it must be invoked with
8793 arguments surrounded by braces. */
8794 return ((char **)NULL
);
8798 return (get_brace_args (def
->flags
& ME_QUOTE_ARG
));
8801 /* Substitute actual parameters for named parameters in body.
8802 The named parameters which appear in BODY must by surrounded
8803 reverse slashes, as in \foo\. */
8805 apply (named
, actuals
, body
)
8806 char **named
, **actuals
, *body
;
8809 int new_body_index
, new_body_size
;
8810 char *new_body
, *text
;
8811 int length_of_actuals
;
8813 length_of_actuals
= array_len (actuals
);
8814 new_body_size
= strlen (body
);
8815 new_body
= (char *)xmalloc (1 + new_body_size
);
8817 /* Copy chars from BODY into NEW_BODY. */
8818 i
= 0; new_body_index
= 0;
8825 if (body
[i
] != '\\')
8826 new_body
[new_body_index
++] = body
[i
++];
8829 /* Snarf parameter name, check against named parameters. */
8831 int param_start
, which
, len
;
8834 while ((body
[i
]) && (body
[i
] != '\\'))
8837 len
= i
- param_start
;
8838 param
= (char *)xmalloc (1 + len
);
8839 memcpy (param
, body
+ param_start
, len
);
8842 if (body
[i
]) /* move past \ */
8845 /* Now check against named parameters. */
8846 for (which
= 0; named
&& named
[which
]; which
++)
8847 if (strcmp (named
[which
], param
) == 0)
8850 if (named
&& named
[which
])
8852 if (which
< length_of_actuals
)
8853 text
= actuals
[which
];
8855 text
= (char *)NULL
;
8860 len
= strlen (text
);
8863 { /* not a parameter, restore \'s */
8864 i
= body
[i
] ? (i
- 1) : i
;
8866 text
= xmalloc (1 + len
);
8867 sprintf (text
, "\\%s", param
);
8870 if ((2 + strlen (param
)) < len
)
8872 new_body_size
+= len
+ 1;
8873 new_body
= xrealloc (new_body
, new_body_size
);
8878 strcpy (new_body
+ new_body_index
, text
);
8879 new_body_index
+= len
;
8881 if (!named
|| !named
[which
])
8885 new_body
[new_body_index
] = 0;
8889 /* Execute the macro passed in DEF, a pointer to a MACRO_DEF. */
8896 char *execution_string
= (char *)NULL
;
8898 if (macro_expansion_output_stream
&& !executing_string
&& !me_inhibit_expansion
)
8899 me_append_before_this_command ();
8901 /* Find out how many arguments this macro definition takes. */
8902 num_args
= array_len (def
->arglist
);
8904 /* Gather the arguments present on the line if there are any. */
8905 arglist
= get_macro_args (def
);
8907 if (num_args
< array_len (arglist
))
8909 free_array (arglist
);
8910 line_error (_("Macro `%s' called with too many args"), def
->name
);
8915 execution_string
= apply (def
->arglist
, arglist
, def
->body
);
8917 free_array (arglist
);
8921 if (macro_expansion_output_stream
&& !executing_string
&& !me_inhibit_expansion
)
8923 remember_itext (input_text
, input_text_offset
);
8924 me_execute_string (execution_string
);
8927 execute_string ("%s", execution_string
);
8929 free (execution_string
);
8933 /* Read and remember the definition of a macro. */
8938 char *name
, **arglist
, *body
, *line
;
8939 int body_size
, body_index
;
8941 int defining_line
= line_number
;
8944 arglist
= (char **)NULL
;
8945 body
= (char *)NULL
;
8949 if (macro_expansion_output_stream
&& !executing_string
)
8950 me_append_before_this_command ();
8954 /* Get the name of the macro. This is the set of characters which are
8955 not whitespace and are not `{' immediately following the @macro. */
8957 int start
= input_text_offset
;
8961 (i
< size_of_input_text
) &&
8962 (input_text
[i
] != '{') &&
8963 (!cr_or_whitespace (input_text
[i
]));
8967 name
= (char *)xmalloc (1 + len
);
8968 strncpy (name
, input_text
+ start
, len
);
8970 input_text_offset
= i
;
8975 /* It is not required that the definition of a macro includes an arglist.
8976 If not, don't try to get the named parameters, just use a null list. */
8977 if (curchar () == '{')
8979 int arglist_index
= 0, arglist_size
= 0;
8980 int gathering_words
= 1;
8981 char *word
= (char *)NULL
;
8984 /* Read the words inside of the braces which determine the arglist.
8985 These words will be replaced within the body of the macro at
8988 input_text_offset
++;
8989 skip_whitespace_and_newlines ();
8991 while (gathering_words
)
8995 for (i
= input_text_offset
;
8996 (character
= input_text
[i
]);
9007 /* Found the end of the current arglist word. Save it. */
9008 len
= i
- input_text_offset
;
9009 word
= (char *)xmalloc (1 + len
);
9010 strncpy (word
, input_text
+ input_text_offset
, len
);
9012 input_text_offset
= i
;
9014 /* Advance to the comma or close-brace that signified
9015 the end of the argument. */
9016 while ((character
= curchar ())
9018 && character
!= '}')
9020 input_text_offset
++;
9021 if (character
== '\n')
9025 /* Add the word to our list of words. */
9026 if ((arglist_index
+ 2) >= arglist_size
)
9027 arglist
= (char **)xrealloc
9028 (arglist
, (arglist_size
+= 10) * sizeof (char *));
9030 arglist
[arglist_index
++] = word
;
9031 arglist
[arglist_index
] = (char *)NULL
;
9035 if (character
== '}')
9037 input_text_offset
++;
9038 gathering_words
= 0;
9042 if (character
== ',')
9044 input_text_offset
++;
9045 skip_whitespace_and_newlines ();
9046 i
= input_text_offset
- 1;
9052 /* Read the text carefully until we find an "@end macro" which
9053 matches this one. The text in between is the body of the macro. */
9054 skip_whitespace_and_newlines ();
9058 if ((input_text_offset
+ 9) > size_of_input_text
)
9060 int temp_line
= line_number
;
9061 line_number
= defining_line
;
9062 line_error (_("%cend macro not found"), COMMAND_PREFIX
);
9063 line_number
= temp_line
;
9067 get_rest_of_line (&line
);
9069 /* Handle commands only meaningful within a macro. */
9070 if ((*line
== COMMAND_PREFIX
) && (depth
== 1) &&
9071 (strncmp (line
+ 1, "allow-recursion", 15) == 0) &&
9072 (line
[16] == 0 || whitespace (line
[16])))
9074 for (i
= 16; whitespace (line
[i
]); i
++);
9075 strcpy (line
, line
+ i
);
9076 flags
|= ME_RECURSE
;
9084 if ((*line
== COMMAND_PREFIX
) && (depth
== 1) &&
9085 (strncmp (line
+ 1, "quote-arg", 9) == 0) &&
9086 (line
[10] == 0 || whitespace (line
[10])))
9088 for (i
= 10; whitespace (line
[i
]); i
++);
9089 strcpy (line
, line
+ i
);
9091 if (arglist
&& arglist
[0] && !arglist
[1])
9093 flags
|= ME_QUOTE_ARG
;
9102 line_error (_("%cquote-arg only useful when the macro takes a single argument"),
9107 if ((*line
== COMMAND_PREFIX
) &&
9108 (strncmp (line
+ 1, "macro ", 6) == 0))
9111 if ((*line
== COMMAND_PREFIX
) &&
9112 (strncmp (line
+ 1, "end macro", 9) == 0))
9117 if ((body_index
+ strlen (line
) + 3) >= body_size
)
9118 body
= (char *)xrealloc
9119 (body
, body_size
+= 3 + strlen (line
));
9120 strcpy (body
+ body_index
, line
);
9121 body_index
+= strlen (line
);
9122 body
[body_index
++] = '\n';
9123 body
[body_index
] = 0;
9128 /* If it was an empty macro like
9131 create an empty body. (Otherwise, the macro is not expanded.) */
9134 body
= (char *)malloc(1);
9138 /* We now have the name, the arglist, and the body. However, BODY
9139 includes the final newline which preceded the `@end macro' text.
9141 if (body
&& strlen (body
))
9142 body
[strlen (body
) - 1] = 0;
9144 add_macro (name
, arglist
, body
, input_filename
, defining_line
, flags
);
9146 if (macro_expansion_output_stream
&& !executing_string
)
9147 remember_itext (input_text
, input_text_offset
);
9157 if (macro_expansion_output_stream
&& !executing_string
)
9158 me_append_before_this_command ();
9160 get_rest_of_line (&line
);
9162 for (i
= 0; line
[i
] && !whitespace (line
[i
]); i
++);
9163 name
= (char *)xmalloc (i
+ 1);
9164 strncpy (name
, line
, i
);
9167 def
= delete_macro (name
);
9171 free (def
->source_file
);
9179 for (i
= 0; def
->arglist
[i
]; i
++)
9180 free (def
->arglist
[i
]);
9182 free (def
->arglist
);
9191 if (macro_expansion_output_stream
&& !executing_string
)
9192 remember_itext (input_text
, input_text_offset
);
9195 /* How to output sections of the input file verbatim. */
9197 /* Set the value of POINTER's offset to OFFSET. */
9199 remember_itext (pointer
, offset
)
9204 ITEXT
*itext
= (ITEXT
*)NULL
;
9206 /* If we have no info, initialize a blank list. */
9209 itext_info
= (ITEXT
**)xmalloc ((itext_size
= 10) * sizeof (ITEXT
*));
9210 for (i
= 0; i
< itext_size
; i
++)
9211 itext_info
[i
] = (ITEXT
*)NULL
;
9214 /* If the pointer is already present in the list, then set the offset. */
9215 for (i
= 0; i
< itext_size
; i
++)
9216 if ((itext_info
[i
] != (ITEXT
*)NULL
) &&
9217 (itext_info
[i
]->pointer
== pointer
))
9219 itext
= itext_info
[i
];
9220 itext_info
[i
]->offset
= offset
;
9224 if (i
== itext_size
)
9226 /* Find a blank slot (or create a new one), and remember the
9227 pointer and offset. */
9228 for (i
= 0; i
< itext_size
; i
++)
9229 if (itext_info
[i
] == (ITEXT
*)NULL
)
9232 /* If not found, then add some slots. */
9233 if (i
== itext_size
)
9237 itext_info
= (ITEXT
**)xrealloc
9238 (itext_info
, (itext_size
+= 10) * sizeof (ITEXT
*));
9240 for (j
= i
; j
< itext_size
; j
++)
9241 itext_info
[j
] = (ITEXT
*)NULL
;
9244 /* Now add the pointer and the offset. */
9245 itext_info
[i
] = (ITEXT
*)xmalloc (sizeof (ITEXT
));
9246 itext_info
[i
]->pointer
= pointer
;
9247 itext_info
[i
]->offset
= offset
;
9248 itext
= itext_info
[i
];
9253 /* Forget the input text associated with POINTER. */
9255 forget_itext (pointer
)
9260 for (i
= 0; i
< itext_size
; i
++)
9261 if (itext_info
[i
] && (itext_info
[i
]->pointer
== pointer
))
9263 free (itext_info
[i
]);
9264 itext_info
[i
] = (ITEXT
*)NULL
;
9269 /* Append the text which appeared in input_text from the last offset to
9270 the character just before the command that we are currently executing. */
9272 me_append_before_this_command ()
9276 for (i
= input_text_offset
; i
&& (input_text
[i
] != COMMAND_PREFIX
); i
--);
9277 maybe_write_itext (input_text
, i
);
9280 /* Similar to execute_string (), but only takes a single string argument,
9281 and remembers the input text location, etc. */
9283 me_execute_string (execution_string
)
9284 char *execution_string
;
9287 input_text_offset
= 0;
9288 input_text
= execution_string
;
9289 input_filename
= xstrdup (input_filename
);
9290 size_of_input_text
= strlen (execution_string
);
9292 remember_itext (execution_string
, 0);
9294 me_executing_string
++;
9297 me_executing_string
--;
9300 /* Append the text which appears in input_text from the last offset to
9301 the current OFFSET. */
9303 append_to_expansion_output (offset
)
9307 ITEXT
*itext
= (ITEXT
*)NULL
;
9309 for (i
= 0; i
< itext_size
; i
++)
9310 if (itext_info
[i
] && itext_info
[i
]->pointer
== input_text
)
9312 itext
= itext_info
[i
];
9319 if (offset
> itext
->offset
)
9321 write_region_to_macro_output
9322 (input_text
, itext
->offset
, offset
);
9323 remember_itext (input_text
, offset
);
9327 /* Only write this input text iff it appears in our itext list. */
9329 maybe_write_itext (pointer
, offset
)
9334 ITEXT
*itext
= (ITEXT
*)NULL
;
9336 for (i
= 0; i
< itext_size
; i
++)
9337 if (itext_info
[i
] && (itext_info
[i
]->pointer
== pointer
))
9339 itext
= itext_info
[i
];
9343 if (itext
&& (itext
->offset
< offset
))
9345 write_region_to_macro_output (itext
->pointer
, itext
->offset
, offset
);
9346 remember_itext (pointer
, offset
);
9351 write_region_to_macro_output (string
, start
, end
)
9355 if (macro_expansion_output_stream
)
9356 fwrite (string
+ start
, 1, end
- start
, macro_expansion_output_stream
);
9359 #endif /* HAVE_MACROS */
9361 /* Return the length of the array in ARRAY. */
9369 for (i
= 0; array
[i
] != (char *)NULL
; i
++);
9382 for (i
= 0; array
[i
] != (char *)NULL
; i
++)
9389 /* Function is used even when we don't have macros. Although, I have
9390 to admit, it is unlikely that you would have a use for it if you
9391 aren't using macros. */
9393 get_brace_args (quote_single
)
9396 char **arglist
, *word
;
9397 int arglist_index
, arglist_size
;
9398 int character
, escape_seen
, start
;
9401 /* There is an arglist in braces here, so gather the args inside of it. */
9402 skip_whitespace_and_newlines ();
9403 input_text_offset
++;
9404 arglist
= (char **)NULL
;
9405 arglist_index
= arglist_size
= 0;
9408 skip_whitespace_and_newlines ();
9409 start
= input_text_offset
;
9412 while ((character
= curchar ()))
9414 if (character
== '\\')
9416 input_text_offset
+= 2;
9419 else if (character
== '{')
9422 input_text_offset
++;
9424 else if ((character
== ',' && !quote_single
) ||
9425 ((character
== '}') && depth
== 1))
9427 int len
= input_text_offset
- start
;
9429 if (len
|| (character
!= '}'))
9431 word
= (char *)xmalloc (1 + len
);
9432 strncpy (word
, input_text
+ start
, len
);
9435 /* Clean up escaped characters. */
9440 for (i
= 0; word
[i
]; i
++)
9441 if (word
[i
] == '\\')
9442 memmove (word
+ i
, word
+ i
+ 1,
9443 1 + strlen (word
+ i
+ 1));
9446 if (arglist_index
+ 2 >= arglist_size
)
9447 arglist
= (char **)xrealloc
9448 (arglist
, (arglist_size
+= 10) * sizeof (char *));
9450 arglist
[arglist_index
++] = word
;
9451 arglist
[arglist_index
] = (char *)NULL
;
9454 input_text_offset
++;
9455 if (character
== '}')
9460 else if (character
== '}')
9463 input_text_offset
++;
9467 input_text_offset
++;
9468 if (character
== '\n') line_number
++;
9474 /* **************************************************************** */
9476 /* Looking For Include Files */
9478 /* **************************************************************** */
9480 /* Given a string containing units of information separated by colons,
9481 return the next one pointed to by INDEX, or NULL if there are no more.
9482 Advance INDEX to the character after the colon. */
9484 extract_colon_unit (string
, index
)
9492 if (!string
|| (i
>= strlen (string
)))
9493 return ((char *)NULL
);
9495 /* Each call to this routine leaves the index pointing at a colon if
9496 there is more to the path. If I is > 0, then increment past the
9497 `:'. If I is 0, then the path has a leading colon. Trailing colons
9498 are handled OK by the `else' part of the if statement; an empty
9499 string is returned in that case. */
9500 if (i
&& string
[i
] == ':')
9505 while (string
[i
] && string
[i
] != ':') i
++;
9514 /* Return "" in the case of a trailing `:'. */
9515 return (xstrdup (""));
9521 value
= (char *)xmalloc (1 + (i
- start
));
9522 strncpy (value
, &string
[start
], (i
- start
));
9523 value
[i
- start
] = 0;
9529 /* Return the full pathname for FILENAME by searching along PATH.
9530 When found, return the stat () info for FILENAME in FINFO.
9531 If PATH is NULL, only the current directory is searched.
9532 If the file could not be found, return a NULL pointer. */
9534 get_file_info_in_path (filename
, path
, finfo
)
9535 char *filename
, *path
;
9539 int result
, index
= 0;
9541 if (path
== (char *)NULL
)
9544 /* Handle absolute pathnames. "./foo", "/foo", "../foo". */
9545 if (*filename
== '/' ||
9546 (*filename
== '.' &&
9547 (filename
[1] == '/' ||
9548 (filename
[1] == '.' && filename
[2] == '/')))
9550 /* Handle names that look like "d:/foo/bar" */
9551 || (isalpha (*filename
) && filename
[1] == ':'
9552 && (filename
[2] == '/' || filename
[2] == '\\'))
9556 if (stat (filename
, finfo
) == 0)
9557 return (xstrdup (filename
));
9559 return ((char *)NULL
);
9562 while ((dir
= extract_colon_unit (path
, &index
)))
9569 dir
= xstrdup (".");
9572 fullpath
= (char *)xmalloc (2 + strlen (dir
) + strlen (filename
));
9573 sprintf (fullpath
, "%s/%s", dir
, filename
);
9576 result
= stat (fullpath
, finfo
);