options-generator.c (34296B)
1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ 2 /* 3 This file is part of GNU libmicrohttpd. 4 Copyright (C) 2024 Christian Grothoff (and other contributing authors) 5 6 GNU libmicrohttpd is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 GNU libmicrohttpd is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 Alternatively, you can redistribute GNU libmicrohttpd and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of 19 the License, or (at your option) any later version, together 20 with the eCos exception, as follows: 21 22 As a special exception, if other files instantiate templates or 23 use macros or inline functions from this file, or you compile this 24 file and link it with other works to produce a work based on this 25 file, this file does not by itself cause the resulting work to be 26 covered by the GNU General Public License. However the source code 27 for this file must still be made available in accordance with 28 section (3) of the GNU General Public License v2. 29 30 This exception does not invalidate any other reasons why a work 31 based on this file might be covered by the GNU General Public 32 License. 33 34 You should have received copies of the GNU Lesser General Public 35 License and the GNU General Public License along with this library; 36 if not, see <https://www.gnu.org/licenses/>. 37 */ 38 /** 39 * @file options-generator.c 40 * @brief Generates code based on Recutils database 41 * @author Christian Grothoff 42 */ 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <stdarg.h> 46 #include <string.h> 47 #include <ctype.h> 48 #if !defined(_WIN32) || defined(__CYGWIN__) 49 # include <unistd.h> 50 #endif 51 #include <sys/stat.h> 52 #include <errno.h> 53 54 #define MAX_ARGS 3 55 56 struct Option 57 { 58 struct Option *next; 59 char *name; 60 unsigned int value; 61 char *type; 62 char *comment; 63 char *custom_setter; 64 unsigned int argc; 65 char *arguments[MAX_ARGS]; 66 unsigned int desc; 67 char *descriptions[MAX_ARGS]; 68 char *conditional; 69 }; 70 71 72 static void 73 option_init_blank (struct Option *o) 74 { 75 unsigned int i; 76 77 memset (o, 0, sizeof (*o)); 78 o->next = NULL; 79 o->name = NULL; 80 o->type = NULL; 81 o->comment = NULL; 82 o->custom_setter = NULL; 83 for (i = 0; i < MAX_ARGS; ++i) 84 { 85 o->arguments[i] = NULL; 86 o->descriptions[i] = NULL; 87 } 88 o->conditional = NULL; 89 } 90 91 92 static FILE *f; 93 94 static char *category; 95 96 typedef void 97 (*Callback)(const char *name, 98 unsigned int value, 99 const char *comment, 100 const char *type, 101 const char *conditional, 102 const char *custom_setter, 103 unsigned int argc, 104 char **arguments, 105 unsigned int desc, 106 char **descriptions); 107 108 109 static int 110 my_asprintf (char **buf, 111 const char *format, 112 ...) 113 { 114 int ret; 115 va_list args; 116 117 va_start (args, 118 format); 119 ret = vsnprintf (NULL, 120 0, 121 format, 122 args); 123 va_end (args); 124 *buf = (char *)malloc (ret + 1); 125 va_start (args, 126 format); 127 ret = vsprintf (*buf, 128 format, 129 args); 130 va_end (args); 131 return ret; 132 } 133 134 135 static void 136 iterate (struct Option *head, 137 Callback cb) 138 { 139 for (struct Option *o = head; NULL != o; o = o->next) 140 { 141 if (0 == strcmp ("end", 142 o->name)) 143 continue; 144 cb (o->name, 145 o->value, 146 o->comment, 147 o->type, 148 o->conditional, 149 o->custom_setter, 150 o->argc, 151 o->arguments, 152 o->desc, 153 o->descriptions); 154 } 155 } 156 157 158 static void 159 check (const char *name, 160 unsigned int value, 161 const char *comment, 162 const char *type, 163 const char *conditional, 164 const char *custom_setter, 165 unsigned int argc, 166 char **arguments, 167 unsigned int desc, 168 char **descriptions) 169 { 170 if (argc != desc) 171 { 172 fprintf (stderr, 173 "Mismatch between descriptions and arguments for `%s'\n", 174 name); 175 exit (2); 176 } 177 if ((NULL == type) 178 && ((0 == argc) 179 || (1 != argc))) 180 { 181 fprintf (stderr, 182 "Type and argument missing for `%s' and not exactly 1 argument\n", 183 name); 184 exit (2); 185 } 186 for (unsigned int i = 0; i < argc; i++) 187 { 188 const char *arg = arguments[i]; 189 190 if (NULL == (strrchr (arg, ' '))) 191 { 192 fprintf (stderr, 193 "Mandatory space missing in argument%u of `%s'\n", 194 i, 195 name); 196 exit (2); 197 } 198 } 199 if (NULL != strchr (name, ' ')) 200 { 201 fprintf (stderr, 202 "Spaces are not allowed in names, found one in `%s'\n", 203 name); 204 exit (2); 205 } 206 } 207 208 209 static char * 210 indent (const char *pfx, 211 const char *input) 212 { 213 char *ret = strdup (input); 214 char *xfx = strdup (pfx); 215 char *off; 216 size_t pos = 0; 217 218 while ((strlen (xfx) > 0) 219 && (isspace (xfx[strlen (xfx) - 1]))) 220 xfx[strlen (xfx) - 1] = '\0'; 221 while (NULL != (off = strchr (ret + pos, '\n'))) 222 { 223 char *tmp; 224 225 my_asprintf (&tmp, 226 "%.*s\n%s%s", 227 (int)(off - ret), 228 ret, 229 (off[1] == '\n') 230 ? xfx 231 : pfx, 232 off + 1); 233 pos = (off - ret) + strlen (pfx) + 1; 234 free (ret); 235 ret = tmp; 236 } 237 return ret; 238 } 239 240 241 static char * 242 uppercase (const char *input) 243 { 244 char *ret = strdup (input); 245 246 for (size_t i = 0; '\0' != ret[i]; i++) 247 ret[i] = toupper (ret[i]); 248 return ret; 249 } 250 251 252 static char * 253 capitalize (const char *input) 254 { 255 char *ret = strdup (input); 256 257 ret[0] = toupper (ret[0]); 258 return ret; 259 } 260 261 262 static char * 263 lowercase (const char *input) 264 { 265 char *ret = strdup (input); 266 267 for (size_t i = 0; '\0' != ret[i]; i++) 268 ret[i] = tolower (ret[i]); 269 return ret; 270 } 271 272 273 static void 274 dump_enum (const char *name, 275 unsigned int value, 276 const char *comment, 277 const char *type, 278 const char *conditional, 279 const char *custom_setter, 280 unsigned int argc, 281 char **arguments, 282 unsigned int desc, 283 char **descriptions) 284 { 285 printf (" /**\n * %s\n */\n MHD_%c_O_%s = %u\n ,\n\n", 286 indent (" * ", comment), 287 (char)toupper (*category), 288 uppercase (name), 289 value); 290 } 291 292 293 static const char * 294 var_name (const char *arg) 295 { 296 const char *space; 297 298 space = strrchr (arg, ' '); 299 while ('*' == space[1]) 300 space++; 301 return space + 1; 302 } 303 304 305 static void 306 dump_union_members (const char *name, 307 unsigned int value, 308 const char *comment, 309 const char *type, 310 const char *conditional, 311 const char *custom_setter, 312 unsigned int argc, 313 char **arguments, 314 unsigned int desct, 315 char **descriptions) 316 { 317 if (NULL == type) 318 return; 319 if (1 >= argc) 320 return; 321 322 printf ("/**\n * Data for #MHD_%c_O_%s\n */\n%s\n{\n", 323 (char)toupper (*category), 324 uppercase (name), 325 type); 326 for (unsigned int i = 0; i < argc; i++) 327 { 328 const char *arg = arguments[i]; 329 const char *desc = descriptions[i]; 330 const char *vn = var_name (arg); 331 332 printf (" /**\n * %s\n */\n %.*sv_%s;\n\n", 333 indent (" * ", 334 desc), 335 (int)(vn - arg), 336 arg, 337 vn); 338 } 339 printf ("};\n\n"); 340 } 341 342 343 static void 344 dump_union (const char *name, 345 unsigned int value, 346 const char *comment, 347 const char *type, 348 const char *conditional, 349 const char *custom_setter, 350 unsigned int argc, 351 char **arguments, 352 unsigned int desc, 353 char **descriptions) 354 { 355 const char *xcomment = xcomment = descriptions[0]; 356 357 fprintf (f, 358 " /**\n" 359 " * Value for #MHD_%c_O_%s.%s%s\n" 360 " */\n", 361 (char)toupper (*category), 362 uppercase (name), 363 NULL != xcomment 364 ? "\n * " 365 : "", 366 NULL != xcomment 367 ? indent (" * ", xcomment) 368 : ""); 369 if (NULL != type) 370 { 371 fprintf (f, 372 " %s %s;\n", 373 type, 374 lowercase (name)); 375 } 376 else 377 { 378 const char *arg = arguments[0]; 379 const char *vn = var_name (arg); 380 381 fprintf (f, 382 " %.*s%s;\n", 383 (int)(vn - arg), 384 arg, 385 lowercase (name)); 386 } 387 fprintf (f, 388 "\n"); 389 } 390 391 392 static void 393 dump_struct (const char *name, 394 unsigned int value, 395 const char *comment, 396 const char *type, 397 const char *conditional, 398 const char *custom_setter, 399 unsigned int argc, 400 char **arguments, 401 unsigned int desc, 402 char **descriptions) 403 { 404 if (NULL != conditional) 405 fprintf (f, 406 "#ifdef HAVE_%s", 407 uppercase (conditional)); 408 dump_union (name, 409 value, 410 comment, 411 type, 412 conditional, 413 custom_setter, 414 argc, 415 arguments, 416 desc, 417 descriptions); 418 if (NULL != conditional) 419 fprintf (f, 420 "#endif\n"); 421 fprintf (f, 422 "\n"); 423 } 424 425 426 static void 427 dump_option_macros (const char *name, 428 unsigned int value, 429 const char *comment, 430 const char *type, 431 const char *conditional, 432 const char *custom_setter, 433 unsigned int argc, 434 char **arguments, 435 unsigned int desct, 436 char **descriptions) 437 { 438 printf ( 439 "/**\n * %s\n", 440 indent (" * ", comment)); 441 for (unsigned int off = 0; off < desct; off++) 442 { 443 const char *arg = arguments[off]; 444 const char *desc = descriptions[off]; 445 const char *vn = var_name (arg); 446 447 printf (" * @param %s %s\n", 448 vn, 449 indent (" * ", 450 desc)); 451 } 452 if (0 == desct) 453 printf (" * @param value the value of the parameter"); 454 printf (" * @return structure with the requested setting\n */\n"); 455 printf ("# define MHD_%c_OPTION_%s(", 456 (char)toupper (*category), 457 uppercase (name)); 458 if (0 == argc) 459 printf ("value"); 460 else 461 for (unsigned int i = 0; i < argc; i++) 462 { 463 if (0 != i) 464 printf (", "); 465 printf ("%s", 466 var_name (arguments[i])); 467 } 468 printf (") \\\n" 469 " MHD_NOWARN_COMPOUND_LITERALS_ " \ 470 "MHD_NOWARN_AGGR_DYN_INIT_ \\\n" 471 " (const struct MHD_%sOptionAndValue) \\\n" 472 " { \\\n" 473 " .opt = MHD_%c_O_%s, \\\n", 474 capitalize (category), 475 (char)toupper (*category), 476 uppercase (name)); 477 if (0 == argc) 478 printf (" .val.%s = (value) \\\n", 479 lowercase (name)); 480 else 481 for (unsigned int i = 0; i < argc; i++) 482 { 483 const char *vn = var_name (arguments[i]); 484 485 if (1 < argc) 486 printf (" .val.%s.v_%s = (%s)%s \\\n", 487 lowercase (name), 488 vn, 489 vn, 490 (i < argc - 1) 491 ? "," 492 : ""); 493 else 494 printf (" .val.%s = (%s)%s \\\n", 495 lowercase (name), 496 vn, 497 (i < argc - 1) 498 ? "," 499 : ""); 500 } 501 502 printf (" } \\\n" 503 " MHD_RESTORE_WARN_COMPOUND_LITERALS_ " 504 "MHD_RESTORE_WARN_AGGR_DYN_INIT_\n"); 505 } 506 507 508 static void 509 dump_option_static_functions (const char *name, 510 unsigned int value, 511 const char *comment, 512 const char *type, 513 const char *conditional, 514 const char *custom_setter, 515 unsigned int argc, 516 char **arguments, 517 unsigned int desct, 518 char **descriptions) 519 { 520 printf ( 521 "\n" 522 "/**\n * %s\n", 523 indent (" * ", comment)); 524 for (unsigned int off = 0; off < desct; off++) 525 { 526 const char *arg = arguments[off]; 527 const char *desc = descriptions[off]; 528 const char *vn = var_name (arg); 529 530 printf (" * @param %s %s\n", 531 vn, 532 indent (" * ", 533 desc)); 534 } 535 if (0 == desct) 536 printf (" * @param value the value of the parameter"); 537 printf (" * @return structure with the requested setting\n */\n"); 538 printf ("static MHD_INLINE struct MHD_%sOptionAndValue\n" 539 "MHD_%c_OPTION_%s (\n", 540 capitalize (category), 541 (char)toupper (*category), 542 uppercase (name)); 543 if (0 == argc) 544 printf (" %s value", 545 NULL != type 546 ? type 547 : arguments[0]); 548 else 549 for (unsigned int i = 0; i < argc; i++) 550 { 551 const char *arg = arguments[i]; 552 const char *vn 553 = var_name (arg); 554 555 if (0 != i) 556 printf (",\n"); 557 printf (" %.*s%s", 558 (int)(vn - arg), 559 arg, 560 vn); 561 } 562 printf ( 563 "\n" 564 " )\n" 565 "{\n" 566 " struct MHD_%sOptionAndValue opt_val;\n\n" 567 " opt_val.opt = MHD_%c_O_%s;\n", 568 capitalize (category), 569 (char)toupper (*category), 570 uppercase (name)); 571 if (0 == argc) 572 printf (" opt_val.val.%s = (value);\n", 573 lowercase (name)); 574 else 575 for (unsigned int i = 0; i < argc; i++) 576 { 577 const char *vn = var_name (arguments[i]); 578 579 if (1 < argc) 580 printf (" opt_val.val.%s.v_%s = %s;\n", 581 lowercase (name), 582 vn, 583 vn); 584 else 585 printf (" opt_val.val.%s = %s;\n", 586 lowercase (name), 587 vn); 588 } 589 printf ("\n return opt_val;\n}\n\n"); 590 } 591 592 593 static void 594 dump_option_documentation_functions (const char *name, 595 unsigned int value, 596 const char *comment, 597 const char *type, 598 const char *conditional, 599 const char *custom_setter, 600 unsigned int argc, 601 char **arguments, 602 unsigned int desct, 603 char **descriptions) 604 { 605 606 fprintf (f, 607 "/**\n * %s\n", 608 indent (" * ", comment)); 609 for (unsigned int off = 0; off < desct; off++) 610 { 611 const char *arg = arguments[off]; 612 const char *desc = descriptions[off]; 613 const char *vn = var_name (arg); 614 615 fprintf (f, " * @param %s %s\n", 616 vn, 617 indent (" * ", 618 desc)); 619 } 620 if (0 == desct) 621 fprintf (f, " * @param value the value of the parameter"); 622 fprintf (f, " * @return structure with the requested setting\n */\n"); 623 fprintf (f, "struct MHD_%sOptionAndValue\n" 624 "MHD_%c_OPTION_%s (\n", 625 capitalize (category), 626 (char)toupper (*category), 627 uppercase (name)); 628 if (0 == argc) 629 fprintf (f, 630 " %s value", 631 NULL != type 632 ? type 633 : arguments[0]); 634 else 635 for (unsigned int i = 0; i < argc; i++) 636 { 637 const char *arg = arguments[i]; 638 const char *vn = var_name (arg); 639 640 if (0 != i) 641 fprintf (f, ",\n"); 642 fprintf (f, 643 " %.*s%s", 644 (int)(vn - arg), 645 arg, 646 vn); 647 } 648 fprintf (f, 649 "\n );\n\n"); 650 } 651 652 653 /* Emit " DST = SRC;", wrapped after the '=' when the whole line would 654 * exceed the 80-column target. */ 655 static void 656 dump_setter_assignment (const char *dst, 657 const char *src) 658 { 659 if (80 >= 6 + strlen (dst) + 3 + strlen (src) + 1) 660 fprintf (f, 661 " %s = %s;\n", 662 dst, 663 src); 664 else 665 fprintf (f, 666 " %s =\n" 667 " %s;\n", 668 dst, 669 src); 670 } 671 672 673 static void 674 dump_option_set_switch (const char *name, 675 unsigned int value, 676 const char *comment, 677 const char *type, 678 const char *conditional, 679 const char *custom_setter, 680 unsigned int argc, 681 char **arguments, 682 unsigned int desc, 683 char **descriptions) 684 { 685 if (NULL != conditional) 686 fprintf (f, 687 "#ifdef HAVE_%s", 688 uppercase (conditional)); 689 fprintf (f, 690 " case MHD_%c_O_%s:\n", 691 (char)toupper (*category), 692 uppercase (name)); 693 if (NULL != custom_setter) 694 { 695 /* Emit line by line: preprocessor directives must stay at the first 696 * column, ordinary code lines get the 'case' body indentation. */ 697 const char *line = custom_setter; 698 699 while (NULL != line) 700 { 701 const char *nl = strchr (line, '\n'); 702 size_t len = (NULL == nl) ? strlen (line) : (size_t)(nl - line); 703 704 if (0 == len) 705 fprintf (f, "\n"); 706 else if ('#' == line[0]) 707 fprintf (f, "%.*s\n", (int)len, line); 708 else 709 fprintf (f, " %.*s\n", (int)len, line); 710 line = (NULL == nl) ? NULL : nl + 1; 711 } 712 } 713 else 714 { 715 if (0 == argc) 716 { 717 char *dst; 718 char *src; 719 720 my_asprintf (&dst, "settings->%s", lowercase (name)); 721 my_asprintf (&src, "option->val.%s", lowercase (name)); 722 dump_setter_assignment (dst, src); 723 free (dst); 724 free (src); 725 } 726 else 727 { 728 for (unsigned int i = 0; i < argc; i++) 729 { 730 const char *vn = var_name (arguments[i]); 731 char *dst; 732 char *src; 733 734 if (1 < argc) 735 { 736 my_asprintf (&dst, "settings->%s.v_%s", lowercase (name), vn); 737 my_asprintf (&src, "option->val.%s.v_%s", lowercase (name), vn); 738 } 739 else 740 { 741 my_asprintf (&dst, "settings->%s", lowercase (name)); 742 my_asprintf (&src, "option->val.%s", lowercase (name)); 743 } 744 dump_setter_assignment (dst, src); 745 free (dst); 746 free (src); 747 } 748 } 749 } 750 fprintf (f, 751 " continue;\n"); 752 if (NULL != conditional) 753 fprintf (f, 754 "#endif\n"); 755 } 756 757 758 static char ** 759 parse (char **target, 760 const char *prefix, 761 const char *input) 762 { 763 if (0 != strncasecmp (prefix, 764 input, 765 strlen (prefix))) 766 return NULL; 767 *target = strdup (input + strlen (prefix)); 768 return target; 769 } 770 771 772 int 773 main (int argc, 774 char **argv) 775 { 776 static char *dummy; 777 struct Option *head = NULL; 778 779 if (argc < 2) 780 { 781 fprintf (stderr, 782 "Category argument required\n"); 783 return 3; 784 } 785 category = argv[1]; 786 787 { 788 char *fn; 789 char line[4092]; 790 char **larg = NULL; 791 unsigned int off; 792 struct Option *last = NULL; 793 794 my_asprintf (&fn, 795 "%c_options.rec", 796 *category); 797 f = fopen (fn, "r"); 798 if (NULL == f) 799 { 800 fprintf (stderr, 801 "Failed to open %s: %s\n", 802 fn, 803 strerror (errno)); 804 free (fn); 805 return 2; 806 } 807 off = 0; 808 TOP: 809 while (1) 810 { 811 ssize_t r; 812 813 if (NULL == 814 fgets (line, 815 sizeof (line), 816 f)) 817 break; 818 r = strlen (line); 819 off++; 820 while ((r > 0) 821 && ((isspace (line[r - 1])) 822 || (line[r - 1] == '\n'))) 823 line[--r] = '\0'; /* remove new line */ 824 if (0 == r) 825 { 826 larg = NULL; 827 continue; 828 } 829 if ((NULL != larg) 830 && ((0 == strncmp ("+ ", 831 line, 832 2)) 833 || (0 == strcmp ("+", 834 line)))) 835 { 836 if (larg == &dummy) 837 { 838 fprintf (stderr, 839 "Continuation after 'Value:' not supported on line %u\n", 840 off); 841 exit (2); 842 } 843 844 *larg = (char *)realloc (*larg, 845 strlen (*larg) + r + 2); 846 strcat (*larg, 847 "\n"); 848 if (0 != strcmp ("+", 849 line)) 850 strcat (*larg, 851 line + 2); 852 continue; 853 } 854 if (('%' == line[0]) 855 || ('#' == line[0])) 856 continue; 857 if (NULL == larg) 858 { 859 struct Option *o = (struct Option *)malloc (sizeof (struct Option)); 860 861 option_init_blank (o); 862 if (NULL == head) 863 head = o; 864 else 865 last->next = o; 866 last = o; 867 } 868 if (NULL != (larg = parse (&last->name, 869 "Name: ", 870 line))) 871 continue; 872 if (NULL != (larg = parse (&last->comment, 873 "Comment: ", 874 line))) 875 continue; 876 if (NULL != (larg = parse (&last->type, 877 "Type: ", 878 line))) 879 continue; 880 if (NULL != (larg = parse (&last->conditional, 881 "Conditional: ", 882 line))) 883 continue; 884 if (NULL != (larg = parse (&last->custom_setter, 885 "CustomSetter: ", 886 line))) 887 continue; 888 if (0 == strncasecmp (line, 889 "Value: ", 890 strlen ("Value: "))) 891 { 892 char xdummy; 893 894 if (1 == sscanf (line + strlen ("Value: "), 895 "%u%c", 896 &last->value, 897 &xdummy)) 898 { 899 larg = &dummy; 900 continue; 901 } 902 fprintf (stderr, 903 "Value on line %d not a number\n", 904 off); 905 return 2; 906 } 907 for (unsigned int i = 0; i < MAX_ARGS; i++) 908 { 909 char name[32]; 910 911 snprintf (name, 912 sizeof (name), 913 "Argument%u: ", 914 i + 1); 915 if (NULL != (larg = parse (&last->arguments[i], 916 name, 917 line))) 918 { 919 last->argc = i + 1; 920 goto TOP; 921 } 922 snprintf (name, 923 sizeof (name), 924 "Description%u: ", 925 i + 1); 926 if (NULL != (larg = parse (&last->descriptions[i], 927 name, 928 line))) 929 { 930 last->desc = i + 1; 931 goto TOP; 932 } 933 } 934 fprintf (stderr, 935 "Could not parse line %u: `%s'\n", 936 off, 937 line); 938 exit (2); 939 } 940 free (fn); 941 } 942 943 iterate (head, 944 &check); 945 946 /* Generate enum MHD_${CATEGORY}Option */ 947 printf ("/**\n" 948 " * The options (parameters) for MHD %s\n" 949 " */\n" 950 "enum MHD_FIXED_ENUM_APP_SET_ MHD_%sOption\n" 951 "{", 952 category, 953 capitalize (category)); 954 printf (" /**\n" 955 " * Not a real option.\n" 956 " * Should not be used directly.\n" 957 " * This value indicates the end of the list of the options.\n" 958 " */\n" 959 " MHD_%c_O_END = 0\n" 960 " ,\n\n", 961 (char)toupper (*category)); 962 iterate (head, 963 &dump_enum); 964 printf (" /**\n" 965 " * The sentinel value.\n" 966 " * This value enforces specific underlying integer type for the enum.\n" 967 " * Do not use.\n" 968 " */\n" 969 " MHD_%c_O_SENTINEL = 65535\n\n", 970 (char)toupper (*category)); 971 printf ("};\n\n"); 972 iterate (head, 973 &dump_union_members); 974 975 /* Generate union MHD_${CATEGORY}OptionValue */ 976 printf ("/**\n" 977 " * Parameters for MHD %s options\n" 978 " */\n" 979 "union MHD_%sOptionValue\n" 980 "{\n", 981 category, 982 capitalize (category)); 983 f = stdout; 984 iterate (head, 985 &dump_union); 986 f = NULL; 987 printf ("};\n\n"); 988 989 printf ("\n" 990 "struct MHD_%sOptionAndValue\n" 991 "{\n" 992 " /**\n" 993 " * The %s configuration option\n" 994 " */\n" 995 " enum MHD_%sOption opt;\n\n" 996 " /**\n" 997 " * The value for the @a opt option\n" 998 " */\n" 999 " union MHD_%sOptionValue val;\n" 1000 "};\n\n", 1001 capitalize (category), 1002 category, 1003 capitalize (category), 1004 capitalize (category)); 1005 printf ( 1006 "#if defined(MHD_USE_COMPOUND_LITERALS) && defined(MHD_USE_DESIG_NEST_INIT)\n"); 1007 iterate (head, 1008 &dump_option_macros); 1009 printf ( 1010 "\n" 1011 "/**\n" 1012 " * Terminate the list of the options\n" 1013 " * @return the terminating object of struct MHD_%sOptionAndValue\n" 1014 " */\n" 1015 "# define MHD_%c_OPTION_TERMINATE() \\\n" 1016 " MHD_NOWARN_COMPOUND_LITERALS_ \\\n" 1017 " (const struct MHD_%sOptionAndValue) \\\n" 1018 " { \\\n" 1019 " .opt = (MHD_%c_O_END) \\\n" 1020 " } \\\n" 1021 " MHD_RESTORE_WARN_COMPOUND_LITERALS_\n\n", 1022 capitalize (category), 1023 (char)toupper (*category), 1024 capitalize (category), 1025 (char)toupper (*category)); 1026 1027 printf ( 1028 "#else /* !MHD_USE_COMPOUND_LITERALS || !MHD_USE_DESIG_NEST_INIT */\n"); 1029 printf ("MHD_NOWARN_UNUSED_FUNC_"); 1030 iterate (head, 1031 &dump_option_static_functions); 1032 printf ("\n/**\n" 1033 " * Terminate the list of the options\n" 1034 " * @return the terminating object of struct MHD_%sOptionAndValue\n" 1035 " */\n" 1036 "static MHD_INLINE struct MHD_%sOptionAndValue\n" 1037 "MHD_%c_OPTION_TERMINATE (void)\n" 1038 "{\n" 1039 " struct MHD_%sOptionAndValue opt_val;\n\n" 1040 " opt_val.opt = MHD_%c_O_END;\n\n" 1041 " return opt_val;\n" 1042 "}\n\n\n", 1043 capitalize (category), 1044 capitalize (category), 1045 (char)toupper (*category), 1046 capitalize (category), 1047 (char)toupper (*category)); 1048 1049 printf ("MHD_RESTORE_WARN_UNUSED_FUNC_\n"); 1050 printf ( 1051 "#endif /* !MHD_USE_COMPOUND_LITERALS || !MHD_USE_DESIG_NEST_INIT */\n"); 1052 1053 { 1054 char *doc_in; 1055 1056 my_asprintf (&doc_in, 1057 "microhttpd2_inline_%s_documentation.h.in", 1058 category); 1059 (void)unlink (doc_in); 1060 f = fopen (doc_in, "w"); 1061 if (NULL == f) 1062 { 1063 fprintf (stderr, 1064 "Failed to open `%s': %s\n", 1065 doc_in, 1066 strerror (errno)); 1067 return 2; 1068 } 1069 fprintf (f, 1070 "/* Beginning of generated code documenting how to use options.\n" 1071 " You should treat the following functions *as if* they were\n" 1072 " part of the header/API. The actual declarations are more\n" 1073 " complex, so these here are just for documentation!\n" 1074 " We do not actually *build* this code... */\n" 1075 "#if 0\n\n"); 1076 iterate (head, 1077 &dump_option_documentation_functions); 1078 fprintf (f, 1079 "/* End of generated code documenting how to use options */\n#endif\n\n"); 1080 fclose (f); 1081 chmod (doc_in, S_IRUSR | S_IRGRP | S_IROTH); 1082 } 1083 1084 { 1085 char *so_c; 1086 1087 my_asprintf (&so_c, 1088 "../mhd2/%s_set_options.c", 1089 category); 1090 (void)unlink (so_c); 1091 f = fopen (so_c, "w"); 1092 if (NULL == f) 1093 { 1094 fprintf (stderr, 1095 "Failed to open `%s': %s\n", 1096 so_c, 1097 strerror (errno)); 1098 return 2; 1099 } 1100 fprintf (f, 1101 "/* This is generated code, it is still under LGPLv2.1+.\n" 1102 " Do not edit directly! */\n" 1103 "/**\n" 1104 " * @file %s_set_options.c\n" 1105 " * @author options-generator.c\n" 1106 " */\n" 1107 "\n", 1108 category); 1109 if (0 == strcmp (category, "daemon")) 1110 { 1111 fprintf (f, 1112 "#include \"mhd_sys_options.h\"\n" 1113 "#include \"sys_base_types.h\"\n" 1114 "#include \"sys_malloc.h\"\n" 1115 "#include <string.h>\n" 1116 "#include \"mhd_daemon.h\"\n" 1117 "#include \"daemon_options.h\"\n" 1118 "#include \"mhd_public_api.h\"\n" 1119 "\n"); 1120 } 1121 else if (0 == strcmp (category, "response")) 1122 { 1123 fprintf (f, 1124 "#include \"mhd_sys_options.h\"\n" 1125 "#include \"response_set_options.h\"\n" 1126 "#include \"sys_base_types.h\"\n" 1127 "#include \"sys_bool_type.h\"\n" 1128 "#include \"response_options.h\"\n" 1129 "#include \"mhd_response.h\"\n" 1130 "#include \"mhd_public_api.h\"\n" 1131 "#include \"mhd_locks.h\"\n" 1132 "#include \"mhd_assert.h\"\n" 1133 "#include \"response_funcs.h\"\n" 1134 "\n"); 1135 } 1136 1137 fprintf (f, 1138 "\n" 1139 "MHD_FN_PAR_NONNULL_ALL_ MHD_EXTERN_\n" 1140 "enum MHD_StatusCode\n" 1141 "MHD_%s_set_options (\n" 1142 " struct MHD_%s *MHD_RESTRICT %s,\n" 1143 " const struct MHD_%sOptionAndValue *MHD_RESTRICT options,\n" 1144 " size_t options_max_num)\n" 1145 "{\n", 1146 category, 1147 capitalize (category), 1148 category, 1149 capitalize (category)); 1150 fprintf (f, 1151 " struct %sOptions *restrict settings = %s->settings;\n" 1152 " enum MHD_StatusCode res = MHD_SC_OK;\n" 1153 " size_t i;\n", 1154 capitalize (category), 1155 category); 1156 if (0 == strcmp (category, "daemon")) 1157 { 1158 fprintf (f, 1159 "\n" 1160 " if (mhd_DAEMON_STATE_NOT_STARTED != daemon->state)\n" 1161 " return MHD_SC_TOO_LATE;\n" 1162 "\n"); 1163 } 1164 else if (0 == strcmp (category, "response")) 1165 { 1166 fprintf (f, 1167 " bool need_unlock = false;\n" 1168 "\n" 1169 " if (response->frozen)\n" 1170 " return MHD_SC_TOO_LATE;\n" 1171 " if (response->reuse.reusable)\n" 1172 " {\n" 1173 " need_unlock = true;\n" 1174 " if (!mhd_mutex_lock (&response->reuse.settings_lock))\n" 1175 " return MHD_SC_RESP_MUTEX_LOCK_FAILED;\n" 1176 " mhd_assert (1 == mhd_atomic_counter_get (&response->reuse.counter));\n" 1177 " if (response->frozen) /* Firm re-check under the lock */\n" 1178 " {\n" 1179 " mhd_mutex_unlock_chk (&response->reuse.settings_lock);\n" 1180 " return MHD_SC_TOO_LATE;\n" 1181 " }\n" 1182 " }\n" 1183 "\n"); 1184 } 1185 else 1186 { 1187 fprintf (f, 1188 "\n" 1189 " if (NULL == settings)\n" 1190 " return MHD_SC_TOO_LATE;\n" 1191 "\n"); 1192 } 1193 fprintf (f, 1194 " for (i = 0; i < options_max_num; i++)\n" 1195 " {\n" 1196 " const struct MHD_%sOptionAndValue *const option\n" 1197 " = options + i;\n" 1198 " switch (option->opt)\n" 1199 " {\n", 1200 capitalize (category)); 1201 fprintf (f, 1202 " case MHD_%c_O_END:\n" 1203 " i = options_max_num - 1;\n" 1204 " break;\n", 1205 (char)toupper (*category)); 1206 iterate (head, 1207 &dump_option_set_switch); 1208 fprintf (f, 1209 " case MHD_%c_O_SENTINEL:\n" 1210 " default: /* for -Wswitch-default -Wswitch-enum */\n" 1211 " res = MHD_SC_OPTION_UNKNOWN;\n" 1212 " i = options_max_num - 1;\n" 1213 " break;\n", 1214 (char)toupper (*category)); 1215 fprintf (f, 1216 " }\n" 1217 " }\n"); 1218 if (0 == strcmp (category, "response")) 1219 { 1220 fprintf (f, 1221 "\n" 1222 " if (need_unlock)\n" 1223 " mhd_mutex_unlock_chk (&response->reuse.settings_lock);\n" 1224 "\n"); 1225 } 1226 fprintf (f, 1227 " return res;\n" 1228 "}\n"); 1229 fclose (f); 1230 chmod (so_c, S_IRUSR | S_IRGRP | S_IROTH); 1231 free (so_c); 1232 } 1233 1234 { 1235 char *do_h; 1236 1237 my_asprintf (&do_h, 1238 "../mhd2/%s_options.h", 1239 category); 1240 (void)unlink (do_h); 1241 f = fopen (do_h, "w"); 1242 if (NULL == f) 1243 { 1244 fprintf (stderr, 1245 "Failed to open `%s': %s\n", 1246 do_h, 1247 strerror (errno)); 1248 return 2; 1249 } 1250 fprintf (f, 1251 "/* This is generated code, it is still under LGPLv2.1+.\n" 1252 " Do not edit directly! */\n" 1253 "/**\n" 1254 " * @file %s_options.h\n" 1255 " * @author %s-options-generator.c\n" 1256 " */\n\n" 1257 "#ifndef MHD_%s_OPTIONS_H\n" 1258 "#define MHD_%s_OPTIONS_H 1\n" 1259 "\n" 1260 "#include \"mhd_sys_options.h\"\n" 1261 "#include \"mhd_public_api.h\"\n" 1262 "\n" 1263 "struct %sOptions\n" 1264 "{\n", 1265 category, 1266 category, 1267 uppercase (category), 1268 uppercase (category), 1269 capitalize (category)); 1270 iterate (head, 1271 &dump_struct); 1272 fprintf (f, 1273 "};\n" 1274 "\n" 1275 "#endif /* ! MHD_%s_OPTIONS_H 1 */\n", 1276 uppercase (category)); 1277 fclose (f); 1278 chmod (do_h, S_IRUSR | S_IRGRP | S_IROTH); 1279 free (do_h); 1280 } 1281 1282 return 0; 1283 }