/* grecs - Gray's Extensible Configuration System
Copyright (C) 2007, 2008, 2009, 2010 Sergey Poznyakoff
Grecs 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.
Grecs 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 Grecs. If not, see . */
#ifdef HAVE_CONFIG_H
# include
#endif
#include
#include
#include
#include
#include
const char *
grecs_data_type_string (enum grecs_data_type type)
{
switch (type)
{
case grecs_type_void:
return "void";
case grecs_type_string:
return "string";
case grecs_type_short:
case grecs_type_ushort:
case grecs_type_int:
case grecs_type_uint:
case grecs_type_long:
case grecs_type_ulong:
case grecs_type_size:
/*FIXME case grecs_type_off:*/
return "number";
case grecs_type_time:
return "time";
case grecs_type_bool:
return "boolean";
case grecs_type_ipv4:
return "IPv4";
case grecs_type_cidr:
return "CIDR";
case grecs_type_host:
return "hostname";
case grecs_type_sockaddr:
return "sock-addr";
case grecs_type_section:
return "section";
}
return "UNKNOWN?";
}
static void
format_level (FILE *stream, unsigned level)
{
while (level--)
fprintf (stream, " ");
}
void
grecs_format_docstring (FILE *stream, const char *docstring, unsigned level)
{
size_t len = strlen (docstring);
int width = 78 - level * 2;
if (width < 0)
{
width = 78;
level = 0;
}
while (len)
{
size_t seglen;
const char *p;
for (seglen = 0, p = docstring; p < docstring + width && *p; p++)
{
if (*p == '\n')
{
seglen = p - docstring;
break;
}
if (isspace (*p))
seglen = p - docstring;
}
if (seglen == 0 || *p == 0)
seglen = p - docstring;
format_level (stream, level);
fprintf (stream, "# ");
fwrite (docstring, seglen, 1, stream);
fputc ('\n', stream);
len -= seglen;
docstring += seglen;
if (*docstring == '\n')
{
docstring++;
len--;
}
else
while (*docstring && isspace (*docstring))
{
docstring++;
len--;
}
}
}
void
grecs_format_simple_statement (FILE *stream, struct grecs_keyword *kwp,
unsigned level)
{
const char *argstr;
if (kwp->docstring)
grecs_format_docstring (stream, kwp->docstring, level);
format_level (stream, level);
if (kwp->argname)
argstr = kwp->argname;
else
argstr = N_("arg");
if (strchr ("<[", argstr[0]))
fprintf (stream, "%s %s;\n", kwp->ident, gettext (argstr));
else if (strchr (argstr, ':'))
fprintf (stream, "%s <%s>;\n", kwp->ident, gettext (argstr));
else
{
fprintf (stream, "%s <%s: ", kwp->ident, gettext (argstr));
if (GRECS_IS_LIST (kwp->type))
fprintf (stream, "list of %s",
gettext (grecs_data_type_string (GRECS_TYPE (kwp->type))));
else
fprintf (stream, "%s", gettext (grecs_data_type_string (kwp->type)));
fprintf (stream, ">;\n");
}
}
void
grecs_format_block_statement (FILE *stream, struct grecs_keyword *kwp,
unsigned level)
{
if (kwp->docstring)
grecs_format_docstring (stream, kwp->docstring, level);
format_level (stream, level);
fprintf (stream, "%s", kwp->ident);
if (kwp->argname)
fprintf (stream, " <%s>", gettext (kwp->argname));
fprintf (stream, " {\n");
grecs_format_statement_array (stream, kwp->kwd, 0, level + 1);
format_level (stream, level);
fprintf (stream, "}\n");
}
void
grecs_format_statement_array (FILE *stream, struct grecs_keyword *kwp,
unsigned n,
unsigned level)
{
for (; kwp->ident; kwp++, n++)
{
if (n)
fputc ('\n', stream);
if (kwp->type == grecs_type_section)
grecs_format_block_statement (stream, kwp, level);
else
grecs_format_simple_statement (stream, kwp, level);
}
}