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