LCOV - code coverage report
Current view: top level - common/options - monet_options.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 82 177 46.3 %
Date: 2024-12-19 23:10:26 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : /*
      14             :  * @f monet_options
      15             :  * @a N.J. Nes
      16             :  * @* A simple option handling library
      17             :  * @T
      18             :  * The monet server and clients make use of command line options and a (possibly)
      19             :  * shared config file. With this library a set (represented by set,setlen) of
      20             :  * options is created. An option is stored as name and value strings with a
      21             :  * special flag indicating the origin of the options, (builtin, system config
      22             :  * file, special config file or command line option).
      23             :  *
      24             :  */
      25             : #include "monetdb_config.h"
      26             : #include "monet_options.h"
      27             : #ifndef HAVE_GETOPT_LONG
      28             : #  include "monet_getopt.h"
      29             : #else
      30             : # ifdef HAVE_GETOPT_H
      31             : #  include "getopt.h"
      32             : # endif
      33             : #endif
      34             : #include <string.h>
      35             : #include <ctype.h>
      36             : 
      37             : #ifdef HAVE_UNISTD_H
      38             : #include <unistd.h>
      39             : #endif
      40             : 
      41             : #ifndef HAVE_GETOPT_LONG
      42             : #  include "getopt.c"
      43             : #  include "getopt1.c"
      44             : #endif
      45             : 
      46             : #ifdef NATIVE_WIN32
      47             : #define getpid _getpid
      48             : #endif
      49             : 
      50             : /* these two are used if the set parameter passed into functions is NULL */
      51             : static int default_setlen = 0;
      52             : static opt *default_set = NULL;
      53             : 
      54             : static int
      55        2094 : mo_default_set(opt **Set, int setlen)
      56             : {
      57        2094 :         if (*Set == NULL) {
      58           0 :                 if (default_set == NULL) {
      59           0 :                         default_setlen = mo_builtin_settings(&default_set);
      60           0 :                         default_setlen = mo_system_config(&default_set, default_setlen);
      61             :                 }
      62           0 :                 *Set = default_set;
      63           0 :                 setlen = default_setlen;
      64             :         }
      65        2094 :         return setlen;
      66             : }
      67             : 
      68             : void
      69         342 : mo_print_options(opt *set, int setlen)
      70             : {
      71         342 :         int i = 0;
      72             : 
      73         342 :         setlen = mo_default_set(&set, setlen);
      74        4531 :         for (i = 0; i < setlen; i++) {
      75        3847 :                 if (set[i].kind == opt_builtin) {
      76        1710 :                         fprintf(stderr, "# builtin opt \t%s = %s\n", set[i].name, set[i].value);
      77             :                 }
      78             :         }
      79        4189 :         for (i = 0; i < setlen; i++) {
      80        3847 :                 if (set[i].kind == opt_config) {
      81           0 :                         fprintf(stderr, "# config opt \t%s = %s\n", set[i].name, set[i].value);
      82             :                 }
      83             :         }
      84        4189 :         for (i = 0; i < setlen; i++) {
      85        3847 :                 if (set[i].kind == opt_cmdline) {
      86        2137 :                         fprintf(stderr, "# cmdline opt \t%s = %s\n", set[i].name, set[i].value);
      87             :                 }
      88             :         }
      89         342 : }
      90             : 
      91             : 
      92             : const char *
      93        1752 : mo_find_option(opt *set, int setlen, const char *name)
      94             : {
      95        1752 :         opt *o = NULL;
      96        1752 :         int i;
      97             : 
      98        1752 :         setlen = mo_default_set(&set, setlen);
      99       22971 :         for (i = 0; i < setlen; i++) {
     100       19467 :                 if (strcmp(set[i].name, name) == 0)
     101         714 :                         if (!o || o->kind < set[i].kind)
     102       19467 :                                 o = set + i;
     103             :         }
     104        1752 :         if (o)
     105         361 :                 return o->value;
     106             :         return NULL;
     107             : }
     108             : 
     109             : static int
     110           0 : mo_config_file(opt **Set, int setlen, const char *file)
     111             : {
     112           0 :         char buf[BUFSIZ];
     113           0 :         FILE *fd = NULL;
     114           0 :         opt *set;
     115             : 
     116           0 :         if (Set == NULL) {
     117           0 :                 if (default_set == NULL) {
     118           0 :                         set = NULL;
     119           0 :                         setlen = mo_default_set(&set, 0);
     120             :                 } else
     121           0 :                         setlen = default_setlen;
     122             :                 Set = &default_set;
     123             :         }
     124           0 :         set = *Set;
     125           0 :         fd = fopen(file, "r");
     126           0 :         if (fd == NULL) {
     127           0 :                 fprintf(stderr, "Could not open file %s\n", file);
     128           0 :                 return setlen;
     129             :         }
     130           0 :         while (fgets(buf, BUFSIZ, fd) != NULL) {
     131             :                 char *s, *t, *val;
     132             :                 int quote;
     133             : 
     134           0 :                 for (s = buf; *s && isspace((unsigned char) *s); s++)
     135             :                         ;
     136           0 :                 if (*s == '#')
     137           0 :                         continue;       /* commentary */
     138           0 :                 if (*s == 0)
     139           0 :                         continue;       /* empty line */
     140             : 
     141           0 :                 val = strchr(s, '=');
     142           0 :                 if (val == NULL) {
     143           0 :                         fprintf(stderr, "mo_config_file: syntax error in %s at %s\n", file, s);
     144           0 :                         break;
     145             :                 }
     146           0 :                 *val = 0;
     147             : 
     148           0 :                 for (t = s; *t && !isspace((unsigned char) *t); t++)
     149             :                         ;
     150           0 :                 *t = 0;
     151             : 
     152             :                 /* skip any leading blanks in the value part */
     153           0 :                 for (val++; *val && isspace((unsigned char) *val); val++)
     154             :                         ;
     155             : 
     156             :                 /* search to unquoted # */
     157             :                 quote = 0;
     158           0 :                 for (t = val; *t; t++) {
     159           0 :                         if (*t == '"')
     160           0 :                                 quote = !quote;
     161           0 :                         else if (!quote && *t == '#')
     162             :                                 break;
     163             :                 }
     164           0 :                 if (quote) {
     165           0 :                         fprintf(stderr, "mo_config_file: wrong number of quotes in %s at %s\n", file, val);
     166           0 :                         break;
     167             :                 }
     168             :                 /* remove trailing white space */
     169           0 :                 while (isspace((unsigned char) t[-1]))
     170           0 :                         t--;
     171           0 :                 *t++ = 0;
     172             : 
     173             :                 /* treat value as empty if it consists only of white space */
     174           0 :                 if (t <= val)
     175           0 :                         val = t - 1;
     176             : 
     177           0 :                 opt *tmp = realloc(set, (setlen + 1) * sizeof(opt));
     178           0 :                 if (tmp == NULL)
     179             :                         break;
     180           0 :                 *Set = set = tmp;
     181           0 :                 set[setlen].kind = opt_config;
     182           0 :                 set[setlen].name = strdup(s);
     183           0 :                 set[setlen].value = malloc((size_t) (t - val));
     184           0 :                 if (set[setlen].name == NULL || set[setlen].value == NULL) {
     185           0 :                         free(set[setlen].name);
     186           0 :                         free(set[setlen].value);
     187           0 :                         break;
     188             :                 }
     189           0 :                 for (t = val, s = set[setlen].value; *t; t++)
     190           0 :                         if (*t != '"')
     191           0 :                                 *s++ = *t;
     192           0 :                 *s = 0;
     193           0 :                 setlen++;
     194             :         }
     195           0 :         (void) fclose(fd);
     196           0 :         return setlen;
     197             : }
     198             : 
     199             : int
     200         342 : mo_system_config(opt **Set, int setlen)
     201             : {
     202         342 :         const char *cfg;
     203             : 
     204         342 :         if (Set == NULL) {
     205           0 :                 if (default_set == NULL) {
     206           0 :                         opt *set = NULL;
     207             : 
     208           0 :                         setlen = mo_default_set(&set, 0);
     209             :                 } else
     210           0 :                         setlen = default_setlen;
     211             :                 Set = &default_set;
     212             :         }
     213         342 :         cfg = mo_find_option(*Set, setlen, "config");
     214         342 :         if (!cfg)
     215             :                 return setlen;
     216           0 :         setlen = mo_config_file(Set, setlen, cfg);
     217           0 :         return setlen;
     218             : }
     219             : 
     220             : int
     221         355 : mo_builtin_settings(opt **Set)
     222             : {
     223         355 :         int i = 0;
     224         355 :         opt *set;
     225             : 
     226         355 :         if (Set == NULL)
     227             :                 return 0;
     228             : 
     229             : #define N_OPTIONS       5       /*MUST MATCH # OPTIONS BELOW */
     230         355 :         set = malloc(sizeof(opt) * N_OPTIONS);
     231         355 :         if (set == NULL)
     232             :                 return 0;
     233             : 
     234         355 :         *Set = set;
     235         355 :         set[i].kind = opt_builtin;
     236         355 :         set[i].name = strdup("gdk_dbpath");
     237         355 :         set[i].value = strdup(LOCALSTATEDIR DIR_SEP_STR "monetdb5" DIR_SEP_STR
     238             :                               "dbfarm" DIR_SEP_STR "demo");
     239         355 :         if (set[i].name == NULL || set[i].value == NULL) {
     240           0 :                 free(set[i].name);
     241           0 :                 free(set[i].value);
     242           0 :                 return i;
     243             :         }
     244         355 :         i++;
     245         355 :         set[i].kind = opt_builtin;
     246         355 :         set[i].name = strdup("mapi_port");
     247         355 :         set[i].value = strdup(MAPI_PORT_STR);
     248         355 :         if (set[i].name == NULL || set[i].value == NULL) {
     249           0 :                 free(set[i].name);
     250           0 :                 free(set[i].value);
     251           0 :                 return i;
     252             :         }
     253         355 :         i++;
     254         355 :         set[i].kind = opt_builtin;
     255         355 :         set[i].name = strdup("sql_optimizer");
     256         355 :         set[i].value = strdup("default_pipe");
     257         355 :         if (set[i].name == NULL || set[i].value == NULL) {
     258           0 :                 free(set[i].name);
     259           0 :                 free(set[i].value);
     260           0 :                 return i;
     261             :         }
     262         355 :         i++;
     263         355 :         set[i].kind = opt_builtin;
     264         355 :         set[i].name = strdup("sql_debug");
     265         355 :         set[i].value = strdup("0");
     266         355 :         if (set[i].name == NULL || set[i].value == NULL) {
     267           0 :                 free(set[i].name);
     268           0 :                 free(set[i].value);
     269           0 :                 return i;
     270             :         }
     271         355 :         i++;
     272         355 :         set[i].kind = opt_builtin;
     273         355 :         set[i].name = strdup("raw_strings");
     274         355 :         set[i].value = strdup("false");
     275         355 :         if (set[i].name == NULL || set[i].value == NULL) {
     276           0 :                 free(set[i].name);
     277           0 :                 free(set[i].value);
     278           0 :                 return i;
     279             :         }
     280         355 :         i++;
     281             : 
     282             :         assert(i == N_OPTIONS);
     283             :         return i;
     284             : }
     285             : 
     286             : int
     287        2149 : mo_add_option(opt **Set, int setlen, opt_kind kind, const char *name, const char *value)
     288             : {
     289        2149 :         opt *set;
     290             : 
     291        2149 :         if (Set == NULL) {
     292           0 :                 if (default_set == NULL) {
     293           0 :                         set = NULL;
     294           0 :                         setlen = mo_default_set(&set, 0);
     295             :                 } else
     296           0 :                         setlen = default_setlen;
     297             :                 Set = &default_set;
     298             :         }
     299        2149 :         opt *tmp = (opt *) realloc(*Set, (setlen + 1) * sizeof(opt));
     300        2149 :         if (tmp == NULL)
     301             :                 return setlen;
     302        2149 :         *Set = set = tmp;
     303        2149 :         set[setlen].kind = kind;
     304        2149 :         set[setlen].name = strdup(name);
     305        2149 :         set[setlen].value = strdup(value);
     306        2149 :         if (set[setlen].name == NULL || set[setlen].value == NULL) {
     307           0 :                 free(set[setlen].name);
     308           0 :                 free(set[setlen].value);
     309           0 :                 return setlen;
     310             :         }
     311             :         return setlen + 1;
     312             : }
     313             : 
     314             : void
     315         354 : mo_free_options(opt *set, int setlen)
     316             : {
     317         354 :         int i;
     318             : 
     319         354 :         if (set == NULL) {
     320           0 :                 set = default_set;
     321           0 :                 setlen = default_setlen;
     322           0 :                 default_set = NULL;
     323           0 :                 default_setlen = 0;
     324             :         }
     325        4273 :         for (i = 0; i < setlen; i++) {
     326        3919 :                 if (set[i].name)
     327        3919 :                         free(set[i].name);
     328        3919 :                 if (set[i].value)
     329        3919 :                         free(set[i].value);
     330             :         }
     331         354 :         free(set);
     332         354 : }

Generated by: LCOV version 1.14