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