1 /* node.c -- nodes for Texinfo.
2 $Id: node.c,v 1.41 2008/07/05 23:57:29 karl Exp $
4 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
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 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
29 #include "sectioning.h"
30 #include "insertion.h"
33 /* See comments in node.h. */
34 NODE_REF *node_references = NULL;
35 NODE_REF *node_node_references = NULL;
36 TAG_ENTRY *tag_table = NULL;
39 int current_section = 0;
40 int outstanding_node = 0;
42 /* Adding nodes, and making tags. */
44 /* Start a new tag table. */
50 TAG_ENTRY *temp = tag_table;
55 tag_table = tag_table->next_ent;
60 /* Write out the contents of the existing tag table.
61 INDIRECT_P says how to format the output (it depends on whether the
62 table is direct or indirect). */
64 write_tag_table_internal (int indirect_p)
67 int old_indent = no_indent;
77 must_start_paragraph = 0;
86 add_word_args ("\037\nTag Table:\n%s", indirect_p ? "(Indirect)\n" : "");
88 /* Do not collapse -- to -, etc., in node names. */
89 in_fixed_width_font++;
91 for (node = tag_table; node; node = node->next_ent)
93 if (node->flags & TAG_FLAG_ANCHOR)
94 { /* This reference is to an anchor. */
95 execute_string ("Ref: %s", node->node);
98 { /* This reference is to a node. */
99 execute_string ("Node: %s", node->node);
101 add_word_args ("\177%d\n", node->position);
104 add_word ("\037\nEnd Tag Table\n");
106 /* Do not collapse -- to -, etc., in node names. */
107 in_fixed_width_font--;
110 no_indent = old_indent;
114 write_tag_table (char *filename)
116 output_stream = fopen (filename, "a");
123 write_tag_table_internal (0); /* Not indirect. */
125 if (fclose (output_stream) != 0)
130 write_tag_table_indirect (void)
132 write_tag_table_internal (1);
135 /* Convert "top" and friends into "Top". */
137 normalize_node_name (char *string)
139 if (mbscasecmp (string, "Top") == 0)
140 strcpy (string, "Top");
144 get_node_token (int expand)
148 get_until_in_line (expand, ",", &string);
150 if (curchar () == ',')
153 fix_whitespace (string);
155 /* Force all versions of "top" to be "Top". */
156 normalize_node_name (string);
161 /* Expand any macros and other directives in a node name, and
162 return the expanded name as an malloc'ed string. */
164 expand_node_name (char *node)
170 /* Don't expand --, `` etc., in case somebody will want
171 to print the result. */
172 in_fixed_width_font++;
173 result = expansion (node, 0);
174 in_fixed_width_font--;
175 fix_whitespace (result);
176 normalize_node_name (result);
181 /* Look up NAME in the tag table, and return the associated
182 tag_entry. If the node is not in the table return NULL. */
184 find_node (char *name)
186 TAG_ENTRY *tag = tag_table;
192 if (tag->node[0] == n1 && strcmp (tag->node, name) == 0)
197 if (!expensive_validation)
200 /* Try harder. Maybe TAG_TABLE has the expanded NAME, or maybe NAME
201 is expanded while TAG_TABLE has its unexpanded form. This may
202 slow down the search, but if they want this feature, let them
203 pay! If they want it fast, they should write every node name
204 consistently (either always expanded or always unexpaned). */
205 expanded_name = expand_node_name (name);
206 for (tag = tag_table; tag; tag = tag->next_ent)
208 if (STREQ (tag->node, expanded_name))
210 /* If the tag name doesn't have the command prefix, there's no
211 chance it could expand into anything but itself. */
212 if (strchr (tag->node, COMMAND_PREFIX))
214 char *expanded_node = expand_node_name (tag->node);
216 if (STREQ (expanded_node, expanded_name))
218 free (expanded_node);
221 free (expanded_node);
224 free (expanded_name);
228 /* Look in the tag table for a node whose file name is FNAME, and
229 return the associated tag_entry. If there's no such node in the
230 table, return NULL. */
232 find_node_by_fname (char *fname)
234 TAG_ENTRY *tag = tag_table;
237 if (tag->html_fname && FILENAME_CMP (tag->html_fname, fname) == 0)
245 /* Remember next, prev, etc. references in a @node command, where we
246 don't care about most of the entries. */
248 remember_node_node_reference (char *node)
250 NODE_REF *temp = xmalloc (sizeof (NODE_REF));
254 temp->next = node_node_references;
255 temp->node = xstrdup (node);
256 temp->type = followed_reference;
257 number = number_of_node (node);
259 temp->number = number; /* Already assigned. */
263 temp->number = node_number;
265 node_node_references = temp;
268 /* Remember NODE and associates. */
270 remember_node (char *node, char *prev, char *next, char *up,
271 int position, int line_no, char *fname, int flags)
273 /* Check for existence of this tag already. */
276 TAG_ENTRY *tag = find_node (node);
279 line_error (_("Node `%s' previously defined at line %d"),
285 if (!(flags & TAG_FLAG_ANCHOR))
287 /* Make this the current node. */
291 /* Add it to the list. */
293 int number = number_of_node (node);
295 TAG_ENTRY *new = xmalloc (sizeof (TAG_ENTRY));
300 new->position = position;
301 new->line_no = line_no;
302 new->filename = node_filename;
306 new->number = number; /* Already assigned. */
310 new->number = node_number;
313 new->html_fname = fname;
315 /* This happens for Top node under split-HTML, for example. */
317 = normalize_filename (filename_part (current_output_filename));
318 new->next_ent = tag_table;
320 /* Increment the order counter, and save it. */
322 new->order = node_order;
328 { /* Note the references to the next etc. nodes too. */
329 remember_node_node_reference (next);
330 remember_node_node_reference (prev);
331 remember_node_node_reference (up);
335 /* Remember this node name for later validation use. This is used to
336 remember menu references while reading the input file. After the
337 output file has been written, if validation is on, then we use the
338 contents of `node_references' as a list of nodes to validate. */
340 remember_node_reference (char *node, int line, enum reftype type)
342 NODE_REF *temp = xmalloc (sizeof (NODE_REF));
343 int number = number_of_node (node);
345 temp->next = node_references;
346 temp->node = xstrdup (node);
347 temp->line_no = line;
348 temp->section = current_section;
350 temp->containing_node = xstrdup (current_node ? current_node : "");
351 temp->filename = node_filename;
353 temp->number = number; /* Already assigned. */
357 temp->number = node_number;
360 node_references = temp;
364 isolate_nodename (char *nodename)
367 int paren_seen, paren;
372 canon_white (nodename);
373 paren_seen = paren = i = 0;
375 if (*nodename == '.' || !*nodename)
381 if (*nodename == '(')
388 for (; (c = nodename[i]); i++)
400 /* If the character following the close paren is a space, then this
401 node has no more characters associated with it. */
405 ((paren_seen && i > 0 && nodename[i - 1] == ')') &&
406 (c == ' ' || c == '.')) ||
408 ((!nodename[i + 1] ||
409 (cr_or_whitespace (nodename[i + 1])) ||
410 (nodename[i + 1] == ')')))))
416 /* This function gets called at the start of every line while inside a
417 menu. It checks to see if the line starts with "* ", and if so and
418 REMEMBER_REF is nonzero, remembers the node reference as type
419 REF_TYPE that this menu refers to. input_text_offset is at the \n
420 just before the menu line. If REMEMBER_REF is zero, REF_TYPE is unused. */
421 #define MENU_STARTER "* "
423 glean_node_from_menu (int remember_ref, enum reftype ref_type)
425 int i, orig_offset = input_text_offset;
427 char *line, *expanded_line;
428 char *old_input = input_text;
429 int old_size = input_text_length;
431 if (strncmp (&input_text[input_text_offset + 1],
433 strlen (MENU_STARTER)) != 0)
436 input_text_offset += strlen (MENU_STARTER) + 1;
438 /* The menu entry might include macro calls, so we need to expand them. */
439 get_until ("\n", &line);
440 only_macro_expansion++; /* only expand macros in menu entries */
441 expanded_line = expansion (line, 0);
442 only_macro_expansion--;
444 input_text = expanded_line;
445 input_text_offset = 0;
446 input_text_length = strlen (expanded_line);
448 get_until_in_line (0, ":", &nodename);
449 if (curchar () == ':')
452 if (curchar () != ':')
455 get_until_in_line (0, "\n", &nodename);
456 isolate_nodename (nodename);
459 input_text = old_input;
460 input_text_offset = orig_offset;
461 input_text_length = old_size;
462 free (expanded_line);
463 fix_whitespace (nodename);
464 normalize_node_name (nodename);
465 i = strlen (nodename);
466 if (i && nodename[i - 1] == ':')
470 remember_node_reference (nodename, line_number, ref_type);
475 /* Set the name of the current output file. */
477 set_current_output_filename (const char *fname)
479 if (current_output_filename)
480 free (current_output_filename);
481 current_output_filename = xstrdup (fname);
485 /* Output the <a name="..."></a> constructs for NODE. We output both
486 the new-style conversion and the old-style, if they are different.
487 See comments at `add_escaped_anchor_name' in html.c. */
490 add_html_names (char *node)
492 char *tem = expand_node_name (node);
493 char *otem = xstrdup (tem);
495 /* Determine if the old and new schemes come up with different names;
496 only output the old scheme if that is so. We don't want to output
497 the same name twice. */
503 for (; *optr; optr++)
505 if (!cr_or_whitespace (*optr) && !URL_SAFE_CHAR (*optr))
514 add_word ("<a name=\"");
515 add_anchor_name (otem, -1); /* old anchor name conversion */
516 add_word ("\"></a>\n");
521 /* Always output the new scheme. */
523 add_word ("<a name=\"");
524 add_anchor_name (tem, 0);
525 add_word ("\"></a>\n");
531 /* The order is: nodename, nextnode, prevnode, upnode.
532 If all of the NEXT, PREV, and UP fields are empty, they are defaulted.
533 You must follow a node command which has those fields defaulted
534 with a sectioning command (e.g., @chapter) giving the "level" of that node.
535 It is an error not to do so.
536 The defaults come from the menu in this node's parent. */
540 static long epilogue_len = 0L;
541 char *node, *prev, *next, *up;
542 int new_node_pos, defaulting, this_section;
544 char *fname_for_this_node = NULL;
546 TAG_ENTRY *tag = NULL;
548 if (strcmp (command, "nwnode") == 0)
549 no_warn = TAG_FLAG_NO_WARN;
551 /* Get rid of unmatched brace arguments from previous commands. */
554 /* There also might be insertions left lying around that haven't been
555 ended yet. Do that also. */
556 discard_insertions (1);
558 if (!html && !already_outputting_pending_notes)
561 output_pending_notes ();
564 new_node_pos = output_position;
566 if (macro_expansion_output_stream && !executing_string)
567 append_to_expansion_output (input_text_offset + 1);
569 /* Do not collapse -- to -, etc., in node names. */
570 in_fixed_width_font++;
572 /* While expanding the @node line, leave any non-macros
573 intact, so that the macro-expanded output includes them. */
574 only_macro_expansion++;
575 node = get_node_token (1);
576 only_macro_expansion--;
577 next = get_node_token (0);
578 prev = get_node_token (0);
579 up = get_node_token (0);
581 if (html && splitting
582 /* If there is a Top node, it always goes into index.html. So
583 don't start a new HTML file for Top. */
584 && (top_node_seen || mbscasecmp (node, "Top") != 0))
586 /* We test *node here so that @node without a valid name won't
587 start a new file name with a bogus name such as ".html".
588 This could happen if we run under "--force", where we cannot
589 simply bail out. Continuing to use the same file sounds like
590 the best we can do in such cases. */
591 if (current_output_filename && output_stream && *node)
593 char *fname_for_prev_node;
597 /* NOTE: current_node at this point still holds the name
598 of the previous node. */
599 tem = expand_node_name (current_node);
600 fname_for_prev_node = nodename_to_filename (tem);
603 else /* could happen if their top node isn't named "Top" */
604 fname_for_prev_node = filename_part (current_output_filename);
605 tem = expand_node_name (node);
606 fname_for_this_node = nodename_to_filename (tem);
608 /* Don't close current output file, if next output file is
609 to have the same name. This may happen at top level, or
610 if two nodes produce the same file name under --split. */
611 if (FILENAME_CMP (fname_for_this_node, fname_for_prev_node) != 0)
615 /* End the current split output file. */
617 output_pending_notes ();
619 /* Compute the length of the HTML file's epilogue. We
620 cannot know the value until run time, due to the
621 text/binary nuisance on DOS/Windows platforms, where
622 2 `\r' characters could be added to the epilogue when
623 it is written in text mode. */
624 if (epilogue_len == 0)
627 pos1 = ftell (output_stream);
629 add_word ("</body></html>\n");
631 if (epilogue_len == 0)
632 epilogue_len = ftell (output_stream) - pos1;
633 fclose (output_stream);
634 output_stream = NULL;
636 tag = find_node_by_fname (fname_for_this_node);
638 free (fname_for_prev_node);
642 filling_enabled = indented_fill = 0;
643 if (!html || (html && splitting))
644 current_footnote_number = 1;
647 printf (_("Formatting node %s...\n"), node);
649 if (macro_expansion_output_stream && !executing_string)
650 remember_itext (input_text, input_text_offset);
652 /* Reset the line number in each node for Info output, so that
653 index entries will save the line numbers of parent node. */
654 node_line_number = 0;
662 xml_insert_element (NODENAME, START);
663 if (macro_expansion_output_stream && !executing_string)
664 me_execute_string (node);
666 execute_string ("%s", node);
667 xml_insert_element (NODENAME, END);
670 xml_node_id = xml_id (node);
672 else if (!no_headers && !html)
674 /* Emacs Info reader cannot grok indented escape sequence. */
675 kill_self_indent (-1);
677 add_word_args ("\037\nFile: %s, Node: ", pretty_output_filename);
679 if (macro_expansion_output_stream && !executing_string)
680 me_execute_string (node);
682 execute_string ("%s", node);
683 filling_enabled = indented_fill = 0;
686 /* Check for defaulting of this node's next, prev, and up fields. */
687 defaulting = (*next == 0 && *prev == 0 && *up == 0);
689 this_section = what_section (input_text + input_text_offset, NULL);
691 /* If we are defaulting, then look at the immediately following
692 sectioning command (error if none) to determine the node's
693 level. Find the node that contains the menu mentioning this node
694 that is one level up (error if not found). That node is the "Up"
695 of this node. Default the "Next" and "Prev" from the menu. */
698 NODE_REF *last_ref = NULL;
699 NODE_REF *ref = node_references;
701 if (this_section < 0 && !STREQ (node, "Top"))
703 char *polite_section_name = "top";
706 for (i = 0; section_alist[i].name; i++)
707 if (section_alist[i].level == current_section + 1)
709 polite_section_name = section_alist[i].name;
714 (_("Node `%s' requires a sectioning command (e.g., %c%s)"),
715 node, COMMAND_PREFIX, polite_section_name);
719 if (strcmp (node, "Top") == 0)
721 /* Default the NEXT pointer to be the first menu item in
722 this node, if there is a menu in this node. We have to
723 try very hard to find the menu, as it may be obscured
724 by execution_strings which are on the filestack. For
725 every member of the filestack which has a FILENAME
726 member which is identical to the current INPUT_FILENAME,
727 search forward from that offset. */
728 int saved_input_text_offset = input_text_offset;
729 int saved_input_text_length = input_text_length;
730 char *saved_input_text = input_text;
731 FSTACK *next_file = filestack;
733 int orig_offset, orig_size;
735 int bye_offset = search_forward ("\n@bye", input_text_offset);
737 /* No matter what, make this file point back at `(dir)'. */
739 up = xstrdup ("(dir)"); /* html fixxme */
743 orig_offset = input_text_offset;
745 search_forward (node_search_string, orig_offset);
748 orig_size = input_text_length;
750 input_text_offset = search_forward ("\n@menu", orig_offset);
751 if (input_text_offset > -1
752 && (bye_offset > -1 && input_text_offset < bye_offset)
753 && cr_or_whitespace (input_text[input_text_offset + 6]))
755 char *nodename_from_menu = NULL;
758 search_forward ("\n* ", input_text_offset);
760 if (input_text_offset != -1)
761 nodename_from_menu = glean_node_from_menu (0,
764 if (nodename_from_menu)
767 next = nodename_from_menu;
772 /* We got here, so it hasn't been found yet. Try
773 the next file on the filestack if there is one. */
775 && FILENAME_CMP (next_file->filename, input_filename)
778 input_text = next_file->text;
779 input_text_offset = next_file->offset;
780 input_text_length = next_file->size;
781 next_file = next_file->next;
784 { /* No more input files to check. */
789 input_text = saved_input_text;
790 input_text_offset = saved_input_text_offset;
791 input_text_length = saved_input_text_length;
795 /* Fix the level of the menu references in the Top node, iff it
796 was declared with @top, and no subsequent reference was found. */
797 if (top_node_seen && !non_top_node_seen)
799 /* Then this is the first non-@top node seen. */
802 level = set_top_section_level (this_section - 1);
803 non_top_node_seen = 1;
807 if (ref->section == level)
808 ref->section = this_section - 1;
812 ref = node_references;
817 if (ref->section == (this_section - 1)
818 && ref->type == menu_reference
819 && strcmp (ref->node, node) == 0)
821 char *containing_node = ref->containing_node;
824 up = xstrdup (containing_node);
827 && last_ref->type == menu_reference
828 && strcmp (last_ref->containing_node, containing_node) == 0)
831 next = xstrdup (last_ref->node);
834 while (ref->section == this_section - 1
836 && ref->next->type != menu_reference)
839 if (ref->next && ref->type == menu_reference
840 && strcmp (ref->next->containing_node, containing_node) == 0)
843 prev = xstrdup (ref->next->node);
846 && mbscasecmp (ref->containing_node, "Top") == 0)
849 prev = xstrdup (ref->containing_node);
858 /* Insert the correct args if we are expanding macros, and the node's
859 pointers weren't defaulted. */
860 if (macro_expansion_output_stream && !executing_string && !defaulting)
863 int op_orig = output_paragraph_offset;
864 int meta_pos_orig = meta_char_pos;
865 int extra = html ? strlen (node) : 0;
867 temp = xmalloc (7 + extra + strlen (next) + strlen (prev) + strlen (up));
868 sprintf (temp, "%s, %s, %s, %s", html ? node : "", next, prev, up);
869 me_execute_string (temp);
872 output_paragraph_offset = op_orig;
873 meta_char_pos = meta_pos_orig;
878 line_error (_("No node name specified for `%c%s' command"),
879 COMMAND_PREFIX, command);
881 free (next); next = NULL;
882 free (prev); prev= NULL;
883 free (up); up = NULL;
884 node_number++; /* else it doesn't get bumped */
888 if (!*next) { free (next); next = NULL; }
889 if (!*prev) { free (prev); prev = NULL; }
890 if (!*up) { free (up); up = NULL; }
891 remember_node (node, prev, next, up, new_node_pos, line_number,
892 fname_for_this_node, no_warn);
893 outstanding_node = 1;
898 if (splitting && *node && output_stream == NULL)
901 char filename[PATH_MAX];
903 dirname = pathname_part (current_output_filename);
904 strcpy (filename, dirname);
905 strcat (filename, fname_for_this_node);
908 /* See if the node name converted to a file name clashes
909 with other nodes or anchors. If it clashes with an
910 anchor, we complain and nuke that anchor's file. */
913 output_stream = fopen (filename, "w");
914 output_head_p = 0; /* so that we generate HTML preamble */
917 else if ((tag->flags & TAG_FLAG_ANCHOR) != 0)
919 line_error (_("Anchor `%s' and node `%s' map to the same file name"),
921 file_line_error (tag->filename, tag->line_no,
922 _("This @anchor command ignored; references to it will not work"));
923 file_line_error (tag->filename, tag->line_no,
924 _("Rename this anchor or use the `--no-split' option"));
925 /* Nuke the file name recorded in anchor's tag.
926 Since we are about to nuke the file itself, we
927 don't want find_node_by_fname to consider this
929 free (tag->html_fname);
930 tag->html_fname = NULL;
931 output_stream = fopen (filename, "w");
932 output_head_p = 0; /* so that we generate HTML preamble */
937 /* This node's file name clashes with another node.
938 We put them both on the same file. */
939 output_stream = fopen (filename, "r+");
942 static char html_end[] = "</body></html>\n";
943 char end_line[sizeof(html_end)];
944 int fpos = fseek (output_stream, -epilogue_len,
948 || fgets (end_line, sizeof (html_end),
949 output_stream) == NULL
950 /* Paranoia: did someone change the way HTML
951 files are finished up? */
952 || mbscasecmp (end_line, html_end) != 0)
954 line_error (_("Unexpected string at end of split-HTML file `%s'"),
955 fname_for_this_node);
956 fclose (output_stream);
959 fseek (output_stream, -epilogue_len, SEEK_END);
962 if (output_stream == NULL)
967 set_current_output_filename (filename);
970 if (!splitting && no_headers)
971 { /* cross refs need a name="#anchor" even if not writing headers */
972 add_html_names (node);
975 if (splitting || !no_headers)
976 { /* Navigation bar. */
977 add_html_block_elt ("<div class=\"node\">\n");
979 /* In the split HTML case, the filename is wrong for the
980 old-style converted names, but we'll add them anyway, for
981 consistency. (And we need them in the normal (not
982 no_headers) nonsplit case.) */
983 add_html_names (node);
985 /* Do this after adding the anchors, so the browser rendering
986 can be better. The <p> avoids the links area running on
988 add_word_args ("<p>%s\n", splitting ? "" : "<hr>");
992 tem = expansion (next, 0);
993 add_word ((char *) gdt("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 *) gdt("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 *) gdt("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;
1108 /* We want to ignore whitespace following @anchor a la
1109 texinfo.tex, but we're sitting at the }. So advance past it,
1110 ignore the whitespace, and then go back one character. When we
1111 return, reader_loop will increment input_text_offset again (see
1112 the '}' case). Sorry. */
1113 input_text_offset++;
1114 skip_whitespace_and_newlines ();
1115 input_text_offset--;
1119 /* Parse the anchor text. */
1120 anchor = get_xref_token (1);
1122 /* Force all versions of "top" to be "Top". */
1123 normalize_node_name (anchor);
1125 /* In HTML mode, need to actually produce some output. */
1128 /* If this anchor is at the beginning of a new paragraph, make
1129 sure a new paragraph is indeed started. */
1130 if (!paragraph_is_open)
1132 if (!executing_string && html)
1135 if (!in_fixed_width_font || in_menu || in_detailmenu)
1137 insert_string ("<p>");
1141 add_word ("<a name=\"");
1142 add_anchor_name (anchor, 0);
1143 add_word ("\"></a>");
1146 /* If we are splitting, cm_xref will produce a reference to
1147 a file whose name is derived from the anchor name. So we
1148 must create a file when we see an @anchor, otherwise
1149 xref's to anchors won't work. The file we create simply
1150 redirects to the file of this anchor's node. */
1153 fname_for_anchor = nodename_to_filename (anchor);
1154 /* See if the anchor name converted to a file name clashes
1155 with other anchors or nodes. */
1156 tag = find_node_by_fname (fname_for_anchor);
1159 if ((tag->flags & TAG_FLAG_ANCHOR) != 0)
1160 line_error (_("Anchors `%s' and `%s' map to the same file name"),
1163 line_error (_("Anchor `%s' and node `%s' map to the same file name"),
1165 line_error (_("@anchor command ignored; references to it will not work"));
1166 line_error (_("Rename this anchor or use the `--no-split' option"));
1167 free (fname_for_anchor);
1168 /* We will not be creating a file for this anchor, so
1169 set its name to NULL, so that remember_node stores a
1170 NULL and find_node_by_fname won't consider this
1171 anchor for clashes. */
1172 fname_for_anchor = NULL;
1177 char filename[PATH_MAX];
1178 FILE *anchor_stream;
1180 dirname = pathname_part (current_output_filename);
1181 strcpy (filename, dirname);
1182 strcat (filename, fname_for_anchor);
1185 anchor_stream = fopen (filename, "w");
1186 if (anchor_stream == NULL)
1188 fs_error (filename);
1191 /* The HTML magic below will cause the browser to
1192 immediately go to the anchor's node's file. Lynx
1193 seems not to support this redirection, but it looks
1194 like a bug in Lynx, and they can work around it by
1195 clicking on the link once more. */
1196 fputs ("<meta http-equiv=\"refresh\" content=\"0; url=",
1198 /* Make the indirect link point to the current node's
1199 file and anchor's "<a name" label. If we don't have
1200 a valid node name, refer to the current output file
1202 if (current_node && *current_node)
1206 tem = expand_node_name (current_node);
1207 fn = nodename_to_filename (tem);
1209 fputs (fn, anchor_stream);
1214 char *base = filename_part (current_output_filename);
1216 fputs (base, anchor_stream);
1219 fputs ("#", anchor_stream);
1220 for (p = anchor; *p; p++)
1223 fputs ("&", anchor_stream);
1224 else if (!URL_SAFE_CHAR (*p))
1225 fprintf (anchor_stream, "%%%x", (unsigned char) *p);
1227 fputc (*p, anchor_stream);
1229 fputs ("\">\n", anchor_stream);
1230 fclose (anchor_stream);
1234 else if (xml || docbook)
1236 xml_insert_element_with_attribute (ANCHOR, START,
1237 docbook ? "id=\"%s\"" : "name=\"%s\"",
1239 xml_insert_element (ANCHOR, END);
1242 /* Save it in the tag table. */
1243 remember_node (anchor, NULL, NULL, NULL,
1244 output_position + output_paragraph_offset,
1245 line_number, fname_for_anchor, TAG_FLAG_ANCHOR);
1248 /* Find NODE in REF_LIST. */
1250 find_node_reference (char *node, NODE_REF *ref_list)
1252 NODE_REF *orig_ref_list = ref_list;
1253 char *expanded_node;
1257 if (strcmp (node, ref_list->node) == 0)
1259 ref_list = ref_list->next;
1262 if (ref_list || !expensive_validation)
1265 /* Maybe NODE is not expanded yet. This may be SLOW. */
1266 expanded_node = expand_node_name (node);
1267 for (ref_list = orig_ref_list; ref_list; ref_list = ref_list->next)
1269 if (STREQ (expanded_node, ref_list->node))
1271 if (strchr (ref_list->node, COMMAND_PREFIX))
1273 char *expanded_ref = expand_node_name (ref_list->node);
1275 if (STREQ (expanded_node, expanded_ref))
1277 free (expanded_ref);
1280 free (expanded_ref);
1283 free (expanded_node);
1288 free_node_references (void)
1290 NODE_REF *list, *temp;
1292 list = node_references;
1298 free (list->containing_node);
1302 node_references = NULL;
1306 free_node_node_references (void)
1308 NODE_REF *list, *temp;
1310 list = node_references;
1319 node_node_references = NULL;
1322 /* Return the number assigned to a named node in either the tag_table
1323 or node_references list or zero if no number has been assigned. */
1325 number_of_node (char *node)
1328 TAG_ENTRY *temp_node = find_node (node);
1331 return temp_node->number;
1332 else if ((temp_ref = find_node_reference (node, node_references)))
1333 return temp_ref->number;
1334 else if ((temp_ref = find_node_reference (node, node_node_references)))
1335 return temp_ref->number;
1342 /* Return 1 if TAG (at LINE) correctly validated, or 0 if not.
1343 LABEL is the (translated) description of the type of reference --
1344 Menu, Cross, Next, etc. */
1347 validate (char *tag, int line, const char *label)
1351 /* If there isn't a tag to verify, or if the tag is in another file,
1352 then it must be okay. */
1353 if (!tag || !*tag || *tag == '(')
1356 /* Otherwise, the tag must exist. */
1357 result = find_node (tag);
1362 line_error (_("%s reference to nonexistent node `%s' (perhaps incorrect sectioning?)"), label, tag);
1369 /* The strings here are followed in the message by `reference to...' in
1370 the `validate' routine. They are only used in messages, thus are
1373 reftype_type_string (enum reftype type)
1377 case menu_reference:
1379 case followed_reference:
1380 return gdt("Cross");
1382 return "Internal-bad-reference-type";
1387 validate_other_references (NODE_REF *ref_list)
1389 char *old_input_filename = input_filename;
1393 input_filename = ref_list->filename;
1394 validate (ref_list->node, ref_list->line_no,
1395 reftype_type_string (ref_list->type));
1396 ref_list = ref_list->next;
1398 input_filename = old_input_filename;
1401 /* Validation of an info file.
1402 Scan through the list of tag entries touching the Prev, Next, and Up
1403 elements of each. It is an error not to be able to touch one of them,
1404 except in the case of external node references, such as "(DIR)".
1406 If the Prev is different from the Up,
1407 then the Prev node must have a Next pointing at this node.
1409 Every node except Top must have an Up.
1410 The Up node must contain some sort of reference, other than a Next,
1413 If the Next is different from the Next of the Up,
1414 then the Next node must have a Prev pointing at this node. */
1416 validate_file (TAG_ENTRY *tag_table)
1418 char *old_input_filename = input_filename;
1419 TAG_ENTRY *tags = tag_table;
1423 TAG_ENTRY *temp_tag;
1426 input_filename = tags->filename;
1427 line_number = tags->line_no;
1429 /* If this is a "no warn" node, don't validate it in any way. */
1430 if (tags->flags & TAG_FLAG_NO_WARN)
1432 tags = tags->next_ent;
1436 /* If this node has a Next, then make sure that the Next exists. */
1439 validate (tags->next, tags->line_no, gdt("Next"));
1441 /* If the Next node exists, and there is no Up, then make sure
1442 that the Prev of the Next points back. But do nothing if
1443 we aren't supposed to issue warnings about this node. */
1444 temp_tag = find_node (tags->next);
1445 if (temp_tag && !(temp_tag->flags & TAG_FLAG_NO_WARN))
1447 char *prev = temp_tag->prev;
1448 int you_lose = !prev || !STREQ (prev, tags->node);
1450 if (you_lose && expensive_validation)
1452 tem1 = expand_node_name (prev);
1453 tem2 = expand_node_name (tags->node);
1455 if (tem1 && tem2 && STREQ (tem1, tem2))
1462 line_error (_("Next field of node `%s' not pointed to (perhaps incorrect sectioning?)"),
1464 file_line_error (temp_tag->filename, temp_tag->line_no,
1465 _("This node (%s) has the bad Prev"),
1467 temp_tag->flags |= TAG_FLAG_PREV_ERROR;
1472 /* Validate the Prev field if there is one, and we haven't already
1473 complained about it in some way. You don't have to have a Prev
1474 field at this stage. */
1475 if (!(tags->flags & TAG_FLAG_PREV_ERROR) && tags->prev)
1477 int valid_p = validate (tags->prev, tags->line_no, gdt("Prev"));
1480 tags->flags |= TAG_FLAG_PREV_ERROR;
1482 { /* If the Prev field is not the same as the Up field,
1483 then the node pointed to by the Prev field must have
1484 a Next field which points to this node. */
1485 int prev_equals_up = !tags->up || STREQ (tags->prev, tags->up);
1487 if (!prev_equals_up && expensive_validation)
1489 tem1 = expand_node_name (tags->prev);
1490 tem2 = expand_node_name (tags->up);
1491 prev_equals_up = STREQ (tem1, tem2);
1495 if (!prev_equals_up)
1497 temp_tag = find_node (tags->prev);
1499 /* If we aren't supposed to issue warnings about the
1500 target node, do nothing. */
1501 if (!temp_tag || (temp_tag->flags & TAG_FLAG_NO_WARN))
1505 int you_lose = !temp_tag->next
1506 || !STREQ (temp_tag->next, tags->node);
1508 if (temp_tag->next && you_lose && expensive_validation)
1510 tem1 = expand_node_name (temp_tag->next);
1511 tem2 = expand_node_name (tags->node);
1512 if (STREQ (tem1, tem2))
1520 (_("Prev field of node `%s' not pointed to"),
1522 file_line_error (temp_tag->filename,
1524 _("This node (%s) has the bad Next"),
1526 temp_tag->flags |= TAG_FLAG_NEXT_ERROR;
1534 && !(tags->flags & TAG_FLAG_ANCHOR)
1535 && mbscasecmp (tags->node, "Top") != 0)
1536 line_error (_("`%s' has no Up field (perhaps incorrect sectioning?)"), tags->node);
1539 int valid_p = validate (tags->up, tags->line_no, gdt("Up"));
1541 /* If node X has Up: Y, then warn if Y fails to have a menu item
1542 or note pointing at X, if Y isn't of the form "(Y)". */
1543 if (valid_p && *tags->up != '(')
1546 NODE_REF *tref = NULL;
1547 NODE_REF *list = node_references;
1551 nref = find_node_reference (tags->node, list);
1555 if (strcmp (nref->containing_node, tags->up) == 0)
1557 if (nref->type != menu_reference)
1570 if (!tref && expensive_validation)
1572 /* Sigh... This might be AWFULLY slow, but if
1573 they want this feature, they'll have to pay!
1574 We do all the loop again expanding each
1575 containing_node reference as we go. */
1576 char *tags_up = expand_node_name (tags->up);
1579 list = node_references;
1583 nref = find_node_reference (tags->node, list);
1586 tem = expand_node_name (nref->containing_node);
1587 if (STREQ (tem, tags_up))
1589 if (nref->type != menu_reference)
1603 temp_tag = find_node (tags->up);
1604 file_line_error (temp_tag->filename, temp_tag->line_no,
1605 _("Node `%s' lacks menu item for `%s' despite being its Up target"),
1606 tags->up, tags->node);
1611 tags = tags->next_ent;
1614 validate_other_references (node_references);
1615 /* We have told the user about the references which didn't exist.
1616 Now tell him about the nodes which aren't referenced. */
1618 for (tags = tag_table; tags; tags = tags->next_ent)
1620 /* If this node is a "no warn" node, do nothing. */
1621 if (tags->flags & TAG_FLAG_NO_WARN)
1623 tags = tags->next_ent;
1627 if (tags->touched == 0)
1629 input_filename = tags->filename;
1630 line_number = tags->line_no;
1632 /* Notice that the node "Top" is special, and doesn't have to
1633 be referenced. Anchors don't have to be referenced
1634 either, you might define them for another document. */
1635 if (mbscasecmp (tags->node, "Top") != 0
1636 && !(tags->flags & TAG_FLAG_ANCHOR))
1637 warning (_("unreferenced node `%s'"), tags->node);
1640 input_filename = old_input_filename;
1646 /* Return true if the tag entry pointed to by TAGS is the last node.
1647 This means only anchors follow. */
1650 last_node_p (TAG_ENTRY *tags)
1653 while (tags->next_ent) {
1654 tags = tags->next_ent;
1655 if (tags->flags & TAG_FLAG_ANCHOR)
1669 enumerate_filename (char *pathname, char *basename, int number)
1671 /* Do we need to generate names of subfiles which don't exceed 8+3 limits? */
1672 const int dos_file_names = !HAVE_LONG_FILENAMES (pathname ? pathname : ".");
1673 unsigned name_len = strlen (basename);
1674 char *filename = xmalloc (10 + strlen (pathname) + name_len);
1675 char *base_filename = xmalloc (10 + name_len);
1677 sprintf (base_filename, "%s-%d", basename, number);
1681 char *dot = strchr (base_filename, '.');
1682 unsigned base_len = strlen (base_filename);
1685 { /* Make foobar.i1, .., foobar.i99, foobar.100, ... */
1687 memmove (number <= 99 ? dot + 2 : dot + 1,
1688 base_filename + name_len + 1,
1689 strlen (base_filename + name_len + 1) + 1);
1691 else if (base_len > 8)
1693 /* Make foobar-1, .., fooba-10, .., foob-100, ... */
1694 unsigned numlen = base_len - name_len;
1696 memmove (base_filename + 8 - numlen, base_filename + name_len, numlen + 1);
1700 sprintf (filename, "%s%s", pathname, base_filename);
1705 /* Remove previously split files, to avoid
1706 lingering parts of shrinked documents. */
1708 clean_old_split_files (char *filename)
1710 char *root_filename = filename_part (filename);
1711 char *root_pathname = pathname_part (filename);
1714 /* We break as soon as we hit an inexistent file,
1715 so looping until large numbers is harmless. */
1716 for (i = 1; i < 1000; i++)
1719 char *check_file = enumerate_filename (root_pathname, root_filename, i);
1721 if (stat (check_file, &st) != 0)
1723 else if (!S_ISDIR (st.st_mode))
1725 /* Give feedback if requested, removing a file is important. */
1727 printf (_("Removing %s\n"), check_file);
1729 /* Warn user that we cannot remove the file. */
1730 if (unlink (check_file) != 0)
1731 warning (_("Can't remove file `%s': %s"), check_file, strerror (errno));
1739 /* Split large output files into a series of smaller files. Each file
1740 is pointed to in the tag table, which then gets written out as the
1741 original file. The new files have the same name as the original file
1742 with a "-num" attached. SIZE is the largest number of bytes to allow
1743 in any single split file. */
1745 split_file (char *filename, int size)
1747 char *root_filename, *root_pathname;
1749 struct stat fileinfo;
1754 /* Can only do this to files with tag tables. */
1759 size = DEFAULT_SPLIT_SIZE;
1761 if ((stat (filename, &fileinfo) != 0)
1762 || (((long) fileinfo.st_size) < size))
1764 file_size = (long) fileinfo.st_size;
1766 the_file = find_and_load (filename, 0);
1770 root_filename = filename_part (filename);
1771 root_pathname = pathname_part (filename);
1774 root_pathname = xstrdup ("");
1776 /* Start splitting the file. Walk along the tag table
1777 outputting sections of the file. When we have written
1778 all of the nodes in the tag table, make the top-level
1779 pointer file, which contains indirect pointers and
1780 tags for the nodes. */
1783 TAG_ENTRY *tags = tag_table;
1784 char *indirect_info = NULL;
1786 /* Maybe we want a Local Variables section. */
1787 char *trailer = info_trailer ();
1788 int trailer_len = trailer ? strlen (trailer) : 0;
1790 /* Remember the `header' of this file. The first tag in the file is
1791 the bottom of the header; the top of the file is the start. */
1792 the_header = xmalloc (1 + (header_size = tags->position));
1793 memcpy (the_header, the_file, header_size);
1797 int file_top, file_bot, limit;
1799 /* Have to include the Control-_. */
1800 file_top = file_bot = tags->position;
1801 limit = file_top + size;
1803 /* If the rest of this file is only one node, then
1804 that is the entire subfile. */
1805 if (last_node_p (tags))
1807 int i = tags->position + 1;
1808 char last_char = the_file[i];
1810 while (i < file_size)
1812 if ((the_file[i] == '\037') &&
1813 ((last_char == '\n') ||
1814 (last_char == '\014')))
1817 last_char = the_file[i];
1821 tags = tags->next_ent;
1825 /* Otherwise, find the largest number of nodes that can fit in
1827 for (; tags; tags = tags->next_ent)
1829 if (last_node_p (tags))
1831 /* This entry is the last node. Search forward for the end
1832 of this node, and that is the end of this file. */
1833 int i = tags->position + 1;
1834 char last_char = the_file[i];
1836 while (i < file_size)
1838 if ((the_file[i] == '\037') &&
1839 ((last_char == '\n') ||
1840 (last_char == '\014')))
1843 last_char = the_file[i];
1848 if (file_bot < limit)
1850 tags = tags->next_ent;
1855 /* Here we want to write out everything before the last
1856 node, and then write the last node out in a file
1858 file_bot = tags->position;
1863 /* Write region only if this was a node, not an anchor. */
1864 if (tags->next_ent->position > limit
1865 && !(tags->flags & TAG_FLAG_ANCHOR))
1867 if (tags->position == file_top)
1868 tags = tags->next_ent;
1870 file_bot = tags->position;
1875 char *split_filename = enumerate_filename (root_pathname,
1876 root_filename, which_file);
1877 char *split_basename = filename_part (split_filename);
1879 fd = open (split_filename, O_WRONLY|O_TRUNC|O_CREAT, 0666);
1881 || write (fd, the_header, header_size) != header_size
1882 || write (fd, the_file + file_top, file_bot - file_top)
1883 != (file_bot - file_top)
1885 && write (fd, trailer, trailer_len) != trailer_len)
1888 perror (split_filename);
1896 indirect_info = the_file + file_top;
1897 sprintf (indirect_info, "\037\nIndirect:\n");
1898 indirect_info += strlen (indirect_info);
1901 sprintf (indirect_info, "%s: %d\n",
1902 split_basename, file_top);
1904 free (split_basename);
1905 free (split_filename);
1906 indirect_info += strlen (indirect_info);
1914 /* We have sucessfully created the subfiles. Now write out the
1915 original again. We must use `output_stream', or
1916 write_tag_table_indirect () won't know where to place the output. */
1917 output_stream = fopen (filename, "w");
1925 int distance = indirect_info - the_file;
1926 fwrite (the_file, 1, distance, output_stream);
1928 /* Inhibit newlines. */
1929 paragraph_is_open = 0;
1931 /* Write the indirect tag table. */
1932 write_tag_table_indirect ();
1934 /* preserve local variables in info output. */
1937 fwrite (trailer, 1, trailer_len, output_stream);
1941 fclose (output_stream);