xref: /netbsd-src/external/gpl2/texinfo/dist/makeinfo/xref.c (revision 29619d2afe564e54d657b83e5a3ae89584f83720)
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