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