[PATCH 1/2] Replace json-c library with minimal replacement
Alex Hung
alex.hung at canonical.com
Fri Aug 21 19:17:25 UTC 2020
On 2020-08-21 4:43 a.m., Colin Ian King wrote:
> On 21/08/2020 11:35, ivanhu wrote:
>> Got build error blow, seems kernelscan.c still hasn't used these functions.
>> #include <json.h> in kernelscan.c
>
> Hrm, it works for me with a clean clone and applying the patches. Did
> you work from a fresh autoconfig. e.g.:
>
> autoreconf -ivf
> ./configure
> make
>
> Colin
>
>
>>
>> kernelscan.c: In function ‘klog_load’:
>> kernelscan.c:365:2: error: ‘json_object_object_get’ is deprecated
>> [-Werror=deprecated-declarations]
>> klog_table = json_object_object_get(klog_objs, table);
>> ^~~~~~~~~~
>> In file included from /usr/include/json-c/linkhash.h:16:0,
>> from /usr/include/json-c/json.h:22,
>> from kernelscan.c:28:
>> /usr/include/json-c/json_object.h:290:56: note: declared here
>> THIS_FUNCTION_IS_DEPRECATED(extern struct json_object*
>> json_object_object_get(struct json_object* obj,
>> ^
>> /usr/include/json-c/json_object.h:17:43: note: in definition of macro
>> ‘THIS_FUNCTION_IS_DEPRECATED’
>> #define THIS_FUNCTION_IS_DEPRECATED(func) func __attribute__ ((deprecated))
>> ^~~~
>> kernelscan.c:401:3: error: ‘json_object_object_get’ is deprecated
>> [-Werror=deprecated-declarations]
>> str = (char*)json_object_get_string(json_object_object_get(obj,
>> "compare_mode"));
>> ^~~
>> In file included from /usr/include/json-c/linkhash.h:16:0,
>> from /usr/include/json-c/json.h:22,
>> from kernelscan.c:28:
>> /usr/include/json-c/json_object.h:290:56: note: declared here
>> THIS_FUNCTION_IS_DEPRECATED(extern struct json_object*
>> json_object_object_get(struct json_object* obj,
>> ^
>> /usr/include/json-c/json_object.h:17:43: note: in definition of macro
>> ‘THIS_FUNCTION_IS_DEPRECATED’
>> #define THIS_FUNCTION_IS_DEPRECATED(func) func __attribute__ ((deprecated))
>> ^~~~
>> kernelscan.c:416:3: error: ‘json_object_object_get’ is deprecated
>> [-Werror=deprecated-declarations]
>> str = (char*)json_object_get_string(json_object_object_get(obj,
>> "pattern"));
>> ^~~
>> In file included from /usr/include/json-c/linkhash.h:16:0,
>> from /usr/include/json-c/json.h:22,
>> from kernelscan.c:28:
>> /usr/include/json-c/json_object.h:290:56: note: declared here
>> THIS_FUNCTION_IS_DEPRECATED(extern struct json_object*
>> json_object_object_get(struct json_object* obj,
>> ^
>> /usr/include/json-c/json_object.h:17:43: note: in definition of macro
>> ‘THIS_FUNCTION_IS_DEPRECATED’
>> #define THIS_FUNCTION_IS_DEPRECATED(func) func __attribute__ ((deprecated))
>> ^~~~
>>
>> Ivan
>>
>> On 8/17/20 6:22 PM, Colin King wrote:
>>> From: Colin Ian King <colin.king at canonical.com>
>>>
>>> FWTS uses a subset of json-c functionality, so replace it with
>>> our own implementation that supports this subset. This also
>>> removes the dependency of two flavours of json libraries that
>>> fwts has been using and also allows us to perform deeper memory
>>> allocation and leaking tracking with static analysis tools.
>>>
>>> Signed-off-by: Colin Ian King <colin.king at canonical.com>
>>> ---
>>> configure.ac | 3 -
>>> src/lib/include/fwts.h | 2 +
>>> src/lib/include/fwts_json.h | 61 ++-
>>> src/lib/src/Makefile.am | 1 +
>>> src/lib/src/fwts_json.c | 917 ++++++++++++++++++++++++++++++++++++
>>> src/utilities/Makefile.am | 5 +-
>>> 6 files changed, 969 insertions(+), 20 deletions(-)
>>> create mode 100644 src/lib/src/fwts_json.c
>>>
>>> diff --git a/configure.ac b/configure.ac
>>> index 39a445cd..f40c3678 100644
>>> --- a/configure.ac
>>> +++ b/configure.ac
>>> @@ -9,8 +9,6 @@
>>> AC_PROG_LIBTOOL
>>> AC_C_INLINE
>>> AM_PROG_CC_C_O
>>> - AC_SEARCH_LIBS([json_object_from_file], [json json-c], [], [ AC_MSG_ERROR([no available json library]) ])
>>> - AC_SEARCH_LIBS([json_object_object_get_ex], [json json-c], [ AC_DEFINE([JSON_HAS_GET_EX], [1], [Define if we have json_object_object_get_ex])], [])
>>> AC_CHECK_FUNCS([localtime_r])
>>> AC_CHECK_FUNCS([dup2])
>>> AC_CHECK_FUNCS([getcwd])
>>> @@ -61,7 +59,6 @@
>>> AC_CHECK_HEADERS([time.h])
>>> AC_CHECK_HEADERS([sys/ioctl.h])
>>> AC_CHECK_HEADERS([sys/time.h])
>>> - AC_CHECK_HEADERS([json/json.h])
>>> AC_CHECK_HEADERS([glib.h])
>>> AC_CHECK_HEADERS([gio/gio.h])
>>> AC_CHECK_HEADERS([asm/opal-prd.h])
>>> diff --git a/src/lib/include/fwts.h b/src/lib/include/fwts.h
>>> index 1e0d5870..6f13d262 100644
>>> --- a/src/lib/include/fwts.h
>>> +++ b/src/lib/include/fwts.h
>>> @@ -153,6 +153,8 @@
>>>
>>> #define FWTS_JSON_DATA_PATH DATAROOTDIR "/fwts"
>>>
>>> +#include <inttypes.h>
>>> +
>>> #include "fwts_version.h"
>>> #include "fwts_backtrace.h"
>>> #include "fwts_types.h"
>>> diff --git a/src/lib/include/fwts_json.h b/src/lib/include/fwts_json.h
>>> index ad51bc45..0c316e02 100644
>>> --- a/src/lib/include/fwts_json.h
>>> +++ b/src/lib/include/fwts_json.h
>>> @@ -1,5 +1,5 @@
>>> /*
>>> - * Copyright (C) 2012-2020 Canonical
>>> + * Copyright (C) 2010-2020 Canonical
>>> *
>>> * This program is free software; you can redistribute it and/or
>>> * modify it under the terms of the GNU General Public License
>>> @@ -16,26 +16,15 @@
>>> * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
>>> *
>>> */
>>> -
>>> #ifndef __FWTS_JSON_H__
>>> #define __FWTS_JSON_H__
>>>
>>> -#include <json.h>
>>> -
>>> -#define __FWTS_JSON_ERR_PTR__ ((json_object*) -1)
>>> /*
>>> - * Older versions of json-c may return an error in an
>>> - * object as a ((json_object*)-1), where as newer
>>> - * versions return NULL, so check for these. Sigh.
>>> + * Minimal subset of json for fwts
>>> */
>>> -#define FWTS_JSON_ERROR(ptr) \
>>> - ( (ptr == NULL) || ((const json_object *)ptr == __FWTS_JSON_ERR_PTR__) )
>>>
>>> -/*
>>> - * json-c 0.13.99 does not define TRUE/FALSE anymore
>>> - * the json-c maintainers replaced them with pure 1/0
>>> - * https://github.com/json-c/json-c/commit/0992aac61f8b
>>> - */
>>> +#define FWTS_JSON_ERROR(ptr) (!ptr)
>>> +
>>> #ifndef FALSE
>>> #define FALSE 0
>>> #endif
>>> @@ -44,4 +33,46 @@
>>> #define TRUE 1
>>> #endif
>>>
>>> +/*
>>> + * json types supported
>>> + */
>>> +typedef enum {
>>> + type_null,
>>> + type_int,
>>> + type_string,
>>> + type_object,
>>> + type_array,
>>> +} json_type;
>>> +
>>> +/*
>>> + * json object information
>>> + */
>>> +typedef struct json_object {
>>> + char *key; /* Null if undefined */
>>> + int length; /* Length of a collection of objects */
>>> + json_type type; /* Object type */
>>> + union {
>>> + void *ptr; /* string or object array pointer */
>>> + int intval; /* integer value */
>>> + } u;
>>> +} json_object;
>>> +
>>> +/*
>>> + * minimal json c library functions as required by fwts
>>> + */
>>> +json_object *json_object_from_file(const char *filename);
>>> +json_object *json_object_object_get(json_object *obj, const char *key);
>>> +int json_object_array_length(json_object *obj);
>>> +json_object *json_object_array_get_idx(json_object *obj, int index);
>>> +const char *json_object_get_string(json_object *obj);
>>> +json_object *json_object_new_int(int);
>>> +void json_object_object_add(json_object *obj, const char *key, json_object *value);
>>> +
>>> +json_object *json_object_new_object(void);
>>> +json_object *json_object_new_array(void);
>>> +char *json_object_to_json_string(json_object *obj);
>>> +void json_object_put(json_object *obj);
>>> +json_object *json_object_new_string(const char *str);
>>> +int json_object_array_add(json_object *obj, json_object *item);
>>> +
>>> #endif
>>> diff --git a/src/lib/src/Makefile.am b/src/lib/src/Makefile.am
>>> index ecc4136b..4593bb82 100644
>>> --- a/src/lib/src/Makefile.am
>>> +++ b/src/lib/src/Makefile.am
>>> @@ -82,6 +82,7 @@ libfwts_la_SOURCES = \
>>> fwts_interactive.c \
>>> fwts_ioport.c \
>>> fwts_ipmi.c \
>>> + fwts_json.c \
>>> fwts_keymap.c \
>>> fwts_klog.c \
>>> fwts_olog.c \
>>> diff --git a/src/lib/src/fwts_json.c b/src/lib/src/fwts_json.c
>>> new file mode 100644
>>> index 00000000..b92a241a
>>> --- /dev/null
>>> +++ b/src/lib/src/fwts_json.c
>>> @@ -0,0 +1,917 @@
>>> +/*
>>> + * Copyright (C) 2010-2020 Canonical
>>> + *
>>> + * This program is free software; you can redistribute it and/or
>>> + * modify it under the terms of the GNU General Public License
>>> + * as published by the Free Software Foundation; either version 2
>>> + * of the License, or (at your option) any later version.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program; if not, write to the Free Software
>>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
>>> + *
>>> + * This is a simplified json parser and json object store
>>> + * based on json but does not support keywords and is designed
>>> + * just for the fwts json data files. It is not a full json
>>> + * implementation and should not be used as such.
>>> + *
>>> + */
>>> +#include <stdlib.h>
>>> +#include <stdio.h>
>>> +#include <stdarg.h>
>>> +#include <stdbool.h>
>>> +#include <string.h>
>>> +#include <unistd.h>
>>> +#include <ctype.h>
>>> +
>>> +#include "fwts.h"
>>> +
>>> +/*
>>> + * json file information
>>> + */
>>> +typedef struct {
>>> + FILE *fp; /* File pointer */
>>> + const char *filename; /* Name of file */
>>> + int linenum; /* Parser line number */
>>> + int charnum; /* Parser char position */
>>> + int error_reported; /* Error count */
>>> +} json_file;
>>> +
>>> +/*
>>> + * json tokens, subset of full json token set as used
>>> + * for fwts requirements
>>> + */
>>> +typedef enum {
>>> + token_lbrace,
>>> + token_rbrace,
>>> + token_lbracket,
>>> + token_rbracket,
>>> + token_colon,
>>> + token_comma,
>>> + token_int,
>>> + token_string,
>>> + token_true,
>>> + token_false,
>>> + token_null,
>>> + token_error,
>>> + token_eof,
>>> +} json_token_type;
>>> +
>>> +/*
>>> + * json parser token
>>> + */
>>> +typedef struct {
>>> + json_token_type type; /* token type */
>>> + long offset; /* offset in file for re-winding */
>>> + union {
>>> + char *str; /* token string value */
>>> + int intval; /* token integer value */
>>> + } u;
>>> +} json_token;
>>> +
>>> +/*
>>> + * json_token_string()
>>> + * convert json token to a human readable string
>>> + */
>>> +char *json_token_string(json_token *jtoken)
>>> +{
>>> + static char tmp[64];
>>> +
>>> + switch (jtoken->type) {
>>> + case token_lbrace:
>>> + return "{";
>>> + case token_rbrace:
>>> + return "}";
>>> + case token_lbracket:
>>> + return "[";
>>> + case token_rbracket:
>>> + return "]";
>>> + case token_colon:
>>> + return ":";
>>> + case token_comma:
>>> + return ",";
>>> + case token_int:
>>> + (void)snprintf(tmp, sizeof(tmp), "%d", jtoken->u.intval);
>>> + return tmp;
>>> + case token_string:
>>> + return jtoken->u.str;
>>> + case token_error:
>>> + return "<error>";
>>> + case token_eof:
>>> + return "end of file";
>>> + default:
>>> + break;
>>> + }
>>> + return "<illegal token>";
>>> +}
>>> +
>>> +/*
>>> + * json_get_string()
>>> + * parse a literal string
>>> + */
>>> +json_token_type json_get_string(json_file *jfile, json_token *token)
>>> +{
>>> + char buffer[4096];
>>> + size_t i = 0;
>>> +
>>> + for (;;) {
>>> + int ch;
>>> +
>>> + ch = fgetc(jfile->fp);
>>> + jfile->charnum++;
>>> + if (ch == EOF) {
>>> + fprintf(stderr, "json_parser: unexpected EOF in literal string\n");
>>> + token->u.str = NULL;
>>> + return token_error;
>>> + }
>>> +
>>> + if (ch == '\\') {
>>> + ch = fgetc(jfile->fp);
>>> + switch (ch) {
>>> + case '\\':
>>> + case '"':
>>> + case '/':
>>> + break;
>>> + case 'b':
>>> + ch = '\b';
>>> + break;
>>> + case 'f':
>>> + ch = '\f';
>>> + break;
>>> + case 'n':
>>> + ch = '\n';
>>> + break;
>>> + case 'r':
>>> + ch = '\r';
>>> + break;
>>> + case 't':
>>> + ch = '\t';
>>> + break;
>>> + case 'u':
>>> + fprintf(stderr, "json parser: escaped hex values not supported\n");
>>> + ch = '?';
>>> + break;
>>> + }
>>> + jfile->charnum++;
>>> + } else if (ch == '"') {
>>> + buffer[i] = '\0';
>>> + token->u.str = strdup(buffer);
>>> + if (!token->u.str) {
>>> + fprintf(stderr, "json parser: out of memory allocating %zd byte string\n", i);
>>> + break;
>>> + }
>>> + return token_string;
>>> + }
>>> + buffer[i] = ch;
>>> + i++;
>>> + if (i >= sizeof(buffer)) {
>>> + fprintf(stderr, "json parser: string too long, maximum size %zd bytes\n", sizeof(buffer) - 1);
>>> + break;
>>> + }
>>> + }
>>> +
>>> + token->u.str = NULL;
>>> + return token_error;
>>> +}
>>> +
>>> +/*
>>> + * json_get_int()
>>> + * parse a simple integer
>>> + */
>>> +json_token_type json_get_int(json_file *jfile, json_token *token)
>>> +{
>>> + char buffer[64];
>>> + size_t i = 0;
>>> +
>>> + for (;;) {
>>> + int ch;
>>> +
>>> + ch = fgetc(jfile->fp);
>>> + if (!isdigit(ch)) {
>>> + (void)ungetc(ch, jfile->fp);
>>> + buffer[i] = '\0';
>>> + token->u.intval = atoi(buffer);
>>> + return token_int;
>>> + }
>>> + jfile->charnum++;
>>> + buffer[i] = ch;
>>> + i++;
>>> + if (i >= sizeof(buffer)) {
>>> + fprintf(stderr, "json parser: integer too long, maximum size %zd bytes\n", sizeof(buffer) - 1);
>>> + break;
>>> + }
>>> + }
>>> +
>>> + token->u.str = NULL;
>>> + return token_error;
>>> +}
>>> +
>>> +/*
>>> + * json_unget_token()
>>> + * push file pointer back to point before the token
>>> + * to unpush the token
>>> + */
>>> +int json_unget_token(json_file *jfile, json_token *token)
>>> +{
>>> + return fseek(jfile->fp, token->offset, SEEK_SET);
>>> +}
>>> +
>>> +/*
>>> + * json_get_keyword()
>>> + * get a keyword
>>> + */
>>> +int json_get_keyword(json_file *jfile, json_token *token)
>>> +{
>>> + char buffer[32];
>>> + size_t i = 0;
>>> +
>>> + token->u.str = NULL;
>>> + *buffer = '\0';
>>> +
>>> + for (;;) {
>>> + int ch;
>>> +
>>> + ch = fgetc(jfile->fp);
>>> + jfile->charnum++;
>>> + if (ch == EOF) {
>>> + fprintf(stderr, "json_parser: unexpected EOF in keyword string\n");
>>> + return token_error;
>>> + }
>>> + if (ch < 'a' || ch > 'z')
>>> + break;
>>> +
>>> + buffer[i] = ch;
>>> + i++;
>>> + if (i >= sizeof(buffer)) {
>>> + fprintf(stderr, "json parser: keyword too long, maximum size %zd bytes\n", sizeof(buffer) - 1);
>>> + return token_error;
>>> + }
>>> + }
>>> + if (!strcmp(buffer, "true"))
>>> + return token_true;
>>> + if (!strcmp(buffer, "false"))
>>> + return token_false;
>>> + if (!strcmp(buffer, "null"))
>>> + return token_null;
>>> + return token_error;
>>> +}
>>> +
>>> +/*
>>> + * json_get_token()
>>> + * read next input character(s) and return a matching token
>>> + */
>>> +json_token_type json_get_token(json_file *jfile, json_token *token)
>>> +{
>>> + (void)memset(token, 0, sizeof(*token));
>>> +
>>> + token->offset = ftell(jfile->fp);
>>> + for (;;) {
>>> + int ch;
>>> +
>>> + ch = fgetc(jfile->fp);
>>> + jfile->charnum++;
>>> +
>>> + switch (ch) {
>>> + case '\n':
>>> + jfile->linenum++;
>>> + continue;
>>> + case ' ':
>>> + case '\r':
>>> + case '\t':
>>> + continue;
>>> + case EOF:
>>> + token->type = token_eof;
>>> + return token->type;
>>> + case '{':
>>> + token->type = token_lbrace;
>>> + return token->type;
>>> + case '}':
>>> + token->type = token_rbrace;
>>> + return token->type;
>>> + case '[':
>>> + token->type = token_lbracket;
>>> + return token->type;
>>> + case ']':
>>> + token->type = token_rbracket;
>>> + return token->type;
>>> + case ':':
>>> + token->type = token_colon;
>>> + return token->type;
>>> + case ',':
>>> + token->type = token_comma;
>>> + return token->type;
>>> + case '"':
>>> + token->type = json_get_string(jfile, token);
>>> + return token->type;
>>> + case '0'...'9':
>>> + token->type = json_get_int(jfile, token);
>>> + return token->type;
>>> + case 'a'...'z':
>>> + fprintf(stderr, "json_parser: keywords not supported\n");
>>> + token->type = token_error;
>>> + return token->type;
>>> + default:
>>> + token->type = token_error;
>>> + return token->type;
>>> + }
>>> + }
>>> +
>>> + /* Should never reach here */
>>> + token->type = token_error;
>>> + return token->type;
>>> +}
>>> +
>>> +/*
>>> + * json_parse_error_where()
>>> + * very simple parser error message, report where in the file
>>> + * the parsing error occurred.
>>> + */
>>> +void json_parse_error_where(json_file *jfile)
>>> +{
>>> + if (jfile->error_reported == 0)
>>> + fprintf(stderr, "json_parser: aborted at line %d, char %d of file %s\n",
>>> + jfile->linenum, jfile->charnum, jfile->filename);
>>> + jfile->error_reported++;
>>> +}
>>> +
>>> +json_object *json_parse_object(json_file *jfile);
>>> +
>>> +/*
>>> + * json_parse_array()
>>> + * parse a json array
>>> + */
>>> +json_object *json_parse_array(json_file *jfile)
>>> +{
>>> + json_object *array_obj;
>>> +
>>> + array_obj = json_object_new_array();
>>> + if (!array_obj) {
>>> + fprintf(stderr, "json_parser: out of memory allocating a json array object\n");
>>> + json_parse_error_where(jfile);
>>> + return NULL;
>>> + }
>>> +
>>> + for (;;) {
>>> + json_object *obj;
>>> + json_token token;
>>> +
>>> + obj = json_parse_object(jfile);
>>> + if (!obj) {
>>> + json_parse_error_where(jfile);
>>> + free(array_obj);
>>> + return NULL;
>>> + }
>>> + json_object_array_add(array_obj, obj);
>>> +
>>> + switch (json_get_token(jfile, &token)) {
>>> + case token_rbracket:
>>> + return array_obj;
>>> + case token_comma:
>>> + continue;
>>> + default:
>>> + if (json_unget_token(jfile, &token) != 0) {
>>> + fprintf(stderr, "json_parser: failed to unget a token\n");
>>> + free(array_obj);
>>> + return NULL;
>>> + }
>>> + break;
>>> + }
>>> + }
>>> + return array_obj;
>>> +}
>>> +
>>> +/*
>>> + * json_parse_object()
>>> + * parse a json object (simplified fwts json format only)
>>> + */
>>> +json_object *json_parse_object(json_file *jfile)
>>> +{
>>> + json_token token;
>>> + json_object *obj, *val_obj;
>>> + char *key = NULL;
>>> +
>>> + if (json_get_token(jfile, &token) != token_lbrace) {
>>> + fprintf(stderr, "json_parser: expecting '{', got %s instead\n", json_token_string(&token));
>>> + return NULL;
>>> + }
>>> +
>>> + obj = json_object_new_object();
>>> + if (!obj)
>>> + goto err_nomem;
>>> +
>>> + for (;;) {
>>> + switch (json_get_token(jfile, &token)) {
>>> + case token_rbrace:
>>> + return obj;
>>> + case token_string:
>>> + key = token.u.str;
>>> + if (!key)
>>> + goto err_nomem;
>>> + token.u.str = NULL;
>>> + break;
>>> + default:
>>> + fprintf(stderr, "json_parser: expecting } or key literal string, got %s instead\n", json_token_string(&token));
>>> + goto err_free;
>>> + }
>>> + if (json_get_token(jfile, &token) != token_colon) {
>>> + fprintf(stderr, "json_parser: expecting ':', got %s instead\n", json_token_string(&token));
>>> + goto err_free;
>>> + }
>>> + switch (json_get_token(jfile, &token)) {
>>> + case token_string:
>>> + val_obj = json_object_new_string(token.u.str);
>>> + if (!val_obj)
>>> + goto err_nomem;
>>> + json_object_object_add(obj, key, val_obj);
>>> + free(key);
>>> + break;
>>> + case token_int:
>>> + val_obj = json_object_new_int(token.u.intval);
>>> + if (!val_obj)
>>> + goto err_nomem;
>>> + json_object_object_add(obj, key, val_obj);
>>> + free(key);
>>> + break;
>>> + case token_lbracket:
>>> + val_obj = json_parse_array(jfile);
>>> + if (!val_obj)
>>> + goto err_nomem;
>>> + json_object_object_add(obj, key, val_obj);
>>> + break;
>>> + case token_lbrace:
>>> + fprintf(stderr, "json_parser: nested objects not supported\n");
>>> + goto err_free;
>>> + case token_true:
>>> + case token_false:
>>> + case token_null:
>>> + fprintf(stderr, "json_parser: tokens %s not supported\n", json_token_string(&token));
>>> + goto err_free;
>>> + default:
>>> + fprintf(stderr, "json_parser: unexpected token %s\n", json_token_string(&token));
>>> + }
>>> + switch (json_get_token(jfile, &token)) {
>>> + case token_comma:
>>> + continue;
>>> + case token_rbrace:
>>> + return obj;
>>> + default:
>>> + fprintf(stderr, "json_parser: expected , or }, got %s instead\n", json_token_string(&token));
>>> + goto err_free;
>>> + }
>>> + }
>>> +
>>> +err_nomem:
>>> + fprintf(stderr, "json_parser: out of memory allocating a json object\n");
>>> + json_parse_error_where(jfile);
>>> +err_free:
>>> + free(obj);
>>> + return NULL;
>>> +}
>>> +
>>> +/*
>>> + * json_object_from_file()
>>> + * parse a simplified fwts json file and convert it into
>>> + * a json object, return NULL if parsing failed or ran
>>> + * out of memory
>>> + */
>>> +json_object *json_object_from_file(const char *filename)
>>> +{
>>> + json_object *obj;
>>> + json_file jfile;
>>> +
>>> + jfile.filename = filename;
>>> + jfile.linenum = 1;
>>> + jfile.charnum = 0;
>>> + jfile.error_reported = 0;
>>> +
>>> + jfile.fp = fopen(filename, "r");
>>> + if (!jfile.fp)
>>> + return NULL;
>>> +
>>> + obj = json_parse_object(&jfile);
>>> +
>>> + fclose(jfile.fp);
>>> + return obj;
>>> +}
>>> +
>>> +/*
>>> + * json_object_new_object()
>>> + * return a new json object, NULL if failed
>>> + */
>>> +json_object *json_object_new_object(void)
>>> +{
>>> + json_object *obj;
>>> +
>>> + obj = calloc(1, sizeof(*obj));
>>> + if (!obj)
>>> + return NULL;
>>> + obj->type = type_object;
>>> + obj->u.ptr = NULL;
>>> +
>>> + return obj;
>>> +}
>>> +
>>> +/*
>>> + * json_object_new_object()
>>> + * return a new json object, NULL if failed
>>> + */
>>> +int json_object_array_length(json_object *obj)
>>> +{
>>> + if (!obj)
>>> + return 0;
>>> + if (obj->type != type_array)
>>> + return 0;
>>> + return obj->length;
>>> +}
>>> +
>>> +/*
>>> + * json_object_new_int()
>>> + * return a new json integer object, NULL if failed
>>> + */
>>> +json_object *json_object_new_int(int val)
>>> +{
>>> + json_object *obj;
>>> +
>>> + obj = calloc(1, sizeof(*obj));
>>> + if (!obj)
>>> + return NULL;
>>> + obj->type = type_int;
>>> + obj->u.intval = val;
>>> +
>>> + return obj;
>>> +}
>>> +
>>> +/*
>>> + * json_object_new_string()
>>> + * return a new json string object, NULL if failed
>>> + */
>>> +json_object *json_object_new_string(const char *str)
>>> +{
>>> + json_object *obj;
>>> +
>>> + obj = calloc(1, sizeof(*obj));
>>> + if (!obj)
>>> + return NULL;
>>> + obj->type = type_string;
>>> + obj->u.ptr = strdup(str);
>>> + if (!obj->u.ptr) {
>>> + free(obj);
>>> + return NULL;
>>> + }
>>> + return obj;
>>> +}
>>> +
>>> +/*
>>> + * json_object_new_array()
>>> + * return a new json array object, NULL if failed
>>> + */
>>> +json_object *json_object_new_array(void)
>>> +{
>>> + json_object *obj;
>>> +
>>> + obj = calloc(1, sizeof(*obj));
>>> + if (!obj)
>>> + return NULL;
>>> + obj->type = type_array;
>>> + obj->length = 0;
>>> + obj->u.ptr = NULL;
>>> +
>>> + return obj;
>>> +}
>>> +
>>> +/*
>>> + * json_object_array_add_item()
>>> + * add an object to another object, return 0 if succeeded,
>>> + * non-zero if failed
>>> + */
>>> +static int json_object_array_add_item(json_object *obj, json_object *item)
>>> +{
>>> + json_object **obj_ptr;
>>> +
>>> + if (obj->length < 0)
>>> + return -1;
>>> + obj_ptr = realloc(obj->u.ptr, sizeof(json_object *) * (obj->length + 1));
>>> + if (!obj_ptr)
>>> + return -1;
>>> + obj->u.ptr = (void *)obj_ptr;
>>> + obj_ptr[obj->length] = item;
>>> + obj->length++;
>>> + return 0;
>>> +}
>>> +
>>> +/*
>>> + * json_object_array_add()
>>> + * add a object to a json array object, return NULL if failed
>>> + */
>>> +int json_object_array_add(json_object *obj, json_object *item)
>>> +{
>>> + if (!obj || !item)
>>> + return -1;
>>> + if (obj->type != type_array)
>>> + return -1;
>>> + return json_object_array_add_item(obj, item);
>>> +}
>>> +
>>> +
>>> +/*
>>> + * json_object_object_add()
>>> + * add a key/valyue object to a json object, return NULL if failed
>>> + */
>>> +void json_object_object_add(json_object *obj, const char *key, json_object *value)
>>> +{
>>> + if (!obj || !key || !value)
>>> + return;
>>> + if (obj->type != type_object)
>>> + return;
>>> + value->key = strdup(key);
>>> + if (!value->key)
>>> + return;
>>> + json_object_array_add_item(obj, value);
>>> +}
>>> +
>>> +/*
>>> + * json_object_array_get_idx()
>>> + * get an object at position index from a json array object,
>>> + * return NULL if failed
>>> + */
>>> +json_object *json_object_array_get_idx(json_object *obj, int index)
>>> +{
>>> + json_object **obj_array;
>>> +
>>> + if (!obj)
>>> + return NULL;
>>> + if (obj->type != type_array)
>>> + return NULL;
>>> + if (index >= obj->length)
>>> + return NULL;
>>> + obj_array = (json_object **)obj->u.ptr;
>>> + if (obj_array == NULL)
>>> + return NULL;
>>> + return obj_array[index];
>>> +}
>>> +
>>> +/*
>>> + * json_object_get_string()
>>> + * return a C string from a json string object
>>> + */
>>> +const char *json_object_get_string(json_object *obj)
>>> +{
>>> + if (!obj)
>>> + return NULL;
>>> + if (obj->type != type_string)
>>> + return NULL;
>>> + return (const char *)obj->u.ptr;
>>> +}
>>> +
>>> +/*
>>> + * json_object_put()
>>> + * free a json object and all sub-objects
>>> + */
>>> +void json_object_put(json_object *obj)
>>> +{
>>> + int i;
>>> + json_object **obj_ptr;
>>> +
>>> + if (!obj)
>>> + return;
>>> +
>>> + if (obj->key)
>>> + free(obj->key);
>>> +
>>> + switch (obj->type) {
>>> + case type_array:
>>> + case type_object:
>>> + obj_ptr = (json_object **)obj->u.ptr;
>>> +
>>> + for (i = 0; i < obj->length; i++) {
>>> + json_object_put(obj_ptr[i]);
>>> + }
>>> + free(obj->u.ptr);
>>> + break;
>>> + case type_string:
>>> + free(obj->u.ptr);
>>> + break;
>>> + case type_null:
>>> + case type_int:
>>> + default:
>>> + break;
>>> + }
>>> + free(obj);
>>> +}
>>> +
>>> +/*
>>> + * str_append()
>>> + * append a string to a string, return NULL if failed
>>> + */
>>> +static char *str_append(char *str, char *append)
>>> +{
>>> + char *new_str;
>>> + size_t len;
>>> +
>>> + if (!append)
>>> + return NULL;
>>> +
>>> + if (str) {
>>> + len = strlen(append) + strlen(str) + 1;
>>> + new_str = realloc(str, len);
>>> + if (!new_str) {
>>> + free(str);
>>> + return NULL;
>>> + }
>>> + strcat(new_str, append);
>>> + } else {
>>> + len = strlen(append) + 1;
>>> + new_str = malloc(len);
>>> + if (!new_str)
>>> + return NULL;
>>> + strcpy(new_str, append);
>>> + }
>>> + return new_str;
>>> +}
>>> +
>>> +/*
>>> + * str_indent()
>>> + * add 2 spaces per indent level to a string, returns
>>> + * NULL if failed
>>> + */
>>> +static char *str_indent(char *str, int indent)
>>> +{
>>> + char buf[81];
>>> + int i;
>>> +
>>> + indent = indent + indent;
>>> + if (indent > 80)
>>> + indent = 80;
>>> +
>>> + for (i = 0; i < indent; i++)
>>> + buf[i] = ' ';
>>> + buf[i] = '\0';
>>> +
>>> + return str_append(str, buf);
>>> +}
>>> +
>>> +/*
>>> + * json_object_to_json_string_indent()
>>> + * turn a simplified fwts json object into a C string, returns
>>> + * the stringified object or NULL if failed. Will traverse object
>>> + * tree and add indentation based on recursion depth.
>>> + */
>>> +static char *json_object_to_json_string_indent(json_object *obj, int indent)
>>> +{
>>> + int i;
>>> + json_object **obj_ptr;
>>> + char *str = NULL;
>>> + char buf[64];
>>> +
>>> + if (!obj)
>>> + return NULL;
>>> +
>>> + if (obj->type == type_object) {
>>> + str = str_indent(str, indent);
>>> + if (!str)
>>> + return NULL;
>>> + str = str_append(str, "{\n");
>>> + if (!str)
>>> + return NULL;
>>> + }
>>> +
>>> + if (obj->key) {
>>> + str = str_indent(str, indent);
>>> + if (!str)
>>> + return NULL;
>>> + str = str_append(str, "\"");
>>> + if (!str)
>>> + return NULL;
>>> + str = str_append(str, obj->key);
>>> + if (!str)
>>> + return NULL;
>>> + str = str_append(str, "\":");
>>> + if (!str)
>>> + return NULL;
>>> + }
>>> +
>>> + switch (obj->type) {
>>> + case type_array:
>>> + str = str_append(str, "[\n");
>>> + if (!str)
>>> + return NULL;
>>> +
>>> + obj_ptr = (json_object **)obj->u.ptr;
>>> + if (obj_ptr) {
>>> + for (i = 0; i < obj->length; i++) {
>>> + char *obj_str = json_object_to_json_string_indent(obj_ptr[i], indent + 1);
>>> +
>>> + if (!obj_str) {
>>> + free(str);
>>> + return NULL;
>>> + }
>>> + str = str_append(str, obj_str);
>>> + if (!str)
>>> + return NULL;
>>> + }
>>> + }
>>> + str = str_append(str, "\n");
>>> + if (!str)
>>> + return NULL;
>>> + str = str_indent(str, indent);
>>> + if (!str)
>>> + return NULL;
>>> + str = str_append(str, "]\n");
>>> + if (!str)
>>> + return NULL;
>>> + break;
>>> +
>>> + case type_object:
>>> + obj_ptr = (json_object **)obj->u.ptr;
>>> + if (obj_ptr) {
>>> + for (i = 0; i < obj->length; i++) {
>>> + char *obj_str = json_object_to_json_string_indent(obj_ptr[i], indent + 1);
>>> +
>>> + if (!obj_str)
>>> + return NULL;
>>> + str = str_append(str, obj_str);
>>> + if (!str)
>>> + return NULL;
>>> + }
>>> + }
>>> + if (!str)
>>> + return NULL;
>>> + break;
>>> +
>>> + case type_string:
>>> + str = str_append(str, "\"");
>>> + if (!str)
>>> + return NULL;
>>> + str = str_append(str, (char *)obj->u.ptr);
>>> + if (!str)
>>> + return NULL;
>>> + str = str_append(str, "\",\n");
>>> + if (!str)
>>> + return NULL;
>>> + break;
>>> +
>>> + case type_null:
>>> + str = str_append(str, "(null)\n");
>>> + if (!str)
>>> + return NULL;
>>> + break;
>>> +
>>> + case type_int:
>>> + snprintf(buf, sizeof(buf), "%d,\n", obj->u.intval);
>>> + str = str_append(str, buf);
>>> + if (!str)
>>> + return NULL;
>>> + break;
>>> + default:
>>> + return NULL;
>>> + }
>>> +
>>> + if (obj->type == type_object) {
>>> + str = str_indent(str, indent);
>>> + if (!str)
>>> + return NULL;
>>> + str = str_append(str, "},\n");
>>> + if (!str)
>>> + return NULL;
>>> + }
>>> + return str;
>>> +}
>>> +
>>> +/*
>>> + * json_object_to_json_string
>>> + * convert simplified fwts object to a C string, returns
>>> + * NULL if failed
>>> + */
>>> +char *json_object_to_json_string(json_object *obj)
>>> +{
>>> + return json_object_to_json_string_indent(obj, 0);
>>> +}
>>> +
>>> +/*
>>> + * json_object_object_get()
>>> + * return value from key/value pair from an object, returns
>>> + * NULL if it can't be found
>>> + */
>>> +json_object *json_object_object_get(json_object *obj, const char *key)
>>> +{
>>> + int i;
>>> + json_object **obj_ptr;
>>> +
>>> + if (!obj || !key)
>>> + return NULL;
>>> + if (obj->type != type_object)
>>> + return NULL;
>>> +
>>> + obj_ptr = (json_object **)obj->u.ptr;
>>> + for (i = 0; i < obj->length; i++) {
>>> + if (obj_ptr[i]->key && !strcmp(obj_ptr[i]->key, key))
>>> + return obj_ptr[i];
>>> + }
>>> + return NULL;
>>> +}
>>> +
>>> diff --git a/src/utilities/Makefile.am b/src/utilities/Makefile.am
>>> index 98d6ebaa..2ae86038 100644
>>> --- a/src/utilities/Makefile.am
>>> +++ b/src/utilities/Makefile.am
>>> @@ -18,10 +18,11 @@
>>>
>>> AM_CPPFLAGS = -Wall -Werror -Wextra -DDATAROOTDIR=\"$(datarootdir)\" \
>>> `pkg-config --silence-errors --cflags json` \
>>> - `pkg-config --silence-errors --cflags json-c`
>>> + `pkg-config --silence-errors --cflags json-c` \
>>> + -I../lib/include
>>>
>>> bin_PROGRAMS = kernelscan
>>> -kernelscan_SOURCES = kernelscan.c
>>> +kernelscan_SOURCES = kernelscan.c ../lib/src/fwts_json.c
>>>
>>>
>>> -include $(top_srcdir)/git.mk
>>>
>
>
I did a test build on PPA but got failures, ex.
https://launchpad.net/~firmware-testing-team/+archive/ubuntu/scratch/+build/19860987
--
Cheers,
Alex Hung
More information about the fwts-devel
mailing list