summaryrefslogtreecommitdiffhomepage
path: root/src/argv
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2016-06-29 10:49:47 -0400
committermidipix <writeonce@midipix.org>2016-06-29 19:16:37 -0400
commitf7b99942f85f4c8c35058f1a8b1194cd4468bc6d (patch)
tree890e0f326a2d0fbee61ae6062f26a4bd9dbef90c /src/argv
parenta2ea1bdf70166f887457b5462332d2df4f6f54c5 (diff)
downloadntapi-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.c93
-rw-r--r--src/argv/ntapi_tt_get_option.c450
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;
-}