From patchwork Wed Jul 25 20:50:25 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [08/14] qerror: add build_error_dict() and error_object_table[] Date: Wed, 25 Jul 2012 10:50:25 -0000 From: Luiz Capitulino X-Patchwork-Id: 173286 Message-Id: <1343249431-9245-9-git-send-email-lcapitulino@redhat.com> To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, aliguori@us.ibm.com, armbru@redhat.com, afaerber@suse.de, peter.maydell@linaro.org In the near future, the QERR_ macros (which are json strings today) will be turned into an enumeration. When we get there, build_error_dict() will be used to (guess what) build an error dict by: 1. Using the error class as an index to error_object_table[], which contains all QMP errors as json strings (with default values) 2. Use the human error string to construct the error object data member. For example, an error message like: "Parameter name=brain has not been found" Will construct the following data member: 'data': { 'name': 'brain' } } Signed-off-by: Luiz Capitulino --- qerror.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ qerror.h | 1 + scripts/qapi-errors.py | 39 +++++++++++++++++++++++ 3 files changed, 126 insertions(+) diff --git a/qerror.c b/qerror.c index 42e8687..267545e 100644 --- a/qerror.c +++ b/qerror.c @@ -38,6 +38,92 @@ static QError *qerror_new(void) return qerr; } +static bool iscchar(int c) +{ + return (isalpha(c) || isdigit(c) || c == '_'); +} + +static char *get_key(const char *str) +{ + char *p, *ret; + + ret = p = g_strdup(str); + + while (!iscchar(*p)) { + p++; + } + memmove(ret, p, strlen(ret)); + + p = ret; + while (iscchar(*p)) { + p++; + } + *p = '\0'; + + return ret; +} + +static char *get_value(const char *str) +{ + char *p, *ret; + + p = strchr(str, '='); + while (!iscchar(*p)) { + p++; + } + p = ret = g_strdup(p); + while (iscchar(*p)) { + p++; + } + *p = '\0'; + + return ret; +} + +static void set_dict_data(const char *msg, QDict *data_dict) +{ + char *str, *msg2, *saveptr = NULL; + + msg2 = g_strdup(msg); + str = strtok_r(msg2, " ", &saveptr); + while (str) { + if (strchr(str, '=')) { + char *key = get_key(str); + char *value = get_value(str); + + /* FIXME: handle ints */ + if (qdict_haskey(data_dict, key)) { + qdict_put(data_dict, key, qstring_from_str(value)); + } + + g_free(key); + g_free(value); + } + str = strtok_r(NULL, " ", &saveptr); + } + + g_free(msg2); +} + +QDict *build_error_dict(int err_class, const char *msg) +{ + QDict *err_dict; + QObject *obj; + + assert(msg[0] != '\0'); + + obj = qobject_from_json(error_object_table[err_class]); + assert(obj); + assert(qobject_type(obj) == QTYPE_QDICT); + + err_dict = qobject_to_qdict(obj); + assert(qdict_haskey(err_dict, "data")); + + set_dict_data(msg, qdict_get_qdict(err_dict, "data")); + + return err_dict; +} + static QDict *error_object_from_fmt(const char *fmt, va_list *va) { QObject *obj; diff --git a/qerror.h b/qerror.h index 16401ff..c4f6053 100644 --- a/qerror.h +++ b/qerror.h @@ -36,5 +36,6 @@ void qerror_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2); void qerror_report_err(Error *err); void assert_no_error(Error *err); char *qerror_format(const char *fmt, QDict *error); +QDict *build_error_dict(int err_class, const char *msg); #endif /* QERROR_H */ diff --git a/scripts/qapi-errors.py b/scripts/qapi-errors.py index 59cf426..5f8723e 100644 --- a/scripts/qapi-errors.py +++ b/scripts/qapi-errors.py @@ -85,6 +85,42 @@ static const QErrorStringTable qerror_table[] = { return ret +def gen_error_data_obj(data): + colon = '' + data_str = '' + for k, v in data.items(): + data_str += colon + "'%s': " % k + if v == 'str': + data_str += "'unknown'" + elif v == 'int': + data_str += '0' + else: + sys.exit("unknown data type '%s' for error '%s'" % (v, name)) + colon = ', ' + return data_str + +def gen_error_obj_table(exprs): + ret = mcgen(''' +static const char *error_object_table[] = { +''') + + for err in exprs: + data = gen_error_data_obj({}) + if err.has_key('data'): + data = gen_error_data_obj(err['data']) + ret += mcgen(''' + "{ 'class': '%(error_class)s', 'data': { %(error_data)s } }", +''', + error_class=err['error'], error_data=data) + + ret += mcgen(''' + NULL, +}; + +''') + + return ret; + def gen_error_macro_data_str(data): colon = '' data_str = '' @@ -173,5 +209,8 @@ if __name__ == '__main__': ret = gen_error_def_table(exprs) fdef.write(ret) + ret = gen_error_obj_table(exprs) + fdef.write(ret) + fdef.flush() fdef.close()