UNIXworkcode

/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2018 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "optparser.h" #include "sopt.h" #include <cx/hash_map.h> void cmd_args_free(CmdArgs *args) { if(args) { cxMapDestroy(args->options); if(args->argv) { free(args->argv); } free(args); } } static void cmd_map_put(CxMap *map, const char *key, const void *value) { cxMapPut(map, key, (void*)value); } CmdArgs* cmd_parse_args(int argc, char **argv) { CmdArgs *a = malloc(sizeof(CmdArgs)); a->options = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 16); a->argv = argc > 0 ? calloc(argc, sizeof(char*)) : NULL; a->argc = 0; const char *NOARG = ""; char *option = NULL; char optchar = 0; int optterminated = 0; for(int i=0;i<argc;i++) { char *arg = argv[i]; size_t len = strlen(arg); if(len == 2 && arg[0] == '-' && arg[1] == '-') { optterminated = 1; } else if(!optterminated && len > 1 && arg[0] == '-') { // argument is in next arg but starts with a dash // we assume this is not intended and consider this an error if(option) { fprintf(stderr, "Missing argument for option -%c\n\n", optchar); cmd_args_free(a); return NULL; } for(int c=1;c<len;c++) { // argument is in the same arg if(option) { cxMapPut(a->options, cx_hash_key_str(option), &arg[c]); option = NULL; break; } switch(arg[c]) { default: { fprintf(stderr, "Unknown option -%c\n\n", arg[c]); cmd_args_free(a); return NULL; } case 'v': { cmd_map_put(a->options, "verbose", NOARG); break; } case 'k': { option = "key"; optchar = 'k'; break; } case 'p': { cmd_map_put(a->options, "plain", NOARG); break; } case 'c': { cmd_map_put(a->options, "crypt", NOARG); break; } case 'a': { cmd_map_put(a->options, "all", NOARG); break; } case 'l': { cmd_map_put(a->options, "list", NOARG); break; } case 'd': { cmd_map_put(a->options, "date", NOARG); break; } case 't': { cmd_map_put(a->options, "type", NOARG); break; } case 'R': { cmd_map_put(a->options, "recursive", NOARG); break; } case 'O': { cmd_map_put(a->options, "override", NOARG); break; } case 'i': { cmd_map_put(a->options, "insecure", NOARG); break; } case 'N': { cmd_map_put(a->options, "noinput", NOARG); break; } case 'e': { cmd_map_put(a->options, "extended", NOARG); break; } case 'x': { cmd_map_put(a->options, "xml", NOARG); break; } case 'F': { option = "finfo"; optchar = 'F'; break; } case 'S': { // undocumented hidden feature cmd_map_put(a->options, "structure", NOARG); break; } case 'K': { cmd_map_put(a->options, "keep", NOARG); break; } case 'o': { option = "output"; optchar = 'o'; break; } case 'u': { option = "update"; optchar = 'u'; break; } case 'n': { option = "namespace"; optchar = 'n'; break; } case 'L': { option = "lock"; optchar = 'L'; break; } case 'T': { option = "timeout"; optchar = 'T'; break; } /* case 'P': { option = "progressfile"; optchar = 'F'; break; } */ case 'V': { option = "version"; optchar = 'V'; break; } } } } else if(option) { cmd_map_put(a->options, option, arg); option = NULL; } else { a->argv[a->argc++] = arg; } } if(option) { fprintf(stderr, "Missing argument for option -%c\n\n", optchar); cmd_args_free(a); return NULL; } return a; } char* cmd_getoption(CmdArgs *arg, const char *name) { return cxMapGet(arg->options, cx_hash_key_str(name)); }