1 /* 2 * Copyright 2019 Uber Technologies, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 /** @file args.h 17 * @brief Miscellaneous functions and constants. 18 */ 19 20 #ifndef ARGS_H 21 #define ARGS_H 22 23 #include <inttypes.h> 24 #include <stdbool.h> 25 #include <stdio.h> 26 27 #include "utility.h" 28 29 /** Maximum number of names an argument may have. */ 30 #define NUM_ARG_NAMES 2 31 32 /** 33 * An argument accepted by on the command line of an H3 application. Specifies 34 * how the argument is presented, parsed, and where parsed values are stored. 35 */ 36 typedef struct { 37 /** 38 * Both short and long names of the argument. A name may be null, but the 39 * first name must be non-null. 40 */ 41 const char* const names[NUM_ARG_NAMES]; 42 43 /** 44 * If true, this argument must be specified. If the argument is not 45 * specified, argument parsing will fail. 46 */ 47 const bool required; 48 49 /** 50 * Scan format for the argument, which will be passed to sscanf. May be null 51 * to indicate the argument does not take a value. 52 */ 53 const char* const scanFormat; 54 55 /** 56 * Name to present the value as when printing help. 57 */ 58 const char* const valueName; 59 60 /** 61 * Value will be placed here if the argument is present and scanFormat is 62 * not null. 63 */ 64 void* const value; 65 66 /** 67 * Will be set to true if the argument is present. Should be false when 68 * passed in to parseArgs. 69 */ 70 bool found; 71 72 /** 73 * Help text for this argument. 74 */ 75 const char* const helpText; 76 } Arg; 77 78 // prototypes 79 80 int parseArgs(int argc, char* argv[], int numArgs, Arg* args[], 81 const Arg* helpArg, const char* helpText); 82 void printHelp(FILE* out, const char* programName, const char* helpText, 83 int numArgs, Arg* args[], const char* errorMessage, 84 const char* errorDetails); 85 86 int _parseArgsList(int argc, char* argv[], int numArgs, Arg* args[], 87 const Arg* helpArg, const char** errorMessage, 88 const char** errorDetail); 89 90 // common arguments 91 92 #define ARG_HELP \ 93 { .names = {"-h", "--help"}, .helpText = "Show this help message." } 94 #define DEFINE_INDEX_ARG(varName, argName) \ 95 H3Index varName = 0; \ 96 Arg argName = { \ 97 .names = {"-i", "--index"}, \ 98 .scanFormat = "%" PRIx64, \ 99 .valueName = "index", \ 100 .value = &varName, \ 101 .helpText = \ 102 "Index, or not specified to read indexes from standard input."} 103 #define ARG_KML \ 104 { .names = {"-k", "--kml"}, .helpText = "Print output in KML format." } 105 #define DEFINE_KML_NAME_ARG(varName, argName) \ 106 char varName[BUFF_SIZE] = {0}; \ 107 Arg argName = { \ 108 .names = {"--kn", "--kml-name"}, \ 109 .scanFormat = "%255c", /* BUFF_SIZE - 1 */ \ 110 .valueName = "name", \ 111 .value = &varName, \ 112 .helpText = "Text for the KML name tag, if --kml is specified."} 113 #define DEFINE_KML_DESC_ARG(varName, argName) \ 114 char varName[BUFF_SIZE] = {0}; \ 115 Arg argName = { \ 116 .names = {"--kd", "--kml-description"}, \ 117 .scanFormat = "%255c", /* BUFF_SIZE - 1 */ \ 118 .valueName = "description", \ 119 .value = &varName, \ 120 .helpText = \ 121 "Text for the KML description tag, if --kml is specified."} 122 123 #endif 124