1 /* $NetBSD: node.c,v 1.1.1.6 2008/09/02 07:50:47 christos Exp $ */
3 /* node.c -- nodes for Texinfo.
4 Id: node.c,v 1.27 2004/12/20 23:56:07 karl Exp
6 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software Foundation,
21 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
32 #include "sectioning.h"
33 #include "insertion.h"
36 /* See comments in node.h. */
37 NODE_REF
*node_references
= NULL
;
38 NODE_REF
*node_node_references
= NULL
;
39 TAG_ENTRY
*tag_table
= NULL
;
42 int current_section
= 0;
43 int outstanding_node
= 0;
45 /* Adding nodes, and making tags. */
47 /* Start a new tag table. */
53 TAG_ENTRY
*temp
= tag_table
;
58 tag_table
= tag_table
->next_ent
;
63 /* Write out the contents of the existing tag table.
64 INDIRECT_P says how to format the output (it depends on whether the
65 table is direct or indirect). */
67 write_tag_table_internal (int indirect_p
)
70 int old_indent
= no_indent
;
80 must_start_paragraph
= 0;
89 add_word_args ("\037\nTag Table:\n%s", indirect_p
? "(Indirect)\n" : "");
91 /* Do not collapse -- to -, etc., in node names. */
92 in_fixed_width_font
++;
94 for (node
= tag_table
; node
; node
= node
->next_ent
)
96 if (node
->flags
& TAG_FLAG_ANCHOR
)
97 { /* This reference is to an anchor. */
98 execute_string ("Ref: %s", node
->node
);
101 { /* This reference is to a node. */
102 execute_string ("Node: %s", node
->node
);
104 add_word_args ("\177%d\n", node
->position
);
107 add_word ("\037\nEnd Tag Table\n");
109 /* Do not collapse -- to -, etc., in node names. */
110 in_fixed_width_font
--;
113 no_indent
= old_indent
;
117 write_tag_table (char *filename
)
119 output_stream
= fopen (filename
, "a");
126 write_tag_table_internal (0); /* Not indirect. */
128 if (fclose (output_stream
) != 0)
133 write_tag_table_indirect (void)
135 write_tag_table_internal (1);
138 /* Convert "top" and friends into "Top". */
140 normalize_node_name (char *string
)
142 if (strcasecmp (string
, "Top") == 0)
143 strcpy (string
, "Top");
147 get_node_token (int expand
)
151 get_until_in_line (expand
, ",", &string
);
153 if (curchar () == ',')
156 fix_whitespace (string
);
158 /* Force all versions of "top" to be "Top". */
159 normalize_node_name (string
);
164 /* Expand any macros and other directives in a node name, and
165 return the expanded name as an malloc'ed string. */
167 expand_node_name (char *node
)
173 /* Don't expand --, `` etc., in case somebody will want
174 to print the result. */
175 in_fixed_width_font
++;
176 result
= expansion (node
, 0);
177 in_fixed_width_font
--;
178 fix_whitespace (result
);
179 normalize_node_name (result
);
184 /* Look up NAME in the tag table, and return the associated
185 tag_entry. If the node is not in the table return NULL. */
187 find_node (char *name
)
189 TAG_ENTRY
*tag
= tag_table
;
195 if (tag
->node
[0] == n1
&& strcmp (tag
->node
, name
) == 0)
200 if (!expensive_validation
)
203 /* Try harder. Maybe TAG_TABLE has the expanded NAME, or maybe NAME
204 is expanded while TAG_TABLE has its unexpanded form. This may
205 slow down the search, but if they want this feature, let them
206 pay! If they want it fast, they should write every node name
207 consistently (either always expanded or always unexpaned). */
208 expanded_name
= expand_node_name (name
);
209 for (tag
= tag_table
; tag
; tag
= tag
->next_ent
)
211 if (STREQ (tag
->node
, expanded_name
))
213 /* If the tag name doesn't have the command prefix, there's no
214 chance it could expand into anything but itself. */
215 if (strchr (tag
->node
, COMMAND_PREFIX
))
217 char *expanded_node
= expand_node_name (tag
->node
);
219 if (STREQ (expanded_node
, expanded_name
))
221 free (expanded_node
);
224 free (expanded_node
);
227 free (expanded_name
);
231 /* Look in the tag table for a node whose file name is FNAME, and
232 return the associated tag_entry. If there's no such node in the
233 table, return NULL. */
235 find_node_by_fname (char *fname
)
237 TAG_ENTRY
*tag
= tag_table
;
240 if (tag
->html_fname
&& FILENAME_CMP (tag
->html_fname
, fname
) == 0)
248 /* Remember next, prev, etc. references in a @node command, where we
249 don't care about most of the entries. */
251 remember_node_node_reference (char *node
)
253 NODE_REF
*temp
= xmalloc (sizeof (NODE_REF
));
257 temp
->next
= node_node_references
;
258 temp
->node
= xstrdup (node
);
259 temp
->type
= followed_reference
;
260 number
= number_of_node (node
);
262 temp
->number
= number
; /* Already assigned. */
266 temp
->number
= node_number
;
268 node_node_references
= temp
;
271 /* Remember NODE and associates. */
273 remember_node (char *node
, char *prev
, char *next
, char *up
,
274 int position
, int line_no
, char *fname
, int flags
)
276 /* Check for existence of this tag already. */
279 TAG_ENTRY
*tag
= find_node (node
);
282 line_error (_("Node `%s' previously defined at line %d"),
288 if (!(flags
& TAG_FLAG_ANCHOR
))
290 /* Make this the current node. */
294 /* Add it to the list. */
296 int number
= number_of_node (node
);
298 TAG_ENTRY
*new = xmalloc (sizeof (TAG_ENTRY
));
303 new->position
= position
;
304 new->line_no
= line_no
;
305 new->filename
= node_filename
;
309 new->number
= number
; /* Already assigned. */
313 new->number
= node_number
;
316 new->html_fname
= fname
;
318 /* This happens for Top node under split-HTML, for example. */
320 = normalize_filename (filename_part (current_output_filename
));
321 new->next_ent
= tag_table
;
323 /* Increment the order counter, and save it. */
325 new->order
= node_order
;
331 { /* Note the references to the next etc. nodes too. */
332 remember_node_node_reference (next
);
333 remember_node_node_reference (prev
);
334 remember_node_node_reference (up
);
338 /* Remember this node name for later validation use. This is used to
339 remember menu references while reading the input file. After the
340 output file has been written, if validation is on, then we use the
341 contents of `node_references' as a list of nodes to validate. */
343 remember_node_reference (char *node
, int line
, enum reftype type
)
345 NODE_REF
*temp
= xmalloc (sizeof (NODE_REF
));
346 int number
= number_of_node (node
);
348 temp
->next
= node_references
;
349 temp
->node
= xstrdup (node
);
350 temp
->line_no
= line
;
351 temp
->section
= current_section
;
353 temp
->containing_node
= xstrdup (current_node
? current_node
: "");
354 temp
->filename
= node_filename
;
356 temp
->number
= number
; /* Already assigned. */
360 temp
->number
= node_number
;
363 node_references
= temp
;
367 isolate_nodename (char *nodename
)
370 int paren_seen
, paren
;
375 canon_white (nodename
);
376 paren_seen
= paren
= i
= 0;
378 if (*nodename
== '.' || !*nodename
)
384 if (*nodename
== '(')
391 for (; (c
= nodename
[i
]); i
++)
403 /* If the character following the close paren is a space, then this
404 node has no more characters associated with it. */
408 ((paren_seen
&& nodename
[i
- 1] == ')') &&
409 (c
== ' ' || c
== '.')) ||
411 ((!nodename
[i
+ 1] ||
412 (cr_or_whitespace (nodename
[i
+ 1])) ||
413 (nodename
[i
+ 1] == ')')))))
419 /* This function gets called at the start of every line while inside a
420 menu. It checks to see if the line starts with "* ", and if so and
421 REMEMBER_REF is nonzero, remembers the node reference as type
422 REF_TYPE that this menu refers to. input_text_offset is at the \n
423 just before the menu line. If REMEMBER_REF is zero, REF_TYPE is unused. */
424 #define MENU_STARTER "* "
426 glean_node_from_menu (int remember_ref
, enum reftype ref_type
)
428 int i
, orig_offset
= input_text_offset
;
430 char *line
, *expanded_line
;
431 char *old_input
= input_text
;
432 int old_size
= input_text_length
;
434 if (strncmp (&input_text
[input_text_offset
+ 1],
436 strlen (MENU_STARTER
)) != 0)
439 input_text_offset
+= strlen (MENU_STARTER
) + 1;
441 /* The menu entry might include macro calls, so we need to expand them. */
442 get_until ("\n", &line
);
443 only_macro_expansion
++; /* only expand macros in menu entries */
444 expanded_line
= expansion (line
, 0);
445 only_macro_expansion
--;
447 input_text
= expanded_line
;
448 input_text_offset
= 0;
449 input_text_length
= strlen (expanded_line
);
451 get_until_in_line (0, ":", &nodename
);
452 if (curchar () == ':')
455 if (curchar () != ':')
458 get_until_in_line (0, "\n", &nodename
);
459 isolate_nodename (nodename
);
462 input_text
= old_input
;
463 input_text_offset
= orig_offset
;
464 input_text_length
= old_size
;
465 free (expanded_line
);
466 fix_whitespace (nodename
);
467 normalize_node_name (nodename
);
468 i
= strlen (nodename
);
469 if (i
&& nodename
[i
- 1] == ':')
473 remember_node_reference (nodename
, line_number
, ref_type
);
478 /* Set the name of the current output file. */
480 set_current_output_filename (const char *fname
)
482 if (current_output_filename
)
483 free (current_output_filename
);
484 current_output_filename
= xstrdup (fname
);
488 /* Output the <a name="..."></a> constructs for NODE. We output both
489 the new-style conversion and the old-style, if they are different.
490 See comments at `add_escaped_anchor_name' in html.c. */
493 add_html_names (char *node
)
495 char *tem
= expand_node_name (node
);
496 char *otem
= xstrdup (tem
);
498 /* Determine if the old and new schemes come up with different names;
499 only output the old scheme if that is so. We don't want to output
500 the same name twice. */
506 for (; *optr
; optr
++)
508 if (!cr_or_whitespace (*optr
) && !URL_SAFE_CHAR (*optr
))
517 add_word ("<a name=\"");
518 add_anchor_name (otem
, -1); /* old anchor name conversion */
519 add_word ("\"></a>\n");
524 /* Always output the new scheme. */
526 add_word ("<a name=\"");
527 add_anchor_name (tem
, 0);
528 add_word ("\"></a>\n");
534 /* The order is: nodename, nextnode, prevnode, upnode.
535 If all of the NEXT, PREV, and UP fields are empty, they are defaulted.
536 You must follow a node command which has those fields defaulted
537 with a sectioning command (e.g., @chapter) giving the "level" of that node.
538 It is an error not to do so.
539 The defaults come from the menu in this node's parent. */
543 static long epilogue_len
= 0L;
544 char *node
, *prev
, *next
, *up
;
545 int new_node_pos
, defaulting
, this_section
;
547 char *fname_for_this_node
= NULL
;
549 TAG_ENTRY
*tag
= NULL
;
551 if (strcmp (command
, "nwnode") == 0)
552 no_warn
= TAG_FLAG_NO_WARN
;
554 /* Get rid of unmatched brace arguments from previous commands. */
557 /* There also might be insertions left lying around that haven't been
558 ended yet. Do that also. */
559 discard_insertions (1);
561 if (!html
&& !already_outputting_pending_notes
)
564 output_pending_notes ();
567 new_node_pos
= output_position
;
569 if (macro_expansion_output_stream
&& !executing_string
)
570 append_to_expansion_output (input_text_offset
+ 1);
572 /* Do not collapse -- to -, etc., in node names. */
573 in_fixed_width_font
++;
575 /* While expanding the @node line, leave any non-macros
576 intact, so that the macro-expanded output includes them. */
577 only_macro_expansion
++;
578 node
= get_node_token (1);
579 only_macro_expansion
--;
580 next
= get_node_token (0);
581 prev
= get_node_token (0);
582 up
= get_node_token (0);
584 if (html
&& splitting
585 /* If there is a Top node, it always goes into index.html. So
586 don't start a new HTML file for Top. */
587 && (top_node_seen
|| strcasecmp (node
, "Top") != 0))
589 /* We test *node here so that @node without a valid name won't
590 start a new file name with a bogus name such as ".html".
591 This could happen if we run under "--force", where we cannot
592 simply bail out. Continuing to use the same file sounds like
593 the best we can do in such cases. */
594 if (current_output_filename
&& output_stream
&& *node
)
596 char *fname_for_prev_node
;
600 /* NOTE: current_node at this point still holds the name
601 of the previous node. */
602 tem
= expand_node_name (current_node
);
603 fname_for_prev_node
= nodename_to_filename (tem
);
606 else /* could happen if their top node isn't named "Top" */
607 fname_for_prev_node
= filename_part (current_output_filename
);
608 tem
= expand_node_name (node
);
609 fname_for_this_node
= nodename_to_filename (tem
);
611 /* Don't close current output file, if next output file is
612 to have the same name. This may happen at top level, or
613 if two nodes produce the same file name under --split. */
614 if (FILENAME_CMP (fname_for_this_node
, fname_for_prev_node
) != 0)
618 /* End the current split output file. */
620 output_pending_notes ();
622 /* Compute the length of the HTML file's epilogue. We
623 cannot know the value until run time, due to the
624 text/binary nuisance on DOS/Windows platforms, where
625 2 `\r' characters could be added to the epilogue when
626 it is written in text mode. */
627 if (epilogue_len
== 0)
630 pos1
= ftell (output_stream
);
632 add_word ("</body></html>\n");
634 if (epilogue_len
== 0)
635 epilogue_len
= ftell (output_stream
) - pos1
;
636 fclose (output_stream
);
637 output_stream
= NULL
;
639 tag
= find_node_by_fname (fname_for_this_node
);
641 free (fname_for_prev_node
);
645 filling_enabled
= indented_fill
= 0;
646 if (!html
|| (html
&& splitting
))
647 current_footnote_number
= 1;
650 printf (_("Formatting node %s...\n"), node
);
652 if (macro_expansion_output_stream
&& !executing_string
)
653 remember_itext (input_text
, input_text_offset
);
655 /* Reset the line number in each node for Info output, so that
656 index entries will save the line numbers of parent node. */
657 node_line_number
= 0;
662 xml_begin_document (current_output_filename
);
666 xml_insert_element (NODENAME
, START
);
667 if (macro_expansion_output_stream
&& !executing_string
)
668 me_execute_string (node
);
670 execute_string ("%s", node
);
671 xml_insert_element (NODENAME
, END
);
674 xml_node_id
= xml_id (node
);
676 else if (!no_headers
&& !html
)
678 /* Emacs Info reader cannot grok indented escape sequence. */
679 kill_self_indent (-1);
681 add_word_args ("\037\nFile: %s, Node: ", pretty_output_filename
);
683 if (macro_expansion_output_stream
&& !executing_string
)
684 me_execute_string (node
);
686 execute_string ("%s", node
);
687 filling_enabled
= indented_fill
= 0;
690 /* Check for defaulting of this node's next, prev, and up fields. */
691 defaulting
= (*next
== 0 && *prev
== 0 && *up
== 0);
693 this_section
= what_section (input_text
+ input_text_offset
, NULL
);
695 /* If we are defaulting, then look at the immediately following
696 sectioning command (error if none) to determine the node's
697 level. Find the node that contains the menu mentioning this node
698 that is one level up (error if not found). That node is the "Up"
699 of this node. Default the "Next" and "Prev" from the menu. */
702 NODE_REF
*last_ref
= NULL
;
703 NODE_REF
*ref
= node_references
;
705 if (this_section
< 0 && !STREQ (node
, "Top"))
707 char *polite_section_name
= "top";
710 for (i
= 0; section_alist
[i
].name
; i
++)
711 if (section_alist
[i
].level
== current_section
+ 1)
713 polite_section_name
= section_alist
[i
].name
;
718 (_("Node `%s' requires a sectioning command (e.g., %c%s)"),
719 node
, COMMAND_PREFIX
, polite_section_name
);
723 if (strcmp (node
, "Top") == 0)
725 /* Default the NEXT pointer to be the first menu item in
726 this node, if there is a menu in this node. We have to
727 try very hard to find the menu, as it may be obscured
728 by execution_strings which are on the filestack. For
729 every member of the filestack which has a FILENAME
730 member which is identical to the current INPUT_FILENAME,
731 search forward from that offset. */
732 int saved_input_text_offset
= input_text_offset
;
733 int saved_input_text_length
= input_text_length
;
734 char *saved_input_text
= input_text
;
735 FSTACK
*next_file
= filestack
;
737 int orig_offset
, orig_size
;
739 int bye_offset
= search_forward ("\n@bye", input_text_offset
);
741 /* No matter what, make this file point back at `(dir)'. */
743 up
= xstrdup ("(dir)"); /* html fixxme */
747 orig_offset
= input_text_offset
;
749 search_forward (node_search_string
, orig_offset
);
752 orig_size
= input_text_length
;
754 input_text_offset
= search_forward ("\n@menu", orig_offset
);
755 if (input_text_offset
> -1
756 && (bye_offset
> -1 && input_text_offset
< bye_offset
)
757 && cr_or_whitespace (input_text
[input_text_offset
+ 6]))
759 char *nodename_from_menu
= NULL
;
762 search_forward ("\n* ", input_text_offset
);
764 if (input_text_offset
!= -1)
765 nodename_from_menu
= glean_node_from_menu (0, 0);
767 if (nodename_from_menu
)
770 next
= nodename_from_menu
;
775 /* We got here, so it hasn't been found yet. Try
776 the next file on the filestack if there is one. */
778 && FILENAME_CMP (next_file
->filename
, input_filename
)
781 input_text
= next_file
->text
;
782 input_text_offset
= next_file
->offset
;
783 input_text_length
= next_file
->size
;
784 next_file
= next_file
->next
;
787 { /* No more input files to check. */
792 input_text
= saved_input_text
;
793 input_text_offset
= saved_input_text_offset
;
794 input_text_length
= saved_input_text_length
;
798 /* Fix the level of the menu references in the Top node, iff it
799 was declared with @top, and no subsequent reference was found. */
800 if (top_node_seen
&& !non_top_node_seen
)
802 /* Then this is the first non-@top node seen. */
805 level
= set_top_section_level (this_section
- 1);
806 non_top_node_seen
= 1;
810 if (ref
->section
== level
)
811 ref
->section
= this_section
- 1;
815 ref
= node_references
;
820 if (ref
->section
== (this_section
- 1)
821 && ref
->type
== menu_reference
822 && strcmp (ref
->node
, node
) == 0)
824 char *containing_node
= ref
->containing_node
;
827 up
= xstrdup (containing_node
);
830 && last_ref
->type
== menu_reference
831 && strcmp (last_ref
->containing_node
, containing_node
) == 0)
834 next
= xstrdup (last_ref
->node
);
837 while (ref
->section
== this_section
- 1
839 && ref
->next
->type
!= menu_reference
)
842 if (ref
->next
&& ref
->type
== menu_reference
843 && strcmp (ref
->next
->containing_node
, containing_node
) == 0)
846 prev
= xstrdup (ref
->next
->node
);
849 && strcasecmp (ref
->containing_node
, "Top") == 0)
852 prev
= xstrdup (ref
->containing_node
);
861 /* Insert the correct args if we are expanding macros, and the node's
862 pointers weren't defaulted. */
863 if (macro_expansion_output_stream
&& !executing_string
&& !defaulting
)
866 int op_orig
= output_paragraph_offset
;
867 int meta_pos_orig
= meta_char_pos
;
868 int extra
= html
? strlen (node
) : 0;
870 temp
= xmalloc (7 + extra
+ strlen (next
) + strlen (prev
) + strlen (up
));
871 sprintf (temp
, "%s, %s, %s, %s", html
? node
: "", next
, prev
, up
);
872 me_execute_string (temp
);
875 output_paragraph_offset
= op_orig
;
876 meta_char_pos
= meta_pos_orig
;
881 line_error (_("No node name specified for `%c%s' command"),
882 COMMAND_PREFIX
, command
);
884 free (next
); next
= NULL
;
885 free (prev
); prev
= NULL
;
886 free (up
); up
= NULL
;
887 node_number
++; /* else it doesn't get bumped */
891 if (!*next
) { free (next
); next
= NULL
; }
892 if (!*prev
) { free (prev
); prev
= NULL
; }
893 if (!*up
) { free (up
); up
= NULL
; }
894 remember_node (node
, prev
, next
, up
, new_node_pos
, line_number
,
895 fname_for_this_node
, no_warn
);
896 outstanding_node
= 1;
901 if (splitting
&& *node
&& output_stream
== NULL
)
904 char filename
[PATH_MAX
];
906 dirname
= pathname_part (current_output_filename
);
907 strcpy (filename
, dirname
);
908 strcat (filename
, fname_for_this_node
);
911 /* See if the node name converted to a file name clashes
912 with other nodes or anchors. If it clashes with an
913 anchor, we complain and nuke that anchor's file. */
916 output_stream
= fopen (filename
, "w");
917 html_output_head_p
= 0; /* so that we generate HTML preamble */
920 else if ((tag
->flags
& TAG_FLAG_ANCHOR
) != 0)
922 line_error (_("Anchor `%s' and node `%s' map to the same file name"),
924 file_line_error (tag
->filename
, tag
->line_no
,
925 _("This @anchor command ignored; references to it will not work"));
926 file_line_error (tag
->filename
, tag
->line_no
,
927 _("Rename this anchor or use the `--no-split' option"));
928 /* Nuke the file name recorded in anchor's tag.
929 Since we are about to nuke the file itself, we
930 don't want find_node_by_fname to consider this
932 free (tag
->html_fname
);
933 tag
->html_fname
= NULL
;
934 output_stream
= fopen (filename
, "w");
935 html_output_head_p
= 0; /* so that we generate HTML preamble */
940 /* This node's file name clashes with another node.
941 We put them both on the same file. */
942 output_stream
= fopen (filename
, "r+");
945 static char html_end
[] = "</body></html>\n";
946 char end_line
[sizeof(html_end
)];
947 int fpos
= fseek (output_stream
, -epilogue_len
,
951 || fgets (end_line
, sizeof (html_end
),
952 output_stream
) == NULL
953 /* Paranoia: did someone change the way HTML
954 files are finished up? */
955 || strcasecmp (end_line
, html_end
) != 0)
957 line_error (_("Unexpected string at end of split-HTML file `%s'"),
958 fname_for_this_node
);
959 fclose (output_stream
);
962 fseek (output_stream
, -epilogue_len
, SEEK_END
);
965 if (output_stream
== NULL
)
970 set_current_output_filename (filename
);
973 if (!splitting
&& no_headers
)
974 { /* cross refs need a name="#anchor" even if not writing headers */
975 add_html_names (node
);
978 if (splitting
|| !no_headers
)
979 { /* Navigation bar. */
980 add_html_block_elt ("<div class=\"node\">\n");
981 /* The <p> avoids the links area running on with old Lynxen. */
982 add_word_args ("<p>%s\n", splitting
? "" : "<hr>");
984 /* In the split HTML case, the filename is wrong for the
985 old-style converted names, but we'll add them anyway, for
986 consistency. (And we need them in the normal (not
987 no_headers) nonsplit case.) */
988 add_html_names (node
);
992 tem
= expansion (next
, 0);
993 add_word ((char *) _("Next:"));
996 add_word ("<a rel=\"next\" accesskey=\"n\" href=\"");
997 add_anchor_name (tem
, 1);
998 tem
= escape_string (tem
);
999 add_word_args ("\">%s</a>", tem
);
1008 tem
= expansion (prev
, 0);
1009 add_word ((char *) _("Previous:"));
1010 add_word (" ");
1011 add_word ("<a rel=\"previous\" accesskey=\"p\" href=\"");
1012 add_anchor_name (tem
, 1);
1013 tem
= escape_string (tem
);
1014 add_word_args ("\">%s</a>", tem
);
1022 tem
= expansion (up
, 0);
1023 add_word ((char *) _("Up:"));
1024 add_word (" ");
1025 add_word ("<a rel=\"up\" accesskey=\"u\" href=\"");
1026 add_anchor_name (tem
, 1);
1027 tem
= escape_string (tem
);
1028 add_word_args ("\">%s</a>", tem
);
1031 /* html fixxme: we want a `top' or `contents' link here. */
1033 add_word_args ("\n%s\n", splitting
? "<hr>" : "");
1034 add_word ("</div>\n");
1043 xml_insert_element (NODENEXT
, START
);
1044 execute_string ("%s", next
);
1045 xml_insert_element (NODENEXT
, END
);
1049 xml_insert_element (NODEPREV
, START
);
1050 execute_string ("%s", prev
);
1051 xml_insert_element (NODEPREV
, END
);
1055 xml_insert_element (NODEUP
, START
);
1056 execute_string ("%s", up
);
1057 xml_insert_element (NODEUP
, END
);
1060 else if (!no_headers
)
1062 if (macro_expansion_output_stream
)
1063 me_inhibit_expansion
++;
1065 /* These strings are not translatable. */
1068 execute_string (", Next: %s", next
);
1069 filling_enabled
= indented_fill
= 0;
1073 execute_string (", Prev: %s", prev
);
1074 filling_enabled
= indented_fill
= 0;
1078 execute_string (", Up: %s", up
);
1079 filling_enabled
= indented_fill
= 0;
1081 if (macro_expansion_output_stream
)
1082 me_inhibit_expansion
--;
1088 /* Change the section only if there was a sectioning command. */
1089 if (this_section
>= 0)
1090 current_section
= this_section
;
1092 if (current_node
&& STREQ (current_node
, "Top"))
1095 filling_enabled
= 1;
1096 in_fixed_width_font
--;
1099 /* Cross-reference target at an arbitrary spot. */
1104 char *fname_for_anchor
= NULL
;
1109 /* Parse the anchor text. */
1110 anchor
= get_xref_token (1);
1112 /* Force all versions of "top" to be "Top". */
1113 normalize_node_name (anchor
);
1115 /* In HTML mode, need to actually produce some output. */
1118 /* If this anchor is at the beginning of a new paragraph, make
1119 sure a new paragraph is indeed started. */
1120 if (!paragraph_is_open
)
1122 if (!executing_string
&& html
)
1123 html_output_head ();
1125 if (!in_fixed_width_font
|| in_menu
|| in_detailmenu
)
1127 insert_string ("<p>");
1131 add_word ("<a name=\"");
1132 add_anchor_name (anchor
, 0);
1133 add_word ("\"></a>");
1136 /* If we are splitting, cm_xref will produce a reference to
1137 a file whose name is derived from the anchor name. So we
1138 must create a file when we see an @anchor, otherwise
1139 xref's to anchors won't work. The file we create simply
1140 redirects to the file of this anchor's node. */
1143 fname_for_anchor
= nodename_to_filename (anchor
);
1144 /* See if the anchor name converted to a file name clashes
1145 with other anchors or nodes. */
1146 tag
= find_node_by_fname (fname_for_anchor
);
1149 if ((tag
->flags
& TAG_FLAG_ANCHOR
) != 0)
1150 line_error (_("Anchors `%s' and `%s' map to the same file name"),
1153 line_error (_("Anchor `%s' and node `%s' map to the same file name"),
1155 line_error (_("@anchor command ignored; references to it will not work"));
1156 line_error (_("Rename this anchor or use the `--no-split' option"));
1157 free (fname_for_anchor
);
1158 /* We will not be creating a file for this anchor, so
1159 set its name to NULL, so that remember_node stores a
1160 NULL and find_node_by_fname won't consider this
1161 anchor for clashes. */
1162 fname_for_anchor
= NULL
;
1167 char filename
[PATH_MAX
];
1168 FILE *anchor_stream
;
1170 dirname
= pathname_part (current_output_filename
);
1171 strcpy (filename
, dirname
);
1172 strcat (filename
, fname_for_anchor
);
1175 anchor_stream
= fopen (filename
, "w");
1176 if (anchor_stream
== NULL
)
1178 fs_error (filename
);
1181 /* The HTML magic below will cause the browser to
1182 immediately go to the anchor's node's file. Lynx
1183 seems not to support this redirection, but it looks
1184 like a bug in Lynx, and they can work around it by
1185 clicking on the link once more. */
1186 fputs ("<meta http-equiv=\"refresh\" content=\"0; url=",
1188 /* Make the indirect link point to the current node's
1189 file and anchor's "<a name" label. If we don't have
1190 a valid node name, refer to the current output file
1192 if (current_node
&& *current_node
)
1196 tem
= expand_node_name (current_node
);
1197 fn
= nodename_to_filename (tem
);
1199 fputs (fn
, anchor_stream
);
1204 char *base
= filename_part (current_output_filename
);
1206 fputs (base
, anchor_stream
);
1209 fputs ("#", anchor_stream
);
1210 for (p
= anchor
; *p
; p
++)
1213 fputs ("&", anchor_stream
);
1214 else if (!URL_SAFE_CHAR (*p
))
1215 fprintf (anchor_stream
, "%%%x", (unsigned char) *p
);
1217 fputc (*p
, anchor_stream
);
1219 fputs ("\">\n", anchor_stream
);
1220 fclose (anchor_stream
);
1226 xml_insert_element_with_attribute (ANCHOR
, START
, "name=\"%s\"", anchor
);
1227 xml_insert_element (ANCHOR
, END
);
1229 /* Save it in the tag table. */
1230 remember_node (anchor
, NULL
, NULL
, NULL
,
1231 output_position
+ output_paragraph_offset
,
1232 line_number
, fname_for_anchor
, TAG_FLAG_ANCHOR
);
1235 /* Find NODE in REF_LIST. */
1237 find_node_reference (char *node
, NODE_REF
*ref_list
)
1239 NODE_REF
*orig_ref_list
= ref_list
;
1240 char *expanded_node
;
1244 if (strcmp (node
, ref_list
->node
) == 0)
1246 ref_list
= ref_list
->next
;
1249 if (ref_list
|| !expensive_validation
)
1252 /* Maybe NODE is not expanded yet. This may be SLOW. */
1253 expanded_node
= expand_node_name (node
);
1254 for (ref_list
= orig_ref_list
; ref_list
; ref_list
= ref_list
->next
)
1256 if (STREQ (expanded_node
, ref_list
->node
))
1258 if (strchr (ref_list
->node
, COMMAND_PREFIX
))
1260 char *expanded_ref
= expand_node_name (ref_list
->node
);
1262 if (STREQ (expanded_node
, expanded_ref
))
1264 free (expanded_ref
);
1267 free (expanded_ref
);
1270 free (expanded_node
);
1275 free_node_references (void)
1277 NODE_REF
*list
, *temp
;
1279 list
= node_references
;
1285 free (list
->containing_node
);
1289 node_references
= NULL
;
1293 free_node_node_references (void)
1295 NODE_REF
*list
, *temp
;
1297 list
= node_references
;
1306 node_node_references
= NULL
;
1309 /* Return the number assigned to a named node in either the tag_table
1310 or node_references list or zero if no number has been assigned. */
1312 number_of_node (char *node
)
1315 TAG_ENTRY
*temp_node
= find_node (node
);
1318 return temp_node
->number
;
1319 else if ((temp_ref
= find_node_reference (node
, node_references
)))
1320 return temp_ref
->number
;
1321 else if ((temp_ref
= find_node_reference (node
, node_node_references
)))
1322 return temp_ref
->number
;
1329 /* Return 1 if TAG (at LINE) correctly validated, or 0 if not.
1330 LABEL is the (translated) description of the type of reference --
1331 Menu, Cross, Next, etc. */
1334 validate (char *tag
, int line
, const char *label
)
1338 /* If there isn't a tag to verify, or if the tag is in another file,
1339 then it must be okay. */
1340 if (!tag
|| !*tag
|| *tag
== '(')
1343 /* Otherwise, the tag must exist. */
1344 result
= find_node (tag
);
1349 line_error (_("%s reference to nonexistent node `%s' (perhaps incorrect sectioning?)"), label
, tag
);
1356 /* The strings here are followed in the message by `reference to...' in
1357 the `validate' routine. They are only used in messages, thus are
1360 reftype_type_string (enum reftype type
)
1364 case menu_reference
:
1366 case followed_reference
:
1369 return "Internal-bad-reference-type";
1374 validate_other_references (NODE_REF
*ref_list
)
1376 char *old_input_filename
= input_filename
;
1380 input_filename
= ref_list
->filename
;
1381 validate (ref_list
->node
, ref_list
->line_no
,
1382 reftype_type_string (ref_list
->type
));
1383 ref_list
= ref_list
->next
;
1385 input_filename
= old_input_filename
;
1388 /* Validation of an info file.
1389 Scan through the list of tag entries touching the Prev, Next, and Up
1390 elements of each. It is an error not to be able to touch one of them,
1391 except in the case of external node references, such as "(DIR)".
1393 If the Prev is different from the Up,
1394 then the Prev node must have a Next pointing at this node.
1396 Every node except Top must have an Up.
1397 The Up node must contain some sort of reference, other than a Next,
1400 If the Next is different from the Next of the Up,
1401 then the Next node must have a Prev pointing at this node. */
1403 validate_file (TAG_ENTRY
*tag_table
)
1405 char *old_input_filename
= input_filename
;
1406 TAG_ENTRY
*tags
= tag_table
;
1410 TAG_ENTRY
*temp_tag
;
1413 input_filename
= tags
->filename
;
1414 line_number
= tags
->line_no
;
1416 /* If this is a "no warn" node, don't validate it in any way. */
1417 if (tags
->flags
& TAG_FLAG_NO_WARN
)
1419 tags
= tags
->next_ent
;
1423 /* If this node has a Next, then make sure that the Next exists. */
1426 validate (tags
->next
, tags
->line_no
, _("Next"));
1428 /* If the Next node exists, and there is no Up, then make sure
1429 that the Prev of the Next points back. But do nothing if
1430 we aren't supposed to issue warnings about this node. */
1431 temp_tag
= find_node (tags
->next
);
1432 if (temp_tag
&& !(temp_tag
->flags
& TAG_FLAG_NO_WARN
))
1434 char *prev
= temp_tag
->prev
;
1435 int you_lose
= !prev
|| !STREQ (prev
, tags
->node
);
1437 if (you_lose
&& expensive_validation
)
1439 tem1
= expand_node_name (prev
);
1440 tem2
= expand_node_name (tags
->node
);
1442 if (tem1
&& tem2
&& STREQ (tem1
, tem2
))
1449 line_error (_("Next field of node `%s' not pointed to (perhaps incorrect sectioning?)"),
1451 file_line_error (temp_tag
->filename
, temp_tag
->line_no
,
1452 _("This node (%s) has the bad Prev"),
1454 temp_tag
->flags
|= TAG_FLAG_PREV_ERROR
;
1459 /* Validate the Prev field if there is one, and we haven't already
1460 complained about it in some way. You don't have to have a Prev
1461 field at this stage. */
1462 if (!(tags
->flags
& TAG_FLAG_PREV_ERROR
) && tags
->prev
)
1464 int valid_p
= validate (tags
->prev
, tags
->line_no
, _("Prev"));
1467 tags
->flags
|= TAG_FLAG_PREV_ERROR
;
1469 { /* If the Prev field is not the same as the Up field,
1470 then the node pointed to by the Prev field must have
1471 a Next field which points to this node. */
1472 int prev_equals_up
= !tags
->up
|| STREQ (tags
->prev
, tags
->up
);
1474 if (!prev_equals_up
&& expensive_validation
)
1476 tem1
= expand_node_name (tags
->prev
);
1477 tem2
= expand_node_name (tags
->up
);
1478 prev_equals_up
= STREQ (tem1
, tem2
);
1482 if (!prev_equals_up
)
1484 temp_tag
= find_node (tags
->prev
);
1486 /* If we aren't supposed to issue warnings about the
1487 target node, do nothing. */
1488 if (!temp_tag
|| (temp_tag
->flags
& TAG_FLAG_NO_WARN
))
1492 int you_lose
= !temp_tag
->next
1493 || !STREQ (temp_tag
->next
, tags
->node
);
1495 if (temp_tag
->next
&& you_lose
&& expensive_validation
)
1497 tem1
= expand_node_name (temp_tag
->next
);
1498 tem2
= expand_node_name (tags
->node
);
1499 if (STREQ (tem1
, tem2
))
1507 (_("Prev field of node `%s' not pointed to"),
1509 file_line_error (temp_tag
->filename
,
1511 _("This node (%s) has the bad Next"),
1513 temp_tag
->flags
|= TAG_FLAG_NEXT_ERROR
;
1521 && !(tags
->flags
& TAG_FLAG_ANCHOR
)
1522 && strcasecmp (tags
->node
, "Top") != 0)
1523 line_error (_("`%s' has no Up field (perhaps incorrect sectioning?)"), tags
->node
);
1526 int valid_p
= validate (tags
->up
, tags
->line_no
, _("Up"));
1528 /* If node X has Up: Y, then warn if Y fails to have a menu item
1529 or note pointing at X, if Y isn't of the form "(Y)". */
1530 if (valid_p
&& *tags
->up
!= '(')
1533 NODE_REF
*tref
= NULL
;
1534 NODE_REF
*list
= node_references
;
1538 nref
= find_node_reference (tags
->node
, list
);
1542 if (strcmp (nref
->containing_node
, tags
->up
) == 0)
1544 if (nref
->type
!= menu_reference
)
1557 if (!tref
&& expensive_validation
)
1559 /* Sigh... This might be AWFULLY slow, but if
1560 they want this feature, they'll have to pay!
1561 We do all the loop again expanding each
1562 containing_node reference as we go. */
1563 char *tags_up
= expand_node_name (tags
->up
);
1566 list
= node_references
;
1570 nref
= find_node_reference (tags
->node
, list
);
1573 tem
= expand_node_name (nref
->containing_node
);
1574 if (STREQ (tem
, tags_up
))
1576 if (nref
->type
!= menu_reference
)
1590 temp_tag
= find_node (tags
->up
);
1591 file_line_error (temp_tag
->filename
, temp_tag
->line_no
,
1592 _("Node `%s' lacks menu item for `%s' despite being its Up target"),
1593 tags
->up
, tags
->node
);
1598 tags
= tags
->next_ent
;
1601 validate_other_references (node_references
);
1602 /* We have told the user about the references which didn't exist.
1603 Now tell him about the nodes which aren't referenced. */
1605 for (tags
= tag_table
; tags
; tags
= tags
->next_ent
)
1607 /* If this node is a "no warn" node, do nothing. */
1608 if (tags
->flags
& TAG_FLAG_NO_WARN
)
1610 tags
= tags
->next_ent
;
1614 /* Special hack. If the node in question appears to have
1615 been referenced more than REFERENCE_WARNING_LIMIT times,
1617 if (tags
->touched
> reference_warning_limit
)
1619 input_filename
= tags
->filename
;
1620 line_number
= tags
->line_no
;
1621 warning (_("node `%s' has been referenced %d times"),
1622 tags
->node
, tags
->touched
);
1625 if (tags
->touched
== 0)
1627 input_filename
= tags
->filename
;
1628 line_number
= tags
->line_no
;
1630 /* Notice that the node "Top" is special, and doesn't have to
1631 be referenced. Anchors don't have to be referenced
1632 either, you might define them for another document. */
1633 if (strcasecmp (tags
->node
, "Top") != 0
1634 && !(tags
->flags
& TAG_FLAG_ANCHOR
))
1635 warning (_("unreferenced node `%s'"), tags
->node
);
1638 input_filename
= old_input_filename
;
1644 /* Return true if the tag entry pointed to by TAGS is the last node.
1645 This means only anchors follow. */
1648 last_node_p (TAG_ENTRY
*tags
)
1651 while (tags
->next_ent
) {
1652 tags
= tags
->next_ent
;
1653 if (tags
->flags
& TAG_FLAG_ANCHOR
)
1667 enumerate_filename (char *pathname
, char *basename
, int number
)
1669 /* Do we need to generate names of subfiles which don't exceed 8+3 limits? */
1670 const int dos_file_names
= !HAVE_LONG_FILENAMES (pathname
? pathname
: ".");
1671 unsigned name_len
= strlen (basename
);
1672 char *filename
= xmalloc (10 + strlen (pathname
) + name_len
);
1673 char *base_filename
= xmalloc (10 + name_len
);
1675 sprintf (base_filename
, "%s-%d", basename
, number
);
1679 char *dot
= strchr (base_filename
, '.');
1680 unsigned base_len
= strlen (base_filename
);
1683 { /* Make foobar.i1, .., foobar.i99, foobar.100, ... */
1685 memmove (number
<= 99 ? dot
+ 2 : dot
+ 1,
1686 base_filename
+ name_len
+ 1,
1687 strlen (base_filename
+ name_len
+ 1) + 1);
1689 else if (base_len
> 8)
1691 /* Make foobar-1, .., fooba-10, .., foob-100, ... */
1692 unsigned numlen
= base_len
- name_len
;
1694 memmove (base_filename
+ 8 - numlen
, base_filename
+ name_len
, numlen
+ 1);
1698 sprintf (filename
, "%s%s", pathname
, base_filename
);
1703 /* Remove previously split files, to avoid
1704 lingering parts of shrinked documents. */
1706 clean_old_split_files (char *filename
)
1708 char *root_filename
= filename_part (filename
);
1709 char *root_pathname
= pathname_part (filename
);
1712 /* We break as soon as we hit an inexistent file,
1713 so looping until large numbers is harmless. */
1714 for (i
= 1; i
< 1000; i
++)
1717 char *check_file
= enumerate_filename (root_pathname
, root_filename
, i
);
1719 if (stat (check_file
, &st
) != 0)
1721 else if (!S_ISDIR (st
.st_mode
))
1723 /* Give feedback if requested, removing a file is important. */
1725 printf (_("Removing %s\n"), check_file
);
1727 /* Warn user that we cannot remove the file. */
1728 if (unlink (check_file
) != 0)
1729 warning (_("Can't remove file `%s': %s"), check_file
, strerror (errno
));
1737 /* Split large output files into a series of smaller files. Each file
1738 is pointed to in the tag table, which then gets written out as the
1739 original file. The new files have the same name as the original file
1740 with a "-num" attached. SIZE is the largest number of bytes to allow
1741 in any single split file. */
1743 split_file (char *filename
, int size
)
1745 char *root_filename
, *root_pathname
;
1747 struct stat fileinfo
;
1752 /* Can only do this to files with tag tables. */
1757 size
= DEFAULT_SPLIT_SIZE
;
1759 if ((stat (filename
, &fileinfo
) != 0)
1760 || (((long) fileinfo
.st_size
) < size
))
1762 file_size
= (long) fileinfo
.st_size
;
1764 the_file
= find_and_load (filename
, 0);
1768 root_filename
= filename_part (filename
);
1769 root_pathname
= pathname_part (filename
);
1772 root_pathname
= xstrdup ("");
1774 /* Start splitting the file. Walk along the tag table
1775 outputting sections of the file. When we have written
1776 all of the nodes in the tag table, make the top-level
1777 pointer file, which contains indirect pointers and
1778 tags for the nodes. */
1781 TAG_ENTRY
*tags
= tag_table
;
1782 char *indirect_info
= NULL
;
1784 /* Maybe we want a Local Variables section. */
1785 char *trailer
= info_trailer ();
1786 int trailer_len
= trailer
? strlen (trailer
) : 0;
1788 /* Remember the `header' of this file. The first tag in the file is
1789 the bottom of the header; the top of the file is the start. */
1790 the_header
= xmalloc (1 + (header_size
= tags
->position
));
1791 memcpy (the_header
, the_file
, header_size
);
1795 int file_top
, file_bot
, limit
;
1797 /* Have to include the Control-_. */
1798 file_top
= file_bot
= tags
->position
;
1799 limit
= file_top
+ size
;
1801 /* If the rest of this file is only one node, then
1802 that is the entire subfile. */
1803 if (last_node_p (tags
))
1805 int i
= tags
->position
+ 1;
1806 char last_char
= the_file
[i
];
1808 while (i
< file_size
)
1810 if ((the_file
[i
] == '\037') &&
1811 ((last_char
== '\n') ||
1812 (last_char
== '\014')))
1815 last_char
= the_file
[i
];
1819 tags
= tags
->next_ent
;
1823 /* Otherwise, find the largest number of nodes that can fit in
1825 for (; tags
; tags
= tags
->next_ent
)
1827 if (last_node_p (tags
))
1829 /* This entry is the last node. Search forward for the end
1830 of this node, and that is the end of this file. */
1831 int i
= tags
->position
+ 1;
1832 char last_char
= the_file
[i
];
1834 while (i
< file_size
)
1836 if ((the_file
[i
] == '\037') &&
1837 ((last_char
== '\n') ||
1838 (last_char
== '\014')))
1841 last_char
= the_file
[i
];
1846 if (file_bot
< limit
)
1848 tags
= tags
->next_ent
;
1853 /* Here we want to write out everything before the last
1854 node, and then write the last node out in a file
1856 file_bot
= tags
->position
;
1861 /* Write region only if this was a node, not an anchor. */
1862 if (tags
->next_ent
->position
> limit
1863 && !(tags
->flags
& TAG_FLAG_ANCHOR
))
1865 if (tags
->position
== file_top
)
1866 tags
= tags
->next_ent
;
1868 file_bot
= tags
->position
;
1873 char *split_filename
= enumerate_filename (root_pathname
,
1874 root_filename
, which_file
);
1875 char *split_basename
= filename_part (split_filename
);
1877 fd
= open (split_filename
, O_WRONLY
|O_TRUNC
|O_CREAT
, 0666);
1879 || write (fd
, the_header
, header_size
) != header_size
1880 || write (fd
, the_file
+ file_top
, file_bot
- file_top
)
1881 != (file_bot
- file_top
)
1883 && write (fd
, trailer
, trailer_len
) != trailer_len
)
1886 perror (split_filename
);
1894 indirect_info
= the_file
+ file_top
;
1895 sprintf (indirect_info
, "\037\nIndirect:\n");
1896 indirect_info
+= strlen (indirect_info
);
1899 sprintf (indirect_info
, "%s: %d\n",
1900 split_basename
, file_top
);
1902 free (split_basename
);
1903 free (split_filename
);
1904 indirect_info
+= strlen (indirect_info
);
1912 /* We have sucessfully created the subfiles. Now write out the
1913 original again. We must use `output_stream', or
1914 write_tag_table_indirect () won't know where to place the output. */
1915 output_stream
= fopen (filename
, "w");
1923 int distance
= indirect_info
- the_file
;
1924 fwrite (the_file
, 1, distance
, output_stream
);
1926 /* Inhibit newlines. */
1927 paragraph_is_open
= 0;
1929 /* Write the indirect tag table. */
1930 write_tag_table_indirect ();
1932 /* preserve local variables in info output. */
1935 fwrite (trailer
, 1, trailer_len
, output_stream
);
1939 fclose (output_stream
);