mirror of
https://git.gnunet.org/libmicrohttpd.git
synced 2026-09-25 04:09:31 +03:00
1191 lines
31 KiB
C
1191 lines
31 KiB
C
/*
|
|
This file is part of libmicrohttpd
|
|
Copyright (C) 2024 Christian Grothoff (and other contributing authors)
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library 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
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/**
|
|
* @file options-generator.c
|
|
* @brief Generates code based on Recutils database
|
|
* @author Christian Grothoff
|
|
*/
|
|
#define _GNU_SOURCE
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <unistd.h>
|
|
#include <sys/stat.h>
|
|
#include <errno.h>
|
|
|
|
#define MAX_ARGS 3
|
|
|
|
struct Option
|
|
{
|
|
struct Option *next;
|
|
char *name;
|
|
unsigned int value;
|
|
char *type;
|
|
char *comment;
|
|
char *custom_setter;
|
|
unsigned int argc;
|
|
char *arguments[MAX_ARGS];
|
|
unsigned int desc;
|
|
char *descriptions[MAX_ARGS];
|
|
char *conditional;
|
|
};
|
|
|
|
static FILE *f;
|
|
|
|
static char *category;
|
|
|
|
typedef void
|
|
(*Callback) (const char *name,
|
|
unsigned int value,
|
|
const char *comment,
|
|
const char *type,
|
|
const char *conditional,
|
|
const char *custom_setter,
|
|
unsigned int argc,
|
|
char **arguments,
|
|
unsigned int desc,
|
|
char **descriptions);
|
|
|
|
|
|
static int
|
|
my_asprintf (char **buf,
|
|
const char *format,
|
|
...)
|
|
{
|
|
int ret;
|
|
va_list args;
|
|
|
|
va_start (args,
|
|
format);
|
|
ret = vsnprintf (NULL,
|
|
0,
|
|
format,
|
|
args);
|
|
va_end (args);
|
|
*buf = malloc (ret + 1);
|
|
va_start (args,
|
|
format);
|
|
ret = vsprintf (*buf,
|
|
format,
|
|
args);
|
|
va_end (args);
|
|
return ret;
|
|
}
|
|
|
|
|
|
static void
|
|
iterate (struct Option *head,
|
|
Callback cb)
|
|
{
|
|
for (struct Option *o = head; NULL != o; o = o->next)
|
|
{
|
|
if (0 == strcmp ("end",
|
|
o->name))
|
|
continue;
|
|
cb (o->name,
|
|
o->value,
|
|
o->comment,
|
|
o->type,
|
|
o->conditional,
|
|
o->custom_setter,
|
|
o->argc,
|
|
o->arguments,
|
|
o->desc,
|
|
o->descriptions);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
check (const char *name,
|
|
unsigned int value,
|
|
const char *comment,
|
|
const char *type,
|
|
const char *conditional,
|
|
const char *custom_setter,
|
|
unsigned int argc,
|
|
char **arguments,
|
|
unsigned int desc,
|
|
char **descriptions)
|
|
{
|
|
if (argc != desc)
|
|
{
|
|
fprintf (stderr,
|
|
"Mismatch between descriptions and arguments for `%s'\n",
|
|
name);
|
|
exit (2);
|
|
}
|
|
if ( (NULL == type) &&
|
|
( (0 == argc) ||
|
|
(1 != argc) ) )
|
|
{
|
|
fprintf (stderr,
|
|
"Type and argument missing for `%s' and not exactly 1 argument\n",
|
|
name);
|
|
exit (2);
|
|
}
|
|
for (unsigned int i = 0; i<argc; i++)
|
|
{
|
|
const char *arg = arguments[i];
|
|
|
|
if (NULL == (strrchr (arg, ' ')))
|
|
{
|
|
fprintf (stderr,
|
|
"Mandatory space missing in argument%u of `%s'\n",
|
|
i,
|
|
name);
|
|
exit (2);
|
|
}
|
|
}
|
|
if (NULL != strchr (name, ' '))
|
|
{
|
|
fprintf (stderr,
|
|
"Spaces are not allowed in names, found one in `%s'\n",
|
|
name);
|
|
exit (2);
|
|
}
|
|
}
|
|
|
|
|
|
static char *
|
|
indent (char *pfx,
|
|
const char *input)
|
|
{
|
|
char *ret = strdup (input);
|
|
char *xfx = strdup (pfx);
|
|
char *off;
|
|
size_t pos = 0;
|
|
|
|
while ( (strlen (xfx) > 0) &&
|
|
(isspace (xfx[strlen (xfx) - 1])) )
|
|
xfx[strlen (xfx) - 1] = '\0';
|
|
while (NULL != (off = strchr (ret + pos, '\n')))
|
|
{
|
|
char *tmp;
|
|
|
|
my_asprintf (&tmp,
|
|
"%.*s\n%s%s",
|
|
(int) (off - ret),
|
|
ret,
|
|
(off[1] == '\n')
|
|
? xfx
|
|
: pfx,
|
|
off + 1);
|
|
pos = (off - ret) + strlen (pfx) + 1;
|
|
free (ret);
|
|
ret = tmp;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
static char *
|
|
uppercase (const char *input)
|
|
{
|
|
char *ret = strdup (input);
|
|
|
|
for (size_t i = 0; '\0' != ret[i]; i++)
|
|
ret[i] = toupper (ret[i]);
|
|
return ret;
|
|
}
|
|
|
|
|
|
static char *
|
|
capitalize (const char *input)
|
|
{
|
|
char *ret = strdup (input);
|
|
|
|
ret[0] = toupper (ret[0]);
|
|
return ret;
|
|
}
|
|
|
|
|
|
static char *
|
|
lowercase (const char *input)
|
|
{
|
|
char *ret = strdup (input);
|
|
|
|
for (size_t i = 0; '\0' != ret[i]; i++)
|
|
ret[i] = tolower (ret[i]);
|
|
return ret;
|
|
}
|
|
|
|
|
|
static void
|
|
dump_enum (const char *name,
|
|
unsigned int value,
|
|
const char *comment,
|
|
const char *type,
|
|
const char *conditional,
|
|
const char *custom_setter,
|
|
unsigned int argc,
|
|
char **arguments,
|
|
unsigned int desc,
|
|
char **descriptions)
|
|
{
|
|
printf (" /**\n * %s\n */\n MHD_%c_O_%s = %u\n ,\n\n",
|
|
indent (" * ", comment),
|
|
(char) toupper (*category),
|
|
uppercase (name),
|
|
value);
|
|
}
|
|
|
|
|
|
static const char *
|
|
var_name (const char *arg)
|
|
{
|
|
const char *space;
|
|
|
|
space = strrchr (arg, ' ');
|
|
while ('*' == space[1])
|
|
space++;
|
|
return space + 1;
|
|
}
|
|
|
|
|
|
static void
|
|
dump_union_members (const char *name,
|
|
unsigned int value,
|
|
const char *comment,
|
|
const char *type,
|
|
const char *conditional,
|
|
const char *custom_setter,
|
|
unsigned int argc,
|
|
char **arguments,
|
|
unsigned int desct,
|
|
char **descriptions)
|
|
{
|
|
if (NULL == type)
|
|
return;
|
|
if (1 >= argc)
|
|
return;
|
|
|
|
printf ("/**\n * Data for #MHD_%c_O_%s\n */\n%s\n{\n",
|
|
(char) toupper (*category),
|
|
uppercase (name),
|
|
type);
|
|
for (unsigned int i = 0; i<argc; i++)
|
|
{
|
|
const char *arg = arguments[i];
|
|
const char *desc = descriptions[i];
|
|
const char *vn = var_name (arg);
|
|
|
|
printf (" /**\n * %s\n */\n %.*sv_%s;\n\n",
|
|
indent (" * ",
|
|
desc),
|
|
(int) (vn - arg),
|
|
arg,
|
|
vn);
|
|
}
|
|
printf ("};\n\n");
|
|
}
|
|
|
|
|
|
static void
|
|
dump_union (const char *name,
|
|
unsigned int value,
|
|
const char *comment,
|
|
const char *type,
|
|
const char *conditional,
|
|
const char *custom_setter,
|
|
unsigned int argc,
|
|
char **arguments,
|
|
unsigned int desc,
|
|
char **descriptions)
|
|
{
|
|
const char *xcomment = xcomment = descriptions[0];
|
|
|
|
fprintf (f,
|
|
" /**\n"
|
|
" * Value for #MHD_%c_O_%s.%s%s\n"
|
|
" */\n",
|
|
(char) toupper (*category),
|
|
uppercase (name),
|
|
NULL != xcomment
|
|
? "\n * "
|
|
: "",
|
|
NULL != xcomment
|
|
? indent (" * ", xcomment)
|
|
: "");
|
|
if (NULL != type)
|
|
{
|
|
fprintf (f,
|
|
" %s %s;\n",
|
|
type,
|
|
lowercase (name));
|
|
}
|
|
else
|
|
{
|
|
const char *arg = arguments[0];
|
|
const char *vn = var_name (arg);
|
|
|
|
fprintf (f,
|
|
" %.*s%s;\n",
|
|
(int) (vn - arg),
|
|
arg,
|
|
lowercase (name));
|
|
}
|
|
fprintf (f,
|
|
"\n");
|
|
}
|
|
|
|
|
|
static void
|
|
dump_struct (const char *name,
|
|
unsigned int value,
|
|
const char *comment,
|
|
const char *type,
|
|
const char *conditional,
|
|
const char *custom_setter,
|
|
unsigned int argc,
|
|
char **arguments,
|
|
unsigned int desc,
|
|
char **descriptions)
|
|
{
|
|
if (NULL != conditional)
|
|
fprintf (f,
|
|
"#ifdef HAVE_%s",
|
|
uppercase (conditional));
|
|
dump_union (name,
|
|
value,
|
|
comment,
|
|
type,
|
|
conditional,
|
|
custom_setter,
|
|
argc,
|
|
arguments,
|
|
desc,
|
|
descriptions);
|
|
if (NULL != conditional)
|
|
fprintf (f,
|
|
"#endif\n");
|
|
fprintf (f,
|
|
"\n");
|
|
}
|
|
|
|
|
|
static void
|
|
dump_option_macros (const char *name,
|
|
unsigned int value,
|
|
const char *comment,
|
|
const char *type,
|
|
const char *conditional,
|
|
const char *custom_setter,
|
|
unsigned int argc,
|
|
char **arguments,
|
|
unsigned int desct,
|
|
char **descriptions)
|
|
{
|
|
printf (
|
|
"/**\n * %s\n",
|
|
indent (" * ", comment));
|
|
for (unsigned int off = 0; off<desct; off++)
|
|
{
|
|
const char *arg = arguments[off];
|
|
const char *desc = descriptions[off];
|
|
const char *vn = var_name (arg);
|
|
|
|
printf (" * @param %s %s\n",
|
|
vn,
|
|
indent (" * ",
|
|
desc));
|
|
}
|
|
if (0 == desct)
|
|
printf (" * @param val the value of the parameter");
|
|
printf (" * @return structure with the requested setting\n */\n");
|
|
printf ("# define MHD_%c_OPTION_%s(",
|
|
(char) toupper (*category),
|
|
uppercase (name));
|
|
if (0 == argc)
|
|
printf ("val");
|
|
else
|
|
for (unsigned int i = 0; i<argc; i++)
|
|
{
|
|
if (0 != i)
|
|
printf (",");
|
|
printf ("%s",
|
|
var_name (arguments[i]));
|
|
}
|
|
printf (") \\\n"
|
|
" MHD_NOWARN_COMPOUND_LITERALS_ \\\n"
|
|
" (const struct MHD_%sOptionAndValue) \\\n"
|
|
" { \\\n"
|
|
" .opt = MHD_%c_O_%s, \\\n",
|
|
capitalize (category),
|
|
(char) toupper (*category),
|
|
uppercase (name));
|
|
if (0 == argc)
|
|
printf (" .val.%s = (val) \\\n",
|
|
lowercase (name));
|
|
else
|
|
for (unsigned int i = 0; i<argc; i++)
|
|
{
|
|
const char *vn = var_name (arguments[i]);
|
|
|
|
if (1 < argc)
|
|
printf (" .val.%s.v_%s = (%s)%s \\\n",
|
|
lowercase (name),
|
|
vn,
|
|
vn,
|
|
(i < argc - 1)
|
|
? ","
|
|
: "");
|
|
else
|
|
printf (" .val.%s = (%s)%s \\\n",
|
|
lowercase (name),
|
|
vn,
|
|
(i < argc - 1)
|
|
? ","
|
|
: "");
|
|
}
|
|
|
|
printf (" } \\\n"
|
|
" MHD_RESTORE_WARN_COMPOUND_LITERALS_\n");
|
|
}
|
|
|
|
|
|
static void
|
|
dump_option_static_functions (const char *name,
|
|
unsigned int value,
|
|
const char *comment,
|
|
const char *type,
|
|
const char *conditional,
|
|
const char *custom_setter,
|
|
unsigned int argc,
|
|
char **arguments,
|
|
unsigned int desct,
|
|
char **descriptions)
|
|
{
|
|
printf (
|
|
"\n"
|
|
"/**\n * %s\n",
|
|
indent (" * ", comment));
|
|
for (unsigned int off = 0; off < desct; off++)
|
|
{
|
|
const char *arg = arguments[off];
|
|
const char *desc = descriptions[off];
|
|
const char *vn = var_name (arg);
|
|
|
|
printf (" * @param %s %s\n",
|
|
vn,
|
|
indent (" * ",
|
|
desc));
|
|
}
|
|
if (0 == desct)
|
|
printf (" * @param val the value of the parameter");
|
|
printf (" * @return structure with the requested setting\n */\n");
|
|
printf ("static MHD_INLINE struct MHD_%sOptionAndValue\n"
|
|
"MHD_%c_OPTION_%s (\n",
|
|
capitalize (category),
|
|
(char) toupper (*category),
|
|
uppercase (name));
|
|
if (0 == argc)
|
|
printf (" %s val",
|
|
NULL != type
|
|
? type
|
|
: arguments[0]);
|
|
else
|
|
for (unsigned int i = 0; i<argc; i++)
|
|
{
|
|
const char *arg = arguments[i];
|
|
const char *vn
|
|
= var_name (arg);
|
|
|
|
if (0 != i)
|
|
printf (",\n");
|
|
printf (" %.*s%s",
|
|
(int) (vn - arg),
|
|
arg,
|
|
vn);
|
|
}
|
|
printf (
|
|
"\n"
|
|
" )\n"
|
|
"{\n"
|
|
" struct MHD_%sOptionAndValue opt_val;\n\n"
|
|
" opt_val.opt = MHD_%c_O_%s;\n",
|
|
capitalize (category),
|
|
(char) toupper (*category),
|
|
uppercase (name));
|
|
if (0 == argc)
|
|
printf (" opt_val.val.%s = (val); \\\n",
|
|
lowercase (name));
|
|
else
|
|
for (unsigned int i = 0; i<argc; i++)
|
|
{
|
|
const char *vn = var_name (arguments[i]);
|
|
|
|
if (1 < argc)
|
|
printf (" opt_val.val.%s.v_%s = %s;\n",
|
|
lowercase (name),
|
|
vn,
|
|
vn);
|
|
else
|
|
printf (" opt_val.val.%s = %s;\n",
|
|
lowercase (name),
|
|
vn);
|
|
}
|
|
printf ("\n return opt_val;\n}\n\n");
|
|
}
|
|
|
|
|
|
static void
|
|
dump_option_documentation_functions (const char *name,
|
|
unsigned int value,
|
|
const char *comment,
|
|
const char *type,
|
|
const char *conditional,
|
|
const char *custom_setter,
|
|
unsigned int argc,
|
|
char **arguments,
|
|
unsigned int desct,
|
|
char **descriptions)
|
|
{
|
|
|
|
fprintf (f,
|
|
"/**\n * %s\n",
|
|
indent (" * ", comment));
|
|
for (unsigned int off = 0; off<desct; off++)
|
|
{
|
|
const char *arg = arguments[off];
|
|
const char *desc = descriptions[off];
|
|
const char *vn = var_name (arg);
|
|
|
|
fprintf (f, " * @param %s %s\n",
|
|
vn,
|
|
indent (" * ",
|
|
desc));
|
|
}
|
|
if (0 == desct)
|
|
fprintf (f, " * @param val the value of the parameter");
|
|
fprintf (f, " * @return structure with the requested setting\n */\n");
|
|
fprintf (f,"struct MHD_%sOptionAndValue\n"
|
|
"MHD_%c_OPTION_%s (\n",
|
|
capitalize (category),
|
|
(char) toupper (*category),
|
|
uppercase (name));
|
|
if (0 == argc)
|
|
fprintf (f,
|
|
" %s val",
|
|
NULL != type
|
|
? type
|
|
: arguments[0]);
|
|
else
|
|
for (unsigned int i = 0; i<argc; i++)
|
|
{
|
|
const char *arg = arguments[i];
|
|
const char *vn = var_name (arg);
|
|
|
|
if (0 != i)
|
|
fprintf (f, ",\n");
|
|
fprintf (f,
|
|
" %.*s%s",
|
|
(int) (vn - arg),
|
|
arg,
|
|
vn);
|
|
}
|
|
fprintf (f,
|
|
"\n );\n\n");
|
|
}
|
|
|
|
|
|
static void
|
|
dump_option_set_switch (const char *name,
|
|
unsigned int value,
|
|
const char *comment,
|
|
const char *type,
|
|
const char *conditional,
|
|
const char *custom_setter,
|
|
unsigned int argc,
|
|
char **arguments,
|
|
unsigned int desc,
|
|
char **descriptions)
|
|
{
|
|
if (NULL != conditional)
|
|
fprintf (f,
|
|
"#ifdef HAVE_%s",
|
|
uppercase (conditional));
|
|
fprintf (f,
|
|
" case MHD_%c_O_%s:\n",
|
|
(char) toupper (*category),
|
|
uppercase (name));
|
|
if (NULL != custom_setter)
|
|
{
|
|
fprintf (f,
|
|
" %s\n",
|
|
indent (" ",
|
|
custom_setter));
|
|
}
|
|
else
|
|
{
|
|
if (0 == argc)
|
|
{
|
|
fprintf (f,
|
|
" settings->%s = option->val.%s;\n",
|
|
lowercase (name),
|
|
lowercase (name));
|
|
}
|
|
else
|
|
{
|
|
for (unsigned int i = 0; i<argc; i++)
|
|
{
|
|
const char *vn = var_name (arguments[i]);
|
|
|
|
if (1 < argc)
|
|
fprintf (f,
|
|
" settings->%s.v_%s = option->val.%s.v_%s;\n",
|
|
lowercase (name),
|
|
vn,
|
|
lowercase (name),
|
|
vn);
|
|
else
|
|
fprintf (f,
|
|
" settings->%s = option->val.%s;\n",
|
|
lowercase (name),
|
|
lowercase (name));
|
|
}
|
|
}
|
|
}
|
|
fprintf (f,
|
|
" continue;\n");
|
|
if (NULL != conditional)
|
|
fprintf (f,
|
|
"#endif\n");
|
|
}
|
|
|
|
|
|
static char **
|
|
parse (char **target,
|
|
const char *prefix,
|
|
const char *input)
|
|
{
|
|
if (0 != strncasecmp (prefix,
|
|
input,
|
|
strlen (prefix)))
|
|
return NULL;
|
|
*target = strdup (input + strlen (prefix));
|
|
return target;
|
|
}
|
|
|
|
|
|
int
|
|
main (int argc,
|
|
char **argv)
|
|
{
|
|
static char *dummy;
|
|
struct Option *head = NULL;
|
|
|
|
if (argc < 2)
|
|
{
|
|
fprintf (stderr,
|
|
"Category argument required\n");
|
|
return 3;
|
|
}
|
|
category = argv[1];
|
|
|
|
{
|
|
char *fn;
|
|
char line[4092];
|
|
char **larg = NULL;
|
|
unsigned int off;
|
|
struct Option *last = NULL;
|
|
|
|
my_asprintf (&fn,
|
|
"%c_options.rec",
|
|
*category);
|
|
f = fopen (fn, "r");
|
|
if (NULL == f)
|
|
{
|
|
fprintf (stderr,
|
|
"Failed to open %s: %s\n",
|
|
fn,
|
|
strerror (errno));
|
|
free (fn);
|
|
return 2;
|
|
}
|
|
off = 0;
|
|
TOP:
|
|
while (1)
|
|
{
|
|
ssize_t r;
|
|
|
|
if (NULL ==
|
|
fgets (line,
|
|
sizeof (line),
|
|
f))
|
|
break;
|
|
r = strlen (line);
|
|
off++;
|
|
while ( (r > 0) &&
|
|
( (isspace (line[r - 1])) ||
|
|
(line[r - 1] == '\n') ) )
|
|
line[--r] = '\0'; /* remove new line */
|
|
if (0 == r)
|
|
{
|
|
larg = NULL;
|
|
continue;
|
|
}
|
|
if ( (NULL != larg) &&
|
|
( (0 == strncmp ("+ ",
|
|
line,
|
|
2) ) ||
|
|
(0 == strcmp ("+",
|
|
line) ) ) )
|
|
{
|
|
if (larg == &dummy)
|
|
{
|
|
fprintf (stderr,
|
|
"Continuation after 'Value:' not supported on line %u\n",
|
|
off);
|
|
exit (2);
|
|
}
|
|
|
|
*larg = realloc (*larg,
|
|
strlen (*larg) + r + 2);
|
|
strcat (*larg,
|
|
"\n");
|
|
if (0 != strcmp ("+",
|
|
line) )
|
|
strcat (*larg,
|
|
line + 2);
|
|
continue;
|
|
}
|
|
if ( ('%' == line[0]) ||
|
|
('#' == line[0]) )
|
|
continue;
|
|
if (NULL == larg)
|
|
{
|
|
struct Option *o = malloc (sizeof (struct Option));
|
|
|
|
memset (o, 0, sizeof (*o));
|
|
if (NULL == head)
|
|
head = o;
|
|
else
|
|
last->next = o;
|
|
last = o;
|
|
}
|
|
if (NULL != (larg = parse (&last->name,
|
|
"Name: ",
|
|
line)))
|
|
continue;
|
|
if (NULL != (larg = parse (&last->comment,
|
|
"Comment: ",
|
|
line)))
|
|
continue;
|
|
if (NULL != (larg = parse (&last->type,
|
|
"Type: ",
|
|
line)))
|
|
continue;
|
|
if (NULL != (larg = parse (&last->conditional,
|
|
"Conditional: ",
|
|
line)))
|
|
continue;
|
|
if (NULL != (larg = parse (&last->custom_setter,
|
|
"CustomSetter: ",
|
|
line)))
|
|
continue;
|
|
if (0 == strncasecmp (line,
|
|
"Value: ",
|
|
strlen ("Value: ")))
|
|
{
|
|
char xdummy;
|
|
|
|
if (1 == sscanf (line + strlen ("Value: "),
|
|
"%u%c",
|
|
&last->value,
|
|
&xdummy))
|
|
{
|
|
larg = &dummy;
|
|
continue;
|
|
}
|
|
fprintf (stderr,
|
|
"Value on line %d not a number\n",
|
|
off);
|
|
return 2;
|
|
}
|
|
for (unsigned int i = 0; i<MAX_ARGS; i++)
|
|
{
|
|
char name[32];
|
|
|
|
snprintf (name,
|
|
sizeof (name),
|
|
"Argument%u: ",
|
|
i + 1);
|
|
if (NULL != (larg = parse (&last->arguments[i],
|
|
name,
|
|
line)))
|
|
{
|
|
last->argc = i + 1;
|
|
goto TOP;
|
|
}
|
|
snprintf (name,
|
|
sizeof (name),
|
|
"Description%u: ",
|
|
i + 1);
|
|
if (NULL != (larg = parse (&last->descriptions[i],
|
|
name,
|
|
line)))
|
|
{
|
|
last->desc = i + 1;
|
|
goto TOP;
|
|
}
|
|
}
|
|
fprintf (stderr,
|
|
"Could not parse line %u: `%s'\n",
|
|
off,
|
|
line);
|
|
exit (2);
|
|
}
|
|
free (fn);
|
|
}
|
|
|
|
iterate (head,
|
|
&check);
|
|
|
|
/* Generate enum MHD_${CATEGORY}Option */
|
|
printf ("/**\n"
|
|
" * The options (parameters) for MHD %s\n"
|
|
" */\n"
|
|
"enum MHD_FIXED_ENUM_APP_SET_ MHD_%sOption\n"
|
|
"{",
|
|
category,
|
|
capitalize (category));
|
|
printf (" /**\n"
|
|
" * Not a real option.\n"
|
|
" * Should not be used directly.\n"
|
|
" * This value indicates the end of the list of the options.\n"
|
|
" */\n"
|
|
" MHD_%c_O_END = 0\n"
|
|
" ,\n\n",
|
|
(char) toupper (*category));
|
|
iterate (head,
|
|
&dump_enum);
|
|
printf (" /**\n"
|
|
" * The sentinel value.\n"
|
|
" * This value enforces specific underlying integer type for the enum.\n"
|
|
" * Do not use.\n"
|
|
" */\n"
|
|
" MHD_%c_O_SENTINEL = 65535\n\n",
|
|
(char) toupper (*category));
|
|
printf ("};\n\n");
|
|
iterate (head,
|
|
&dump_union_members);
|
|
|
|
/* Generate union MHD_${CATEGORY}OptionValue */
|
|
printf ("/**\n"
|
|
" * Parameters for MHD %s options\n"
|
|
" */\n"
|
|
"union MHD_%sOptionValue\n"
|
|
"{\n",
|
|
category,
|
|
capitalize (category));
|
|
f = stdout;
|
|
iterate (head,
|
|
&dump_union);
|
|
f = NULL;
|
|
printf ("};\n\n");
|
|
|
|
printf ("\n"
|
|
"struct MHD_%sOptionAndValue\n"
|
|
"{\n"
|
|
" /**\n"
|
|
" * The %s configuration option\n"
|
|
" */\n"
|
|
" enum MHD_%sOption opt;\n\n"
|
|
" /**\n"
|
|
" * The value for the @a opt option\n"
|
|
" */\n"
|
|
" union MHD_%sOptionValue val;\n"
|
|
"};\n\n",
|
|
capitalize (category),
|
|
category,
|
|
capitalize (category),
|
|
capitalize (category));
|
|
printf (
|
|
"#if defined(MHD_USE_COMPOUND_LITERALS) && defined(MHD_USE_DESIG_NEST_INIT)\n");
|
|
iterate (head,
|
|
&dump_option_macros);
|
|
printf (
|
|
"\n"
|
|
"/**\n"
|
|
" * Terminate the list of the options\n"
|
|
" * @return the terminating object of struct MHD_%sOptionAndValue\n"
|
|
" */\n"
|
|
"# define MHD_%c_OPTION_TERMINATE() \\\n"
|
|
" MHD_NOWARN_COMPOUND_LITERALS_ \\\n"
|
|
" (const struct MHD_%sOptionAndValue) \\\n"
|
|
" { \\\n"
|
|
" .opt = (MHD_%c_O_END) \\\n"
|
|
" } \\\n"
|
|
" MHD_RESTORE_WARN_COMPOUND_LITERALS_\n\n",
|
|
capitalize (category),
|
|
(char) toupper (*category),
|
|
capitalize (category),
|
|
(char) toupper (*category));
|
|
|
|
printf (
|
|
"#else /* !MHD_USE_COMPOUND_LITERALS || !MHD_USE_DESIG_NEST_INIT */\n");
|
|
printf ("MHD_NOWARN_UNUSED_FUNC_");
|
|
iterate (head,
|
|
&dump_option_static_functions);
|
|
printf ("\n/**\n"
|
|
" * Terminate the list of the options\n"
|
|
" * @return the terminating object of struct MHD_%sOptionAndValue\n"
|
|
" */\n"
|
|
"static MHD_INLINE struct MHD_%sOptionAndValue\n"
|
|
"MHD_%c_OPTION_TERMINATE (void)\n"
|
|
"{\n"
|
|
" struct MHD_%sOptionAndValue opt_val;\n\n"
|
|
" opt_val.opt = MHD_%c_O_END;\n\n"
|
|
" return opt_val;\n"
|
|
"}\n\n\n",
|
|
capitalize (category),
|
|
capitalize (category),
|
|
(char) toupper (*category),
|
|
capitalize (category),
|
|
(char) toupper (*category));
|
|
|
|
printf ("MHD_RESTORE_WARN_UNUSED_FUNC_\n");
|
|
printf (
|
|
"#endif /* !MHD_USE_COMPOUND_LITERALS || !MHD_USE_DESIG_NEST_INIT */\n");
|
|
|
|
{
|
|
char *doc_in;
|
|
|
|
my_asprintf (&doc_in,
|
|
"microhttpd2_inline_%s_documentation.h.in",
|
|
category);
|
|
(void) unlink (doc_in);
|
|
f = fopen (doc_in, "w");
|
|
if (NULL == f)
|
|
{
|
|
fprintf (stderr,
|
|
"Failed to open `%s': %s\n",
|
|
doc_in,
|
|
strerror (errno));
|
|
return 2;
|
|
}
|
|
fprintf (f,
|
|
"/* Beginning of generated code documenting how to use options.\n"
|
|
" You should treat the following functions *as if* they were\n"
|
|
" part of the header/API. The actual declarations are more\n"
|
|
" complex, so these here are just for documentation!\n"
|
|
" We do not actually *build* this code... */\n"
|
|
"#if 0\n\n");
|
|
iterate (head,
|
|
&dump_option_documentation_functions);
|
|
fprintf (f,
|
|
"/* End of generated code documenting how to use options */\n#endif\n\n");
|
|
fclose (f);
|
|
chmod (doc_in, S_IRUSR | S_IRGRP | S_IROTH);
|
|
}
|
|
|
|
{
|
|
char *so_c;
|
|
|
|
my_asprintf (&so_c,
|
|
"../mhd2/%s_set_options.c",
|
|
category);
|
|
(void) unlink (so_c);
|
|
f = fopen (so_c, "w");
|
|
if (NULL == f)
|
|
{
|
|
fprintf (stderr,
|
|
"Failed to open `%s': %s\n",
|
|
so_c,
|
|
strerror (errno));
|
|
return 2;
|
|
}
|
|
fprintf (f,
|
|
"/* This is generated code, it is still under LGPLv2.1+.\n"
|
|
" Do not edit directly! */\n"
|
|
"/* *INDENT-OFF* */\n"
|
|
"/**\n"
|
|
" * @file %s_set_options.c\n"
|
|
" * @author %s-options-generator.c\n"
|
|
" */\n"
|
|
"\n"
|
|
"#include \"mhd_sys_options.h\"\n"
|
|
"#include \"sys_bool_type.h\"\n"
|
|
"#include \"sys_base_types.h\"\n"
|
|
"#include \"sys_malloc.h\"\n"
|
|
"#include <string.h>\n"
|
|
"#include \"mhd_%s.h\"\n"
|
|
"#include \"%s_options.h\"\n"
|
|
"#include \"mhd_public_api.h\"\n",
|
|
category,
|
|
category,
|
|
category,
|
|
category);
|
|
if (0 == strcmp (category, "response"))
|
|
fprintf (f,
|
|
"#include \"mhd_locks.h\"\n"
|
|
"#include \"mhd_assert.h\"\n"
|
|
"#include \"response_funcs.h\"\n");
|
|
fprintf (f,
|
|
"\n"
|
|
"MHD_FN_PAR_NONNULL_ALL_ MHD_EXTERN_\n"
|
|
"enum MHD_StatusCode\n"
|
|
"MHD_%s_set_options (\n"
|
|
" struct MHD_%s *%s,\n"
|
|
" const struct MHD_%sOptionAndValue *options,\n"
|
|
" size_t options_max_num)\n"
|
|
"{\n",
|
|
category,
|
|
capitalize (category),
|
|
category,
|
|
capitalize (category));
|
|
fprintf (f,
|
|
" struct %sOptions *restrict settings = %s->settings;\n"
|
|
" enum MHD_StatusCode res = MHD_SC_OK;\n"
|
|
" size_t i;\n",
|
|
capitalize (category),
|
|
category);
|
|
if (0 == strcmp (category, "daemon"))
|
|
{
|
|
fprintf (f,
|
|
"\n"
|
|
" if (mhd_DAEMON_STATE_NOT_STARTED != daemon->state)\n"
|
|
" return MHD_SC_TOO_LATE;\n"
|
|
"\n");
|
|
}
|
|
else if (0 == strcmp (category, "response"))
|
|
{
|
|
fprintf (f,
|
|
" bool need_unlock = false;\n"
|
|
"\n"
|
|
" if (response->frozen)\n"
|
|
" return MHD_SC_TOO_LATE;\n"
|
|
" if (response->reuse.reusable)\n"
|
|
" {\n"
|
|
" need_unlock = true;\n"
|
|
" if (! mhd_mutex_lock(&response->reuse.settings_lock))\n"
|
|
" return MHD_SC_RESPONSE_MUTEX_LOCK_FAILED;\n"
|
|
" mhd_assert (1 == mhd_atomic_counter_get(&response->reuse.counter));\n"
|
|
" if (! response->frozen) /* Firm re-check under the lock */\n"
|
|
" {\n"
|
|
" mhd_mutex_unlock_chk(&response->reuse.settings_lock);\n"
|
|
" return MHD_SC_TOO_LATE;\n"
|
|
" }\n"
|
|
" }\n"
|
|
"\n");
|
|
}
|
|
else
|
|
{
|
|
fprintf (f,
|
|
"\n"
|
|
" if (NULL == settings)\n"
|
|
" return MHD_SC_TOO_LATE;\n"
|
|
"\n");
|
|
}
|
|
fprintf (f,
|
|
" for (i = 0; i < options_max_num; i++)\n"
|
|
" {\n"
|
|
" const struct MHD_%sOptionAndValue *const option\n"
|
|
" = options + i;\n"
|
|
" switch (option->opt)\n"
|
|
" {\n",
|
|
capitalize (category));
|
|
fprintf (f,
|
|
" case MHD_%c_O_END:\n"
|
|
" i = options_max_num - 1;\n"
|
|
" break;\n",
|
|
(char) toupper (*category));
|
|
iterate (head,
|
|
&dump_option_set_switch);
|
|
fprintf (f,
|
|
" case MHD_%c_O_SENTINEL:\n"
|
|
" default: /* for -Wswitch-default -Wswitch-enum */ \n"
|
|
" res = MHD_SC_OPTION_UNKNOWN;\n"
|
|
" i = options_max_num - 1;\n"
|
|
" break;\n",
|
|
(char) toupper (*category));
|
|
fprintf (f,
|
|
" }\n"
|
|
" }\n");
|
|
if (0 == strcmp (category, "response"))
|
|
{
|
|
fprintf (f,
|
|
"\n"
|
|
" if (need_unlock)\n"
|
|
" mhd_mutex_unlock_chk(&response->reuse.settings_lock);\n"
|
|
"\n");
|
|
}
|
|
fprintf (f,
|
|
" return res;\n"
|
|
"}\n");
|
|
fclose (f);
|
|
chmod (so_c, S_IRUSR | S_IRGRP | S_IROTH);
|
|
free (so_c);
|
|
}
|
|
|
|
{
|
|
char *do_h;
|
|
|
|
my_asprintf (&do_h,
|
|
"../mhd2/%s_options.h",
|
|
category);
|
|
(void) unlink (do_h);
|
|
f = fopen (do_h, "w");
|
|
if (NULL == f)
|
|
{
|
|
fprintf (stderr,
|
|
"Failed to open `%s': %s\n",
|
|
do_h,
|
|
strerror (errno));
|
|
return 2;
|
|
}
|
|
fprintf (f,
|
|
"/* This is generated code, it is still under LGPLv2.1+.\n"
|
|
" Do not edit directly! */\n"
|
|
"/* *INDENT-OFF* */\n"
|
|
"/**\n"
|
|
" * @file %s_options.h\n"
|
|
" * @author %s-options-generator.c\n"
|
|
" */\n\n"
|
|
"#ifndef MHD_%s_OPTIONS_H\n"
|
|
"#define MHD_%s_OPTIONS_H 1\n"
|
|
"\n"
|
|
"#include \"mhd_sys_options.h\"\n"
|
|
"#include \"mhd_public_api.h\"\n"
|
|
"\n"
|
|
"struct %sOptions\n"
|
|
"{\n",
|
|
category,
|
|
category,
|
|
uppercase (category),
|
|
uppercase (category),
|
|
capitalize (category));
|
|
iterate (head,
|
|
&dump_struct);
|
|
fprintf (f,
|
|
"};\n"
|
|
"\n"
|
|
"#endif /* ! MHD_%s_OPTIONS_H 1 */\n",
|
|
uppercase (category));
|
|
fclose (f);
|
|
chmod (do_h, S_IRUSR | S_IRGRP | S_IROTH);
|
|
free (do_h);
|
|
}
|
|
|
|
return 0;
|
|
}
|