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
--;