/* Copyright 2010-2019 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)
/* 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;
if (cmd)
{
ADD("@"); ADD(command_name(cmd));
}
// TODO extra spaces
k = lookup_extra (e, "spaces_before_argument");
if (k)
ADD((char *)k->value);
// TODO multitable or block command
if (cmd == CM_macro || cmd == CM_rmacro)
{
KEY_PAIR *k;
char *s = 0;
k = lookup_extra (e, "arg_line");
if (k)
s = (char *)k->value;
if (s)
{
ADD(s);
return;
}
}
// TODO node
if (e->args.number > 0)
{
int braces, arg_nr, i;
braces = (e->args.list[0]->type == ET_brace_command_arg
|| e->args.list[0]->type == ET_brace_command_context);
if (braces)
ADD("{");
if (e->cmd == CM_verb)
{
k = lookup_extra (e, "delimiter");
ADD((char *)k->value);
}
arg_nr = 0;
for (i = 0; i < e->args.number; i++)
{
if (command_data(cmd).flags & CF_brace)
{
if (arg_nr)
ADD(",");
arg_nr++;
}
k = lookup_extra (e->args.list[i], "spaces_before_argument");
if (k)
ADD((char *)k->value);
convert_to_texinfo_internal (e->args.list[i], result);
k = lookup_extra (e->args.list[i], "spaces_after_argument");
if (k)
ADD((char *)k->value);
}
if (e->cmd == CM_verb)
{
k = lookup_extra (e, "delimiter");
ADD((char *)k->value);
}
if (braces)
ADD("}");
}
}
static void
convert_to_texinfo_internal (ELEMENT *e, TEXT *result)
{
if (e->text.end > 0)
ADD(e->text.text);
else
{
if (e->cmd
|| e->type == ET_def_line
|| e->type == ET_menu_entry
|| e->type == ET_menu_comment)
{
expand_cmd_args_to_texi (e, result);
}
if (e->type == ET_bracketed
|| e->type == ET_bracketed_def_content)
{
KEY_PAIR *k;
ADD("{");
k = lookup_extra (e, "spaces_before_argument");
if (k)
ADD((char *)k->value);
}
if (e->contents.number > 0)
{
int i;
for (i = 0; i < e->contents.number; i++)
convert_to_texinfo_internal (e->contents.list[i], result);
}
if (e->type == ET_bracketed)
ADD("}");
// TODO: raw block command
if (command_flags (e) & CF_block)
{
ADD("@end ");
ADD(command_name(e->cmd));
if (command_data(e->cmd).data != BLOCK_raw)
ADD("\n");
}
}
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;
}
/* Very stripped-down version of Texinfo::Convert::Text.
Convert the contents of E to plain text. Suitable for specifying a file
name containing an at sign or braces. Set *SUPERFLUOUS_ARG if the contents
of E are too complicated to convert properly. */
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