Skip to content

Commit

Permalink
Merge pull request #836 from xexyl/jval-jnamval-Sn
Browse files Browse the repository at this point in the history
  • Loading branch information
lcn2 authored Aug 9, 2023
2 parents 1581a56 + fd963b7 commit f73bbaf
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 135 deletions.
21 changes: 21 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Major changes to the IOCCC entry toolkit

## Release 1.0.52 2023-08-09

New version of `jval` and `jnamval`, `"0.0.14 2023-08-09"`.

Fixed the lists of `-S` and `-n` option parsing. For now it should just be a
string that's strdup()d. The operators are in the list in the order specified,
one list for strings and one list for numbers. This can be changed to a single
list later on if necessary (as I suspect it might need to be but the way it is
now is set up as two which is what I'm operating under).

The function that frees the `-S` and `-n` lists in `jval` and `jnamval` is now
in `json_util.c` as they are actually in a struct common to both `jval` and
`jnamval`. The functions that free them in `jval_util.c` and `jnamval_util.c`
simply check that `jval` or `jnamval` is not NULL and then calls the new
`free_json_util_cmp_list()` function.

Made the json util operator macros an enum.

Rename the enum `output_format` to `JSON_UTIL_OUTPUT_FMT`.


## Release 1.0.51 2023-08-07

Fix link in make rule `jparse.clone` to use
Expand Down
4 changes: 2 additions & 2 deletions jparse/jnamval.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,15 +300,15 @@ main(int argc, char **argv)
dbg(DBG_LOW, "-e specified, will encode strings");
break;
case 'n': /* -n op=num */
jnamval->json_name_val.num_cmp_used = true;
jnamval->json_name_val.numcmp_used = true;
if (json_util_parse_cmp_op(&jnamval->json_name_val, "n", optarg) == NULL) {
free_jnamval(&jnamval);
err(24, "jnamval", "couldn't parse -n option");
not_reached();
}
break;
case 'S': /* -S op=str */
jnamval->json_name_val.string_cmp_used = true;
jnamval->json_name_val.strcmp_used = true;
if (json_util_parse_cmp_op(&jnamval->json_name_val, "S", optarg) == NULL) {
free_jnamval(&jnamval);
err(25, "jnamval", "couldn't parse -S option");
Expand Down
2 changes: 1 addition & 1 deletion jparse/jnamval.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
#include "jparse.h"

/* jnamval version string */
#define JNAMVAL_VERSION "0.0.13 2023-08-07" /* format: major.minor YYYY-MM-DD */
#define JNAMVAL_VERSION "0.0.14 2023-08-09" /* format: major.minor YYYY-MM-DD */

/* jnamval functions - see jnamval_util.h for most */

Expand Down
30 changes: 5 additions & 25 deletions jparse/jnamval_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,11 @@ alloc_jnamval(void)
/* comparison options -S and -n */

/* -S op=string */
jnamval->json_name_val.string_cmp_used = false;
jnamval->json_name_val.string_cmp = NULL;
jnamval->json_name_val.strcmp_used = false;
jnamval->json_name_val.strcmp = NULL;
/* -n op=number */
jnamval->json_name_val.num_cmp_used = false;
jnamval->json_name_val.num_cmp = NULL;
jnamval->json_name_val.numcmp_used = false;
jnamval->json_name_val.numcmp = NULL;

/* parsing related */
jnamval->common.max_depth = JSON_DEFAULT_MAX_DEPTH; /* max depth to traverse set by -m depth */
Expand Down Expand Up @@ -913,31 +913,11 @@ parse_jnamval_args(struct jnamval *jnamval, int *argc, char ***argv)
void
free_jnamval_cmp_op_lists(struct jnamval *jnamval)
{
struct json_util_cmp_op *op, *next_op;

/* firewall */
if (jnamval == NULL) {
err(29, __func__, "jnamval is NULL");
not_reached();
}

/* first the string compare list */
for (op = jnamval->json_name_val.string_cmp; op != NULL; op = next_op) {
next_op = op->next;

/* XXX - free json node - XXX */

free(op);
op = NULL;
}

/* now the number compare list */
for (op = jnamval->json_name_val.num_cmp; op != NULL; op = next_op) {
next_op = op->next;

/* XXX - free json node - XXX */

free(op);
op = NULL;
}
free_json_util_cmp_list(&jnamval->json_name_val);
}
177 changes: 115 additions & 62 deletions jparse/json_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -2726,9 +2726,9 @@ json_util_parse_cmp_op(struct json_util_name_val *json_name_val, const char *opt
{
char *p = NULL; /* to find the = separator */
char *mode = NULL; /* if -S then "str" else "num" */
struct json *item = NULL; /* to get the converted value */
struct json_util_cmp_op *cmp = NULL; /* to add to list */
int op = JSON_UTIL_CMP_OP_NONE; /* assume no op for syntax wrong */
struct json_util_cmp_op *tmp_cmp = NULL; /* to append to list */
enum JSON_UTIL_CMP_OP op = JSON_CMP_OP_NONE; /* assume no op for syntax error */

/* firewall */
if (json_name_val == NULL) {
Expand All @@ -2749,99 +2749,152 @@ json_util_parse_cmp_op(struct json_util_name_val *json_name_val, const char *opt
} else if (!strcmp(option, "n")) {
mode = "num";
} else {
err(30, __func__, "invalid option used for function: -%s", option);
err(30, __func__, "invalid arg used for option: -%s", option);
not_reached();
}

p = strchr(optarg, '=');
if (p == NULL) {
err(31, __func__, "syntax error in -%s: use -%s {eq,lt,le,gt,ge}=%s", option, option, mode);
err(31, __func__, "syntax error in -%s: use -%s {eq,lt,le,gt,ge,ne}=%s", option, option, mode);
not_reached();
} else if (p == optarg) {
err(32, __func__, "syntax error in -%s: use -%s {eq,lt,le,gt,ge}=%s", option, option, mode);
err(32, __func__, "syntax error in -%s: use -%s {eq,lt,le,gt,ge,ne}=%s", option, option, mode);
not_reached();
} else if (p[1] == '\0') {
err(33, __func__, "nothing found after =: use -%s {eq,lt,le,gt,ge}=%s", option, mode);
err(33, __func__, "nothing found after =: use -%s {eq,lt,le,gt,ge,ne}=%s", option, mode);
not_reached();
}

if (!strncmp(optarg, "eq=", 3)) {
op = JSON_UTIL_CMP_EQ;
op = JSON_CMP_OP_EQ;
} else if (!strncmp(optarg, "lt=", 3)) {
op = JSON_UTIL_CMP_LT;
op = JSON_CMP_OP_LT;
} else if (!strncmp(optarg, "le=", 3)) {
op = JSON_UTIL_CMP_LE;
op = JSON_CMP_OP_LE;
} else if (!strncmp(optarg, "gt=", 3)){
op = JSON_UTIL_CMP_GT;
op = JSON_CMP_OP_GT;
} else if (!strncmp(optarg, "ge=", 3)) {
op = JSON_UTIL_CMP_GE;
op = JSON_CMP_OP_GE;
} else if (!strncmp(optarg, "ne=", 3)) {
op = JSON_CMP_OP_NE;
} else {
err(34, __func__, "invalid op found for -%s: use -%s {eq,lt,le,gt,ge}=%s", option, option, mode);
err(34, __func__, "invalid op found for -%s: use -%s {eq,lt,le,gt,ge,ne}=%s", option, option, mode);
not_reached();
}

errno = 0; /* pre-clear errno for errp() */
cmp = calloc(1, sizeof *cmp);
if (cmp == NULL) {
errp(36, __func__, "failed to allocate struct json_util_cmp_op * for -%s %s=%s", option, optarg, optarg + 3);
not_reached();
} else {
/* explicitly clear out struct */
cmp->string = NULL;

cmp->is_string = false;
cmp->is_number = false;

/* set up operator which we already have */
cmp->op = op;

/* next in list starts at NULL */
cmp->next = NULL;
}
if (!strcmp(option, "S")) { /* -S */
errno = 0;
item = json_conv_string(optarg + 3, strlen(optarg + 3), *(optarg +3) == '"' ? true : false);
if (item == NULL) {
err(35, __func__, "failed to convert string <%s> for -%s", optarg + 3, option);
errno = 0; /* pre-clear errno for errp() */
cmp->string = strdup(optarg + 3);
if (cmp->string == NULL) {
errp(37, __func__, "failed to strdup string: <%s> for -%s: cmp->string is NULL", optarg + 3, option);
not_reached();
} else {
cmp = calloc(1, sizeof *cmp);
if (cmp == NULL) {
err(36, __func__, "failed to allocate struct json_util_cmp_op *");
not_reached();
}
cmp->string = &(item->item.string);
if (cmp->string == NULL) {
err(37, __func__, "failed to convert string: <%s> for -%s: cmp->string is NULL", optarg + 3, option);
not_reached();
} else if (!CONVERTED_PARSED_JSON_NODE(cmp->string)) {
err(38, __func__, "failed to convert or parse string: <%s> for option -%s but string pointer not NULL!",
optarg + 3, option);
not_reached();
}
}

cmp->op = op;
cmp->is_string = true;

cmp->next = json_name_val->string_cmp;
json_name_val->string_cmp = cmp;
/* append to string compare list */
for (tmp_cmp = json_name_val->strcmp; tmp_cmp && tmp_cmp->next != NULL; tmp_cmp = tmp_cmp->next)
;; /* on a separate line to silence dubious warnings */

/* XXX - add function that prints out what compare operation - XXX */
json_dbg(JSON_DBG_NONE, __func__, "string to compare: <%s>", cmp->string->str);
if (tmp_cmp == NULL) {
json_name_val->strcmp = cmp;
} else {
tmp_cmp->next = cmp;
}

/* XXX - add function that prints out what compare operation - XXX */
json_dbg(JSON_DBG_NONE, __func__, "string to compare: <%s>", cmp->string);
} else if (!strcmp(option, "n")) { /* -n */
item = json_conv_number(optarg + 3, strlen(optarg + 3));
if (item == NULL) {
err(39, __func__, "syntax error in -%s: no number found: <%s>", option, optarg + 3);
errno = 0; /* pre-clear errno for errp() */
cmp->string = strdup(optarg + 3);
if (cmp->string == NULL) {
err(37, __func__, "failed to strdup string: <%s> for -%s: cmp->string is NULL", optarg + 3, option);
not_reached();
}
cmp->is_number = true;

/* append to number compare list */
for (tmp_cmp = json_name_val->numcmp; tmp_cmp && tmp_cmp->next != NULL; tmp_cmp = tmp_cmp->next)
;; /* on a separate line to silence dubious warnings */

if (tmp_cmp == NULL) {
json_name_val->numcmp = cmp;
} else {
cmp = calloc(1, sizeof *cmp);
if (cmp == NULL) {
err(40, __func__, "failed to allocate struct json_util_cmp_op *");
not_reached();
}
cmp->number = &(item->item.number);
if (!CONVERTED_PARSED_JSON_NODE(cmp->number)) {
err(7, __func__, "failed to convert or parse number: <%s> for option -%s but number pointer not NULL!",/*ooo*/
optarg + 3, option);
not_reached();
} else if (PARSED_JSON_NODE(cmp->number) && !CONVERTED_JSON_NODE(cmp->number)) {
err(7, __func__, "failed to convert number: <%s> for option -%s", optarg +3 , option); /*ooo*/
not_reached();
}
tmp_cmp->next = cmp;
}

/* XXX - add function that prints out what compare operation - XXX */
json_dbg(JSON_DBG_NONE, __func__, "number to compare: <%s>", cmp->string);
}

return cmp;
}

/* free_json_util_cmp_list - free a compare list for jval / jnamval -S and -n options
*
* given:
*
* json_name_val - struct with the compare lists
*
* This function does not return on NULL pointer passed in.
*
* This function returns void.
*/
void
free_json_util_cmp_list(struct json_util_name_val *json_name_val)
{
struct json_util_cmp_op *op, *next_op;

cmp->op = op;
/* firewall */
if (json_name_val == NULL) {
err(35, __func__, "NULL json_name_val");
not_reached();
}

cmp->next = json_name_val->num_cmp;
json_name_val->num_cmp = cmp;
/* first the string compare list */
for (op = json_name_val->strcmp; op != NULL; op = next_op) {
next_op = op->next;

/* XXX - add function that prints out what compare operation - XXX */
json_dbg(JSON_DBG_NONE, __func__, "number to compare: <%s>", cmp->number->as_str);
if (op->string != NULL) {
free(op->string);
op->string = NULL;
}

free(op);
op = NULL;
}

/* now the number compare list */
for (op = json_name_val->numcmp; op != NULL; op = next_op) {
next_op = op->next;

if (op->string != NULL) {
free(op->string);
op->string = NULL;
}

free(op);
op = NULL;
}

return cmp;
}

/* parse_json_util_format - parse -F format option of jfmt, jval and jnamval
Expand All @@ -2855,13 +2908,13 @@ json_util_parse_cmp_op(struct json_util_name_val *json_name_val, const char *opt
*
* This function will not return on NULL pointer.
*
* This function returns an enum output_format which is also given in the struct
* This function returns an enum JSON_UTIL_OUTPUT_FMT which is also given in the struct
* json_util json_util in the struct of the tool used.
*/
enum output_format
enum JSON_UTIL_OUTPUT_FMT
parse_json_util_format(struct json_util *json_util, char const *name, char const *optarg)
{
enum output_format format = JSON_FMT_TTY;
enum JSON_UTIL_OUTPUT_FMT format = JSON_FMT_TTY;

/* firewall */

Expand Down
Loading

0 comments on commit f73bbaf

Please sign in to comment.