diff options
author | midipix <writeonce@midipix.org> | 2016-06-29 10:49:47 -0400 |
---|---|---|
committer | midipix <writeonce@midipix.org> | 2016-06-29 19:16:37 -0400 |
commit | f7b99942f85f4c8c35058f1a8b1194cd4468bc6d (patch) | |
tree | 890e0f326a2d0fbee61ae6062f26a4bd9dbef90c /src/argv | |
parent | a2ea1bdf70166f887457b5462332d2df4f6f54c5 (diff) | |
download | ntapi-f7b99942f85f4c8c35058f1a8b1194cd4468bc6d.tar.bz2 ntapi-f7b99942f85f4c8c35058f1a8b1194cd4468bc6d.tar.xz |
free-standing environment: remove fluff from the argv/envp parsing facility.
Diffstat (limited to 'src/argv')
-rw-r--r-- | src/argv/ntapi_tt_env_vars.c | 93 | ||||
-rw-r--r-- | src/argv/ntapi_tt_get_option.c | 450 |
2 files changed, 15 insertions, 528 deletions
diff --git a/src/argv/ntapi_tt_env_vars.c b/src/argv/ntapi_tt_env_vars.c index 4fe590c..5642101 100644 --- a/src/argv/ntapi_tt_env_vars.c +++ b/src/argv/ntapi_tt_env_vars.c @@ -9,104 +9,41 @@ #include "ntapi_impl.h" int32_t __stdcall __ntapi_tt_get_env_var_meta_utf16( - __in const uint32_t * crc32_table, __in wchar16_t * env_var_name, - __in uint32_t env_var_name_hash __optional, __in wchar16_t ** envp, __out nt_env_var_meta_utf16 * env_var_meta) { int idx; - uint32_t crc32; - unsigned char * byte_buffer; wchar16_t * wch; - #define EQUAL_SIGN 0x3D + #define EQUAL_SIGN 0x3D - /* step 1: crc32 of the target env_var_name */ - if (env_var_name_hash) - crc32 = env_var_name_hash; - else { - crc32 = 0 ^ 0xFFFFFFFF; + /* init */ + env_var_meta->name = 0; + env_var_meta->value = 0; + env_var_meta->envp_index = 0; + env_var_meta->flags = 0; - /* initialize byte_buffer */ - byte_buffer = (unsigned char *)env_var_name; - - /* iterate */ - while (*byte_buffer) { - /* two bytes at a time */ - crc32 = (crc32 >> 8) ^ crc32_table[(crc32 ^ *byte_buffer) & 0xFF]; - byte_buffer++; - crc32 = (crc32 >> 8) ^ crc32_table[(crc32 ^ *byte_buffer) & 0xFF]; - byte_buffer++; - } - crc32 = (crc32 ^ 0xFFFFFFFF); - } - - /* initialize the env_var_meta structure */ - env_var_meta->name_hash = crc32; - env_var_meta->name = (wchar16_t *)0; - env_var_meta->value = (wchar16_t *)0; - env_var_meta->value_hash = 0; - env_var_meta->envp_index = 0; - env_var_meta->flags = 0; - - /* step 2: look for the environment variable in envp[] */ - idx = 0; - while (envp[idx] && (!env_var_meta->value)) { + /* lookup */ + for (idx=0; envp[idx] && !env_var_meta->value; idx++) { wch = envp[idx]; - /* find the equal sign */ - while ((*wch) && (*wch != EQUAL_SIGN)) + while (*wch && (*wch != EQUAL_SIGN)) wch++; if (*wch != EQUAL_SIGN) return NT_STATUS_ILLEGAL_CHARACTER; - /* hash the current environment variable */ - crc32 = 0 ^ 0xFFFFFFFF; - - /* initialize byte_buffer */ - byte_buffer = (unsigned char *)envp[idx]; - - /* iterate */ - while ((uintptr_t)(byte_buffer) < (uintptr_t)wch) { - /* two bytes at a time */ - crc32 = (crc32 >> 8) ^ crc32_table[(crc32 ^ *byte_buffer) & 0xFF]; - byte_buffer++; - crc32 = (crc32 >> 8) ^ crc32_table[(crc32 ^ *byte_buffer) & 0xFF]; - byte_buffer++; - } - - if (env_var_meta->name_hash == (crc32 ^ 0xFFFFFFFF)) { - /* found it, get ready to hash the value */ + if (!(__ntapi->tt_strncmp_utf16( + envp[idx], + env_var_name, + wch - envp[idx]))) { wch++; - env_var_meta->name = envp[idx]; - env_var_meta->value = wch; + env_var_meta->name = envp[idx]; + env_var_meta->value = wch; env_var_meta->envp_index = idx; - } else { - idx++; - } - } - - if (env_var_meta->value) { - /* hash the value: utf-16, null-terminated */ - crc32 = 0 ^ 0xFFFFFFFF; - - /* initialize byte_buffer */ - byte_buffer = (unsigned char *)env_var_meta->value; - - /* iterate */ - while (*byte_buffer) { - /* two bytes at a time */ - crc32 = (crc32 >> 8) ^ crc32_table[(crc32 ^ *byte_buffer) & 0xFF]; - byte_buffer++; - crc32 = (crc32 >> 8) ^ crc32_table[(crc32 ^ *byte_buffer) & 0xFF]; - byte_buffer++; } - - env_var_meta->value_hash = (crc32 ^ 0xFFFFFFFF); } return NT_STATUS_SUCCESS; } - diff --git a/src/argv/ntapi_tt_get_option.c b/src/argv/ntapi_tt_get_option.c deleted file mode 100644 index 6cb3993..0000000 --- a/src/argv/ntapi_tt_get_option.c +++ /dev/null @@ -1,450 +0,0 @@ -/********************************************************/ -/* ntapi: Native API core library */ -/* Copyright (C) 2013--2016 Z. Gilboa */ -/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ -/********************************************************/ - -#include <psxtypes/psxtypes.h> -#include <ntapi/ntapi.h> -#include "ntapi_impl.h" - - -/** - * a simple facility for minimal programs or system libraries - * with no libc available at the time of invocation, as well - * as applications using the midipix free-standing development - * environment. - * - * the approach taken by this module to the support of short - * and long options reflects the above constraint, namely - * the absence of a callable libc at the time of invocation; - * there is no intent for interfaces in this module to - * be POSIXLY correct or otherwise portable. the sole - * purpose of all functions in this module is to serve - * internal or otherwise free-standing midipix applications, - * and their relevance otherwise is accordingly non-existent. - * - * all options are encoded in utf-16; note, however, that - * short options may only use code points that are located - * in the basic multilingual plane. - * - * option values are either required or not allowed altogether, - * and the first character of an option value may not be a hyphen. - * if you need the first character of an option value to be a - * hyphen, then make sure you escape it somehow (for instance by - * enclosing it in quotation marks). - * - * a short option and its value must reside in two separate - * argv[] elements (in other words: -ooutput is illegal). - * - * a long option and its value must reside in the same argv[] - * element and be separated by a single equal sign. - * - * Examples of valid options and option values: - * -------------------------------------------- - * -o - * -o value - * --long-option-with-no-value - * --long-option=value -**/ - -#define HYPHEN 0x2D -#define EQUAL_SIGN 0x3D - - -static __inline__ __fastcall int __is_bmp_code_point(uint16_t code_point) -{ - return ((code_point < 0xD800) || (code_point >= 0xE000)); -} - - -static __inline__ __fastcall int __is_last_program_option( - __in nt_program_option * option) -{ - return (!(option->short_name_code)) - && (!(option->long_name)) - && (!(option->long_name_hash)); -} - - -static int __fastcall __is_short_option(wchar16_t * wch) -{ - return ((wch) && (*wch == HYPHEN) - && __is_bmp_code_point(*++wch) - && (*++wch == 0)); -} - -static int __fastcall __is_long_option(wchar16_t * wch) -{ - return ((wch) && (*wch == HYPHEN) - && (++wch) && (*wch == HYPHEN) - && (*++wch)); -} - - -static int __fastcall __is_last_option_argument(wchar16_t * wch) -{ - return ((wch) && (*wch == HYPHEN) - && (*++wch == HYPHEN) - && (*++wch == 0)); -} - - -static uint32_t __fastcall __compute_crc32_utf16_str( - __in const uint32_t * crc32_table, - __in wchar16_t * wch) -{ - uint32_t crc32; - unsigned char * byte_buffer; - - /* crc32 hash... */ - crc32 = 0 ^ 0xFFFFFFFF; - - /* initialize byte_buffer */ - byte_buffer = (unsigned char *)wch; - - /* iterate */ - while (*byte_buffer) { - /* two bytes at a time */ - crc32 = (crc32 >> 8) ^ crc32_table[(crc32 ^ *byte_buffer) & 0xFF]; - byte_buffer++; - crc32 = (crc32 >> 8) ^ crc32_table[(crc32 ^ *byte_buffer) & 0xFF]; - byte_buffer++; - } - - return crc32; -} - - -static uint32_t __fastcall __compute_crc32_long_option_name( - __in const uint32_t * crc32_table, - __in wchar16_t * wch_arg, - __in wchar16_t * wch_termination) -{ - uint32_t crc32; - unsigned char * byte_buffer; - - /* crc32 hash... */ - crc32 = 0 ^ 0xFFFFFFFF; - - /* initialize byte_buffer */ - byte_buffer = (unsigned char *)wch_arg; - - /* iterate */ - while ((uintptr_t)byte_buffer < (uintptr_t)wch_termination) { - /* two bytes at a time */ - crc32 = (crc32 >> 8) ^ crc32_table[(crc32 ^ *byte_buffer) & 0xFF]; - byte_buffer++; - crc32 = (crc32 >> 8) ^ crc32_table[(crc32 ^ *byte_buffer) & 0xFF]; - byte_buffer++; - } - - return crc32; -} - - -static void __fastcall __init_cmd_option_meta_utf16( - __in nt_cmd_option_meta_utf16 * cmd_opt_meta) -{ - cmd_opt_meta->short_name = (wchar16_t *)0; - cmd_opt_meta->short_name_code = 0; - cmd_opt_meta->long_name = (wchar16_t *)0; - cmd_opt_meta->long_name_hash = 0; - cmd_opt_meta->value = (wchar16_t *)0; - cmd_opt_meta->value_hash = 0; - cmd_opt_meta->argv_index = 0; - cmd_opt_meta->flags = 0; - - return; -} - - -int32_t __stdcall __ntapi_tt_get_short_option_meta_utf16( - __in const uint32_t * crc32_table, - __in wchar16_t option_name, - __in wchar16_t * argv[], - __out nt_cmd_option_meta_utf16 * cmd_opt_meta) -{ - int idx; - wchar16_t * wch; - - if (!crc32_table) - return NT_STATUS_INVALID_PARAMETER_1; - else if (!option_name) - return NT_STATUS_INVALID_PARAMETER_2; - else if (!argv) - return NT_STATUS_INVALID_PARAMETER_3; - - /* initialize cmd_opt_meta */ - __init_cmd_option_meta_utf16(cmd_opt_meta); - - /* step 1: attempt to find the short option in argv[] */ - idx = 0; - while (argv[idx] && (!cmd_opt_meta->short_name_code)) { - wch = argv[idx]; - - /* is this our option? */ - if ((*wch == HYPHEN) - && (*++wch == option_name) - && (*++wch == 0)) { - - /* found it, get ready to hash the value */ - cmd_opt_meta->short_name_code = option_name; - cmd_opt_meta->short_name = argv[idx]; - cmd_opt_meta->argv_index = idx; - } else { - idx++; - } - } - - /* if the next argument is also an option (or is null), just exit */ - idx++; - if ((!argv[idx]) || (*argv[idx] == HYPHEN)) - return NT_STATUS_SUCCESS; - - /* step 2: hash the value */ - cmd_opt_meta->value = argv[idx]; - cmd_opt_meta->value_hash = - __compute_crc32_utf16_str( - crc32_table, - argv[idx]); - - return NT_STATUS_SUCCESS; -} - - -int32_t __stdcall __ntapi_tt_get_long_option_meta_utf16( - __in const uint32_t * crc32_table, - __in wchar16_t * option_name, - __in uint32_t option_name_hash __optional, - __in wchar16_t * argv[], - __out nt_cmd_option_meta_utf16 * cmd_opt_meta) -{ - /** - * option_name must always include the two-hyphen prefix; - * and the option value must be preceded by an equal sign. - * - * the only valid long option forms in argv[] are therefore: - * --long-option - * --long-option=value - **/ - - int idx; - uint32_t crc32; - wchar16_t * wch; - - /* validation */ - if (!crc32_table) - return NT_STATUS_INVALID_PARAMETER_1; - else if ((!option_name) && (!option_name_hash)) - return NT_STATUS_INVALID_PARAMETER; - else if ((option_name) && (option_name_hash)) - return NT_STATUS_INVALID_PARAMETER_MIX; - else if (!argv) - return NT_STATUS_INVALID_PARAMETER_4; - - /* initialize cmd_opt_meta */ - __init_cmd_option_meta_utf16(cmd_opt_meta); - - /* step 1: crc32 of the target option_name */ - if (option_name_hash) - crc32 = option_name_hash; - else - option_name_hash = - __compute_crc32_utf16_str( - crc32_table, - option_name); - - /* step 2: attempt to find the long option in argv[] */ - idx = 0; - while (argv[idx] && (!cmd_opt_meta->value)) { - wch = argv[idx]; - - if (__is_long_option(wch)) { - /* find the equal sign or null termination */ - while ((*wch) && (*wch != EQUAL_SIGN)) - wch++; - - crc32 = __compute_crc32_long_option_name( - crc32_table, - argv[idx], - wch); - - if (crc32 == option_name_hash) { - /* found it, get ready to hash the value */ - cmd_opt_meta->long_name_hash = option_name_hash; - cmd_opt_meta->long_name = argv[idx]; - cmd_opt_meta->argv_index = idx; - - if (*wch) - /* skip the equal sign */ - wch++; - - cmd_opt_meta->value = wch; - } else - idx++; - } - } - - if (cmd_opt_meta->value) - cmd_opt_meta->value_hash = - __compute_crc32_utf16_str( - crc32_table, - cmd_opt_meta->value); - - return NT_STATUS_SUCCESS; -} - - -int32_t __stdcall __ntapi_tt_validate_program_options( - __in const uint32_t * crc32_table, - __in wchar16_t * argv[], - __in nt_program_option * options[], - __in nt_program_options_meta * options_meta) -{ - int idx; - int idx_arg; - int idx_option; - int idx_max; - uint32_t crc32; - nt_program_option * option; - wchar16_t * parg; - wchar16_t * pvalue; - - /* validation */ - if (!crc32_table) - return NT_STATUS_INVALID_PARAMETER_1; - else if (!argv) - return NT_STATUS_INVALID_PARAMETER_2; - else if (!options) - return NT_STATUS_INVALID_PARAMETER_3; - else if (!options_meta) - return NT_STATUS_INVALID_PARAMETER_4; - - - /* step 1: validate options[] hash the long option names */ - idx = 0; - idx_option = 0; - option = options[0]; - pvalue = (wchar16_t *)0; - - while (!__is_last_program_option(option)) { - if (option->short_name_code) { - if (!(__is_bmp_code_point(option->short_name_code))) { - options_meta->idx_invalid_short_name = idx; - return NT_STATUS_INVALID_PARAMETER; - } - } - - if (option->long_name) { - if (!(__is_long_option(option->long_name))) { - options_meta->idx_invalid_long_name = idx; - return NT_STATUS_INVALID_PARAMETER; - } - - /* update the long name hash (unconditionally) */ - option->long_name_hash = - __compute_crc32_utf16_str( - crc32_table, - option->long_name); - } - - idx++; - option++; - } - - /* book keeping */ - idx_max = idx; - - /* step 2: validate argv[] */ - parg = argv[0]; - idx_arg = 0; - - while ((parg) && (!(__is_last_option_argument(parg)))) { - if (__is_short_option(parg)) { - idx = 0; - idx_option = 0; - - while ((idx < idx_max) && (!idx_option)) { - option = options[idx]; - - if (*(parg+1) == option->short_name_code) - idx_option = idx; - else - idx++; - } - - if (idx == idx_max) { - options_meta->idx_invalid_argument = idx_arg; - return NT_STATUS_INVALID_PARAMETER; - } else { - /* get ready for the next element (or value) */ - parg++; - idx_arg++; - pvalue = parg; - } - } else if (__is_long_option(parg)) { - idx = 0; - idx_option = 0; - /* find the equal sign or null termination */ - pvalue = parg; - while ((*pvalue) && (*pvalue != EQUAL_SIGN)) - pvalue++; - - while ((idx < idx_max) && (!idx_option)) { - option = options[idx]; - crc32 = __compute_crc32_long_option_name( - crc32_table, - parg, - pvalue); - - if (crc32 == option->long_name_hash) - idx_option = idx; - else - idx++; - } - - if (idx == idx_max) { - options_meta->idx_invalid_argument = idx_arg; - return NT_STATUS_INVALID_PARAMETER; - } else { - if (*pvalue != EQUAL_SIGN) - /* skip the equal sign */ - pvalue++; - pvalue = (wchar16_t *)0; - } - } - - /* validate the occurrence */ - if (idx_option) { - if (option->flags & NT_OPTION_ALLOWED_ONCE) { - if (option->option_count) { - options_meta->idx_invalid_argument - = idx_arg; - return NT_STATUS_INVALID_PARAMETER; - } else { - option->option_count++; - } - } - - if (option->flags & NT_OPTION_VALUE_REQUIRED) { - if ((!(*pvalue)) || (*pvalue == HYPHEN)) { - options_meta->idx_missing_option_value - = idx_arg; - return NT_STATUS_INVALID_PARAMETER; - } else { - option->value = pvalue; - option->value_hash = - __compute_crc32_utf16_str( - crc32_table, - option->value); - } - } - } - - parg++; - idx_arg++; - } - - return NT_STATUS_SUCCESS; -} |