diff options
Diffstat (limited to 'l4arg.c')
-rw-r--r-- | l4arg.c | 399 |
1 files changed, 200 insertions, 199 deletions
@@ -1,3 +1,4 @@ +/* vim: set sw=4 ts=4 sts=4 et: */ #include "l4arg.h" #include "l4array.h" @@ -5,237 +6,237 @@ #include <string.h> LbsStrv* lbs_arg_parse (const char* str, const char* delim, - const char* esc, const LbsArgQuote* q, LbsArray** detail_ptr) { + const char* esc, const LbsArgQuote* q, LbsArray** detail_ptr) { - LbsStrv* strv = lbs_strv_new (); - if (strv == NULL) { - return NULL; - } - /* goto label => free_strv */ + LbsStrv* strv = lbs_strv_new (); + if (strv == NULL) { + return NULL; + } + /* goto label => free_strv */ - // string length cache - int qlen; // user-supplied quoting string table length - for (qlen = 0; q[qlen].left != NULL && q[qlen].right != NULL; qlen++); + // string length cache + int qlen; // user-supplied quoting string table length + for (qlen = 0; q[qlen].left != NULL && q[qlen].right != NULL; qlen++); - // qlen will not be too long, so we can use VLA - int qlen_p = qlen <= 0 ? 1 : qlen; + // qlen will not be too long, so we can use VLA + int qlen_p = qlen <= 0 ? 1 : qlen; #if __STDC_NO_VLA__ - int* qllen = malloc (sizeof (int) * qlen_p); - if (qllen == NULL) { - lbs_strv_unref (strv); - return NULL; - } - int* qrlen = malloc (sizeof (int) * qlen_p); - if (qrlen == NULL) { - lbs_strv_unref (strv); - return NULL; - } + int* qllen = malloc (sizeof (int) * qlen_p); + if (qllen == NULL) { + lbs_strv_unref (strv); + return NULL; + } + int* qrlen = malloc (sizeof (int) * qlen_p); + if (qrlen == NULL) { + lbs_strv_unref (strv); + return NULL; + } #else - int qllen[qlen_p]; // left quoting string length - int qrlen[qlen_p]; // right quoting string length + int qllen[qlen_p]; // left quoting string length + int qrlen[qlen_p]; // right quoting string length #endif - for (int i = 0; i < qlen; i++) { - // empty strings are not allowed - qllen[i] = strlen (q[i].left); - if (qllen[i] <= 0) { - goto free_strv; - } - qrlen[i] = strlen (q[i].right); - if (qrlen[i] <= 0) { - goto free_strv; - } - } - - LbsArray* detail; - if (detail_ptr != NULL) { - detail = lbs_array_new (sizeof (int)); - if (detail == NULL) { - goto free_strv; - } - if (lbs_array_push_back (detail, &(int){-1}) < 0) { - goto free_detail; - } - } else { - detail = NULL; - } - /* goto label => free_detail */ - - bool is_delimed = true; - bool is_escaped = false; - bool is_quoted = false; - bool ignore_esc = false; - int stri = 0; // strv index - int qi; // quoting string index currently used - - const char* p = str; - for (; *p != '\0'; p++) { + for (int i = 0; i < qlen; i++) { + // empty strings are not allowed + qllen[i] = strlen (q[i].left); + if (qllen[i] <= 0) { + goto free_strv; + } + qrlen[i] = strlen (q[i].right); + if (qrlen[i] <= 0) { + goto free_strv; + } + } + + LbsArray* detail; + if (detail_ptr != NULL) { + detail = lbs_array_new (sizeof (int)); + if (detail == NULL) { + goto free_strv; + } + if (lbs_array_push_back (detail, &(int){-1}) < 0) { + goto free_detail; + } + } else { + detail = NULL; + } + /* goto label => free_detail */ + + bool is_delimed = true; + bool is_escaped = false; + bool is_quoted = false; + bool ignore_esc = false; + int stri = 0; // strv index + int qi; // quoting string index currently used + + const char* p = str; + for (; *p != '\0'; p++) { loop_start: - if (is_escaped) { - if (lbs_strv_append_char (strv, stri, *p) < 0) { - goto free_detail; - } - is_escaped = false; - continue; - } - - if (is_quoted) { - if (strncmp (p, q[qi].right, qrlen[qi]) == 0) { - is_quoted = false; - is_escaped = false; - ignore_esc = false; - p += qrlen[qi] - 1; - } else { - if (!ignore_esc && strchr (esc, *p)) { - is_escaped = true; - } else { - if (lbs_strv_append_char (strv, stri, *p) < 0) { - goto free_detail; - } - } - } - continue; - } - - if (strchr (delim, *p)) { - if (is_delimed) { - continue; - } - if (lbs_strv_append_str_empty (strv) < 0) { - goto free_detail; - } - if (detail != NULL && lbs_array_push_back (detail, &(int){-1}) < 0) { - goto free_detail; - } - stri++; - is_delimed = true; - continue; - } - if (strchr (esc, *p)) { - is_escaped = true; - continue; - } - - is_delimed = false; - - for (int i = 0; i < qlen; i++) { - if (strncmp (p, q[i].left, qllen[i]) == 0) { - is_quoted = true; - ignore_esc = q[i].super; - qi = i; - p += qllen[qi]; // p++ will be skipped, so do not minus 1 here - if (detail != NULL) { - lbs_array_v (detail, int, stri) = qi; - } - goto loop_start; // restart the loop - } - } - - if (lbs_strv_append_char (strv, stri, *p) < 0) { - goto free_detail; - } - } - - if (is_delimed && lbs_strv_get_str_len (strv, stri) == 0) { - lbs_strv_remove_str (strv); - lbs_array_pop_back (detail); - } - - if (detail_ptr != NULL) { - *detail_ptr = detail; - } + if (is_escaped) { + if (lbs_strv_append_char (strv, stri, *p) < 0) { + goto free_detail; + } + is_escaped = false; + continue; + } + + if (is_quoted) { + if (strncmp (p, q[qi].right, qrlen[qi]) == 0) { + is_quoted = false; + is_escaped = false; + ignore_esc = false; + p += qrlen[qi] - 1; + } else { + if (!ignore_esc && strchr (esc, *p)) { + is_escaped = true; + } else { + if (lbs_strv_append_char (strv, stri, *p) < 0) { + goto free_detail; + } + } + } + continue; + } + + if (strchr (delim, *p)) { + if (is_delimed) { + continue; + } + if (lbs_strv_append_str_empty (strv) < 0) { + goto free_detail; + } + if (detail != NULL && lbs_array_push_back (detail, &(int){-1}) < 0) { + goto free_detail; + } + stri++; + is_delimed = true; + continue; + } + if (strchr (esc, *p)) { + is_escaped = true; + continue; + } + + is_delimed = false; + + for (int i = 0; i < qlen; i++) { + if (strncmp (p, q[i].left, qllen[i]) == 0) { + is_quoted = true; + ignore_esc = q[i].super; + qi = i; + p += qllen[qi]; // p++ will be skipped, so do not minus 1 here + if (detail != NULL) { + lbs_array_v (detail, int, stri) = qi; + } + goto loop_start; // restart the loop + } + } + + if (lbs_strv_append_char (strv, stri, *p) < 0) { + goto free_detail; + } + } + + if (is_delimed && lbs_strv_get_str_len (strv, stri) == 0) { + lbs_strv_remove_str (strv); + lbs_array_pop_back (detail); + } + + if (detail_ptr != NULL) { + *detail_ptr = detail; + } #if __STDC_NO_VLA__ - free (qllen); - free (qrlen); + free (qllen); + free (qrlen); #endif - return strv; + return strv; - /* Error-handling goto label */ + /* Error-handling goto label */ free_detail: - if (detail != NULL) { - lbs_array_unref (detail); - } + if (detail != NULL) { + lbs_array_unref (detail); + } free_strv: #if __STDC_NO_VLA__ - free (qllen); - free (qrlen); + free (qllen); + free (qrlen); #endif - lbs_strv_unref (strv); - return NULL; + lbs_strv_unref (strv); + return NULL; } LbsArgQopt* lbs_arg_qopt_new (const char* str) { - LbsStrv* strv; - LbsArray* detail; - - strv = lbs_arg_parse (str, ",", "\\", (LbsArgQuote[]) { - { "\"", "\"", false }, { "\'", "\'", true }, { NULL, NULL, false}}, - &detail); - - if (strv == NULL || detail == NULL) { - return NULL; - } - /* goto label => free_detail_and_strv */ - - size_t strv_len = lbs_strv_get_len (strv); - LbsArgQopt* qopt = malloc (sizeof (LbsArgQopt) + - sizeof (LbsArgQoptItem) * (strv_len + 1)); - if (qopt == NULL) { - goto free_detail_and_strv; - } - - qopt->len = strv_len; - qopt->strv = NULL; - qopt->detail = NULL; - qopt->opts[strv_len] = (LbsArgQoptItem) { NULL, NULL }; - - for (size_t i = 0; i < strv_len; i++) { - qopt->opts[i].name = lbs_strv_dup_str (strv, i); - if (qopt->opts[i].name == NULL) { - goto free_qopt; - } - - char* pos = strchr (qopt->opts[i].name, '='); - if (pos == NULL) { - qopt->opts[i].value = NULL; - } else { - *pos = '\0'; - qopt->opts[i].value = pos + 1; - } - - } - - qopt->strv = strv; - qopt->detail = detail; - return qopt; + LbsStrv* strv; + LbsArray* detail; + + strv = lbs_arg_parse (str, ",", "\\", (LbsArgQuote[]) { + { "\"", "\"", false }, { "\'", "\'", true }, { NULL, NULL, false}}, + &detail); + + if (strv == NULL || detail == NULL) { + return NULL; + } + /* goto label => free_detail_and_strv */ + + size_t strv_len = lbs_strv_get_len (strv); + LbsArgQopt* qopt = malloc (sizeof (LbsArgQopt) + + sizeof (LbsArgQoptItem) * (strv_len + 1)); + if (qopt == NULL) { + goto free_detail_and_strv; + } + + qopt->len = strv_len; + qopt->strv = NULL; + qopt->detail = NULL; + qopt->opts[strv_len] = (LbsArgQoptItem) { NULL, NULL }; + + for (size_t i = 0; i < strv_len; i++) { + qopt->opts[i].name = lbs_strv_dup_str (strv, i); + if (qopt->opts[i].name == NULL) { + goto free_qopt; + } + + char* pos = strchr (qopt->opts[i].name, '='); + if (pos == NULL) { + qopt->opts[i].value = NULL; + } else { + *pos = '\0'; + qopt->opts[i].value = pos + 1; + } + + } + + qopt->strv = strv; + qopt->detail = detail; + return qopt; free_qopt: - lbs_arg_qopt_free (qopt); + lbs_arg_qopt_free (qopt); free_detail_and_strv: - lbs_strv_unref (strv); - lbs_array_unref (detail); - return NULL; + lbs_strv_unref (strv); + lbs_array_unref (detail); + return NULL; } void lbs_arg_qopt_free_generic (void* qopt_generic) { - if (qopt_generic == NULL) { - return; - } + if (qopt_generic == NULL) { + return; + } - LbsArgQopt* qopt = qopt_generic; - lbs_strv_unref (qopt->strv); - lbs_array_unref (qopt->detail); + LbsArgQopt* qopt = qopt_generic; + lbs_strv_unref (qopt->strv); + lbs_array_unref (qopt->detail); - for (int i = 0; qopt->opts[i].name != NULL; i++) { - free (qopt->opts[i].name); - } + for (int i = 0; qopt->opts[i].name != NULL; i++) { + free (qopt->opts[i].name); + } - free (qopt); + free (qopt); } |