1 /* xref.c -- cross references for Texinfo.
2 $Id: xref.c,v 1.4 2004/12/21 17:28:35 karl Exp $
4 Copyright (C) 2004 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 2, or (at your option)
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, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
31 /* Flags which control initial output string for xrefs. */
35 /* Called in the multiple-argument case to make sure we generate a valid
36 Info reference. In the single-argument case, the :: we output
37 suffices for the Info readers to find the end of the reference. */
39 add_xref_punctuation (void)
41 if (px_ref_flag || ref_flag) /* user inserts punct after @xref */
43 /* Check if there's already punctuation. */
44 int next_char = next_nonwhitespace_character ();
47 /* EOF while looking for punctuation, let's
48 insert a period instead of crying. */
50 else if (next_char != ',' && next_char != '.')
51 /* period and comma terminate xrefs, and nothing else. Instead
52 of generating an Info reference that can't be followed,
53 though, just insert a period. Not pretty, but functional. */
58 /* Return next comma-delimited argument, but do not cross a close-brace
59 boundary. Clean up whitespace, too. If EXPAND is nonzero, replace
60 the entire brace-delimited argument list with its expansion before
61 looking for the next comma. */
63 get_xref_token (int expand)
68 xml_in_xref_token = 1;
72 int old_offset = input_text_offset;
73 int old_lineno = line_number;
75 get_until_in_braces ("}", &string);
76 if (curchar () == '}') /* as opposed to end of text */
78 if (input_text_offset > old_offset)
80 int limit = input_text_offset;
82 input_text_offset = old_offset;
83 line_number = old_lineno;
84 only_macro_expansion++;
85 replace_with_expansion (input_text_offset, &limit);
86 only_macro_expansion--;
91 get_until_in_braces (",", &string);
92 if (curchar () == ',')
94 fix_whitespace (string);
97 xml_in_xref_token = 0;
103 /* NOTE: If you wonder why the HTML output is produced with such a
104 peculiar mix of calls to add_word and execute_string, here's the
105 reason. get_xref_token (1) expands all macros in a reference, but
106 any other commands, like @value, @@, etc., are left intact. To
107 expand them, we need to run the arguments through execute_string.
108 However, characters like <, &, > and others cannot be let into
109 execute_string, because they will be escaped. See the mess? */
111 /* Make a cross reference. */
117 char *arg1 = get_xref_token (1); /* expands all macros in xref */
118 char *arg2 = get_xref_token (0);
119 char *arg3 = get_xref_token (0);
120 char *arg4 = get_xref_token (0);
121 char *arg5 = get_xref_token (0);
124 /* "@xref{,Foo,, Bar, Baz} is not valid usage of @xref. The
125 first argument must never be blank." --rms.
126 We hereby comply by disallowing such constructs. */
128 line_error (_("First argument to cross-reference may not be empty"));
133 add_word (px_ref_flag || printing_index
134 ? (char *) _("see ") : (char *) _("See "));
136 if (!*arg4 && !*arg5)
138 char *arg1_id = xml_id (arg1);
142 xml_insert_element_with_attribute (XREFNODENAME, START,
143 "linkend=\"%s\"", arg1_id);
145 execute_string ("%s", *arg3 ? arg3 : arg2);
146 xml_insert_element (XREFNODENAME, END);
150 xml_insert_element_with_attribute (XREF, START,
151 "linkend=\"%s\"", arg1_id);
152 xml_insert_element (XREF, END);
158 add_word_args (_("See section ``%s'' in "), *arg3 ? arg3 : arg1);
159 xml_insert_element (CITE, START);
161 xml_insert_element (CITE, END);
165 /* Very sad, we are losing xrefs made to ``info only'' books. */
171 add_word_args ("%s", px_ref_flag ? _("see ") : _("See "));
173 xml_insert_element (XREF, START);
174 xml_insert_element (XREFNODENAME, START);
175 execute_string ("%s", arg1);
176 xml_insert_element (XREFNODENAME, END);
179 xml_insert_element (XREFINFONAME, START);
180 execute_string ("%s", arg2);
181 xml_insert_element (XREFINFONAME, END);
185 xml_insert_element (XREFPRINTEDDESC, START);
186 execute_string ("%s", arg3);
187 xml_insert_element (XREFPRINTEDDESC, END);
191 xml_insert_element (XREFINFOFILE, START);
192 execute_string ("%s", arg4);
193 xml_insert_element (XREFINFOFILE, END);
197 xml_insert_element (XREFPRINTEDNAME, START);
198 execute_string ("%s", arg5);
199 xml_insert_element (XREFPRINTEDNAME, END);
201 xml_insert_element (XREF, END);
206 add_word_args ("%s", px_ref_flag ? _("see ") : _("See "));
209 add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
216 arg2 - reference name
217 arg3 - title or topic (and reference name if arg2 is NULL)
218 arg4 - info file name
219 arg5 - printed manual title */
233 { /* More to do eventually, down to Unicode
234 Normalization Form C. See the HTML Xref nodes in
236 char *file_arg = arg4;
237 add_html_elt ("<a href=");
240 /* If there's a directory part, ignore it. */
241 char *p = strrchr (file_arg, '/');
245 /* If there's a dot, make it a NULL terminator, so the
246 extension does not get into the way. */
247 p = strrchr (file_arg , '.');
253 warning (_("Empty file name for HTML cross reference in `%s'"),
256 /* Note that if we are splitting, and the referenced
257 tag is an anchor rather than a node, we will
258 produce a reference to a file whose name is
259 derived from the anchor name. However, only
260 nodes create files, so we are referencing a
261 non-existent file. cm_anchor, which see, deals
262 with that problem. */
264 execute_string ("\"../%s/", file_arg);
266 execute_string ("\"%s.html", file_arg);
267 /* Do not collapse -- to -, etc., in references. */
268 in_fixed_width_font++;
269 tem = expansion (arg1, 0); /* expand @-commands in node */
270 in_fixed_width_font--;
271 add_anchor_name (tem, 1);
274 execute_string ("%s",ref_name);
279 execute_string ("%s:", ref_name);
280 in_fixed_width_font++;
281 execute_string (" (%s)%s", arg4, arg1);
282 add_xref_punctuation ();
283 in_fixed_width_font--;
286 /* Free all of the arguments found. */
287 if (arg1) free (arg1);
288 if (arg2) free (arg2);
289 if (arg3) free (arg3);
290 if (arg4) free (arg4);
291 if (arg5) free (arg5);
295 remember_node_reference (arg1, line_number, followed_reference);
301 add_html_elt ("<a href=\"");
302 in_fixed_width_font++;
303 tem = expansion (arg1, 0);
304 in_fixed_width_font--;
305 add_anchor_name (tem, 1);
308 execute_string ("%s", *arg2 ? arg2 : arg3);
313 execute_string ("%s:", *arg2 ? arg2 : arg3);
314 in_fixed_width_font++;
315 execute_string (" %s", arg1);
316 add_xref_punctuation ();
317 in_fixed_width_font--;
324 add_html_elt ("<a href=\"");
325 in_fixed_width_font++;
326 tem = expansion (arg1, 0);
327 in_fixed_width_font--;
328 add_anchor_name (tem, 1);
332 execute_string ("%s", arg2);
335 char *fref = get_float_ref (arg1);
336 execute_string ("%s", fref ? fref : arg1);
345 execute_string ("%s:", arg2);
346 in_fixed_width_font++;
347 execute_string (" %s", arg1);
348 add_xref_punctuation ();
349 in_fixed_width_font--;
353 char *fref = get_float_ref (arg1);
355 { /* Reference is being made to a float. */
356 execute_string ("%s:", fref);
357 in_fixed_width_font++;
358 execute_string (" %s", arg1);
359 add_xref_punctuation ();
360 in_fixed_width_font--;
364 in_fixed_width_font++;
365 execute_string ("%s::", arg1);
366 in_fixed_width_font--;
372 /* Free all of the arguments found. */
373 if (arg1) free (arg1);
374 if (arg2) free (arg2);
375 if (arg3) free (arg3);
376 if (arg4) free (arg4);
377 if (arg5) free (arg5);
380 { /* Check that the next non-whitespace character is valid to follow
381 an xref (so Info readers can find the node names).
382 `input_text_offset' is pointing at the "}" which ended the xref
383 command. This is not used for @pxref or @ref, since we insert
384 the necessary punctuation above, if needed. */
385 int temp = next_nonwhitespace_character ();
388 warning (_("End of file reached while looking for `.' or `,'"));
389 else if (temp != '.' && temp != ',')
390 warning (_("`.' or `,' must follow @%s, not `%c'"), command, temp);
403 /* cm_xref isn't called with arg == END, which disables the code near
404 the end of cm_xref that checks for `.' or `,' after the
405 cross-reference. This is because cm_xref generates the required
406 character itself (when needed) if px_ref_flag is set. */
412 /* See the comments in cm_pxref about the checks for punctuation. */
426 char *node = get_xref_token (1); /* expands all macros in inforef */
427 char *pname = get_xref_token (0);
428 char *file = get_xref_token (0);
430 /* (see comments at cm_xref). */
432 line_error (_("First argument to @inforef may not be empty"));
436 xml_insert_element (INFOREF, START);
437 xml_insert_element (INFOREFNODENAME, START);
438 execute_string ("%s", node);
439 xml_insert_element (INFOREFNODENAME, END);
442 xml_insert_element (INFOREFREFNAME, START);
443 execute_string ("%s", pname);
444 xml_insert_element (INFOREFREFNAME, END);
446 xml_insert_element (INFOREFINFONAME, START);
447 execute_string ("%s", file);
448 xml_insert_element (INFOREFINFONAME, END);
450 xml_insert_element (INFOREF, END);
456 add_word ((char *) _("see "));
457 /* html fixxme: revisit this */
458 add_html_elt ("<a href=");
460 execute_string ("\"../%s/", file);
462 execute_string ("\"%s.html", file);
463 tem = expansion (node, 0);
464 add_anchor_name (tem, 1);
466 execute_string ("%s", *pname ? pname : tem);
473 execute_string ("*note %s: (%s)%s", pname, file, node);
475 execute_string ("*note (%s)%s::", file, node);
484 /* A URL reference. */
490 extern int printing_index;
491 char *url = get_xref_token (1); /* expands all macros in uref */
492 char *desc = get_xref_token (0);
493 char *replacement = get_xref_token (0);
497 xml_insert_element_with_attribute (UREF, START, "url=\"%s\"",
498 text_expansion (url));
500 execute_string ("%s", replacement);
502 execute_string ("%s", desc);
504 execute_string ("%s", url);
505 xml_insert_element (UREF, END);
509 xml_insert_element (UREF, START);
510 xml_insert_element (UREFURL, START);
511 execute_string ("%s", url);
512 xml_insert_element (UREFURL, END);
515 xml_insert_element (UREFDESC, START);
516 execute_string ("%s", desc);
517 xml_insert_element (UREFDESC, END);
521 xml_insert_element (UREFREPLACEMENT, START);
522 execute_string ("%s", replacement);
523 xml_insert_element (UREFREPLACEMENT, END);
525 xml_insert_element (UREF, END);
528 { /* never need to show the url */
529 add_html_elt ("<a href=");
530 /* don't collapse `--' etc. in the url */
531 in_fixed_width_font++;
532 execute_string ("\"%s\"", url);
533 in_fixed_width_font--;
535 execute_string ("%s", *replacement ? replacement
536 : (*desc ? desc : url));
539 else if (*replacement) /* do not show the url */
540 execute_string ("%s", replacement);
541 else if (*desc) /* show both text and url */
543 execute_string ("%s ", desc);
544 in_fixed_width_font++;
545 execute_string ("(%s)", url);
546 in_fixed_width_font--;
548 else /* no text at all, so have the url to show */
550 in_fixed_width_font++;
551 execute_string ("%s%s%s",
552 printing_index ? "" : "`",
554 printing_index ? "" : "'");
555 in_fixed_width_font--;
566 /* An email reference. */
572 char *addr = get_xref_token (1); /* expands all macros in email */
573 char *name = get_xref_token (0);
577 xml_insert_element_with_attribute (EMAIL, START, "url=\"mailto:%s\"", addr);
579 execute_string ("%s", name);
580 xml_insert_element (EMAIL, END);
584 xml_insert_element (EMAIL, START);
585 xml_insert_element (EMAILADDRESS, START);
586 execute_string ("%s", addr);
587 xml_insert_element (EMAILADDRESS, END);
590 xml_insert_element (EMAILNAME, START);
591 execute_string ("%s", name);
592 xml_insert_element (EMAILNAME, END);
594 xml_insert_element (EMAIL, END);
598 add_html_elt ("<a href=");
599 /* don't collapse `--' etc. in the address */
600 in_fixed_width_font++;
601 execute_string ("\"mailto:%s\"", addr);
602 in_fixed_width_font--;
604 execute_string ("%s", *name ? name : addr);
609 execute_string ("%s%s", name, *name ? " " : "");
610 in_fixed_width_font++;
611 execute_string ("<%s>", addr);
612 in_fixed_width_font--;