1 /* xref.c -- cross references for Texinfo.
2 $Id: xref.c,v 1.14 2007/09/26 20:53:40 karl Exp $
4 Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
30 /* Flags which control initial output string for xrefs. */
34 /* Called in the multiple-argument case to make sure we generate a valid
35 Info reference. In the single-argument case, the :: we output
36 suffices for the Info readers to find the end of the reference. */
38 add_xref_punctuation (void)
40 if (px_ref_flag || ref_flag) /* user inserts punct after @xref */
42 /* Check if there's already punctuation. */
43 int next_char = next_nonwhitespace_character ();
46 /* EOF while looking for punctuation, let's
47 insert a period instead of crying. */
49 else if (next_char != ',' && next_char != '.')
50 /* period and comma terminate xrefs, and nothing else. Instead
51 of generating an Info reference that can't be followed,
52 though, just insert a period. Not pretty, but functional. */
57 /* Return next comma-delimited argument, but do not cross a close-brace
58 boundary. Clean up whitespace, too. If EXPAND is nonzero, replace
59 the entire brace-delimited argument list with its expansion before
60 looking for the next comma. */
62 get_xref_token (int expand)
67 xml_in_xref_token = 1;
71 int old_offset = input_text_offset;
72 int old_lineno = line_number;
74 get_until_in_braces ("}", &string);
75 if (curchar () == '}') /* as opposed to end of text */
77 if (input_text_offset > old_offset)
79 int limit = input_text_offset;
81 input_text_offset = old_offset;
82 line_number = old_lineno;
83 only_macro_expansion++;
84 replace_with_expansion (input_text_offset, &limit);
85 only_macro_expansion--;
90 get_until_in_braces (",", &string);
91 if (curchar () == ',')
93 fix_whitespace (string);
96 xml_in_xref_token = 0;
102 /* NOTE: If you wonder why the HTML output is produced with such a
103 peculiar mix of calls to add_word and execute_string, here's the
104 reason. get_xref_token (1) expands all macros in a reference, but
105 any other commands, like @value, @@, etc., are left intact. To
106 expand them, we need to run the arguments through execute_string.
107 However, characters like <, &, > and others cannot be let into
108 execute_string, because they will be escaped. See the mess? */
110 /* Make a cross reference. */
116 char *arg1 = get_xref_token (1); /* expands all macros in xref */
117 char *arg2 = get_xref_token (0);
118 char *arg3 = get_xref_token (0);
119 char *arg4 = get_xref_token (0);
120 char *arg5 = get_xref_token (0);
123 /* "@xref{,Foo,, Bar, Baz} is not valid usage of @xref. The
124 first argument must never be blank." --rms.
125 We hereby comply by disallowing such constructs. */
127 line_error (_("First argument to cross-reference may not be empty"));
132 add_word (px_ref_flag || printing_index
133 ? (char *) gdt("see ") : (char *) gdt("See "));
135 if (!*arg4 && !*arg5)
137 char *arg1_id = xml_id (arg1);
141 xml_insert_element_with_attribute (XREFNODENAME, START,
142 "linkend=\"%s\"", arg1_id);
144 execute_string ("%s", *arg3 ? arg3 : arg2);
145 xml_insert_element (XREFNODENAME, END);
149 xml_insert_element_with_attribute (XREF, START,
150 "linkend=\"%s\"", arg1_id);
151 xml_insert_element (XREF, END);
157 add_word_args (gdt("See section ``%s'' in "), *arg3 ? arg3 : arg1);
158 xml_insert_element (CITE, START);
160 xml_insert_element (CITE, END);
164 /* Very sad, we are losing xrefs made to ``info only'' books. */
170 add_word_args ("%s", px_ref_flag ? gdt("see ") : gdt("See "));
172 xml_insert_element (XREF, START);
173 xml_insert_element (XREFNODENAME, START);
174 execute_string ("%s", arg1);
175 xml_insert_element (XREFNODENAME, END);
178 xml_insert_element (XREFINFONAME, START);
179 execute_string ("%s", arg2);
180 xml_insert_element (XREFINFONAME, END);
184 xml_insert_element (XREFPRINTEDDESC, START);
185 execute_string ("%s", arg3);
186 xml_insert_element (XREFPRINTEDDESC, END);
190 xml_insert_element (XREFINFOFILE, START);
191 execute_string ("%s", arg4);
192 xml_insert_element (XREFINFOFILE, END);
196 xml_insert_element (XREFPRINTEDNAME, START);
197 execute_string ("%s", arg5);
198 xml_insert_element (XREFPRINTEDNAME, END);
200 xml_insert_element (XREF, END);
205 add_word_args ("%s", px_ref_flag ? gdt("see ") : gdt("See "));
208 add_word_args ("%s", px_ref_flag || ref_flag ? "*note " : "*Note ");
215 arg2 - reference name
216 arg3 - title or topic (and reference name if arg2 is NULL)
217 arg4 - info file name
218 arg5 - printed manual title */
232 { /* More to do eventually, down to Unicode
233 Normalization Form C. See the HTML Xref nodes in
235 char *file_arg = arg4;
236 add_html_elt ("<a href=");
239 /* If there's a directory part, ignore it. */
240 char *p = strrchr (file_arg, '/');
244 /* If there's a dot, make it a NULL terminator, so the
245 extension does not get into the way. */
246 p = strrchr (file_arg , '.');
252 warning (_("Empty file name for HTML cross reference in `%s'"),
255 /* Note that if we are splitting, and the referenced
256 tag is an anchor rather than a node, we will
257 produce a reference to a file whose name is
258 derived from the anchor name. However, only
259 nodes create files, so we are referencing a
260 non-existent file. cm_anchor, which see, deals
261 with that problem. */
263 execute_string ("\"../%s/", file_arg);
265 execute_string ("\"%s.html", file_arg);
266 /* Do not collapse -- to -, etc., in references. */
267 in_fixed_width_font++;
268 tem = expansion (arg1, 0); /* expand @-commands in node */
269 in_fixed_width_font--;
270 add_anchor_name (tem, 1);
273 execute_string ("%s",ref_name);
278 execute_string ("%s:", ref_name);
279 in_fixed_width_font++;
280 execute_string (" (%s)%s", arg4, arg1);
281 add_xref_punctuation ();
282 in_fixed_width_font--;
285 /* Free all of the arguments found. */
286 if (arg1) free (arg1);
287 if (arg2) free (arg2);
288 if (arg3) free (arg3);
289 if (arg4) free (arg4);
290 if (arg5) free (arg5);
294 remember_node_reference (arg1, line_number, followed_reference);
300 add_html_elt ("<a href=\"");
301 in_fixed_width_font++;
302 tem = expansion (arg1, 0);
303 in_fixed_width_font--;
304 add_anchor_name (tem, 1);
307 execute_string ("%s", *arg2 ? arg2 : arg3);
312 execute_string ("%s:", *arg2 ? arg2 : arg3);
313 in_fixed_width_font++;
314 execute_string (" %s", arg1);
315 add_xref_punctuation ();
316 in_fixed_width_font--;
323 add_html_elt ("<a href=\"");
324 in_fixed_width_font++;
325 tem = expansion (arg1, 0);
326 in_fixed_width_font--;
327 add_anchor_name (tem, 1);
331 execute_string ("%s", arg2);
334 char *fref = get_float_ref (arg1);
335 execute_string ("%s", fref ? fref : arg1);
344 execute_string ("%s:", arg2);
345 in_fixed_width_font++;
346 execute_string (" %s", arg1);
347 add_xref_punctuation ();
348 in_fixed_width_font--;
352 char *fref = get_float_ref (arg1);
354 { /* Reference is being made to a float. */
355 execute_string ("%s:", fref);
356 in_fixed_width_font++;
357 execute_string (" %s", arg1);
358 add_xref_punctuation ();
359 in_fixed_width_font--;
363 in_fixed_width_font++;
364 execute_string ("%s::", arg1);
365 in_fixed_width_font--;
371 /* Free all of the arguments found. */
372 if (arg1) free (arg1);
373 if (arg2) free (arg2);
374 if (arg3) free (arg3);
375 if (arg4) free (arg4);
376 if (arg5) free (arg5);
379 { /* Check that the next non-whitespace character is valid to follow
380 an xref (so Info readers can find the node names).
381 `input_text_offset' is pointing at the "}" which ended the xref
382 command. This is not used for @pxref or @ref, since we insert
383 the necessary punctuation above, if needed. */
384 int temp = next_nonwhitespace_character ();
387 warning (_("End of file reached while looking for `.' or `,'"));
388 else if (temp != '.' && temp != ',')
390 warning (_("`.' or `,' must follow @%s, not `%c'"), command, temp);
392 warning (_("for cross-references in parentheses, use @pxref"));
406 /* cm_xref isn't called with arg == END, which disables the code near
407 the end of cm_xref that checks for `.' or `,' after the
408 cross-reference. This is because cm_xref generates the required
409 character itself (when needed) if px_ref_flag is set. */
415 /* See the comments in cm_pxref about the checks for punctuation. */
429 char *node = get_xref_token (1); /* expands all macros in inforef */
430 char *pname = get_xref_token (0);
431 char *file = get_xref_token (0);
433 /* (see comments at cm_xref). */
435 line_error (_("First argument to @inforef may not be empty"));
439 xml_insert_element (INFOREF, START);
440 xml_insert_element (INFOREFNODENAME, START);
441 execute_string ("%s", node);
442 xml_insert_element (INFOREFNODENAME, END);
445 xml_insert_element (INFOREFREFNAME, START);
446 execute_string ("%s", pname);
447 xml_insert_element (INFOREFREFNAME, END);
449 xml_insert_element (INFOREFINFONAME, START);
450 execute_string ("%s", file);
451 xml_insert_element (INFOREFINFONAME, END);
453 xml_insert_element (INFOREF, END);
459 add_word ((char *) gdt("see "));
460 /* html fixxme: revisit this */
461 add_html_elt ("<a href=");
463 execute_string ("\"../%s/", file);
465 execute_string ("\"%s.html", file);
466 tem = expansion (node, 0);
467 add_anchor_name (tem, 1);
469 execute_string ("%s", *pname ? pname : tem);
476 execute_string ("*note %s: (%s)%s", pname, file, node);
478 execute_string ("*note (%s)%s::", file, node);
487 /* A URL reference. */
493 char *url = get_xref_token (1); /* expands all macros in uref */
494 char *desc = get_xref_token (0);
495 char *replacement = get_xref_token (0);
499 xml_insert_element_with_attribute (UREF, START, "url=\"%s\"",
500 maybe_escaped_expansion (url, 0, 1));
502 execute_string ("%s", replacement);
504 execute_string ("%s", desc);
506 execute_string ("%s", url);
507 xml_insert_element (UREF, END);
511 xml_insert_element (UREF, START);
512 xml_insert_element (UREFURL, START);
513 execute_string ("%s", url);
514 xml_insert_element (UREFURL, END);
517 xml_insert_element (UREFDESC, START);
518 execute_string ("%s", desc);
519 xml_insert_element (UREFDESC, END);
523 xml_insert_element (UREFREPLACEMENT, START);
524 execute_string ("%s", replacement);
525 xml_insert_element (UREFREPLACEMENT, END);
527 xml_insert_element (UREF, END);
530 { /* never need to show the url */
531 add_html_elt ("<a href=");
532 /* don't collapse `--' etc. in the url */
533 in_fixed_width_font++;
534 execute_string ("\"%s\"", url);
535 in_fixed_width_font--;
537 execute_string ("%s", *replacement ? replacement
538 : (*desc ? desc : url));
541 else if (*replacement) /* do not show the url */
542 execute_string ("%s", replacement);
543 else if (*desc) /* show both text and url */
545 execute_string ("%s ", desc);
546 in_fixed_width_font++;
547 execute_string ("(%s)", url);
548 in_fixed_width_font--;
550 else /* no text at all, so have the url to show */
552 in_fixed_width_font++;
553 execute_string ("%s%s%s",
554 printing_index ? "" : "`",
556 printing_index ? "" : "'");
557 in_fixed_width_font--;
568 /* An email reference. */
574 char *addr = get_xref_token (1); /* expands all macros in email */
575 char *name = get_xref_token (0);
581 xml_insert_element_with_attribute (EMAIL, START,
583 maybe_escaped_expansion (addr, 0, 1));
584 execute_string ("%s", name);
585 xml_insert_element (EMAIL, END);
589 xml_insert_element (EMAILADDRESS, START);
590 execute_string ("%s", addr);
591 xml_insert_element (EMAILADDRESS, END);
596 xml_insert_element (EMAIL, START);
597 xml_insert_element (EMAILADDRESS, START);
598 execute_string ("%s", addr);
599 xml_insert_element (EMAILADDRESS, END);
602 xml_insert_element (EMAILNAME, START);
603 execute_string ("%s", name);
604 xml_insert_element (EMAILNAME, END);
606 xml_insert_element (EMAIL, END);
610 add_html_elt ("<a href=");
611 /* don't collapse `--' etc. in the address */
612 in_fixed_width_font++;
613 execute_string ("\"mailto:%s\"", addr);
614 in_fixed_width_font--;
616 execute_string ("%s", *name ? name : addr);
621 execute_string ("%s%s", name, *name ? " " : "");
622 in_fixed_width_font++;
623 execute_string ("<%s>", addr);
624 in_fixed_width_font--;