1 /* node.c -- nodes for Texinfo.
2 $Id: node.c,v 1.27 2004/12/20 23:56:07 karl Exp $
4 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
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 Foundation,
19 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
30 #include "sectioning.h"
31 #include "insertion.h"
34 /* See comments in node.h. */
35 NODE_REF
*node_references
= NULL
;
36 NODE_REF
*node_node_references
= NULL
;
37 TAG_ENTRY
*tag_table
= NULL
;
40 int current_section
= 0;
41 int outstanding_node
= 0;
43 /* Adding nodes, and making tags. */
45 /* Start a new tag table. */
51 TAG_ENTRY
*temp
= tag_table
;
56 tag_table
= tag_table
->next_ent
;
61 /* Write out the contents of the existing tag table.
62 INDIRECT_P says how to format the output (it depends on whether the
63 table is direct or indirect). */
65 write_tag_table_internal (int indirect_p
)
68 int old_indent
= no_indent
;
78 must_start_paragraph
= 0;
87 add_word_args ("\037\nTag Table:\n%s", indirect_p
? "(Indirect)\n" : "");
89 /* Do not collapse -- to -, etc., in node names. */
90 in_fixed_width_font
++;
92 for (node
= tag_table
; node
; node
= node
->next_ent
)
94 if (node
->flags
& TAG_FLAG_ANCHOR
)
95 { /* This reference is to an anchor. */
96 execute_string ("Ref: %s", node
->node
);
99 { /* This reference is to a node. */
100 execute_string ("Node: %s", node
->node
);
102 add_word_args ("\177%d\n", node
->position
);
105 add_word ("\037\nEnd Tag Table\n");
107 /* Do not collapse -- to -, etc., in node names. */
108 in_fixed_width_font
--;
111 no_indent
= old_indent
;
115 write_tag_table (char *filename
)
117 output_stream
= fopen (filename
, "a");
124 write_tag_table_internal (0); /* Not indirect. */
126 if (fclose (output_stream
) != 0)
131 write_tag_table_indirect (void)
133 write_tag_table_internal (1);
136 /* Convert "top" and friends into "Top". */
138 normalize_node_name (char *string
)
140 if (strcasecmp (string
, "Top") == 0)
141 strcpy (string
, "Top");
145 get_node_token (int expand
)
149 get_until_in_line (expand
, ",", &string
);
151 if (curchar () == ',')
154 fix_whitespace (string
);
156 /* Force all versions of "top" to be "Top". */
157 normalize_node_name (string
);
162 /* Expand any macros and other directives in a node name, and
163 return the expanded name as an malloc'ed string. */
165 expand_node_name (char *node
)
171 /* Don't expand --, `` etc., in case somebody will want
172 to print the result. */
173 in_fixed_width_font
++;
174 result
= expansion (node
, 0);
175 in_fixed_width_font
--;
176 fix_whitespace (result
);
177 normalize_node_name (result
);
182 /* Look up NAME in the tag table, and return the associated
183 tag_entry. If the node is not in the table return NULL. */
185 find_node (char *name
)
187 TAG_ENTRY
*tag
= tag_table
;
193 if (tag
->node
[0] == n1
&& strcmp (tag
->node
, name
) == 0)
198 if (!expensive_validation
)
201 /* Try harder. Maybe TAG_TABLE has the expanded NAME, or maybe NAME
202 is expanded while TAG_TABLE has its unexpanded form. This may
203 slow down the search, but if they want this feature, let them
204 pay! If they want it fast, they should write every node name
205 consistently (either always expanded or always unexpaned). */
206 expanded_name
= expand_node_name (name
);
207 for (tag
= tag_table
; tag
; tag
= tag
->next_ent
)
209 if (STREQ (tag
->node
, expanded_name
))
211 /* If the tag name doesn't have the command prefix, there's no
212 chance it could expand into anything but itself. */
213 if (strchr (tag
->node
, COMMAND_PREFIX
))
215 char *expanded_node
= expand_node_name (tag
->node
);
217 if (STREQ (expanded_node
, expanded_name
))
219 free (expanded_node
);
222 free (expanded_node
);
225 free (expanded_name
);
229 /* Look in the tag table for a node whose file name is FNAME, and
230 return the associated tag_entry. If there's no such node in the
231 table, return NULL. */
233 find_node_by_fname (char *fname
)
235 TAG_ENTRY
*tag
= tag_table
;
238 if (tag
->html_fname
&& FILENAME_CMP (tag
->html_fname
, fname
) == 0)
246 /* Remember next, prev, etc. references in a @node command, where we
247 don't care about most of the entries. */
249 remember_node_node_reference (char *node
)
251 NODE_REF
*temp
= xmalloc (sizeof (NODE_REF
));
255 temp
->next
= node_node_references
;
256 temp
->node
= xstrdup (node
);
257 temp
->type
= followed_reference
;
258 number
= number_of_node (node
);
260 temp
->number
= number
; /* Already assigned. */
264 temp
->number
= node_number
;
266 node_node_references
= temp
;
269 /* Remember NODE and associates. */
271 remember_node (char *node
, char *prev
, char *next
, char *up
,
272 int position
, int line_no
, char *fname
, int flags
)
274 /* Check for existence of this tag already. */
277 TAG_ENTRY
*tag
= find_node (node
);
280 line_error (_("Node `%s' previously defined at line %d"),
286 if (!(flags
& TAG_FLAG_ANCHOR
))
288 /* Make this the current node. */
292 /* Add it to the list. */
294 int number
= number_of_node (node
);
296 TAG_ENTRY
*new = xmalloc (sizeof (TAG_ENTRY
));
301 new->position
= position
;
302 new->line_no
= line_no
;
303 new->filename
= node_filename
;
307 new->number
= number
; /* Already assigned. */
311 new->number
= node_number
;
314 new->html_fname
= fname
;
316 /* This happens for Top node under split-HTML, for example. */
318 = normalize_filename (filename_part (current_output_filename
));
319 new->next_ent
= tag_table
;
321 /* Increment the order counter, and save it. */
323 new->order
= node_order
;
329 { /* Note the references to the next etc. nodes too. */
330 remember_node_node_reference (next
);
331 remember_node_node_reference (prev
);
332 remember_node_node_reference (up
);
336 /* Remember this node name for later validation use. This is used to
337 remember menu references while reading the input file. After the
338 output file has been written, if validation is on, then we use the
339 contents of `node_references' as a list of nodes to validate. */
341 remember_node_reference (char *node
, int line
, enum reftype type
)
343 NODE_REF
*temp
= xmalloc (sizeof (NODE_REF
));
344 int number
= number_of_node (node
);
346 temp
->next
= node_references
;
347 temp
->node
= xstrdup (node
);
348 temp
->line_no
= line
;
349 temp
->section
= current_section
;
351 temp
->containing_node
= xstrdup (current_node
? current_node
: "");
352 temp
->filename
= node_filename
;
354 temp
->number
= number
; /* Already assigned. */
358 temp
->number
= node_number
;
361 node_references
= temp
;
365 isolate_nodename (char *nodename
)
368 int paren_seen
, paren
;
373 canon_white (nodename
);
374 paren_seen
= paren
= i
= 0;
376 if (*nodename
== '.' || !*nodename
)
382 if (*nodename
== '(')
389 for (; (c
= nodename
[i
]); i
++)
401 /* If the character following the close paren is a space, then this
402 node has no more characters associated with it. */
406 ((paren_seen
&& nodename
[i
- 1] == ')') &&
407 (c
== ' ' || c
== '.')) ||
409 ((!nodename
[i
+ 1] ||
410 (cr_or_whitespace (nodename
[i
+ 1])) ||
411 (nodename
[i
+ 1] == ')')))))
417 /* This function gets called at the start of every line while inside a
418 menu. It checks to see if the line starts with "* ", and if so and
419 REMEMBER_REF is nonzero, remembers the node reference as type
420 REF_TYPE that this menu refers to. input_text_offset is at the \n
421 just before the menu line. If REMEMBER_REF is zero, REF_TYPE is unused. */
422 #define MENU_STARTER "* "
424 glean_node_from_menu (int remember_ref
, enum reftype ref_type
)
426 int i
, orig_offset
= input_text_offset
;
428 char *line
, *expanded_line
;
429 char *old_input
= input_text
;
430 int old_size
= input_text_length
;
432 if (strncmp (&input_text
[input_text_offset
+ 1],
434 strlen (MENU_STARTER
)) != 0)
437 input_text_offset
+= strlen (MENU_STARTER
) + 1;
439 /* The menu entry might include macro calls, so we need to expand them. */
440 get_until ("\n", &line
);
441 only_macro_expansion
++; /* only expand macros in menu entries */
442 expanded_line
= expansion (line
, 0);
443 only_macro_expansion
--;
445 input_text
= expanded_line
;
446 input_text_offset
= 0;
447 input_text_length
= strlen (expanded_line
);
449 get_until_in_line (0, ":", &nodename
);
450 if (curchar () == ':')
453 if (curchar () != ':')
456 get_until_in_line (0, "\n", &nodename
);
457 isolate_nodename (nodename
);
460 input_text
= old_input
;
461 input_text_offset
= orig_offset
;
462 input_text_length
= old_size
;
463 free (expanded_line
);
464 fix_whitespace (nodename
);
465 normalize_node_name (nodename
);
466 i
= strlen (nodename
);
467 if (i
&& nodename
[i
- 1] == ':')
471 remember_node_reference (nodename
, line_number
, ref_type
);
476 /* Set the name of the current output file. */
478 set_current_output_filename (const char *fname
)
480 if (current_output_filename
)
481 free (current_output_filename
);
482 current_output_filename
= xstrdup (fname
);
486 /* Output the <a name="..."></a> constructs for NODE. We output both
487 the new-style conversion and the old-style, if they are different.
488 See comments at `add_escaped_anchor_name' in html.c. */
491 add_html_names (char *node
)
493 char *tem
= expand_node_name (node
);
494 char *otem
= xstrdup (tem
);
496 /* Determine if the old and new schemes come up with different names;
497 only output the old scheme if that is so. We don't want to output
498 the same name twice. */
504 for (; *optr
; optr
++)
506 if (!cr_or_whitespace (*optr
) && !URL_SAFE_CHAR (*optr
))
515 add_word ("<a name=\"");
516 add_anchor_name (otem
, -1); /* old anchor name conversion */
517 add_word ("\"></a>\n");
522 /* Always output the new scheme. */
524 add_word ("<a name=\"");
525 add_anchor_name (tem
, 0);
526 add_word ("\"></a>\n");
532 /* The order is: nodename, nextnode, prevnode, upnode.
533 If all of the NEXT, PREV, and UP fields are empty, they are defaulted.
534 You must follow a node command which has those fields defaulted
535 with a sectioning command (e.g., @chapter) giving the "level" of that node.
536 It is an error not to do so.
537 The defaults come from the menu in this node's parent. */
541 static long epilogue_len
= 0L;
542 char *node
, *prev
, *next
, *up
;
543 int new_node_pos
, defaulting
, this_section
;
545 char *fname_for_this_node
= NULL
;
547 TAG_ENTRY
*tag
= NULL
;
549 if (strcmp (command
, "nwnode") == 0)
550 no_warn
= TAG_FLAG_NO_WARN
;
552 /* Get rid of unmatched brace arguments from previous commands. */
555 /* There also might be insertions left lying around that haven't been
556 ended yet. Do that also. */
557 discard_insertions (1);
559 if (!html
&& !already_outputting_pending_notes
)
562 output_pending_notes ();
565 new_node_pos
= output_position
;
567 if (macro_expansion_output_stream
&& !executing_string
)
568 append_to_expansion_output (input_text_offset
+ 1);
570 /* Do not collapse -- to -, etc., in node names. */
571 in_fixed_width_font
++;
573 /* While expanding the @node line, leave any non-macros
574 intact, so that the macro-expanded output includes them. */
575 only_macro_expansion
++;
576 node
= get_node_token (1);
577 only_macro_expansion
--;
578 next
= get_node_token (0);
579 prev
= get_node_token (0);
580 up
= get_node_token (0);
582 if (html
&& splitting
583 /* If there is a Top node, it always goes into index.html. So
584 don't start a new HTML file for Top. */
585 && (top_node_seen
|| strcasecmp (node
, "Top") != 0))
587 /* We test *node here so that @node without a valid name won't
588 start a new file name with a bogus name such as ".html".
589 This could happen if we run under "--force", where we cannot
590 simply bail out. Continuing to use the same file sounds like
591 the best we can do in such cases. */
592 if (current_output_filename
&& output_stream
&& *node
)
594 char *fname_for_prev_node
;
598 /* NOTE: current_node at this point still holds the name
599 of the previous node. */
600 tem
= expand_node_name (current_node
);
601 fname_for_prev_node
= nodename_to_filename (tem
);
604 else /* could happen if their top node isn't named "Top" */
605 fname_for_prev_node
= filename_part (current_output_filename
);
606 tem
= expand_node_name (node
);
607 fname_for_this_node
= nodename_to_filename (tem
);
609 /* Don't close current output file, if next output file is
610 to have the same name. This may happen at top level, or
611 if two nodes produce the same file name under --split. */
612 if (FILENAME_CMP (fname_for_this_node
, fname_for_prev_node
) != 0)
616 /* End the current split output file. */
618 output_pending_notes ();
620 /* Compute the length of the HTML file's epilogue. We
621 cannot know the value until run time, due to the
622 text/binary nuisance on DOS/Windows platforms, where
623 2 `\r' characters could be added to the epilogue when
624 it is written in text mode. */
625 if (epilogue_len
== 0)
628 pos1
= ftell (output_stream
);
630 add_word ("</body></html>\n");
632 if (epilogue_len
== 0)
633 epilogue_len
= ftell (output_stream
) - pos1
;
634 fclose (output_stream
);
635 output_stream
= NULL
;
637 tag
= find_node_by_fname (fname_for_this_node
);
639 free (fname_for_prev_node
);
643 filling_enabled
= indented_fill
= 0;
644 if (!html
|| (html
&& splitting
))
645 current_footnote_number
= 1;
648 printf (_("Formatting node %s...\n"), node
);
650 if (macro_expansion_output_stream
&& !executing_string
)
651 remember_itext (input_text
, input_text_offset
);
653 /* Reset the line number in each node for Info output, so that
654 index entries will save the line numbers of parent node. */
655 node_line_number
= 0;
660 xml_begin_document (current_output_filename
);
664 xml_insert_element (NODENAME
, START
);
665 if (macro_expansion_output_stream
&& !executing_string
)
666 me_execute_string (node
);
668 execute_string ("%s", node
);
669 xml_insert_element (NODENAME
, END
);
672 xml_node_id
= xml_id (node
);
674 else if (!no_headers
&& !html
)
676 /* Emacs Info reader cannot grok indented escape sequence. */
677 kill_self_indent (-1);
679 add_word_args ("\037\nFile: %s, Node: ", pretty_output_filename
);
681 if (macro_expansion_output_stream
&& !executing_string
)
682 me_execute_string (node
);
684 execute_string ("%s", node
);
685 filling_enabled
= indented_fill
= 0;
688 /* Check for defaulting of this node's next, prev, and up fields. */
689 defaulting
= (*next
== 0 && *prev
== 0 && *up
== 0);
691 this_section
= what_section (input_text
+ input_text_offset
, NULL
);
693 /* If we are defaulting, then look at the immediately following
694 sectioning command (error if none) to determine the node's
695 level. Find the node that contains the menu mentioning this node
696 that is one level up (error if not found). That node is the "Up"
697 of this node. Default the "Next" and "Prev" from the menu. */
700 NODE_REF
*last_ref
= NULL
;
701 NODE_REF
*ref
= node_references
;
703 if (this_section
< 0 && !STREQ (node
, "Top"))
705 char *polite_section_name
= "top";
708 for (i
= 0; section_alist
[i
].name
; i
++)
709 if (section_alist
[i
].level
== current_section
+ 1)
711 polite_section_name
= section_alist
[i
].name
;
716 (_("Node `%s' requires a sectioning command (e.g., %c%s)"),
717 node
, COMMAND_PREFIX
, polite_section_name
);
721 if (strcmp (node
, "Top") == 0)
723 /* Default the NEXT pointer to be the first menu item in
724 this node, if there is a menu in this node. We have to
725 try very hard to find the menu, as it may be obscured
726 by execution_strings which are on the filestack. For
727 every member of the filestack which has a FILENAME
728 member which is identical to the current INPUT_FILENAME,
729 search forward from that offset. */
730 int saved_input_text_offset
= input_text_offset
;
731 int saved_input_text_length
= input_text_length
;
732 char *saved_input_text
= input_text
;
733 FSTACK
*next_file
= filestack
;
735 int orig_offset
, orig_size
;
737 int bye_offset
= search_forward ("\n@bye", input_text_offset
);
739 /* No matter what, make this file point back at `(dir)'. */
741 up
= xstrdup ("(dir)"); /* html fixxme */
745 orig_offset
= input_text_offset
;
747 search_forward (node_search_string
, orig_offset
);
750 orig_size
= input_text_length
;
752 input_text_offset
= search_forward ("\n@menu", orig_offset
);
753 if (input_text_offset
> -1
754 && (bye_offset
> -1 && input_text_offset
< bye_offset
)
755 && cr_or_whitespace (input_text
[input_text_offset
+ 6]))
757 char *nodename_from_menu
= NULL
;
760 search_forward ("\n* ", input_text_offset
);
762 if (input_text_offset
!= -1)
763 nodename_from_menu
= glean_node_from_menu (0, 0);
765 if (nodename_from_menu
)
768 next
= nodename_from_menu
;
773 /* We got here, so it hasn't been found yet. Try
774 the next file on the filestack if there is one. */
776 && FILENAME_CMP (next_file
->filename
, input_filename
)
779 input_text
= next_file
->text
;
780 input_text_offset
= next_file
->offset
;
781 input_text_length
= next_file
->size
;
782 next_file
= next_file
->next
;
785 { /* No more input files to check. */
790 input_text
= saved_input_text
;
791 input_text_offset
= saved_input_text_offset
;
792 input_text_length
= saved_input_text_length
;
796 /* Fix the level of the menu references in the Top node, iff it
797 was declared with @top, and no subsequent reference was found. */
798 if (top_node_seen
&& !non_top_node_seen
)
800 /* Then this is the first non-@top node seen. */
803 level
= set_top_section_level (this_section
- 1);
804 non_top_node_seen
= 1;
808 if (ref
->section
== level
)
809 ref
->section
= this_section
- 1;
813 ref
= node_references
;
818 if (ref
->section
== (this_section
- 1)
819 && ref
->type
== menu_reference
820 && strcmp (ref
->node
, node
) == 0)
822 char *containing_node
= ref
->containing_node
;
825 up
= xstrdup (containing_node
);
828 && last_ref
->type
== menu_reference
829 && strcmp (last_ref
->containing_node
, containing_node
) == 0)
832 next
= xstrdup (last_ref
->node
);
835 while (ref
->section
== this_section
- 1
837 && ref
->next
->type
!= menu_reference
)
840 if (ref
->next
&& ref
->type
== menu_reference
841 && strcmp (ref
->next
->containing_node
, containing_node
) == 0)
844 prev
= xstrdup (ref
->next
->node
);
847 && strcasecmp (ref
->containing_node
, "Top") == 0)
850 prev
= xstrdup (ref
->containing_node
);
859 /* Insert the correct args if we are expanding macros, and the node's
860 pointers weren't defaulted. */
861 if (macro_expansion_output_stream
&& !executing_string
&& !defaulting
)
864 int op_orig
= output_paragraph_offset
;
865 int meta_pos_orig
= meta_char_pos
;
866 int extra
= html
? strlen (node
) : 0;
868 temp
= xmalloc (7 + extra
+ strlen (next
) + strlen (prev
) + strlen (up
));
869 sprintf (temp
, "%s, %s, %s, %s", html
? node
: "", next
, prev
, up
);
870 me_execute_string (temp
);
873 output_paragraph_offset
= op_orig
;
874 meta_char_pos
= meta_pos_orig
;
879 line_error (_("No node name specified for `%c%s' command"),
880 COMMAND_PREFIX
, command
);
882 free (next
); next
= NULL
;
883 free (prev
); prev
= NULL
;
884 free (up
); up
= NULL
;
885 node_number
++; /* else it doesn't get bumped */
889 if (!*next
) { free (next
); next
= NULL
; }
890 if (!*prev
) { free (prev
); prev
= NULL
; }
891 if (!*up
) { free (up
); up
= NULL
; }
892 remember_node (node
, prev
, next
, up
, new_node_pos
, line_number
,
893 fname_for_this_node
, no_warn
);
894 outstanding_node
= 1;
899 if (splitting
&& *node
&& output_stream
== NULL
)
902 char filename
[PATH_MAX
];
904 dirname
= pathname_part (current_output_filename
);
905 strcpy (filename
, dirname
);
906 strcat (filename
, fname_for_this_node
);
909 /* See if the node name converted to a file name clashes
910 with other nodes or anchors. If it clashes with an
911 anchor, we complain and nuke that anchor's file. */
914 output_stream
= fopen (filename
, "w");
915 html_output_head_p
= 0; /* so that we generate HTML preamble */
918 else if ((tag
->flags
& TAG_FLAG_ANCHOR
) != 0)
920 line_error (_("Anchor `%s' and node `%s' map to the same file name"),
922 file_line_error (tag
->filename
, tag
->line_no
,
923 _("This @anchor command ignored; references to it will not work"));
924 file_line_error (tag
->filename
, tag
->line_no
,
925 _("Rename this anchor or use the `--no-split' option"));
926 /* Nuke the file name recorded in anchor's tag.
927 Since we are about to nuke the file itself, we
928 don't want find_node_by_fname to consider this
930 free (tag
->html_fname
);
931 tag
->html_fname
= NULL
;
932 output_stream
= fopen (filename
, "w");
933 html_output_head_p
= 0; /* so that we generate HTML preamble */
938 /* This node's file name clashes with another node.
939 We put them both on the same file. */
940 output_stream
= fopen (filename
, "r+");
943 static char html_end
[] = "</body></html>\n";
944 char end_line
[sizeof(html_end
)];
945 int fpos
= fseek (output_stream
, -epilogue_len
,
949 || fgets (end_line
, sizeof (html_end
),
950 output_stream
) == NULL
951 /* Paranoia: did someone change the way HTML
952 files are finished up? */
953 || strcasecmp (end_line
, html_end
) != 0)
955 line_error (_("Unexpected string at end of split-HTML file `%s'"),
956 fname_for_this_node
);
957 fclose (output_stream
);
960 fseek (output_stream
, -epilogue_len
, SEEK_END
);
963 if (output_stream
== NULL
)
968 set_current_output_filename (filename
);
971 if (!splitting
&& no_headers
)
972 { /* cross refs need a name="#anchor" even if not writing headers */
973 add_html_names (node
);
976 if (splitting
|| !no_headers
)
977 { /* Navigation bar. */
978 add_html_block_elt ("<div class=\"node\">\n");
979 /* The <p> avoids the links area running on with old Lynxen. */
980 add_word_args ("<p>%s\n", splitting
? "" : "<hr>");
982 /* In the split HTML case, the filename is wrong for the
983 old-style converted names, but we'll add them anyway, for
984 consistency. (And we need them in the normal (not
985 no_headers) nonsplit case.) */
986 add_html_names (node
);
990 tem
= expansion (next
, 0);
991 add_word ((char *) _("Next:"));
994 add_word ("<a rel=\"next\" accesskey=\"n\" href=\"");
995 add_anchor_name (tem
, 1);
996 tem
= escape_string (tem
);
997 add_word_args ("\">%s</a>", tem
);
1006 tem
= expansion (prev
, 0);
1007 add_word ((char *) _("Previous:"));
1008 add_word (" ");
1009 add_word ("<a rel=\"previous\" accesskey=\"p\" href=\"");
1010 add_anchor_name (tem
, 1);
1011 tem
= escape_string (tem
);
1012 add_word_args ("\">%s</a>", tem
);
1020 tem
= expansion (up
, 0);
1021 add_word ((char *) _("Up:"));
1022 add_word (" ");
1023 add_word ("<a rel=\"up\" accesskey=\"u\" href=\"");
1024 add_anchor_name (tem
, 1);
1025 tem
= escape_string (tem
);
1026 add_word_args ("\">%s</a>", tem
);
1029 /* html fixxme: we want a `top' or `contents' link here. */
1031 add_word_args ("\n%s\n", splitting
? "<hr>" : "");
1032 add_word ("</div>\n");
1041 xml_insert_element (NODENEXT
, START
);
1042 execute_string ("%s", next
);
1043 xml_insert_element (NODENEXT
, END
);
1047 xml_insert_element (NODEPREV
, START
);
1048 execute_string ("%s", prev
);
1049 xml_insert_element (NODEPREV
, END
);
1053 xml_insert_element (NODEUP
, START
);
1054 execute_string ("%s", up
);
1055 xml_insert_element (NODEUP
, END
);
1058 else if (!no_headers
)
1060 if (macro_expansion_output_stream
)
1061 me_inhibit_expansion
++;
1063 /* These strings are not translatable. */
1066 execute_string (", Next: %s", next
);
1067 filling_enabled
= indented_fill
= 0;
1071 execute_string (", Prev: %s", prev
);
1072 filling_enabled
= indented_fill
= 0;
1076 execute_string (", Up: %s", up
);
1077 filling_enabled
= indented_fill
= 0;
1079 if (macro_expansion_output_stream
)
1080 me_inhibit_expansion
--;
1086 /* Change the section only if there was a sectioning command. */
1087 if (this_section
>= 0)
1088 current_section
= this_section
;
1090 if (current_node
&& STREQ (current_node
, "Top"))
1093 filling_enabled
= 1;
1094 in_fixed_width_font
--;
1097 /* Cross-reference target at an arbitrary spot. */
1102 char *fname_for_anchor
= NULL
;
1107 /* Parse the anchor text. */
1108 anchor
= get_xref_token (1);
1110 /* Force all versions of "top" to be "Top". */
1111 normalize_node_name (anchor
);
1113 /* In HTML mode, need to actually produce some output. */
1116 /* If this anchor is at the beginning of a new paragraph, make
1117 sure a new paragraph is indeed started. */
1118 if (!paragraph_is_open
)
1120 if (!executing_string
&& html
)
1121 html_output_head ();
1123 if (!in_fixed_width_font
|| in_menu
|| in_detailmenu
)
1125 insert_string ("<p>");
1129 add_word ("<a name=\"");
1130 add_anchor_name (anchor
, 0);
1131 add_word ("\"></a>");
1134 /* If we are splitting, cm_xref will produce a reference to
1135 a file whose name is derived from the anchor name. So we
1136 must create a file when we see an @anchor, otherwise
1137 xref's to anchors won't work. The file we create simply
1138 redirects to the file of this anchor's node. */
1141 fname_for_anchor
= nodename_to_filename (anchor
);
1142 /* See if the anchor name converted to a file name clashes
1143 with other anchors or nodes. */
1144 tag
= find_node_by_fname (fname_for_anchor
);
1147 if ((tag
->flags
& TAG_FLAG_ANCHOR
) != 0)
1148 line_error (_("Anchors `%s' and `%s' map to the same file name"),
1151 line_error (_("Anchor `%s' and node `%s' map to the same file name"),
1153 line_error (_("@anchor command ignored; references to it will not work"));
1154 line_error (_("Rename this anchor or use the `--no-split' option"));
1155 free (fname_for_anchor
);
1156 /* We will not be creating a file for this anchor, so
1157 set its name to NULL, so that remember_node stores a
1158 NULL and find_node_by_fname won't consider this
1159 anchor for clashes. */
1160 fname_for_anchor
= NULL
;
1165 char filename
[PATH_MAX
];
1166 FILE *anchor_stream
;
1168 dirname
= pathname_part (current_output_filename
);
1169 strcpy (filename
, dirname
);
1170 strcat (filename
, fname_for_anchor
);
1173 anchor_stream
= fopen (filename
, "w");
1174 if (anchor_stream
== NULL
)
1176 fs_error (filename
);
1179 /* The HTML magic below will cause the browser to
1180 immediately go to the anchor's node's file. Lynx
1181 seems not to support this redirection, but it looks
1182 like a bug in Lynx, and they can work around it by
1183 clicking on the link once more. */
1184 fputs ("<meta http-equiv=\"refresh\" content=\"0; url=",
1186 /* Make the indirect link point to the current node's
1187 file and anchor's "<a name" label. If we don't have
1188 a valid node name, refer to the current output file
1190 if (current_node
&& *current_node
)
1194 tem
= expand_node_name (current_node
);
1195 fn
= nodename_to_filename (tem
);
1197 fputs (fn
, anchor_stream
);
1202 char *base
= filename_part (current_output_filename
);
1204 fputs (base
, anchor_stream
);
1207 fputs ("#", anchor_stream
);
1208 for (p
= anchor
; *p
; p
++)
1211 fputs ("&", anchor_stream
);
1212 else if (!URL_SAFE_CHAR (*p
))
1213 fprintf (anchor_stream
, "%%%x", (unsigned char) *p
);
1215 fputc (*p
, anchor_stream
);
1217 fputs ("\">\n", anchor_stream
);
1218 fclose (anchor_stream
);
1224 xml_insert_element_with_attribute (ANCHOR
, START
, "name=\"%s\"", anchor
);
1225 xml_insert_element (ANCHOR
, END
);
1227 /* Save it in the tag table. */
1228 remember_node (anchor
, NULL
, NULL
, NULL
,
1229 output_position
+ output_paragraph_offset
,
1230 line_number
, fname_for_anchor
, TAG_FLAG_ANCHOR
);
1233 /* Find NODE in REF_LIST. */
1235 find_node_reference (char *node
, NODE_REF
*ref_list
)
1237 NODE_REF
*orig_ref_list
= ref_list
;
1238 char *expanded_node
;
1242 if (strcmp (node
, ref_list
->node
) == 0)
1244 ref_list
= ref_list
->next
;
1247 if (ref_list
|| !expensive_validation
)
1250 /* Maybe NODE is not expanded yet. This may be SLOW. */
1251 expanded_node
= expand_node_name (node
);
1252 for (ref_list
= orig_ref_list
; ref_list
; ref_list
= ref_list
->next
)
1254 if (STREQ (expanded_node
, ref_list
->node
))
1256 if (strchr (ref_list
->node
, COMMAND_PREFIX
))
1258 char *expanded_ref
= expand_node_name (ref_list
->node
);
1260 if (STREQ (expanded_node
, expanded_ref
))
1262 free (expanded_ref
);
1265 free (expanded_ref
);
1268 free (expanded_node
);
1273 free_node_references (void)
1275 NODE_REF
*list
, *temp
;
1277 list
= node_references
;
1283 free (list
->containing_node
);
1287 node_references
= NULL
;
1291 free_node_node_references (void)
1293 NODE_REF
*list
, *temp
;
1295 list
= node_references
;
1304 node_node_references
= NULL
;
1307 /* Return the number assigned to a named node in either the tag_table
1308 or node_references list or zero if no number has been assigned. */
1310 number_of_node (char *node
)
1313 TAG_ENTRY
*temp_node
= find_node (node
);
1316 return temp_node
->number
;
1317 else if ((temp_ref
= find_node_reference (node
, node_references
)))
1318 return temp_ref
->number
;
1319 else if ((temp_ref
= find_node_reference (node
, node_node_references
)))
1320 return temp_ref
->number
;
1327 /* Return 1 if TAG (at LINE) correctly validated, or 0 if not.
1328 LABEL is the (translated) description of the type of reference --
1329 Menu, Cross, Next, etc. */
1332 validate (char *tag
, int line
, const char *label
)
1336 /* If there isn't a tag to verify, or if the tag is in another file,
1337 then it must be okay. */
1338 if (!tag
|| !*tag
|| *tag
== '(')
1341 /* Otherwise, the tag must exist. */
1342 result
= find_node (tag
);
1347 line_error (_("%s reference to nonexistent node `%s' (perhaps incorrect sectioning?)"), label
, tag
);
1354 /* The strings here are followed in the message by `reference to...' in
1355 the `validate' routine. They are only used in messages, thus are
1358 reftype_type_string (enum reftype type
)
1362 case menu_reference
:
1364 case followed_reference
:
1367 return "Internal-bad-reference-type";
1372 validate_other_references (NODE_REF
*ref_list
)
1374 char *old_input_filename
= input_filename
;
1378 input_filename
= ref_list
->filename
;
1379 validate (ref_list
->node
, ref_list
->line_no
,
1380 reftype_type_string (ref_list
->type
));
1381 ref_list
= ref_list
->next
;
1383 input_filename
= old_input_filename
;
1386 /* Validation of an info file.
1387 Scan through the list of tag entries touching the Prev, Next, and Up
1388 elements of each. It is an error not to be able to touch one of them,
1389 except in the case of external node references, such as "(DIR)".
1391 If the Prev is different from the Up,
1392 then the Prev node must have a Next pointing at this node.
1394 Every node except Top must have an Up.
1395 The Up node must contain some sort of reference, other than a Next,
1398 If the Next is different from the Next of the Up,
1399 then the Next node must have a Prev pointing at this node. */
1401 validate_file (TAG_ENTRY
*tag_table
)
1403 char *old_input_filename
= input_filename
;
1404 TAG_ENTRY
*tags
= tag_table
;
1408 TAG_ENTRY
*temp_tag
;
1411 input_filename
= tags
->filename
;
1412 line_number
= tags
->line_no
;
1414 /* If this is a "no warn" node, don't validate it in any way. */
1415 if (tags
->flags
& TAG_FLAG_NO_WARN
)
1417 tags
= tags
->next_ent
;
1421 /* If this node has a Next, then make sure that the Next exists. */
1424 validate (tags
->next
, tags
->line_no
, _("Next"));
1426 /* If the Next node exists, and there is no Up, then make sure
1427 that the Prev of the Next points back. But do nothing if
1428 we aren't supposed to issue warnings about this node. */
1429 temp_tag
= find_node (tags
->next
);
1430 if (temp_tag
&& !(temp_tag
->flags
& TAG_FLAG_NO_WARN
))
1432 char *prev
= temp_tag
->prev
;
1433 int you_lose
= !prev
|| !STREQ (prev
, tags
->node
);
1435 if (you_lose
&& expensive_validation
)
1437 tem1
= expand_node_name (prev
);
1438 tem2
= expand_node_name (tags
->node
);
1440 if (tem1
&& tem2
&& STREQ (tem1
, tem2
))
1447 line_error (_("Next field of node `%s' not pointed to (perhaps incorrect sectioning?)"),
1449 file_line_error (temp_tag
->filename
, temp_tag
->line_no
,
1450 _("This node (%s) has the bad Prev"),
1452 temp_tag
->flags
|= TAG_FLAG_PREV_ERROR
;
1457 /* Validate the Prev field if there is one, and we haven't already
1458 complained about it in some way. You don't have to have a Prev
1459 field at this stage. */
1460 if (!(tags
->flags
& TAG_FLAG_PREV_ERROR
) && tags
->prev
)
1462 int valid_p
= validate (tags
->prev
, tags
->line_no
, _("Prev"));
1465 tags
->flags
|= TAG_FLAG_PREV_ERROR
;
1467 { /* If the Prev field is not the same as the Up field,
1468 then the node pointed to by the Prev field must have
1469 a Next field which points to this node. */
1470 int prev_equals_up
= !tags
->up
|| STREQ (tags
->prev
, tags
->up
);
1472 if (!prev_equals_up
&& expensive_validation
)
1474 tem1
= expand_node_name (tags
->prev
);
1475 tem2
= expand_node_name (tags
->up
);
1476 prev_equals_up
= STREQ (tem1
, tem2
);
1480 if (!prev_equals_up
)
1482 temp_tag
= find_node (tags
->prev
);
1484 /* If we aren't supposed to issue warnings about the
1485 target node, do nothing. */
1486 if (!temp_tag
|| (temp_tag
->flags
& TAG_FLAG_NO_WARN
))
1490 int you_lose
= !temp_tag
->next
1491 || !STREQ (temp_tag
->next
, tags
->node
);
1493 if (temp_tag
->next
&& you_lose
&& expensive_validation
)
1495 tem1
= expand_node_name (temp_tag
->next
);
1496 tem2
= expand_node_name (tags
->node
);
1497 if (STREQ (tem1
, tem2
))
1505 (_("Prev field of node `%s' not pointed to"),
1507 file_line_error (temp_tag
->filename
,
1509 _("This node (%s) has the bad Next"),
1511 temp_tag
->flags
|= TAG_FLAG_NEXT_ERROR
;
1519 && !(tags
->flags
& TAG_FLAG_ANCHOR
)
1520 && strcasecmp (tags
->node
, "Top") != 0)
1521 line_error (_("`%s' has no Up field (perhaps incorrect sectioning?)"), tags
->node
);
1524 int valid_p
= validate (tags
->up
, tags
->line_no
, _("Up"));
1526 /* If node X has Up: Y, then warn if Y fails to have a menu item
1527 or note pointing at X, if Y isn't of the form "(Y)". */
1528 if (valid_p
&& *tags
->up
!= '(')
1531 NODE_REF
*tref
= NULL
;
1532 NODE_REF
*list
= node_references
;
1536 nref
= find_node_reference (tags
->node
, list
);
1540 if (strcmp (nref
->containing_node
, tags
->up
) == 0)
1542 if (nref
->type
!= menu_reference
)
1555 if (!tref
&& expensive_validation
)
1557 /* Sigh... This might be AWFULLY slow, but if
1558 they want this feature, they'll have to pay!
1559 We do all the loop again expanding each
1560 containing_node reference as we go. */
1561 char *tags_up
= expand_node_name (tags
->up
);
1564 list
= node_references
;
1568 nref
= find_node_reference (tags
->node
, list
);
1571 tem
= expand_node_name (nref
->containing_node
);
1572 if (STREQ (tem
, tags_up
))
1574 if (nref
->type
!= menu_reference
)
1588 temp_tag
= find_node (tags
->up
);
1589 file_line_error (temp_tag
->filename
, temp_tag
->line_no
,
1590 _("Node `%s' lacks menu item for `%s' despite being its Up target"),
1591 tags
->up
, tags
->node
);
1596 tags
= tags
->next_ent
;
1599 validate_other_references (node_references
);
1600 /* We have told the user about the references which didn't exist.
1601 Now tell him about the nodes which aren't referenced. */
1603 for (tags
= tag_table
; tags
; tags
= tags
->next_ent
)
1605 /* If this node is a "no warn" node, do nothing. */
1606 if (tags
->flags
& TAG_FLAG_NO_WARN
)
1608 tags
= tags
->next_ent
;
1612 /* Special hack. If the node in question appears to have
1613 been referenced more than REFERENCE_WARNING_LIMIT times,
1615 if (tags
->touched
> reference_warning_limit
)
1617 input_filename
= tags
->filename
;
1618 line_number
= tags
->line_no
;
1619 warning (_("node `%s' has been referenced %d times"),
1620 tags
->node
, tags
->touched
);
1623 if (tags
->touched
== 0)
1625 input_filename
= tags
->filename
;
1626 line_number
= tags
->line_no
;
1628 /* Notice that the node "Top" is special, and doesn't have to
1629 be referenced. Anchors don't have to be referenced
1630 either, you might define them for another document. */
1631 if (strcasecmp (tags
->node
, "Top") != 0
1632 && !(tags
->flags
& TAG_FLAG_ANCHOR
))
1633 warning (_("unreferenced node `%s'"), tags
->node
);
1636 input_filename
= old_input_filename
;
1642 /* Return true if the tag entry pointed to by TAGS is the last node.
1643 This means only anchors follow. */
1646 last_node_p (TAG_ENTRY
*tags
)
1649 while (tags
->next_ent
) {
1650 tags
= tags
->next_ent
;
1651 if (tags
->flags
& TAG_FLAG_ANCHOR
)
1665 enumerate_filename (char *pathname
, char *basename
, int number
)
1667 /* Do we need to generate names of subfiles which don't exceed 8+3 limits? */
1668 const int dos_file_names
= !HAVE_LONG_FILENAMES (pathname
? pathname
: ".");
1669 unsigned name_len
= strlen (basename
);
1670 char *filename
= xmalloc (10 + strlen (pathname
) + name_len
);
1671 char *base_filename
= xmalloc (10 + name_len
);
1673 sprintf (base_filename
, "%s-%d", basename
, number
);
1677 char *dot
= strchr (base_filename
, '.');
1678 unsigned base_len
= strlen (base_filename
);
1681 { /* Make foobar.i1, .., foobar.i99, foobar.100, ... */
1683 memmove (number
<= 99 ? dot
+ 2 : dot
+ 1,
1684 base_filename
+ name_len
+ 1,
1685 strlen (base_filename
+ name_len
+ 1) + 1);
1687 else if (base_len
> 8)
1689 /* Make foobar-1, .., fooba-10, .., foob-100, ... */
1690 unsigned numlen
= base_len
- name_len
;
1692 memmove (base_filename
+ 8 - numlen
, base_filename
+ name_len
, numlen
+ 1);
1696 sprintf (filename
, "%s%s", pathname
, base_filename
);
1701 /* Remove previously split files, to avoid
1702 lingering parts of shrinked documents. */
1704 clean_old_split_files (char *filename
)
1706 char *root_filename
= filename_part (filename
);
1707 char *root_pathname
= pathname_part (filename
);
1710 /* We break as soon as we hit an inexistent file,
1711 so looping until large numbers is harmless. */
1712 for (i
= 1; i
< 1000; i
++)
1715 char *check_file
= enumerate_filename (root_pathname
, root_filename
, i
);
1717 if (stat (check_file
, &st
) != 0)
1719 else if (!S_ISDIR (st
.st_mode
))
1721 /* Give feedback if requested, removing a file is important. */
1723 printf (_("Removing %s\n"), check_file
);
1725 /* Warn user that we cannot remove the file. */
1726 if (unlink (check_file
) != 0)
1727 warning (_("Can't remove file `%s': %s"), check_file
, strerror (errno
));
1735 /* Split large output files into a series of smaller files. Each file
1736 is pointed to in the tag table, which then gets written out as the
1737 original file. The new files have the same name as the original file
1738 with a "-num" attached. SIZE is the largest number of bytes to allow
1739 in any single split file. */
1741 split_file (char *filename
, int size
)
1743 char *root_filename
, *root_pathname
;
1745 struct stat fileinfo
;
1750 /* Can only do this to files with tag tables. */
1755 size
= DEFAULT_SPLIT_SIZE
;
1757 if ((stat (filename
, &fileinfo
) != 0)
1758 || (((long) fileinfo
.st_size
) < size
))
1760 file_size
= (long) fileinfo
.st_size
;
1762 the_file
= find_and_load (filename
, 0);
1766 root_filename
= filename_part (filename
);
1767 root_pathname
= pathname_part (filename
);
1770 root_pathname
= xstrdup ("");
1772 /* Start splitting the file. Walk along the tag table
1773 outputting sections of the file. When we have written
1774 all of the nodes in the tag table, make the top-level
1775 pointer file, which contains indirect pointers and
1776 tags for the nodes. */
1779 TAG_ENTRY
*tags
= tag_table
;
1780 char *indirect_info
= NULL
;
1782 /* Maybe we want a Local Variables section. */
1783 char *trailer
= info_trailer ();
1784 int trailer_len
= trailer
? strlen (trailer
) : 0;
1786 /* Remember the `header' of this file. The first tag in the file is
1787 the bottom of the header; the top of the file is the start. */
1788 the_header
= xmalloc (1 + (header_size
= tags
->position
));
1789 memcpy (the_header
, the_file
, header_size
);
1793 int file_top
, file_bot
, limit
;
1795 /* Have to include the Control-_. */
1796 file_top
= file_bot
= tags
->position
;
1797 limit
= file_top
+ size
;
1799 /* If the rest of this file is only one node, then
1800 that is the entire subfile. */
1801 if (last_node_p (tags
))
1803 int i
= tags
->position
+ 1;
1804 char last_char
= the_file
[i
];
1806 while (i
< file_size
)
1808 if ((the_file
[i
] == '\037') &&
1809 ((last_char
== '\n') ||
1810 (last_char
== '\014')))
1813 last_char
= the_file
[i
];
1817 tags
= tags
->next_ent
;
1821 /* Otherwise, find the largest number of nodes that can fit in
1823 for (; tags
; tags
= tags
->next_ent
)
1825 if (last_node_p (tags
))
1827 /* This entry is the last node. Search forward for the end
1828 of this node, and that is the end of this file. */
1829 int i
= tags
->position
+ 1;
1830 char last_char
= the_file
[i
];
1832 while (i
< file_size
)
1834 if ((the_file
[i
] == '\037') &&
1835 ((last_char
== '\n') ||
1836 (last_char
== '\014')))
1839 last_char
= the_file
[i
];
1844 if (file_bot
< limit
)
1846 tags
= tags
->next_ent
;
1851 /* Here we want to write out everything before the last
1852 node, and then write the last node out in a file
1854 file_bot
= tags
->position
;
1859 /* Write region only if this was a node, not an anchor. */
1860 if (tags
->next_ent
->position
> limit
1861 && !(tags
->flags
& TAG_FLAG_ANCHOR
))
1863 if (tags
->position
== file_top
)
1864 tags
= tags
->next_ent
;
1866 file_bot
= tags
->position
;
1871 char *split_filename
= enumerate_filename (root_pathname
,
1872 root_filename
, which_file
);
1873 char *split_basename
= filename_part (split_filename
);
1875 fd
= open (split_filename
, O_WRONLY
|O_TRUNC
|O_CREAT
, 0666);
1877 || write (fd
, the_header
, header_size
) != header_size
1878 || write (fd
, the_file
+ file_top
, file_bot
- file_top
)
1879 != (file_bot
- file_top
)
1881 && write (fd
, trailer
, trailer_len
) != trailer_len
)
1884 perror (split_filename
);
1892 indirect_info
= the_file
+ file_top
;
1893 sprintf (indirect_info
, "\037\nIndirect:\n");
1894 indirect_info
+= strlen (indirect_info
);
1897 sprintf (indirect_info
, "%s: %d\n",
1898 split_basename
, file_top
);
1900 free (split_basename
);
1901 free (split_filename
);
1902 indirect_info
+= strlen (indirect_info
);
1910 /* We have sucessfully created the subfiles. Now write out the
1911 original again. We must use `output_stream', or
1912 write_tag_table_indirect () won't know where to place the output. */
1913 output_stream
= fopen (filename
, "w");
1921 int distance
= indirect_info
- the_file
;
1922 fwrite (the_file
, 1, distance
, output_stream
);
1924 /* Inhibit newlines. */
1925 paragraph_is_open
= 0;
1927 /* Write the indirect tag table. */
1928 write_tag_table_indirect ();
1930 /* preserve local variables in info output. */
1933 fwrite (trailer
, 1, trailer_len
, output_stream
);
1937 fclose (output_stream
);