forked from cosmonaut/wraith-lang
				
			input option parsing
							parent
							
								
									ca1835f98d
								
							
						
					
					
						commit
						272c809c69
					
				|  | @ -23,8 +23,8 @@ find_package(LLVM) | |||
| 
 | ||||
| include_directories(${CMAKE_SOURCE_DIR}) | ||||
| 
 | ||||
| BISON_TARGET(Parser wraith.y ${CMAKE_CURRENT_BINARY_DIR}/y.tab.c COMPILE_FLAGS "-d -v -t") | ||||
| FLEX_TARGET(Scanner wraith.lex ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.c) | ||||
| BISON_TARGET(Parser generators/wraith.y ${CMAKE_CURRENT_BINARY_DIR}/y.tab.c COMPILE_FLAGS "-d -v -t") | ||||
| FLEX_TARGET(Scanner generators/wraith.lex ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.c) | ||||
| 
 | ||||
| ADD_FLEX_BISON_DEPENDENCY(Scanner Parser) | ||||
| 
 | ||||
|  | @ -32,11 +32,21 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}) | |||
| 
 | ||||
| add_executable( | ||||
|     wraith | ||||
|     ast.c | ||||
|     stack.c | ||||
| 	# Libs | ||||
| 	lib/dropt/dropt.h | ||||
| 	lib/dropt/dropt_string.h | ||||
| 	lib/dropt/dropt.c | ||||
| 	lib/dropt/dropt_string.c | ||||
| 	lib/dropt/dropt_handlers.c | ||||
| 	# Source | ||||
| 	src/ast.h | ||||
| 	src/stack.h | ||||
|     src/ast.c | ||||
|     src/stack.c | ||||
| 	src/compiler.c | ||||
| 	# Generated code | ||||
|     ${BISON_Parser_OUTPUTS} | ||||
|     ${FLEX_Scanner_OUTPUTS} | ||||
|     compiler.c | ||||
| ) | ||||
| 
 | ||||
| if(NOT MSVC) | ||||
|  |  | |||
|  | @ -1,11 +1,11 @@ | |||
| %code requires { | ||||
|     #include "stack.h" | ||||
|     #include "../src/stack.h" | ||||
| } | ||||
| 
 | ||||
| %{ | ||||
| #include <stdio.h> | ||||
| #include "ast.h" | ||||
| #include "stack.h" | ||||
| #include "../src/ast.h" | ||||
| #include "../src/stack.h" | ||||
| 
 | ||||
| void yyerror(FILE *fp, Stack *stack, char *s) | ||||
| { | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,272 @@ | |||
| /** dropt.h
 | ||||
|   * | ||||
|   * A deliberately rudimentary command-line option parser. | ||||
|   * | ||||
|   * Version 2.0.0 | ||||
|   * | ||||
|   * Copyright (C) 2006-2018 James D. Lin <jamesdlin@berkeley.edu> | ||||
|   * | ||||
|   * The latest version of this file can be downloaded from: | ||||
|   * <http://www.taenarum.com/software/dropt/>
 | ||||
|   * | ||||
|   * This software is provided 'as-is', without any express or implied | ||||
|   * warranty.  In no event will the authors be held liable for any damages | ||||
|   * arising from the use of this software. | ||||
|   * | ||||
|   * Permission is granted to anyone to use this software for any purpose, | ||||
|   * including commercial applications, and to alter it and redistribute it | ||||
|   * freely, subject to the following restrictions: | ||||
|   * | ||||
|   * 1. The origin of this software must not be misrepresented; you must not | ||||
|   *    claim that you wrote the original software. If you use this software | ||||
|   *    in a product, an acknowledgment in the product documentation would be | ||||
|   *    appreciated but is not required. | ||||
|   * | ||||
|   * 2. Altered source versions must be plainly marked as such, and must not be | ||||
|   *    misrepresented as being the original software. | ||||
|   * | ||||
|   * 3. This notice may not be removed or altered from any source distribution. | ||||
|   */ | ||||
| 
 | ||||
| #ifndef DROPT_H | ||||
| #define DROPT_H | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <wchar.h> | ||||
| 
 | ||||
| #if __STDC_VERSION__ >= 199901L | ||||
|     #include <stdint.h> | ||||
|     typedef uintptr_t dropt_uintptr; | ||||
| #else | ||||
|     typedef size_t dropt_uintptr; | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #ifndef DROPT_USE_WCHAR | ||||
| #if defined _UNICODE && (defined _MSC_VER || defined DROPT_NO_STRING_BUFFERS) | ||||
| #define DROPT_USE_WCHAR 1 | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifdef DROPT_USE_WCHAR | ||||
|     /* This may be used for both char and string literals. */ | ||||
|     #define DROPT_TEXT_LITERAL(s) L ## s | ||||
| 
 | ||||
|     typedef wchar_t dropt_char; | ||||
| #else | ||||
|     #define DROPT_TEXT_LITERAL(s) s | ||||
| 
 | ||||
|     typedef char dropt_char; | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| enum | ||||
| { | ||||
|     /* Errors in the range [0x00, 0x7F] are reserved for dropt. */ | ||||
|     dropt_error_none, | ||||
|     dropt_error_unknown, | ||||
|     dropt_error_bad_configuration, | ||||
|     dropt_error_insufficient_memory, | ||||
|     dropt_error_invalid_option, | ||||
|     dropt_error_insufficient_arguments, | ||||
|     dropt_error_mismatch, | ||||
|     dropt_error_overflow, | ||||
|     dropt_error_underflow, | ||||
| 
 | ||||
|     /* Errors in the range [0x80, 0xFFFF] are free for clients to use. */ | ||||
|     dropt_error_custom_start = 0x80, | ||||
|     dropt_error_custom_last = 0xFFFF | ||||
| }; | ||||
| typedef unsigned int dropt_error; | ||||
| 
 | ||||
| typedef unsigned char dropt_bool; | ||||
| 
 | ||||
| /* Opaque. */ | ||||
| typedef struct dropt_context dropt_context; | ||||
| 
 | ||||
| /* Forward declarations. */ | ||||
| typedef struct dropt_option dropt_option; | ||||
| 
 | ||||
| 
 | ||||
| /** `dropt_option_handler_func` callbacks are responsible for parsing
 | ||||
|   * individual options and storing the parsed value. | ||||
|   * | ||||
|   * `dropt_option_handler_decl` may be used for declaring the callback | ||||
|   * functions (see the stock option handlers below for examples). | ||||
|   * `dropt_option_handler_func` is the actual function pointer type. | ||||
|   * | ||||
|   * `option` points to the `dropt_option` entry that matched the option | ||||
|   * supplied by the user.  This will never be `NULL` when dropt invokes the | ||||
|   * handler. | ||||
|   * | ||||
|   * `optionArgument` will be `NULL` if no argument is specified for an option. | ||||
|   * It will be the empty string if the user explicitly passed an empty string | ||||
|   * as the argument (e.g. `--option=""`). | ||||
|   * | ||||
|   * An option that doesn't expect an argument still can receive a non-null | ||||
|   * value for `optionArgument` if the user explicitly specified one (e.g. | ||||
|   * `--option=arg`). | ||||
|   * | ||||
|   * If the option's argument is optional, the handler might be called twice: | ||||
|   * once with a candidate argument, and if that argument is rejected by the | ||||
|   * handler, again with no argument.  Handlers should be aware of this if they | ||||
|   * have side-effects. | ||||
|   * | ||||
|   * `dest` is the client-specified pointer to a variable for the handler to | ||||
|   * modify. | ||||
|   */ | ||||
| typedef dropt_error dropt_option_handler_decl(dropt_context* context, | ||||
|                                               const dropt_option* option, | ||||
|                                               const dropt_char* optionArgument, | ||||
|                                               void* dest); | ||||
| typedef dropt_option_handler_decl* dropt_option_handler_func; | ||||
| 
 | ||||
| /** `dropt_error_handler_func` callbacks are responsible for generating error
 | ||||
|   * messages.  The returned string must be allocated on the heap and must be | ||||
|   * freeable with `free()`. | ||||
|   */ | ||||
| typedef dropt_char* (*dropt_error_handler_func)(dropt_error error, | ||||
|                                                 const dropt_char* optionName, | ||||
|                                                 const dropt_char* optionArgument, | ||||
|                                                 void* handlerData); | ||||
| 
 | ||||
| /** `dropt_strncmp_func` callbacks allow callers to provide their own (possibly
 | ||||
|   * case-insensitive) string comparison function. | ||||
|   */ | ||||
| typedef int (*dropt_strncmp_func)(const dropt_char* s, const dropt_char* t, | ||||
|                                   size_t n); | ||||
| 
 | ||||
| 
 | ||||
| /** Properties defining each option:
 | ||||
|   * | ||||
|   * short_name: | ||||
|   *     The option's short name (e.g. the 'h' in `-h`). | ||||
|   *     Use '\0' if the option has no short name. | ||||
|   * | ||||
|   * long_name: | ||||
|   *     The option's long name (e.g. "help" in `--help`). | ||||
|   *     Use `NULL` if the option has no long name. | ||||
|   * | ||||
|   * description: | ||||
|   *     The description shown when generating help. | ||||
|   *     May be `NULL` for undocumented options. | ||||
|   * | ||||
|   * arg_description: | ||||
|   *     The description for the option's argument (e.g. `--option=argument` or | ||||
|   *     `--option argument`), printed when generating help. | ||||
|   *     Use `NULL` if the option does not take an argument. | ||||
|   * | ||||
|   * handler: | ||||
|   *     The handler callback and data invoked in response to encountering the | ||||
|   *     option. | ||||
|   * | ||||
|   * dest: | ||||
|   *     The address of a variable for the handler to modify, if necessary. | ||||
|   * | ||||
|   * attr: | ||||
|   *     Miscellaneous attributes.  See below. | ||||
|   * | ||||
|   * extra_data: | ||||
|   *     Additional callback data for the handler. | ||||
|   */ | ||||
| struct dropt_option | ||||
| { | ||||
|     dropt_char short_name; | ||||
|     const dropt_char* long_name; | ||||
|     const dropt_char* description; | ||||
|     const dropt_char* arg_description; | ||||
|     dropt_option_handler_func handler; | ||||
|     void* dest; | ||||
|     unsigned int attr; | ||||
|     dropt_uintptr extra_data; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /** Bitwise flags for option attributes:
 | ||||
|   * | ||||
|   * dropt_attr_halt: | ||||
|   *     Stop processing when this option is encountered. | ||||
|   * | ||||
|   * dropt_attr_hidden: | ||||
|   *     Don't list the option when generating help.  Use this for undocumented | ||||
|   *     options. | ||||
|   * | ||||
|   * dropt_attr_optional_val: | ||||
|   *     The option's argument is optional.  If an option has this attribute, | ||||
|   *     the handler callback may be invoked twice (once with a potential | ||||
|   *     argument, and if that fails, again with a `NULL` argument). | ||||
|   */ | ||||
| enum | ||||
| { | ||||
|     dropt_attr_halt = (1 << 0), | ||||
|     dropt_attr_hidden = (1 << 1), | ||||
|     dropt_attr_optional_val = (1 << 2) | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| typedef struct dropt_help_params | ||||
| { | ||||
|     unsigned int indent; | ||||
|     unsigned int description_start_column; | ||||
|     dropt_bool blank_lines_between_options; | ||||
| } dropt_help_params; | ||||
| 
 | ||||
| 
 | ||||
| dropt_context* dropt_new_context(const dropt_option* options); | ||||
| void dropt_free_context(dropt_context* context); | ||||
| 
 | ||||
| const dropt_option* dropt_get_options(const dropt_context* context); | ||||
| 
 | ||||
| void dropt_set_error_handler(dropt_context* context, | ||||
|                              dropt_error_handler_func handler, | ||||
|                              void* handlerData); | ||||
| void dropt_set_strncmp(dropt_context* context, dropt_strncmp_func cmp); | ||||
| 
 | ||||
| /* Use this only for backward compatibility purposes. */ | ||||
| void dropt_allow_concatenated_arguments(dropt_context* context, | ||||
|                                         dropt_bool allow); | ||||
| 
 | ||||
| dropt_char** dropt_parse(dropt_context* context, int argc, dropt_char** argv); | ||||
| 
 | ||||
| dropt_error dropt_get_error(const dropt_context* context); | ||||
| void dropt_get_error_details(const dropt_context* context, | ||||
|                              dropt_char** optionName, | ||||
|                              dropt_char** optionArgument); | ||||
| const dropt_char* dropt_get_error_message(dropt_context* context); | ||||
| void dropt_clear_error(dropt_context* context); | ||||
| 
 | ||||
| #ifndef DROPT_NO_STRING_BUFFERS | ||||
| dropt_char* dropt_default_error_handler(dropt_error error, | ||||
|                                         const dropt_char* optionName, | ||||
|                                         const dropt_char* optionArgument); | ||||
| 
 | ||||
| void dropt_init_help_params(dropt_help_params* helpParams); | ||||
| dropt_char* dropt_get_help(const dropt_context* context, | ||||
|                            const dropt_help_params* helpParams); | ||||
| void dropt_print_help(FILE* f, const dropt_context* context, | ||||
|                       const dropt_help_params* helpParams); | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* Stock option handlers for common types. */ | ||||
| dropt_option_handler_decl dropt_handle_bool; | ||||
| dropt_option_handler_decl dropt_handle_verbose_bool; | ||||
| dropt_option_handler_decl dropt_handle_int; | ||||
| dropt_option_handler_decl dropt_handle_uint; | ||||
| dropt_option_handler_decl dropt_handle_double; | ||||
| dropt_option_handler_decl dropt_handle_string; | ||||
| dropt_option_handler_decl dropt_handle_const; | ||||
| 
 | ||||
| #define DROPT_MISUSE(message) dropt_misuse(message, __FILE__, __LINE__) | ||||
| void dropt_misuse(const char* message, const char* filename, int line); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } /* extern "C" */ | ||||
| #endif | ||||
| 
 | ||||
| #endif /* DROPT_H */ | ||||
|  | @ -0,0 +1,520 @@ | |||
| /** dropt_handlers.c
 | ||||
|   * | ||||
|   * Default type handlers for dropt. | ||||
|   * | ||||
|   * Copyright (C) 2006-2018 James D. Lin <jamesdlin@berkeley.edu> | ||||
|   * | ||||
|   * The latest version of this file can be downloaded from: | ||||
|   * <http://www.taenarum.com/software/dropt/>
 | ||||
|   * | ||||
|   * This software is provided 'as-is', without any express or implied | ||||
|   * warranty.  In no event will the authors be held liable for any damages | ||||
|   * arising from the use of this software. | ||||
|   * | ||||
|   * Permission is granted to anyone to use this software for any purpose, | ||||
|   * including commercial applications, and to alter it and redistribute it | ||||
|   * freely, subject to the following restrictions: | ||||
|   * | ||||
|   * 1. The origin of this software must not be misrepresented; you must not | ||||
|   *    claim that you wrote the original software. If you use this software | ||||
|   *    in a product, an acknowledgment in the product documentation would be | ||||
|   *    appreciated but is not required. | ||||
|   * | ||||
|   * 2. Altered source versions must be plainly marked as such, and must not be | ||||
|   *    misrepresented as being the original software. | ||||
|   * | ||||
|   * 3. This notice may not be removed or altered from any source distribution. | ||||
|   */ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <limits.h> | ||||
| #include <float.h> | ||||
| #include <errno.h> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| #include "dropt.h" | ||||
| #include "dropt_string.h" | ||||
| 
 | ||||
| 
 | ||||
| #define CONCAT(s, t) s ## t | ||||
| #define XCONCAT(s, t) CONCAT(s, t) | ||||
| 
 | ||||
| #define STATIC_ASSERT(cond) \ | ||||
|   enum { XCONCAT(static_assert_line_,  __LINE__) = 1 / ((cond) != 0) } | ||||
| 
 | ||||
| #define ABS(x) (((x) < 0) ? -(x) : (x)) | ||||
| 
 | ||||
| typedef enum { false, true } bool; | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_handle_bool
 | ||||
|   * | ||||
|   *     Stores a boolean value parsed from the given string if possible. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN/OUT context    : The options context. | ||||
|   *     IN option         : The matched option.  For more information, see | ||||
|   *                         `dropt_option_handler_decl`. | ||||
|   *     IN optionArgument : A string representing a boolean value (0 or 1). | ||||
|   *                         If `NULL`, the boolean value is assumed to be true. | ||||
|   *     OUT dest          : A `dropt_bool*`. | ||||
|   *                         On success, set to the interpreted boolean value. | ||||
|   *                         On error, left untouched. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     dropt_error_none | ||||
|   *     dropt_error_unknown | ||||
|   *     dropt_error_bad_configuration | ||||
|   *     dropt_error_mismatch | ||||
|   */ | ||||
| dropt_error | ||||
| dropt_handle_bool(dropt_context* context, | ||||
|                   const dropt_option* option, | ||||
|                   const dropt_char* optionArgument, | ||||
|                   void* dest) | ||||
| { | ||||
|     dropt_error err = dropt_error_none; | ||||
|     bool val = false; | ||||
|     dropt_bool* out = dest; | ||||
| 
 | ||||
|     if (out == NULL) | ||||
|     { | ||||
|         DROPT_MISUSE("No handler destination specified."); | ||||
|         err = dropt_error_bad_configuration; | ||||
|     } | ||||
|     else if (optionArgument == NULL) | ||||
|     { | ||||
|         /* No explicit argument implies that the option is being turned on. */ | ||||
|         val = true; | ||||
|     } | ||||
|     else if (optionArgument[0] == DROPT_TEXT_LITERAL('\0')) | ||||
|     { | ||||
|         err = dropt_error_mismatch; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         unsigned int i = 0; | ||||
|         err = dropt_handle_uint(context, option, optionArgument, &i); | ||||
|         if (err == dropt_error_none) | ||||
|         { | ||||
|             switch (i) | ||||
|             { | ||||
|                 case 0: | ||||
|                     val = false; | ||||
|                     break; | ||||
|                 case 1: | ||||
|                     val = true; | ||||
|                     break; | ||||
|                 default: | ||||
|                     err = dropt_error_mismatch; | ||||
|                     break; | ||||
|             } | ||||
|         } | ||||
|         else if (err == dropt_error_overflow) | ||||
|         { | ||||
|             err = dropt_error_mismatch; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (err == dropt_error_none) { *out = val; } | ||||
|     return err; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_handle_verbose_bool
 | ||||
|   * | ||||
|   *     Like `dropt_handle_bool` but accepts "true" and "false" string values. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN/OUT context    : The options context. | ||||
|   *     IN option         : The matched option.  For more information, see | ||||
|   *                         `dropt_option_handler_decl`. | ||||
|   *     IN optionArgument : A string representing a boolean value. | ||||
|   *                         If `NULL`, the boolean value is assumed to be true. | ||||
|   *     OUT dest          : A `dropt_bool*`. | ||||
|   *                         On success, set to the interpreted boolean value. | ||||
|   *                         On error, left untouched. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     See dropt_handle_bool. | ||||
|   */ | ||||
| dropt_error | ||||
| dropt_handle_verbose_bool(dropt_context* context, | ||||
|                           const dropt_option* option, | ||||
|                           const dropt_char* optionArgument, | ||||
|                           void* dest) | ||||
| { | ||||
|     dropt_error err = dropt_handle_bool(context, option, optionArgument, dest); | ||||
|     if (err == dropt_error_mismatch) | ||||
|     { | ||||
|         bool val = false; | ||||
|         dropt_bool* out = dest; | ||||
| 
 | ||||
|         /* `dropt_handle_bool` already checks for this. */ | ||||
|         assert(out != NULL); | ||||
| 
 | ||||
|         if (dropt_stricmp(optionArgument, DROPT_TEXT_LITERAL("false")) == 0) | ||||
|         { | ||||
|             val = false; | ||||
|             err = dropt_error_none; | ||||
|         } | ||||
|         else if (dropt_stricmp(optionArgument, DROPT_TEXT_LITERAL("true")) == 0) | ||||
|         { | ||||
|             val = true; | ||||
|             err = dropt_error_none; | ||||
|         } | ||||
| 
 | ||||
|         if (err == dropt_error_none) { *out = val; } | ||||
|     } | ||||
|     return err; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_handle_int
 | ||||
|   * | ||||
|   *     Stores an integer parsed from the given string. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN/OUT context    : The options context. | ||||
|   *     IN option         : The matched option.  For more information, see | ||||
|   *                         `dropt_option_handler_decl`. | ||||
|   *     IN optionArgument : A string representing a base-10 integer. | ||||
|   *                         If `NULL`, returns | ||||
|   *                           `dropt_error_insufficient_arguments`. | ||||
|   *     OUT dest          : An `int*`. | ||||
|   *                         On success, set to the interpreted integer. | ||||
|   *                         On error, left untouched. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     dropt_error_none | ||||
|   *     dropt_error_unknown | ||||
|   *     dropt_error_bad_configuration | ||||
|   *     dropt_error_insufficient_arguments | ||||
|   *     dropt_error_mismatch | ||||
|   *     dropt_error_overflow | ||||
|   */ | ||||
| dropt_error | ||||
| dropt_handle_int(dropt_context* context, | ||||
|                  const dropt_option* option, | ||||
|                  const dropt_char* optionArgument, | ||||
|                  void* dest) | ||||
| { | ||||
|     dropt_error err = dropt_error_none; | ||||
|     int val = 0; | ||||
|     int* out = dest; | ||||
| 
 | ||||
|     if (out == NULL) | ||||
|     { | ||||
|         DROPT_MISUSE("No handler destination specified."); | ||||
|         err = dropt_error_bad_configuration; | ||||
|     } | ||||
|     else if (   optionArgument == NULL | ||||
|              || optionArgument[0] == DROPT_TEXT_LITERAL('\0')) | ||||
|     { | ||||
|         err = dropt_error_insufficient_arguments; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         dropt_char* end; | ||||
|         long n; | ||||
|         errno = 0; | ||||
|         n = dropt_strtol(optionArgument, &end, 10); | ||||
| 
 | ||||
|         /* Check that we matched at least one digit.
 | ||||
|          * (`strtol`/`strtoul` will return 0 if fed a string with no digits.) | ||||
|          */ | ||||
|         if (*end == DROPT_TEXT_LITERAL('\0') && end > optionArgument) | ||||
|         { | ||||
|             if (errno == ERANGE || n < INT_MIN || n > INT_MAX) | ||||
|             { | ||||
|                 err = dropt_error_overflow; | ||||
|                 val = (n < 0) ? INT_MIN : INT_MAX; | ||||
|             } | ||||
|             else if (errno == 0) | ||||
|             { | ||||
|                 val = (int) n; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 err = dropt_error_unknown; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             err = dropt_error_mismatch; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (err == dropt_error_none) { *out = val; } | ||||
|     return err; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_handle_uint
 | ||||
|   * | ||||
|   *     Stores an unsigned integer parsed from the given string. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN/OUT context    : The options context. | ||||
|   *     IN option         : The matched option.  For more information, see | ||||
|   *                         `dropt_option_handler_decl`. | ||||
|   *     IN optionArgument : A string representing an unsigned base-10 integer. | ||||
|   *                         If `NULL`, returns | ||||
|   *                           `dropt_error_insufficient_arguments`. | ||||
|   *     IN option         : The matched option.  For more information, see | ||||
|   *                         dropt_option_handler_decl. | ||||
|   *     OUT dest          : An `unsigned int*`. | ||||
|   *                         On success, set to the interpreted integer. | ||||
|   *                         On error, left untouched. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     dropt_error_none | ||||
|   *     dropt_error_unknown | ||||
|   *     dropt_error_bad_configuration | ||||
|   *     dropt_error_insufficient_arguments | ||||
|   *     dropt_error_mismatch | ||||
|   *     dropt_error_overflow | ||||
|   */ | ||||
| dropt_error | ||||
| dropt_handle_uint(dropt_context* context, | ||||
|                   const dropt_option* option, | ||||
|                   const dropt_char* optionArgument, | ||||
|                   void* dest) | ||||
| { | ||||
|     dropt_error err = dropt_error_none; | ||||
|     int val = 0; | ||||
|     unsigned int* out = dest; | ||||
| 
 | ||||
|     if (out == NULL) | ||||
|     { | ||||
|         DROPT_MISUSE("No handler destination specified."); | ||||
|         err = dropt_error_bad_configuration; | ||||
|     } | ||||
|     else if (   optionArgument == NULL | ||||
|              || optionArgument[0] == DROPT_TEXT_LITERAL('\0')) | ||||
|     { | ||||
|         err = dropt_error_insufficient_arguments; | ||||
|     } | ||||
|     else if (optionArgument[0] == DROPT_TEXT_LITERAL('-')) | ||||
|     { | ||||
|         err = dropt_error_mismatch; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         dropt_char* end; | ||||
|         unsigned long n; | ||||
|         errno = 0; | ||||
|         n = dropt_strtoul(optionArgument, &end, 10); | ||||
| 
 | ||||
|         /* Check that we matched at least one digit.
 | ||||
|          * (`strtol`/`strtoul` will return 0 if fed a string with no digits.) | ||||
|          */ | ||||
|         if (*end == DROPT_TEXT_LITERAL('\0') && end > optionArgument) | ||||
|         { | ||||
|             if (errno == ERANGE || n > UINT_MAX) | ||||
|             { | ||||
|                 err = dropt_error_overflow; | ||||
|                 val = UINT_MAX; | ||||
|             } | ||||
|             else if (errno == 0) | ||||
|             { | ||||
|                 val = (unsigned int) n; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 err = dropt_error_unknown; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             err = dropt_error_mismatch; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (err == dropt_error_none) { *out = val; } | ||||
|     return err; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_handle_double
 | ||||
|   * | ||||
|   *     Stores a `double` parsed from the given string. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN/OUT context    : The options context. | ||||
|   *     IN option         : The matched option.  For more information, see | ||||
|   *                         `dropt_option_handler_decl`. | ||||
|   *     IN optionArgument : A string representing a base-10 floating-point | ||||
|   *                           number. | ||||
|   *                         If `NULL`, returns | ||||
|   *                           `dropt_error_insufficient_arguments`. | ||||
|   *     OUT dest          : A `double*`. | ||||
|   *                         On success, set to the interpreted `double`. | ||||
|   *                         On error, left untouched. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     dropt_error_none | ||||
|   *     dropt_error_unknown | ||||
|   *     dropt_error_bad_configuration | ||||
|   *     dropt_error_insufficient_arguments | ||||
|   *     dropt_error_mismatch | ||||
|   *     dropt_error_overflow | ||||
|   *     dropt_error_underflow | ||||
|   */ | ||||
| dropt_error | ||||
| dropt_handle_double(dropt_context* context, | ||||
|                     const dropt_option* option, | ||||
|                     const dropt_char* optionArgument, | ||||
|                     void* dest) | ||||
| { | ||||
|     dropt_error err = dropt_error_none; | ||||
|     double val = 0.0; | ||||
|     double* out = dest; | ||||
| 
 | ||||
|     if (out == NULL) | ||||
|     { | ||||
|         DROPT_MISUSE("No handler destination specified."); | ||||
|         err = dropt_error_bad_configuration; | ||||
|     } | ||||
|     else if (   optionArgument == NULL | ||||
|              || optionArgument[0] == DROPT_TEXT_LITERAL('\0')) | ||||
|     { | ||||
|         err = dropt_error_insufficient_arguments; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         dropt_char* end; | ||||
|         errno = 0; | ||||
|         val = dropt_strtod(optionArgument, &end); | ||||
| 
 | ||||
|         /* Check that we matched at least one digit.
 | ||||
|          * (`strtod` will return 0 if fed a string with no digits.) | ||||
|          */ | ||||
|         if (*end == DROPT_TEXT_LITERAL('\0') && end > optionArgument) | ||||
|         { | ||||
|             if (errno == ERANGE) | ||||
|             { | ||||
|                 /* Note that setting `errno` to `ERANGE` for underflow errors
 | ||||
|                  * is implementation-defined behavior, but glibc, BSD's | ||||
|                  * libc, and Microsoft's CRT all have implementations of | ||||
|                  * `strtod` documented to return 0 and to set `errno` to | ||||
|                  * `ERANGE` for such cases. | ||||
|                  */ | ||||
|                 err = (ABS(val) <= DBL_MIN) | ||||
|                       ? dropt_error_underflow | ||||
|                       : dropt_error_overflow; | ||||
|             } | ||||
|             else if (errno != 0) | ||||
|             { | ||||
|                 err = dropt_error_unknown; | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             err = dropt_error_mismatch; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (err == dropt_error_none) { *out = val; } | ||||
|     return err; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_handle_string
 | ||||
|   * | ||||
|   *     Stores a string. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN/OUT context    : The options context. | ||||
|   *     IN option         : The matched option.  For more information, see | ||||
|   *                         `dropt_option_handler_decl`. | ||||
|   *     IN optionArgument : A string. | ||||
|   *                         If `NULL`, returns | ||||
|   *                           `dropt_error_insufficient_arguments`. | ||||
|   *     OUT dest          : A `dropt_char**`. | ||||
|   *                         On success, set to the input string.  The string is | ||||
|   *                           NOT copied from the original `argv` array, so do | ||||
|   *                           not free it. | ||||
|   *                         On error, left untouched. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     dropt_error_none | ||||
|   *     dropt_error_bad_configuration | ||||
|   *     dropt_error_insufficient_arguments | ||||
|   */ | ||||
| dropt_error | ||||
| dropt_handle_string(dropt_context* context, | ||||
|                     const dropt_option* option, | ||||
|                     const dropt_char* optionArgument, | ||||
|                     void* dest) | ||||
| { | ||||
|     dropt_error err = dropt_error_none; | ||||
|     const dropt_char** out = dest; | ||||
| 
 | ||||
|     if (out == NULL) | ||||
|     { | ||||
|         DROPT_MISUSE("No handler destination specified."); | ||||
|         err = dropt_error_bad_configuration; | ||||
|     } | ||||
|     else if (optionArgument == NULL) | ||||
|     { | ||||
|         err = dropt_error_insufficient_arguments; | ||||
|     } | ||||
| 
 | ||||
|     if (err == dropt_error_none) { *out = optionArgument; } | ||||
|     return err; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_handle_const
 | ||||
|   * | ||||
|   *     Stores a predefined value.  This can be used to set a single variable | ||||
|   *     to different values in response to different boolean-like command-line | ||||
|   *     options. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN/OUT context    : The options context. | ||||
|   *     IN option         : The matched option.  For more information, see | ||||
|   *                         `dropt_option_handler_decl`. | ||||
|   *     IN optionArgument : Must be `NULL`. | ||||
|   *     OUT dest          : A `dropt_uintptr*`. | ||||
|   *                         On success, set to the constant value specified by | ||||
|   *                           `option->extra_data`. | ||||
|   *                         On error, left untouched. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     dropt_error_none | ||||
|   *     dropt_error_bad_configuration | ||||
|   *     dropt_error_mismatch | ||||
|   */ | ||||
| 
 | ||||
| dropt_error | ||||
| dropt_handle_const(dropt_context* context, | ||||
|                    const dropt_option* option, | ||||
|                    const dropt_char* optionArgument, | ||||
|                    void* dest) | ||||
| { | ||||
|     dropt_error err = dropt_error_none; | ||||
|     dropt_uintptr* out = dest; | ||||
| 
 | ||||
|     STATIC_ASSERT(sizeof (dropt_uintptr) >= sizeof (void*)); | ||||
| 
 | ||||
|     if (out == NULL) | ||||
|     { | ||||
|         DROPT_MISUSE("No handler destination specified."); | ||||
|         err = dropt_error_bad_configuration; | ||||
|     } | ||||
|     else if (option == NULL) | ||||
|     { | ||||
|         DROPT_MISUSE("No option entry given."); | ||||
|         err = dropt_error_bad_configuration; | ||||
|     } | ||||
|     else if (optionArgument != NULL) | ||||
|     { | ||||
|         err = dropt_error_mismatch; | ||||
|     } | ||||
| 
 | ||||
|     if (err == dropt_error_none) { *out = option->extra_data; } | ||||
|     return err; | ||||
| } | ||||
|  | @ -0,0 +1,692 @@ | |||
| /** dropt_string.c
 | ||||
|   * | ||||
|   * String routines for dropt. | ||||
|   * | ||||
|   * Copyright (C) 2006-2018 James D. Lin <jamesdlin@berkeley.edu> | ||||
|   * | ||||
|   * The latest version of this file can be downloaded from: | ||||
|   * <http://www.taenarum.com/software/dropt/>
 | ||||
|   * | ||||
|   * This software is provided 'as-is', without any express or implied | ||||
|   * warranty.  In no event will the authors be held liable for any damages | ||||
|   * arising from the use of this software. | ||||
|   * | ||||
|   * Permission is granted to anyone to use this software for any purpose, | ||||
|   * including commercial applications, and to alter it and redistribute it | ||||
|   * freely, subject to the following restrictions: | ||||
|   * | ||||
|   * 1. The origin of this software must not be misrepresented; you must not | ||||
|   *    claim that you wrote the original software. If you use this software | ||||
|   *    in a product, an acknowledgment in the product documentation would be | ||||
|   *    appreciated but is not required. | ||||
|   * | ||||
|   * 2. Altered source versions must be plainly marked as such, and must not be | ||||
|   *    misrepresented as being the original software. | ||||
|   * | ||||
|   * 3. This notice may not be removed or altered from any source distribution. | ||||
|   */ | ||||
| 
 | ||||
| #ifdef _MSC_VER | ||||
|     #include <tchar.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdarg.h> | ||||
| #include <string.h> | ||||
| #include <ctype.h> | ||||
| #include <wctype.h> | ||||
| #include <stdio.h> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| #if __STDC_VERSION__ >= 199901L | ||||
|     #include <stdint.h> | ||||
| #else | ||||
|     /* Compatibility junk for things that don't yet support ISO C99. */ | ||||
|     #if defined _MSC_VER || defined __BORLANDC__ | ||||
|         #ifndef va_copy | ||||
|             #define va_copy(dest, src) (dest = (src)) | ||||
|         #endif | ||||
|     #else | ||||
|         #ifndef va_copy | ||||
|             #error Unsupported platform.  va_copy is not defined. | ||||
|         #endif | ||||
|     #endif | ||||
| 
 | ||||
|     #ifndef SIZE_MAX | ||||
|         #define SIZE_MAX ((size_t) -1) | ||||
|     #endif | ||||
| #endif | ||||
| 
 | ||||
| #include "dropt_string.h" | ||||
| 
 | ||||
| #ifndef MAX | ||||
| #define MAX(x, y) (((x) > (y)) ? (x) : (y)) | ||||
| #endif | ||||
| 
 | ||||
| #ifndef MIN | ||||
| #define MIN(x, y) (((x) < (y)) ? (x) : (y)) | ||||
| #endif | ||||
| 
 | ||||
| #ifdef DROPT_DEBUG_STRING_BUFFERS | ||||
|     enum { default_stringstream_buffer_size = 1 }; | ||||
|     #define GROWN_STRINGSTREAM_BUFFER_SIZE(oldSize, minAmount) \ | ||||
|         ((oldSize) + (minAmount)) | ||||
| #else | ||||
|     enum { default_stringstream_buffer_size = 256 }; | ||||
|     #define GROWN_STRINGSTREAM_BUFFER_SIZE(oldSize, minAmount) \ | ||||
|         MAX((oldSize) * 2, (oldSize) + (minAmount)) | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #ifndef DROPT_NO_STRING_BUFFERS | ||||
| struct dropt_stringstream | ||||
| { | ||||
|     /* The string buffer. */ | ||||
|     dropt_char* string; | ||||
| 
 | ||||
|     /* Size of the string buffer, in `dropt_char`s, including space for `NUL`.
 | ||||
|      */ | ||||
|     size_t maxSize; | ||||
| 
 | ||||
|     /* Number of elements used in the string buffer, excluding `NUL`. */ | ||||
|     size_t used; | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_safe_malloc
 | ||||
|   * | ||||
|   *     A version of `malloc` that checks for integer overflow. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN numElements : The number of elements to allocate. | ||||
|   *     IN elementSize : The size of each element, in bytes. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     A pointer to the allocated memory. | ||||
|   *     Returns `NULL` if `numElements` is 0. | ||||
|   *     Returns `NULL` on error. | ||||
|   */ | ||||
| void* | ||||
| dropt_safe_malloc(size_t numElements, size_t elementSize) | ||||
| { | ||||
|     return dropt_safe_realloc(NULL, numElements, elementSize); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_safe_realloc
 | ||||
|   * | ||||
|   *     Wrapper around `realloc` to check for integer overflow. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN/OUT p       : A pointer to the memory block to resize. | ||||
|   *                      If `NULL`, a new memory block of the specified size | ||||
|   *                        will be allocated. | ||||
|   *     IN numElements : The number of elements to allocate. | ||||
|   *                      If 0, frees `p`. | ||||
|   *     IN elementSize : The size of each element, in bytes. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     A pointer to the allocated memory. | ||||
|   *     Returns `NULL` if `numElements` is 0. | ||||
|   *     Returns `NULL` on error. | ||||
|   */ | ||||
| void* | ||||
| dropt_safe_realloc(void* p, size_t numElements, size_t elementSize) | ||||
| { | ||||
|     size_t numBytes; | ||||
| 
 | ||||
|     /* `elementSize` shouldn't legally be 0, but we check for it in case a
 | ||||
|      * caller got the argument order wrong. | ||||
|      */ | ||||
|     if (numElements == 0 || elementSize == 0) | ||||
|     { | ||||
|         /* The behavior of `realloc(p, 0)` is implementation-defined.  Let's
 | ||||
|          * enforce a particular behavior. | ||||
|          */ | ||||
|         free(p); | ||||
| 
 | ||||
|         assert(elementSize != 0); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     numBytes = numElements * elementSize; | ||||
|     if (numBytes / elementSize != numElements) | ||||
|     { | ||||
|         /* Overflow. */ | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     return realloc(p, numBytes); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_strdup
 | ||||
|   * | ||||
|   *     Duplicates a string. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN s : A `NUL`-terminated string to duplicate. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     The duplicated string.  The caller is responsible for calling `free()` | ||||
|   *       on it when no longer needed. | ||||
|   *     Returns `NULL` on error. | ||||
|   */ | ||||
| dropt_char* | ||||
| dropt_strdup(const dropt_char* s) | ||||
| { | ||||
|     return dropt_strndup(s, SIZE_MAX); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_strndup
 | ||||
|   * | ||||
|   *     Duplicates the first `n` characters of a string. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN s : The string to duplicate. | ||||
|   *     IN n : The maximum number of `dropt_char`s to copy, excluding the | ||||
|   *              `NUL`-terminator. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     The duplicated string, which is always `NUL`-terminated.  The caller is | ||||
|   *       responsible for calling `free()` on it when no longer needed. | ||||
|   *     Returns `NULL` on error. | ||||
|   */ | ||||
| dropt_char* | ||||
| dropt_strndup(const dropt_char* s, size_t n) | ||||
| { | ||||
|     dropt_char* copy; | ||||
|     size_t len = 0; | ||||
| 
 | ||||
|     assert(s != NULL); | ||||
| 
 | ||||
|     while (len < n && s[len] != DROPT_TEXT_LITERAL('\0')) | ||||
|     { | ||||
|         len++; | ||||
|     } | ||||
| 
 | ||||
|     if (len + 1 < len) | ||||
|     { | ||||
|         /* This overflow check shouldn't be strictly necessary. `len` can be at
 | ||||
|          * most `SIZE_MAX`, so `SIZE_MAX + 1` can wrap around to 0, but | ||||
|          * `dropt_safe_malloc` will return `NULL` for a 0-sized allocation. | ||||
|          * However, favor defensive paranoia. | ||||
|          */ | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     copy = dropt_safe_malloc(len + 1 /* NUL */, sizeof *copy); | ||||
|     if (copy != NULL) | ||||
|     { | ||||
|         memcpy(copy, s, len * sizeof *copy); | ||||
|         copy[len] = DROPT_TEXT_LITERAL('\0'); | ||||
|     } | ||||
| 
 | ||||
|     return copy; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_stricmp
 | ||||
|   * | ||||
|   *     Compares two `NUL`-terminated strings ignoring case differences.  Not | ||||
|   *       recommended for non-ASCII strings. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN s, t : The strings to compare. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     0 if the strings are equivalent, | ||||
|   *     < 0 if `s` should precede `t`, | ||||
|   *     > 0 if `s` should follow `t`. | ||||
|   */ | ||||
| int | ||||
| dropt_stricmp(const dropt_char* s, const dropt_char* t) | ||||
| { | ||||
|     assert(s != NULL); | ||||
|     assert(t != NULL); | ||||
|     return dropt_strnicmp(s, t, SIZE_MAX); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_strnicmp
 | ||||
|   * | ||||
|   *     Compares the first `n` characters of two strings, ignoring case | ||||
|   *       differences.  Not recommended for non-ASCII strings. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN s, t : The strings to compare. | ||||
|   *     IN n    : The maximum number of `dropt_char`s to compare. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     0 if the strings are equivalent, | ||||
|   *     < 0 if `s` should precede `t`, | ||||
|   *     > 0 if `s` should follow `t`. | ||||
|   */ | ||||
| int | ||||
| dropt_strnicmp(const dropt_char* s, const dropt_char* t, size_t n) | ||||
| { | ||||
|     assert(s != NULL); | ||||
|     assert(t != NULL); | ||||
| 
 | ||||
|     if (s == t) { return 0; } | ||||
| 
 | ||||
|     while (n--) | ||||
|     { | ||||
|         if (*s == DROPT_TEXT_LITERAL('\0') && *t == DROPT_TEXT_LITERAL('\0')) | ||||
|         { | ||||
|             break; | ||||
|         } | ||||
|         else if (*s == *t || dropt_tolower(*s) == dropt_tolower(*t)) | ||||
|         { | ||||
|             s++; | ||||
|             t++; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return (dropt_tolower(*s) < dropt_tolower(*t)) | ||||
|                    ? -1 | ||||
|                    : +1; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifndef DROPT_NO_STRING_BUFFERS | ||||
| /** dropt_vsnprintf
 | ||||
|   * | ||||
|   *     `vsnprintf` wrapper to provide ISO C99-compliant behavior. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     OUT s     : The destination buffer.  May be `NULL` if `n` is 0. | ||||
|   *                 If non-`NULL`, always `NUL`-terminated. | ||||
|   *     IN n      : The size of the destination buffer, measured in | ||||
|   *                   `dropt_char`s. | ||||
|   *     IN format : `printf`-style format specifier.  Must not be `NULL`. | ||||
|   *     IN args   : Arguments to insert into the formatted string. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     The number of characters that would be written to the destination | ||||
|   *       buffer if it's sufficiently large, excluding the `NUL`-terminator. | ||||
|   *     Returns -1 on error. | ||||
|   */ | ||||
| int | ||||
| dropt_vsnprintf(dropt_char* s, size_t n, const dropt_char* format, va_list args) | ||||
| { | ||||
| #if __STDC_VERSION__ >= 199901L || __GNUC__ | ||||
|     /* ISO C99-compliant.
 | ||||
|      * | ||||
|      * As far as I can tell, gcc's implementation of `vsnprintf` has always | ||||
|      * matched the behavior required by the C99 standard (which is to return | ||||
|      * the necessary buffer size). | ||||
|      * | ||||
|      * Note that this won't work with `wchar_t` because there is no true, | ||||
|      * standard `wchar_t` equivalent of `snprintf`. `swprintf` comes close but | ||||
|      * doesn't return the necessary buffer size (and the standard does not | ||||
|      * provide a guaranteed way to test if truncation occurred), and its | ||||
|      * format string can't be used interchangeably with `snprintf`. | ||||
|      * | ||||
|      * It's simpler not to support `wchar_t` on non-Windows platforms. | ||||
|      */ | ||||
|     assert(format != NULL); | ||||
|     return vsnprintf(s, n, format, args); | ||||
| #elif defined __BORLANDC__ | ||||
|     /* Borland's compiler neglects to `NUL`-terminate. */ | ||||
|     int ret; | ||||
|     assert(format != NULL); | ||||
|     ret = vsnprintf(s, n, format, args); | ||||
|     if (n != 0) { s[n - 1] = DROPT_TEXT_LITERAL('\0'); } | ||||
|     return ret; | ||||
| #elif defined _MSC_VER | ||||
|     /* `_vsntprintf` and `_vsnprintf_s` on Windows don't have C99 semantics;
 | ||||
|      * they return -1 if truncation occurs. | ||||
|      */ | ||||
|     va_list argsCopy; | ||||
|     int ret; | ||||
| 
 | ||||
|     assert(format != NULL); | ||||
| 
 | ||||
|     va_copy(argsCopy, args); | ||||
|     ret = _vsctprintf(format, argsCopy); | ||||
|     va_end(argsCopy); | ||||
| 
 | ||||
|     if (n != 0) | ||||
|     { | ||||
|         assert(s != NULL); | ||||
| 
 | ||||
|     #if _MSC_VER >= 1400 | ||||
|         (void) _vsntprintf_s(s, n, _TRUNCATE, format, args); | ||||
|     #else | ||||
|         /* This version doesn't necessarily `NUL`-terminate.  Sigh. */ | ||||
|         (void) _vsnprintf(s, n, format, args); | ||||
|         s[n - 1] = DROPT_TEXT_LITERAL('\0'); | ||||
|     #endif | ||||
|     } | ||||
| 
 | ||||
|     return ret; | ||||
| 
 | ||||
| #else | ||||
|     #error Unsupported platform.  dropt_vsnprintf unimplemented. | ||||
|     return -1; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** See `dropt_vsnprintf`. */ | ||||
| int | ||||
| dropt_snprintf(dropt_char* s, size_t n, const dropt_char* format, ...) | ||||
| { | ||||
|     int ret; | ||||
|     va_list args; | ||||
|     va_start(args, format); | ||||
|     ret = dropt_vsnprintf(s, n, format, args); | ||||
|     va_end(args); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_vasprintf
 | ||||
|   * | ||||
|   *     Allocates a formatted string with `vprintf` semantics. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN format : `printf`-style format specifier.  Must not be `NULL`. | ||||
|   *     IN args   : Arguments to insert into the formatted string. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     The formatted string, which is always NUL-terminated.  The caller is | ||||
|   *       responsible for calling `free()` on it when no longer needed. | ||||
|   *     Returns `NULL` on error. | ||||
|   */ | ||||
| dropt_char* | ||||
| dropt_vasprintf(const dropt_char* format, va_list args) | ||||
| { | ||||
|     dropt_char* s = NULL; | ||||
|     int len; | ||||
|     va_list argsCopy; | ||||
|     assert(format != NULL); | ||||
| 
 | ||||
|     va_copy(argsCopy, args); | ||||
|     len = dropt_vsnprintf(NULL, 0, format, argsCopy); | ||||
|     va_end(argsCopy); | ||||
| 
 | ||||
|     if (len >= 0) | ||||
|     { | ||||
|         size_t n = len + 1 /* NUL */; | ||||
|         s = dropt_safe_malloc(n, sizeof *s); | ||||
|         if (s != NULL) | ||||
|         { | ||||
|             dropt_vsnprintf(s, n, format, args); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return s; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** See `dropt_vasprintf`. */ | ||||
| dropt_char* | ||||
| dropt_asprintf(const dropt_char* format, ...) | ||||
| { | ||||
|     dropt_char* s; | ||||
| 
 | ||||
|     va_list args; | ||||
|     va_start(args, format); | ||||
|     s = dropt_vasprintf(format, args); | ||||
|     va_end(args); | ||||
| 
 | ||||
|     return s; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_ssopen
 | ||||
|   * | ||||
|   *     Constructs a new `dropt_stringstream`. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     An initialized `dropt_stringstream`.  The caller is responsible for | ||||
|   *       calling either `dropt_ssclose()` or `dropt_ssfinalize()` on it when | ||||
|   *       no longer needed. | ||||
|   *     Returns `NULL` on error. | ||||
|   */ | ||||
| dropt_stringstream* | ||||
| dropt_ssopen(void) | ||||
| { | ||||
|     dropt_stringstream* ss = malloc(sizeof *ss); | ||||
|     if (ss != NULL) | ||||
|     { | ||||
|         ss->used = 0; | ||||
|         ss->maxSize = default_stringstream_buffer_size; | ||||
|         ss->string = dropt_safe_malloc(ss->maxSize, sizeof *ss->string); | ||||
|         if (ss->string == NULL) | ||||
|         { | ||||
|             free(ss); | ||||
|             ss = NULL; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             ss->string[0] = DROPT_TEXT_LITERAL('\0'); | ||||
|         } | ||||
|     } | ||||
|     return ss; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_ssclose
 | ||||
|   * | ||||
|   *     Destroys a `dropt_stringstream`. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN/OUT ss : The `dropt_stringstream`. | ||||
|   */ | ||||
| void | ||||
| dropt_ssclose(dropt_stringstream* ss) | ||||
| { | ||||
|     if (ss != NULL) | ||||
|     { | ||||
|         free(ss->string); | ||||
|         free(ss); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_ssgetfreespace
 | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     The amount of free space in the `dropt_stringstream`'s internal buffer, | ||||
|   *       measured in `dropt_char`s.  Space used for the `NUL`-terminator is | ||||
|   *       considered free. (The amount of free space therefore is always | ||||
|   *       positive.) | ||||
|   */ | ||||
| static size_t | ||||
| dropt_ssgetfreespace(const dropt_stringstream* ss) | ||||
| { | ||||
|     assert(ss != NULL); | ||||
|     assert(ss->maxSize > 0); | ||||
|     assert(ss->maxSize > ss->used); | ||||
|     return ss->maxSize - ss->used; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_ssresize
 | ||||
|   * | ||||
|   *     Resizes a `dropt_stringstream`'s internal buffer.  If the requested | ||||
|   *     size is less than the amount of buffer already in use, the buffer will | ||||
|   *     be shrunk to the minimum size necessary. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN/OUT ss : The `dropt_stringstream`. | ||||
|   *     IN n      : The desired buffer size, in `dropt_char`s. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     The new size of the `dropt_stringstream`'s buffer in `dropt_char`s, | ||||
|   *       including space for a terminating `NUL`. | ||||
|   */ | ||||
| static size_t | ||||
| dropt_ssresize(dropt_stringstream* ss, size_t n) | ||||
| { | ||||
|     assert(ss != NULL); | ||||
| 
 | ||||
|     /* Don't allow shrinking if it will truncate the string. */ | ||||
|     if (n < ss->maxSize) { n = MAX(n, ss->used + 1 /* NUL */); } | ||||
| 
 | ||||
|     /* There should always be a buffer to point to. */ | ||||
|     assert(n > 0); | ||||
| 
 | ||||
|     if (n != ss->maxSize) | ||||
|     { | ||||
|         dropt_char* p = dropt_safe_realloc(ss->string, n, sizeof *ss->string); | ||||
|         if (p != NULL) | ||||
|         { | ||||
|             ss->string = p; | ||||
|             ss->maxSize = n; | ||||
|             assert(ss->maxSize > 0); | ||||
|          } | ||||
|     } | ||||
|     return ss->maxSize; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_ssclear
 | ||||
|   * | ||||
|   *     Clears and re-initializes a `dropt_stringstream`. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN/OUT ss : The `dropt_stringstream`. | ||||
|   */ | ||||
| void | ||||
| dropt_ssclear(dropt_stringstream* ss) | ||||
| { | ||||
|     assert(ss != NULL); | ||||
| 
 | ||||
|     ss->string[0] = DROPT_TEXT_LITERAL('\0'); | ||||
|     ss->used = 0; | ||||
| 
 | ||||
|     dropt_ssresize(ss, default_stringstream_buffer_size); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_ssfinalize
 | ||||
|   * | ||||
|   *     Finalizes a `dropt_stringstream`; returns the contained string and | ||||
|   *     destroys the `dropt_stringstream`. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN/OUT ss : The `dropt_stringstream`. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     The `dropt_stringstream`'s string, which is always `NUL`-terminated. | ||||
|   *       Note that the caller assumes ownership of the returned string and is | ||||
|   *       responsible for calling `free()` on it when no longer needed. | ||||
|   */ | ||||
| dropt_char* | ||||
| dropt_ssfinalize(dropt_stringstream* ss) | ||||
| { | ||||
|     dropt_char* s; | ||||
|     assert(ss != NULL); | ||||
| 
 | ||||
|     /* Shrink to fit. */ | ||||
|     dropt_ssresize(ss, 0); | ||||
| 
 | ||||
|     s = ss->string; | ||||
|     ss->string = NULL; | ||||
| 
 | ||||
|     dropt_ssclose(ss); | ||||
| 
 | ||||
|     return s; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_ssgetstring
 | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN ss : The `dropt_stringstream`. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     The `dropt_stringstream`'s string, which is always `NUL`-terminated. | ||||
|   *       The returned string will no longer be valid if further operations are | ||||
|   *       performed on the `dropt_stringstream` or if the `dropt_stringstream` | ||||
|   *       is closed. | ||||
|   */ | ||||
| const dropt_char* | ||||
| dropt_ssgetstring(const dropt_stringstream* ss) | ||||
| { | ||||
|     assert(ss != NULL); | ||||
|     return ss->string; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** dropt_vssprintf
 | ||||
|   * | ||||
|   *     Appends a formatted string with `vprintf` semantics to a | ||||
|   *     `dropt_stringstream`. | ||||
|   * | ||||
|   * PARAMETERS: | ||||
|   *     IN/OUT ss : The `dropt_stringstream`. | ||||
|   *     IN format : `printf`-style format specifier.  Must not be `NULL`. | ||||
|   *     IN args   : Arguments to insert into the formatted string. | ||||
|   * | ||||
|   * RETURNS: | ||||
|   *     The number of characters written to the `dropt_stringstream`, excluding | ||||
|   *       the `NUL`-terminator. | ||||
|   *     Returns a negative value on error. | ||||
|   */ | ||||
| int | ||||
| dropt_vssprintf(dropt_stringstream* ss, const dropt_char* format, va_list args) | ||||
| { | ||||
|     int n; | ||||
|     va_list argsCopy; | ||||
|     assert(ss != NULL); | ||||
|     assert(format != NULL); | ||||
| 
 | ||||
|     va_copy(argsCopy, args); | ||||
|     n = dropt_vsnprintf(NULL, 0, format, argsCopy); | ||||
|     va_end(argsCopy); | ||||
| 
 | ||||
|     if (n > 0) | ||||
|     { | ||||
|         size_t available = dropt_ssgetfreespace(ss); | ||||
|         if ((unsigned int) n >= available) | ||||
|         { | ||||
|             /* It's possible that `newSize < ss->maxSize` if
 | ||||
|              * `GROWN_STRINGSTREAM_BUFFER_SIZE()` overflows, but it should be | ||||
|              * safe since we'll recompute the available space. | ||||
|              */ | ||||
|             size_t newSize = GROWN_STRINGSTREAM_BUFFER_SIZE(ss->maxSize, n); | ||||
|             dropt_ssresize(ss, newSize); | ||||
|             available = dropt_ssgetfreespace(ss); | ||||
|         } | ||||
|         assert(available > 0); /* Space always is reserved for NUL. */ | ||||
| 
 | ||||
|         /* `snprintf`'s family of functions return the number of characters
 | ||||
|          * that would be output with a sufficiently large buffer, excluding | ||||
|          * `NUL`. | ||||
|          */ | ||||
|         n = dropt_vsnprintf(ss->string + ss->used, available, format, args); | ||||
| 
 | ||||
|         /* We couldn't allocate enough space. */ | ||||
|         if ((unsigned int) n >= available) { n = -1; } | ||||
| 
 | ||||
|         if (n > 0) { ss->used += n; } | ||||
|     } | ||||
|     return n; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** See `dropt_vssprintf`. */ | ||||
| int | ||||
| dropt_ssprintf(dropt_stringstream* ss, const dropt_char* format, ...) | ||||
| { | ||||
|     int n; | ||||
| 
 | ||||
|     va_list args; | ||||
|     va_start(args, format); | ||||
|     n = dropt_vssprintf(ss, format, args); | ||||
|     va_end(args); | ||||
| 
 | ||||
|     return n; | ||||
| } | ||||
| #endif /* DROPT_NO_STRING_BUFFERS */ | ||||
|  | @ -0,0 +1,96 @@ | |||
| /** dropt_string.h
 | ||||
|   * | ||||
|   * String routines for dropt. | ||||
|   * | ||||
|   * Copyright (C) 2006-2010 James D. Lin <jamesdlin@berkeley.edu> | ||||
|   * | ||||
|   * The latest version of this file can be downloaded from: | ||||
|   * <http://www.taenarum.com/software/dropt/>
 | ||||
|   * | ||||
|   * This software is provided 'as-is', without any express or implied | ||||
|   * warranty.  In no event will the authors be held liable for any damages | ||||
|   * arising from the use of this software. | ||||
|   * | ||||
|   * Permission is granted to anyone to use this software for any purpose, | ||||
|   * including commercial applications, and to alter it and redistribute it | ||||
|   * freely, subject to the following restrictions: | ||||
|   * | ||||
|   * 1. The origin of this software must not be misrepresented; you must not | ||||
|   *    claim that you wrote the original software. If you use this software | ||||
|   *    in a product, an acknowledgment in the product documentation would be | ||||
|   *    appreciated but is not required. | ||||
|   * | ||||
|   * 2. Altered source versions must be plainly marked as such, and must not be | ||||
|   *    misrepresented as being the original software. | ||||
|   * | ||||
|   * 3. This notice may not be removed or altered from any source distribution. | ||||
|   */ | ||||
| 
 | ||||
| #ifndef DROPT_STRING_H | ||||
| #define DROPT_STRING_H | ||||
| 
 | ||||
| #include <stdarg.h> | ||||
| 
 | ||||
| #include "dropt.h" | ||||
| 
 | ||||
| #ifdef DROPT_USE_WCHAR | ||||
|     #define dropt_strlen wcslen | ||||
|     #define dropt_strcmp wcscmp | ||||
|     #define dropt_strncmp wcsncmp | ||||
|     #define dropt_strchr wcschr | ||||
|     #define dropt_strtol wcstol | ||||
|     #define dropt_strtoul wcstoul | ||||
|     #define dropt_strtod wcstod | ||||
|     #define dropt_tolower towlower | ||||
|     #define dropt_fputs fputws | ||||
| #else | ||||
|     #define dropt_strlen strlen | ||||
|     #define dropt_strcmp strcmp | ||||
|     #define dropt_strncmp strncmp | ||||
|     #define dropt_strchr strchr | ||||
|     #define dropt_strtol strtol | ||||
|     #define dropt_strtoul strtoul | ||||
|     #define dropt_strtod strtod | ||||
|     #define dropt_tolower tolower | ||||
|     #define dropt_fputs fputs | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| void* dropt_safe_malloc(size_t numElements, size_t elementSize); | ||||
| void* dropt_safe_realloc(void* p, size_t numElements, size_t elementSize); | ||||
| 
 | ||||
| dropt_char* dropt_strdup(const dropt_char* s); | ||||
| dropt_char* dropt_strndup(const dropt_char* s, size_t n); | ||||
| int dropt_stricmp(const dropt_char* s, const dropt_char* t); | ||||
| int dropt_strnicmp(const dropt_char* s, const dropt_char* t, size_t n); | ||||
| 
 | ||||
| 
 | ||||
| #ifndef DROPT_NO_STRING_BUFFERS | ||||
| typedef struct dropt_stringstream dropt_stringstream; | ||||
| 
 | ||||
| int dropt_vsnprintf(dropt_char* s, size_t n, const dropt_char* format, va_list args); | ||||
| int dropt_snprintf(dropt_char* s, size_t n, const dropt_char* format, ...); | ||||
| 
 | ||||
| dropt_char* dropt_vasprintf(const dropt_char* format, va_list args); | ||||
| dropt_char* dropt_asprintf(const dropt_char* format, ...); | ||||
| 
 | ||||
| dropt_stringstream* dropt_ssopen(void); | ||||
| void dropt_ssclose(dropt_stringstream* ss); | ||||
| 
 | ||||
| void dropt_ssclear(dropt_stringstream* ss); | ||||
| dropt_char* dropt_ssfinalize(dropt_stringstream* ss); | ||||
| const dropt_char* dropt_ssgetstring(const dropt_stringstream* ss); | ||||
| 
 | ||||
| int dropt_vssprintf(dropt_stringstream* ss, const dropt_char* format, va_list args); | ||||
| int dropt_ssprintf(dropt_stringstream* ss, const dropt_char* format, ...); | ||||
| #endif /* DROPT_NO_STRING_BUFFERS */ | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } /* extern "C" */ | ||||
| #endif | ||||
| 
 | ||||
| #endif /* DROPT_STRING_H */ | ||||
|  | @ -16,6 +16,7 @@ | |||
| #include "y.tab.h" | ||||
| #include "ast.h" | ||||
| #include "stack.h" | ||||
| #include "../lib/dropt/dropt.h" | ||||
| 
 | ||||
| extern FILE *yyin; | ||||
| Stack *stack; | ||||
|  | @ -819,17 +820,8 @@ static void Compile(LLVMModuleRef module, LLVMContextRef context, Node *node) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char *argv[]) | ||||
| static int Build(char *inputFilename, uint32_t optimizationLevel) | ||||
| { | ||||
|     if (argc < 2) | ||||
|     { | ||||
|         printf("Please provide a file.\n"); | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     extern int yydebug; | ||||
|     yydebug = 1; | ||||
| 
 | ||||
|     scope = CreateScope(); | ||||
| 
 | ||||
|     structTypeDeclarations = NULL; | ||||
|  | @ -837,7 +829,7 @@ int main(int argc, char *argv[]) | |||
| 
 | ||||
|     stack = CreateStack(); | ||||
| 
 | ||||
|     FILE *fp = fopen(argv[1], "r"); | ||||
|     FILE *fp = fopen(inputFilename, "r"); | ||||
|     yyin = fp; | ||||
|     yyparse(fp, stack); | ||||
|     fclose(fp); | ||||
|  | @ -866,7 +858,13 @@ int main(int argc, char *argv[]) | |||
| 
 | ||||
|     /* verify */ | ||||
|     char *error = NULL; | ||||
|     LLVMVerifyModule(module, LLVMAbortProcessAction, &error); | ||||
| 
 | ||||
|     if (LLVMVerifyModule(module, LLVMAbortProcessAction, &error) != 0) | ||||
|     { | ||||
|         fprintf(stderr, "%s\n", error); | ||||
|         LLVMDisposeMessage(error); | ||||
|         return EXIT_FAILURE; | ||||
|     } | ||||
| 
 | ||||
|     /* prepare to emit assembly */ | ||||
|     LLVMInitializeNativeTarget(); | ||||
|  | @ -883,24 +881,25 @@ int main(int argc, char *argv[]) | |||
|         fprintf(stderr, "Failed to get target!\n"); | ||||
|         fprintf(stderr, "%s\n", error); | ||||
|         LLVMDisposeMessage(error); | ||||
|         return 1; | ||||
|         return EXIT_FAILURE; | ||||
|     } | ||||
| 
 | ||||
|     LLVMPassManagerRef passManager = LLVMCreatePassManager(); | ||||
| 
 | ||||
|     //LLVMAddInstructionCombiningPass(passManager);
 | ||||
|     //LLVMAddCFGSimplificationPass(passManager);
 | ||||
|     //LLVMAddReassociatePass(passManager);
 | ||||
|     //LLVMAddPromoteMemoryToRegisterPass(passManager);
 | ||||
|     // LLVMAddInstructionCombiningPass(passManager);
 | ||||
|     // LLVMAddCFGSimplificationPass(passManager);
 | ||||
|     // LLVMAddReassociatePass(passManager);
 | ||||
|     // LLVMAddPromoteMemoryToRegisterPass(passManager);
 | ||||
| 
 | ||||
|     LLVMPassManagerBuilderRef passManagerBuilder = LLVMPassManagerBuilderCreate(); | ||||
|     LLVMPassManagerBuilderSetOptLevel(passManagerBuilder, 0); | ||||
|     LLVMPassManagerBuilderSetOptLevel(passManagerBuilder, optimizationLevel); | ||||
|     LLVMPassManagerBuilderPopulateModulePassManager(passManagerBuilder, passManager); | ||||
| 
 | ||||
|     LLVMRunPassManager(passManager, module); | ||||
| 
 | ||||
|     if (LLVMWriteBitcodeToFile(module, "test.bc") != 0) { | ||||
|         fprintf(stderr, "error writing bitcode to file\n"); | ||||
|         return EXIT_FAILURE; | ||||
|     } | ||||
| 
 | ||||
|     char *cpu = "generic"; | ||||
|  | @ -921,7 +920,7 @@ int main(int argc, char *argv[]) | |||
|         fprintf(stderr, "Failed to emit machine code!\n"); | ||||
|         fprintf(stderr, "%s\n", error); | ||||
|         LLVMDisposeMessage(error); | ||||
|         return 1; | ||||
|         return EXIT_FAILURE; | ||||
|     } | ||||
| 
 | ||||
|     LLVMDisposeMessage(error); | ||||
|  | @ -929,5 +928,64 @@ int main(int argc, char *argv[]) | |||
|     LLVMPassManagerBuilderDispose(passManagerBuilder); | ||||
|     LLVMDisposePassManager(passManager); | ||||
|     LLVMDisposeModule(module); | ||||
|     return 0; | ||||
| 
 | ||||
|     return EXIT_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
|     dropt_bool showHelp; | ||||
|     uint32_t optimizationLevel = 0; | ||||
|     char *inputFilename; | ||||
|     extern int yydebug; | ||||
|     int exitCode = EXIT_SUCCESS; | ||||
| 
 | ||||
|     dropt_option options[] = { | ||||
|         { 'h', "help", "Shows help.", NULL, dropt_handle_bool, &showHelp, dropt_attr_halt }, | ||||
|         { 'O', "optimize", "Sets optimization level of the output IR. Must be a value between 0 and 3.", "number", dropt_handle_uint, &optimizationLevel }, | ||||
|         { 0 } /* Required sentinel value. */ | ||||
|     }; | ||||
| 
 | ||||
|     dropt_context *droptContext = dropt_new_context(options); | ||||
| 
 | ||||
|     if (droptContext == NULL) | ||||
|     { | ||||
|         exitCode = EXIT_FAILURE; | ||||
|     } | ||||
|     else if (argc == 0) | ||||
|     { | ||||
|         printf("Must supply an input file."); | ||||
|         exitCode = EXIT_FAILURE; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         char** rest = dropt_parse(droptContext, -1, &argv[1]); | ||||
|         if (dropt_get_error(droptContext) != dropt_error_none) | ||||
|         { | ||||
|             fprintf(stderr, "wraith: %s\n", dropt_get_error_message(droptContext)); | ||||
|             exitCode = EXIT_FAILURE; | ||||
|         } | ||||
|         else if (showHelp) | ||||
|         { | ||||
|             printf("Usage: wraith [options] [--] [input_file]\n\n" | ||||
|                    "Options:\n"); | ||||
|             dropt_print_help(stdout, droptContext, NULL); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             yydebug = 1; /* FIXME: make this an option */ | ||||
|             inputFilename = *rest; | ||||
|             if (inputFilename == NULL) | ||||
|             { | ||||
|                 fprintf(stderr, "ERROR: Must provide an input file.\n"); | ||||
|                 exitCode = EXIT_FAILURE; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 exitCode = Build(inputFilename, optimizationLevel); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return exitCode; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue