1*29619d2aSchristos /* $NetBSD: xref.c,v 1.1.1.1 2016/01/14 00:11:29 christos Exp $ */
2*29619d2aSchristos
3*29619d2aSchristos /* xref.c -- cross references for Texinfo.
4*29619d2aSchristos Id: xref.c,v 1.4 2004/12/21 17:28:35 karl Exp
5*29619d2aSchristos
6*29619d2aSchristos Copyright (C) 2004 Free Software Foundation, Inc.
7*29619d2aSchristos
8*29619d2aSchristos This program is free software; you can redistribute it and/or modify
9*29619d2aSchristos it under the terms of the GNU General Public License as published by
10*29619d2aSchristos the Free Software Foundation; either version 2, or (at your option)
11*29619d2aSchristos any later version.
12*29619d2aSchristos
13*29619d2aSchristos This program is distributed in the hope that it will be useful,
14*29619d2aSchristos but WITHOUT ANY WARRANTY; without even the implied warranty of
15*29619d2aSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16*29619d2aSchristos GNU General Public License for more details.
17*29619d2aSchristos
18*29619d2aSchristos You should have received a copy of the GNU General Public License
19*29619d2aSchristos along with this program; if not, write to the Free Software Foundation,
20*29619d2aSchristos Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21*29619d2aSchristos
22*29619d2aSchristos #include "system.h"
23*29619d2aSchristos #include "cmds.h"
24*29619d2aSchristos #include "float.h"
25*29619d2aSchristos #include "html.h"
26*29619d2aSchristos #include "index.h"
27*29619d2aSchristos #include "macro.h"
28*29619d2aSchristos #include "makeinfo.h"
29*29619d2aSchristos #include "node.h"
30*29619d2aSchristos #include "xml.h"
31*29619d2aSchristos #include "xref.h"
32*29619d2aSchristos
33*29619d2aSchristos /* Flags which control initial output string for xrefs. */
34*29619d2aSchristos int px_ref_flag = 0;
35*29619d2aSchristos int ref_flag = 0;
36*29619d2aSchristos
37*29619d2aSchristos /* Called in the multiple-argument case to make sure we generate a valid
38*29619d2aSchristos Info reference. In the single-argument case, the :: we output
39*29619d2aSchristos suffices for the Info readers to find the end of the reference. */
40*29619d2aSchristos static void
add_xref_punctuation(void)41*29619d2aSchristos add_xref_punctuation (void)
42*29619d2aSchristos {
43*29619d2aSchristos if (px_ref_flag || ref_flag) /* user inserts punct after @xref */
44*29619d2aSchristos {
45*29619d2aSchristos /* Check if there's already punctuation. */
46*29619d2aSchristos int next_char = next_nonwhitespace_character ();
47*29619d2aSchristos
48*29619d2aSchristos if (next_char == -1)
49*29619d2aSchristos /* EOF while looking for punctuation, let's
50*29619d2aSchristos insert a period instead of crying. */
51*29619d2aSchristos add_char ('.');
52*29619d2aSchristos else if (next_char != ',' && next_char != '.')
53*29619d2aSchristos /* period and comma terminate xrefs, and nothing else. Instead
54*29619d2aSchristos of generating an Info reference that can't be followed,
55*29619d2aSchristos though, just insert a period. Not pretty, but functional. */
56*29619d2aSchristos add_char ('.');
57*29619d2aSchristos }
58*29619d2aSchristos }
59*29619d2aSchristos
60*29619d2aSchristos /* Return next comma-delimited argument, but do not cross a close-brace
61*29619d2aSchristos boundary. Clean up whitespace, too. If EXPAND is nonzero, replace
62*29619d2aSchristos the entire brace-delimited argument list with its expansion before
63*29619d2aSchristos looking for the next comma. */
64*29619d2aSchristos char *
get_xref_token(int expand)65*29619d2aSchristos get_xref_token (int expand)
66*29619d2aSchristos {
67*29619d2aSchristos char *string = 0;
68*29619d2aSchristos
69*29619d2aSchristos if (docbook)
70*29619d2aSchristos xml_in_xref_token = 1;
71*29619d2aSchristos
72*29619d2aSchristos if (expand)
73*29619d2aSchristos {
74*29619d2aSchristos int old_offset = input_text_offset;
75*29619d2aSchristos int old_lineno = line_number;
76*29619d2aSchristos
77*29619d2aSchristos get_until_in_braces ("}", &string);
78*29619d2aSchristos if (curchar () == '}') /* as opposed to end of text */
79*29619d2aSchristos input_text_offset++;
80*29619d2aSchristos if (input_text_offset > old_offset)
81*29619d2aSchristos {
82*29619d2aSchristos int limit = input_text_offset;
83*29619d2aSchristos
84*29619d2aSchristos input_text_offset = old_offset;
85*29619d2aSchristos line_number = old_lineno;
86*29619d2aSchristos only_macro_expansion++;
87*29619d2aSchristos replace_with_expansion (input_text_offset, &limit);
88*29619d2aSchristos only_macro_expansion--;
89*29619d2aSchristos }
90*29619d2aSchristos free (string);
91*29619d2aSchristos }
92*29619d2aSchristos
93*29619d2aSchristos get_until_in_braces (",", &string);
94*29619d2aSchristos if (curchar () == ',')
95*29619d2aSchristos input_text_offset++;
96*29619d2aSchristos fix_whitespace (string);
97*29619d2aSchristos
98*29619d2aSchristos if (docbook)
99*29619d2aSchristos xml_in_xref_token = 0;
100*29619d2aSchristos
101*29619d2aSchristos return string;
102*29619d2aSchristos }
103*29619d2aSchristos
104*29619d2aSchristos
105*29619d2aSchristos /* NOTE: If you wonder why the HTML output is produced with such a
106*29619d2aSchristos peculiar mix of calls to add_word and execute_string, here's the
107*29619d2aSchristos reason. get_xref_token (1) expands all macros in a reference, but
108*29619d2aSchristos any other commands, like @value, @@, etc., are left intact. To
109*29619d2aSchristos expand them, we need to run the arguments through execute_string.
110*29619d2aSchristos However, characters like <, &, > and others cannot be let into
111*29619d2aSchristos execute_string, because they will be escaped. See the mess? */
112*29619d2aSchristos
113*29619d2aSchristos /* Make a cross reference. */
114*29619d2aSchristos void
cm_xref(int arg)115*29619d2aSchristos cm_xref (int arg)
116*29619d2aSchristos {
117*29619d2aSchristos if (arg == START)
118*29619d2aSchristos {
119*29619d2aSchristos char *arg1 = get_xref_token (1); /* expands all macros in xref */
120*29619d2aSchristos char *arg2 = get_xref_token (0);
121*29619d2aSchristos char *arg3 = get_xref_token (0);
122*29619d2aSchristos char *arg4 = get_xref_token (0);
123*29619d2aSchristos char *arg5 = get_xref_token (0);
124*29619d2aSchristos char *tem;
125*29619d2aSchristos
126*29619d2aSchristos /* "@xref{,Foo,, Bar, Baz} is not valid usage of @xref. The
127*29619d2aSchristos first argument must never be blank." --rms.
128*29619d2aSchristos We hereby comply by disallowing such constructs. */
129*29619d2aSchristos if (!*arg1)
130*29619d2aSchristos line_error (_("First argument to cross-reference may not be empty"));
131*29619d2aSchristos
132*29619d2aSchristos if (docbook)
133*29619d2aSchristos {
134*29619d2aSchristos if (!ref_flag)
135*29619d2aSchristos add_word (px_ref_flag || printing_index
136*29619d2aSchristos ? (char *) _("see ") : (char *) _("See "));
137*29619d2aSchristos
138*29619d2aSchristos if (!*arg4 && !*arg5)
139*29619d2aSchristos {
140*29619d2aSchristos char *arg1_id = xml_id (arg1);
141*29619d2aSchristos
142*29619d2aSchristos if (*arg2 || *arg3)
143*29619d2aSchristos {
144*29619d2aSchristos xml_insert_element_with_attribute (XREFNODENAME, START,
145*29619d2aSchristos "linkend=\"%s\"", arg1_id);
146*29619d2aSchristos free (arg1_id);
147*29619d2aSchristos execute_string ("%s", *arg3 ? arg3 : arg2);
148*29619d2aSchristos xml_insert_element (XREFNODENAME, END);
149*29619d2aSchristos }
150*29619d2aSchristos else
151*29619d2aSchristos {
152*29619d2aSchristos xml_insert_element_with_attribute (XREF, START,
153*29619d2aSchristos "linkend=\"%s\"", arg1_id);
154*29619d2aSchristos xml_insert_element (XREF, END);
155*29619d2aSchristos free (arg1_id);
156*29619d2aSchristos }
157*29619d2aSchristos }
158*29619d2aSchristos else if (*arg5)
159*29619d2aSchristos {
160*29619d2aSchristos add_word_args (_("See section ``%s'' in "), *arg3 ? arg3 : arg1);
161*29619d2aSchristos xml_insert_element (CITE, START);
162*29619d2aSchristos add_word (arg5);
163*29619d2aSchristos xml_insert_element (CITE, END);
164*29619d2aSchristos }
165*29619d2aSchristos else if (*arg4)
166*29619d2aSchristos {
167*29619d2aSchristos /* Very sad, we are losing xrefs made to ``info only'' books. */
168*29619d2aSchristos }
169*29619d2aSchristos }
170*29619d2aSchristos else if (xml)
171*29619d2aSchristos {
172*29619d2aSchristos if (!ref_flag)
173*29619d2aSchristos add_word_args ("%s", px_ref_flag ? _("see ") : _("See "));
174*29619d2aSchristos
175*29619d2aSchristos xml_insert_element (XREF, START);
176*29619d2aSchristos xml_insert_element (XREFNODENAME, START);
177*29619d2aSchristos execute_string ("%s", arg1);
178*29619d2aSchristos xml_insert_element (XREFNODENAME, END);
179*29619d2aSchristos if (*arg2)
180*29619d2aSchristos {
181*29619d2aSchristos xml_insert_element (XREFINFONAME, START);
182*29619d2aSchristos execute_string ("%s", arg2);
183*29619d2aSchristos xml_insert_element (XREFINFONAME, END);
184*29619d2aSchristos }
185*29619d2aSchristos if (*arg3)
186*29619d2aSchristos {
187*29619d2aSchristos xml_insert_element (XREFPRINTEDDESC, START);
188*29619d2aSchristos execute_string ("%s", arg3);
189*29619d2aSchristos xml_insert_element (XREFPRINTEDDESC, END);
190*29619d2aSchristos }
191*29619d2aSchristos if (*arg4)
192*29619d2aSchristos {
193*29619d2aSchristos xml_insert_element (XREFINFOFILE, START);
194*29619d2aSchristos execute_string ("%s", arg4);
195*29619d2aSchristos xml_insert_element (XREFINFOFILE, END);
196*29619d2aSchristos }
197*29619d2aSchristos if (*arg5)
198*29619d2aSchristos {
199*29619d2aSchristos xml_insert_element (XREFPRINTEDNAME, START);
200*29619d2aSchristos execute_string ("%s", arg5);
201*29619d2aSchristos xml_insert_element (XREFPRINTEDNAME, END);
202*29619d2aSchristos }
203*29619d2aSchristos xml_insert_element (XREF, END);
204*29619d2aSchristos }
205*29619d2aSchristos else if (html)
206*29619d2aSchristos {
207*29619d2aSchristos if (!ref_flag)
208*29619d2aSchristos add_word_args ("%s", px_ref_flag ? _("see ") : _("See "));
209*29619d2aSchristos }
210*29619d2aSchristos else
211*29619d2aSchristos add_word_args ("%s", px_ref_flag ? "*note " : "*Note ");
212*29619d2aSchristos
213*29619d2aSchristos if (!xml)
214*29619d2aSchristos {
215*29619d2aSchristos if (*arg5 || *arg4)
216*29619d2aSchristos {
217*29619d2aSchristos /* arg1 - node name
218*29619d2aSchristos arg2 - reference name
219*29619d2aSchristos arg3 - title or topic (and reference name if arg2 is NULL)
220*29619d2aSchristos arg4 - info file name
221*29619d2aSchristos arg5 - printed manual title */
222*29619d2aSchristos char *ref_name;
223*29619d2aSchristos
224*29619d2aSchristos if (!*arg2)
225*29619d2aSchristos {
226*29619d2aSchristos if (*arg3)
227*29619d2aSchristos ref_name = arg3;
228*29619d2aSchristos else
229*29619d2aSchristos ref_name = arg1;
230*29619d2aSchristos }
231*29619d2aSchristos else
232*29619d2aSchristos ref_name = arg2;
233*29619d2aSchristos
234*29619d2aSchristos if (html)
235*29619d2aSchristos { /* More to do eventually, down to Unicode
236*29619d2aSchristos Normalization Form C. See the HTML Xref nodes in
237*29619d2aSchristos the manual. */
238*29619d2aSchristos char *file_arg = arg4;
239*29619d2aSchristos add_html_elt ("<a href=");
240*29619d2aSchristos
241*29619d2aSchristos {
242*29619d2aSchristos /* If there's a directory part, ignore it. */
243*29619d2aSchristos char *p = strrchr (file_arg, '/');
244*29619d2aSchristos if (p)
245*29619d2aSchristos file_arg = p + 1;
246*29619d2aSchristos
247*29619d2aSchristos /* If there's a dot, make it a NULL terminator, so the
248*29619d2aSchristos extension does not get into the way. */
249*29619d2aSchristos p = strrchr (file_arg , '.');
250*29619d2aSchristos if (p != NULL)
251*29619d2aSchristos *p = 0;
252*29619d2aSchristos }
253*29619d2aSchristos
254*29619d2aSchristos if (! *file_arg)
255*29619d2aSchristos warning (_("Empty file name for HTML cross reference in `%s'"),
256*29619d2aSchristos arg4);
257*29619d2aSchristos
258*29619d2aSchristos /* Note that if we are splitting, and the referenced
259*29619d2aSchristos tag is an anchor rather than a node, we will
260*29619d2aSchristos produce a reference to a file whose name is
261*29619d2aSchristos derived from the anchor name. However, only
262*29619d2aSchristos nodes create files, so we are referencing a
263*29619d2aSchristos non-existent file. cm_anchor, which see, deals
264*29619d2aSchristos with that problem. */
265*29619d2aSchristos if (splitting)
266*29619d2aSchristos execute_string ("\"../%s/", file_arg);
267*29619d2aSchristos else
268*29619d2aSchristos execute_string ("\"%s.html", file_arg);
269*29619d2aSchristos /* Do not collapse -- to -, etc., in references. */
270*29619d2aSchristos in_fixed_width_font++;
271*29619d2aSchristos tem = expansion (arg1, 0); /* expand @-commands in node */
272*29619d2aSchristos in_fixed_width_font--;
273*29619d2aSchristos add_anchor_name (tem, 1);
274*29619d2aSchristos free (tem);
275*29619d2aSchristos add_word ("\">");
276*29619d2aSchristos execute_string ("%s",ref_name);
277*29619d2aSchristos add_word ("</a>");
278*29619d2aSchristos }
279*29619d2aSchristos else
280*29619d2aSchristos {
281*29619d2aSchristos execute_string ("%s:", ref_name);
282*29619d2aSchristos in_fixed_width_font++;
283*29619d2aSchristos execute_string (" (%s)%s", arg4, arg1);
284*29619d2aSchristos add_xref_punctuation ();
285*29619d2aSchristos in_fixed_width_font--;
286*29619d2aSchristos }
287*29619d2aSchristos
288*29619d2aSchristos /* Free all of the arguments found. */
289*29619d2aSchristos if (arg1) free (arg1);
290*29619d2aSchristos if (arg2) free (arg2);
291*29619d2aSchristos if (arg3) free (arg3);
292*29619d2aSchristos if (arg4) free (arg4);
293*29619d2aSchristos if (arg5) free (arg5);
294*29619d2aSchristos return;
295*29619d2aSchristos }
296*29619d2aSchristos else
297*29619d2aSchristos remember_node_reference (arg1, line_number, followed_reference);
298*29619d2aSchristos
299*29619d2aSchristos if (*arg3)
300*29619d2aSchristos {
301*29619d2aSchristos if (html)
302*29619d2aSchristos {
303*29619d2aSchristos add_html_elt ("<a href=\"");
304*29619d2aSchristos in_fixed_width_font++;
305*29619d2aSchristos tem = expansion (arg1, 0);
306*29619d2aSchristos in_fixed_width_font--;
307*29619d2aSchristos add_anchor_name (tem, 1);
308*29619d2aSchristos free (tem);
309*29619d2aSchristos add_word ("\">");
310*29619d2aSchristos execute_string ("%s", *arg2 ? arg2 : arg3);
311*29619d2aSchristos add_word ("</a>");
312*29619d2aSchristos }
313*29619d2aSchristos else
314*29619d2aSchristos {
315*29619d2aSchristos execute_string ("%s:", *arg2 ? arg2 : arg3);
316*29619d2aSchristos in_fixed_width_font++;
317*29619d2aSchristos execute_string (" %s", arg1);
318*29619d2aSchristos add_xref_punctuation ();
319*29619d2aSchristos in_fixed_width_font--;
320*29619d2aSchristos }
321*29619d2aSchristos }
322*29619d2aSchristos else
323*29619d2aSchristos {
324*29619d2aSchristos if (html)
325*29619d2aSchristos {
326*29619d2aSchristos add_html_elt ("<a href=\"");
327*29619d2aSchristos in_fixed_width_font++;
328*29619d2aSchristos tem = expansion (arg1, 0);
329*29619d2aSchristos in_fixed_width_font--;
330*29619d2aSchristos add_anchor_name (tem, 1);
331*29619d2aSchristos free (tem);
332*29619d2aSchristos add_word ("\">");
333*29619d2aSchristos if (*arg2)
334*29619d2aSchristos execute_string ("%s", arg2);
335*29619d2aSchristos else
336*29619d2aSchristos {
337*29619d2aSchristos char *fref = get_float_ref (arg1);
338*29619d2aSchristos execute_string ("%s", fref ? fref : arg1);
339*29619d2aSchristos free (fref);
340*29619d2aSchristos }
341*29619d2aSchristos add_word ("</a>");
342*29619d2aSchristos }
343*29619d2aSchristos else
344*29619d2aSchristos {
345*29619d2aSchristos if (*arg2)
346*29619d2aSchristos {
347*29619d2aSchristos execute_string ("%s:", arg2);
348*29619d2aSchristos in_fixed_width_font++;
349*29619d2aSchristos execute_string (" %s", arg1);
350*29619d2aSchristos add_xref_punctuation ();
351*29619d2aSchristos in_fixed_width_font--;
352*29619d2aSchristos }
353*29619d2aSchristos else
354*29619d2aSchristos {
355*29619d2aSchristos char *fref = get_float_ref (arg1);
356*29619d2aSchristos if (fref)
357*29619d2aSchristos { /* Reference is being made to a float. */
358*29619d2aSchristos execute_string ("%s:", fref);
359*29619d2aSchristos in_fixed_width_font++;
360*29619d2aSchristos execute_string (" %s", arg1);
361*29619d2aSchristos add_xref_punctuation ();
362*29619d2aSchristos in_fixed_width_font--;
363*29619d2aSchristos }
364*29619d2aSchristos else
365*29619d2aSchristos {
366*29619d2aSchristos in_fixed_width_font++;
367*29619d2aSchristos execute_string ("%s::", arg1);
368*29619d2aSchristos in_fixed_width_font--;
369*29619d2aSchristos }
370*29619d2aSchristos }
371*29619d2aSchristos }
372*29619d2aSchristos }
373*29619d2aSchristos }
374*29619d2aSchristos /* Free all of the arguments found. */
375*29619d2aSchristos if (arg1) free (arg1);
376*29619d2aSchristos if (arg2) free (arg2);
377*29619d2aSchristos if (arg3) free (arg3);
378*29619d2aSchristos if (arg4) free (arg4);
379*29619d2aSchristos if (arg5) free (arg5);
380*29619d2aSchristos }
381*29619d2aSchristos else
382*29619d2aSchristos { /* Check that the next non-whitespace character is valid to follow
383*29619d2aSchristos an xref (so Info readers can find the node names).
384*29619d2aSchristos `input_text_offset' is pointing at the "}" which ended the xref
385*29619d2aSchristos command. This is not used for @pxref or @ref, since we insert
386*29619d2aSchristos the necessary punctuation above, if needed. */
387*29619d2aSchristos int temp = next_nonwhitespace_character ();
388*29619d2aSchristos
389*29619d2aSchristos if (temp == -1)
390*29619d2aSchristos warning (_("End of file reached while looking for `.' or `,'"));
391*29619d2aSchristos else if (temp != '.' && temp != ',')
392*29619d2aSchristos warning (_("`.' or `,' must follow @%s, not `%c'"), command, temp);
393*29619d2aSchristos }
394*29619d2aSchristos }
395*29619d2aSchristos
396*29619d2aSchristos void
cm_pxref(int arg)397*29619d2aSchristos cm_pxref (int arg)
398*29619d2aSchristos {
399*29619d2aSchristos if (arg == START)
400*29619d2aSchristos {
401*29619d2aSchristos px_ref_flag++;
402*29619d2aSchristos cm_xref (arg);
403*29619d2aSchristos px_ref_flag--;
404*29619d2aSchristos }
405*29619d2aSchristos /* cm_xref isn't called with arg == END, which disables the code near
406*29619d2aSchristos the end of cm_xref that checks for `.' or `,' after the
407*29619d2aSchristos cross-reference. This is because cm_xref generates the required
408*29619d2aSchristos character itself (when needed) if px_ref_flag is set. */
409*29619d2aSchristos }
410*29619d2aSchristos
411*29619d2aSchristos void
cm_ref(int arg)412*29619d2aSchristos cm_ref (int arg)
413*29619d2aSchristos {
414*29619d2aSchristos /* See the comments in cm_pxref about the checks for punctuation. */
415*29619d2aSchristos if (arg == START)
416*29619d2aSchristos {
417*29619d2aSchristos ref_flag++;
418*29619d2aSchristos cm_xref (arg);
419*29619d2aSchristos ref_flag--;
420*29619d2aSchristos }
421*29619d2aSchristos }
422*29619d2aSchristos
423*29619d2aSchristos void
cm_inforef(int arg)424*29619d2aSchristos cm_inforef (int arg)
425*29619d2aSchristos {
426*29619d2aSchristos if (arg == START)
427*29619d2aSchristos {
428*29619d2aSchristos char *node = get_xref_token (1); /* expands all macros in inforef */
429*29619d2aSchristos char *pname = get_xref_token (0);
430*29619d2aSchristos char *file = get_xref_token (0);
431*29619d2aSchristos
432*29619d2aSchristos /* (see comments at cm_xref). */
433*29619d2aSchristos if (!*node)
434*29619d2aSchristos line_error (_("First argument to @inforef may not be empty"));
435*29619d2aSchristos
436*29619d2aSchristos if (xml && !docbook)
437*29619d2aSchristos {
438*29619d2aSchristos xml_insert_element (INFOREF, START);
439*29619d2aSchristos xml_insert_element (INFOREFNODENAME, START);
440*29619d2aSchristos execute_string ("%s", node);
441*29619d2aSchristos xml_insert_element (INFOREFNODENAME, END);
442*29619d2aSchristos if (*pname)
443*29619d2aSchristos {
444*29619d2aSchristos xml_insert_element (INFOREFREFNAME, START);
445*29619d2aSchristos execute_string ("%s", pname);
446*29619d2aSchristos xml_insert_element (INFOREFREFNAME, END);
447*29619d2aSchristos }
448*29619d2aSchristos xml_insert_element (INFOREFINFONAME, START);
449*29619d2aSchristos execute_string ("%s", file);
450*29619d2aSchristos xml_insert_element (INFOREFINFONAME, END);
451*29619d2aSchristos
452*29619d2aSchristos xml_insert_element (INFOREF, END);
453*29619d2aSchristos }
454*29619d2aSchristos else if (html)
455*29619d2aSchristos {
456*29619d2aSchristos char *tem;
457*29619d2aSchristos
458*29619d2aSchristos add_word ((char *) _("see "));
459*29619d2aSchristos /* html fixxme: revisit this */
460*29619d2aSchristos add_html_elt ("<a href=");
461*29619d2aSchristos if (splitting)
462*29619d2aSchristos execute_string ("\"../%s/", file);
463*29619d2aSchristos else
464*29619d2aSchristos execute_string ("\"%s.html", file);
465*29619d2aSchristos tem = expansion (node, 0);
466*29619d2aSchristos add_anchor_name (tem, 1);
467*29619d2aSchristos add_word ("\">");
468*29619d2aSchristos execute_string ("%s", *pname ? pname : tem);
469*29619d2aSchristos add_word ("</a>");
470*29619d2aSchristos free (tem);
471*29619d2aSchristos }
472*29619d2aSchristos else
473*29619d2aSchristos {
474*29619d2aSchristos if (*pname)
475*29619d2aSchristos execute_string ("*note %s: (%s)%s", pname, file, node);
476*29619d2aSchristos else
477*29619d2aSchristos execute_string ("*note (%s)%s::", file, node);
478*29619d2aSchristos }
479*29619d2aSchristos
480*29619d2aSchristos free (node);
481*29619d2aSchristos free (pname);
482*29619d2aSchristos free (file);
483*29619d2aSchristos }
484*29619d2aSchristos }
485*29619d2aSchristos
486*29619d2aSchristos /* A URL reference. */
487*29619d2aSchristos void
cm_uref(int arg)488*29619d2aSchristos cm_uref (int arg)
489*29619d2aSchristos {
490*29619d2aSchristos if (arg == START)
491*29619d2aSchristos {
492*29619d2aSchristos extern int printing_index;
493*29619d2aSchristos char *url = get_xref_token (1); /* expands all macros in uref */
494*29619d2aSchristos char *desc = get_xref_token (0);
495*29619d2aSchristos char *replacement = get_xref_token (0);
496*29619d2aSchristos
497*29619d2aSchristos if (docbook)
498*29619d2aSchristos {
499*29619d2aSchristos xml_insert_element_with_attribute (UREF, START, "url=\"%s\"",
500*29619d2aSchristos text_expansion (url));
501*29619d2aSchristos if (*replacement)
502*29619d2aSchristos execute_string ("%s", replacement);
503*29619d2aSchristos else if (*desc)
504*29619d2aSchristos execute_string ("%s", desc);
505*29619d2aSchristos else
506*29619d2aSchristos execute_string ("%s", url);
507*29619d2aSchristos xml_insert_element (UREF, END);
508*29619d2aSchristos }
509*29619d2aSchristos else if (xml)
510*29619d2aSchristos {
511*29619d2aSchristos xml_insert_element (UREF, START);
512*29619d2aSchristos xml_insert_element (UREFURL, START);
513*29619d2aSchristos execute_string ("%s", url);
514*29619d2aSchristos xml_insert_element (UREFURL, END);
515*29619d2aSchristos if (*desc)
516*29619d2aSchristos {
517*29619d2aSchristos xml_insert_element (UREFDESC, START);
518*29619d2aSchristos execute_string ("%s", desc);
519*29619d2aSchristos xml_insert_element (UREFDESC, END);
520*29619d2aSchristos }
521*29619d2aSchristos if (*replacement)
522*29619d2aSchristos {
523*29619d2aSchristos xml_insert_element (UREFREPLACEMENT, START);
524*29619d2aSchristos execute_string ("%s", replacement);
525*29619d2aSchristos xml_insert_element (UREFREPLACEMENT, END);
526*29619d2aSchristos }
527*29619d2aSchristos xml_insert_element (UREF, END);
528*29619d2aSchristos }
529*29619d2aSchristos else if (html)
530*29619d2aSchristos { /* never need to show the url */
531*29619d2aSchristos add_html_elt ("<a href=");
532*29619d2aSchristos /* don't collapse `--' etc. in the url */
533*29619d2aSchristos in_fixed_width_font++;
534*29619d2aSchristos execute_string ("\"%s\"", url);
535*29619d2aSchristos in_fixed_width_font--;
536*29619d2aSchristos add_word (">");
537*29619d2aSchristos execute_string ("%s", *replacement ? replacement
538*29619d2aSchristos : (*desc ? desc : url));
539*29619d2aSchristos add_word ("</a>");
540*29619d2aSchristos }
541*29619d2aSchristos else if (*replacement) /* do not show the url */
542*29619d2aSchristos execute_string ("%s", replacement);
543*29619d2aSchristos else if (*desc) /* show both text and url */
544*29619d2aSchristos {
545*29619d2aSchristos execute_string ("%s ", desc);
546*29619d2aSchristos in_fixed_width_font++;
547*29619d2aSchristos execute_string ("(%s)", url);
548*29619d2aSchristos in_fixed_width_font--;
549*29619d2aSchristos }
550*29619d2aSchristos else /* no text at all, so have the url to show */
551*29619d2aSchristos {
552*29619d2aSchristos in_fixed_width_font++;
553*29619d2aSchristos execute_string ("%s%s%s",
554*29619d2aSchristos printing_index ? "" : "`",
555*29619d2aSchristos url,
556*29619d2aSchristos printing_index ? "" : "'");
557*29619d2aSchristos in_fixed_width_font--;
558*29619d2aSchristos }
559*29619d2aSchristos if (url)
560*29619d2aSchristos free (url);
561*29619d2aSchristos if (desc)
562*29619d2aSchristos free (desc);
563*29619d2aSchristos if (replacement)
564*29619d2aSchristos free (replacement);
565*29619d2aSchristos }
566*29619d2aSchristos }
567*29619d2aSchristos
568*29619d2aSchristos /* An email reference. */
569*29619d2aSchristos void
cm_email(int arg)570*29619d2aSchristos cm_email (int arg)
571*29619d2aSchristos {
572*29619d2aSchristos if (arg == START)
573*29619d2aSchristos {
574*29619d2aSchristos char *addr = get_xref_token (1); /* expands all macros in email */
575*29619d2aSchristos char *name = get_xref_token (0);
576*29619d2aSchristos
577*29619d2aSchristos if (xml && docbook)
578*29619d2aSchristos {
579*29619d2aSchristos xml_insert_element_with_attribute (EMAIL, START, "url=\"mailto:%s\"", addr);
580*29619d2aSchristos if (*name)
581*29619d2aSchristos execute_string ("%s", name);
582*29619d2aSchristos xml_insert_element (EMAIL, END);
583*29619d2aSchristos }
584*29619d2aSchristos else if (xml)
585*29619d2aSchristos {
586*29619d2aSchristos xml_insert_element (EMAIL, START);
587*29619d2aSchristos xml_insert_element (EMAILADDRESS, START);
588*29619d2aSchristos execute_string ("%s", addr);
589*29619d2aSchristos xml_insert_element (EMAILADDRESS, END);
590*29619d2aSchristos if (*name)
591*29619d2aSchristos {
592*29619d2aSchristos xml_insert_element (EMAILNAME, START);
593*29619d2aSchristos execute_string ("%s", name);
594*29619d2aSchristos xml_insert_element (EMAILNAME, END);
595*29619d2aSchristos }
596*29619d2aSchristos xml_insert_element (EMAIL, END);
597*29619d2aSchristos }
598*29619d2aSchristos else if (html)
599*29619d2aSchristos {
600*29619d2aSchristos add_html_elt ("<a href=");
601*29619d2aSchristos /* don't collapse `--' etc. in the address */
602*29619d2aSchristos in_fixed_width_font++;
603*29619d2aSchristos execute_string ("\"mailto:%s\"", addr);
604*29619d2aSchristos in_fixed_width_font--;
605*29619d2aSchristos add_word (">");
606*29619d2aSchristos execute_string ("%s", *name ? name : addr);
607*29619d2aSchristos add_word ("</a>");
608*29619d2aSchristos }
609*29619d2aSchristos else
610*29619d2aSchristos {
611*29619d2aSchristos execute_string ("%s%s", name, *name ? " " : "");
612*29619d2aSchristos in_fixed_width_font++;
613*29619d2aSchristos execute_string ("<%s>", addr);
614*29619d2aSchristos in_fixed_width_font--;
615*29619d2aSchristos }
616*29619d2aSchristos
617*29619d2aSchristos if (addr)
618*29619d2aSchristos free (addr);
619*29619d2aSchristos if (name)
620*29619d2aSchristos free (name);
621*29619d2aSchristos }
622*29619d2aSchristos }
623