aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2022-04-21 02:37:15 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2022-04-21 02:37:15 +0000
commit8cd2200ba1758cd127a1b95ab1808cde4f56713c (patch)
tree81f7e8e9c995548351865b77c13092ebf40d7174 /lib
parentf26bb872bf4f043a1b817c808a6947fcb03ecda4 (diff)
downloadsg3_utils-8cd2200ba1758cd127a1b95ab1808cde4f56713c.tar.gz
sg_opcodes: add --inhex=FN to process earlier -HHH, add experimental --json[=JO] option; sg_turs: change nanosleep() to Sleep() in MinGW
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@945 6180dd3e-e324-4e3e-922d-17de1ae2f315
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am1
-rw-r--r--lib/Makefile.in46
-rw-r--r--lib/sg_json_builder.c4
-rw-r--r--lib/sg_json_builder.h17
-rw-r--r--lib/sg_lib.c14
-rw-r--r--lib/sg_pr2serr.c242
6 files changed, 285 insertions, 39 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index b481816d..77e56408 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,5 +1,6 @@
libsgutils2_la_SOURCES = \
sg_lib.c \
+ sg_pr2serr.c \
sg_lib_data.c \
sg_lib_names.c \
sg_cmds_basic.c \
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 1a6dbeee..64cf1d08 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -144,7 +144,7 @@ am__uninstall_files_from_dir = { \
}
am__installdirs = "$(DESTDIR)$(libdir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
-am__libsgutils2_la_SOURCES_DIST = sg_lib.c sg_lib_data.c \
+am__libsgutils2_la_SOURCES_DIST = sg_lib.c sg_pr2serr.c sg_lib_data.c \
sg_lib_names.c sg_cmds_basic.c sg_cmds_basic2.c \
sg_cmds_extra.c sg_cmds_mmc.c sg_pt_common.c sg_json_builder.c \
sg_pt_dummy.c sg_pt_linux.c sg_io_linux.c sg_pt_linux_nvme.c \
@@ -165,14 +165,14 @@ am__libsgutils2_la_SOURCES_DIST = sg_lib.c sg_lib_data.c \
@OS_NETBSD_TRUE@am__objects_11 = sg_pt_dummy.lo
@OS_OPENBSD_TRUE@am__objects_12 = sg_pt_dummy.lo
@OS_OTHER_TRUE@am__objects_13 = sg_pt_dummy.lo
-am_libsgutils2_la_OBJECTS = sg_lib.lo sg_lib_data.lo sg_lib_names.lo \
- sg_cmds_basic.lo sg_cmds_basic2.lo sg_cmds_extra.lo \
- sg_cmds_mmc.lo sg_pt_common.lo sg_json_builder.lo \
- $(am__objects_1) $(am__objects_2) $(am__objects_3) \
- $(am__objects_4) $(am__objects_5) $(am__objects_6) \
- $(am__objects_7) $(am__objects_8) $(am__objects_9) \
- $(am__objects_10) $(am__objects_11) $(am__objects_12) \
- $(am__objects_13)
+am_libsgutils2_la_OBJECTS = sg_lib.lo sg_pr2serr.lo sg_lib_data.lo \
+ sg_lib_names.lo sg_cmds_basic.lo sg_cmds_basic2.lo \
+ sg_cmds_extra.lo sg_cmds_mmc.lo sg_pt_common.lo \
+ sg_json_builder.lo $(am__objects_1) $(am__objects_2) \
+ $(am__objects_3) $(am__objects_4) $(am__objects_5) \
+ $(am__objects_6) $(am__objects_7) $(am__objects_8) \
+ $(am__objects_9) $(am__objects_10) $(am__objects_11) \
+ $(am__objects_12) $(am__objects_13)
libsgutils2_la_OBJECTS = $(am_libsgutils2_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -202,11 +202,11 @@ am__depfiles_remade = ./$(DEPDIR)/sg_cmds_basic.Plo \
./$(DEPDIR)/sg_cmds_mmc.Plo ./$(DEPDIR)/sg_io_linux.Plo \
./$(DEPDIR)/sg_json_builder.Plo ./$(DEPDIR)/sg_lib.Plo \
./$(DEPDIR)/sg_lib_data.Plo ./$(DEPDIR)/sg_lib_names.Plo \
- ./$(DEPDIR)/sg_pt_common.Plo ./$(DEPDIR)/sg_pt_dummy.Plo \
- ./$(DEPDIR)/sg_pt_freebsd.Plo ./$(DEPDIR)/sg_pt_haiku.Plo \
- ./$(DEPDIR)/sg_pt_linux.Plo ./$(DEPDIR)/sg_pt_linux_nvme.Plo \
- ./$(DEPDIR)/sg_pt_osf1.Plo ./$(DEPDIR)/sg_pt_solaris.Plo \
- ./$(DEPDIR)/sg_pt_win32.Plo
+ ./$(DEPDIR)/sg_pr2serr.Plo ./$(DEPDIR)/sg_pt_common.Plo \
+ ./$(DEPDIR)/sg_pt_dummy.Plo ./$(DEPDIR)/sg_pt_freebsd.Plo \
+ ./$(DEPDIR)/sg_pt_haiku.Plo ./$(DEPDIR)/sg_pt_linux.Plo \
+ ./$(DEPDIR)/sg_pt_linux_nvme.Plo ./$(DEPDIR)/sg_pt_osf1.Plo \
+ ./$(DEPDIR)/sg_pt_solaris.Plo ./$(DEPDIR)/sg_pt_win32.Plo
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -377,13 +377,14 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-libsgutils2_la_SOURCES = sg_lib.c sg_lib_data.c sg_lib_names.c \
- sg_cmds_basic.c sg_cmds_basic2.c sg_cmds_extra.c sg_cmds_mmc.c \
- sg_pt_common.c sg_json_builder.c $(am__append_1) \
- $(am__append_2) $(am__append_3) $(am__append_4) \
- $(am__append_5) $(am__append_6) $(am__append_7) \
- $(am__append_8) $(am__append_9) $(am__append_10) \
- $(am__append_11) $(am__append_12) $(am__append_13)
+libsgutils2_la_SOURCES = sg_lib.c sg_pr2serr.c sg_lib_data.c \
+ sg_lib_names.c sg_cmds_basic.c sg_cmds_basic2.c \
+ sg_cmds_extra.c sg_cmds_mmc.c sg_pt_common.c sg_json_builder.c \
+ $(am__append_1) $(am__append_2) $(am__append_3) \
+ $(am__append_4) $(am__append_5) $(am__append_6) \
+ $(am__append_7) $(am__append_8) $(am__append_9) \
+ $(am__append_10) $(am__append_11) $(am__append_12) \
+ $(am__append_13)
@DEBUG_FALSE@DBG_CFLAGS =
# This is active if --enable-debug given to ./configure
@@ -496,6 +497,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_lib.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_lib_data.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_lib_names.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pr2serr.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_common.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_dummy.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sg_pt_freebsd.Plo@am__quote@ # am--include-marker
@@ -675,6 +677,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/sg_lib.Plo
-rm -f ./$(DEPDIR)/sg_lib_data.Plo
-rm -f ./$(DEPDIR)/sg_lib_names.Plo
+ -rm -f ./$(DEPDIR)/sg_pr2serr.Plo
-rm -f ./$(DEPDIR)/sg_pt_common.Plo
-rm -f ./$(DEPDIR)/sg_pt_dummy.Plo
-rm -f ./$(DEPDIR)/sg_pt_freebsd.Plo
@@ -738,6 +741,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/sg_lib.Plo
-rm -f ./$(DEPDIR)/sg_lib_data.Plo
-rm -f ./$(DEPDIR)/sg_lib_names.Plo
+ -rm -f ./$(DEPDIR)/sg_pr2serr.Plo
-rm -f ./$(DEPDIR)/sg_pt_common.Plo
-rm -f ./$(DEPDIR)/sg_pt_dummy.Plo
-rm -f ./$(DEPDIR)/sg_pt_freebsd.Plo
diff --git a/lib/sg_json_builder.c b/lib/sg_json_builder.c
index 4d616989..ed2d1397 100644
--- a/lib/sg_json_builder.c
+++ b/lib/sg_json_builder.c
@@ -35,6 +35,10 @@
#include <stdlib.h>
#include <stdio.h>
+/* This code was fetched from https://github.com/json-parser/json-builder
+ * and comes with the 2 clause BSD license (shown above) which is the same
+ * license that most of the rest of this package uses. */
+
#ifdef _MSC_VER
#define snprintf _snprintf
#endif
diff --git a/lib/sg_json_builder.h b/lib/sg_json_builder.h
index 9d83b026..9027ed5b 100644
--- a/lib/sg_json_builder.h
+++ b/lib/sg_json_builder.h
@@ -28,11 +28,20 @@
* SUCH DAMAGE.
*/
-#ifndef _JSON_BUILDER_H
-#define _JSON_BUILDER_H
+#ifndef SG_JSON_BUILDER_H
+#define SG_JSON_BUILDER_H
+
+/* This code was fetched from https://github.com/json-parser/json-builder
+ * and comes with the 2 clause BSD license (shown above) which is the same
+ * license that most of the rest of this package uses.
+ *
+ * This header file is in this 'lib' directory so its interface is _not_
+ * published with sg3_utils other header files found in the 'include'
+ * directory. Currently only this header's implementation (i.e.
+ * sg_json_builder.c) and sg_pr2serr.c are the only users of this header. */
/*
- * Used to require json.h from json-parser but what was need as been
+ * Used to require json.h from json-parser but what was needed as been
* included in this header.
* https://github.com/udp/json-parser
*/
@@ -318,7 +327,7 @@ void json_builder_free (json_value *);
}
#endif
-#endif
+#endif /* SG_JSON_BUILDER_H */
diff --git a/lib/sg_lib.c b/lib/sg_lib.c
index 36af6e6f..86fd37dc 100644
--- a/lib/sg_lib.c
+++ b/lib/sg_lib.c
@@ -75,20 +75,6 @@ pr2ws(const char * fmt, ...)
return n;
}
-/* Users of the sg_pr2serr.h header need this function definition */
-int
-pr2serr(const char * fmt, ...)
-{
- va_list args;
- int n;
-
- va_start(args, fmt);
- n = vfprintf(stderr, fmt, args);
- va_end(args);
- return n;
-}
-
-
/* Want safe, 'n += snprintf(b + n, blen - n, ...)' style sequence of
* functions. Returns number of chars placed in cp excluding the
* trailing null char. So for cp_max_len > 0 the return value is always
diff --git a/lib/sg_pr2serr.c b/lib/sg_pr2serr.c
new file mode 100644
index 00000000..5bb87acf
--- /dev/null
+++ b/lib/sg_pr2serr.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2022 Douglas Gilbert.
+ * All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the BSD_LICENSE file.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "sg_pr2serr.h"
+#include "sg_json_builder.h"
+
+/*
+ * #define json_serialize_mode_multiline 0
+ * #define json_serialize_mode_single_line 1
+ * #define json_serialize_mode_packed 2
+ *
+ * #define json_serialize_opt_CRLF (1 << 1)
+ * #define json_serialize_opt_pack_brackets (1 << 2)
+ * #define json_serialize_opt_no_space_after_comma (1 << 3)
+ * #define json_serialize_opt_no_space_after_colon (1 << 4)
+ * #define json_serialize_opt_use_tabs (1 << 5)
+ */
+
+
+static const json_serialize_opts def_out_settings = {
+ json_serialize_mode_multiline, /* one of serialize_mode_* */
+ 0, /* serialize_opt_* OR-ed together */
+ 4 /* indent size */
+};
+
+/* Users of the sg_pr2serr.h header need this function definition */
+int
+pr2serr(const char * fmt, ...)
+{
+ va_list args;
+ int n;
+
+ va_start(args, fmt);
+ n = vfprintf(stderr, fmt, args);
+ va_end(args);
+ return n;
+}
+
+void
+sg_json_init_state(sg_json_state * jstp)
+{
+ jstp->pr_as_json = true;
+ jstp->pr_pretty = true;
+ jstp->pr_sorted = false;
+ jstp->pr_output = false;
+ jstp->pr_implemented = false;
+ jstp->pr_unimplemented = false;
+ jstp->pr_format = 0;
+ jstp->verbose = 0;
+ jstp->pr_indent_size = 4;
+ jstp->basep = NULL;
+ jstp->outputp = NULL;
+ jstp->userp = NULL;
+}
+
+sg_json_opaque_p
+sg_json_start(const char * util_name, const char * ver_str, int argc,
+ char *argv[], sg_json_state * jstp)
+{
+ int k;
+ json_value * jvp = json_object_new(0);
+ json_value * jv2p;
+ json_value * jap = json_array_new(0);
+
+ if ((NULL == jvp) || (NULL == jap)) {
+ if (jvp)
+ json_builder_free(jvp);
+ if (jap)
+ json_builder_free(jap);
+ return NULL;
+ }
+ jstp->basep = jvp;
+ json_array_push(jap, json_integer_new(1));
+ json_array_push(jap, json_integer_new(0));
+ json_object_push(jvp, "json_format_version", jap);
+ jap = json_array_new(0);
+ for (k = 0; k < argc; ++k)
+ json_array_push(jap, json_string_new(argv[k]));
+ jv2p = json_object_push(jvp, util_name, json_object_new(0));
+ if (ver_str)
+ json_object_push(jv2p, "version_date", json_string_new(ver_str));
+ else
+ json_object_push(jv2p, "version_date", json_string_new("0.0"));
+ json_object_push(jv2p, "argv", jap);
+ if (jstp->pr_output)
+ jstp->outputp = json_object_push(jv2p, "output", json_array_new(0));
+ return jvp;
+}
+
+void
+sgj_pr2file(sg_json_opaque_p jop, sg_json_state * jstp, FILE * fp)
+{
+ size_t len;
+ char * b;
+ json_value * jvp = (json_value *)jop;
+ json_serialize_opts out_settings;
+
+ memcpy(&out_settings, &def_out_settings, sizeof(out_settings));
+ if (jstp->pr_indent_size != def_out_settings.indent_size)
+ out_settings.indent_size = jstp->pr_indent_size;
+ if (! jstp->pr_pretty)
+ out_settings.mode = json_serialize_mode_single_line;
+
+ len = json_measure_ex(jvp, out_settings);
+ if (len < 1)
+ return;
+ if (jstp->verbose > 3)
+ fprintf(fp, "%s: serialization length: %zu bytes\n", __func__, len);
+ b = calloc(len, 1);
+ if (NULL == b) {
+ if (jstp->verbose > 3)
+ pr2serr("%s: unable to get %zu bytes on heap\n", __func__, len);
+ return;
+ }
+ json_serialize_ex(b, jvp, out_settings);
+ if (jstp->verbose > 3)
+ fprintf(fp, "json serialized:\n");
+ fprintf(fp, "%s\n", b);
+}
+
+void
+sg_json_free(sg_json_opaque_p jop)
+{
+ json_value * jvp = (json_value *)jop;
+
+ json_builder_free(jvp);
+}
+
+void
+sgj_pr_hr(sg_json_state * jsp, const char * fmt, ...)
+{
+ va_list args;
+
+ if (jsp->pr_as_json && jsp->pr_output) {
+ size_t len;
+ char b[256];
+
+ va_start(args, fmt);
+ len = vsnprintf(b, sizeof(b), fmt, args);
+ if ((len > 0) && (len < sizeof(b))) {
+ const char * cp = b;
+
+ if (b[len - 1] == '\n') {
+ b[len - 1] = '\0';
+ --len;
+ }
+ if ((len > 0) && ('\n' == b[0]))
+ ++cp;
+ json_array_push(jsp->outputp, json_string_new(cp));
+ }
+ va_end(args);
+ } else if (jsp->pr_as_json) {
+ va_start(args, fmt);
+ va_end(args);
+ } else {
+ va_start(args, fmt);
+ vfprintf(stdout, fmt, args);
+ va_end(args);
+ }
+}
+
+sg_json_opaque_p
+sgj_new_named_object(sg_json_state * jsp, sg_json_opaque_p jop,
+ const char * name)
+{
+ sg_json_opaque_p resp = NULL;
+
+ if (jsp->pr_as_json)
+ resp = json_object_push(jop, name, json_object_new(0));
+ return resp;
+}
+
+sg_json_opaque_p
+sgj_new_named_array(sg_json_state * jsp, sg_json_opaque_p jop,
+ const char * name)
+{
+ sg_json_opaque_p resp = NULL;
+
+ if (jsp->pr_as_json)
+ resp = json_object_push(jop, name, json_array_new(0));
+ return resp;
+}
+
+sg_json_opaque_p
+sgj_add_array_element(sg_json_state * jsp, sg_json_opaque_p jap,
+ sg_json_opaque_p ejop)
+{
+ if (jsp->pr_as_json)
+ return json_array_push(jap, ejop);
+ else
+ return NULL;
+}
+
+/* Newly created object is un-attached */
+sg_json_opaque_p
+sgj_new_object(sg_json_state * jsp)
+{
+ return jsp->pr_as_json ? json_object_new(0) : NULL;
+}
+
+sg_json_opaque_p
+sgj_add_name_vs(sg_json_state * jsp, sg_json_opaque_p jop, const char * name,
+ const char * value)
+{
+ if (jsp->pr_as_json)
+ return json_object_push(jop, name, json_string_new(value));
+ else
+ return NULL;
+}
+
+sg_json_opaque_p
+sgj_add_name_vi(sg_json_state * jsp, sg_json_opaque_p jop, const char * name,
+ int64_t value)
+{
+ if (jsp->pr_as_json)
+ return json_object_push(jop, name, json_integer_new(value));
+ else
+ return NULL;
+}
+
+sg_json_opaque_p
+sgj_add_name_vb(sg_json_state * jsp, sg_json_opaque_p jop, const char * name,
+ bool value)
+{
+ if (jsp->pr_as_json)
+ return json_object_push(jop, name, json_boolean_new(value));
+ else
+ return NULL;
+}