/* An email reference. */ void cm_email (int arg) { if (arg == START) { char *addr = get_xref_token (1); /* expands all macros in email */ char *name = get_xref_token (0); if (xml && docbook) { xml_insert_element_with_attribute (EMAIL, START, "url=\"mailto:%s\"", addr); if (*name) execute_string ("%s", name); xml_insert_element (EMAIL, END); } else if (xml) { xml_insert_element (EMAIL, START); xml_insert_element (EMAILADDRESS, START); execute_string ("%s", addr); xml_insert_element (EMAILADDRESS, END); if (*name) { xml_insert_element (EMAILNAME, START); execute_string ("%s", name); xml_insert_element (EMAILNAME, END); } xml_insert_element (EMAIL, END); } else if (html) { add_html_elt ("<a href="); /* don't collapse `--' etc. in the address */ in_fixed_width_font++; execute_string ("\"mailto:%s\"", addr); in_fixed_width_font--; add_word (">"); execute_string ("%s", *name ? name : addr); add_word ("</a>"); } else { execute_string ("%s%s", name, *name ? " " : ""); in_fixed_width_font++; execute_string ("<%s>", addr); in_fixed_width_font--; } if (addr) free (addr); if (name) free (name); } }
/* Handle a "footnote". footnote *{this is a footnote} where "*" is the (optional) marker character for this note. */ void cm_footnote (void) { char *marker; char *note; get_until ("{", &marker); canon_white (marker); if (macro_expansion_output_stream && !executing_string) append_to_expansion_output (input_text_offset + 1); /* include the { */ /* Read the argument in braces. */ if (curchar () != '{') { line_error (_("`%c%s' needs an argument `{...}', not just `%s'"), COMMAND_PREFIX, command, marker); free (marker); return; } else { int len; int braces = 1; int loc = ++input_text_offset; while (braces) { if (loc == input_text_length) { line_error (_("No closing brace for footnote `%s'"), marker); return; } if (input_text[loc] == '{') braces++; else if (input_text[loc] == '}') braces--; else if (input_text[loc] == '\n') line_number++; loc++; } len = (loc - input_text_offset) - 1; note = xmalloc (len + 1); memcpy (note, &input_text[input_text_offset], len); note[len] = 0; input_text_offset = loc; } /* Must write the macro-expanded argument to the macro expansion output stream. This is like the case in index_add_arg. */ if (macro_expansion_output_stream && !executing_string) { /* Calling me_execute_string on a lone } provokes an error, since as far as the reader knows there is no matching {. We wrote the { above in the call to append_to_expansion_output. */ me_execute_string_keep_state (note, "}"); } if (!current_node || !*current_node) { line_error (_("Footnote defined without parent node")); free (marker); free (note); return; } /* output_pending_notes is non-reentrant (it uses a global data structure pending_notes, which it frees before it returns), and TeX doesn't grok footnotes inside footnotes anyway. Disallow that. */ if (already_outputting_pending_notes) { line_error (_("Footnotes inside footnotes are not allowed")); free (marker); free (note); return; } if (!*marker) { free (marker); if (number_footnotes) { marker = xmalloc (10); sprintf (marker, "%d", current_footnote_number); } else marker = xstrdup ("*"); } if (xml) xml_insert_footnote (note); else { remember_note (marker, note); /* fixme: html: footnote processing needs work; we currently ignore the style requested; we could clash with a node name of the form `fn-<n>', though that's unlikely. */ if (html) { /* Hyperlink also serves as an anchor (mnemonic: fnd is footnote definition.) */ add_html_elt ("<a rel=\"footnote\" href="); add_word_args ("\"#fn-%d\" name=\"fnd-%d\"><sup>%s</sup></a>", current_footnote_number, current_footnote_number, marker); } else /* Your method should at least insert MARKER. */ switch (footnote_style) { case separate_node: add_word_args ("(%s)", marker); execute_string (" (*note %s-Footnote-%d::)", current_node, current_footnote_number); if (first_footnote_this_node) { char *temp_string, *expanded_ref; temp_string = xmalloc (strlen (current_node) + strlen ("-Footnotes") + 1); strcpy (temp_string, current_node); strcat (temp_string, "-Footnotes"); expanded_ref = expansion (temp_string, 0); remember_node_reference (expanded_ref, line_number, followed_reference); free (temp_string); free (expanded_ref); first_footnote_this_node = 0; } break; case end_node: add_word_args ("(%s)", marker); break; default: break; } current_footnote_number++; } free (marker); free (note); }
void cm_inforef (int arg) { if (arg == START) { char *node = get_xref_token (1); /* expands all macros in inforef */ char *pname = get_xref_token (0); char *file = get_xref_token (0); /* (see comments at cm_xref). */ if (!*node) line_error (_("First argument to @inforef may not be empty")); if (xml && !docbook) { xml_insert_element (INFOREF, START); xml_insert_element (INFOREFNODENAME, START); execute_string ("%s", node); xml_insert_element (INFOREFNODENAME, END); if (*pname) { xml_insert_element (INFOREFREFNAME, START); execute_string ("%s", pname); xml_insert_element (INFOREFREFNAME, END); } xml_insert_element (INFOREFINFONAME, START); execute_string ("%s", file); xml_insert_element (INFOREFINFONAME, END); xml_insert_element (INFOREF, END); } else if (html) { char *tem; add_word ((char *) _("see ")); /* html fixxme: revisit this */ add_html_elt ("<a href="); if (splitting) execute_string ("\"../%s/", file); else execute_string ("\"%s.html", file); tem = expansion (node, 0); add_anchor_name (tem, 1); add_word ("\">"); execute_string ("%s", *pname ? pname : tem); add_word ("</a>"); free (tem); } else { if (*pname) execute_string ("*note %s: (%s)%s", pname, file, node); else execute_string ("*note (%s)%s::", file, node); } free (node); free (pname); free (file); } }
/* A URL reference. */ void cm_uref (int arg) { if (arg == START) { extern int printing_index; char *url = get_xref_token (1); /* expands all macros in uref */ char *desc = get_xref_token (0); char *replacement = get_xref_token (0); if (docbook) { xml_insert_element_with_attribute (UREF, START, "url=\"%s\"", text_expansion (url)); if (*replacement) execute_string ("%s", replacement); else if (*desc) execute_string ("%s", desc); else execute_string ("%s", url); xml_insert_element (UREF, END); } else if (xml) { xml_insert_element (UREF, START); xml_insert_element (UREFURL, START); execute_string ("%s", url); xml_insert_element (UREFURL, END); if (*desc) { xml_insert_element (UREFDESC, START); execute_string ("%s", desc); xml_insert_element (UREFDESC, END); } if (*replacement) { xml_insert_element (UREFREPLACEMENT, START); execute_string ("%s", replacement); xml_insert_element (UREFREPLACEMENT, END); } xml_insert_element (UREF, END); } else if (html) { /* never need to show the url */ add_html_elt ("<a href="); /* don't collapse `--' etc. in the url */ in_fixed_width_font++; execute_string ("\"%s\"", url); in_fixed_width_font--; add_word (">"); execute_string ("%s", *replacement ? replacement : (*desc ? desc : url)); add_word ("</a>"); } else if (*replacement) /* do not show the url */ execute_string ("%s", replacement); else if (*desc) /* show both text and url */ { execute_string ("%s ", desc); in_fixed_width_font++; execute_string ("(%s)", url); in_fixed_width_font--; } else /* no text at all, so have the url to show */ { in_fixed_width_font++; execute_string ("%s%s%s", printing_index ? "" : "`", url, printing_index ? "" : "'"); in_fixed_width_font--; } if (url) free (url); if (desc) free (desc); if (replacement) free (replacement); } }
/* Make a cross reference. */ void cm_xref (int arg) { if (arg == START) { char *arg1 = get_xref_token (1); /* expands all macros in xref */ char *arg2 = get_xref_token (0); char *arg3 = get_xref_token (0); char *arg4 = get_xref_token (0); char *arg5 = get_xref_token (0); char *tem; /* "@xref{,Foo,, Bar, Baz} is not valid usage of @xref. The first argument must never be blank." --rms. We hereby comply by disallowing such constructs. */ if (!*arg1) line_error (_("First argument to cross-reference may not be empty")); if (docbook) { if (!ref_flag) add_word (px_ref_flag || printing_index ? (char *) _("see ") : (char *) _("See ")); if (!*arg4 && !*arg5) { char *arg1_id = xml_id (arg1); if (*arg2 || *arg3) { xml_insert_element_with_attribute (XREFNODENAME, START, "linkend=\"%s\"", arg1_id); free (arg1_id); execute_string ("%s", *arg3 ? arg3 : arg2); xml_insert_element (XREFNODENAME, END); } else { xml_insert_element_with_attribute (XREF, START, "linkend=\"%s\"", arg1_id); xml_insert_element (XREF, END); free (arg1_id); } } else if (*arg5) { add_word_args (_("See section ``%s'' in "), *arg3 ? arg3 : arg1); xml_insert_element (CITE, START); add_word (arg5); xml_insert_element (CITE, END); } else if (*arg4) { /* Very sad, we are losing xrefs made to ``info only'' books. */ } } else if (xml) { if (!ref_flag) add_word_args ("%s", px_ref_flag ? _("see ") : _("See ")); xml_insert_element (XREF, START); xml_insert_element (XREFNODENAME, START); execute_string ("%s", arg1); xml_insert_element (XREFNODENAME, END); if (*arg2) { xml_insert_element (XREFINFONAME, START); execute_string ("%s", arg2); xml_insert_element (XREFINFONAME, END); } if (*arg3) { xml_insert_element (XREFPRINTEDDESC, START); execute_string ("%s", arg3); xml_insert_element (XREFPRINTEDDESC, END); } if (*arg4) { xml_insert_element (XREFINFOFILE, START); execute_string ("%s", arg4); xml_insert_element (XREFINFOFILE, END); } if (*arg5) { xml_insert_element (XREFPRINTEDNAME, START); execute_string ("%s", arg5); xml_insert_element (XREFPRINTEDNAME, END); } xml_insert_element (XREF, END); } else if (html) { if (!ref_flag) add_word_args ("%s", px_ref_flag ? _("see ") : _("See ")); } else add_word_args ("%s", px_ref_flag ? "*note " : "*Note "); if (!xml) { if (*arg5 || *arg4) { /* arg1 - node name arg2 - reference name arg3 - title or topic (and reference name if arg2 is NULL) arg4 - info file name arg5 - printed manual title */ char *ref_name; if (!*arg2) { if (*arg3) ref_name = arg3; else ref_name = arg1; } else ref_name = arg2; if (html) { /* More to do eventually, down to Unicode Normalization Form C. See the HTML Xref nodes in the manual. */ char *file_arg = arg4; add_html_elt ("<a href="); { /* If there's a directory part, ignore it. */ char *p = strrchr (file_arg, '/'); if (p) file_arg = p + 1; /* If there's a dot, make it a NULL terminator, so the extension does not get into the way. */ p = strrchr (file_arg , '.'); if (p != NULL) *p = 0; } if (! *file_arg) warning (_("Empty file name for HTML cross reference in `%s'"), arg4); /* Note that if we are splitting, and the referenced tag is an anchor rather than a node, we will produce a reference to a file whose name is derived from the anchor name. However, only nodes create files, so we are referencing a non-existent file. cm_anchor, which see, deals with that problem. */ if (splitting) execute_string ("\"../%s/", file_arg); else execute_string ("\"%s.html", file_arg); /* Do not collapse -- to -, etc., in references. */ in_fixed_width_font++; tem = expansion (arg1, 0); /* expand @-commands in node */ in_fixed_width_font--; add_anchor_name (tem, 1); free (tem); add_word ("\">"); execute_string ("%s",ref_name); add_word ("</a>"); } else { execute_string ("%s:", ref_name); in_fixed_width_font++; execute_string (" (%s)%s", arg4, arg1); add_xref_punctuation (); in_fixed_width_font--; } /* Free all of the arguments found. */ if (arg1) free (arg1); if (arg2) free (arg2); if (arg3) free (arg3); if (arg4) free (arg4); if (arg5) free (arg5); return; } else remember_node_reference (arg1, line_number, followed_reference); if (*arg3) { if (html) { add_html_elt ("<a href=\""); in_fixed_width_font++; tem = expansion (arg1, 0); in_fixed_width_font--; add_anchor_name (tem, 1); free (tem); add_word ("\">"); execute_string ("%s", *arg2 ? arg2 : arg3); add_word ("</a>"); } else { execute_string ("%s:", *arg2 ? arg2 : arg3); in_fixed_width_font++; execute_string (" %s", arg1); add_xref_punctuation (); in_fixed_width_font--; } } else { if (html) { add_html_elt ("<a href=\""); in_fixed_width_font++; tem = expansion (arg1, 0); in_fixed_width_font--; add_anchor_name (tem, 1); free (tem); add_word ("\">"); if (*arg2) execute_string ("%s", arg2); else { char *fref = get_float_ref (arg1); execute_string ("%s", fref ? fref : arg1); free (fref); } add_word ("</a>"); } else { if (*arg2) { execute_string ("%s:", arg2); in_fixed_width_font++; execute_string (" %s", arg1); add_xref_punctuation (); in_fixed_width_font--; } else { char *fref = get_float_ref (arg1); if (fref) { /* Reference is being made to a float. */ execute_string ("%s:", fref); in_fixed_width_font++; execute_string (" %s", arg1); add_xref_punctuation (); in_fixed_width_font--; } else { in_fixed_width_font++; execute_string ("%s::", arg1); in_fixed_width_font--; } } } } } /* Free all of the arguments found. */ if (arg1) free (arg1); if (arg2) free (arg2); if (arg3) free (arg3); if (arg4) free (arg4); if (arg5) free (arg5); } else { /* Check that the next non-whitespace character is valid to follow an xref (so Info readers can find the node names). `input_text_offset' is pointing at the "}" which ended the xref command. This is not used for @pxref or @ref, since we insert the necessary punctuation above, if needed. */ int temp = next_nonwhitespace_character (); if (temp == -1) warning (_("End of file reached while looking for `.' or `,'")); else if (temp != '.' && temp != ',') warning (_("`.' or `,' must follow @%s, not `%c'"), command, temp); } }