1*44704f69SBart Van Assche /*
2*44704f69SBart Van Assche * Copyright (c) 2022 Douglas Gilbert.
3*44704f69SBart Van Assche * All rights reserved.
4*44704f69SBart Van Assche * Use of this source code is governed by a BSD-style
5*44704f69SBart Van Assche * license that can be found in the BSD_LICENSE file.
6*44704f69SBart Van Assche *
7*44704f69SBart Van Assche * SPDX-License-Identifier: BSD-2-Clause
8*44704f69SBart Van Assche */
9*44704f69SBart Van Assche
10*44704f69SBart Van Assche #include <unistd.h>
11*44704f69SBart Van Assche #include <stdio.h>
12*44704f69SBart Van Assche #include <stdlib.h>
13*44704f69SBart Van Assche #include <stdarg.h>
14*44704f69SBart Van Assche #include <stdbool.h>
15*44704f69SBart Van Assche #include <string.h>
16*44704f69SBart Van Assche #include <ctype.h>
17*44704f69SBart Van Assche
18*44704f69SBart Van Assche #include "sg_pr2serr.h"
19*44704f69SBart Van Assche #include "sg_json_builder.h"
20*44704f69SBart Van Assche
21*44704f69SBart Van Assche /*
22*44704f69SBart Van Assche * Some users of sg_pr2serr may not need fixed and descriptor sense decoded
23*44704f69SBart Van Assche * for JSON output. If the following define is commented out the effective
24*44704f69SBart Van Assche * compile size of this file is reduced by 800 lines plus dependencies on
25*44704f69SBart Van Assche * other large components of the sg3_utils library.
26*44704f69SBart Van Assche * Comment out the next line to remove dependency on sg_lib.h and its code.
27*44704f69SBart Van Assche */
28*44704f69SBart Van Assche #define SG_PRSE_SENSE_DECODE 1
29*44704f69SBart Van Assche
30*44704f69SBart Van Assche #ifdef SG_PRSE_SENSE_DECODE
31*44704f69SBart Van Assche #include "sg_lib.h"
32*44704f69SBart Van Assche #include "sg_lib_data.h"
33*44704f69SBart Van Assche #include "sg_unaligned.h"
34*44704f69SBart Van Assche #endif
35*44704f69SBart Van Assche
36*44704f69SBart Van Assche
37*44704f69SBart Van Assche #define sgj_opts_ev "SG3_UTILS_JSON_OPTS"
38*44704f69SBart Van Assche
39*44704f69SBart Van Assche /*
40*44704f69SBart Van Assche * #define json_serialize_mode_multiline 0
41*44704f69SBart Van Assche * #define json_serialize_mode_single_line 1
42*44704f69SBart Van Assche * #define json_serialize_mode_packed 2
43*44704f69SBart Van Assche *
44*44704f69SBart Van Assche * #define json_serialize_opt_CRLF (1 << 1)
45*44704f69SBart Van Assche * #define json_serialize_opt_pack_brackets (1 << 2)
46*44704f69SBart Van Assche * #define json_serialize_opt_no_space_after_comma (1 << 3)
47*44704f69SBart Van Assche * #define json_serialize_opt_no_space_after_colon (1 << 4)
48*44704f69SBart Van Assche * #define json_serialize_opt_use_tabs (1 << 5)
49*44704f69SBart Van Assche */
50*44704f69SBart Van Assche
51*44704f69SBart Van Assche
52*44704f69SBart Van Assche static const json_serialize_opts def_out_settings = {
53*44704f69SBart Van Assche json_serialize_mode_multiline, /* one of serialize_mode_* */
54*44704f69SBart Van Assche 0, /* serialize_opt_* OR-ed together */
55*44704f69SBart Van Assche 4 /* indent size */
56*44704f69SBart Van Assche };
57*44704f69SBart Van Assche
58*44704f69SBart Van Assche static int sgj_name_to_snake(const char * in, char * out, int maxlen_out);
59*44704f69SBart Van Assche
60*44704f69SBart Van Assche
61*44704f69SBart Van Assche /* Users of the sg_pr2serr.h header need this function definition */
62*44704f69SBart Van Assche int
pr2serr(const char * fmt,...)63*44704f69SBart Van Assche pr2serr(const char * fmt, ...)
64*44704f69SBart Van Assche {
65*44704f69SBart Van Assche va_list args;
66*44704f69SBart Van Assche int n;
67*44704f69SBart Van Assche
68*44704f69SBart Van Assche va_start(args, fmt);
69*44704f69SBart Van Assche n = vfprintf(stderr, fmt, args);
70*44704f69SBart Van Assche va_end(args);
71*44704f69SBart Van Assche return n;
72*44704f69SBart Van Assche }
73*44704f69SBart Van Assche
74*44704f69SBart Van Assche #ifndef SG_PRSE_SENSE_DECODE
75*44704f69SBart Van Assche
76*44704f69SBart Van Assche /* Want safe, 'n += snprintf(b + n, blen - n, ...)' style sequence of
77*44704f69SBart Van Assche * functions. Returns number of chars placed in cp excluding the
78*44704f69SBart Van Assche * trailing null char. So for cp_max_len > 0 the return value is always
79*44704f69SBart Van Assche * < cp_max_len; for cp_max_len <= 1 the return value is 0 and no chars are
80*44704f69SBart Van Assche * written to cp. Note this means that when cp_max_len = 1, this function
81*44704f69SBart Van Assche * assumes that cp[0] is the null character and does nothing (and returns
82*44704f69SBart Van Assche * 0). Linux kernel has a similar function called scnprintf(). Public
83*44704f69SBart Van Assche * declaration in sg_pr2serr.h header */
84*44704f69SBart Van Assche int
sg_scnpr(char * cp,int cp_max_len,const char * fmt,...)85*44704f69SBart Van Assche sg_scnpr(char * cp, int cp_max_len, const char * fmt, ...)
86*44704f69SBart Van Assche {
87*44704f69SBart Van Assche va_list args;
88*44704f69SBart Van Assche int n;
89*44704f69SBart Van Assche
90*44704f69SBart Van Assche if (cp_max_len < 2)
91*44704f69SBart Van Assche return 0;
92*44704f69SBart Van Assche va_start(args, fmt);
93*44704f69SBart Van Assche n = vsnprintf(cp, cp_max_len, fmt, args);
94*44704f69SBart Van Assche va_end(args);
95*44704f69SBart Van Assche return (n < cp_max_len) ? n : (cp_max_len - 1);
96*44704f69SBart Van Assche }
97*44704f69SBart Van Assche
98*44704f69SBart Van Assche int
pr2ws(const char * fmt,...)99*44704f69SBart Van Assche pr2ws(const char * fmt, ...)
100*44704f69SBart Van Assche {
101*44704f69SBart Van Assche va_list args;
102*44704f69SBart Van Assche int n;
103*44704f69SBart Van Assche
104*44704f69SBart Van Assche va_start(args, fmt);
105*44704f69SBart Van Assche n = vfprintf(stderr, fmt, args);
106*44704f69SBart Van Assche va_end(args);
107*44704f69SBart Van Assche return n;
108*44704f69SBart Van Assche }
109*44704f69SBart Van Assche
110*44704f69SBart Van Assche #endif
111*44704f69SBart Van Assche
112*44704f69SBart Van Assche static bool
sgj_parse_opts(sgj_state * jsp,const char * j_optarg)113*44704f69SBart Van Assche sgj_parse_opts(sgj_state * jsp, const char * j_optarg)
114*44704f69SBart Van Assche {
115*44704f69SBart Van Assche bool bad_arg = false;
116*44704f69SBart Van Assche bool prev_negate = false;
117*44704f69SBart Van Assche bool negate;
118*44704f69SBart Van Assche int k, c;
119*44704f69SBart Van Assche
120*44704f69SBart Van Assche for (k = 0; j_optarg[k]; ++k) { /* step over leading whitespace */
121*44704f69SBart Van Assche if (! isspace(j_optarg[k]))
122*44704f69SBart Van Assche break;
123*44704f69SBart Van Assche }
124*44704f69SBart Van Assche for ( ; j_optarg[k]; ++k) {
125*44704f69SBart Van Assche c = j_optarg[k];
126*44704f69SBart Van Assche negate = false;
127*44704f69SBart Van Assche switch (c) {
128*44704f69SBart Van Assche case '=':
129*44704f69SBart Van Assche if (0 == k)
130*44704f69SBart Van Assche break; /* allow and ignore leading '=' */
131*44704f69SBart Van Assche bad_arg = true;
132*44704f69SBart Van Assche if (0 == jsp->first_bad_char)
133*44704f69SBart Van Assche jsp->first_bad_char = c;
134*44704f69SBart Van Assche break;
135*44704f69SBart Van Assche case '!':
136*44704f69SBart Van Assche case '~':
137*44704f69SBart Van Assche case '-': /* '-' is probably most practical negation symbol */
138*44704f69SBart Van Assche negate = true;
139*44704f69SBart Van Assche break;
140*44704f69SBart Van Assche case '0':
141*44704f69SBart Van Assche case '2':
142*44704f69SBart Van Assche jsp->pr_indent_size = 2;
143*44704f69SBart Van Assche break;
144*44704f69SBart Van Assche case '3':
145*44704f69SBart Van Assche jsp->pr_indent_size = 3;
146*44704f69SBart Van Assche break;
147*44704f69SBart Van Assche case '4':
148*44704f69SBart Van Assche jsp->pr_indent_size = 4;
149*44704f69SBart Van Assche break;
150*44704f69SBart Van Assche case '8':
151*44704f69SBart Van Assche jsp->pr_indent_size = 8;
152*44704f69SBart Van Assche break;
153*44704f69SBart Van Assche case 'e':
154*44704f69SBart Van Assche jsp->pr_exit_status = ! prev_negate;
155*44704f69SBart Van Assche break;
156*44704f69SBart Van Assche case 'g':
157*44704f69SBart Van Assche jsp->pr_format = 'g';
158*44704f69SBart Van Assche break;
159*44704f69SBart Van Assche case 'h':
160*44704f69SBart Van Assche jsp->pr_hex = ! prev_negate;
161*44704f69SBart Van Assche break;
162*44704f69SBart Van Assche case 'k':
163*44704f69SBart Van Assche jsp->pr_packed = ! prev_negate;
164*44704f69SBart Van Assche break;
165*44704f69SBart Van Assche case 'l':
166*44704f69SBart Van Assche jsp->pr_leadin = ! prev_negate;
167*44704f69SBart Van Assche break;
168*44704f69SBart Van Assche case 'n':
169*44704f69SBart Van Assche jsp->pr_name_ex = ! prev_negate;
170*44704f69SBart Van Assche break;
171*44704f69SBart Van Assche case 'o':
172*44704f69SBart Van Assche jsp->pr_out_hr = ! prev_negate;
173*44704f69SBart Van Assche break;
174*44704f69SBart Van Assche case 'p':
175*44704f69SBart Van Assche jsp->pr_pretty = ! prev_negate;
176*44704f69SBart Van Assche break;
177*44704f69SBart Van Assche case 's':
178*44704f69SBart Van Assche jsp->pr_string = ! prev_negate;
179*44704f69SBart Van Assche break;
180*44704f69SBart Van Assche case 'v':
181*44704f69SBart Van Assche ++jsp->verbose;
182*44704f69SBart Van Assche break;
183*44704f69SBart Van Assche case 'y':
184*44704f69SBart Van Assche jsp->pr_format = 'g';
185*44704f69SBart Van Assche break;
186*44704f69SBart Van Assche case '?':
187*44704f69SBart Van Assche bad_arg = true;
188*44704f69SBart Van Assche jsp->first_bad_char = '\0';
189*44704f69SBart Van Assche break;
190*44704f69SBart Van Assche default:
191*44704f69SBart Van Assche bad_arg = true;
192*44704f69SBart Van Assche if (0 == jsp->first_bad_char)
193*44704f69SBart Van Assche jsp->first_bad_char = c;
194*44704f69SBart Van Assche break;
195*44704f69SBart Van Assche }
196*44704f69SBart Van Assche prev_negate = negate ? ! prev_negate : false;
197*44704f69SBart Van Assche }
198*44704f69SBart Van Assche return ! bad_arg;
199*44704f69SBart Van Assche }
200*44704f69SBart Van Assche
201*44704f69SBart Van Assche char *
sg_json_usage(int char_if_not_j,char * b,int blen)202*44704f69SBart Van Assche sg_json_usage(int char_if_not_j, char * b, int blen)
203*44704f69SBart Van Assche {
204*44704f69SBart Van Assche int n = 0;
205*44704f69SBart Van Assche char short_opt = char_if_not_j ? char_if_not_j : 'j';
206*44704f69SBart Van Assche
207*44704f69SBart Van Assche if ((NULL == b) || (blen < 1))
208*44704f69SBart Van Assche goto fini;
209*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, "JSON option usage:\n");
210*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
211*44704f69SBart Van Assche " --json[-JO] | -%c[JO]\n\n", short_opt);
212*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " where JO is a string of one or more "
213*44704f69SBart Van Assche "of:\n");
214*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
215*44704f69SBart Van Assche " 0 | 2 tab pretty output to 2 spaces\n");
216*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
217*44704f69SBart Van Assche " 4 tab pretty output to 4 spaces\n");
218*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
219*44704f69SBart Van Assche " 8 tab pretty output to 8 spaces\n");
220*44704f69SBart Van Assche if (n >= (blen - 1))
221*44704f69SBart Van Assche goto fini;
222*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
223*44704f69SBart Van Assche " e show 'exit_status' field\n");
224*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
225*44704f69SBart Van Assche " h show 'hex' fields\n");
226*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
227*44704f69SBart Van Assche " k packed, only non-pretty printed output\n");
228*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
229*44704f69SBart Van Assche " l show lead-in fields (invocation "
230*44704f69SBart Van Assche "information)\n");
231*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
232*44704f69SBart Van Assche " n show 'name_extra' information fields\n");
233*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
234*44704f69SBart Van Assche " o non-JSON output placed in 'output' array in "
235*44704f69SBart Van Assche "lead-in\n");
236*44704f69SBart Van Assche if (n >= (blen - 1))
237*44704f69SBart Van Assche goto fini;
238*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
239*44704f69SBart Van Assche " p pretty print the JSON output\n");
240*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
241*44704f69SBart Van Assche " s show string output (usually fields named "
242*44704f69SBart Van Assche "'meaning')\n");
243*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
244*44704f69SBart Van Assche " v make JSON output more verbose\n");
245*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
246*44704f69SBart Van Assche " = ignored if first character, else it's an "
247*44704f69SBart Van Assche "error\n");
248*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n,
249*44704f69SBart Van Assche " - | ~ | ! toggle next letter setting\n");
250*44704f69SBart Van Assche
251*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, "\nIn the absence of the optional JO "
252*44704f69SBart Van Assche "argument, the following are set\non: 'elps' while the "
253*44704f69SBart Van Assche "others are set off, and tabs are set to 4.\nBefore "
254*44704f69SBart Van Assche "command line JO options are applied, the environment\n"
255*44704f69SBart Van Assche "variable: %s is applied (if present). Note that\nno "
256*44704f69SBart Van Assche "space is permitted between the short option ('-%c') "
257*44704f69SBart Van Assche "and its\nargument ('JO').\n", sgj_opts_ev, short_opt);
258*44704f69SBart Van Assche fini:
259*44704f69SBart Van Assche return b;
260*44704f69SBart Van Assche }
261*44704f69SBart Van Assche
262*44704f69SBart Van Assche char *
sg_json_settings(sgj_state * jsp,char * b,int blen)263*44704f69SBart Van Assche sg_json_settings(sgj_state * jsp, char * b, int blen)
264*44704f69SBart Van Assche {
265*44704f69SBart Van Assche snprintf(b, blen, "%d%se%sh%sk%sl%sn%so%sp%ss%sv", jsp->pr_indent_size,
266*44704f69SBart Van Assche jsp->pr_exit_status ? "" : "-", jsp->pr_hex ? "" : "-",
267*44704f69SBart Van Assche jsp->pr_packed ? "" : "-", jsp->pr_leadin ? "" : "-",
268*44704f69SBart Van Assche jsp->pr_name_ex ? "" : "-", jsp->pr_out_hr ? "" : "-",
269*44704f69SBart Van Assche jsp->pr_pretty ? "" : "-", jsp->pr_string ? "" : "-",
270*44704f69SBart Van Assche jsp->verbose ? "" : "-");
271*44704f69SBart Van Assche return b;
272*44704f69SBart Van Assche }
273*44704f69SBart Van Assche
274*44704f69SBart Van Assche static void
sgj_def_opts(sgj_state * jsp)275*44704f69SBart Van Assche sgj_def_opts(sgj_state * jsp)
276*44704f69SBart Van Assche {
277*44704f69SBart Van Assche jsp->pr_as_json = true;
278*44704f69SBart Van Assche jsp->pr_exit_status = true;
279*44704f69SBart Van Assche jsp->pr_hex = false;
280*44704f69SBart Van Assche jsp->pr_leadin = true;
281*44704f69SBart Van Assche jsp->pr_out_hr = false;
282*44704f69SBart Van Assche jsp->pr_name_ex = false;
283*44704f69SBart Van Assche jsp->pr_packed = false; /* 'k' control character, needs '-p' */
284*44704f69SBart Van Assche jsp->pr_pretty = true;
285*44704f69SBart Van Assche jsp->pr_string = true;
286*44704f69SBart Van Assche jsp->pr_format = 0;
287*44704f69SBart Van Assche jsp->first_bad_char = 0;
288*44704f69SBart Van Assche jsp->verbose = 0;
289*44704f69SBart Van Assche jsp->pr_indent_size = 4;
290*44704f69SBart Van Assche }
291*44704f69SBart Van Assche
292*44704f69SBart Van Assche bool
sgj_init_state(sgj_state * jsp,const char * j_optarg)293*44704f69SBart Van Assche sgj_init_state(sgj_state * jsp, const char * j_optarg)
294*44704f69SBart Van Assche {
295*44704f69SBart Van Assche const char * cp;
296*44704f69SBart Van Assche
297*44704f69SBart Van Assche sgj_def_opts(jsp);
298*44704f69SBart Van Assche jsp->basep = NULL;
299*44704f69SBart Van Assche jsp->out_hrp = NULL;
300*44704f69SBart Van Assche jsp->userp = NULL;
301*44704f69SBart Van Assche
302*44704f69SBart Van Assche cp = getenv(sgj_opts_ev);
303*44704f69SBart Van Assche if (cp) {
304*44704f69SBart Van Assche if (! sgj_parse_opts(jsp, cp)) {
305*44704f69SBart Van Assche pr2ws("error parsing %s environment variable, ignore\n",
306*44704f69SBart Van Assche sgj_opts_ev);
307*44704f69SBart Van Assche sgj_def_opts(jsp);
308*44704f69SBart Van Assche }
309*44704f69SBart Van Assche }
310*44704f69SBart Van Assche return j_optarg ? sgj_parse_opts(jsp, j_optarg) : true;
311*44704f69SBart Van Assche }
312*44704f69SBart Van Assche
313*44704f69SBart Van Assche sgj_opaque_p
sgj_start_r(const char * util_name,const char * ver_str,int argc,char * argv[],sgj_state * jsp)314*44704f69SBart Van Assche sgj_start_r(const char * util_name, const char * ver_str, int argc,
315*44704f69SBart Van Assche char *argv[], sgj_state * jsp)
316*44704f69SBart Van Assche {
317*44704f69SBart Van Assche int k;
318*44704f69SBart Van Assche json_value * jvp = json_object_new(0);
319*44704f69SBart Van Assche json_value * jv2p = NULL;
320*44704f69SBart Van Assche json_value * jap = NULL;
321*44704f69SBart Van Assche
322*44704f69SBart Van Assche if (NULL == jvp)
323*44704f69SBart Van Assche return NULL;
324*44704f69SBart Van Assche if (NULL == jsp)
325*44704f69SBart Van Assche return jvp;
326*44704f69SBart Van Assche
327*44704f69SBart Van Assche jsp->basep = jvp;
328*44704f69SBart Van Assche if (jsp->pr_leadin) {
329*44704f69SBart Van Assche jap = json_array_new(0);
330*44704f69SBart Van Assche if (NULL == jap) {
331*44704f69SBart Van Assche json_builder_free((json_value *)jvp);
332*44704f69SBart Van Assche return NULL;
333*44704f69SBart Van Assche }
334*44704f69SBart Van Assche /* assume rest of json_*_new() calls succeed */
335*44704f69SBart Van Assche json_array_push((json_value *)jap, json_integer_new(1));
336*44704f69SBart Van Assche json_array_push((json_value *)jap, json_integer_new(0));
337*44704f69SBart Van Assche json_object_push((json_value *)jvp, "json_format_version",
338*44704f69SBart Van Assche (json_value *)jap);
339*44704f69SBart Van Assche if (util_name) {
340*44704f69SBart Van Assche jap = json_array_new(0);
341*44704f69SBart Van Assche if (argv) {
342*44704f69SBart Van Assche for (k = 0; k < argc; ++k)
343*44704f69SBart Van Assche json_array_push((json_value *)jap,
344*44704f69SBart Van Assche json_string_new(argv[k]));
345*44704f69SBart Van Assche }
346*44704f69SBart Van Assche jv2p = json_object_push((json_value *)jvp, "utility_invoked",
347*44704f69SBart Van Assche json_object_new(0));
348*44704f69SBart Van Assche json_object_push((json_value *)jv2p, "name",
349*44704f69SBart Van Assche json_string_new(util_name));
350*44704f69SBart Van Assche if (ver_str)
351*44704f69SBart Van Assche json_object_push((json_value *)jv2p, "version_date",
352*44704f69SBart Van Assche json_string_new(ver_str));
353*44704f69SBart Van Assche else
354*44704f69SBart Van Assche json_object_push((json_value *)jv2p, "version_date",
355*44704f69SBart Van Assche json_string_new("0.0"));
356*44704f69SBart Van Assche json_object_push((json_value *)jv2p, "argv", jap);
357*44704f69SBart Van Assche }
358*44704f69SBart Van Assche if (jsp->verbose) {
359*44704f69SBart Van Assche const char * cp = getenv(sgj_opts_ev);
360*44704f69SBart Van Assche char b[32];
361*44704f69SBart Van Assche
362*44704f69SBart Van Assche json_object_push((json_value *)jv2p, "environment_variable_name",
363*44704f69SBart Van Assche json_string_new(sgj_opts_ev));
364*44704f69SBart Van Assche json_object_push((json_value *)jv2p, "environment_variable_value",
365*44704f69SBart Van Assche json_string_new(cp ? cp : "no available"));
366*44704f69SBart Van Assche sg_json_settings(jsp, b, sizeof(b));
367*44704f69SBart Van Assche json_object_push((json_value *)jv2p, "json_options",
368*44704f69SBart Van Assche json_string_new(b));
369*44704f69SBart Van Assche }
370*44704f69SBart Van Assche } else {
371*44704f69SBart Van Assche if (jsp->pr_out_hr && util_name)
372*44704f69SBart Van Assche jv2p = json_object_push((json_value *)jvp, "utility_invoked",
373*44704f69SBart Van Assche json_object_new(0));
374*44704f69SBart Van Assche }
375*44704f69SBart Van Assche if (jsp->pr_out_hr && jv2p) {
376*44704f69SBart Van Assche jsp->out_hrp = json_object_push((json_value *)jv2p, "output",
377*44704f69SBart Van Assche json_array_new(0));
378*44704f69SBart Van Assche if (jsp->pr_leadin && (jsp->verbose > 3)) {
379*44704f69SBart Van Assche char * bp = (char *)calloc(4096, 1);
380*44704f69SBart Van Assche
381*44704f69SBart Van Assche if (bp) {
382*44704f69SBart Van Assche sg_json_usage(0, bp, 4096);
383*44704f69SBart Van Assche sgj_js_str_out(jsp, bp, strlen(bp));
384*44704f69SBart Van Assche free(bp);
385*44704f69SBart Van Assche }
386*44704f69SBart Van Assche }
387*44704f69SBart Van Assche }
388*44704f69SBart Van Assche return jvp;
389*44704f69SBart Van Assche }
390*44704f69SBart Van Assche
391*44704f69SBart Van Assche void
sgj_js2file(sgj_state * jsp,sgj_opaque_p jop,int exit_status,FILE * fp)392*44704f69SBart Van Assche sgj_js2file(sgj_state * jsp, sgj_opaque_p jop, int exit_status, FILE * fp)
393*44704f69SBart Van Assche {
394*44704f69SBart Van Assche size_t len;
395*44704f69SBart Van Assche char * b;
396*44704f69SBart Van Assche json_value * jvp = (json_value *)(jop ? jop : jsp->basep);
397*44704f69SBart Van Assche json_serialize_opts out_settings;
398*44704f69SBart Van Assche
399*44704f69SBart Van Assche if (NULL == jvp) {
400*44704f69SBart Van Assche fprintf(fp, "%s: all NULL pointers ??\n", __func__);
401*44704f69SBart Van Assche return;
402*44704f69SBart Van Assche }
403*44704f69SBart Van Assche if ((NULL == jop) && jsp->pr_exit_status) {
404*44704f69SBart Van Assche char d[80];
405*44704f69SBart Van Assche
406*44704f69SBart Van Assche #ifdef SG_PRSE_SENSE_DECODE
407*44704f69SBart Van Assche if (sg_exit2str(exit_status, jsp->verbose, sizeof(d), d)) {
408*44704f69SBart Van Assche if (0 == strlen(d))
409*44704f69SBart Van Assche strncpy(d, "no errors", sizeof(d) - 1);
410*44704f69SBart Van Assche } else
411*44704f69SBart Van Assche strncpy(d, "not available", sizeof(d) - 1);
412*44704f69SBart Van Assche #else
413*44704f69SBart Van Assche if (0 == exit_status)
414*44704f69SBart Van Assche strncpy(d, "no errors", sizeof(d) - 1);
415*44704f69SBart Van Assche else
416*44704f69SBart Van Assche snprintf(d, sizeof(d), "exit_status=%d", exit_status);
417*44704f69SBart Van Assche #endif
418*44704f69SBart Van Assche sgj_js_nv_istr(jsp, jop, "exit_status", exit_status, NULL, d);
419*44704f69SBart Van Assche }
420*44704f69SBart Van Assche memcpy(&out_settings, &def_out_settings, sizeof(out_settings));
421*44704f69SBart Van Assche if (jsp->pr_indent_size != def_out_settings.indent_size)
422*44704f69SBart Van Assche out_settings.indent_size = jsp->pr_indent_size;
423*44704f69SBart Van Assche if (! jsp->pr_pretty)
424*44704f69SBart Van Assche out_settings.mode = jsp->pr_packed ? json_serialize_mode_packed :
425*44704f69SBart Van Assche json_serialize_mode_single_line;
426*44704f69SBart Van Assche
427*44704f69SBart Van Assche len = json_measure_ex(jvp, out_settings);
428*44704f69SBart Van Assche if (len < 1)
429*44704f69SBart Van Assche return;
430*44704f69SBart Van Assche if (jsp->verbose > 3)
431*44704f69SBart Van Assche fprintf(fp, "%s: serialization length: %zu bytes\n", __func__, len);
432*44704f69SBart Van Assche b = (char *)calloc(len, 1);
433*44704f69SBart Van Assche if (NULL == b) {
434*44704f69SBart Van Assche if (jsp->verbose > 3)
435*44704f69SBart Van Assche pr2serr("%s: unable to get %zu bytes on heap\n", __func__, len);
436*44704f69SBart Van Assche return;
437*44704f69SBart Van Assche }
438*44704f69SBart Van Assche
439*44704f69SBart Van Assche json_serialize_ex(b, jvp, out_settings);
440*44704f69SBart Van Assche if (jsp->verbose > 3)
441*44704f69SBart Van Assche fprintf(fp, "json serialized:\n");
442*44704f69SBart Van Assche fprintf(fp, "%s\n", b);
443*44704f69SBart Van Assche }
444*44704f69SBart Van Assche
445*44704f69SBart Van Assche void
sgj_finish(sgj_state * jsp)446*44704f69SBart Van Assche sgj_finish(sgj_state * jsp)
447*44704f69SBart Van Assche {
448*44704f69SBart Van Assche if (jsp && jsp->basep) {
449*44704f69SBart Van Assche json_builder_free((json_value *)jsp->basep);
450*44704f69SBart Van Assche jsp->basep = NULL;
451*44704f69SBart Van Assche jsp->out_hrp = NULL;
452*44704f69SBart Van Assche jsp->userp = NULL;
453*44704f69SBart Van Assche }
454*44704f69SBart Van Assche }
455*44704f69SBart Van Assche
456*44704f69SBart Van Assche void
sgj_free_unattached(sgj_opaque_p jop)457*44704f69SBart Van Assche sgj_free_unattached(sgj_opaque_p jop)
458*44704f69SBart Van Assche {
459*44704f69SBart Van Assche if (jop)
460*44704f69SBart Van Assche json_builder_free((json_value *)jop);
461*44704f69SBart Van Assche }
462*44704f69SBart Van Assche
463*44704f69SBart Van Assche void
sgj_pr_hr(sgj_state * jsp,const char * fmt,...)464*44704f69SBart Van Assche sgj_pr_hr(sgj_state * jsp, const char * fmt, ...)
465*44704f69SBart Van Assche {
466*44704f69SBart Van Assche va_list args;
467*44704f69SBart Van Assche
468*44704f69SBart Van Assche if (jsp->pr_as_json && jsp->pr_out_hr) {
469*44704f69SBart Van Assche size_t len;
470*44704f69SBart Van Assche char b[256];
471*44704f69SBart Van Assche
472*44704f69SBart Van Assche va_start(args, fmt);
473*44704f69SBart Van Assche len = vsnprintf(b, sizeof(b), fmt, args);
474*44704f69SBart Van Assche if ((len > 0) && (len < sizeof(b))) {
475*44704f69SBart Van Assche const char * cp = b;
476*44704f69SBart Van Assche
477*44704f69SBart Van Assche /* remove up to two trailing linefeeds */
478*44704f69SBart Van Assche if (b[len - 1] == '\n') {
479*44704f69SBart Van Assche --len;
480*44704f69SBart Van Assche if (b[len - 1] == '\n')
481*44704f69SBart Van Assche --len;
482*44704f69SBart Van Assche b[len] = '\0';
483*44704f69SBart Van Assche }
484*44704f69SBart Van Assche /* remove leading linefeed, if present */
485*44704f69SBart Van Assche if ((len > 0) && ('\n' == b[0]))
486*44704f69SBart Van Assche ++cp;
487*44704f69SBart Van Assche json_array_push((json_value *)jsp->out_hrp, json_string_new(cp));
488*44704f69SBart Van Assche }
489*44704f69SBart Van Assche va_end(args);
490*44704f69SBart Van Assche } else if (jsp->pr_as_json) {
491*44704f69SBart Van Assche va_start(args, fmt);
492*44704f69SBart Van Assche va_end(args);
493*44704f69SBart Van Assche } else {
494*44704f69SBart Van Assche va_start(args, fmt);
495*44704f69SBart Van Assche vfprintf(stdout, fmt, args);
496*44704f69SBart Van Assche va_end(args);
497*44704f69SBart Van Assche }
498*44704f69SBart Van Assche }
499*44704f69SBart Van Assche
500*44704f69SBart Van Assche /* jop will 'own' returned value (if non-NULL) */
501*44704f69SBart Van Assche sgj_opaque_p
sgj_named_subobject_r(sgj_state * jsp,sgj_opaque_p jop,const char * name)502*44704f69SBart Van Assche sgj_named_subobject_r(sgj_state * jsp, sgj_opaque_p jop, const char * name)
503*44704f69SBart Van Assche {
504*44704f69SBart Van Assche sgj_opaque_p resp = NULL;
505*44704f69SBart Van Assche
506*44704f69SBart Van Assche if (jsp && jsp->pr_as_json && name)
507*44704f69SBart Van Assche resp = json_object_push((json_value *)(jop ? jop : jsp->basep), name,
508*44704f69SBart Van Assche json_object_new(0));
509*44704f69SBart Van Assche return resp;
510*44704f69SBart Van Assche }
511*44704f69SBart Van Assche
512*44704f69SBart Van Assche sgj_opaque_p
sgj_snake_named_subobject_r(sgj_state * jsp,sgj_opaque_p jop,const char * conv2sname)513*44704f69SBart Van Assche sgj_snake_named_subobject_r(sgj_state * jsp, sgj_opaque_p jop,
514*44704f69SBart Van Assche const char * conv2sname)
515*44704f69SBart Van Assche {
516*44704f69SBart Van Assche if (jsp && jsp->pr_as_json && conv2sname) {
517*44704f69SBart Van Assche int olen = strlen(conv2sname);
518*44704f69SBart Van Assche char * sname = (char *)malloc(olen + 8);
519*44704f69SBart Van Assche int nlen = sgj_name_to_snake(conv2sname, sname, olen + 8);
520*44704f69SBart Van Assche
521*44704f69SBart Van Assche if (nlen > 0)
522*44704f69SBart Van Assche return json_object_push((json_value *)(jop ? jop : jsp->basep),
523*44704f69SBart Van Assche sname, json_object_new(0));
524*44704f69SBart Van Assche }
525*44704f69SBart Van Assche return NULL;
526*44704f69SBart Van Assche }
527*44704f69SBart Van Assche
528*44704f69SBart Van Assche /* jop will 'own' returned value (if non-NULL) */
529*44704f69SBart Van Assche sgj_opaque_p
sgj_named_subarray_r(sgj_state * jsp,sgj_opaque_p jop,const char * name)530*44704f69SBart Van Assche sgj_named_subarray_r(sgj_state * jsp, sgj_opaque_p jop, const char * name)
531*44704f69SBart Van Assche {
532*44704f69SBart Van Assche sgj_opaque_p resp = NULL;
533*44704f69SBart Van Assche
534*44704f69SBart Van Assche if (jsp && jsp->pr_as_json && name)
535*44704f69SBart Van Assche resp = json_object_push((json_value *)(jop ? jop : jsp->basep), name,
536*44704f69SBart Van Assche json_array_new(0));
537*44704f69SBart Van Assche return resp;
538*44704f69SBart Van Assche }
539*44704f69SBart Van Assche
540*44704f69SBart Van Assche sgj_opaque_p
sgj_snake_named_subarray_r(sgj_state * jsp,sgj_opaque_p jop,const char * conv2sname)541*44704f69SBart Van Assche sgj_snake_named_subarray_r(sgj_state * jsp, sgj_opaque_p jop,
542*44704f69SBart Van Assche const char * conv2sname)
543*44704f69SBart Van Assche {
544*44704f69SBart Van Assche if (jsp && jsp->pr_as_json && conv2sname) {
545*44704f69SBart Van Assche int olen = strlen(conv2sname);
546*44704f69SBart Van Assche char * sname = (char *)malloc(olen + 8);
547*44704f69SBart Van Assche int nlen = sgj_name_to_snake(conv2sname, sname, olen + 8);
548*44704f69SBart Van Assche
549*44704f69SBart Van Assche if (nlen > 0)
550*44704f69SBart Van Assche return json_object_push((json_value *)(jop ? jop : jsp->basep),
551*44704f69SBart Van Assche sname, json_array_new(0));
552*44704f69SBart Van Assche }
553*44704f69SBart Van Assche return NULL;
554*44704f69SBart Van Assche }
555*44704f69SBart Van Assche
556*44704f69SBart Van Assche /* Newly created object is un-attached to jsp->basep tree */
557*44704f69SBart Van Assche sgj_opaque_p
sgj_new_unattached_object_r(sgj_state * jsp)558*44704f69SBart Van Assche sgj_new_unattached_object_r(sgj_state * jsp)
559*44704f69SBart Van Assche {
560*44704f69SBart Van Assche return (jsp && jsp->pr_as_json) ? json_object_new(0) : NULL;
561*44704f69SBart Van Assche }
562*44704f69SBart Van Assche
563*44704f69SBart Van Assche /* Newly created array is un-attached to jsp->basep tree */
564*44704f69SBart Van Assche sgj_opaque_p
sgj_new_unattached_array_r(sgj_state * jsp)565*44704f69SBart Van Assche sgj_new_unattached_array_r(sgj_state * jsp)
566*44704f69SBart Van Assche {
567*44704f69SBart Van Assche return (jsp && jsp->pr_as_json) ? json_array_new(0) : NULL;
568*44704f69SBart Van Assche }
569*44704f69SBart Van Assche
570*44704f69SBart Van Assche sgj_opaque_p
sgj_js_nv_s(sgj_state * jsp,sgj_opaque_p jop,const char * name,const char * value)571*44704f69SBart Van Assche sgj_js_nv_s(sgj_state * jsp, sgj_opaque_p jop, const char * name,
572*44704f69SBart Van Assche const char * value)
573*44704f69SBart Van Assche {
574*44704f69SBart Van Assche if (jsp && jsp->pr_as_json && value) {
575*44704f69SBart Van Assche if (name)
576*44704f69SBart Van Assche return json_object_push((json_value *)(jop ? jop : jsp->basep),
577*44704f69SBart Van Assche name, json_string_new(value));
578*44704f69SBart Van Assche else
579*44704f69SBart Van Assche return json_array_push((json_value *)(jop ? jop : jsp->basep),
580*44704f69SBart Van Assche json_string_new(value));
581*44704f69SBart Van Assche } else
582*44704f69SBart Van Assche return NULL;
583*44704f69SBart Van Assche }
584*44704f69SBart Van Assche
585*44704f69SBart Van Assche sgj_opaque_p
sgj_js_nv_s_len(sgj_state * jsp,sgj_opaque_p jop,const char * name,const char * value,int slen)586*44704f69SBart Van Assche sgj_js_nv_s_len(sgj_state * jsp, sgj_opaque_p jop, const char * name,
587*44704f69SBart Van Assche const char * value, int slen)
588*44704f69SBart Van Assche {
589*44704f69SBart Van Assche int k;
590*44704f69SBart Van Assche
591*44704f69SBart Van Assche if (jsp && jsp->pr_as_json && value && (slen >= 0)) {
592*44704f69SBart Van Assche for (k = 0; k < slen; ++k) { /* don't want '\0' in value string */
593*44704f69SBart Van Assche if (0 == value[k])
594*44704f69SBart Van Assche break;
595*44704f69SBart Van Assche }
596*44704f69SBart Van Assche if (name)
597*44704f69SBart Van Assche return json_object_push((json_value *)(jop ? jop : jsp->basep),
598*44704f69SBart Van Assche name, json_string_new_length(k, value));
599*44704f69SBart Van Assche else
600*44704f69SBart Van Assche return json_array_push((json_value *)(jop ? jop : jsp->basep),
601*44704f69SBart Van Assche json_string_new_length(k, value));
602*44704f69SBart Van Assche } else
603*44704f69SBart Van Assche return NULL;
604*44704f69SBart Van Assche }
605*44704f69SBart Van Assche
606*44704f69SBart Van Assche sgj_opaque_p
sgj_js_nv_i(sgj_state * jsp,sgj_opaque_p jop,const char * name,int64_t value)607*44704f69SBart Van Assche sgj_js_nv_i(sgj_state * jsp, sgj_opaque_p jop, const char * name,
608*44704f69SBart Van Assche int64_t value)
609*44704f69SBart Van Assche {
610*44704f69SBart Van Assche if (jsp && jsp->pr_as_json) {
611*44704f69SBart Van Assche if (name)
612*44704f69SBart Van Assche return json_object_push((json_value *)(jop ? jop : jsp->basep),
613*44704f69SBart Van Assche name, json_integer_new(value));
614*44704f69SBart Van Assche else
615*44704f69SBart Van Assche return json_array_push((json_value *)(jop ? jop : jsp->basep),
616*44704f69SBart Van Assche json_integer_new(value));
617*44704f69SBart Van Assche }
618*44704f69SBart Van Assche else
619*44704f69SBart Van Assche return NULL;
620*44704f69SBart Van Assche }
621*44704f69SBart Van Assche
622*44704f69SBart Van Assche sgj_opaque_p
sgj_js_nv_b(sgj_state * jsp,sgj_opaque_p jop,const char * name,bool value)623*44704f69SBart Van Assche sgj_js_nv_b(sgj_state * jsp, sgj_opaque_p jop, const char * name, bool value)
624*44704f69SBart Van Assche {
625*44704f69SBart Van Assche if (jsp && jsp->pr_as_json) {
626*44704f69SBart Van Assche if (name)
627*44704f69SBart Van Assche return json_object_push((json_value *)(jop ? jop : jsp->basep),
628*44704f69SBart Van Assche name, json_boolean_new(value));
629*44704f69SBart Van Assche else
630*44704f69SBart Van Assche return json_array_push((json_value *)(jop ? jop : jsp->basep),
631*44704f69SBart Van Assche json_boolean_new(value));
632*44704f69SBart Van Assche } else
633*44704f69SBart Van Assche return NULL;
634*44704f69SBart Van Assche }
635*44704f69SBart Van Assche
636*44704f69SBart Van Assche /* jop will 'own' ua_jop (if returned value is non-NULL) */
637*44704f69SBart Van Assche sgj_opaque_p
sgj_js_nv_o(sgj_state * jsp,sgj_opaque_p jop,const char * name,sgj_opaque_p ua_jop)638*44704f69SBart Van Assche sgj_js_nv_o(sgj_state * jsp, sgj_opaque_p jop, const char * name,
639*44704f69SBart Van Assche sgj_opaque_p ua_jop)
640*44704f69SBart Van Assche {
641*44704f69SBart Van Assche if (jsp && jsp->pr_as_json && ua_jop) {
642*44704f69SBart Van Assche if (name)
643*44704f69SBart Van Assche return json_object_push((json_value *)(jop ? jop : jsp->basep),
644*44704f69SBart Van Assche name, (json_value *)ua_jop);
645*44704f69SBart Van Assche else
646*44704f69SBart Van Assche return json_array_push((json_value *)(jop ? jop : jsp->basep),
647*44704f69SBart Van Assche (json_value *)ua_jop);
648*44704f69SBart Van Assche } else
649*44704f69SBart Van Assche return NULL;
650*44704f69SBart Van Assche }
651*44704f69SBart Van Assche
652*44704f69SBart Van Assche void
sgj_js_nv_ihex(sgj_state * jsp,sgj_opaque_p jop,const char * name,uint64_t value)653*44704f69SBart Van Assche sgj_js_nv_ihex(sgj_state * jsp, sgj_opaque_p jop, const char * name,
654*44704f69SBart Van Assche uint64_t value)
655*44704f69SBart Van Assche {
656*44704f69SBart Van Assche if ((NULL == jsp) || (NULL == name) || (! jsp->pr_as_json))
657*44704f69SBart Van Assche return;
658*44704f69SBart Van Assche else if (jsp->pr_hex) {
659*44704f69SBart Van Assche sgj_opaque_p jo2p = sgj_named_subobject_r(jsp, jop, name);
660*44704f69SBart Van Assche char b[64];
661*44704f69SBart Van Assche
662*44704f69SBart Van Assche if (NULL == jo2p)
663*44704f69SBart Van Assche return;
664*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "i", (int64_t)value);
665*44704f69SBart Van Assche snprintf(b, sizeof(b), "%" PRIx64, value);
666*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, "hex", b);
667*44704f69SBart Van Assche } else
668*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, name, (int64_t)value);
669*44704f69SBart Van Assche }
670*44704f69SBart Van Assche
671*44704f69SBart Van Assche static const char * sc_mn_s = "meaning";
672*44704f69SBart Van Assche
673*44704f69SBart Van Assche void
sgj_js_nv_istr(sgj_state * jsp,sgj_opaque_p jop,const char * name,int64_t val_i,const char * str_name,const char * val_s)674*44704f69SBart Van Assche sgj_js_nv_istr(sgj_state * jsp, sgj_opaque_p jop, const char * name,
675*44704f69SBart Van Assche int64_t val_i, const char * str_name, const char * val_s)
676*44704f69SBart Van Assche {
677*44704f69SBart Van Assche if ((NULL == jsp) || (! jsp->pr_as_json))
678*44704f69SBart Van Assche return;
679*44704f69SBart Van Assche else if (val_s && jsp->pr_string) {
680*44704f69SBart Van Assche sgj_opaque_p jo2p = sgj_named_subobject_r(jsp, jop, name);
681*44704f69SBart Van Assche
682*44704f69SBart Van Assche if (NULL == jo2p)
683*44704f69SBart Van Assche return;
684*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "i", (int64_t)val_i);
685*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, str_name ? str_name : sc_mn_s, val_s);
686*44704f69SBart Van Assche } else
687*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, name, val_i);
688*44704f69SBart Van Assche }
689*44704f69SBart Van Assche
690*44704f69SBart Van Assche void
sgj_js_nv_ihexstr(sgj_state * jsp,sgj_opaque_p jop,const char * name,int64_t val_i,const char * str_name,const char * val_s)691*44704f69SBart Van Assche sgj_js_nv_ihexstr(sgj_state * jsp, sgj_opaque_p jop, const char * name,
692*44704f69SBart Van Assche int64_t val_i, const char * str_name, const char * val_s)
693*44704f69SBart Van Assche {
694*44704f69SBart Van Assche bool as_str;
695*44704f69SBart Van Assche
696*44704f69SBart Van Assche if ((NULL == jsp) || (! jsp->pr_as_json))
697*44704f69SBart Van Assche return;
698*44704f69SBart Van Assche as_str = jsp->pr_string && val_s;
699*44704f69SBart Van Assche if ((! jsp->pr_hex) && (! as_str))
700*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, name, val_i);
701*44704f69SBart Van Assche else {
702*44704f69SBart Van Assche char b[64];
703*44704f69SBart Van Assche sgj_opaque_p jo2p = sgj_named_subobject_r(jsp, jop, name);
704*44704f69SBart Van Assche
705*44704f69SBart Van Assche if (NULL == jo2p)
706*44704f69SBart Van Assche return;
707*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "i", (int64_t)val_i);
708*44704f69SBart Van Assche if (jsp->pr_hex) {
709*44704f69SBart Van Assche snprintf(b, sizeof(b), "%" PRIx64, val_i);
710*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, "hex", b);
711*44704f69SBart Van Assche }
712*44704f69SBart Van Assche if (as_str)
713*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, str_name ? str_name : sc_mn_s, val_s);
714*44704f69SBart Van Assche }
715*44704f69SBart Van Assche }
716*44704f69SBart Van Assche
717*44704f69SBart Van Assche static const char * sc_nex_s = "name_extra";
718*44704f69SBart Van Assche
719*44704f69SBart Van Assche void
sgj_js_nv_ihex_nex(sgj_state * jsp,sgj_opaque_p jop,const char * name,int64_t val_i,bool hex_as_well,const char * nex_s)720*44704f69SBart Van Assche sgj_js_nv_ihex_nex(sgj_state * jsp, sgj_opaque_p jop, const char * name,
721*44704f69SBart Van Assche int64_t val_i, bool hex_as_well, const char * nex_s)
722*44704f69SBart Van Assche {
723*44704f69SBart Van Assche bool as_hex, as_nex;
724*44704f69SBart Van Assche
725*44704f69SBart Van Assche if ((NULL == jsp) || (! jsp->pr_as_json))
726*44704f69SBart Van Assche return;
727*44704f69SBart Van Assche as_hex = jsp->pr_hex && hex_as_well;
728*44704f69SBart Van Assche as_nex = jsp->pr_name_ex && nex_s;
729*44704f69SBart Van Assche if (! (as_hex || as_nex))
730*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, name, val_i);
731*44704f69SBart Van Assche else {
732*44704f69SBart Van Assche char b[64];
733*44704f69SBart Van Assche sgj_opaque_p jo2p =
734*44704f69SBart Van Assche sgj_named_subobject_r(jsp, jop, name);
735*44704f69SBart Van Assche
736*44704f69SBart Van Assche if (NULL == jo2p)
737*44704f69SBart Van Assche return;
738*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "i", (int64_t)val_i);
739*44704f69SBart Van Assche if (as_hex) {
740*44704f69SBart Van Assche snprintf(b, sizeof(b), "%" PRIx64, val_i);
741*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, "hex", b);
742*44704f69SBart Van Assche }
743*44704f69SBart Van Assche if (as_nex)
744*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, sc_nex_s, nex_s);
745*44704f69SBart Van Assche }
746*44704f69SBart Van Assche }
747*44704f69SBart Van Assche
748*44704f69SBart Van Assche #ifndef SG_PRSE_SENSE_DECODE
749*44704f69SBart Van Assche static void
h2str(const uint8_t * byte_arr,int num_bytes,char * bp,int blen)750*44704f69SBart Van Assche h2str(const uint8_t * byte_arr, int num_bytes, char * bp, int blen)
751*44704f69SBart Van Assche {
752*44704f69SBart Van Assche int j, k, n;
753*44704f69SBart Van Assche
754*44704f69SBart Van Assche for (k = 0, n = 0; (k < num_bytes) && (n < blen); ) {
755*44704f69SBart Van Assche j = sg_scnpr(bp + n, blen - n, "%02x ", byte_arr[k]);
756*44704f69SBart Van Assche if (j < 2)
757*44704f69SBart Van Assche break;
758*44704f69SBart Van Assche n += j;
759*44704f69SBart Van Assche ++k;
760*44704f69SBart Van Assche if ((0 == (k % 8)) && (k < num_bytes) && (n < blen)) {
761*44704f69SBart Van Assche bp[n++] = ' ';
762*44704f69SBart Van Assche }
763*44704f69SBart Van Assche }
764*44704f69SBart Van Assche j = strlen(bp);
765*44704f69SBart Van Assche if ((j > 0) && (' ' == bp[j - 1]))
766*44704f69SBart Van Assche bp[j - 1] = '\0'; /* chop off trailing space */
767*44704f69SBart Van Assche }
768*44704f69SBart Van Assche #endif
769*44704f69SBart Van Assche
770*44704f69SBart Van Assche /* Add hex byte strings irrespective of jsp->pr_hex setting. */
771*44704f69SBart Van Assche void
sgj_js_nv_hex_bytes(sgj_state * jsp,sgj_opaque_p jop,const char * name,const uint8_t * byte_arr,int num_bytes)772*44704f69SBart Van Assche sgj_js_nv_hex_bytes(sgj_state * jsp, sgj_opaque_p jop, const char * name,
773*44704f69SBart Van Assche const uint8_t * byte_arr, int num_bytes)
774*44704f69SBart Van Assche {
775*44704f69SBart Van Assche int blen = num_bytes * 4;
776*44704f69SBart Van Assche char * bp;
777*44704f69SBart Van Assche
778*44704f69SBart Van Assche if ((NULL == jsp) || (! jsp->pr_as_json))
779*44704f69SBart Van Assche return;
780*44704f69SBart Van Assche bp = (char *)calloc(blen + 4, 1);
781*44704f69SBart Van Assche if (bp) {
782*44704f69SBart Van Assche #ifdef SG_PRSE_SENSE_DECODE
783*44704f69SBart Van Assche hex2str(byte_arr, num_bytes, NULL, 2, blen, bp);
784*44704f69SBart Van Assche #else
785*44704f69SBart Van Assche h2str(byte_arr, num_bytes, bp, blen);
786*44704f69SBart Van Assche #endif
787*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, name, bp);
788*44704f69SBart Van Assche free(bp);
789*44704f69SBart Van Assche }
790*44704f69SBart Van Assche }
791*44704f69SBart Van Assche
792*44704f69SBart Van Assche void
sgj_js_nv_ihexstr_nex(sgj_state * jsp,sgj_opaque_p jop,const char * name,int64_t val_i,bool hex_as_well,const char * str_name,const char * val_s,const char * nex_s)793*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(sgj_state * jsp, sgj_opaque_p jop, const char * name,
794*44704f69SBart Van Assche int64_t val_i, bool hex_as_well, const char * str_name,
795*44704f69SBart Van Assche const char * val_s, const char * nex_s)
796*44704f69SBart Van Assche {
797*44704f69SBart Van Assche bool as_hex = jsp->pr_hex && hex_as_well;
798*44704f69SBart Van Assche bool as_str = jsp->pr_string && val_s;
799*44704f69SBart Van Assche bool as_nex = jsp->pr_name_ex && nex_s;
800*44704f69SBart Van Assche const char * sname = str_name ? str_name : sc_mn_s;
801*44704f69SBart Van Assche
802*44704f69SBart Van Assche if ((NULL == jsp) || (! jsp->pr_as_json))
803*44704f69SBart Van Assche return;
804*44704f69SBart Van Assche if (! (as_hex || as_nex || as_str))
805*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, name, val_i);
806*44704f69SBart Van Assche else {
807*44704f69SBart Van Assche char b[64];
808*44704f69SBart Van Assche sgj_opaque_p jo2p =
809*44704f69SBart Van Assche sgj_named_subobject_r(jsp, jop, name);
810*44704f69SBart Van Assche
811*44704f69SBart Van Assche if (NULL == jo2p)
812*44704f69SBart Van Assche return;
813*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "i", (int64_t)val_i);
814*44704f69SBart Van Assche if (as_nex) {
815*44704f69SBart Van Assche if (as_hex) {
816*44704f69SBart Van Assche snprintf(b, sizeof(b), "%" PRIx64, val_i);
817*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, "hex", b);
818*44704f69SBart Van Assche }
819*44704f69SBart Van Assche if (as_str) {
820*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, sname, val_s);
821*44704f69SBart Van Assche }
822*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, sc_nex_s, nex_s);
823*44704f69SBart Van Assche } else if (as_hex) {
824*44704f69SBart Van Assche snprintf(b, sizeof(b), "%" PRIx64, val_i);
825*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, "hex", b);
826*44704f69SBart Van Assche if (as_str)
827*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, sname, val_s);
828*44704f69SBart Van Assche } else if (as_str)
829*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, sname, val_s);
830*44704f69SBart Van Assche }
831*44704f69SBart Van Assche }
832*44704f69SBart Van Assche
833*44704f69SBart Van Assche /* Treat '\n' in sp as line breaks. Consumes characters from sp until either
834*44704f69SBart Van Assche * a '\0' is found or slen is exhausted. Add each line to jsp->out_hrp JSON
835*44704f69SBart Van Assche * array (if conditions met). */
836*44704f69SBart Van Assche void
sgj_js_str_out(sgj_state * jsp,const char * sp,int slen)837*44704f69SBart Van Assche sgj_js_str_out(sgj_state * jsp, const char * sp, int slen)
838*44704f69SBart Van Assche {
839*44704f69SBart Van Assche char c;
840*44704f69SBart Van Assche int k, n;
841*44704f69SBart Van Assche const char * prev_sp = sp;
842*44704f69SBart Van Assche const char * cur_sp = sp;
843*44704f69SBart Van Assche
844*44704f69SBart Van Assche if ((NULL == jsp) || (NULL == jsp->out_hrp) || (! jsp->pr_as_json) ||
845*44704f69SBart Van Assche (! jsp->pr_out_hr))
846*44704f69SBart Van Assche return;
847*44704f69SBart Van Assche for (k = 0; k < slen; ++k, ++cur_sp) {
848*44704f69SBart Van Assche c = *cur_sp;
849*44704f69SBart Van Assche if ('\0' == c)
850*44704f69SBart Van Assche break;
851*44704f69SBart Van Assche else if ('\n' == c) {
852*44704f69SBart Van Assche n = cur_sp - prev_sp;
853*44704f69SBart Van Assche /* when name is NULL, add to array (jsp->out_hrp) */
854*44704f69SBart Van Assche sgj_js_nv_s_len(jsp, jsp->out_hrp, NULL, prev_sp, n);
855*44704f69SBart Van Assche prev_sp = cur_sp + 1;
856*44704f69SBart Van Assche }
857*44704f69SBart Van Assche }
858*44704f69SBart Van Assche if (prev_sp < cur_sp) {
859*44704f69SBart Van Assche n = cur_sp - prev_sp;
860*44704f69SBart Van Assche sgj_js_nv_s_len(jsp, jsp->out_hrp, NULL, prev_sp, n);
861*44704f69SBart Van Assche }
862*44704f69SBart Van Assche }
863*44704f69SBart Van Assche
864*44704f69SBart Van Assche char *
sgj_convert_to_snake_name(const char * in_name,char * sname,int max_sname_len)865*44704f69SBart Van Assche sgj_convert_to_snake_name(const char * in_name, char * sname,
866*44704f69SBart Van Assche int max_sname_len)
867*44704f69SBart Van Assche {
868*44704f69SBart Van Assche sgj_name_to_snake(in_name, sname, max_sname_len);
869*44704f69SBart Van Assche return sname;
870*44704f69SBart Van Assche }
871*44704f69SBart Van Assche
872*44704f69SBart Van Assche bool
sgj_is_snake_name(const char * in_name)873*44704f69SBart Van Assche sgj_is_snake_name(const char * in_name)
874*44704f69SBart Van Assche {
875*44704f69SBart Van Assche size_t k;
876*44704f69SBart Van Assche size_t ln = strlen(in_name);
877*44704f69SBart Van Assche char c;
878*44704f69SBart Van Assche
879*44704f69SBart Van Assche for (k = 0; k < ln; ++k) {
880*44704f69SBart Van Assche c = in_name[k];
881*44704f69SBart Van Assche if (((c >= '0') && (c <= '9')) ||
882*44704f69SBart Van Assche ((c >= 'a') && (c <= 'z')) ||
883*44704f69SBart Van Assche (c == '_'))
884*44704f69SBart Van Assche continue;
885*44704f69SBart Van Assche else
886*44704f69SBart Van Assche return false;
887*44704f69SBart Van Assche }
888*44704f69SBart Van Assche return true;
889*44704f69SBart Van Assche }
890*44704f69SBart Van Assche
891*44704f69SBart Van Assche /* This function tries to convert the 'in' C string to "snake_case"
892*44704f69SBart Van Assche * convention so the output 'out' only contains lower case ASCII letters,
893*44704f69SBart Van Assche * numerals and "_" as a separator. Any leading or trailing underscores
894*44704f69SBart Van Assche * are removed as are repeated underscores (e.g. "_Snake __ case" becomes
895*44704f69SBart Van Assche * "snake_case"). Parentheses and the characters between them are removed.
896*44704f69SBart Van Assche * Returns number of characters placed in 'out' excluding the trailing
897*44704f69SBart Van Assche * NULL */
898*44704f69SBart Van Assche static int
sgj_name_to_snake(const char * in,char * out,int maxlen_out)899*44704f69SBart Van Assche sgj_name_to_snake(const char * in, char * out, int maxlen_out)
900*44704f69SBart Van Assche {
901*44704f69SBart Van Assche bool prev_underscore = false;
902*44704f69SBart Van Assche bool within_paren = false;
903*44704f69SBart Van Assche int c, k, j, inlen;
904*44704f69SBart Van Assche
905*44704f69SBart Van Assche if (maxlen_out < 2) {
906*44704f69SBart Van Assche if (maxlen_out == 1)
907*44704f69SBart Van Assche out[0] = '\0';
908*44704f69SBart Van Assche return 0;
909*44704f69SBart Van Assche }
910*44704f69SBart Van Assche inlen = strlen(in);
911*44704f69SBart Van Assche for (k = 0, j = 0; (k < inlen) && (j < maxlen_out); ++k) {
912*44704f69SBart Van Assche c = in[k];
913*44704f69SBart Van Assche if (within_paren) {
914*44704f69SBart Van Assche if (')' == c)
915*44704f69SBart Van Assche within_paren = false;
916*44704f69SBart Van Assche continue;
917*44704f69SBart Van Assche }
918*44704f69SBart Van Assche if (isalnum(c)) {
919*44704f69SBart Van Assche out[j++] = isupper(c) ? tolower(c) : c;
920*44704f69SBart Van Assche prev_underscore = false;
921*44704f69SBart Van Assche } else if ('(' == c)
922*44704f69SBart Van Assche within_paren = true;
923*44704f69SBart Van Assche else if ((j > 0) && (! prev_underscore)) {
924*44704f69SBart Van Assche out[j++] = '_';
925*44704f69SBart Van Assche prev_underscore = true;
926*44704f69SBart Van Assche }
927*44704f69SBart Van Assche /* else we are skipping character 'c' */
928*44704f69SBart Van Assche }
929*44704f69SBart Van Assche if (j == maxlen_out)
930*44704f69SBart Van Assche out[--j] = '\0';
931*44704f69SBart Van Assche /* trim of trailing underscores (might have been spaces) */
932*44704f69SBart Van Assche for (k = j - 1; k >= 0; --k) {
933*44704f69SBart Van Assche if (out[k] != '_')
934*44704f69SBart Van Assche break;
935*44704f69SBart Van Assche }
936*44704f69SBart Van Assche if (k < 0)
937*44704f69SBart Van Assche k = 0;
938*44704f69SBart Van Assche else
939*44704f69SBart Van Assche ++k;
940*44704f69SBart Van Assche out[k] = '\0';
941*44704f69SBart Van Assche return k;
942*44704f69SBart Van Assche }
943*44704f69SBart Van Assche
944*44704f69SBart Van Assche static int
sgj_jtype_to_s(char * b,int blen_max,json_value * jvp)945*44704f69SBart Van Assche sgj_jtype_to_s(char * b, int blen_max, json_value * jvp)
946*44704f69SBart Van Assche {
947*44704f69SBart Van Assche json_type jtype = jvp ? jvp->type : json_none;
948*44704f69SBart Van Assche
949*44704f69SBart Van Assche switch (jtype) {
950*44704f69SBart Van Assche case json_string:
951*44704f69SBart Van Assche return sg_scnpr(b, blen_max, "%s", jvp->u.string.ptr);
952*44704f69SBart Van Assche case json_integer:
953*44704f69SBart Van Assche return sg_scnpr(b, blen_max, "%" PRIi64, jvp->u.integer);
954*44704f69SBart Van Assche case json_boolean:
955*44704f69SBart Van Assche return sg_scnpr(b, blen_max, "%s", jvp->u.boolean ? "true" : "false");
956*44704f69SBart Van Assche case json_none:
957*44704f69SBart Van Assche default:
958*44704f69SBart Van Assche if ((blen_max > 0) && ('\0' != b[0]))
959*44704f69SBart Van Assche b[0] = '\0';
960*44704f69SBart Van Assche break;
961*44704f69SBart Van Assche }
962*44704f69SBart Van Assche return 0;
963*44704f69SBart Van Assche }
964*44704f69SBart Van Assche
965*44704f69SBart Van Assche static int
sgj_haj_helper(char * b,int blen_max,const char * name,enum sgj_separator_t sep,bool use_jvp,json_value * jvp,int64_t val_instead)966*44704f69SBart Van Assche sgj_haj_helper(char * b, int blen_max, const char * name,
967*44704f69SBart Van Assche enum sgj_separator_t sep, bool use_jvp,
968*44704f69SBart Van Assche json_value * jvp, int64_t val_instead)
969*44704f69SBart Van Assche {
970*44704f69SBart Van Assche int n = 0;
971*44704f69SBart Van Assche
972*44704f69SBart Van Assche if (name) {
973*44704f69SBart Van Assche n += sg_scnpr(b + n, blen_max - n, "%s", name);
974*44704f69SBart Van Assche switch (sep) {
975*44704f69SBart Van Assche case SGJ_SEP_NONE:
976*44704f69SBart Van Assche break;
977*44704f69SBart Van Assche case SGJ_SEP_SPACE_1:
978*44704f69SBart Van Assche n += sg_scnpr(b + n, blen_max - n, " ");
979*44704f69SBart Van Assche break;
980*44704f69SBart Van Assche case SGJ_SEP_SPACE_2:
981*44704f69SBart Van Assche n += sg_scnpr(b + n, blen_max - n, " ");
982*44704f69SBart Van Assche break;
983*44704f69SBart Van Assche case SGJ_SEP_SPACE_3:
984*44704f69SBart Van Assche n += sg_scnpr(b + n, blen_max - n, " ");
985*44704f69SBart Van Assche break;
986*44704f69SBart Van Assche case SGJ_SEP_SPACE_4:
987*44704f69SBart Van Assche n += sg_scnpr(b + n, blen_max - n, " ");
988*44704f69SBart Van Assche break;
989*44704f69SBart Van Assche case SGJ_SEP_EQUAL_NO_SPACE:
990*44704f69SBart Van Assche n += sg_scnpr(b + n, blen_max - n, "=");
991*44704f69SBart Van Assche break;
992*44704f69SBart Van Assche case SGJ_SEP_EQUAL_1_SPACE:
993*44704f69SBart Van Assche n += sg_scnpr(b + n, blen_max - n, "= ");
994*44704f69SBart Van Assche break;
995*44704f69SBart Van Assche case SGJ_SEP_COLON_NO_SPACE:
996*44704f69SBart Van Assche n += sg_scnpr(b + n, blen_max - n, ":");
997*44704f69SBart Van Assche break;
998*44704f69SBart Van Assche case SGJ_SEP_COLON_1_SPACE:
999*44704f69SBart Van Assche n += sg_scnpr(b + n, blen_max - n, ": ");
1000*44704f69SBart Van Assche break;
1001*44704f69SBart Van Assche default:
1002*44704f69SBart Van Assche break;
1003*44704f69SBart Van Assche }
1004*44704f69SBart Van Assche }
1005*44704f69SBart Van Assche if (use_jvp)
1006*44704f69SBart Van Assche n += sgj_jtype_to_s(b + n, blen_max - n, jvp);
1007*44704f69SBart Van Assche else
1008*44704f69SBart Van Assche n += sg_scnpr(b + n, blen_max - n, "%" PRIi64, val_instead);
1009*44704f69SBart Van Assche return n;
1010*44704f69SBart Van Assche }
1011*44704f69SBart Van Assche
1012*44704f69SBart Van Assche static void
sgj_haj_xx(sgj_state * jsp,sgj_opaque_p jop,int leadin_sp,const char * name,enum sgj_separator_t sep,json_value * jvp,bool hex_as_well,const char * val_s,const char * nex_s)1013*44704f69SBart Van Assche sgj_haj_xx(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
1014*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep, json_value * jvp,
1015*44704f69SBart Van Assche bool hex_as_well, const char * val_s, const char * nex_s)
1016*44704f69SBart Van Assche {
1017*44704f69SBart Van Assche bool eaten = false;
1018*44704f69SBart Van Assche bool as_json = (jsp && jsp->pr_as_json);
1019*44704f69SBart Van Assche bool done;
1020*44704f69SBart Van Assche int n;
1021*44704f69SBart Van Assche json_type jtype = jvp ? jvp->type : json_none;
1022*44704f69SBart Van Assche char b[256];
1023*44704f69SBart Van Assche char jname[96];
1024*44704f69SBart Van Assche static const int blen = sizeof(b);
1025*44704f69SBart Van Assche
1026*44704f69SBart Van Assche if (leadin_sp > 128)
1027*44704f69SBart Van Assche leadin_sp = 128;
1028*44704f69SBart Van Assche for (n = 0; n < leadin_sp; ++n)
1029*44704f69SBart Van Assche b[n] = ' ';
1030*44704f69SBart Van Assche b[n] = '\0';
1031*44704f69SBart Van Assche if (NULL == name) {
1032*44704f69SBart Van Assche if ((! as_json) || (jsp && jsp->pr_out_hr)) {
1033*44704f69SBart Van Assche n += sgj_jtype_to_s(b + n, blen - n, jvp);
1034*44704f69SBart Van Assche printf("%s\n", b);
1035*44704f69SBart Van Assche }
1036*44704f69SBart Van Assche if (NULL == jop) {
1037*44704f69SBart Van Assche if (as_json && jsp->pr_out_hr) {
1038*44704f69SBart Van Assche eaten = true;
1039*44704f69SBart Van Assche json_array_push((json_value *)jsp->out_hrp,
1040*44704f69SBart Van Assche jvp ? jvp : json_null_new());
1041*44704f69SBart Van Assche }
1042*44704f69SBart Van Assche } else { /* assume jop points to named array */
1043*44704f69SBart Van Assche if (as_json) {
1044*44704f69SBart Van Assche eaten = true;
1045*44704f69SBart Van Assche json_array_push((json_value *)jop,
1046*44704f69SBart Van Assche jvp ? jvp : json_null_new());
1047*44704f69SBart Van Assche }
1048*44704f69SBart Van Assche }
1049*44704f69SBart Van Assche goto fini;
1050*44704f69SBart Van Assche }
1051*44704f69SBart Van Assche if (as_json) {
1052*44704f69SBart Van Assche int k;
1053*44704f69SBart Van Assche
1054*44704f69SBart Van Assche if (NULL == jop)
1055*44704f69SBart Van Assche jop = jsp->basep;
1056*44704f69SBart Van Assche k = sgj_name_to_snake(name, jname, sizeof(jname));
1057*44704f69SBart Van Assche if (k > 0) {
1058*44704f69SBart Van Assche done = false;
1059*44704f69SBart Van Assche if (nex_s && (strlen(nex_s) > 0)) {
1060*44704f69SBart Van Assche switch (jtype) {
1061*44704f69SBart Van Assche case json_string:
1062*44704f69SBart Van Assche break;
1063*44704f69SBart Van Assche case json_integer:
1064*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jop, jname, jvp->u.integer,
1065*44704f69SBart Van Assche hex_as_well, sc_mn_s, val_s, nex_s);
1066*44704f69SBart Van Assche done = true;
1067*44704f69SBart Van Assche break;
1068*44704f69SBart Van Assche case json_boolean:
1069*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jop, jname, jvp->u.boolean,
1070*44704f69SBart Van Assche false, sc_mn_s, val_s, nex_s);
1071*44704f69SBart Van Assche done = true;
1072*44704f69SBart Van Assche break;
1073*44704f69SBart Van Assche case json_none:
1074*44704f69SBart Van Assche default:
1075*44704f69SBart Van Assche break;
1076*44704f69SBart Van Assche }
1077*44704f69SBart Van Assche } else {
1078*44704f69SBart Van Assche switch (jtype) {
1079*44704f69SBart Van Assche case json_string:
1080*44704f69SBart Van Assche break;
1081*44704f69SBart Van Assche case json_integer:
1082*44704f69SBart Van Assche if (hex_as_well) {
1083*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, jname, jvp->u.integer,
1084*44704f69SBart Van Assche sc_mn_s, val_s);
1085*44704f69SBart Van Assche done = true;
1086*44704f69SBart Van Assche }
1087*44704f69SBart Van Assche break;
1088*44704f69SBart Van Assche case json_none:
1089*44704f69SBart Van Assche default:
1090*44704f69SBart Van Assche break;
1091*44704f69SBart Van Assche }
1092*44704f69SBart Van Assche }
1093*44704f69SBart Van Assche if (! done) {
1094*44704f69SBart Van Assche eaten = true;
1095*44704f69SBart Van Assche json_object_push((json_value *)jop, jname,
1096*44704f69SBart Van Assche jvp ? jvp : json_null_new());
1097*44704f69SBart Van Assche }
1098*44704f69SBart Van Assche }
1099*44704f69SBart Van Assche }
1100*44704f69SBart Van Assche if (jvp && ((as_json && jsp->pr_out_hr) || (! as_json)))
1101*44704f69SBart Van Assche n += sgj_haj_helper(b + n, blen - n, name, sep, true, jvp, 0);
1102*44704f69SBart Van Assche
1103*44704f69SBart Van Assche if (as_json && jsp->pr_out_hr)
1104*44704f69SBart Van Assche json_array_push((json_value *)jsp->out_hrp, json_string_new(b));
1105*44704f69SBart Van Assche if (! as_json)
1106*44704f69SBart Van Assche printf("%s\n", b);
1107*44704f69SBart Van Assche fini:
1108*44704f69SBart Van Assche if (jvp && (! eaten))
1109*44704f69SBart Van Assche json_builder_free((json_value *)jvp);
1110*44704f69SBart Van Assche }
1111*44704f69SBart Van Assche
1112*44704f69SBart Van Assche void
sgj_haj_vs(sgj_state * jsp,sgj_opaque_p jop,int leadin_sp,const char * name,enum sgj_separator_t sep,const char * value)1113*44704f69SBart Van Assche sgj_haj_vs(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
1114*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep, const char * value)
1115*44704f69SBart Van Assche {
1116*44704f69SBart Van Assche json_value * jvp;
1117*44704f69SBart Van Assche
1118*44704f69SBart Van Assche /* make json_value even if jsp->pr_as_json is false */
1119*44704f69SBart Van Assche jvp = value ? json_string_new(value) : NULL;
1120*44704f69SBart Van Assche sgj_haj_xx(jsp, jop, leadin_sp, name, sep, jvp, false, NULL, NULL);
1121*44704f69SBart Van Assche }
1122*44704f69SBart Van Assche
1123*44704f69SBart Van Assche void
sgj_haj_vi(sgj_state * jsp,sgj_opaque_p jop,int leadin_sp,const char * name,enum sgj_separator_t sep,int64_t value,bool hex_as_well)1124*44704f69SBart Van Assche sgj_haj_vi(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
1125*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep, int64_t value,
1126*44704f69SBart Van Assche bool hex_as_well)
1127*44704f69SBart Van Assche {
1128*44704f69SBart Van Assche json_value * jvp;
1129*44704f69SBart Van Assche
1130*44704f69SBart Van Assche jvp = json_integer_new(value);
1131*44704f69SBart Van Assche sgj_haj_xx(jsp, jop, leadin_sp, name, sep, jvp, hex_as_well, NULL, NULL);
1132*44704f69SBart Van Assche }
1133*44704f69SBart Van Assche
1134*44704f69SBart Van Assche void
sgj_haj_vistr(sgj_state * jsp,sgj_opaque_p jop,int leadin_sp,const char * name,enum sgj_separator_t sep,int64_t value,bool hex_as_well,const char * val_s)1135*44704f69SBart Van Assche sgj_haj_vistr(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
1136*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep, int64_t value,
1137*44704f69SBart Van Assche bool hex_as_well, const char * val_s)
1138*44704f69SBart Van Assche {
1139*44704f69SBart Van Assche json_value * jvp;
1140*44704f69SBart Van Assche
1141*44704f69SBart Van Assche jvp = json_integer_new(value);
1142*44704f69SBart Van Assche sgj_haj_xx(jsp, jop, leadin_sp, name, sep, jvp, hex_as_well, val_s,
1143*44704f69SBart Van Assche NULL);
1144*44704f69SBart Van Assche }
1145*44704f69SBart Van Assche
1146*44704f69SBart Van Assche void
sgj_haj_vi_nex(sgj_state * jsp,sgj_opaque_p jop,int leadin_sp,const char * name,enum sgj_separator_t sep,int64_t value,bool hex_as_well,const char * nex_s)1147*44704f69SBart Van Assche sgj_haj_vi_nex(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
1148*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep,
1149*44704f69SBart Van Assche int64_t value, bool hex_as_well, const char * nex_s)
1150*44704f69SBart Van Assche {
1151*44704f69SBart Van Assche json_value * jvp;
1152*44704f69SBart Van Assche
1153*44704f69SBart Van Assche jvp = json_integer_new(value);
1154*44704f69SBart Van Assche sgj_haj_xx(jsp, jop, leadin_sp, name, sep, jvp, hex_as_well, NULL, nex_s);
1155*44704f69SBart Van Assche }
1156*44704f69SBart Van Assche
1157*44704f69SBart Van Assche void
sgj_haj_vistr_nex(sgj_state * jsp,sgj_opaque_p jop,int leadin_sp,const char * name,enum sgj_separator_t sep,int64_t value,bool hex_as_well,const char * val_s,const char * nex_s)1158*44704f69SBart Van Assche sgj_haj_vistr_nex(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
1159*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep,
1160*44704f69SBart Van Assche int64_t value, bool hex_as_well,
1161*44704f69SBart Van Assche const char * val_s, const char * nex_s)
1162*44704f69SBart Van Assche {
1163*44704f69SBart Van Assche json_value * jvp;
1164*44704f69SBart Van Assche
1165*44704f69SBart Van Assche jvp = json_integer_new(value);
1166*44704f69SBart Van Assche sgj_haj_xx(jsp, jop, leadin_sp, name, sep, jvp, hex_as_well, val_s,
1167*44704f69SBart Van Assche nex_s);
1168*44704f69SBart Van Assche }
1169*44704f69SBart Van Assche
1170*44704f69SBart Van Assche void
sgj_haj_vb(sgj_state * jsp,sgj_opaque_p jop,int leadin_sp,const char * name,enum sgj_separator_t sep,bool value)1171*44704f69SBart Van Assche sgj_haj_vb(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
1172*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep, bool value)
1173*44704f69SBart Van Assche {
1174*44704f69SBart Van Assche json_value * jvp;
1175*44704f69SBart Van Assche
1176*44704f69SBart Van Assche jvp = json_boolean_new(value);
1177*44704f69SBart Van Assche sgj_haj_xx(jsp, jop, leadin_sp, name, sep, jvp, false, NULL, NULL);
1178*44704f69SBart Van Assche }
1179*44704f69SBart Van Assche
1180*44704f69SBart Van Assche sgj_opaque_p
sgj_haj_subo_r(sgj_state * jsp,sgj_opaque_p jop,int leadin_sp,const char * name,enum sgj_separator_t sep,int64_t value,bool hex_as_well)1181*44704f69SBart Van Assche sgj_haj_subo_r(sgj_state * jsp, sgj_opaque_p jop, int leadin_sp,
1182*44704f69SBart Van Assche const char * name, enum sgj_separator_t sep, int64_t value,
1183*44704f69SBart Van Assche bool hex_as_well)
1184*44704f69SBart Van Assche {
1185*44704f69SBart Van Assche bool as_json = (jsp && jsp->pr_as_json);
1186*44704f69SBart Van Assche int n = 0;
1187*44704f69SBart Van Assche sgj_opaque_p jo2p;
1188*44704f69SBart Van Assche char b[256];
1189*44704f69SBart Van Assche static const int blen = sizeof(b);
1190*44704f69SBart Van Assche
1191*44704f69SBart Van Assche if (NULL == name)
1192*44704f69SBart Van Assche return NULL;
1193*44704f69SBart Van Assche for (n = 0; n < leadin_sp; ++n)
1194*44704f69SBart Van Assche b[n] = ' ';
1195*44704f69SBart Van Assche b[n] = '\0';
1196*44704f69SBart Van Assche if ((! as_json) || (jsp && jsp->pr_out_hr))
1197*44704f69SBart Van Assche n += sgj_haj_helper(b + n, blen - n, name, sep, false, NULL, value);
1198*44704f69SBart Van Assche
1199*44704f69SBart Van Assche if (as_json && jsp->pr_out_hr)
1200*44704f69SBart Van Assche json_array_push((json_value *)jsp->out_hrp, json_string_new(b));
1201*44704f69SBart Van Assche if (! as_json)
1202*44704f69SBart Van Assche printf("%s\n", b);
1203*44704f69SBart Van Assche
1204*44704f69SBart Van Assche if (as_json) {
1205*44704f69SBart Van Assche sgj_name_to_snake(name, b, blen);
1206*44704f69SBart Van Assche jo2p = sgj_named_subobject_r(jsp, jop, b);
1207*44704f69SBart Van Assche if (jo2p) {
1208*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "i", value);
1209*44704f69SBart Van Assche if (hex_as_well && jsp->pr_hex) {
1210*44704f69SBart Van Assche snprintf(b, blen, "%" PRIx64, value);
1211*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, "hex", b);
1212*44704f69SBart Van Assche }
1213*44704f69SBart Van Assche }
1214*44704f69SBart Van Assche return jo2p;
1215*44704f69SBart Van Assche }
1216*44704f69SBart Van Assche return NULL;
1217*44704f69SBart Van Assche }
1218*44704f69SBart Van Assche
1219*44704f69SBart Van Assche #ifdef SG_PRSE_SENSE_DECODE
1220*44704f69SBart Van Assche
1221*44704f69SBart Van Assche static const char * dtsp = "descriptor too short";
1222*44704f69SBart Van Assche static const char * sksvp = "sense-key specific valid";
1223*44704f69SBart Van Assche static const char * ddep = "designation_descriptor_error";
1224*44704f69SBart Van Assche static const char * naa_exp = "Network Address Authority";
1225*44704f69SBart Van Assche static const char * aoi_exp = "IEEE-Administered Organizational Identifier";
1226*44704f69SBart Van Assche
1227*44704f69SBart Van Assche bool
sgj_js_designation_descriptor(sgj_state * jsp,sgj_opaque_p jop,const uint8_t * ddp,int dd_len)1228*44704f69SBart Van Assche sgj_js_designation_descriptor(sgj_state * jsp, sgj_opaque_p jop,
1229*44704f69SBart Van Assche const uint8_t * ddp, int dd_len)
1230*44704f69SBart Van Assche {
1231*44704f69SBart Van Assche int p_id, piv, c_set, assoc, desig_type, d_id, naa;
1232*44704f69SBart Van Assche int n, aoi, vsi, dlen;
1233*44704f69SBart Van Assche uint64_t ull;
1234*44704f69SBart Van Assche const uint8_t * ip;
1235*44704f69SBart Van Assche char e[80];
1236*44704f69SBart Van Assche char b[256];
1237*44704f69SBart Van Assche const char * cp;
1238*44704f69SBart Van Assche const char * naa_sp;
1239*44704f69SBart Van Assche sgj_opaque_p jo2p;
1240*44704f69SBart Van Assche static const int blen = sizeof(b);
1241*44704f69SBart Van Assche static const int elen = sizeof(e);
1242*44704f69SBart Van Assche
1243*44704f69SBart Van Assche if (dd_len < 4) {
1244*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, ddep, "too short");
1245*44704f69SBart Van Assche return false;
1246*44704f69SBart Van Assche }
1247*44704f69SBart Van Assche dlen = ddp[3];
1248*44704f69SBart Van Assche if (dlen > (dd_len - 4)) {
1249*44704f69SBart Van Assche snprintf(e, elen, "too long: says it is %d bytes, but given %d "
1250*44704f69SBart Van Assche "bytes\n", dlen, dd_len - 4);
1251*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, ddep, e);
1252*44704f69SBart Van Assche return false;
1253*44704f69SBart Van Assche }
1254*44704f69SBart Van Assche ip = ddp + 4;
1255*44704f69SBart Van Assche p_id = ((ddp[0] >> 4) & 0xf);
1256*44704f69SBart Van Assche c_set = (ddp[0] & 0xf);
1257*44704f69SBart Van Assche piv = ((ddp[1] & 0x80) ? 1 : 0);
1258*44704f69SBart Van Assche assoc = ((ddp[1] >> 4) & 0x3);
1259*44704f69SBart Van Assche desig_type = (ddp[1] & 0xf);
1260*44704f69SBart Van Assche cp = sg_get_desig_assoc_str(assoc);
1261*44704f69SBart Van Assche if (assoc == 3)
1262*44704f69SBart Van Assche cp = "Reserved [0x3]"; /* should not happen */
1263*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "association", assoc, NULL, cp);
1264*44704f69SBart Van Assche cp = sg_get_desig_type_str(desig_type);
1265*44704f69SBart Van Assche if (NULL == cp)
1266*44704f69SBart Van Assche cp = "unknown";
1267*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "designator_type", desig_type,
1268*44704f69SBart Van Assche NULL, cp);
1269*44704f69SBart Van Assche cp = sg_get_desig_code_set_str(c_set);
1270*44704f69SBart Van Assche if (NULL == cp)
1271*44704f69SBart Van Assche cp = "unknown";
1272*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "code_set", desig_type,
1273*44704f69SBart Van Assche NULL, cp);
1274*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "piv", piv, false,
1275*44704f69SBart Van Assche "Protocol Identifier Valid");
1276*44704f69SBart Van Assche sg_get_trans_proto_str(p_id, elen, e);
1277*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "protocol_identifier", p_id, NULL, e);
1278*44704f69SBart Van Assche switch (desig_type) {
1279*44704f69SBart Van Assche case 0: /* vendor specific */
1280*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jop, "vendor_specific_hexbytes", ip, dlen);
1281*44704f69SBart Van Assche break;
1282*44704f69SBart Van Assche case 1: /* T10 vendor identification */
1283*44704f69SBart Van Assche n = (dlen < 8) ? dlen : 8;
1284*44704f69SBart Van Assche snprintf(b, blen, "%.*s", n, ip);
1285*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "t10_vendor_identification", b);
1286*44704f69SBart Van Assche b[0] = '\0';
1287*44704f69SBart Van Assche if (dlen > 8)
1288*44704f69SBart Van Assche snprintf(b, blen, "%.*s", dlen - 8, ip + 8);
1289*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "vendor_specific_identifier", b);
1290*44704f69SBart Van Assche break;
1291*44704f69SBart Van Assche case 2: /* EUI-64 based */
1292*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, "eui_64_based_designator_length", dlen);
1293*44704f69SBart Van Assche ull = sg_get_unaligned_be64(ip);
1294*44704f69SBart Van Assche switch (dlen) {
1295*44704f69SBart Van Assche case 8:
1296*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "ieee_identifier", ull);
1297*44704f69SBart Van Assche break;
1298*44704f69SBart Van Assche case 12:
1299*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "ieee_identifier", ull);
1300*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "directory_id",
1301*44704f69SBart Van Assche sg_get_unaligned_be32(ip + 8));
1302*44704f69SBart Van Assche break;
1303*44704f69SBart Van Assche case 16:
1304*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "identifier_extension", ull);
1305*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "ieee_identifier",
1306*44704f69SBart Van Assche sg_get_unaligned_be64(ip + 8));
1307*44704f69SBart Van Assche break;
1308*44704f69SBart Van Assche default:
1309*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "eui_64", "decoding failed");
1310*44704f69SBart Van Assche break;
1311*44704f69SBart Van Assche }
1312*44704f69SBart Van Assche break;
1313*44704f69SBart Van Assche case 3: /* NAA <n> */
1314*44704f69SBart Van Assche if (jsp->pr_hex)
1315*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jop, "full_naa_hexbytes", ip, dlen);
1316*44704f69SBart Van Assche naa = (ip[0] >> 4) & 0xff;
1317*44704f69SBart Van Assche switch (naa) {
1318*44704f69SBart Van Assche case 2:
1319*44704f69SBart Van Assche naa_sp = "IEEE Extended";
1320*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jop, "naa", naa, false, NULL, naa_sp,
1321*44704f69SBart Van Assche naa_exp);
1322*44704f69SBart Van Assche d_id = (((ip[0] & 0xf) << 8) | ip[1]);
1323*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "vendor_specific_identifier_a", d_id);
1324*44704f69SBart Van Assche aoi = sg_get_unaligned_be24(ip + 2);
1325*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "aoi", aoi, true, aoi_exp);
1326*44704f69SBart Van Assche vsi = sg_get_unaligned_be24(ip + 5);
1327*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "vendor_specific_identifier_b", vsi);
1328*44704f69SBart Van Assche break;
1329*44704f69SBart Van Assche case 3:
1330*44704f69SBart Van Assche naa_sp = "Locally Assigned";
1331*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jop, "naa", naa, false, NULL, naa_sp,
1332*44704f69SBart Van Assche naa_exp);
1333*44704f69SBart Van Assche ull = sg_get_unaligned_be64(ip + 0) & 0xfffffffffffffffULL;
1334*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "locally_administered_value", ull);
1335*44704f69SBart Van Assche break;
1336*44704f69SBart Van Assche case 5:
1337*44704f69SBart Van Assche naa_sp = "IEEE Registered";
1338*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jop, "naa", naa, false, NULL, naa_sp,
1339*44704f69SBart Van Assche naa_exp);
1340*44704f69SBart Van Assche aoi = (sg_get_unaligned_be32(ip + 0) >> 4) & 0xffffff;
1341*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "aoi", aoi, true, aoi_exp);
1342*44704f69SBart Van Assche ull = sg_get_unaligned_be48(ip + 2) & 0xfffffffffULL;
1343*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "vendor_specific_identifier", ull);
1344*44704f69SBart Van Assche break;
1345*44704f69SBart Van Assche case 6:
1346*44704f69SBart Van Assche naa_sp = "IEEE Registered Extended";
1347*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jop, "naa", naa, false, NULL, naa_sp,
1348*44704f69SBart Van Assche naa_exp);
1349*44704f69SBart Van Assche aoi = (sg_get_unaligned_be32(ip + 0) >> 4) & 0xffffff;
1350*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "aoi", aoi, true, aoi_exp);
1351*44704f69SBart Van Assche ull = sg_get_unaligned_be48(ip + 2) & 0xfffffffffULL;
1352*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "vendor_specific_identifier", ull);
1353*44704f69SBart Van Assche ull = sg_get_unaligned_be64(ip + 8);
1354*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "vendor_specific_identifier_extension",
1355*44704f69SBart Van Assche ull);
1356*44704f69SBart Van Assche break;
1357*44704f69SBart Van Assche default:
1358*44704f69SBart Van Assche snprintf(b, blen, "unknown NAA value=0x%x", naa);
1359*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex(jsp, jop, "naa", naa, true, NULL, b,
1360*44704f69SBart Van Assche naa_exp);
1361*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jop, "full_naa_hexbytes", ip, dlen);
1362*44704f69SBart Van Assche break;
1363*44704f69SBart Van Assche }
1364*44704f69SBart Van Assche break;
1365*44704f69SBart Van Assche case 4: /* Relative target port */
1366*44704f69SBart Van Assche if (jsp->pr_hex)
1367*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jop, "relative_target_port_hexbytes",
1368*44704f69SBart Van Assche ip, dlen);
1369*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "relative_target_port_identifier",
1370*44704f69SBart Van Assche sg_get_unaligned_be16(ip + 2));
1371*44704f69SBart Van Assche break;
1372*44704f69SBart Van Assche case 5: /* (primary) Target port group */
1373*44704f69SBart Van Assche if (jsp->pr_hex)
1374*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jop, "target_port_group_hexbytes",
1375*44704f69SBart Van Assche ip, dlen);
1376*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "target_port_group",
1377*44704f69SBart Van Assche sg_get_unaligned_be16(ip + 2));
1378*44704f69SBart Van Assche break;
1379*44704f69SBart Van Assche case 6: /* Logical unit group */
1380*44704f69SBart Van Assche if (jsp->pr_hex)
1381*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jop, "logical_unit_group_hexbytes",
1382*44704f69SBart Van Assche ip, dlen);
1383*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "logical_unit_group",
1384*44704f69SBart Van Assche sg_get_unaligned_be16(ip + 2));
1385*44704f69SBart Van Assche break;
1386*44704f69SBart Van Assche case 7: /* MD5 logical unit identifier */
1387*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jop, "md5_logical_unit_hexbytes",
1388*44704f69SBart Van Assche ip, dlen);
1389*44704f69SBart Van Assche break;
1390*44704f69SBart Van Assche case 8: /* SCSI name string */
1391*44704f69SBart Van Assche if (jsp->pr_hex)
1392*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jop, "scsi_name_string_hexbytes",
1393*44704f69SBart Van Assche ip, dlen);
1394*44704f69SBart Van Assche snprintf(b, blen, "%.*s", dlen, ip);
1395*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "scsi_name_string", b);
1396*44704f69SBart Van Assche break;
1397*44704f69SBart Van Assche case 9: /* Protocol specific port identifier */
1398*44704f69SBart Van Assche if (jsp->pr_hex)
1399*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jop,
1400*44704f69SBart Van Assche "protocol_specific_port_identifier_hexbytes",
1401*44704f69SBart Van Assche ip, dlen);
1402*44704f69SBart Van Assche if (TPROTO_UAS == p_id) {
1403*44704f69SBart Van Assche jo2p = sgj_named_subobject_r(jsp, jop,
1404*44704f69SBart Van Assche "usb_target_port_identifier");
1405*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "device_address", 0x7f & ip[0]);
1406*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "interface_number", ip[2]);
1407*44704f69SBart Van Assche } else if (TPROTO_SOP == p_id) {
1408*44704f69SBart Van Assche jo2p = sgj_named_subobject_r(jsp, jop, "pci_express_routing_id");
1409*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "routing_id",
1410*44704f69SBart Van Assche sg_get_unaligned_be16(ip + 0));
1411*44704f69SBart Van Assche } else
1412*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "protocol_specific_port_identifier",
1413*44704f69SBart Van Assche "decoding failure");
1414*44704f69SBart Van Assche
1415*44704f69SBart Van Assche break;
1416*44704f69SBart Van Assche case 0xa: /* UUID identifier */
1417*44704f69SBart Van Assche if (jsp->pr_hex)
1418*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jop, "uuid_hexbytes", ip, dlen);
1419*44704f69SBart Van Assche sg_t10_uuid_desig2str(ip, dlen, c_set, false, true, NULL, blen, b);
1420*44704f69SBart Van Assche n = strlen(b);
1421*44704f69SBart Van Assche if ((n > 0) && ('\n' == b[n - 1]))
1422*44704f69SBart Van Assche b[n - 1] = '\0';
1423*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "uuid", b);
1424*44704f69SBart Van Assche break;
1425*44704f69SBart Van Assche default: /* reserved */
1426*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jop, "reserved_designator_hexbytes",
1427*44704f69SBart Van Assche ip, dlen);
1428*44704f69SBart Van Assche break;
1429*44704f69SBart Van Assche }
1430*44704f69SBart Van Assche return true;
1431*44704f69SBart Van Assche }
1432*44704f69SBart Van Assche
1433*44704f69SBart Van Assche static void
sgj_progress_indication(sgj_state * jsp,sgj_opaque_p jop,uint16_t prog_indic,bool is_another)1434*44704f69SBart Van Assche sgj_progress_indication(sgj_state * jsp, sgj_opaque_p jop,
1435*44704f69SBart Van Assche uint16_t prog_indic, bool is_another)
1436*44704f69SBart Van Assche {
1437*44704f69SBart Van Assche uint32_t progress, pr, rem;
1438*44704f69SBart Van Assche sgj_opaque_p jo2p;
1439*44704f69SBart Van Assche char b[64];
1440*44704f69SBart Van Assche
1441*44704f69SBart Van Assche if (is_another)
1442*44704f69SBart Van Assche jo2p = sgj_named_subobject_r(jsp, jop, "another_progress_indication");
1443*44704f69SBart Van Assche else
1444*44704f69SBart Van Assche jo2p = sgj_named_subobject_r(jsp, jop, "progress_indication");
1445*44704f69SBart Van Assche if (NULL == jo2p)
1446*44704f69SBart Van Assche return;
1447*44704f69SBart Van Assche progress = prog_indic;
1448*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "i", progress);
1449*44704f69SBart Van Assche snprintf(b, sizeof(b), "%x", progress);
1450*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, "hex", b);
1451*44704f69SBart Van Assche progress *= 100;
1452*44704f69SBart Van Assche pr = progress / 65536;
1453*44704f69SBart Van Assche rem = (progress % 65536) / 656;
1454*44704f69SBart Van Assche snprintf(b, sizeof(b), "%d.02%d%%\n", pr, rem);
1455*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, "percentage", b);
1456*44704f69SBart Van Assche }
1457*44704f69SBart Van Assche
1458*44704f69SBart Van Assche static bool
sgj_decode_sks(sgj_state * jsp,sgj_opaque_p jop,const uint8_t * dp,int dlen,int sense_key)1459*44704f69SBart Van Assche sgj_decode_sks(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * dp, int dlen,
1460*44704f69SBart Van Assche int sense_key)
1461*44704f69SBart Van Assche {
1462*44704f69SBart Van Assche switch (sense_key) {
1463*44704f69SBart Van Assche case SPC_SK_ILLEGAL_REQUEST:
1464*44704f69SBart Van Assche if (dlen < 3) {
1465*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "illegal_request_sks", dtsp);
1466*44704f69SBart Van Assche return false;
1467*44704f69SBart Van Assche }
1468*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
1469*44704f69SBart Van Assche sksvp);
1470*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "c_d", !! (dp[0] & 0x40), false,
1471*44704f69SBart Van Assche "c: cdb; d: data-out");
1472*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "bpv", !! (dp[0] & 0x8), false,
1473*44704f69SBart Van Assche "bit pointer (index) valid");
1474*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, "bit_pointer", dp[0] & 0x7);
1475*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "field_pointer",
1476*44704f69SBart Van Assche sg_get_unaligned_be16(dp + 1));
1477*44704f69SBart Van Assche break;
1478*44704f69SBart Van Assche case SPC_SK_HARDWARE_ERROR:
1479*44704f69SBart Van Assche case SPC_SK_MEDIUM_ERROR:
1480*44704f69SBart Van Assche case SPC_SK_RECOVERED_ERROR:
1481*44704f69SBart Van Assche if (dlen < 3) {
1482*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "actual_retry_count_sks", dtsp);
1483*44704f69SBart Van Assche return false;
1484*44704f69SBart Van Assche }
1485*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
1486*44704f69SBart Van Assche sksvp);
1487*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "actual_retry_count",
1488*44704f69SBart Van Assche sg_get_unaligned_be16(dp + 1));
1489*44704f69SBart Van Assche break;
1490*44704f69SBart Van Assche case SPC_SK_NO_SENSE:
1491*44704f69SBart Van Assche case SPC_SK_NOT_READY:
1492*44704f69SBart Van Assche if (dlen < 7) {
1493*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "progress_indication_sks", dtsp);
1494*44704f69SBart Van Assche return false;
1495*44704f69SBart Van Assche }
1496*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
1497*44704f69SBart Van Assche sksvp);
1498*44704f69SBart Van Assche sgj_progress_indication(jsp, jop, sg_get_unaligned_be16(dp + 1),
1499*44704f69SBart Van Assche false);
1500*44704f69SBart Van Assche break;
1501*44704f69SBart Van Assche case SPC_SK_COPY_ABORTED:
1502*44704f69SBart Van Assche if (dlen < 7) {
1503*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "segment_indication_sks", dtsp);
1504*44704f69SBart Van Assche return false;
1505*44704f69SBart Van Assche }
1506*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
1507*44704f69SBart Van Assche sksvp);
1508*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "sd", !! (dp[0] & 0x20), false,
1509*44704f69SBart Van Assche "field pointer relative to: 1->segment "
1510*44704f69SBart Van Assche "descriptor, 0->parameter list");
1511*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "bpv", !! (dp[0] & 0x8), false,
1512*44704f69SBart Van Assche "bit pointer (index) valid");
1513*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, "bit_pointer", dp[0] & 0x7);
1514*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "field_pointer",
1515*44704f69SBart Van Assche sg_get_unaligned_be16(dp + 1));
1516*44704f69SBart Van Assche break;
1517*44704f69SBart Van Assche case SPC_SK_UNIT_ATTENTION:
1518*44704f69SBart Van Assche if (dlen < 7) {
1519*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "segment_indication_sks", dtsp);
1520*44704f69SBart Van Assche return false;
1521*44704f69SBart Van Assche }
1522*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "sksv", !! (dp[0] & 0x80), false,
1523*44704f69SBart Van Assche sksvp);
1524*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, "overflow", !! (dp[0] & 0x80));
1525*44704f69SBart Van Assche break;
1526*44704f69SBart Van Assche default:
1527*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "unexpected_sense_key", sense_key);
1528*44704f69SBart Van Assche return false;
1529*44704f69SBart Van Assche }
1530*44704f69SBart Van Assche return true;
1531*44704f69SBart Van Assche }
1532*44704f69SBart Van Assche
1533*44704f69SBart Van Assche #define TPGS_STATE_OPTIMIZED 0x0
1534*44704f69SBart Van Assche #define TPGS_STATE_NONOPTIMIZED 0x1
1535*44704f69SBart Van Assche #define TPGS_STATE_STANDBY 0x2
1536*44704f69SBart Van Assche #define TPGS_STATE_UNAVAILABLE 0x3
1537*44704f69SBart Van Assche #define TPGS_STATE_OFFLINE 0xe
1538*44704f69SBart Van Assche #define TPGS_STATE_TRANSITIONING 0xf
1539*44704f69SBart Van Assche
1540*44704f69SBart Van Assche static int
decode_tpgs_state(int st,char * b,int blen)1541*44704f69SBart Van Assche decode_tpgs_state(int st, char * b, int blen)
1542*44704f69SBart Van Assche {
1543*44704f69SBart Van Assche switch (st) {
1544*44704f69SBart Van Assche case TPGS_STATE_OPTIMIZED:
1545*44704f69SBart Van Assche return sg_scnpr(b, blen, "active/optimized");
1546*44704f69SBart Van Assche case TPGS_STATE_NONOPTIMIZED:
1547*44704f69SBart Van Assche return sg_scnpr(b, blen, "active/non optimized");
1548*44704f69SBart Van Assche case TPGS_STATE_STANDBY:
1549*44704f69SBart Van Assche return sg_scnpr(b, blen, "standby");
1550*44704f69SBart Van Assche case TPGS_STATE_UNAVAILABLE:
1551*44704f69SBart Van Assche return sg_scnpr(b, blen, "unavailable");
1552*44704f69SBart Van Assche case TPGS_STATE_OFFLINE:
1553*44704f69SBart Van Assche return sg_scnpr(b, blen, "offline");
1554*44704f69SBart Van Assche case TPGS_STATE_TRANSITIONING:
1555*44704f69SBart Van Assche return sg_scnpr(b, blen, "transitioning between states");
1556*44704f69SBart Van Assche default:
1557*44704f69SBart Van Assche return sg_scnpr(b, blen, "unknown: 0x%x", st);
1558*44704f69SBart Van Assche }
1559*44704f69SBart Van Assche }
1560*44704f69SBart Van Assche
1561*44704f69SBart Van Assche static bool
sgj_uds_referral_descriptor(sgj_state * jsp,sgj_opaque_p jop,const uint8_t * dp,int alen)1562*44704f69SBart Van Assche sgj_uds_referral_descriptor(sgj_state * jsp, sgj_opaque_p jop,
1563*44704f69SBart Van Assche const uint8_t * dp, int alen)
1564*44704f69SBart Van Assche {
1565*44704f69SBart Van Assche int dlen = alen - 2;
1566*44704f69SBart Van Assche int k, j, g, f, aas;
1567*44704f69SBart Van Assche uint64_t ull;
1568*44704f69SBart Van Assche const uint8_t * tp;
1569*44704f69SBart Van Assche sgj_opaque_p jap, jo2p, ja2p, jo3p;
1570*44704f69SBart Van Assche char c[40];
1571*44704f69SBart Van Assche
1572*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "not_all_r", (dp[2] & 0x1), false,
1573*44704f69SBart Van Assche "Not all referrals");
1574*44704f69SBart Van Assche dp += 4;
1575*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jop,
1576*44704f69SBart Van Assche "user_data_segment_referral_descriptor_list");
1577*44704f69SBart Van Assche for (k = 0, f = 1; (k + 4) < dlen; k += g, dp += g, ++f) {
1578*44704f69SBart Van Assche int ntpgd = dp[3];
1579*44704f69SBart Van Assche
1580*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
1581*44704f69SBart Van Assche g = (ntpgd * 4) + 20;
1582*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "number_of_target_port_group_descriptors",
1583*44704f69SBart Van Assche ntpgd);
1584*44704f69SBart Van Assche if ((k + g) > dlen) {
1585*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "truncated_descriptor_dlen", dlen);
1586*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
1587*44704f69SBart Van Assche return false;
1588*44704f69SBart Van Assche }
1589*44704f69SBart Van Assche ull = sg_get_unaligned_be64(dp + 4);
1590*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "first_user_date_sgment_lba", ull);
1591*44704f69SBart Van Assche ull = sg_get_unaligned_be64(dp + 12);
1592*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "last_user_date_sgment_lba", ull);
1593*44704f69SBart Van Assche ja2p = sgj_named_subarray_r(jsp, jo2p,
1594*44704f69SBart Van Assche "target_port_group_descriptor_list");
1595*44704f69SBart Van Assche for (j = 0; j < ntpgd; ++j) {
1596*44704f69SBart Van Assche jo3p = sgj_new_unattached_object_r(jsp);
1597*44704f69SBart Van Assche tp = dp + 20 + (j * 4);
1598*44704f69SBart Van Assche aas = tp[0] & 0xf;
1599*44704f69SBart Van Assche decode_tpgs_state(aas, c, sizeof(c));
1600*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo3p, "asymmetric_access_state", aas,
1601*44704f69SBart Van Assche NULL, c);
1602*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo3p, "target_port_group",
1603*44704f69SBart Van Assche sg_get_unaligned_be16(tp + 2));
1604*44704f69SBart Van Assche sgj_js_nv_o(jsp, ja2p, NULL /* name */, jo3p);
1605*44704f69SBart Van Assche }
1606*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
1607*44704f69SBart Van Assche }
1608*44704f69SBart Van Assche return true;
1609*44704f69SBart Van Assche }
1610*44704f69SBart Van Assche
1611*44704f69SBart Van Assche /* Copy of static array in sg_lib.c */
1612*44704f69SBart Van Assche static const char * dd_usage_reason_str_arr[] = {
1613*44704f69SBart Van Assche "Unknown",
1614*44704f69SBart Van Assche "resend this and further commands to:",
1615*44704f69SBart Van Assche "resend this command to:",
1616*44704f69SBart Van Assche "new subsidiary lu added to this administrative lu:",
1617*44704f69SBart Van Assche "administrative lu associated with a preferred binding:",
1618*44704f69SBart Van Assche };
1619*44704f69SBart Van Assche
1620*44704f69SBart Van Assche static bool
sgj_js_sense_descriptors(sgj_state * jsp,sgj_opaque_p jop,const struct sg_scsi_sense_hdr * sshp,const uint8_t * sbp,int sb_len)1621*44704f69SBart Van Assche sgj_js_sense_descriptors(sgj_state * jsp, sgj_opaque_p jop,
1622*44704f69SBart Van Assche const struct sg_scsi_sense_hdr * sshp,
1623*44704f69SBart Van Assche const uint8_t * sbp, int sb_len)
1624*44704f69SBart Van Assche {
1625*44704f69SBart Van Assche bool processed = true;
1626*44704f69SBart Van Assche int add_sb_len, desc_len, k, dt, sense_key, n, sds;
1627*44704f69SBart Van Assche uint16_t sct_sc;
1628*44704f69SBart Van Assche uint64_t ull;
1629*44704f69SBart Van Assche const uint8_t * descp;
1630*44704f69SBart Van Assche const char * cp;
1631*44704f69SBart Van Assche sgj_opaque_p jap, jo2p, jo3p;
1632*44704f69SBart Van Assche char b[80];
1633*44704f69SBart Van Assche static const int blen = sizeof(b);
1634*44704f69SBart Van Assche static const char * parsing = "parsing_error";
1635*44704f69SBart Van Assche #if 0
1636*44704f69SBart Van Assche static const char * eccp = "Extended copy command";
1637*44704f69SBart Van Assche static const char * ddp = "destination device";
1638*44704f69SBart Van Assche #endif
1639*44704f69SBart Van Assche
1640*44704f69SBart Van Assche add_sb_len = sshp->additional_length;
1641*44704f69SBart Van Assche add_sb_len = (add_sb_len < sb_len) ? add_sb_len : sb_len;
1642*44704f69SBart Van Assche sense_key = sshp->sense_key;
1643*44704f69SBart Van Assche jap = sgj_named_subarray_r(jsp, jop, "sense_data_descriptor_list");
1644*44704f69SBart Van Assche
1645*44704f69SBart Van Assche for (descp = sbp, k = 0; (k < add_sb_len);
1646*44704f69SBart Van Assche k += desc_len, descp += desc_len) {
1647*44704f69SBart Van Assche int add_d_len = (k < (add_sb_len - 1)) ? descp[1] : -1;
1648*44704f69SBart Van Assche
1649*44704f69SBart Van Assche jo2p = sgj_new_unattached_object_r(jsp);
1650*44704f69SBart Van Assche if ((k + add_d_len + 2) > add_sb_len)
1651*44704f69SBart Van Assche add_d_len = add_sb_len - k - 2;
1652*44704f69SBart Van Assche desc_len = add_d_len + 2;
1653*44704f69SBart Van Assche processed = true;
1654*44704f69SBart Van Assche dt = descp[0];
1655*44704f69SBart Van Assche switch (dt) {
1656*44704f69SBart Van Assche case 0:
1657*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt,
1658*44704f69SBart Van Assche NULL, "Information");
1659*44704f69SBart Van Assche if (add_d_len >= 10) {
1660*44704f69SBart Van Assche int valid = !! (0x80 & descp[2]);
1661*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "valid", valid, NULL,
1662*44704f69SBart Van Assche valid ? "as per T10" : "Vendor specific");
1663*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "information",
1664*44704f69SBart Van Assche sg_get_unaligned_be64(descp + 4));
1665*44704f69SBart Van Assche } else {
1666*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, parsing, dtsp);
1667*44704f69SBart Van Assche processed = false;
1668*44704f69SBart Van Assche }
1669*44704f69SBart Van Assche break;
1670*44704f69SBart Van Assche case 1:
1671*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt,
1672*44704f69SBart Van Assche NULL, "Command specific");
1673*44704f69SBart Van Assche if (add_d_len >= 10) {
1674*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "command_specific_information",
1675*44704f69SBart Van Assche sg_get_unaligned_be64(descp + 4));
1676*44704f69SBart Van Assche } else {
1677*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, parsing, dtsp);
1678*44704f69SBart Van Assche processed = false;
1679*44704f69SBart Van Assche }
1680*44704f69SBart Van Assche break;
1681*44704f69SBart Van Assche case 2: /* Sense Key Specific */
1682*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1683*44704f69SBart Van Assche "Sense key specific");
1684*44704f69SBart Van Assche processed = sgj_decode_sks(jsp, jo2p, descp + 4, desc_len - 4,
1685*44704f69SBart Van Assche sense_key);
1686*44704f69SBart Van Assche break;
1687*44704f69SBart Van Assche case 3:
1688*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1689*44704f69SBart Van Assche "Field replaceable unit code");
1690*44704f69SBart Van Assche if (add_d_len >= 2)
1691*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "field_replaceable_unit_code",
1692*44704f69SBart Van Assche descp[3]);
1693*44704f69SBart Van Assche else {
1694*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, parsing, dtsp);
1695*44704f69SBart Van Assche processed = false;
1696*44704f69SBart Van Assche }
1697*44704f69SBart Van Assche break;
1698*44704f69SBart Van Assche case 4:
1699*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1700*44704f69SBart Van Assche "Stream commands");
1701*44704f69SBart Van Assche if (add_d_len >= 2) {
1702*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "filemark", !! (descp[3] & 0x80));
1703*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "eom", !! (descp[3] & 0x40),
1704*44704f69SBart Van Assche false, "End Of Medium");
1705*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "ili", !! (descp[3] & 0x20),
1706*44704f69SBart Van Assche false, "Incorrect Length Indicator");
1707*44704f69SBart Van Assche } else {
1708*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, parsing, dtsp);
1709*44704f69SBart Van Assche processed = false;
1710*44704f69SBart Van Assche }
1711*44704f69SBart Van Assche break;
1712*44704f69SBart Van Assche case 5:
1713*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1714*44704f69SBart Van Assche "Block commands");
1715*44704f69SBart Van Assche if (add_d_len >= 2)
1716*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "ili", !! (descp[3] & 0x20),
1717*44704f69SBart Van Assche false, "Incorrect Length Indicator");
1718*44704f69SBart Van Assche else {
1719*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, parsing, dtsp);
1720*44704f69SBart Van Assche processed = false;
1721*44704f69SBart Van Assche }
1722*44704f69SBart Van Assche break;
1723*44704f69SBart Van Assche case 6:
1724*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1725*44704f69SBart Van Assche "OSD object identification");
1726*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, parsing, "Unsupported");
1727*44704f69SBart Van Assche processed = false;
1728*44704f69SBart Van Assche break;
1729*44704f69SBart Van Assche case 7:
1730*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1731*44704f69SBart Van Assche "OSD response integrity check value");
1732*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, parsing, "Unsupported");
1733*44704f69SBart Van Assche break;
1734*44704f69SBart Van Assche case 8:
1735*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1736*44704f69SBart Van Assche "OSD attribute identification");
1737*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, parsing, "Unsupported");
1738*44704f69SBart Van Assche processed = false;
1739*44704f69SBart Van Assche break;
1740*44704f69SBart Van Assche case 9: /* this is defined in SAT (SAT-2) */
1741*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1742*44704f69SBart Van Assche "ATA status return");
1743*44704f69SBart Van Assche if (add_d_len >= 12) {
1744*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "extend", !! (descp[2] & 1));
1745*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "error", descp[3]);
1746*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "count",
1747*44704f69SBart Van Assche sg_get_unaligned_be16(descp + 4));
1748*44704f69SBart Van Assche ull = ((uint64_t)descp[10] << 40) |
1749*44704f69SBart Van Assche ((uint64_t)descp[8] << 32) |
1750*44704f69SBart Van Assche (descp[6] << 24) |
1751*44704f69SBart Van Assche (descp[11] << 16) |
1752*44704f69SBart Van Assche (descp[9] << 8) |
1753*44704f69SBart Van Assche descp[7];
1754*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "lba", ull);
1755*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "device", descp[12]);
1756*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "status", descp[13]);
1757*44704f69SBart Van Assche } else {
1758*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, parsing, dtsp);
1759*44704f69SBart Van Assche processed = false;
1760*44704f69SBart Van Assche }
1761*44704f69SBart Van Assche break;
1762*44704f69SBart Van Assche case 0xa:
1763*44704f69SBart Van Assche /* Added in SPC-4 rev 17, became 'Another ...' in rev 34 */
1764*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1765*44704f69SBart Van Assche "Another progress indication");
1766*44704f69SBart Van Assche if (add_d_len < 6) {
1767*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, parsing, dtsp);
1768*44704f69SBart Van Assche processed = false;
1769*44704f69SBart Van Assche break;
1770*44704f69SBart Van Assche }
1771*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "another_sense_key", descp[2]);
1772*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "another_additional_sense_code",
1773*44704f69SBart Van Assche descp[3]);
1774*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p,
1775*44704f69SBart Van Assche "another_additional_sense_code_qualifier",
1776*44704f69SBart Van Assche descp[4]);
1777*44704f69SBart Van Assche sgj_progress_indication(jsp, jo2p,
1778*44704f69SBart Van Assche sg_get_unaligned_be16(descp + 6), true);
1779*44704f69SBart Van Assche break;
1780*44704f69SBart Van Assche case 0xb: /* Added in SPC-4 rev 23, defined in SBC-3 rev 22 */
1781*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1782*44704f69SBart Van Assche "User data segment referral");
1783*44704f69SBart Van Assche if (add_d_len < 2) {
1784*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, parsing, dtsp);
1785*44704f69SBart Van Assche processed = false;
1786*44704f69SBart Van Assche break;
1787*44704f69SBart Van Assche }
1788*44704f69SBart Van Assche if (! sgj_uds_referral_descriptor(jsp, jo2p, descp, add_d_len)) {
1789*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, parsing, dtsp);
1790*44704f69SBart Van Assche processed = false;
1791*44704f69SBart Van Assche }
1792*44704f69SBart Van Assche break;
1793*44704f69SBart Van Assche case 0xc: /* Added in SPC-4 rev 28 */
1794*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1795*44704f69SBart Van Assche "Forwarded sense data");
1796*44704f69SBart Van Assche if (add_d_len < 2) {
1797*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, parsing, dtsp);
1798*44704f69SBart Van Assche processed = false;
1799*44704f69SBart Van Assche break;
1800*44704f69SBart Van Assche }
1801*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "fsdt", !! (0x80 & descp[2]),
1802*44704f69SBart Van Assche false, "Forwarded Sense Data Truncated");
1803*44704f69SBart Van Assche sds = (0x7 & descp[2]);
1804*44704f69SBart Van Assche if (sds < 1)
1805*44704f69SBart Van Assche snprintf(b, blen, "%s [%d]", "Unknown", sds);
1806*44704f69SBart Van Assche else if (sds > 9)
1807*44704f69SBart Van Assche snprintf(b, blen, "%s [%d]", "Reserved", sds);
1808*44704f69SBart Van Assche else {
1809*44704f69SBart Van Assche n = 0;
1810*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, "EXTENDED COPY command copy %s",
1811*44704f69SBart Van Assche (sds == 1) ? "source" : "destination");
1812*44704f69SBart Van Assche if (sds > 1)
1813*44704f69SBart Van Assche n += sg_scnpr(b + n, blen - n, " %d", sds - 1);
1814*44704f69SBart Van Assche }
1815*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "sense_data_source",
1816*44704f69SBart Van Assche (0x7 & descp[2]), NULL, b);
1817*44704f69SBart Van Assche jo3p = sgj_named_subobject_r(jsp, jo2p, "forwarded_sense_data");
1818*44704f69SBart Van Assche sgj_js_sense(jsp, jo3p, descp + 4, desc_len - 4);
1819*44704f69SBart Van Assche break;
1820*44704f69SBart Van Assche case 0xd: /* Added in SBC-3 rev 36d */
1821*44704f69SBart Van Assche /* this descriptor combines descriptors 0, 1, 2 and 3 */
1822*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1823*44704f69SBart Van Assche "Direct-access block device");
1824*44704f69SBart Van Assche if (add_d_len < 28) {
1825*44704f69SBart Van Assche sgj_js_nv_s(jsp, jo2p, parsing, dtsp);
1826*44704f69SBart Van Assche processed = false;
1827*44704f69SBart Van Assche break;
1828*44704f69SBart Van Assche }
1829*44704f69SBart Van Assche sgj_js_nv_i(jsp, jo2p, "valid", (0x80 & descp[2]));
1830*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "ili", !! (0x20 & descp[2]),
1831*44704f69SBart Van Assche false, "Incorrect Length Indicator");
1832*44704f69SBart Van Assche processed = sgj_decode_sks(jsp, jo2p, descp + 4, desc_len - 4,
1833*44704f69SBart Van Assche sense_key);
1834*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "field_replaceable_unit_code",
1835*44704f69SBart Van Assche descp[7]);
1836*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "information",
1837*44704f69SBart Van Assche sg_get_unaligned_be64(descp + 8));
1838*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "command_specific_information",
1839*44704f69SBart Van Assche sg_get_unaligned_be64(descp + 16));
1840*44704f69SBart Van Assche break;
1841*44704f69SBart Van Assche case 0xe: /* Added in SPC-5 rev 6 (for Bind/Unbind) */
1842*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1843*44704f69SBart Van Assche "Device designation");
1844*44704f69SBart Van Assche n = descp[3];
1845*44704f69SBart Van Assche cp = (n < (int)SG_ARRAY_SIZE(dd_usage_reason_str_arr)) ?
1846*44704f69SBart Van Assche dd_usage_reason_str_arr[n] : "Unknown (reserved)";
1847*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_usage_reason",
1848*44704f69SBart Van Assche n, NULL, cp);
1849*44704f69SBart Van Assche jo3p = sgj_named_subobject_r(jsp, jo2p,
1850*44704f69SBart Van Assche "device_designation_descriptor");
1851*44704f69SBart Van Assche sgj_js_designation_descriptor(jsp, jo3p, descp + 4, desc_len - 4);
1852*44704f69SBart Van Assche break;
1853*44704f69SBart Van Assche case 0xf: /* Added in SPC-5 rev 10 (for Write buffer) */
1854*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1855*44704f69SBart Van Assche "Microcode activation");
1856*44704f69SBart Van Assche if (add_d_len < 6) {
1857*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, parsing, dtsp);
1858*44704f69SBart Van Assche processed = false;
1859*44704f69SBart Van Assche break;
1860*44704f69SBart Van Assche }
1861*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "microcode_activation_time",
1862*44704f69SBart Van Assche sg_get_unaligned_be16(descp + 6));
1863*44704f69SBart Van Assche break;
1864*44704f69SBart Van Assche case 0xde: /* NVME Status Field; vendor (sg3_utils) specific */
1865*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jo2p, "descriptor_type", dt, NULL,
1866*44704f69SBart Van Assche "NVME status (sg3_utils)");
1867*44704f69SBart Van Assche if (add_d_len < 6) {
1868*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, parsing, dtsp);
1869*44704f69SBart Van Assche processed = false;
1870*44704f69SBart Van Assche break;
1871*44704f69SBart Van Assche }
1872*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "dnr", !! (0x80 & descp[5]),
1873*44704f69SBart Van Assche false, "Do not retry");
1874*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jo2p, "m", !! (0x40 & descp[5]),
1875*44704f69SBart Van Assche false, "More");
1876*44704f69SBart Van Assche sct_sc = sg_get_unaligned_be16(descp + 6);
1877*44704f69SBart Van Assche sgj_js_nv_ihexstr_nex
1878*44704f69SBart Van Assche (jsp, jo2p, "sct_sc", sct_sc, true, NULL,
1879*44704f69SBart Van Assche sg_get_nvme_cmd_status_str(sct_sc, blen, b),
1880*44704f69SBart Van Assche "Status Code Type (upper 8 bits) and Status Code");
1881*44704f69SBart Van Assche break;
1882*44704f69SBart Van Assche default:
1883*44704f69SBart Van Assche if (dt >= 0x80)
1884*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "vendor_specific_descriptor_type",
1885*44704f69SBart Van Assche dt);
1886*44704f69SBart Van Assche else
1887*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jo2p, "unknown_descriptor_type", dt);
1888*44704f69SBart Van Assche sgj_js_nv_hex_bytes(jsp, jo2p, "descriptor_hexbytes",
1889*44704f69SBart Van Assche descp, desc_len);
1890*44704f69SBart Van Assche processed = false;
1891*44704f69SBart Van Assche break;
1892*44704f69SBart Van Assche }
1893*44704f69SBart Van Assche sgj_js_nv_o(jsp, jap, NULL /* name */, jo2p);
1894*44704f69SBart Van Assche }
1895*44704f69SBart Van Assche return processed;
1896*44704f69SBart Van Assche }
1897*44704f69SBart Van Assche
1898*44704f69SBart Van Assche #define ASCQ_ATA_PT_INFO_AVAILABLE 0x1d /* corresponding ASC is 0 */
1899*44704f69SBart Van Assche
1900*44704f69SBart Van Assche /* Fetch sense information */
1901*44704f69SBart Van Assche bool
sgj_js_sense(sgj_state * jsp,sgj_opaque_p jop,const uint8_t * sbp,int sb_len)1902*44704f69SBart Van Assche sgj_js_sense(sgj_state * jsp, sgj_opaque_p jop, const uint8_t * sbp,
1903*44704f69SBart Van Assche int sb_len)
1904*44704f69SBart Van Assche {
1905*44704f69SBart Van Assche bool descriptor_format = false;
1906*44704f69SBart Van Assche bool sdat_ovfl = false;
1907*44704f69SBart Van Assche bool ret = true;
1908*44704f69SBart Van Assche bool valid_info_fld;
1909*44704f69SBart Van Assche int len, n;
1910*44704f69SBart Van Assche uint32_t info;
1911*44704f69SBart Van Assche uint8_t resp_code;
1912*44704f69SBart Van Assche const char * ebp = NULL;
1913*44704f69SBart Van Assche char ebuff[64];
1914*44704f69SBart Van Assche char b[256];
1915*44704f69SBart Van Assche struct sg_scsi_sense_hdr ssh;
1916*44704f69SBart Van Assche static int blen = sizeof(b);
1917*44704f69SBart Van Assche static int elen = sizeof(ebuff);
1918*44704f69SBart Van Assche
1919*44704f69SBart Van Assche if ((NULL == sbp) || (sb_len < 1)) {
1920*44704f69SBart Van Assche snprintf(ebuff, elen, "sense buffer empty\n");
1921*44704f69SBart Van Assche ebp = ebuff;
1922*44704f69SBart Van Assche ret = false;
1923*44704f69SBart Van Assche goto fini;
1924*44704f69SBart Van Assche }
1925*44704f69SBart Van Assche resp_code = 0x7f & sbp[0];
1926*44704f69SBart Van Assche valid_info_fld = !!(sbp[0] & 0x80);
1927*44704f69SBart Van Assche len = sb_len;
1928*44704f69SBart Van Assche if (! sg_scsi_normalize_sense(sbp, sb_len, &ssh)) {
1929*44704f69SBart Van Assche ebp = "unable to normalize sense buffer";
1930*44704f69SBart Van Assche ret = false;
1931*44704f69SBart Van Assche goto fini;
1932*44704f69SBart Van Assche }
1933*44704f69SBart Van Assche /* We have been able to normalize the sense buffer */
1934*44704f69SBart Van Assche switch (resp_code) {
1935*44704f69SBart Van Assche case 0x70: /* fixed, current */
1936*44704f69SBart Van Assche ebp = "Fixed format, current";
1937*44704f69SBart Van Assche len = (sb_len > 7) ? (sbp[7] + 8) : sb_len;
1938*44704f69SBart Van Assche len = (len > sb_len) ? sb_len : len;
1939*44704f69SBart Van Assche sdat_ovfl = (len > 2) ? !!(sbp[2] & 0x10) : false;
1940*44704f69SBart Van Assche break;
1941*44704f69SBart Van Assche case 0x71: /* fixed, deferred */
1942*44704f69SBart Van Assche /* error related to a previous command */
1943*44704f69SBart Van Assche ebp = "Fixed format, <<<deferred>>>";
1944*44704f69SBart Van Assche len = (sb_len > 7) ? (sbp[7] + 8) : sb_len;
1945*44704f69SBart Van Assche len = (len > sb_len) ? sb_len : len;
1946*44704f69SBart Van Assche sdat_ovfl = (len > 2) ? !!(sbp[2] & 0x10) : false;
1947*44704f69SBart Van Assche break;
1948*44704f69SBart Van Assche case 0x72: /* descriptor, current */
1949*44704f69SBart Van Assche descriptor_format = true;
1950*44704f69SBart Van Assche ebp = "Descriptor format, current";
1951*44704f69SBart Van Assche sdat_ovfl = (sb_len > 4) ? !!(sbp[4] & 0x80) : false;
1952*44704f69SBart Van Assche break;
1953*44704f69SBart Van Assche case 0x73: /* descriptor, deferred */
1954*44704f69SBart Van Assche descriptor_format = true;
1955*44704f69SBart Van Assche ebp = "Descriptor format, <<<deferred>>>";
1956*44704f69SBart Van Assche sdat_ovfl = (sb_len > 4) ? !!(sbp[4] & 0x80) : false;
1957*44704f69SBart Van Assche break;
1958*44704f69SBart Van Assche default:
1959*44704f69SBart Van Assche sg_scnpr(ebuff, elen, "Unknown code: 0x%x", resp_code);
1960*44704f69SBart Van Assche ebp = ebuff;
1961*44704f69SBart Van Assche break;
1962*44704f69SBart Van Assche }
1963*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "response_code", resp_code, NULL, ebp);
1964*44704f69SBart Van Assche sgj_js_nv_b(jsp, jop, "descriptor_format", descriptor_format);
1965*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "sdat_ovfl", sdat_ovfl, false,
1966*44704f69SBart Van Assche "Sense data overflow");
1967*44704f69SBart Van Assche sgj_js_nv_ihexstr(jsp, jop, "sense_key", ssh.sense_key, NULL,
1968*44704f69SBart Van Assche sg_lib_sense_key_desc[ssh.sense_key]);
1969*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "additional_sense_code", ssh.asc);
1970*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "additional_sense_code_qualifier", ssh.ascq);
1971*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "additional_sense_str",
1972*44704f69SBart Van Assche sg_get_additional_sense_str(ssh.asc, ssh.ascq, false,
1973*44704f69SBart Van Assche blen, b));
1974*44704f69SBart Van Assche if (descriptor_format) {
1975*44704f69SBart Van Assche if (len > 8) {
1976*44704f69SBart Van Assche ret = sgj_js_sense_descriptors(jsp, jop, &ssh, sbp + 8, len - 8);
1977*44704f69SBart Van Assche if (ret == false) {
1978*44704f69SBart Van Assche ebp = "unable to decode sense descriptor";
1979*44704f69SBart Van Assche goto fini;
1980*44704f69SBart Van Assche }
1981*44704f69SBart Van Assche }
1982*44704f69SBart Van Assche } else if ((len > 12) && (0 == ssh.asc) &&
1983*44704f69SBart Van Assche (ASCQ_ATA_PT_INFO_AVAILABLE == ssh.ascq)) {
1984*44704f69SBart Van Assche /* SAT ATA PASS-THROUGH fixed format */
1985*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "error", sbp[3]);
1986*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "status", sbp[4]);
1987*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "device", sbp[5]);
1988*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, "extend", !! (0x80 & sbp[8]));
1989*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, "count_upper_nonzero", !! (0x40 & sbp[8]));
1990*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, "lba_upper_nonzero", !! (0x20 & sbp[8]));
1991*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, "log_index", (0xf & sbp[8]));
1992*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, "lba", sg_get_unaligned_le24(sbp + 9));
1993*44704f69SBart Van Assche } else if (len > 2) { /* fixed format */
1994*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, "valid", valid_info_fld);
1995*44704f69SBart Van Assche sgj_js_nv_i(jsp, jop, "filemark", !! (sbp[2] & 0x80));
1996*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "eom", !! (sbp[2] & 0x40),
1997*44704f69SBart Van Assche false, "End Of Medium");
1998*44704f69SBart Van Assche sgj_js_nv_ihex_nex(jsp, jop, "ili", !! (sbp[2] & 0x20),
1999*44704f69SBart Van Assche false, "Incorrect Length Indicator");
2000*44704f69SBart Van Assche info = sg_get_unaligned_be32(sbp + 3);
2001*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "information", info);
2002*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "additional_sense_length", sbp[7]);
2003*44704f69SBart Van Assche if (sb_len > 11) {
2004*44704f69SBart Van Assche info = sg_get_unaligned_be32(sbp + 8);
2005*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "command_specific_information", info);
2006*44704f69SBart Van Assche }
2007*44704f69SBart Van Assche if (sb_len > 14)
2008*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "field_replaceable_unit_code", sbp[14]);
2009*44704f69SBart Van Assche if (sb_len > 17)
2010*44704f69SBart Van Assche sgj_decode_sks(jsp, jop, sbp + 15, sb_len - 15, ssh.sense_key);
2011*44704f69SBart Van Assche n = sbp[7];
2012*44704f69SBart Van Assche n = (sb_len > n) ? n : sb_len;
2013*44704f69SBart Van Assche sgj_js_nv_ihex(jsp, jop, "number_of_bytes_beyond_18",
2014*44704f69SBart Van Assche (n > 18) ? n - 18 : 0);
2015*44704f69SBart Van Assche } else {
2016*44704f69SBart Van Assche snprintf(ebuff, sizeof(ebuff), "sb_len=%d too short", sb_len);
2017*44704f69SBart Van Assche ebp = ebuff;
2018*44704f69SBart Van Assche ret = false;
2019*44704f69SBart Van Assche }
2020*44704f69SBart Van Assche fini:
2021*44704f69SBart Van Assche if ((! ret) && ebp)
2022*44704f69SBart Van Assche sgj_js_nv_s(jsp, jop, "sense_decode_error", ebp);
2023*44704f69SBart Van Assche return ret;
2024*44704f69SBart Van Assche }
2025*44704f69SBart Van Assche
2026*44704f69SBart Van Assche #endif
2027