/* Copyright 2010-2023 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include
#include
#include
#include
#include
#include "parser.h"
#include "text.h"
#include "convert.h"
static void expand_cmd_args_to_texi (ELEMENT *e, TEXT *result);
static void convert_to_texinfo_internal (ELEMENT *e, TEXT *result);
#define ADD(x) text_append (result, x)
/* Currently unused, but could be used to implement link_element_to_texi
from Texinfo::Convert::Texinfo */
/* Return value to be freed by caller. */
char *
node_extra_to_texi (NODE_SPEC_EXTRA *nse)
{
TEXT result;
if (!nse)
return "";
text_init (&result);
if (nse->manual_content
&& nse->manual_content->contents.number > 0)
{
text_append_n (&result, "(", 1);
convert_to_texinfo_internal (nse->manual_content, &result);
text_append_n (&result, ")", 1);
}
if (nse->node_content
&& nse->node_content->contents.number > 0)
{
convert_to_texinfo_internal (nse->node_content, &result);
}
return result.text;
}
static void
expand_cmd_args_to_texi (ELEMENT *e, TEXT *result)
{
enum command_id cmd = e->cmd;
KEY_PAIR *k, *arg_line;
ELEMENT *elt, *spc_before_arg;
if (cmd)
{
ADD("@"); ADD(command_name(cmd));
elt = lookup_info_element (e, "spaces_after_cmd_before_arg");
if (elt)
ADD((char *)elt->text.text);
}
spc_before_arg = lookup_info_element (e, "spaces_before_argument");
arg_line = lookup_info (e, "arg_line");
if (arg_line)
{
char *s = 0;
if (spc_before_arg)
ADD((char *)spc_before_arg->text.text);
s = (char *)arg_line->value;
if (s)
{
ADD(s);
}
}
else if (e->args.number > 0)
{
int braces, arg_nr, i;
int with_commas = 0;
braces = (e->args.list[0]->type == ET_brace_command_arg
|| e->args.list[0]->type == ET_brace_command_context
|| cmd == CM_value);
if (braces)
ADD("{");
if (e->cmd == CM_verb)
{
k = lookup_info (e, "delimiter");
ADD((char *)k->value);
}
if (spc_before_arg)
ADD((char *)spc_before_arg->text.text);
if ((command_data(cmd).flags & CF_block
&& ! (command_data(cmd).flags & CF_def
|| cmd == CM_multitable))
|| cmd == CM_node
|| (command_data(cmd).flags & CF_brace)
|| (command_data(cmd).flags & CF_INFOENCLOSE))
with_commas = 1;
arg_nr = 0;
for (i = 0; i < e->args.number; i++)
{
ELEMENT *arg = e->args.list[i];
if (arg->type == ET_spaces_inserted
|| arg->type == ET_bracketed_inserted
|| arg->type == ET_command_as_argument_inserted)
continue;
if (with_commas)
{
if (arg_nr)
ADD(",");
arg_nr++;
}
convert_to_texinfo_internal (arg, result);
}
if (e->cmd == CM_verb)
{
k = lookup_info (e, "delimiter");
ADD((char *)k->value);
}
if (braces)
ADD("}");
}
else
{
if (spc_before_arg)
ADD((char *)spc_before_arg->text.text);
}
}
static void
convert_to_texinfo_internal (ELEMENT *e, TEXT *result)
{
ELEMENT *elt;
if (e->type == ET_spaces_inserted
|| e->type == ET_bracketed_inserted
|| e->type == ET_command_as_argument_inserted)
{}
else if (e->text.end > 0)
ADD(e->text.text);
else
{
if (e->cmd
|| e->type == ET_def_line)
{
expand_cmd_args_to_texi (e, result);
}
if (e->type == ET_bracketed_arg || e->type == ET_bracketed_linemacro_arg)
ADD("{");
elt = lookup_info_element (e, "spaces_before_argument");
if (elt)
ADD((char *)elt->text.text);
if (e->contents.number > 0)
{
int i;
for (i = 0; i < e->contents.number; i++)
convert_to_texinfo_internal (e->contents.list[i], result);
}
elt = lookup_info_element (e, "spaces_after_argument");
if (elt)
{
ADD((char *)elt->text.text);
}
elt = lookup_info_element (e, "comment_at_end");
if (elt)
convert_to_texinfo_internal (elt, result);
if (e->type == ET_bracketed_arg || e->type == ET_bracketed_linemacro_arg)
ADD("}");
}
return;
}
#undef ADD
/* Return value to be freed by caller. */
char *
convert_to_texinfo (ELEMENT *e)
{
TEXT result;
if (!e)
return strdup ("");
text_init (&result);
convert_to_texinfo_internal (e, &result);
return result.text;
}
char *
convert_contents_to_texinfo (ELEMENT *e)
{
ELEMENT *tmp = new_element (ET_NONE);
char *result;
tmp->contents = e->contents;
result = convert_to_texinfo (tmp);
tmp->contents.list = 0;
destroy_element (tmp);
return result;
}
/*
Convert the contents of E to plain text. Suitable for specifying a file
name containing an at sign or braces, but no other commands nor element
types. Set *SUPERFLUOUS_ARG if the E contains other commands or element
types. */
char *
convert_to_text (ELEMENT *e, int *superfluous_arg)
{
#define ADD(x) text_append (&result, x)
TEXT result; int i;
if (!e)
return "";
text_init (&result);
for (i = 0; i < e->contents.number; i++)
{
ELEMENT *e1 = contents_child_by_index (e, i);
if (e1->text.end > 0)
ADD(e1->text.text);
else if (e1->cmd == CM_AT_SIGN
|| e1->cmd == CM_atchar)
ADD("@");
else if (e1->cmd == CM_OPEN_BRACE
|| e1->cmd == CM_lbracechar)
ADD("{");
else if (e1->cmd == CM_CLOSE_BRACE
|| e1->cmd == CM_rbracechar)
ADD("}");
else
*superfluous_arg = 1;
}
return result.text;
}
#undef ADD