/* grecs - Gray's Extensible Configuration System Copyright (C) 2007-2011 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); } }