3 /* xref.c -- cross references for Texinfo.
4 Id: xref.c,v 1.4 2004/12/21 17:28:35 karl Exp
6 Copyright (C) 2004 Free Software Foundation, Inc.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software Foundation,
20 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
33 /* Flags which control initial output string for xrefs. */
37 /* Called in the multiple-argument case to make sure we generate a valid
38 Info reference. In the single-argument case, the :: we output
39 suffices for the Info readers to find the end of the reference. */
41 add_xref_punctuation (void)
43 if (px_ref_flag
|| ref_flag
) /* user inserts punct after @xref */
45 /* Check if there's already punctuation. */
46 int next_char
= next_nonwhitespace_character ();
49 /* EOF while looking for punctuation, let's
50 insert a period instead of crying. */
52 else if (next_char
!= ',' && next_char
!= '.')
53 /* period and comma terminate xrefs, and nothing else. Instead
54 of generating an Info reference that can't be followed,
55 though, just insert a period. Not pretty, but functional. */
60 /* Return next comma-delimited argument, but do not cross a close-brace
61 boundary. Clean up whitespace, too. If EXPAND is nonzero, replace
62 the entire brace-delimited argument list with its expansion before
63 looking for the next comma. */
65 get_xref_token (int expand
)
70 xml_in_xref_token
= 1;
74 int old_offset
= input_text_offset
;
75 int old_lineno
= line_number
;
77 get_until_in_braces ("}", &string
);
78 if (curchar () == '}') /* as opposed to end of text */
80 if (input_text_offset
> old_offset
)
82 int limit
= input_text_offset
;
84 input_text_offset
= old_offset
;
85 line_number
= old_lineno
;
86 only_macro_expansion
++;
87 replace_with_expansion (input_text_offset
, &limit
);
88 only_macro_expansion
--;
93 get_until_in_braces (",", &string
);
94 if (curchar () == ',')
96 fix_whitespace (string
);
99 xml_in_xref_token
= 0;
105 /* NOTE: If you wonder why the HTML output is produced with such a
106 peculiar mix of calls to add_word and execute_string, here's the
107 reason. get_xref_token (1) expands all macros in a reference, but
108 any other commands, like @value, @@, etc., are left intact. To
109 expand them, we need to run the arguments through execute_string.
110 However, characters like <, &, > and others cannot be let into
111 execute_string, because they will be escaped. See the mess? */
113 /* Make a cross reference. */
119 char *arg1
= get_xref_token (1); /* expands all macros in xref */
120 char *arg2
= get_xref_token (0);
121 char *arg3
= get_xref_token (0);
122 char *arg4
= get_xref_token (0);
123 char *arg5
= get_xref_token (0);
126 /* "@xref{,Foo,, Bar, Baz} is not valid usage of @xref. The
127 first argument must never be blank." --rms.
128 We hereby comply by disallowing such constructs. */
130 line_error (_("First argument to cross-reference may not be empty"));
135 add_word (px_ref_flag
|| printing_index
136 ? (char *) _("see ") : (char *) _("See "));
138 if (!*arg4
&& !*arg5
)
140 char *arg1_id
= xml_id (arg1
);
144 xml_insert_element_with_attribute (XREFNODENAME
, START
,
145 "linkend=\"%s\"", arg1_id
);
147 execute_string ("%s", *arg3
? arg3
: arg2
);
148 xml_insert_element (XREFNODENAME
, END
);
152 xml_insert_element_with_attribute (XREF
, START
,
153 "linkend=\"%s\"", arg1_id
);
154 xml_insert_element (XREF
, END
);
160 add_word_args (_("See section ``%s'' in "), *arg3
? arg3
: arg1
);
161 xml_insert_element (CITE
, START
);
163 xml_insert_element (CITE
, END
);
167 /* Very sad, we are losing xrefs made to ``info only'' books. */
173 add_word_args ("%s", px_ref_flag
? _("see ") : _("See "));
175 xml_insert_element (XREF
, START
);
176 xml_insert_element (XREFNODENAME
, START
);
177 execute_string ("%s", arg1
);
178 xml_insert_element (XREFNODENAME
, END
);
181 xml_insert_element (XREFINFONAME
, START
);
182 execute_string ("%s", arg2
);
183 xml_insert_element (XREFINFONAME
, END
);
187 xml_insert_element (XREFPRINTEDDESC
, START
);
188 execute_string ("%s", arg3
);
189 xml_insert_element (XREFPRINTEDDESC
, END
);
193 xml_insert_element (XREFINFOFILE
, START
);
194 execute_string ("%s", arg4
);
195 xml_insert_element (XREFINFOFILE
, END
);
199 xml_insert_element (XREFPRINTEDNAME
, START
);
200 execute_string ("%s", arg5
);
201 xml_insert_element (XREFPRINTEDNAME
, END
);
203 xml_insert_element (XREF
, END
);
208 add_word_args ("%s", px_ref_flag
? _("see ") : _("See "));
211 add_word_args ("%s", px_ref_flag
? "*note " : "*Note ");
218 arg2 - reference name
219 arg3 - title or topic (and reference name if arg2 is NULL)
220 arg4 - info file name
221 arg5 - printed manual title */
235 { /* More to do eventually, down to Unicode
236 Normalization Form C. See the HTML Xref nodes in
238 char *file_arg
= arg4
;
239 add_html_elt ("<a href=");
242 /* If there's a directory part, ignore it. */
243 char *p
= strrchr (file_arg
, '/');
247 /* If there's a dot, make it a NULL terminator, so the
248 extension does not get into the way. */
249 p
= strrchr (file_arg
, '.');
255 warning (_("Empty file name for HTML cross reference in `%s'"),
258 /* Note that if we are splitting, and the referenced
259 tag is an anchor rather than a node, we will
260 produce a reference to a file whose name is
261 derived from the anchor name. However, only
262 nodes create files, so we are referencing a
263 non-existent file. cm_anchor, which see, deals
264 with that problem. */
266 execute_string ("\"../%s/", file_arg
);
268 execute_string ("\"%s.html", file_arg
);
269 /* Do not collapse -- to -, etc., in references. */
270 in_fixed_width_font
++;
271 tem
= expansion (arg1
, 0); /* expand @-commands in node */
272 in_fixed_width_font
--;
273 add_anchor_name (tem
, 1);
276 execute_string ("%s",ref_name
);
281 execute_string ("%s:", ref_name
);
282 in_fixed_width_font
++;
283 execute_string (" (%s)%s", arg4
, arg1
);
284 add_xref_punctuation ();
285 in_fixed_width_font
--;
288 /* Free all of the arguments found. */
289 if (arg1
) free (arg1
);
290 if (arg2
) free (arg2
);
291 if (arg3
) free (arg3
);
292 if (arg4
) free (arg4
);
293 if (arg5
) free (arg5
);
297 remember_node_reference (arg1
, line_number
, followed_reference
);
303 add_html_elt ("<a href=\"");
304 in_fixed_width_font
++;
305 tem
= expansion (arg1
, 0);
306 in_fixed_width_font
--;
307 add_anchor_name (tem
, 1);
310 execute_string ("%s", *arg2
? arg2
: arg3
);
315 execute_string ("%s:", *arg2
? arg2
: arg3
);
316 in_fixed_width_font
++;
317 execute_string (" %s", arg1
);
318 add_xref_punctuation ();
319 in_fixed_width_font
--;
326 add_html_elt ("<a href=\"");
327 in_fixed_width_font
++;
328 tem
= expansion (arg1
, 0);
329 in_fixed_width_font
--;
330 add_anchor_name (tem
, 1);
334 execute_string ("%s", arg2
);
337 char *fref
= get_float_ref (arg1
);
338 execute_string ("%s", fref
? fref
: arg1
);
347 execute_string ("%s:", arg2
);
348 in_fixed_width_font
++;
349 execute_string (" %s", arg1
);
350 add_xref_punctuation ();
351 in_fixed_width_font
--;
355 char *fref
= get_float_ref (arg1
);
357 { /* Reference is being made to a float. */
358 execute_string ("%s:", fref
);
359 in_fixed_width_font
++;
360 execute_string (" %s", arg1
);
361 add_xref_punctuation ();
362 in_fixed_width_font
--;
366 in_fixed_width_font
++;
367 execute_string ("%s::", arg1
);
368 in_fixed_width_font
--;
374 /* Free all of the arguments found. */
375 if (arg1
) free (arg1
);
376 if (arg2
) free (arg2
);
377 if (arg3
) free (arg3
);
378 if (arg4
) free (arg4
);
379 if (arg5
) free (arg5
);
382 { /* Check that the next non-whitespace character is valid to follow
383 an xref (so Info readers can find the node names).
384 `input_text_offset' is pointing at the "}" which ended the xref
385 command. This is not used for @pxref or @ref, since we insert
386 the necessary punctuation above, if needed. */
387 int temp
= next_nonwhitespace_character ();
390 warning (_("End of file reached while looking for `.' or `,'"));
391 else if (temp
!= '.' && temp
!= ',')
392 warning (_("`.' or `,' must follow @%s, not `%c'"), command
, temp
);
405 /* cm_xref isn't called with arg == END, which disables the code near
406 the end of cm_xref that checks for `.' or `,' after the
407 cross-reference. This is because cm_xref generates the required
408 character itself (when needed) if px_ref_flag is set. */
414 /* See the comments in cm_pxref about the checks for punctuation. */
428 char *node
= get_xref_token (1); /* expands all macros in inforef */
429 char *pname
= get_xref_token (0);
430 char *file
= get_xref_token (0);
432 /* (see comments at cm_xref). */
434 line_error (_("First argument to @inforef may not be empty"));
438 xml_insert_element (INFOREF
, START
);
439 xml_insert_element (INFOREFNODENAME
, START
);
440 execute_string ("%s", node
);
441 xml_insert_element (INFOREFNODENAME
, END
);
444 xml_insert_element (INFOREFREFNAME
, START
);
445 execute_string ("%s", pname
);
446 xml_insert_element (INFOREFREFNAME
, END
);
448 xml_insert_element (INFOREFINFONAME
, START
);
449 execute_string ("%s", file
);
450 xml_insert_element (INFOREFINFONAME
, END
);
452 xml_insert_element (INFOREF
, END
);
458 add_word ((char *) _("see "));
459 /* html fixxme: revisit this */
460 add_html_elt ("<a href=");
462 execute_string ("\"../%s/", file
);
464 execute_string ("\"%s.html", file
);
465 tem
= expansion (node
, 0);
466 add_anchor_name (tem
, 1);
468 execute_string ("%s", *pname
? pname
: tem
);
475 execute_string ("*note %s: (%s)%s", pname
, file
, node
);
477 execute_string ("*note (%s)%s::", file
, node
);
486 /* A URL reference. */
492 extern int printing_index
;
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 text_expansion (url
));
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);
579 xml_insert_element_with_attribute (EMAIL
, START
, "url=\"mailto:%s\"", addr
);
581 execute_string ("%s", name
);
582 xml_insert_element (EMAIL
, END
);
586 xml_insert_element (EMAIL
, START
);
587 xml_insert_element (EMAILADDRESS
, START
);
588 execute_string ("%s", addr
);
589 xml_insert_element (EMAILADDRESS
, END
);
592 xml_insert_element (EMAILNAME
, START
);
593 execute_string ("%s", name
);
594 xml_insert_element (EMAILNAME
, END
);
596 xml_insert_element (EMAIL
, END
);
600 add_html_elt ("<a href=");
601 /* don't collapse `--' etc. in the address */
602 in_fixed_width_font
++;
603 execute_string ("\"mailto:%s\"", addr
);
604 in_fixed_width_font
--;
606 execute_string ("%s", *name
? name
: addr
);
611 execute_string ("%s%s", name
, *name
? " " : "");
612 in_fixed_width_font
++;
613 execute_string ("<%s>", addr
);
614 in_fixed_width_font
--;