/* Copyright (C) 2017-2020, Dirk Krause SPDX-License-Identifier: BSD-3-Clause */ /* WARNING: This file was generated by the dkct program (see http://dktools.sourceforge.net/ for details). Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk4opt07.ctr */ /** @file dk4opt07.c The dk4opt07 module. */ #line 7 "dk4opt07.ctr" #include "dk4conf.h" #include "dk4types.h" #include "dk4error.h" #include "dk4opt.h" #include "dk4maidddi.h" #include "dk4maidddu.h" #include "dk4maiddsz.h" #include "dk4maiddbl.h" #include "dk4strd.h" #include "dk4fput.h" #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif #line 28 "dk4opt07.ctr" static const dkChar * const dk4opt_kwnl[] = { /* 0 */ dkT("\n"), /* 1 */ dkT("ERROR: Option "), /* 2 */ dkT("-"), /* 3 */ dkT("/"), /* 4 */ dkT("--"), /* 5 */ dkT(" requires "), /* 6 */ dkT("boolean "), /* 7 */ dkT("size "), /* 8 */ dkT("integer "), /* 9 */ dkT("unsigned integer "), /* 10 */ dkT("double "), /* 11 */ dkT("string "), /* 12 */ dkT("argument!\n"), /* 13 */ dkT("Illegal argument text: \""), /* 14 */ dkT("\"!\n"), /* 15 */ dkT(": "), /* 16 */ dkT("ERROR: No file names expected!\n"), /* 17 */ dkT("ERROR: Too many file names!\n"), /* 18 */ dkT("ERROR: Illegal option: \""), /* 19 */ dkT("\"!\n"), /* 20 */ dkT("Warning: Option used multiple times: \""), /* 21 */ dkT("\".\n"), /* 22 */ dkT("Warning: Unused argument in option: \""), /* 23 */ dkT("\".\n"), NULL #line 88 "dk4opt07.ctr" }; static void dk4opt_log_1( size_t kwind, const dkChar *progname, int logstderr ) { if (0 != logstderr) { dk4fput_initialize_stderr(); if (NULL != progname) { dk4fputs(progname, stderr, NULL); dk4fputs(dk4opt_kwnl[15], stderr, NULL); } dk4fputs(dk4opt_kwnl[kwind], stderr, NULL); fflush(stderr); } } static void dk4opt_log_3( size_t kwi1, size_t kwi2, const dkChar *vartext, const dkChar *progname, int logstderr ) { if (0 != logstderr) { dk4fput_initialize_stderr(); if (NULL != progname) { dk4fputs(progname, stderr, NULL); dk4fputs(dk4opt_kwnl[15], stderr, NULL); } dk4fputs(dk4opt_kwnl[kwi1], stderr, NULL); if (NULL != vartext) { dk4fputs(vartext, stderr, NULL); } dk4fputs(dk4opt_kwnl[kwi2], stderr, NULL); fflush(stderr); } } static void dk4opt_complain_argument( dk4_option_t *opt, const dkChar *valstr, const dkChar *argv0, int progname, int logstderr ) { #if DK4_USE_ASSERT assert(NULL != opt); #endif if (0 != logstderr) { if ((dkT('\0') != opt->spec.c) || (NULL != opt->spec.longopt)) { dk4fput_initialize_stderr(); if ((0 != progname) && (NULL != argv0)) { dk4fputs(argv0, stderr, NULL); dk4fputs(dk4opt_kwnl[15], stderr, NULL); } dk4fputs(dk4opt_kwnl[1], stderr, NULL); if (dkT('\0') != opt->spec.c) { dk4fputs(dk4opt_kwnl[2], stderr, NULL); dk4fputc(opt->spec.c, stderr, NULL); if (NULL != opt->spec.longopt) { dk4fputs(dk4opt_kwnl[3], stderr, NULL); } } if (NULL != opt->spec.longopt) { dk4fputs(dk4opt_kwnl[4], stderr, NULL); dk4fputs(opt->spec.longopt, stderr, NULL); } dk4fputs(dk4opt_kwnl[5], stderr, NULL); switch (opt->spec.argtype) { case DK4_OPT_ARG_BOOL : { dk4fputs(dk4opt_kwnl[6], stderr, NULL); } break; case DK4_OPT_ARG_SIZE : { dk4fputs(dk4opt_kwnl[7], stderr, NULL); } break; case DK4_OPT_ARG_INT : { dk4fputs(dk4opt_kwnl[8], stderr, NULL); } break; case DK4_OPT_ARG_UNSIGNED : { dk4fputs(dk4opt_kwnl[9], stderr, NULL); } break; case DK4_OPT_ARG_DOUBLE : { dk4fputs(dk4opt_kwnl[10], stderr, NULL); } break; } dk4fputs(dk4opt_kwnl[12], stderr, NULL); if (NULL != valstr) { dk4fputs(dk4opt_kwnl[13], stderr, NULL); dk4fputs(valstr, stderr, NULL); dk4fputs(dk4opt_kwnl[14], stderr, NULL); } fflush(stderr); } } } /** Find first position of equal sign in string. Before calling this function we manually checked there is no equal sign at position 0. @param str String to check. @return Position of first equal sign on success, 0 on error. */ static size_t dk4opt_i_equal_sign_position(const dkChar *str) { size_t back = 0; size_t num = 0; while ((dkT('\0') != *str) && (0 == back)) { if (dkT('=') == *str) { back = num; } else { str++; num++; } } return back; } /** Set argument for one option. @param opt Option to set. @param valstr String containing the value. @param logstderr Flag: Logging to stderr allowed. @param progname Program name or NULL. @return 1 on success, 0 on error. */ static int dk4opt_i_set_value( dk4_option_t *opt, dkChar *valstr, int logstderr, const dkChar *progname ) { const dkChar *ep = NULL; /* First unconvertable char */ double d = 0.0; /* Default double value */ dk4_um_t um = (dk4_um_t)0UL; /* Default unsigned value */ dk4_im_t im = (dk4_im_t)0L; /* Default integer value */ size_t sz = (size_t)0UL; /* Default size value */ int back = 0; /* Result */ #line 249 "dk4opt07.ctr" #if DK4_USE_ASSERT assert(NULL != opt); #endif switch (opt->spec.argtype) { case DK4_OPT_ARG_BOOL : { #line 254 "dk4opt07.ctr" opt->val.b = 0; opt->found = 0; if (0 != dk4str_is_bool(valstr)) { opt->val.b = ((0 != dk4str_is_on(valstr)) ? 1 : 0); opt->found = 1; back = 1; } else { back = dk4ma_input_dk_dec_dk4_im_t(&im, valstr, &ep, 1, NULL); if (0 != back) { opt->val.b = (((dk4_im_t)0L != im) ? 1 : 0); opt->found = 1; } else { /* ERROR: Not a boolean */ dk4opt_complain_argument( opt, valstr, progname, ((NULL != progname) ? 1 : 0), logstderr ); } } } break; case DK4_OPT_ARG_SIZE : { #line 274 "dk4opt07.ctr" opt->val.s = (size_t)0UL; opt->found = 0; back = dk4ma_input_dk_dec_size_t(&sz, valstr, &ep, 1, NULL); if (0 != back) { opt->val.s = sz; opt->found = 1; } else { /* ERROR: Not a size */ dk4opt_complain_argument( opt, valstr, progname, ((NULL != progname) ? 1 : 0), logstderr ); } } break; case DK4_OPT_ARG_INT : { #line 288 "dk4opt07.ctr" opt->val.i = (dk4_im_t)0L; opt->found = 0; back = dk4ma_input_dk_dec_dk4_im_t(&im, valstr, &ep, 1, NULL); if (0 != back) { opt->val.i = im; opt->found = 1; } else { /* ERROR: Not an int */ dk4opt_complain_argument( opt, valstr, progname, ((NULL != progname) ? 1 : 0), logstderr ); } } break; case DK4_OPT_ARG_UNSIGNED : { #line 302 "dk4opt07.ctr" opt->val.u = (dk4_um_t)0UL; opt->found = 0; back = dk4ma_input_dk_dec_dk4_um_t(&um, valstr, &ep, 1, NULL); if (0 != back) { opt->val.u = um; opt->found = 1; } else { /* ERROR: Not an unsigned number */ dk4opt_complain_argument( opt, valstr, progname, ((NULL != progname) ? 1 : 0), logstderr ); } } break; case DK4_OPT_ARG_DOUBLE : { #line 316 "dk4opt07.ctr" opt->val.d = 0.0; opt->found = 0; back = dk4ma_input_dk_double(&d, valstr, &ep, 1, NULL); if (0 != back) { opt->val.d = d; opt->found = 1; } else { /* ERROR: Not a double */ dk4opt_complain_argument( opt, valstr, progname, ((NULL != progname) ? 1 : 0), logstderr ); } } break; case DK4_OPT_ARG_STRING : { #line 330 "dk4opt07.ctr" opt->val.t = valstr; opt->found = 1; if (NULL != valstr) { back = 1; } } break; } #line 335 "dk4opt07.ctr" return back; } int dk4opt_process_argv( dk4_option_t *optptr, size_t szoptptr, int argc, dkChar *argv[], dkChar **filenames, size_t *nfilenames, int progname, int logstderr, dk4_er_t *erp ) { dkChar *curptr = NULL; /* Current argument to process */ dkChar *ocurptr = NULL; /* Original (complete) argument */ size_t fnused = 0; /* Used elements in filenames */ size_t j = 0; /* Option index to test */ size_t eqpos = 0; /* Equal sign position */ int i = 0; /* Current argument index */ int found = 0; /* Flag: current opt found in set */ int res = 0; /* Operation result */ int back = 0; #line 363 "dk4opt07.ctr" #if DK4_USE_ASSERT assert(NULL != optptr); assert(0 < szoptptr); #endif if ((NULL != optptr) && (0 < szoptptr)) { #line 368 "dk4opt07.ctr" for (j = 0; j < szoptptr; j++) { optptr[j].found = 0; optptr[j].val.t = NULL; } if ((0 < argc) && (NULL != argv)) { #line 373 "dk4opt07.ctr" if ((NULL != filenames) && (NULL != nfilenames)) { for (fnused = 0; fnused < *nfilenames; fnused++) { filenames[fnused] = NULL; } fnused = 0; } back = 1; i = 0; if (0 != progname) { i = 1; } while(i < argc) { ocurptr = curptr = argv[i]; #line 384 "dk4opt07.ctr" if (dkT('-') == *curptr) { curptr++; if (dkT('-') == *curptr) { curptr++; if (dkT('\0' != *curptr)) { if (dkT('=') != *curptr) { eqpos = dk4opt_i_equal_sign_position(curptr); found = 0; #line 392 "dk4opt07.ctr" for (j = 0; ((j < szoptptr) && (0 == found)); j++) { if (NULL != optptr[j].spec.longopt) { if (0 != eqpos) { if (eqpos == dk4str_len(optptr[j].spec.longopt)) { res = dk4str_ncmp(curptr,optptr[j].spec.longopt,eqpos); } else { res = 1; } } else { res = dk4str_cmp(curptr, optptr[j].spec.longopt); } if (0 == res) { if (0 != optptr[j].found) { /* WARNING: Option used multiple times */ dk4opt_log_3( 20, 21, ocurptr, ((0 != progname) ? argv[0] : NULL), logstderr ); dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } found = 1; switch (optptr[j].spec.argtype) { case DK4_OPT_ARG_BOOL : case DK4_OPT_ARG_SIZE : case DK4_OPT_ARG_INT : case DK4_OPT_ARG_UNSIGNED : case DK4_OPT_ARG_DOUBLE : case DK4_OPT_ARG_STRING : { if (0 < eqpos) { curptr = &(curptr[eqpos+1]); if (dkT('\0') == *curptr) { curptr = NULL; } } else { curptr = NULL; } if (NULL == curptr) { if (++i < argc) { curptr = argv[i]; } } if (NULL != curptr) { res = dk4opt_i_set_value( &(optptr[j]), curptr, logstderr, ((0 != progname) ? argv[0] : NULL) ); if (0 == res) { back = 0; dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } else { back = 0; /* ERROR: Option required argument */ dk4opt_complain_argument( &(optptr[j]), NULL, argv[0], progname, logstderr ); dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } break; default : { optptr[j].found = 1; if (0 < eqpos) { /* WARNING: Option does not use argument */ dk4opt_log_3( 22, 23, ocurptr, ((0 != progname) ? argv[0] : NULL), logstderr ); } } break; } } } } if (0 == found) { back = 0; /* ERROR: Illegal option */ dk4opt_log_3( 18,19,ocurptr,((0 != progname) ? argv[0] : NULL),logstderr ); dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } else { back = 0; /* ERROR: Long option without name */ dk4opt_log_3( 18, 19, ocurptr, ((0 != progname) ? argv[0] : NULL), logstderr ); dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } else { if ((NULL != filenames) && (NULL != nfilenames)) { if (fnused < *nfilenames) { filenames[fnused++] = ocurptr; } else { back = 0; /* ERROR: Too many file names */ dk4opt_log_1(17,((0 != progname) ? argv[0] : NULL),logstderr); dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } else { back = 0; /*ERROR: No file names expected */ dk4opt_log_1(16, ((0 != progname) ? argv[0] : NULL), logstderr); dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } } else { if (dkT('\0') != *curptr) { found = 0; for (j = 0; ((j < szoptptr) && (0 == found)); j++) { if (optptr[j].spec.c == *curptr) { if (0 != optptr[j].found) { /* WARNING: Option used multiple times */ dk4opt_log_3( 20,21,ocurptr,((0 != progname) ? argv[0] : NULL),logstderr ); } found = 1; switch(optptr[j].spec.argtype) { case DK4_OPT_ARG_BOOL : case DK4_OPT_ARG_SIZE : case DK4_OPT_ARG_INT : case DK4_OPT_ARG_UNSIGNED : case DK4_OPT_ARG_DOUBLE : case DK4_OPT_ARG_STRING : { curptr++; if (dkT('\0') == *curptr) { curptr = NULL; if (++i < argc) { curptr = argv[i]; } } if (NULL != curptr) { res = dk4opt_i_set_value( &(optptr[j]), curptr, logstderr, ((0 != progname) ? argv[0] : NULL) ); if (0 == res) { back = 0; dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } else { back = 0; /* ERROR: Option requires argument */ dk4opt_complain_argument( &(optptr[j]), NULL, argv[0], progname, logstderr ); dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } break; default : { optptr[j].found = 1; } break; } } } if (0 == found) { back = 0; /* ERROR: Option not found in specification */ dk4opt_log_3( 18, 19, ocurptr, ((0 != progname) ? argv[0] : NULL), logstderr ); dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } else { if ((NULL != filenames) && (NULL != nfilenames)) { if (fnused < *nfilenames) { filenames[fnused++] = ocurptr; } else { back = 0; /* ERROR: Too many file names */ dk4opt_log_1(17,((0 != progname) ? argv[0] : NULL),logstderr); dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } else { back = 0; /* ERROR: No file names expected */ dk4opt_log_1(16, ((0 != progname) ? argv[0] : NULL), logstderr); dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } } } } else { if ((NULL != filenames) && (NULL != nfilenames)) { if (fnused < *nfilenames) { filenames[fnused++] = curptr; } else { back = 0; /* ERROR: Too many file names */ dk4opt_log_1(17, ((0 != progname) ? argv[0] : NULL), logstderr); dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); } } else { back = 0; /* ERROR: No file names expected */ dk4opt_log_1(16, ((0 != progname) ? argv[0] : NULL), logstderr); dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); } } i++; } } else { /* ERROR: Arguments */ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } } else { /* ERROR: Arguments */ dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } if (NULL != nfilenames) { *nfilenames = fnused; } #line 603 "dk4opt07.ctr" return back; }