No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / texinfo / makeinfo / xref.c
blob45d1d4db08fbef39f7981faf6543c408e759612c
1 /* $NetBSD$ */
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)
11 any later version.
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. */
22 #include "system.h"
23 #include "cmds.h"
24 #include "float.h"
25 #include "html.h"
26 #include "index.h"
27 #include "macro.h"
28 #include "makeinfo.h"
29 #include "node.h"
30 #include "xml.h"
31 #include "xref.h"
33 /* Flags which control initial output string for xrefs. */
34 int px_ref_flag = 0;
35 int ref_flag = 0;
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. */
40 static void
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 ();
48 if (next_char == -1)
49 /* EOF while looking for punctuation, let's
50 insert a period instead of crying. */
51 add_char ('.');
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. */
56 add_char ('.');
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. */
64 char *
65 get_xref_token (int expand)
67 char *string = 0;
69 if (docbook)
70 xml_in_xref_token = 1;
72 if (expand)
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 */
79 input_text_offset++;
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--;
90 free (string);
93 get_until_in_braces (",", &string);
94 if (curchar () == ',')
95 input_text_offset++;
96 fix_whitespace (string);
98 if (docbook)
99 xml_in_xref_token = 0;
101 return string;
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. */
114 void
115 cm_xref (int arg)
117 if (arg == START)
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);
124 char *tem;
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. */
129 if (!*arg1)
130 line_error (_("First argument to cross-reference may not be empty"));
132 if (docbook)
134 if (!ref_flag)
135 add_word (px_ref_flag || printing_index
136 ? (char *) _("see ") : (char *) _("See "));
138 if (!*arg4 && !*arg5)
140 char *arg1_id = xml_id (arg1);
142 if (*arg2 || *arg3)
144 xml_insert_element_with_attribute (XREFNODENAME, START,
145 "linkend=\"%s\"", arg1_id);
146 free (arg1_id);
147 execute_string ("%s", *arg3 ? arg3 : arg2);
148 xml_insert_element (XREFNODENAME, END);
150 else
152 xml_insert_element_with_attribute (XREF, START,
153 "linkend=\"%s\"", arg1_id);
154 xml_insert_element (XREF, END);
155 free (arg1_id);
158 else if (*arg5)
160 add_word_args (_("See section ``%s'' in "), *arg3 ? arg3 : arg1);
161 xml_insert_element (CITE, START);
162 add_word (arg5);
163 xml_insert_element (CITE, END);
165 else if (*arg4)
167 /* Very sad, we are losing xrefs made to ``info only'' books. */
170 else if (xml)
172 if (!ref_flag)
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);
179 if (*arg2)
181 xml_insert_element (XREFINFONAME, START);
182 execute_string ("%s", arg2);
183 xml_insert_element (XREFINFONAME, END);
185 if (*arg3)
187 xml_insert_element (XREFPRINTEDDESC, START);
188 execute_string ("%s", arg3);
189 xml_insert_element (XREFPRINTEDDESC, END);
191 if (*arg4)
193 xml_insert_element (XREFINFOFILE, START);
194 execute_string ("%s", arg4);
195 xml_insert_element (XREFINFOFILE, END);
197 if (*arg5)
199 xml_insert_element (XREFPRINTEDNAME, START);
200 execute_string ("%s", arg5);
201 xml_insert_element (XREFPRINTEDNAME, END);
203 xml_insert_element (XREF, END);
205 else if (html)
207 if (!ref_flag)
208 add_word_args ("%s", px_ref_flag ? _("see ") : _("See "));
210 else
211 add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
213 if (!xml)
215 if (*arg5 || *arg4)
217 /* arg1 - node name
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 */
222 char *ref_name;
224 if (!*arg2)
226 if (*arg3)
227 ref_name = arg3;
228 else
229 ref_name = arg1;
231 else
232 ref_name = arg2;
234 if (html)
235 { /* More to do eventually, down to Unicode
236 Normalization Form C. See the HTML Xref nodes in
237 the manual. */
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, '/');
244 if (p)
245 file_arg = p + 1;
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 , '.');
250 if (p != NULL)
251 *p = 0;
254 if (! *file_arg)
255 warning (_("Empty file name for HTML cross reference in `%s'"),
256 arg4);
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. */
265 if (splitting)
266 execute_string ("\"../%s/", file_arg);
267 else
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);
274 free (tem);
275 add_word ("\">");
276 execute_string ("%s",ref_name);
277 add_word ("</a>");
279 else
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);
294 return;
296 else
297 remember_node_reference (arg1, line_number, followed_reference);
299 if (*arg3)
301 if (html)
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);
308 free (tem);
309 add_word ("\">");
310 execute_string ("%s", *arg2 ? arg2 : arg3);
311 add_word ("</a>");
313 else
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--;
322 else
324 if (html)
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);
331 free (tem);
332 add_word ("\">");
333 if (*arg2)
334 execute_string ("%s", arg2);
335 else
337 char *fref = get_float_ref (arg1);
338 execute_string ("%s", fref ? fref : arg1);
339 free (fref);
341 add_word ("</a>");
343 else
345 if (*arg2)
347 execute_string ("%s:", arg2);
348 in_fixed_width_font++;
349 execute_string (" %s", arg1);
350 add_xref_punctuation ();
351 in_fixed_width_font--;
353 else
355 char *fref = get_float_ref (arg1);
356 if (fref)
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--;
364 else
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);
381 else
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 ();
389 if (temp == -1)
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);
396 void
397 cm_pxref (int arg)
399 if (arg == START)
401 px_ref_flag++;
402 cm_xref (arg);
403 px_ref_flag--;
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. */
411 void
412 cm_ref (int arg)
414 /* See the comments in cm_pxref about the checks for punctuation. */
415 if (arg == START)
417 ref_flag++;
418 cm_xref (arg);
419 ref_flag--;
423 void
424 cm_inforef (int arg)
426 if (arg == START)
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). */
433 if (!*node)
434 line_error (_("First argument to @inforef may not be empty"));
436 if (xml && !docbook)
438 xml_insert_element (INFOREF, START);
439 xml_insert_element (INFOREFNODENAME, START);
440 execute_string ("%s", node);
441 xml_insert_element (INFOREFNODENAME, END);
442 if (*pname)
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);
454 else if (html)
456 char *tem;
458 add_word ((char *) _("see "));
459 /* html fixxme: revisit this */
460 add_html_elt ("<a href=");
461 if (splitting)
462 execute_string ("\"../%s/", file);
463 else
464 execute_string ("\"%s.html", file);
465 tem = expansion (node, 0);
466 add_anchor_name (tem, 1);
467 add_word ("\">");
468 execute_string ("%s", *pname ? pname : tem);
469 add_word ("</a>");
470 free (tem);
472 else
474 if (*pname)
475 execute_string ("*note %s: (%s)%s", pname, file, node);
476 else
477 execute_string ("*note (%s)%s::", file, node);
480 free (node);
481 free (pname);
482 free (file);
486 /* A URL reference. */
487 void
488 cm_uref (int arg)
490 if (arg == START)
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);
497 if (docbook)
499 xml_insert_element_with_attribute (UREF, START, "url=\"%s\"",
500 text_expansion (url));
501 if (*replacement)
502 execute_string ("%s", replacement);
503 else if (*desc)
504 execute_string ("%s", desc);
505 else
506 execute_string ("%s", url);
507 xml_insert_element (UREF, END);
509 else if (xml)
511 xml_insert_element (UREF, START);
512 xml_insert_element (UREFURL, START);
513 execute_string ("%s", url);
514 xml_insert_element (UREFURL, END);
515 if (*desc)
517 xml_insert_element (UREFDESC, START);
518 execute_string ("%s", desc);
519 xml_insert_element (UREFDESC, END);
521 if (*replacement)
523 xml_insert_element (UREFREPLACEMENT, START);
524 execute_string ("%s", replacement);
525 xml_insert_element (UREFREPLACEMENT, END);
527 xml_insert_element (UREF, END);
529 else if (html)
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--;
536 add_word (">");
537 execute_string ("%s", *replacement ? replacement
538 : (*desc ? desc : url));
539 add_word ("</a>");
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 ? "" : "`",
555 url,
556 printing_index ? "" : "'");
557 in_fixed_width_font--;
559 if (url)
560 free (url);
561 if (desc)
562 free (desc);
563 if (replacement)
564 free (replacement);
568 /* An email reference. */
569 void
570 cm_email (int arg)
572 if (arg == START)
574 char *addr = get_xref_token (1); /* expands all macros in email */
575 char *name = get_xref_token (0);
577 if (xml && docbook)
579 xml_insert_element_with_attribute (EMAIL, START, "url=\"mailto:%s\"", addr);
580 if (*name)
581 execute_string ("%s", name);
582 xml_insert_element (EMAIL, END);
584 else if (xml)
586 xml_insert_element (EMAIL, START);
587 xml_insert_element (EMAILADDRESS, START);
588 execute_string ("%s", addr);
589 xml_insert_element (EMAILADDRESS, END);
590 if (*name)
592 xml_insert_element (EMAILNAME, START);
593 execute_string ("%s", name);
594 xml_insert_element (EMAILNAME, END);
596 xml_insert_element (EMAIL, END);
598 else if (html)
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--;
605 add_word (">");
606 execute_string ("%s", *name ? name : addr);
607 add_word ("</a>");
609 else
611 execute_string ("%s%s", name, *name ? " " : "");
612 in_fixed_width_font++;
613 execute_string ("<%s>", addr);
614 in_fixed_width_font--;
617 if (addr)
618 free (addr);
619 if (name)
620 free (name);