kernel - TMPFS - Stabilization pass, fix accounting for rmdir
[dragonfly.git] / contrib / texinfo-4 / makeinfo / xref.c
blob314d4a0fb648120f5fdb1f647e2d8d99148b3594
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)
9 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, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 #include "system.h"
21 #include "cmds.h"
22 #include "float.h"
23 #include "html.h"
24 #include "index.h"
25 #include "macro.h"
26 #include "makeinfo.h"
27 #include "node.h"
28 #include "xml.h"
29 #include "xref.h"
31 /* Flags which control initial output string for xrefs. */
32 int px_ref_flag = 0;
33 int ref_flag = 0;
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. */
38 static void
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 ();
46 if (next_char == -1)
47 /* EOF while looking for punctuation, let's
48 insert a period instead of crying. */
49 add_char ('.');
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. */
54 add_char ('.');
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. */
62 char *
63 get_xref_token (int expand)
65 char *string = 0;
67 if (docbook)
68 xml_in_xref_token = 1;
70 if (expand)
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 */
77 input_text_offset++;
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--;
88 free (string);
91 get_until_in_braces (",", &string);
92 if (curchar () == ',')
93 input_text_offset++;
94 fix_whitespace (string);
96 if (docbook)
97 xml_in_xref_token = 0;
99 return string;
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. */
112 void
113 cm_xref (int arg)
115 if (arg == START)
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);
122 char *tem;
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. */
127 if (!*arg1)
128 line_error (_("First argument to cross-reference may not be empty"));
130 if (docbook)
132 if (!ref_flag)
133 add_word (px_ref_flag || printing_index
134 ? (char *) _("see ") : (char *) _("See "));
136 if (!*arg4 && !*arg5)
138 char *arg1_id = xml_id (arg1);
140 if (*arg2 || *arg3)
142 xml_insert_element_with_attribute (XREFNODENAME, START,
143 "linkend=\"%s\"", arg1_id);
144 free (arg1_id);
145 execute_string ("%s", *arg3 ? arg3 : arg2);
146 xml_insert_element (XREFNODENAME, END);
148 else
150 xml_insert_element_with_attribute (XREF, START,
151 "linkend=\"%s\"", arg1_id);
152 xml_insert_element (XREF, END);
153 free (arg1_id);
156 else if (*arg5)
158 add_word_args (_("See section ``%s'' in "), *arg3 ? arg3 : arg1);
159 xml_insert_element (CITE, START);
160 add_word (arg5);
161 xml_insert_element (CITE, END);
163 else if (*arg4)
165 /* Very sad, we are losing xrefs made to ``info only'' books. */
168 else if (xml)
170 if (!ref_flag)
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);
177 if (*arg2)
179 xml_insert_element (XREFINFONAME, START);
180 execute_string ("%s", arg2);
181 xml_insert_element (XREFINFONAME, END);
183 if (*arg3)
185 xml_insert_element (XREFPRINTEDDESC, START);
186 execute_string ("%s", arg3);
187 xml_insert_element (XREFPRINTEDDESC, END);
189 if (*arg4)
191 xml_insert_element (XREFINFOFILE, START);
192 execute_string ("%s", arg4);
193 xml_insert_element (XREFINFOFILE, END);
195 if (*arg5)
197 xml_insert_element (XREFPRINTEDNAME, START);
198 execute_string ("%s", arg5);
199 xml_insert_element (XREFPRINTEDNAME, END);
201 xml_insert_element (XREF, END);
203 else if (html)
205 if (!ref_flag)
206 add_word_args ("%s", px_ref_flag ? _("see ") : _("See "));
208 else
209 add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
211 if (!xml)
213 if (*arg5 || *arg4)
215 /* arg1 - node name
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 */
220 char *ref_name;
222 if (!*arg2)
224 if (*arg3)
225 ref_name = arg3;
226 else
227 ref_name = arg1;
229 else
230 ref_name = arg2;
232 if (html)
233 { /* More to do eventually, down to Unicode
234 Normalization Form C. See the HTML Xref nodes in
235 the manual. */
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, '/');
242 if (p)
243 file_arg = p + 1;
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 , '.');
248 if (p != NULL)
249 *p = 0;
252 if (! *file_arg)
253 warning (_("Empty file name for HTML cross reference in `%s'"),
254 arg4);
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. */
263 if (splitting)
264 execute_string ("\"../%s/", file_arg);
265 else
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);
272 free (tem);
273 add_word ("\">");
274 execute_string ("%s",ref_name);
275 add_word ("</a>");
277 else
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);
292 return;
294 else
295 remember_node_reference (arg1, line_number, followed_reference);
297 if (*arg3)
299 if (html)
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);
306 free (tem);
307 add_word ("\">");
308 execute_string ("%s", *arg2 ? arg2 : arg3);
309 add_word ("</a>");
311 else
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--;
320 else
322 if (html)
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);
329 free (tem);
330 add_word ("\">");
331 if (*arg2)
332 execute_string ("%s", arg2);
333 else
335 char *fref = get_float_ref (arg1);
336 execute_string ("%s", fref ? fref : arg1);
337 free (fref);
339 add_word ("</a>");
341 else
343 if (*arg2)
345 execute_string ("%s:", arg2);
346 in_fixed_width_font++;
347 execute_string (" %s", arg1);
348 add_xref_punctuation ();
349 in_fixed_width_font--;
351 else
353 char *fref = get_float_ref (arg1);
354 if (fref)
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--;
362 else
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);
379 else
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 ();
387 if (temp == -1)
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);
394 void
395 cm_pxref (int arg)
397 if (arg == START)
399 px_ref_flag++;
400 cm_xref (arg);
401 px_ref_flag--;
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. */
409 void
410 cm_ref (int arg)
412 /* See the comments in cm_pxref about the checks for punctuation. */
413 if (arg == START)
415 ref_flag++;
416 cm_xref (arg);
417 ref_flag--;
421 void
422 cm_inforef (int arg)
424 if (arg == START)
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). */
431 if (!*node)
432 line_error (_("First argument to @inforef may not be empty"));
434 if (xml && !docbook)
436 xml_insert_element (INFOREF, START);
437 xml_insert_element (INFOREFNODENAME, START);
438 execute_string ("%s", node);
439 xml_insert_element (INFOREFNODENAME, END);
440 if (*pname)
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);
452 else if (html)
454 char *tem;
456 add_word ((char *) _("see "));
457 /* html fixxme: revisit this */
458 add_html_elt ("<a href=");
459 if (splitting)
460 execute_string ("\"../%s/", file);
461 else
462 execute_string ("\"%s.html", file);
463 tem = expansion (node, 0);
464 add_anchor_name (tem, 1);
465 add_word ("\">");
466 execute_string ("%s", *pname ? pname : tem);
467 add_word ("</a>");
468 free (tem);
470 else
472 if (*pname)
473 execute_string ("*note %s: (%s)%s", pname, file, node);
474 else
475 execute_string ("*note (%s)%s::", file, node);
478 free (node);
479 free (pname);
480 free (file);
484 /* A URL reference. */
485 void
486 cm_uref (int arg)
488 if (arg == START)
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);
495 if (docbook)
497 xml_insert_element_with_attribute (UREF, START, "url=\"%s\"",
498 text_expansion (url));
499 if (*replacement)
500 execute_string ("%s", replacement);
501 else if (*desc)
502 execute_string ("%s", desc);
503 else
504 execute_string ("%s", url);
505 xml_insert_element (UREF, END);
507 else if (xml)
509 xml_insert_element (UREF, START);
510 xml_insert_element (UREFURL, START);
511 execute_string ("%s", url);
512 xml_insert_element (UREFURL, END);
513 if (*desc)
515 xml_insert_element (UREFDESC, START);
516 execute_string ("%s", desc);
517 xml_insert_element (UREFDESC, END);
519 if (*replacement)
521 xml_insert_element (UREFREPLACEMENT, START);
522 execute_string ("%s", replacement);
523 xml_insert_element (UREFREPLACEMENT, END);
525 xml_insert_element (UREF, END);
527 else if (html)
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--;
534 add_word (">");
535 execute_string ("%s", *replacement ? replacement
536 : (*desc ? desc : url));
537 add_word ("</a>");
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 ? "" : "`",
553 url,
554 printing_index ? "" : "'");
555 in_fixed_width_font--;
557 if (url)
558 free (url);
559 if (desc)
560 free (desc);
561 if (replacement)
562 free (replacement);
566 /* An email reference. */
567 void
568 cm_email (int arg)
570 if (arg == START)
572 char *addr = get_xref_token (1); /* expands all macros in email */
573 char *name = get_xref_token (0);
575 if (xml && docbook)
577 xml_insert_element_with_attribute (EMAIL, START, "url=\"mailto:%s\"", addr);
578 if (*name)
579 execute_string ("%s", name);
580 xml_insert_element (EMAIL, END);
582 else if (xml)
584 xml_insert_element (EMAIL, START);
585 xml_insert_element (EMAILADDRESS, START);
586 execute_string ("%s", addr);
587 xml_insert_element (EMAILADDRESS, END);
588 if (*name)
590 xml_insert_element (EMAILNAME, START);
591 execute_string ("%s", name);
592 xml_insert_element (EMAILNAME, END);
594 xml_insert_element (EMAIL, END);
596 else if (html)
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--;
603 add_word (">");
604 execute_string ("%s", *name ? name : addr);
605 add_word ("</a>");
607 else
609 execute_string ("%s%s", name, *name ? " " : "");
610 in_fixed_width_font++;
611 execute_string ("<%s>", addr);
612 in_fixed_width_font--;
615 if (addr)
616 free (addr);
617 if (name)
618 free (name);