diff --git a/modules/libcom/src/yacc/error.c b/modules/libcom/src/yacc/error.c
index 6da8161a7..04bddf708 100644
--- a/modules/libcom/src/yacc/error.c
+++ b/modules/libcom/src/yacc/error.c
@@ -1,11 +1,3 @@
-/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-* National Laboratory.
-* Copyright (c) 2002 The Regents of the University of California, as
-* Operator of Los Alamos National Laboratory.
-* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
-\*************************************************************************/
/* routines for printing error messages */
#include "defs.h"
diff --git a/modules/libcom/src/yacc/lalr.c b/modules/libcom/src/yacc/lalr.c
index bbe149b8e..b3d44103c 100644
--- a/modules/libcom/src/yacc/lalr.c
+++ b/modules/libcom/src/yacc/lalr.c
@@ -1,11 +1,3 @@
-/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-* National Laboratory.
-* Copyright (c) 2002 The Regents of the University of California, as
-* Operator of Los Alamos National Laboratory.
-* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
-\*************************************************************************/
#include "defs.h"
typedef
diff --git a/modules/libcom/src/yacc/lr0.c b/modules/libcom/src/yacc/lr0.c
index 7cf7521ba..d93b0bc7a 100644
--- a/modules/libcom/src/yacc/lr0.c
+++ b/modules/libcom/src/yacc/lr0.c
@@ -1,12 +1,3 @@
-/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-* National Laboratory.
-* Copyright (c) 2002 The Regents of the University of California, as
-* Operator of Los Alamos National Laboratory.
-* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
-\*************************************************************************/
-
#include "defs.h"
extern short *itemset;
diff --git a/modules/libcom/src/yacc/mkpar.c b/modules/libcom/src/yacc/mkpar.c
index 03f5496e8..356be2363 100644
--- a/modules/libcom/src/yacc/mkpar.c
+++ b/modules/libcom/src/yacc/mkpar.c
@@ -1,12 +1,3 @@
-/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-* National Laboratory.
-* Copyright (c) 2002 The Regents of the University of California, as
-* Operator of Los Alamos National Laboratory.
-* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
-\*************************************************************************/
-
#include "defs.h"
action **parser;
diff --git a/modules/libcom/src/yacc/output.c b/modules/libcom/src/yacc/output.c
index 96b6d1e6f..49cfab3cc 100644
--- a/modules/libcom/src/yacc/output.c
+++ b/modules/libcom/src/yacc/output.c
@@ -1,11 +1,3 @@
-/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-* National Laboratory.
-* Copyright (c) 2002 The Regents of the University of California, as
-* Operator of Los Alamos National Laboratory.
-* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
-\*************************************************************************/
#include "defs.h"
static int nvectors;
diff --git a/modules/libcom/src/yacc/reader.c b/modules/libcom/src/yacc/reader.c
index 05c5b1a50..ff87bea7e 100644
--- a/modules/libcom/src/yacc/reader.c
+++ b/modules/libcom/src/yacc/reader.c
@@ -1,11 +1,3 @@
-/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-* National Laboratory.
-* Copyright (c) 2002 The Regents of the University of California, as
-* Operator of Los Alamos National Laboratory.
-* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
-\*************************************************************************/
#include "defs.h"
/* The line size must be a positive integer. One hundred was chosen */
diff --git a/modules/libcom/src/yacc/skeleton.c b/modules/libcom/src/yacc/skeleton.c
index 18fe40371..4dbc16815 100644
--- a/modules/libcom/src/yacc/skeleton.c
+++ b/modules/libcom/src/yacc/skeleton.c
@@ -1,11 +1,3 @@
-/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-* National Laboratory.
-* Copyright (c) 2002 The Regents of the University of California, as
-* Operator of Los Alamos National Laboratory.
-* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
-\*************************************************************************/
#include "defs.h"
/* If the skeleton is changed, the banner should be changed so that */
diff --git a/modules/libcom/src/yacc/symtab.c b/modules/libcom/src/yacc/symtab.c
index cdf800b83..b9719728a 100644
--- a/modules/libcom/src/yacc/symtab.c
+++ b/modules/libcom/src/yacc/symtab.c
@@ -1,11 +1,3 @@
-/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-* National Laboratory.
-* Copyright (c) 2002 The Regents of the University of California, as
-* Operator of Los Alamos National Laboratory.
-* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
-\*************************************************************************/
#include "defs.h"
diff --git a/modules/libcom/src/yacc/verbose.c b/modules/libcom/src/yacc/verbose.c
index bb539c9e3..64c831a74 100644
--- a/modules/libcom/src/yacc/verbose.c
+++ b/modules/libcom/src/yacc/verbose.c
@@ -1,12 +1,3 @@
-/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-* National Laboratory.
-* Copyright (c) 2002 The Regents of the University of California, as
-* Operator of Los Alamos National Laboratory.
-* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
-\*************************************************************************/
-
#include "defs.h"
static short *null_rules;
diff --git a/modules/libcom/src/yacc/warshall.c b/modules/libcom/src/yacc/warshall.c
index 93a9177e5..186fdbce9 100644
--- a/modules/libcom/src/yacc/warshall.c
+++ b/modules/libcom/src/yacc/warshall.c
@@ -1,11 +1,3 @@
-/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-* National Laboratory.
-* Copyright (c) 2002 The Regents of the University of California, as
-* Operator of Los Alamos National Laboratory.
-* EPICS BASE is distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
-\*************************************************************************/
#include "defs.h"
static void
diff --git a/modules/libcom/src/yacc/yacc.html b/modules/libcom/src/yacc/yacc.html
index 1258b439f..fa29c79b2 100644
--- a/modules/libcom/src/yacc/yacc.html
+++ b/modules/libcom/src/yacc/yacc.html
@@ -1,12 +1,3 @@
-/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
-* National Laboratory.
-* Copyright (c) 2002 The Regents of the University of California, as
-* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
-* in file LICENSE that is included with this distribution.
-\*************************************************************************/
diff --git a/modules/libcom/src/yajl/yajl.c b/modules/libcom/src/yajl/yajl.c
index 3fbb87aea..fdad3f68e 100644
--- a/modules/libcom/src/yajl/yajl.c
+++ b/modules/libcom/src/yajl/yajl.c
@@ -74,7 +74,7 @@ yajl_alloc(const yajl_callbacks * callbacks,
hand->lexer = NULL;
hand->bytesConsumed = 0;
hand->decodeBuf = yajl_buf_alloc(&(hand->alloc));
- hand->flags = 0;
+ hand->flags = yajl_allow_json5 | yajl_allow_comments;
yajl_bs_init(hand->stateStack, &(hand->alloc));
yajl_bs_push(hand->stateStack, yajl_state_start);
@@ -82,13 +82,16 @@ yajl_alloc(const yajl_callbacks * callbacks,
}
int
-yajl_config(yajl_handle h, yajl_option opt, ...)
+yajl_config(yajl_handle h, int option, ...)
{
+ yajl_option opt = option; /* UB to use an enum in va_start */
int rv = 1;
va_list ap;
- va_start(ap, opt);
+ va_start(ap, option);
switch(opt) {
+ case yajl_allow_json5:
+ opt |= yajl_allow_comments; /* JSON5 allows comments */
case yajl_allow_comments:
case yajl_dont_validate_strings:
case yajl_allow_trailing_garbage:
@@ -127,7 +130,8 @@ yajl_parse(yajl_handle hand, const unsigned char * jsonText,
if (hand->lexer == NULL) {
hand->lexer = yajl_lex_alloc(&(hand->alloc),
hand->flags & yajl_allow_comments,
- !(hand->flags & yajl_dont_validate_strings));
+ !(hand->flags & yajl_dont_validate_strings),
+ hand->flags & yajl_allow_json5);
}
if (hand->lexer == NULL) {
return yajl_status_error;
@@ -150,7 +154,8 @@ yajl_complete_parse(yajl_handle hand)
if (hand->lexer == NULL) {
hand->lexer = yajl_lex_alloc(&(hand->alloc),
hand->flags & yajl_allow_comments,
- !(hand->flags & yajl_dont_validate_strings));
+ !(hand->flags & yajl_dont_validate_strings),
+ hand->flags & yajl_allow_json5);
}
return yajl_do_finish(hand);
diff --git a/modules/libcom/src/yajl/yajl_common.h b/modules/libcom/src/yajl/yajl_common.h
index 57e2d7eb5..fca8454a8 100644
--- a/modules/libcom/src/yajl/yajl_common.h
+++ b/modules/libcom/src/yajl/yajl_common.h
@@ -37,18 +37,34 @@ extern "C" {
* YAJL 1.0.12 version that was
* bundled with EPICS Base 3.15.0.1
*
- * YAJL 2.1.0
+ * ***YAJL 2.1.0***
* \li Changes argument type for yajl_integer() from \c int to \c long \c long
- * \li Changes argument type for yajl_string() and yajl_map_key() from \c unsigned to \c size_t
+ * \li Changes argument type for yajl_string() and yajl_map_key() from
+ * \c unsigned to \c size_t
* \li Replacement of struct yajl_parser_config with yajl_config()
* \li Replacement of yajl_parse_complete() with yajl_complete_parse()
+ *
+ * ***YAJL 2.2.0***
+ * This version adds support for JSON5 parsing and generation.
+ * The upstream YAJL repository is no longer being maintained and the
+ * original author no longer responds to messsages, so while this code
+ * has been offered for merging into the upstream it is unlikely that
+ * will ever happen. The version number here is thus an EPICS-specific
+ * construct.
*/
-#define EPICS_YAJL_VERSION VERSION_INT(2,1,0,0)
+#define EPICS_YAJL_VERSION VERSION_INT(2,2,0,0)
-/** Maximum generation depth for YAJL's JSON generation routines */
+/** A macro to make it easy to conditionally compile code that supports
+ * older releases.
+ */
+#define HAS_JSON5
+
+/** A limit used by the generator API, YAJL_MAX_DEPTH is the maximum
+ * depth to which arrays and maps may be nested.
+ */
#define YAJL_MAX_DEPTH 128
-/** Symbol decoration for Microsoft builds */
+/** Marks a yajl routine for export from the DLL/shared library. */
#define YAJL_API LIBCOM_API
/** Pointer to a malloc() function, supporting client overriding memory
@@ -62,18 +78,18 @@ typedef void (*yajl_free_func)(void *ctx, void * ptr);
/** Pointer to a realloc() function which can resize an allocation. */
typedef void * (*yajl_realloc_func)(void *ctx, void * ptr, size_t sz);
-/** A structure which can be passed to yajl_*_alloc routines to allow the
+/** A structure which can be passed to yajl_*_alloc() routines to allow the
* client to specify memory allocation functions to be used. */
typedef struct
{
- /** Pointer to a function that can allocate uninitialized memory */
+ /** Pointer to a function that can allocate uninitialized memory. */
yajl_malloc_func malloc;
- /** Pointer to a function that can resize memory allocations */
+ /** Pointer to a function that can resize memory allocations. */
yajl_realloc_func realloc;
/** Pointer to a function that can free memory allocated using
- * reallocFunction or mallocFunction */
+ * the above realloc or malloc functions. */
yajl_free_func free;
- /** A context pointer that will be passed to above allocation routines */
+ /** A context pointer that will be passed to above allocation routines. */
void * ctx;
} yajl_alloc_funcs;
diff --git a/modules/libcom/src/yajl/yajl_encode.c b/modules/libcom/src/yajl/yajl_encode.c
index dfd4af6ac..732f451f9 100644
--- a/modules/libcom/src/yajl/yajl_encode.c
+++ b/modules/libcom/src/yajl/yajl_encode.c
@@ -33,13 +33,22 @@ yajl_string_encode(const yajl_print_t print,
void * ctx,
const unsigned char * str,
size_t len,
- int escape_solidus)
+ int escape_solidus,
+ int output_json5)
{
size_t beg = 0;
size_t end = 0;
char hexBuf[7];
- hexBuf[0] = '\\'; hexBuf[1] = 'u'; hexBuf[2] = '0'; hexBuf[3] = '0';
- hexBuf[6] = 0;
+ char *hexAt;
+ if (output_json5) {
+ hexBuf[0] = '\\'; hexBuf[1] = 'x';
+ hexBuf[4] = 0;
+ hexAt = &hexBuf[2];
+ } else {
+ hexBuf[0] = '\\'; hexBuf[1] = 'u'; hexBuf[2] = '0'; hexBuf[3] = '0';
+ hexBuf[6] = 0;
+ hexAt = &hexBuf[4];
+ }
while (end < len) {
const char * escaped = NULL;
@@ -57,9 +66,20 @@ yajl_string_encode(const yajl_print_t print,
case '\f': escaped = "\\f"; break;
case '\b': escaped = "\\b"; break;
case '\t': escaped = "\\t"; break;
+ case '\0':
+ if (output_json5) {
+ escaped = "\\0"; break;
+ }
+ goto ashex;
+ case '\v':
+ if (output_json5) {
+ escaped = "\\v"; break;
+ }
+ goto ashex;
default:
if ((unsigned char) str[end] < 32) {
- CharToHex(str[end], hexBuf + 4);
+ ashex:
+ CharToHex(str[end], hexAt);
escaped = hexBuf;
}
break;
@@ -75,10 +95,10 @@ yajl_string_encode(const yajl_print_t print,
print(ctx, (const char *) (str + beg), end - beg);
}
-static void hexToDigit(unsigned int * val, const unsigned char * hex)
+static void hexToDigit(unsigned int * val, unsigned int len, const unsigned char * hex)
{
unsigned int i;
- for (i=0;i<4;i++) {
+ for (i=0;i= 'A') c = (c & ~0x20) - 7;
c -= '0';
@@ -128,21 +148,19 @@ void yajl_string_decode(yajl_buf buf, const unsigned char * str,
case 'r': unescaped = "\r"; break;
case 'n': unescaped = "\n"; break;
case '\\': unescaped = "\\"; break;
- case '/': unescaped = "/"; break;
- case '"': unescaped = "\""; break;
case 'f': unescaped = "\f"; break;
case 'b': unescaped = "\b"; break;
case 't': unescaped = "\t"; break;
case 'u': {
unsigned int codepoint = 0;
- hexToDigit(&codepoint, str + ++end);
+ hexToDigit(&codepoint, 4, str + ++end);
end+=3;
/* check if this is a surrogate */
if ((codepoint & 0xFC00) == 0xD800) {
end++;
if (str[end] == '\\' && str[end + 1] == 'u') {
unsigned int surrogate = 0;
- hexToDigit(&surrogate, str + end + 2);
+ hexToDigit(&surrogate, 4, str + end + 2);
codepoint =
(((codepoint & 0x3F) << 10) |
((((codepoint >> 6) & 0xF) + 1) << 16) |
@@ -165,8 +183,33 @@ void yajl_string_decode(yajl_buf buf, const unsigned char * str,
break;
}
+ /* The following escapes are only valid when parsing JSON5.
+ * The lexer catches them when allowJson5 is not set.
+ */
+ case '\n': beg = ++end; continue;
+ case '\r':
+ if (str[++end] == '\n') ++end;
+ beg = end;
+ continue;
+ case '0':
+ utf8Buf[0] = '\0';
+ yajl_buf_append(buf, utf8Buf, 1);
+ beg = ++end;
+ continue;
+ case 'v': unescaped = "\v"; break;
+ case 'x': {
+ unsigned int codepoint = 0;
+ hexToDigit(&codepoint, 2, str + ++end);
+ end++;
+ utf8Buf[0] = (char) codepoint;
+ yajl_buf_append(buf, utf8Buf, 1);
+ beg = ++end;
+ continue;
+ }
default:
- assert("this should never happen" == NULL);
+ utf8Buf[0] = str[end];
+ utf8Buf[1] = 0;
+ unescaped = utf8Buf;
}
yajl_buf_append(buf, unescaped, (unsigned int)strlen(unescaped));
beg = ++end;
@@ -218,3 +261,27 @@ int yajl_string_validate_utf8(const unsigned char * s, size_t len)
return 1;
}
+
+int yajl_string_validate_identifier(const unsigned char * str, size_t len)
+{
+ const unsigned char * s = str;
+ int c;
+
+ if (!len || !str) return 0;
+
+ c = *s++; /* First character [$_A-Za-z] */
+ if ((c != '$' && c < 'A') ||
+ (c > 'Z' && c != '_' && c < 'a') ||
+ (c > 'z'))
+ return 0;
+
+ while (--len) {
+ c = *s++; /* Remaining characters [$_A-Za-z0-9] */
+ if ((c != '$' && c < '0') ||
+ (c > '9' && c < 'A') ||
+ (c > 'Z' && c != '_' && c < 'a') ||
+ (c > 'z'))
+ return 0;
+ }
+ return 1;
+}
diff --git a/modules/libcom/src/yajl/yajl_encode.h b/modules/libcom/src/yajl/yajl_encode.h
index 2c0559705..fd58dec9c 100644
--- a/modules/libcom/src/yajl/yajl_encode.h
+++ b/modules/libcom/src/yajl/yajl_encode.h
@@ -28,13 +28,16 @@ void yajl_string_encode(const yajl_print_t printer,
void * ctx,
const unsigned char * str,
size_t length,
- int escape_solidus);
+ int escape_solidus,
+ int output_json5);
void yajl_string_decode(yajl_buf buf, const unsigned char * str,
size_t length);
int yajl_string_validate_utf8(const unsigned char * s, size_t len);
+int yajl_string_validate_identifier(const unsigned char * str, size_t len);
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/libcom/src/yajl/yajl_gen.c b/modules/libcom/src/yajl/yajl_gen.c
index a40b9760a..6d93784f5 100644
--- a/modules/libcom/src/yajl/yajl_gen.c
+++ b/modules/libcom/src/yajl/yajl_gen.c
@@ -48,15 +48,17 @@ struct yajl_gen_t
};
int
-yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...)
+yajl_gen_config(yajl_gen g, int option, ...)
{
+ yajl_gen_option opt = option; /* UB to use an enum in va_start */
int rv = 1;
va_list ap;
- va_start(ap, opt);
+ va_start(ap, option);
switch(opt) {
case yajl_gen_beautify:
case yajl_gen_validate_utf8:
+ case yajl_gen_json5:
if (va_arg(ap, int)) g->flags |= opt;
else g->flags &= ~opt;
break;
@@ -124,6 +126,14 @@ yajl_gen_alloc(const yajl_alloc_funcs * afs)
return g;
}
+void
+yajl_gen_reset(yajl_gen g, const char * sep)
+{
+ g->depth = 0;
+ memset((void *) &(g->state), 0, sizeof(g->state));
+ if (sep != NULL) g->print(g->ctx, sep, strlen(sep));
+}
+
void
yajl_gen_free(yajl_gen g)
{
@@ -132,17 +142,17 @@ yajl_gen_free(yajl_gen g)
}
#define INSERT_SEP \
- if (g->state[g->depth] == yajl_gen_map_key || \
- g->state[g->depth] == yajl_gen_in_array) { \
- g->print(g->ctx, ",", 1); \
- if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); \
- } else if (g->state[g->depth] == yajl_gen_map_val) { \
- g->print(g->ctx, ":", 1); \
- if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, " ", 1); \
- }
+ if (g->state[g->depth] == yajl_gen_map_key || \
+ g->state[g->depth] == yajl_gen_in_array) { \
+ g->print(g->ctx, ",", 1); \
+ if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); \
+ } else if (g->state[g->depth] == yajl_gen_map_val) { \
+ g->print(g->ctx, ":", 1); \
+ if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, " ", 1); \
+ }
-#define INSERT_WHITESPACE \
- if ((g->flags & yajl_gen_beautify)) { \
+#define INSERT_WHITESPACE \
+ if ((g->flags & yajl_gen_beautify)) { \
if (g->state[g->depth] != yajl_gen_map_val) { \
unsigned int _i; \
for (_i=0;_idepth;_i++) \
@@ -161,8 +171,8 @@ yajl_gen_free(yajl_gen g)
/* check that we're not complete, or in error state. in a valid state
* to be generating */
#define ENSURE_VALID_STATE \
- if (g->state[g->depth] == yajl_gen_error) { \
- return yajl_gen_in_error_state;\
+ if (g->state[g->depth] == yajl_gen_error) { \
+ return yajl_gen_in_error_state; \
} else if (g->state[g->depth] == yajl_gen_complete) { \
return yajl_gen_generation_complete; \
}
@@ -192,8 +202,9 @@ yajl_gen_free(yajl_gen g)
break; \
} \
-#define FINAL_NEWLINE \
- if ((g->flags & yajl_gen_beautify) && g->state[g->depth] == yajl_gen_complete) \
+#define FINAL_NEWLINE \
+ if ((g->flags & yajl_gen_beautify) && \
+ g->state[g->depth] == yajl_gen_complete) \
g->print(g->ctx, "\n", 1);
yajl_gen_status
@@ -212,10 +223,24 @@ yajl_gen_status
yajl_gen_double(yajl_gen g, double number)
{
char i[32];
+ int special = 1;
ENSURE_VALID_STATE; ENSURE_NOT_KEY;
- if (isnan(number) || isinf(number)) return yajl_gen_invalid_number;
+ if (isnan(number)) {
+ strcpy(i, "NaN");
+ }
+ else if (isinf(number)) {
+ sprintf(i, "%cInfinity", number < 0 ? '-' : '+');
+ }
+ else {
+ special = 0;
+ sprintf(i, "%.17g", number);
+ if (strspn(i, "0123456789-") == strlen(i)) {
+ strcat(i, ".0");
+ }
+ }
+ if (special && !(g->flags & yajl_gen_json5))
+ return yajl_gen_invalid_number;
INSERT_SEP; INSERT_WHITESPACE;
- sprintf(i, "%.20g", number);
g->print(g->ctx, i, (unsigned int)strlen(i));
APPENDED_ATOM;
FINAL_NEWLINE;
@@ -245,9 +270,19 @@ yajl_gen_string(yajl_gen g, const unsigned char * str,
}
}
ENSURE_VALID_STATE; INSERT_SEP; INSERT_WHITESPACE;
- g->print(g->ctx, "\"", 1);
- yajl_string_encode(g->print, g->ctx, str, len, g->flags & yajl_gen_escape_solidus);
- g->print(g->ctx, "\"", 1);
+ if (g->flags & yajl_gen_json5 &&
+ (g->state[g->depth] == yajl_gen_map_key ||
+ g->state[g->depth] == yajl_gen_map_start) &&
+ yajl_string_validate_identifier(str, len)) {
+ /* No need to quote this key */
+ g->print(g->ctx, (const char *) str, len);
+ }
+ else {
+ g->print(g->ctx, "\"", 1);
+ yajl_string_encode(g->print, g->ctx, str, len, g->flags & yajl_gen_escape_solidus,
+ g->flags & yajl_gen_json5);
+ g->print(g->ctx, "\"", 1);
+ }
APPENDED_ATOM;
FINAL_NEWLINE;
return yajl_gen_status_ok;
diff --git a/modules/libcom/src/yajl/yajl_gen.h b/modules/libcom/src/yajl/yajl_gen.h
index e4a2c87a3..aba643a5a 100644
--- a/modules/libcom/src/yajl/yajl_gen.h
+++ b/modules/libcom/src/yajl/yajl_gen.h
@@ -28,34 +28,34 @@
#ifdef __cplusplus
extern "C" {
#endif
- /** Generator status codes */
+ /** Generator status codes. */
typedef enum {
- /** No error */
+ /** No error. */
yajl_gen_status_ok = 0,
/** At a point where a map key is generated, a function other than
- * yajl_gen_string() was called */
+ * yajl_gen_string() was called. */
yajl_gen_keys_must_be_strings,
- /** YAJL's maximum generation depth was exceeded. see
+ /** YAJL's maximum generation depth was exceeded. See
* \ref YAJL_MAX_DEPTH */
yajl_max_depth_exceeded,
- /** A generator function (yajl_gen_XXX) was called while in an error
- * state */
+ /** A yajl_gen_XXX() generator function was called while in an error
+ * state. */
yajl_gen_in_error_state,
- /** A complete JSON document has been generated */
+ /** A complete JSON document has been generated. */
yajl_gen_generation_complete,
/** yajl_gen_double() was passed an invalid floating point value
- * (infinity or NaN). */
+ * (infinity or NaN) without \ref yajl_gen_json5 set. */
yajl_gen_invalid_number,
/** A print callback was passed in, so there is no internal
- * buffer to get from */
+ * buffer to get from. */
yajl_gen_no_buf,
- /** Returned from yajl_gen_string() when the yajl_gen_validate_utf8()
- * option is enabled and an invalid was passed by client code.
+ /** Returned from yajl_gen_string() when the \ref yajl_gen_validate_utf8
+ * option is enabled and an invalid UTF8 code was passed by client.
*/
yajl_gen_invalid_string
} yajl_gen_status;
- /** An opaque handle to a generator */
+ /** An opaque handle to a generator. */
typedef struct yajl_gen_t * yajl_gen;
/** A callback used for "printing" the results. */
@@ -64,67 +64,111 @@ extern "C" {
size_t len);
/** Configuration parameters for the parser, these may be passed to
- * yajl_gen_config() along with option specific argument(s). In general,
+ * yajl_gen_config() along with option-specific argument(s). In general,
* all configuration parameters default to *off*. */
typedef enum {
- /** Generate indented (beautiful) output */
+ /** Generate indented (beautiful) output.
+ *
+ * yajl_gen_config() argument type: int (boolean)
+ *
+ * Example: \code{.cpp}
+ * yajl_gen_config(g, yajl_gen_beautify, 1); // Human format please
+ * \endcode
+ */
yajl_gen_beautify = 0x01,
/**
- * Set an indent string which is used when yajl_gen_beautify()
- * is enabled. Maybe something like \\t or some number of
- * spaces. The default is four spaces ' '.
+ * Set the indent string which is used when \ref yajl_gen_beautify
+ * is enabled, which may only contain whitespace characters such as
+ * \c \\t or some number of spaces. The default is four spaces ' '.
+ *
+ * yajl_gen_config() argument type: const char *
+ *
+ * Example: \code{.cpp}
+ * yajl_gen_config(g, yajl_gen_indent_string, " "); // 2 spaces
+ * \endcode
*/
yajl_gen_indent_string = 0x02,
/**
* Set a function and context argument that should be used to
- * output generated json. the function should conform to the
- * yajl_print_t() prototype while the context argument is a
+ * output the generated json. The function should conform to the
+ * \ref yajl_print_t prototype while the context argument may be any
* void * of your choosing.
*
+ * yajl_gen_config() arguments: \ref yajl_print_t, void *
+ *
* Example: \code{.cpp}
- * yajl_gen_config(g, yajl_gen_print_callback, myFunc, myVoidPtr);
- * \endcode
+ * yajl_gen_config(g, yajl_gen_print_callback, myFunc, myVoidPtr);
+ * \endcode
*/
yajl_gen_print_callback = 0x04,
/**
* Normally the generator does not validate that strings you
- * pass to it via yajl_gen_string() are valid UTF8. Enabling
+ * pass to it via yajl_gen_string() are valid UTF8. Enabling
* this option will cause it to do so.
+ *
+ * yajl_gen_config() argument type: int (boolean)
+ *
+ * Example: \code{.cpp}
+ * yajl_gen_config(g, yajl_gen_validate_utf8, 1); // Check UTF8
+ * \endcode
*/
yajl_gen_validate_utf8 = 0x08,
/**
* The forward solidus (slash or '/' in human) is not required to be
- * escaped in json text. By default, YAJL will not escape it in the
- * iterest of saving bytes. Setting this flag will cause YAJL to
+ * escaped in JSON text. By default, YAJL will not escape it in the
+ * interest of saving bytes. Setting this flag will cause YAJL to
* always escape '/' in generated JSON strings.
+ *
+ * yajl_gen_config() argument type: int (boolean)
*/
- yajl_gen_escape_solidus = 0x10
+ yajl_gen_escape_solidus = 0x10,
+ /**
+ * JSON5 is an updated version of JSON with additional capabilities.
+ * Special numbers such as NaN and Infinity cannot be represented in
+ * the original JSON, but are permitted in JSON5. Setting this flag
+ * allows YAJL to output the JSON5 representation of these special
+ * numbers instead of returning with an error, and to emit map keys
+ * that are valid javascript identifiers without quotes.
+ *
+ * yajl_gen_config() argument type: int (boolean)
+ *
+ * Example: \code{.cpp}
+ * yajl_gen_config(g, yajl_gen_json5, 1); // Output JSON5
+ * \endcode
+ */
+ yajl_gen_json5 = 0x20,
} yajl_gen_option;
- /** Allow the modification of generator options subsequent to handle
- * allocation (via yajl_alloc())
- * \returns zero in case of errors, non-zero otherwise
+ /** Set generator options associated with a generator handle. See the
+ * \ref yajl_gen_option documentation for details of the available
+ * options and their arguments.
+ * \returns Zero in case of error, non-zero otherwise.
*/
- YAJL_API int yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...);
+ YAJL_API int yajl_gen_config(yajl_gen hand, int option, ...);
- /** Allocate a generator handle
- * \param allocFuncs An optional pointer to a structure which allows
- * the client to overide the memory allocation
- * used by yajl. May be NULL, in which case
- * malloc(), free() and realloc() will be used.
+ /** Allocate a generator handle.
+ * \param allocFuncs An optional pointer to a structure which allows the
+ * client to provide memory allocation functions for
+ * use by yajl. May be \c NULL to use the C runtime
+ * library's malloc(), free() and realloc().
*
- * \returns an allocated handle on success, NULL on failure (bad params)
+ * \returns An allocated handle on success, \c NULL on failure (bad params)
*/
YAJL_API yajl_gen yajl_gen_alloc(const yajl_alloc_funcs * allocFuncs);
- /** Free a generator handle */
+ /** Free a generator handle. */
YAJL_API void yajl_gen_free(yajl_gen handle);
/** Generate an integer number. */
YAJL_API yajl_gen_status yajl_gen_integer(yajl_gen hand, long long int number);
- /** Generate a floating point number. \p number may not be infinity or
- * NaN, as these have no representation in JSON. In these cases the
- * generator will return \ref yajl_gen_invalid_number */
+ /** Generate a floating point number.
+ * \param hand The generator handle.
+ * \param number The value to output. The values \c Infinity or \c NaN are
+ * only accepted if the \ref yajl_gen_json5 option is set,
+ * as these values have no legal representation in JSON;
+ * the generator will return \ref yajl_gen_invalid_number
+ * otherwise.
+ */
YAJL_API yajl_gen_status yajl_gen_double(yajl_gen hand, double number);
/** Generate a number from the string given in \p num. */
YAJL_API yajl_gen_status yajl_gen_number(yajl_gen hand,
@@ -149,18 +193,31 @@ extern "C" {
/** Finish generating a JSON array. */
YAJL_API yajl_gen_status yajl_gen_array_close(yajl_gen hand);
- /** Access the null terminated generator buffer. If incrementally
+ /** Access the zero-terminated generator buffer. If incrementally
* outputing JSON, one should call yajl_gen_clear() to clear the
- * buffer. This allows stream generation. */
+ * buffer. This allows stream generation. */
YAJL_API yajl_gen_status yajl_gen_get_buf(yajl_gen hand,
const unsigned char ** buf,
size_t * len);
/** Clear yajl's output buffer, but maintain all internal generation
- * state. This function will not "reset" the generator state, and is
- * intended to enable incremental JSON outputing. */
+ * state. This function will not reset the generator state, and is
+ * intended to enable incremental JSON output. */
YAJL_API void yajl_gen_clear(yajl_gen hand);
+ /** Reset the generator state. Allows a client to generate multiple
+ * JSON entities in a stream.
+ * \param hand The generator handle.
+ * \param sep This string will be inserted to separate the previously
+ * generated output from the following; passing \c NULL means
+ * *no separation* of entites (beware that generating
+ * multiple JSON numbers without a separator creates
+ * ambiguous output).
+ *
+ * Note: This call does not clear yajl's output buffer, which must be
+ * accomplished explicitly by calling yajl_gen_clear(). */
+ YAJL_API void yajl_gen_reset(yajl_gen hand, const char * sep);
+
#ifdef __cplusplus
}
#endif
diff --git a/modules/libcom/src/yajl/yajl_lex.c b/modules/libcom/src/yajl/yajl_lex.c
index e0cc3b539..8dbff43da 100644
--- a/modules/libcom/src/yajl/yajl_lex.c
+++ b/modules/libcom/src/yajl/yajl_lex.c
@@ -87,6 +87,9 @@ struct yajl_lexer_t {
/* shall we allow comments? */
unsigned int allowComments;
+ /* are we parsing JSON5? */
+ unsigned int allowJson5;
+
/* shall we validate utf8 inside strings? */
unsigned int validateUTF8;
@@ -102,7 +105,8 @@ struct yajl_lexer_t {
yajl_lexer
yajl_lex_alloc(yajl_alloc_funcs * alloc,
- unsigned int allowComments, unsigned int validateUTF8)
+ unsigned int allowComments, unsigned int validateUTF8,
+ unsigned int allowJson5)
{
yajl_lexer lxr = (yajl_lexer) YA_MALLOC(alloc, sizeof(struct yajl_lexer_t));
if (lxr == NULL) {
@@ -113,6 +117,7 @@ yajl_lex_alloc(yajl_alloc_funcs * alloc,
lxr->buf = yajl_buf_alloc(alloc);
lxr->allowComments = allowComments;
lxr->validateUTF8 = validateUTF8;
+ lxr->allowJson5 = !!allowJson5;
lxr->alloc = alloc;
return lxr;
}
@@ -125,19 +130,21 @@ yajl_lex_free(yajl_lexer lxr)
return;
}
-/* a lookup table which lets us quickly determine three things:
+/* a lookup table which lets us quickly determine various things:
* VEC - valid escaped control char
- * note. the solidus '/' may be escaped or not.
+ * Note: the solidus '/' may be escaped or not.
* IJC - invalid json char
* VHC - valid hex char
* NFP - needs further processing (from a string scanning perspective)
* NUC - needs utf8 checking when enabled (from a string scanning perspective)
+ * VIC - valid identifier char (after the first char)
*/
#define VEC 0x01
#define IJC 0x02
#define VHC 0x04
#define NFP 0x08
#define NUC 0x10
+#define VIC 0x20
static const char charLookupTable[256] =
{
@@ -146,20 +153,20 @@ static const char charLookupTable[256] =
/*10*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC ,
/*18*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC ,
-/*20*/ 0 , 0 , NFP|VEC|IJC, 0 , 0 , 0 , 0 , 0 ,
+/*20*/ 0 , 0 , NFP|VEC, 0 , VIC , 0 , 0 , NFP|VEC,
/*28*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , VEC ,
-/*30*/ VHC , VHC , VHC , VHC , VHC , VHC , VHC , VHC ,
-/*38*/ VHC , VHC , 0 , 0 , 0 , 0 , 0 , 0 ,
+/*30*/ VHC|VIC, VHC|VIC, VHC|VIC, VHC|VIC, VHC|VIC, VHC|VIC, VHC|VIC, VHC|VIC,
+/*38*/ VHC|VIC, VHC|VIC, 0 , 0 , 0 , 0 , 0 , 0 ,
-/*40*/ 0 , VHC , VHC , VHC , VHC , VHC , VHC , 0 ,
-/*48*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
-/*50*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
-/*58*/ 0 , 0 , 0 , 0 , NFP|VEC|IJC, 0 , 0 , 0 ,
+/*40*/ 0 , VHC|VIC, VHC|VIC, VHC|VIC, VHC|VIC, VHC|VIC, VHC|VIC, VIC ,
+/*48*/ VIC , VIC , VIC , VIC , VIC , VIC , VIC , VIC ,
+/*50*/ VIC , VIC , VIC , VIC , VIC , VIC , VIC , VIC ,
+/*58*/ VIC , VIC , VIC , 0 , NFP|VEC|IJC, 0 , 0 , VIC ,
-/*60*/ 0 , VHC , VEC|VHC, VHC , VHC , VHC , VEC|VHC, 0 ,
-/*68*/ 0 , 0 , 0 , 0 , 0 , 0 , VEC , 0 ,
-/*70*/ 0 , 0 , VEC , 0 , VEC , 0 , 0 , 0 ,
-/*78*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+/*60*/ 0 , VHC|VIC, VEC|VHC|VIC, VHC|VIC, VHC|VIC, VHC|VIC, VEC|VHC|VIC, VIC,
+/*68*/ VIC , VIC , VIC , VIC , VIC , VIC , VEC|VIC, VIC ,
+/*70*/ VIC , VIC , VEC|VIC, VIC , VEC|VIC, VIC , VIC , VIC ,
+/*78*/ VIC , VIC , VIC , 0 , 0 , 0 , 0 , 0 ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC ,
@@ -193,7 +200,7 @@ static const char charLookupTable[256] =
*
* NOTE: on error the offset will point to the first char of the
* invalid utf8 */
-#define UTF8_CHECK_EOF if (*offset >= jsonTextLen) { return yajl_tok_eof; }
+#define UTF8_CHECK_EOF if (*offset >= jsonTextLen) return yajl_tok_eof;
static yajl_tok
yajl_lex_utf8_char(yajl_lexer lexer, const unsigned char * jsonText,
@@ -270,7 +277,7 @@ yajl_string_scan(const unsigned char * buf, size_t len, int utf8check)
static yajl_tok
yajl_lex_string(yajl_lexer lexer, const unsigned char * jsonText,
- size_t jsonTextLen, size_t * offset)
+ size_t jsonTextLen, size_t * offset, const char quote)
{
yajl_tok tok = yajl_tok_error;
int hasEscapes = 0;
@@ -305,7 +312,7 @@ yajl_lex_string(yajl_lexer lexer, const unsigned char * jsonText,
curChar = readChar(lexer, jsonText, offset);
/* quote terminates */
- if (curChar == '"') {
+ if (curChar == quote) {
tok = yajl_tok_string;
break;
}
@@ -325,16 +332,38 @@ yajl_lex_string(yajl_lexer lexer, const unsigned char * jsonText,
if (!(charLookupTable[curChar] & VHC)) {
/* back up to offending char */
unreadChar(lexer, offset);
- lexer->error = yajl_lex_string_invalid_hex_char;
+ lexer->error = yajl_lex_string_invalid_hex_u_char;
goto finish_string_lex;
}
}
- } else if (!(charLookupTable[curChar] & VEC)) {
+ }
+ else if (lexer->allowJson5 && curChar == 'x') {
+ unsigned int i = 0;
+
+ for (i=0;i<2;i++) {
+ STR_CHECK_EOF;
+ curChar = readChar(lexer, jsonText, offset);
+ if (!(charLookupTable[curChar] & VHC)) {
+ /* back up to offending char */
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_string_invalid_hex_x_char;
+ goto finish_string_lex;
+ }
+ }
+ }
+ else if (lexer->allowJson5 ? (curChar >= '1' && curChar <= '9')
+ : !(charLookupTable[curChar] & VEC)) {
/* back up to offending char */
unreadChar(lexer, offset);
lexer->error = yajl_lex_string_invalid_escaped_char;
goto finish_string_lex;
}
+ else if (lexer->allowJson5 && curChar == '\r') {
+ STR_CHECK_EOF;
+ curChar = readChar(lexer, jsonText, offset);
+ if (curChar != '\n')
+ unreadChar(lexer, offset);
+ }
}
/* when not validating UTF8 it's a simple table lookup to determine
* if the present character is invalid */
@@ -371,36 +400,83 @@ yajl_lex_string(yajl_lexer lexer, const unsigned char * jsonText,
#define RETURN_IF_EOF if (*offset >= jsonTextLen) return yajl_tok_eof;
+/* For both identifiers and numbers, we always have to lex one
+ * character too many to know when they are complete.
+ */
+
+static yajl_tok
+yajl_lex_identifier(yajl_lexer lexer, const unsigned char * jsonText,
+ size_t jsonTextLen, size_t * offset)
+{
+ unsigned char c;
+
+ do {
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+ } while (charLookupTable[c] & VIC);
+
+ /* we always go "one too far" */
+ unreadChar(lexer, offset);
+
+ return yajl_tok_identifier;
+}
+
static yajl_tok
yajl_lex_number(yajl_lexer lexer, const unsigned char * jsonText,
size_t jsonTextLen, size_t * offset)
{
- /** XXX: numbers are the only entities in json that we must lex
- * _beyond_ in order to know that they are complete. There
- * is an ambiguous case for integers at EOF. */
-
+ const char hexDigits[] = "0123456789abcdefABCDEF";
unsigned char c;
+ int numRd = 0;
yajl_tok tok = yajl_tok_integer;
RETURN_IF_EOF;
c = readChar(lexer, jsonText, offset);
- /* optional leading minus */
- if (c == '-') {
+ /* optional leading plus/minus */
+ if (c == '-' || (lexer->allowJson5 && c == '+')) {
RETURN_IF_EOF;
c = readChar(lexer, jsonText, offset);
}
- /* a single zero, or a series of integers */
- if (c == '0') {
- RETURN_IF_EOF;
- c = readChar(lexer, jsonText, offset);
- } else if (c >= '1' && c <= '9') {
+ if (c == 'I') {
+ const char * want = "nfinity";
do {
RETURN_IF_EOF;
c = readChar(lexer, jsonText, offset);
+ if (c != *want) {
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_invalid_string;
+ return yajl_tok_error;
+ }
+ } while (*(++want));
+ if (!lexer->allowJson5) {
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_unallowed_special_number;
+ return yajl_tok_error;
+ }
+ return yajl_tok_double;
+ }
+
+ /* a single zero, hex number, or a series of decimal digits */
+ if (c == '0') {
+ numRd++;
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+ if (c == 'x' || c == 'X') {
+ if (lexer->allowJson5) goto got_hex;
+ lexer->error = yajl_lex_unallowed_hex_integer;
+ return yajl_tok_error;
+ }
+ } else if (c >= '1' && c <= '9') {
+ do {
+ numRd++;
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
} while (c >= '0' && c <= '9');
+ } else if (lexer->allowJson5 && c == '.') {
+ goto got_decimal;
} else {
unreadChar(lexer, offset);
lexer->error = yajl_lex_missing_integer_after_minus;
@@ -409,10 +485,10 @@ yajl_lex_number(yajl_lexer lexer, const unsigned char * jsonText,
/* optional fraction (indicates this is floating point) */
if (c == '.') {
- int numRd = 0;
-
+ got_decimal:
RETURN_IF_EOF;
c = readChar(lexer, jsonText, offset);
+ if (!lexer->allowJson5) numRd = 0;
while (c >= '0' && c <= '9') {
numRd++;
@@ -452,6 +528,25 @@ yajl_lex_number(yajl_lexer lexer, const unsigned char * jsonText,
tok = yajl_tok_double;
}
+ goto end_number;
+
+ got_hex:
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+
+ if (strchr(hexDigits, c)) {
+ do {
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+ } while (strchr(hexDigits, c));
+ }
+ else {
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_missing_hex_digit_after_0x;
+ return yajl_tok_error;
+ }
+
+ end_number:
/* we always go "one too far" */
unreadChar(lexer, offset);
@@ -499,6 +594,23 @@ yajl_lex_comment(yajl_lexer lexer, const unsigned char * jsonText,
return tok;
}
+/* Macro to reduce code duplication in yajl_lex_lex() */
+#define LEX_WANT(tring) \
+ const char * want = tring; \
+ do { \
+ if (*offset >= jsonTextLen) { \
+ tok = yajl_tok_eof; \
+ goto lexed; \
+ } \
+ c = readChar(lexer, jsonText, offset); \
+ if (c != *want) { \
+ unreadChar(lexer, offset); \
+ lexer->error = yajl_lex_invalid_string; \
+ tok = yajl_tok_error; \
+ goto lexed; \
+ } \
+ } while (*(++want))
+
yajl_tok
yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText,
size_t jsonTextLen, size_t * offset,
@@ -544,71 +656,58 @@ yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText,
startOffset++;
break;
case 't': {
- const char * want = "rue";
- do {
- if (*offset >= jsonTextLen) {
- tok = yajl_tok_eof;
- goto lexed;
- }
- c = readChar(lexer, jsonText, offset);
- if (c != *want) {
- unreadChar(lexer, offset);
- lexer->error = yajl_lex_invalid_string;
- tok = yajl_tok_error;
- goto lexed;
- }
- } while (*(++want));
+ LEX_WANT("rue");
tok = yajl_tok_bool;
goto lexed;
}
case 'f': {
- const char * want = "alse";
- do {
- if (*offset >= jsonTextLen) {
- tok = yajl_tok_eof;
- goto lexed;
- }
- c = readChar(lexer, jsonText, offset);
- if (c != *want) {
- unreadChar(lexer, offset);
- lexer->error = yajl_lex_invalid_string;
- tok = yajl_tok_error;
- goto lexed;
- }
- } while (*(++want));
+ LEX_WANT("alse");
tok = yajl_tok_bool;
goto lexed;
}
case 'n': {
- const char * want = "ull";
- do {
- if (*offset >= jsonTextLen) {
- tok = yajl_tok_eof;
- goto lexed;
- }
- c = readChar(lexer, jsonText, offset);
- if (c != *want) {
- unreadChar(lexer, offset);
- lexer->error = yajl_lex_invalid_string;
- tok = yajl_tok_error;
- goto lexed;
- }
- } while (*(++want));
+ LEX_WANT("ull");
tok = yajl_tok_null;
goto lexed;
}
- case '"': {
- tok = yajl_lex_string(lexer, (const unsigned char *) jsonText,
- jsonTextLen, offset);
+ case 'I': {
+ LEX_WANT("nfinity");
+ if (!lexer->allowJson5) {
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_unallowed_special_number;
+ tok = yajl_tok_error;
+ } else {
+ tok = yajl_tok_double;
+ }
goto lexed;
}
+ case 'N': {
+ LEX_WANT("aN");
+ if (!lexer->allowJson5) {
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_unallowed_special_number;
+ tok = yajl_tok_error;
+ } else {
+ tok = yajl_tok_double;
+ }
+ goto lexed;
+ }
+ case '\'':
+ if (!lexer->allowJson5) goto invalid;
+ /* Fall through... */
+ case '"': {
+ tok = yajl_lex_string(lexer, jsonText, jsonTextLen, offset, c);
+ goto lexed;
+ }
+ case '+': case '.':
+ if (!lexer->allowJson5)
+ goto invalid;
case '-':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
/* integer parsing wants to start from the beginning */
unreadChar(lexer, offset);
- tok = yajl_lex_number(lexer, (const unsigned char *) jsonText,
- jsonTextLen, offset);
+ tok = yajl_lex_number(lexer, jsonText, jsonTextLen, offset);
goto lexed;
}
case '/':
@@ -640,6 +739,7 @@ yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText,
/* hit error or eof, bail */
goto lexed;
default:
+ invalid:
lexer->error = yajl_lex_invalid_char;
tok = yajl_tok_error;
goto lexed;
@@ -674,6 +774,126 @@ yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText,
*outLen -= 2;
}
+#ifdef YAJL_LEXER_DEBUG
+ if (tok == yajl_tok_error) {
+ printf("lexical error: %s\n",
+ yajl_lex_error_to_string(yajl_lex_get_error(lexer)));
+ } else if (tok == yajl_tok_eof) {
+ printf("EOF hit\n");
+ } else {
+ printf("lexed %s: '", tokToStr(tok));
+ fwrite(*outBuf, 1, *outLen, stdout);
+ printf("'\n");
+ }
+#endif
+
+ return tok;
+}
+
+yajl_tok yajl_lex_key(yajl_lexer lexer, const unsigned char * jsonText,
+ size_t jsonTextLen, size_t * offset,
+ const unsigned char ** outBuf, size_t * outLen)
+{
+ yajl_tok tok = yajl_tok_error;
+ unsigned char c;
+ size_t startOffset = *offset;
+
+ *outBuf = NULL;
+ *outLen = 0;
+
+ for (;;) {
+ assert(*offset <= jsonTextLen);
+
+ if (*offset >= jsonTextLen) {
+ tok = yajl_tok_eof;
+ goto lexed;
+ }
+
+ c = readChar(lexer, jsonText, offset);
+
+ switch (c) {
+ case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
+ startOffset++;
+ break;
+ case '}':
+ tok = yajl_tok_right_brace;
+ goto lexed;
+ case '\'':
+ if (!lexer->allowJson5) goto invalid;
+ /* Fall through... */
+ case '"': {
+ tok = yajl_lex_string(lexer, jsonText, jsonTextLen, offset, c);
+ goto lexed;
+ }
+ case '/':
+ /* If comments are disabled this is an error. */
+ if (!lexer->allowComments) {
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_unallowed_comment;
+ tok = yajl_tok_error;
+ goto lexed;
+ }
+ /* Comments are enabled, so lex it.
+ * Possible outcomes are:
+ * - successful lex (tok_comment, which means continue),
+ * - malformed comment opening (slash not followed by
+ * '*' or '/') (tok_error)
+ * - eof hit. (tok_eof) */
+ tok = yajl_lex_comment(lexer, jsonText, jsonTextLen, offset);
+ if (tok == yajl_tok_comment) {
+ /* "error" is silly, but that's the initial
+ * state of tok. guilty until proven innocent. */
+ tok = yajl_tok_error;
+ yajl_buf_clear(lexer->buf);
+ lexer->bufInUse = 0;
+ startOffset = *offset;
+ break;
+ }
+ /* hit error or eof, bail */
+ goto lexed;
+ default:
+ if (lexer->allowJson5 && (c == '$' || c == '_' ||
+ (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))) {
+ tok = yajl_lex_identifier(lexer, jsonText, jsonTextLen, offset);
+ }
+ else {
+ invalid:
+ lexer->error = yajl_lex_invalid_char;
+ tok = yajl_tok_error;
+ }
+ goto lexed;
+ }
+ }
+
+ lexed:
+ /* need to append to buffer if the buffer is in use or
+ * if it's an EOF token */
+ if (tok == yajl_tok_eof || lexer->bufInUse) {
+ if (!lexer->bufInUse) yajl_buf_clear(lexer->buf);
+ lexer->bufInUse = 1;
+ yajl_buf_append(lexer->buf, jsonText + startOffset, *offset - startOffset);
+ lexer->bufOff = 0;
+
+ if (tok != yajl_tok_eof) {
+ *outBuf = yajl_buf_data(lexer->buf);
+ *outLen = yajl_buf_len(lexer->buf);
+ lexer->bufInUse = 0;
+ }
+ } else if (tok != yajl_tok_error) {
+ *outBuf = jsonText + startOffset;
+ *outLen = *offset - startOffset;
+ }
+
+ /* For strings skip the quotes. */
+ if (tok == yajl_tok_string ||
+ tok == yajl_tok_string_with_escapes) {
+ assert(*outLen >= 2);
+ (*outBuf)++;
+ *outLen -= 2;
+ }
+ else if (tok == yajl_tok_identifier) {
+ tok = yajl_tok_string;
+ }
#ifdef YAJL_LEXER_DEBUG
if (tok == yajl_tok_error) {
@@ -704,9 +924,12 @@ yajl_lex_error_to_string(yajl_lex_error error)
"which it may not.";
case yajl_lex_string_invalid_json_char:
return "invalid character inside string.";
- case yajl_lex_string_invalid_hex_char:
+ case yajl_lex_string_invalid_hex_u_char:
return "invalid (non-hex) character occurs after '\\u' inside "
"string.";
+ case yajl_lex_string_invalid_hex_x_char:
+ return "invalid (non-hex) character occurs after '\\x' inside "
+ "string.";
case yajl_lex_invalid_char:
return "invalid char in json text.";
case yajl_lex_invalid_string:
@@ -718,10 +941,16 @@ yajl_lex_error_to_string(yajl_lex_error error)
"decimal point.";
case yajl_lex_missing_integer_after_minus:
return "malformed number, a digit is required after the "
- "minus sign.";
+ "plus/minus sign.";
case yajl_lex_unallowed_comment:
return "probable comment found in input text, comments are "
"not enabled.";
+ case yajl_lex_missing_hex_digit_after_0x:
+ return "malformed number, a hex digit is required after the 0x/0X.";
+ case yajl_lex_unallowed_hex_integer:
+ return "probable hex number found, JSON5 is not enabled.";
+ case yajl_lex_unallowed_special_number:
+ return "special number Infinity or NaN found, JSON5 is not enabled.";
}
return "unknown error code";
}
diff --git a/modules/libcom/src/yajl/yajl_lex.h b/modules/libcom/src/yajl/yajl_lex.h
index 806ea1de0..7c2a6b9d8 100644
--- a/modules/libcom/src/yajl/yajl_lex.h
+++ b/modules/libcom/src/yajl/yajl_lex.h
@@ -41,7 +41,12 @@ typedef enum {
yajl_tok_string,
yajl_tok_string_with_escapes,
- /* comment tokens are not currently returned to the parser, ever */
+ /* These tokens are used within the lexer and never seen by the parser: */
+
+ /* An unquoted map key, for JSON5 only, returned as yajl_tok_string */
+ yajl_tok_identifier,
+
+ /* A comment token, never returned */
yajl_tok_comment
} yajl_tok;
@@ -53,7 +58,8 @@ extern "C" {
yajl_lexer yajl_lex_alloc(yajl_alloc_funcs * alloc,
unsigned int allowComments,
- unsigned int validateUTF8);
+ unsigned int validateUTF8,
+ unsigned int allowJson5);
void yajl_lex_free(yajl_lexer lexer);
@@ -83,6 +89,14 @@ yajl_tok yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText,
size_t jsonTextLen, size_t * offset,
const unsigned char ** outBuf, size_t * outLen);
+/**
+ * A specialized version of yajl_lex_lex for use when the next token is
+ * a map key, which the parser knows.
+ */
+yajl_tok yajl_lex_key(yajl_lexer lexer, const unsigned char * jsonText,
+ size_t jsonTextLen, size_t * offset,
+ const unsigned char ** outBuf, size_t * outLen);
+
/** have a peek at the next token, but don't move the lexer forward */
yajl_tok yajl_lex_peek(yajl_lexer lexer, const unsigned char * jsonText,
size_t jsonTextLen, size_t offset);
@@ -93,13 +107,17 @@ typedef enum {
yajl_lex_string_invalid_utf8,
yajl_lex_string_invalid_escaped_char,
yajl_lex_string_invalid_json_char,
- yajl_lex_string_invalid_hex_char,
+ yajl_lex_string_invalid_hex_u_char,
+ yajl_lex_string_invalid_hex_x_char,
yajl_lex_invalid_char,
yajl_lex_invalid_string,
yajl_lex_missing_integer_after_decimal,
yajl_lex_missing_integer_after_exponent,
yajl_lex_missing_integer_after_minus,
- yajl_lex_unallowed_comment
+ yajl_lex_unallowed_comment,
+ yajl_lex_missing_hex_digit_after_0x,
+ yajl_lex_unallowed_hex_integer,
+ yajl_lex_unallowed_special_number,
} yajl_lex_error;
const char * yajl_lex_error_to_string(yajl_lex_error error);
diff --git a/modules/libcom/src/yajl/yajl_parse.h b/modules/libcom/src/yajl/yajl_parse.h
index e5b565c80..90367d978 100644
--- a/modules/libcom/src/yajl/yajl_parse.h
+++ b/modules/libcom/src/yajl/yajl_parse.h
@@ -28,42 +28,42 @@
#ifdef __cplusplus
extern "C" {
#endif
- /** Error codes returned from this interface */
+ /** Error codes returned from this interface. */
typedef enum {
- /** No error was encountered */
+ /** No error was encountered. */
yajl_status_ok,
- /** A client callback returned zero, stopping the parse */
+ /** A client callback returned zero, stopping the parse. */
yajl_status_client_canceled,
- /** An error occured during the parse. Call yajl_get_error() for
- * more information about the encountered error */
+ /** An error occured during the parse. Call yajl_get_error() for
+ * more information about the encountered error. */
yajl_status_error
} yajl_status;
- /** Attain a human readable, english, string for an error */
+ /** Return a human readable, english, string for an error. */
YAJL_API const char * yajl_status_to_string(yajl_status code);
- /** An opaque handle to a parser */
+ /** An opaque handle to a parser. */
typedef struct yajl_handle_t * yajl_handle;
- /** YAJL is an event driven parser. This means as json elements are
- * parsed, you are called back to do something with the data. The
+ /** YAJL is an event driven parser. This means as json elements are
+ * parsed, you are called back to do something with the data. The
* functions in this table indicate the various events for which
* you will be called back. Each callback accepts a "context"
- * pointer, this is a void * that is passed into the yajl_parse()
+ * pointer, this is a \c void \c * that is passed into the yajl_parse()
* function which the client code may use to pass around context.
*
- * All callbacks return an integer. If non-zero, the parse will
- * continue. If zero, the parse will be canceled and
- * yajl_status_client_canceled() will be returned from the parse.
+ * All callbacks return an integer. If non-zero, the parse will
+ * continue. If zero, the parse will be canceled and
+ * \c yajl_status_client_canceled will be returned from the parse.
*
* \attention
* A note about the handling of numbers:
- * yajl will only convert numbers that can be represented in a
+ * YAJL will only convert numbers that can be represented in a
* double or a 64 bit (long long) int. All other numbers will
* be passed to the client in string form using the yajl_number()
* callback. Furthermore, if yajl_number() is not NULL, it will
* always be used to return numbers, that is yajl_integer() and
- * yajl_double() will be ignored. If yajl_number() is NULL but one
+ * yajl_double() will be ignored. If yajl_number() is NULL but one
* of yajl_integer() or yajl_double() are defined, parsing of a
* number larger than is representable in a double or 64 bit
* integer will result in a parse error.
@@ -74,12 +74,12 @@ extern "C" {
int (* yajl_integer)(void * ctx, long long integerVal);
int (* yajl_double)(void * ctx, double doubleVal);
/** A callback which passes the string representation of the number
- * back to the client. Will be used for all numbers when present */
+ * back to the client. Will be used for all numbers when present. */
int (* yajl_number)(void * ctx, const char * numberVal,
size_t numberLen);
- /** Strings are returned as pointers into the JSON text when,
- * possible, as a result, they are _not_ null padded */
+ /** Strings are returned as pointers into the JSON text when
+ * possible. As a result they are _not_ zero-terminated. */
int (* yajl_string)(void * ctx, const unsigned char * stringVal,
size_t stringLen);
@@ -92,117 +92,153 @@ extern "C" {
int (* yajl_end_array)(void * ctx);
} yajl_callbacks;
- /** Allocate a parser handle
- * \param callbacks A yajl callbacks structure specifying the
+ /** Allocate a parser handle.
+ * \param callbacks A \c yajl_callbacks structure specifying the
* functions to call when different JSON entities
- * are encountered in the input text. May be NULL,
+ * are encountered in the input text. May be \c NULL,
* which is only useful for validation.
- * \param afs memory allocation functions, may be NULL for to use
- * C runtime library routines (malloc and friends)
- * \param ctx a context pointer that will be passed to callbacks.
+ * \param afs Memory allocation functions, pass \c NULL to use the
+ * C runtime library routines (malloc() and friends).
+ * \param ctx A context pointer that will be passed to callbacks.
*/
YAJL_API yajl_handle yajl_alloc(const yajl_callbacks * callbacks,
yajl_alloc_funcs * afs,
void * ctx);
- /** Configuration parameters for the parser, these may be passed to
- * yajl_config() along with option specific argument(s). In general,
- * all configuration parameters default to *off*. */
+ /** Configuration parameters for the parser. These should be passed to
+ * yajl_config() followed by any option specific argument(s). In general,
+ * all boolean configuration parameters default to *off*. */
typedef enum {
- /** Ignore javascript style comments present in
- * JSON input. Non-standard, but rather fun
- * arguments: toggled off with integer zero, on otherwise.
+ /**
+ * Ignore javascript style comments present in the input. These are
+ * not standard in JSON but can be enabled with this. Turning on the
+ * \ref yajl_allow_json5 option enables this option automatically.
*
- * Example: \code{.cpp}
- * yajl_config(h, yajl_allow_comments, 1); // turn comment support on
- * \endcode
+ * yajl_config() argument type: int (boolean)
+ *
+ * Example: \code{.cpp}
+ * yajl_config(h, yajl_allow_comments, 1); // turn comment support on
+ * \endcode
*/
yajl_allow_comments = 0x01,
/**
* When set the parser will verify that all strings in JSON input are
- * valid UTF8 and will emit a parse error if this is not so. When set,
- * this option makes parsing slightly more expensive (~7% depending
- * on processor and compiler in use)
+ * valid UTF8, and will emit a parse error if this is not so. When set,
+ * this option makes parsing slightly more expensive (~7% depending on
+ * the processor and compiler in use)
+ *
+ * yajl_config() argument type: int (boolean)
*
* Example: \code{.cpp}
- * yajl_config(h, yajl_dont_validate_strings, 1); // disable utf8 checking
- * \endcode
+ * yajl_config(h, yajl_dont_validate_strings, 1); // disable utf8 checking
+ * \endcode
*/
yajl_dont_validate_strings = 0x02,
/**
- * By default, upon calls to yajl_complete_parse(), yajl will
- * ensure the entire input text was consumed and will raise an error
- * otherwise. Enabling this flag will cause yajl to disable this
- * check. This can be useful when parsing json out of a that contains more
- * than a single JSON document.
+ * By default, upon calls to yajl_complete_parse(), yajl will ensure
+ * the entire input text was consumed and will raise an error
+ * otherwise. Turning this flag on causes YAJL to disable the garbage
+ * check. This can be useful when parsing JSON out of an input stream
+ * that contains more than a single JSON document.
+ *
+ * yajl_config() argument type: int (boolean)
+ *
+ * Example: \code{.cpp}
+ * yajl_config(h, yajl_allow_trailing_garbage, 1); // non-JSON follows
+ * \endcode
*/
yajl_allow_trailing_garbage = 0x04,
/**
- * Allow multiple values to be parsed by a single handle. The
- * entire text must be valid JSON, and values can be seperated
- * by any kind of whitespace. This flag will change the
- * behavior of the parser, and cause it continue parsing after
- * a value is parsed, rather than transitioning into a
- * complete state. This option can be useful when parsing multiple
- * values from an input stream.
+ * Allow multiple values to be parsed by a single handle. The entire
+ * text must be valid JSON, and values can be seperated by any kind of
+ * whitespace. This flag will change the behavior of the parser, and
+ * cause it to continue parsing after a value is parsed, rather than
+ * transitioning into a complete state. This option can be useful when
+ * parsing multiple values from an input stream.
+ *
+ * yajl_config() argument type: int (boolean)
+ *
+ * Example: \code{.cpp}
+ * yajl_config(h, yajl_allow_multiple_values, 1); // multi-doc stream
+ * \endcode
*/
yajl_allow_multiple_values = 0x08,
/**
- * When yajl_complete_parse() is called the parser will
- * check that the top level value was completely consumed. I.E.,
- * if called whilst in the middle of parsing a value
- * yajl will enter an error state (premature EOF). Setting this
- * flag suppresses that check and the corresponding error.
+ * When yajl_complete_parse() is called the parser will check that the
+ * top level value was completely consumed. If called whilst in the
+ * middle of parsing a value, yajl will enter an error state (premature
+ * EOF). Setting this flag suppresses that check and the corresponding
+ * error.
+ *
+ * yajl_config() argument type: int (boolean)
+ *
+ * Example: \code{.cpp}
+ * yajl_config(h, yajl_allow_partial_values, 1); // might stop early
+ * \endcode
*/
- yajl_allow_partial_values = 0x10
+ yajl_allow_partial_values = 0x10,
+ /**
+ * The JSON5 standard allows additional formats for numbers, strings
+ * and object keys which are not permitted by the JSON standard.
+ * Setting this flag tells yajl to accept JSON5 standard input.
+ * This flag also enables \c yajl_allow_comments since comments are
+ * part of the JSON5 standard. In the EPICS build this option is
+ * enabled by default, it must be turned off to disable JSON5.
+ *
+ * yajl_config() argument type: int (boolean)
+ *
+ * Example: \code{.cpp}
+ * yajl_config(h, yajl_allow_json5, 1); // We accept JSON5!
+ * \endcode
+ */
+ yajl_allow_json5 = 0x20,
} yajl_option;
- /** Allow the modification of parser options subsequent to handle
- * allocation (via yajl_alloc())
- * \returns zero in case of errors, non-zero otherwise
+ /** Set parser options associated with a parser handle. See the
+ * \ref yajl_option documentation for details of the available options
+ * and their arguments.
+ * \returns Zero in case of error, non-zero otherwise.
*/
- YAJL_API int yajl_config(yajl_handle h, yajl_option opt, ...);
+ YAJL_API int yajl_config(yajl_handle hand, int option, ...);
- /** Free a parser handle */
- YAJL_API void yajl_free(yajl_handle handle);
+ /** Free a parser handle. */
+ YAJL_API void yajl_free(yajl_handle hand);
/** Parse some json!
- * \param hand - a handle to the json parser allocated with yajl_alloc()
- * \param jsonText - a pointer to the UTF8 json text to be parsed
- * \param jsonTextLength - the length, in bytes, of input text
+ * \param hand A handle to the json parser allocated with yajl_alloc().
+ * \param jsonText A pointer to the UTF8 json text to be parsed.
+ * \param jsonTextLength The length, in bytes, of input text.
*/
YAJL_API yajl_status yajl_parse(yajl_handle hand,
const unsigned char * jsonText,
size_t jsonTextLength);
/** Parse any remaining buffered json.
+ *
* Since yajl is a stream-based parser, without an explicit end of
* input, yajl sometimes can't decide if content at the end of the
- * stream is valid or not. For example, if "1" has been fed in,
+ * stream is valid or not. For example, if "1" has been received,
* yajl can't know whether another digit is next or some character
* that would terminate the integer token.
*
- * \param hand - a handle to the json parser allocated with yajl_alloc()
+ * \param hand a handle to the json parser allocated with yajl_alloc().
*/
YAJL_API yajl_status yajl_complete_parse(yajl_handle hand);
- /** Get an error string describing the state of the
- * parse.
+ /** Get an error string describing the state of the parse.
*
- * If verbose is non-zero, the message will include the JSON
- * text where the error occured, along with an arrow pointing to
- * the specific char.
+ * If verbose is non-zero, the message will include the JSON text where
+ * the error occured, along with an arrow pointing to the specific char.
*
* \returns A dynamically allocated string will be returned which should
- * be freed with yajl_free_error()
+ * be freed with yajl_free_error().
*/
YAJL_API unsigned char * yajl_get_error(yajl_handle hand, int verbose,
const unsigned char * jsonText,
size_t jsonTextLength);
- /**
- * Get the amount of data consumed from the last chunk passed to YAJL.
+ /** Get the amount of data consumed from the last chunk passed to YAJL.
*
* In the case of a successful parse this can help you understand if
* the entire buffer was consumed (which will allow you to handle
@@ -215,7 +251,7 @@ extern "C" {
*/
YAJL_API size_t yajl_get_bytes_consumed(yajl_handle hand);
- /** Free an error returned from yajl_get_error() */
+ /** Free an error string returned from yajl_get_error(). */
YAJL_API void yajl_free_error(yajl_handle hand, unsigned char * str);
#ifdef __cplusplus
diff --git a/modules/libcom/src/yajl/yajl_parser.c b/modules/libcom/src/yajl/yajl_parser.c
index cb910f79d..b400709a6 100644
--- a/modules/libcom/src/yajl/yajl_parser.c
+++ b/modules/libcom/src/yajl/yajl_parser.c
@@ -34,29 +34,52 @@
#define LLONG_MIN (-0x7FFFFFFFFFFFFFFFLL - 1)
#endif
-#define MAX_VALUE_TO_MULTIPLY ((LLONG_MAX / 10) + (LLONG_MAX % 10))
-
- /* same semantics as strtol */
long long
yajl_parse_integer(const unsigned char *number, size_t length)
{
long long ret = 0;
long sign = 1;
+ long base = 10;
+ long long max = LLONG_MAX / base;
const unsigned char *pos = number;
- if (*pos == '-') { pos++; sign = -1; }
- if (*pos == '+') { pos++; }
+ const unsigned char *end = number + length;
- while (pos < number + length) {
- if ( ret > MAX_VALUE_TO_MULTIPLY ) {
+ if (*pos == '-') {
+ pos++;
+ sign = -1;
+ }
+ else if (*pos == '+') {
+ pos++;
+ }
+
+ if (*pos == '0' &&
+ (pos[1] == 'x' || pos[1] == 'X')) {
+ base = 16;
+ max = LLONG_MAX / base;
+ pos += 2;
+ }
+
+ while (pos < end) {
+ int digit;
+
+ if (ret > max) {
errno = ERANGE;
return sign == 1 ? LLONG_MAX : LLONG_MIN;
}
- ret *= 10;
- if (LLONG_MAX - ret < (*pos - '0')) {
+
+ ret *= base;
+ digit = *pos++ - '0';
+ /* Don't have to check for non-digit characters,
+ * the lexer has already rejected any bad digits.
+ */
+ if (digit > 9)
+ digit = (digit - ('A' - '0') + 10) & 0xf;
+
+ if (LLONG_MAX - ret < digit) {
errno = ERANGE;
return sign == 1 ? LLONG_MAX : LLONG_MIN;
}
- ret += (*pos++ - '0');
+ ret += digit;
}
return sign * ret;
@@ -332,7 +355,8 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
case yajl_tok_right_bracket: {
yajl_state s = yajl_bs_current(hand->stateStack);
if (s == yajl_state_array_start ||
- s == yajl_state_array_need_val)
+ ((hand->flags & yajl_allow_json5) &&
+ (s == yajl_state_array_need_val)))
{
if (hand->callbacks &&
hand->callbacks->yajl_end_array)
@@ -377,8 +401,8 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
case yajl_state_map_need_key: {
/* only difference between these two states is that in
* start '}' is valid, whereas in need_key, we've parsed
- * a comma, and a string key _must_ follow */
- tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
+ * a comma, so unless this is JSON5 a key _must_ follow. */
+ tok = yajl_lex_key(hand->lexer, jsonText, jsonTextLen,
offset, &buf, &bufLen);
switch (tok) {
case yajl_tok_eof:
@@ -404,7 +428,8 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
case yajl_tok_right_brace: {
yajl_state s = yajl_bs_current(hand->stateStack);
if (s == yajl_state_map_start ||
- s == yajl_state_map_need_key) {
+ ((hand->flags & yajl_allow_json5) &&
+ (s == yajl_state_map_need_key))) {
if (hand->callbacks && hand->callbacks->yajl_end_map) {
_CC_CHK(hand->callbacks->yajl_end_map(hand->ctx));
}
@@ -414,7 +439,8 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
}
default:
yajl_bs_set(hand->stateStack, yajl_state_parse_error);
- hand->parseError =
+ hand->parseError = hand->flags & yajl_allow_json5 ?
+ "invalid object key (must be a string or identifier)" :
"invalid object key (must be a string)";
goto around_again;
}
diff --git a/modules/libcom/test/aslibtest.c b/modules/libcom/test/aslibtest.c
index 4237fafb1..eefad5700 100644
--- a/modules/libcom/test/aslibtest.c
+++ b/modules/libcom/test/aslibtest.c
@@ -1,5 +1,6 @@
/*************************************************************************\
* Copyright (c) 2018 Michael Davidsaver
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/blockingSockTest.cpp b/modules/libcom/test/blockingSockTest.cpp
index be2dcc4d3..f802974d8 100644
--- a/modules/libcom/test/blockingSockTest.cpp
+++ b/modules/libcom/test/blockingSockTest.cpp
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/buckTest.c b/modules/libcom/test/buckTest.c
index 6fc34954e..ec914b5a6 100644
--- a/modules/libcom/test/buckTest.c
+++ b/modules/libcom/test/buckTest.c
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/cvtFastPerform.cpp b/modules/libcom/test/cvtFastPerform.cpp
index 28c831349..0416046a8 100644
--- a/modules/libcom/test/cvtFastPerform.cpp
+++ b/modules/libcom/test/cvtFastPerform.cpp
@@ -1,3 +1,9 @@
+/*************************************************************************\
+* SPDX-License-Identifier: EPICS
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+\*************************************************************************/
+
// Original Author: Jeff Hill, LANL
#include
diff --git a/modules/libcom/test/cvtFastTest.c b/modules/libcom/test/cvtFastTest.c
index ac853ecc3..b3e4248f3 100644
--- a/modules/libcom/test/cvtFastTest.c
+++ b/modules/libcom/test/cvtFastTest.c
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsAlgorithmTest.cpp b/modules/libcom/test/epicsAlgorithmTest.cpp
index ac1985b3b..09f7041b6 100644
--- a/modules/libcom/test/epicsAlgorithmTest.cpp
+++ b/modules/libcom/test/epicsAlgorithmTest.cpp
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsAtomicPerform.cpp b/modules/libcom/test/epicsAtomicPerform.cpp
index 9062e9748..21f11fd4e 100644
--- a/modules/libcom/test/epicsAtomicPerform.cpp
+++ b/modules/libcom/test/epicsAtomicPerform.cpp
@@ -1,3 +1,8 @@
+/*************************************************************************\
+* SPDX-License-Identifier: EPICS
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+\*************************************************************************/
#include
#include
diff --git a/modules/libcom/test/epicsAtomicTest.cpp b/modules/libcom/test/epicsAtomicTest.cpp
index 318661edc..0b57ed8d6 100644
--- a/modules/libcom/test/epicsAtomicTest.cpp
+++ b/modules/libcom/test/epicsAtomicTest.cpp
@@ -1,3 +1,8 @@
+/*************************************************************************\
+* SPDX-License-Identifier: EPICS
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+\*************************************************************************/
#include
#include
diff --git a/modules/libcom/test/epicsCalcTest.cpp b/modules/libcom/test/epicsCalcTest.cpp
index a47736497..cf4cf9b62 100644
--- a/modules/libcom/test/epicsCalcTest.cpp
+++ b/modules/libcom/test/epicsCalcTest.cpp
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsEllTest.c b/modules/libcom/test/epicsEllTest.c
index 1ff66aa7e..ba19a9a0d 100644
--- a/modules/libcom/test/epicsEllTest.c
+++ b/modules/libcom/test/epicsEllTest.c
@@ -4,6 +4,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsEnvTest.c b/modules/libcom/test/epicsEnvTest.c
index bbce4b749..531f6c4bd 100644
--- a/modules/libcom/test/epicsEnvTest.c
+++ b/modules/libcom/test/epicsEnvTest.c
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsEnvUnsetTest.c b/modules/libcom/test/epicsEnvUnsetTest.c
index e9d0f8603..05e764a43 100644
--- a/modules/libcom/test/epicsEnvUnsetTest.c
+++ b/modules/libcom/test/epicsEnvUnsetTest.c
@@ -1,3 +1,9 @@
+/*************************************************************************\
+* SPDX-License-Identifier: EPICS
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+\*************************************************************************/
+
#include
#include
#include
diff --git a/modules/libcom/test/epicsErrlogTest.c b/modules/libcom/test/epicsErrlogTest.c
index 2f1c42740..5d6bbdcad 100644
--- a/modules/libcom/test/epicsErrlogTest.c
+++ b/modules/libcom/test/epicsErrlogTest.c
@@ -3,6 +3,7 @@
* Brookhaven National Laboratory.
* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsEventTest.cpp b/modules/libcom/test/epicsEventTest.cpp
index 1f6ec9d0f..cc73f8398 100644
--- a/modules/libcom/test/epicsEventTest.cpp
+++ b/modules/libcom/test/epicsEventTest.cpp
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsExitTest.c b/modules/libcom/test/epicsExitTest.c
index dc901b5ac..fcb9ae70d 100644
--- a/modules/libcom/test/epicsExitTest.c
+++ b/modules/libcom/test/epicsExitTest.c
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsInlineTest1.c b/modules/libcom/test/epicsInlineTest1.c
index e377e5f1d..62da1a134 100644
--- a/modules/libcom/test/epicsInlineTest1.c
+++ b/modules/libcom/test/epicsInlineTest1.c
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2015 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsInlineTest2.c b/modules/libcom/test/epicsInlineTest2.c
index b787276fb..d2e39a208 100644
--- a/modules/libcom/test/epicsInlineTest2.c
+++ b/modules/libcom/test/epicsInlineTest2.c
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2015 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsInlineTest3.cpp b/modules/libcom/test/epicsInlineTest3.cpp
index 9647be6dc..08993ca4d 100644
--- a/modules/libcom/test/epicsInlineTest3.cpp
+++ b/modules/libcom/test/epicsInlineTest3.cpp
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2015 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsInlineTest4.cpp b/modules/libcom/test/epicsInlineTest4.cpp
index 545b45ffd..c2e083369 100644
--- a/modules/libcom/test/epicsInlineTest4.cpp
+++ b/modules/libcom/test/epicsInlineTest4.cpp
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2015 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsLoadTest.cpp b/modules/libcom/test/epicsLoadTest.cpp
index 77b37f2db..304c42d73 100644
--- a/modules/libcom/test/epicsLoadTest.cpp
+++ b/modules/libcom/test/epicsLoadTest.cpp
@@ -1,5 +1,6 @@
/*************************************************************************\
* Copyright (c) 2020 Michael Davidsaver
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsMMIOTest.c b/modules/libcom/test/epicsMMIOTest.c
index 939627348..1e7d9e3b9 100644
--- a/modules/libcom/test/epicsMMIOTest.c
+++ b/modules/libcom/test/epicsMMIOTest.c
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2013 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsMathTest.c b/modules/libcom/test/epicsMathTest.c
index 393d0c127..53967d480 100644
--- a/modules/libcom/test/epicsMathTest.c
+++ b/modules/libcom/test/epicsMathTest.c
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsMaxThreads.c b/modules/libcom/test/epicsMaxThreads.c
index 8d0d06da5..61a683a08 100644
--- a/modules/libcom/test/epicsMaxThreads.c
+++ b/modules/libcom/test/epicsMaxThreads.c
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsMessageQueueTest.cpp b/modules/libcom/test/epicsMessageQueueTest.cpp
index 340ae6b58..c2e041a75 100644
--- a/modules/libcom/test/epicsMessageQueueTest.cpp
+++ b/modules/libcom/test/epicsMessageQueueTest.cpp
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsMutexTest.cpp b/modules/libcom/test/epicsMutexTest.cpp
index c46a8ce61..3086f679a 100644
--- a/modules/libcom/test/epicsMutexTest.cpp
+++ b/modules/libcom/test/epicsMutexTest.cpp
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsRunLibComTests.c b/modules/libcom/test/epicsRunLibComTests.c
index 94fe3d76f..d469fcf83 100644
--- a/modules/libcom/test/epicsRunLibComTests.c
+++ b/modules/libcom/test/epicsRunLibComTests.c
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsSockResolveTest.c b/modules/libcom/test/epicsSockResolveTest.c
index 04b2973fa..14a34c853 100644
--- a/modules/libcom/test/epicsSockResolveTest.c
+++ b/modules/libcom/test/epicsSockResolveTest.c
@@ -3,6 +3,9 @@
* Brookhaven National Lab.
* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
+* SPDX-License-Identifier: EPICS
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include "dbDefs.h"
diff --git a/modules/libcom/test/epicsSpinTest.c b/modules/libcom/test/epicsSpinTest.c
index c45348beb..dbf109142 100644
--- a/modules/libcom/test/epicsSpinTest.c
+++ b/modules/libcom/test/epicsSpinTest.c
@@ -2,6 +2,7 @@
* Copyright (c) 2012 Helmholtz-Zentrum Berlin
* fuer Materialien und Energie GmbH.
* Copyright (c) 2012 ITER Organization.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsStackTraceTest.c b/modules/libcom/test/epicsStackTraceTest.c
index 3739884fc..39a6dceb2 100644
--- a/modules/libcom/test/epicsStackTraceTest.c
+++ b/modules/libcom/test/epicsStackTraceTest.c
@@ -1,6 +1,7 @@
/*
* Copyright: Stanford University / SLAC National Laboratory.
*
+ * SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*
diff --git a/modules/libcom/test/epicsStdioTest.c b/modules/libcom/test/epicsStdioTest.c
index 5b32d144f..6569b5029 100644
--- a/modules/libcom/test/epicsStdioTest.c
+++ b/modules/libcom/test/epicsStdioTest.c
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsStdlibTest.c b/modules/libcom/test/epicsStdlibTest.c
index e460e67d4..c66673ec2 100644
--- a/modules/libcom/test/epicsStdlibTest.c
+++ b/modules/libcom/test/epicsStdlibTest.c
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsStringTest.c b/modules/libcom/test/epicsStringTest.c
index 3e4aed7e7..e4e95c998 100644
--- a/modules/libcom/test/epicsStringTest.c
+++ b/modules/libcom/test/epicsStringTest.c
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
@@ -16,6 +17,7 @@
#include "epicsUnitTest.h"
#include "epicsString.h"
+#include "epicsMath.h"
#include "testMain.h"
static
@@ -73,6 +75,35 @@ void testGlob(void) {
testOk1(epicsStrGlobMatch("hello","*"));
}
+static
+void testDistance(void) {
+ double dist;
+ testDiag("testDistance()");
+
+#define TEST(EXPECT, A, B) dist = epicsStrSimilarity(A, B); testOk(fabs(dist-(EXPECT))<0.01, "distance \"%s\", \"%s\" %f ~= %f", A, B, dist, EXPECT)
+
+ TEST(1.00, "", "");
+ TEST(1.00, "A", "A");
+ TEST(0.00, "A", "B");
+ TEST(1.00, "exact", "exact");
+ TEST(0.90, "10 second", "10 seconds");
+ TEST(0.71, "Passive", "Pensive");
+ TEST(0.11, "10 second", "Pensive");
+ TEST(0.97, "Set output to IVOV", "Set output To IVOV");
+
+ /* we modify Levenshtein to give half weight to case insensitive matches */
+
+ /* totally unrelated except for 'i' ~= 'I' */
+ TEST(0.06, "Passive", "I/O Intr");
+ TEST(0.06, "I/O Intr", "Pensive");
+ /* 2x subst and 1x case subst, max distance 2xlen("YES") */
+ TEST(0.50, "YES", "yes");
+ TEST(0.00, "YES", "NO");
+ TEST(0.67, "YES", "Yes");
+ TEST(0.67, "Tes", "yes");
+#undef TEST
+}
+
MAIN(epicsStringTest)
{
const char * const empty = "";
@@ -87,7 +118,7 @@ MAIN(epicsStringTest)
char *s;
int status;
- testPlan(406);
+ testPlan(401);
testChars();
@@ -158,7 +189,7 @@ MAIN(epicsStringTest)
status = epicsStrnEscapedFromRawSize(ABCD, 4);
testOk(status == 4, "size(\"ABCD\", 4) -> %d (exp. 4)", status);
status = epicsStrnEscapedFromRawSize(ABCD, 5);
- testOk(status == 8, "size(\"ABCD\", 5) -> %d (exp. 8)", status);
+ testOk(status == 6, "size(\"ABCD\", 5) -> %d (exp. 8)", status);
testDiag("Testing esc = epicsStrnEscapedFromRaw(out, 4, ...)");
@@ -176,7 +207,7 @@ MAIN(epicsStringTest)
memset(result, 'x', sizeof(result));
status = epicsStrnEscapedFromRaw(result, 4, ABCD, 5);
- testOk(status == 8, "esc(\"ABCD\", 5) -> %d (exp. 8)", status);
+ testOk(status == 6, "esc(\"ABCD\", 5) -> %d (exp. 8)", status);
testOk(result[3] == 0, " 0-terminated");
testOk(result[4] == 'x', " No overrun");
@@ -233,49 +264,6 @@ MAIN(epicsStringTest)
testOk(result[0] == 'A', " Char '%c' (exp. 'A')", result[0]);
testOk(result[status] == 0, " 0-terminated");
- memset(result, 'x', sizeof(result));
- status = epicsStrnRawFromEscaped(result, 4, "\\123", 1);
- testOk(status == 0, "raw(\"\\123\", 1) -> %d (exp. 0)", status);
- testOk(result[status] == 0, " 0-terminated");
-
- memset(result, 'x', sizeof(result));
- status = epicsStrnRawFromEscaped(result, 4, "\\123", 2);
- testOk(status == 1, "raw(\"\\123\", 2) -> %d (exp. 1)", status);
- testOk(result[0] == 1, " Octal escape (got \\%03o)", result[0]);
- testOk(result[status] == 0, " 0-terminated");
-
- memset(result, 'x', sizeof(result));
- status = epicsStrnRawFromEscaped(result, 4, "\\123", 3);
- testOk(status == 1, "raw(\"\\123\", 3) -> %d (exp. 1)", status);
- testOk(result[0] == 012, " Octal escape (got \\%03o)", result[0]);
- testOk(result[status] == 0, " 0-terminated");
-
- memset(result, 'x', sizeof(result));
- status = epicsStrnRawFromEscaped(result, 4, "\\123", 4);
- testOk(status == 1, "raw(\"\\123\", 4) -> %d (exp. 1)", status);
- testOk(result[0] == 0123, " Octal escape (got \\%03o)", result[0]);
- testOk(result[status] == 0, " 0-terminated");
-
- memset(result, 'x', sizeof(result));
- status = epicsStrnRawFromEscaped(result, 4, "\\812", 2);
- testOk(status == 1, "raw(\"\\812\", 2) -> %d (exp. 1)", status);
- testOk(result[0] == '8', " Escaped '%c')", result[0]);
- testOk(result[status] == 0, " 0-terminated");
-
- memset(result, 'x', sizeof(result));
- status = epicsStrnRawFromEscaped(result, 4, "\\182", 3);
- testOk(status == 2, "raw(\"\\182\", 3) -> %d (exp. 2)", status);
- testOk(result[0] == 1, " Octal escape (got \\%03o)", result[0]);
- testOk(result[1] == '8', " Terminated with '%c'", result[1]);
- testOk(result[status] == 0, " 0-terminated");
-
- memset(result, 'x', sizeof(result));
- status = epicsStrnRawFromEscaped(result, 4, "\\128", 4);
- testOk(status == 2, "raw(\"\\128\", 4) -> %d (exp. 2)", status);
- testOk(result[0] == 012, " Octal escape (got \\%03o)", result[0]);
- testOk(result[1] == '8', " Terminator char got '%c'", result[1]);
- testOk(result[status] == 0, " 0-terminated");
-
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\x12", 1);
testOk(status == 0, "raw(\"\\x12\", 1) -> %d (exp. 0)", status);
@@ -306,14 +294,17 @@ MAIN(epicsStringTest)
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\x012", 5);
- testOk(status == 1, "raw(\"\\x012\", 5) -> %d (exp. 1)", status);
- testOk(result[0] == 0x12," Hex escape (got \\x%x)", result[0]);
+ testOk(status == 2, "raw(\"\\x012\", 5) -> %d (exp. 2)", status);
+ testOk(result[0] == 0x1," Hex escape (got \\x%x)", result[0]);
+ testOk(result[1] == '2', " Terminator char got '%c'", result[1]);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
status = epicsStrnRawFromEscaped(result, 4, "\\x0012", 6);
- testOk(status == 1, "raw(\"\\x0012\", 6) -> %d (exp. 1)", status);
- testOk(result[0] == 0x12," Hex escape (got \\x%x)", result[0]);
+ testOk(status == 3, "raw(\"\\x0012\", 6) -> %d (exp. 3)", status);
+ testOk(result[0] == 0," Hex escape (got \\x%x)", result[0]);
+ testOk(result[1] == '1', " Terminator char got '%c'", result[1]);
+ testOk(result[2] == '2', " Following char got '%c'", result[2]);
testOk(result[status] == 0, " 0-terminated");
memset(result, 'x', sizeof(result));
@@ -323,5 +314,7 @@ MAIN(epicsStringTest)
testOk(result[1] == 'g', " Terminator char got '%c'", result[1]);
testOk(result[status] == 0, " 0-terminated");
+ testDistance();
+
return testDone();
}
diff --git a/modules/libcom/test/epicsThreadClassTest.cpp b/modules/libcom/test/epicsThreadClassTest.cpp
index 1dba5ee26..cef5123bc 100644
--- a/modules/libcom/test/epicsThreadClassTest.cpp
+++ b/modules/libcom/test/epicsThreadClassTest.cpp
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2020 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsThreadHooksTest.c b/modules/libcom/test/epicsThreadHooksTest.c
index b6ba833e0..9f49cafb5 100644
--- a/modules/libcom/test/epicsThreadHooksTest.c
+++ b/modules/libcom/test/epicsThreadHooksTest.c
@@ -3,6 +3,7 @@
* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
*
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsThreadOnceTest.c b/modules/libcom/test/epicsThreadOnceTest.c
index 2ecdf3a68..6241e88f6 100644
--- a/modules/libcom/test/epicsThreadOnceTest.c
+++ b/modules/libcom/test/epicsThreadOnceTest.c
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsThreadPerform.cpp b/modules/libcom/test/epicsThreadPerform.cpp
index b73d90c9e..aad3a9e68 100644
--- a/modules/libcom/test/epicsThreadPerform.cpp
+++ b/modules/libcom/test/epicsThreadPerform.cpp
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsThreadPoolTest.c b/modules/libcom/test/epicsThreadPoolTest.c
index b949ec9cd..f54318419 100644
--- a/modules/libcom/test/epicsThreadPoolTest.c
+++ b/modules/libcom/test/epicsThreadPoolTest.c
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2014 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsThreadPriorityTest.cpp b/modules/libcom/test/epicsThreadPriorityTest.cpp
index 4f5a82d9e..88e8521bd 100644
--- a/modules/libcom/test/epicsThreadPriorityTest.cpp
+++ b/modules/libcom/test/epicsThreadPriorityTest.cpp
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsThreadPrivateTest.cpp b/modules/libcom/test/epicsThreadPrivateTest.cpp
index 330b96f81..989a3be42 100644
--- a/modules/libcom/test/epicsThreadPrivateTest.cpp
+++ b/modules/libcom/test/epicsThreadPrivateTest.cpp
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsThreadTest.cpp b/modules/libcom/test/epicsThreadTest.cpp
index 46f116f9c..f0add15a8 100644
--- a/modules/libcom/test/epicsThreadTest.cpp
+++ b/modules/libcom/test/epicsThreadTest.cpp
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsTimeTest.cpp b/modules/libcom/test/epicsTimeTest.cpp
index 8eb8de6d4..3e10e6808 100644
--- a/modules/libcom/test/epicsTimeTest.cpp
+++ b/modules/libcom/test/epicsTimeTest.cpp
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsTimeZoneTest.c b/modules/libcom/test/epicsTimeZoneTest.c
index 685295fc4..4067c3f7d 100644
--- a/modules/libcom/test/epicsTimeZoneTest.c
+++ b/modules/libcom/test/epicsTimeZoneTest.c
@@ -1,5 +1,6 @@
/*************************************************************************\
* Copyright (c) 2015 Michael Davidsaver
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsTimerTest.cpp b/modules/libcom/test/epicsTimerTest.cpp
index 4e1e3e725..d4640b84f 100644
--- a/modules/libcom/test/epicsTimerTest.cpp
+++ b/modules/libcom/test/epicsTimerTest.cpp
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsTypesTest.c b/modules/libcom/test/epicsTypesTest.c
index aa882aa9f..eeaac7bef 100644
--- a/modules/libcom/test/epicsTypesTest.c
+++ b/modules/libcom/test/epicsTypesTest.c
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsUnitTestTest.c b/modules/libcom/test/epicsUnitTestTest.c
index b16bad52a..539d31470 100644
--- a/modules/libcom/test/epicsUnitTestTest.c
+++ b/modules/libcom/test/epicsUnitTestTest.c
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2006 The University of Chicago, as Operator of Argonne
* National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/epicsUnitTestTest.plt b/modules/libcom/test/epicsUnitTestTest.plt
index 1cb9e0c1b..67460e5e2 100644
--- a/modules/libcom/test/epicsUnitTestTest.plt
+++ b/modules/libcom/test/epicsUnitTestTest.plt
@@ -1,4 +1,9 @@
#!/usr/bin/perl
+#*************************************************************************
+# SPDX-License-Identifier: EPICS
+# EPICS BASE is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
+#*************************************************************************
use strict;
use Test;
diff --git a/modules/libcom/test/fdmgrTest.c b/modules/libcom/test/fdmgrTest.c
index 950da0715..a7f91d493 100644
--- a/modules/libcom/test/fdmgrTest.c
+++ b/modules/libcom/test/fdmgrTest.c
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/iocshTest.cpp b/modules/libcom/test/iocshTest.cpp
index 1216ed579..e07bf8686 100644
--- a/modules/libcom/test/iocshTest.cpp
+++ b/modules/libcom/test/iocshTest.cpp
@@ -1,5 +1,6 @@
/*************************************************************************\
* Copyright (c) 2019 Michael Davidsaver
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/ipAddrToAsciiTest.cpp b/modules/libcom/test/ipAddrToAsciiTest.cpp
index f9323374d..7e6b9cc00 100644
--- a/modules/libcom/test/ipAddrToAsciiTest.cpp
+++ b/modules/libcom/test/ipAddrToAsciiTest.cpp
@@ -1,5 +1,6 @@
/*************************************************************************\
* Copyright (c) 2017 Michael Davidsaver
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/macDefExpandTest.c b/modules/libcom/test/macDefExpandTest.c
index 8ce161923..37f11f9f4 100644
--- a/modules/libcom/test/macDefExpandTest.c
+++ b/modules/libcom/test/macDefExpandTest.c
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/macLib.plt b/modules/libcom/test/macLib.plt
index 559f27df8..5c0aa7fa0 100644
--- a/modules/libcom/test/macLib.plt
+++ b/modules/libcom/test/macLib.plt
@@ -1,4 +1,9 @@
#!/usr/bin/perl
+#*************************************************************************
+# SPDX-License-Identifier: EPICS
+# EPICS BASE is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
+#*************************************************************************
use lib '@TOP@/lib/perl';
diff --git a/modules/libcom/test/macLibTest.c b/modules/libcom/test/macLibTest.c
index 742fc79e2..eea6268dd 100644
--- a/modules/libcom/test/macLibTest.c
+++ b/modules/libcom/test/macLibTest.c
@@ -3,6 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
diff --git a/modules/libcom/test/nonEpicsThreadPriorityTest.cpp b/modules/libcom/test/nonEpicsThreadPriorityTest.cpp
index 088f0fca7..a2f9b08f6 100644
--- a/modules/libcom/test/nonEpicsThreadPriorityTest.cpp
+++ b/modules/libcom/test/nonEpicsThreadPriorityTest.cpp
@@ -1,3 +1,9 @@
+/*************************************************************************\
+* SPDX-License-Identifier: EPICS
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+\*************************************************************************/
+
#include
#include "epicsUnitTest.h"
#include "testMain.h"
diff --git a/modules/libcom/test/osiSockTest.c b/modules/libcom/test/osiSockTest.c
index 073a031ee..f2adb41cd 100644
--- a/modules/libcom/test/osiSockTest.c
+++ b/modules/libcom/test/osiSockTest.c
@@ -1,6 +1,7 @@
/*************************************************************************\
* Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
+* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
@@ -220,7 +221,7 @@ void udpSockFanoutTestRx(void* raw)
#else
struct timeval timeout;
memset(&timeout, 0, sizeof(struct timeval));
- timeout.tv_sec = 10;
+ timeout.tv_sec = 5;
timeout.tv_usec = 0;
#endif
@@ -233,7 +234,7 @@ void udpSockFanoutTestRx(void* raw)
return;
}
- while(epicsTimeDiffInSeconds(&now, &start)<=5.0) {
+ while(!epicsTimeGetCurrent(&now) && epicsTimeDiffInSeconds(&now, &start)<=5.0) {
union CASearchU buf;
osiSockAddr src;
osiSocklen_t srclen = sizeof(src);
@@ -258,7 +259,9 @@ void udpSockFanoutTestRx(void* raw)
if(0==--nremain)
break;
} else {
- testDiag("RX ignore");
+ testDiag("RX ignore n=%d cmd=%d size=%d dtype=%d dcnt=%d body=%s",
+ n, ntohs(buf.msg.cmd), ntohs(buf.msg.size),
+ ntohs(buf.msg.dtype), ntohs(buf.msg.dcnt), buf.msg.body);
}
}
testDiag("RX%u end", info->id);
@@ -276,6 +279,7 @@ void udpSockFanoutTestIface(const osiSockAddr* addr)
osiSockAddr any;
epicsUInt32 key = 0xdeadbeef ^ ntohl(addr->ia.sin_addr.s_addr);
union CASearchU buf;
+ int ret;
topts.joinable = 1;
@@ -318,12 +322,17 @@ void udpSockFanoutTestIface(const osiSockAddr* addr)
if(bind(rx2.sock, &any.sa, sizeof(any)))
testFail("Can't bind test socket rx2 %d", (int)SOCKERRNO);
+ /* test to see if send is possible (not EPERM) */
+ ret = sendto(sender, buf.bytes, sizeof(buf.bytes), 0, &addr->sa, sizeof(*addr));
+ if(ret!=(int)sizeof(buf.bytes)) {
+ testDiag("test sendto() error %d (%d)", ret, (int)SOCKERRNO);
+ goto cleanup;
+ }
+
trx1 = epicsThreadCreateOpt("rx1", &udpSockFanoutTestRx, &rx1, &topts);
trx2 = epicsThreadCreateOpt("rx2", &udpSockFanoutTestRx, &rx2, &topts);
for(i=0; i
diff --git a/modules/libcom/test/yajlTestCases.pm b/modules/libcom/test/yajlTestCases.pm
index 40eaff6e7..7d2aff130 100644
--- a/modules/libcom/test/yajlTestCases.pm
+++ b/modules/libcom/test/yajlTestCases.pm
@@ -7,6 +7,300 @@
sub cases {
my $VAR1 = [
+ {
+ name => "codepoints_from_hex",
+ opts => [
+ -5
+ ],
+ input => [
+ "\"\\x0a\\x07\\x21\\x40\\x7c\"",
+ ""
+ ],
+ gives => [
+ "string: '",
+ "\a!\@|'",
+ "memory leaks:\t0"
+ ]
+ },
+ {
+ name => "doubles",
+ opts => [
+ -5
+ ],
+ input => [
+ "[ .1e2, 10., +3.141569, -.1e4, NaN, Infinity, +Infinity, -Infinity ]",
+ ""
+ ],
+ gives => [
+ "array open '['",
+ "double: 10",
+ "double: 10",
+ "double: 3.14157",
+ "double: -1000",
+ "double: NaN",
+ "double: Infinity",
+ "double: Infinity",
+ "double: -Infinity",
+ "array close ']'",
+ "memory leaks:\t0"
+ ]
+ },
+ {
+ name => "integers",
+ opts => [
+ -5
+ ],
+ input => [
+ "[ +1,+2,+3,+4,+5,+6,+7,+8,+9,",
+ " 0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,",
+ " 0xa,0xb,0xc,0xd,0xe,0xf,",
+ " 0xA,0xB,0xC,0xD,0xE,0xF,",
+ " +0xfedcba98, -0x6789ABCD,",
+ " +123456789 , -123456789,",
+ " +2147483647, -2147483648,",
+ " 0x7fffFFFFffffFFFF, -0x7FFFffffFFFFffff,",
+ " 9223372036854775807, -9223372036854775807",
+ "]",
+ ""
+ ],
+ gives => [
+ "array open '['",
+ "integer: 1",
+ "integer: 2",
+ "integer: 3",
+ "integer: 4",
+ "integer: 5",
+ "integer: 6",
+ "integer: 7",
+ "integer: 8",
+ "integer: 9",
+ "integer: 1",
+ "integer: 2",
+ "integer: 3",
+ "integer: 4",
+ "integer: 5",
+ "integer: 6",
+ "integer: 7",
+ "integer: 8",
+ "integer: 9",
+ "integer: 10",
+ "integer: 11",
+ "integer: 12",
+ "integer: 13",
+ "integer: 14",
+ "integer: 15",
+ "integer: 10",
+ "integer: 11",
+ "integer: 12",
+ "integer: 13",
+ "integer: 14",
+ "integer: 15",
+ "integer: 4275878552",
+ "integer: -1737075661",
+ "integer: 123456789",
+ "integer: -123456789",
+ "integer: 2147483647",
+ "integer: -2147483648",
+ "integer: 9223372036854775807",
+ "integer: -9223372036854775807",
+ "integer: 9223372036854775807",
+ "integer: -9223372036854775807",
+ "array close ']'",
+ "memory leaks:\t0"
+ ]
+ },
+ {
+ name => "invalid_hex_char",
+ opts => [
+ -5
+ ],
+ input => [
+ "\"yabba dabba do \\x1g !!\"",
+ ""
+ ],
+ gives => [
+ "lexical error: invalid (non-hex) character occurs after '\\x' inside string.",
+ "memory leaks:\t0"
+ ]
+ },
+ {
+ name => "map_identifiers",
+ opts => [
+ -5
+ ],
+ input => [
+ "{",
+ " \$:1,",
+ " _:2,",
+ " A:3,",
+ " Z:4,",
+ " a:5,",
+ " z:6,",
+ " \$1:7,",
+ " _zz:8,",
+ " ZZ9\$Zalpha:9",
+ "}",
+ ""
+ ],
+ gives => [
+ "map open '{'",
+ "key: '\$'",
+ "integer: 1",
+ "key: '_'",
+ "integer: 2",
+ "key: 'A'",
+ "integer: 3",
+ "key: 'Z'",
+ "integer: 4",
+ "key: 'a'",
+ "integer: 5",
+ "key: 'z'",
+ "integer: 6",
+ "key: '\$1'",
+ "integer: 7",
+ "key: '_zz'",
+ "integer: 8",
+ "key: 'ZZ9\$Zalpha'",
+ "integer: 9",
+ "map close '}'",
+ "memory leaks:\t0"
+ ]
+ },
+ {
+ name => "simple_with_comments",
+ opts => [
+ -5
+ ],
+ input => [
+ "{",
+ " \"this\": \"is\", // ignore this",
+ " \"really\": \"simple\",",
+ " /* ignore",
+ "this",
+ "too * / ",
+ "** //",
+ "(/",
+ "******/",
+ " \"json\": \"right?\"",
+ "}",
+ ""
+ ],
+ gives => [
+ "map open '{'",
+ "key: 'this'",
+ "string: 'is'",
+ "key: 'really'",
+ "string: 'simple'",
+ "key: 'json'",
+ "string: 'right?'",
+ "map close '}'",
+ "memory leaks:\t0"
+ ]
+ },
+ {
+ name => "spec_example",
+ opts => [
+ -5
+ ],
+ input => [
+ "{",
+ " // comments",
+ " unquoted: 'and you can quote me on that',",
+ " singleQuotes: 'I can use \"double quotes\" here',",
+ " lineBreaks: \"Look, Mom! \\",
+ "No \\\\n's!\",",
+ " hexadecimal: 0xdecaf,",
+ " leadingDecimalPoint: .8675309, andTrailing: 8675309.,",
+ " positiveSign: +1,",
+ " trailingComma: 'in objects', andIn: ['arrays',],",
+ " \"backwardsCompatible\": \"with JSON\",",
+ "}",
+ ""
+ ],
+ gives => [
+ "map open '{'",
+ "key: 'unquoted'",
+ "string: 'and you can quote me on that'",
+ "key: 'singleQuotes'",
+ "string: 'I can use \"double quotes\" here'",
+ "key: 'lineBreaks'",
+ "string: 'Look, Mom! No \\n's!'",
+ "key: 'hexadecimal'",
+ "integer: 912559",
+ "key: 'leadingDecimalPoint'",
+ "double: 0.867531",
+ "key: 'andTrailing'",
+ "double: 8.67531e+06",
+ "key: 'positiveSign'",
+ "integer: 1",
+ "key: 'trailingComma'",
+ "string: 'in objects'",
+ "key: 'andIn'",
+ "array open '['",
+ "string: 'arrays'",
+ "array close ']'",
+ "key: 'backwardsCompatible'",
+ "string: 'with JSON'",
+ "map close '}'",
+ "memory leaks:\t0"
+ ]
+ },
+ {
+ name => "strings",
+ opts => [
+ -5
+ ],
+ input => [
+ "[",
+ " 'Hello\\!',",
+ " \"\\\"Evenin\\',\\\" said the barman.\",",
+ " // The following string has 3 different escaped line-endings,",
+ " // LF, CR, and CR+LF, which all disappear from the final string.",
+ " \"Well \\",
+ "hi \\\rthere \\\r",
+ "y'all!\",",
+ " \"\\b\\f\\n\\r\\t\\v\\\\\",",
+ " '\\A\\C\\/\\D\\C',",
+ "]",
+ ""
+ ],
+ gives => [
+ "array open '['",
+ "string: 'Hello!'",
+ "string: '\"Evenin',\" said the barman.'",
+ "string: 'Well hi there y'all!'",
+ "string: '\b\f",
+ "\r\t\13\\'",
+ "string: 'AC/DC'",
+ "array close ']'",
+ "memory leaks:\t0"
+ ]
+ },
+ {
+ name => "trailing_commas",
+ opts => [
+ -5
+ ],
+ input => [
+ "{\"array\":[1,2,],\"map\":{\"a\":1,},}",
+ ""
+ ],
+ gives => [
+ "map open '{'",
+ "key: 'array'",
+ "array open '['",
+ "integer: 1",
+ "integer: 2",
+ "array close ']'",
+ "key: 'map'",
+ "map open '{'",
+ "key: 'a'",
+ "integer: 1",
+ "map close '}'",
+ "map close '}'",
+ "memory leaks:\t0"
+ ]
+ },
{
name => "difficult_json_c_test_case_with_comments",
opts => [
@@ -2636,6 +2930,18 @@ sub cases {
"memory leaks:\t0"
]
},
+ {
+ name => "hex",
+ opts => [],
+ input => [
+ "0x1",
+ ""
+ ],
+ gives => [
+ "lexical error: probable hex number found, JSON5 is not enabled.",
+ "memory leaks:\t0"
+ ]
+ },
{
name => "high_overflow",
opts => [],
@@ -2647,6 +2953,18 @@ sub cases {
"memory leaks:\t0"
]
},
+ {
+ name => "infinity",
+ opts => [],
+ input => [
+ "Infinity",
+ ""
+ ],
+ gives => [
+ "lexical error: special number Infinity or NaN found, JSON5 is not enabled.",
+ "memory leaks:\t0"
+ ]
+ },
{
name => "integers",
opts => [],
@@ -2733,7 +3051,7 @@ sub cases {
"string: 'blue'",
"string: 'baby where are you?'",
"string: 'oh boo hoo!'",
- "lexical error: malformed number, a digit is required after the minus sign.",
+ "lexical error: malformed number, a digit is required after the plus/minus sign.",
"memory leaks:\t0"
]
},
@@ -2771,6 +3089,18 @@ sub cases {
"memory leaks:\t0"
]
},
+ {
+ name => "minus_infinity",
+ opts => [],
+ input => [
+ "-Infinity",
+ ""
+ ],
+ gives => [
+ "lexical error: special number Infinity or NaN found, JSON5 is not enabled.",
+ "memory leaks:\t0"
+ ]
+ },
{
name => "missing_integer_after_decimal_point",
opts => [],
@@ -2811,6 +3141,18 @@ sub cases {
"memory leaks:\t0"
]
},
+ {
+ name => "nan",
+ opts => [],
+ input => [
+ "NaN",
+ ""
+ ],
+ gives => [
+ "lexical error: special number Infinity or NaN found, JSON5 is not enabled.",
+ "memory leaks:\t0"
+ ]
+ },
{
name => "non_utf8_char_in_string",
opts => [],
@@ -3000,29 +3342,6 @@ sub cases {
"memory leaks:\t0"
]
},
- {
- name => "trailing_commas",
- opts => [],
- input => [
- "{\"array\":[1,2,],\"map\":{\"a\":1,},}",
- ""
- ],
- gives => [
- "map open '{'",
- "key: 'array'",
- "array open '['",
- "integer: 1",
- "integer: 2",
- "array close ']'",
- "key: 'map'",
- "map open '{'",
- "key: 'a'",
- "integer: 1",
- "map close '}'",
- "map close '}'",
- "memory leaks:\t0"
- ]
- },
{
name => "true",
opts => [],
diff --git a/modules/libcom/test/yajlTestConverter.pl b/modules/libcom/test/yajlTestConverter.pl
index c3d2b54b6..31413a6bd 100755
--- a/modules/libcom/test/yajlTestConverter.pl
+++ b/modules/libcom/test/yajlTestConverter.pl
@@ -22,14 +22,17 @@ my $caseFile = 'yajlTestCases.pm';
my @cases;
for my $file (@files) {
- $file =~ m|/([afn][cgmp]_)?([^/]*)\.json$|;
+ $file =~ m|/([afn][5cgmp]_)?([^/]*)\.json$|;
my $allow = $1;
my $name = $2;
next if $name eq '';
my $case = { name => $name };
- if ($allow eq 'ac_') {
+ if ($allow eq 'a5_') {
+ $case->{opts} = ['-5'];
+ }
+ elsif ($allow eq 'ac_') {
$case->{opts} = ['-c'];
}
elsif ($allow eq 'ag_') {
diff --git a/modules/libcom/test/yajl_test.c b/modules/libcom/test/yajl_test.c
index cacfdcb5c..be92aecfd 100644
--- a/modules/libcom/test/yajl_test.c
+++ b/modules/libcom/test/yajl_test.c
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
#include
#include
@@ -85,7 +86,15 @@ static int test_yajl_integer(void *ctx, long long integerVal)
static int test_yajl_double(void *ctx, double doubleVal)
{
- printf("double: %g\n", doubleVal);
+ if (isnan(doubleVal)) {
+ printf("double: NaN\n");
+ }
+ else if (isinf(doubleVal)) {
+ printf("double: %sInfinity\n", doubleVal > 0 ? "" : "-");
+ }
+ else {
+ printf("double: %g\n", doubleVal);
+ }
return 1;
}
@@ -154,6 +163,7 @@ static void usage(const char * progname)
"usage: %s [options]\n"
"Parse input from stdin as JSON and ouput parsing details "
"to stdout\n"
+ " -5 allow JSON5\n"
" -b set the read buffer size\n"
" -c allow comments\n"
" -g allow *g*arbage after valid JSON text\n"
@@ -195,9 +205,14 @@ main(int argc, char ** argv)
/* allocate the parser */
hand = yajl_alloc(&callbacks, &allocFuncs, NULL);
+ /* turn off JSON5 (the EPICS default) */
+ yajl_config(hand, yajl_allow_json5, 0);
+
/* check arguments. We expect exactly one! */
for (i=1;i= argc) usage(argv[0]);
diff --git a/modules/normativeTypes b/modules/normativeTypes
index 7a2d264f2..1250a3c23 160000
--- a/modules/normativeTypes
+++ b/modules/normativeTypes
@@ -1 +1 @@
-Subproject commit 7a2d264f2cb107bfd10adb23bc2b73d8323a79e4
+Subproject commit 1250a3c236f0aa92e0b5bd73647fd71d8a09360d
diff --git a/modules/pvAccess b/modules/pvAccess
index 4e85d38bb..64c284cd4 160000
--- a/modules/pvAccess
+++ b/modules/pvAccess
@@ -1 +1 @@
-Subproject commit 4e85d38bbad1c1562ea34bdd18bc1964fb00350b
+Subproject commit 64c284cd41f114ee07e999a94ff55ae53a87c7e0
diff --git a/modules/pvData b/modules/pvData
index 0fa927afa..b1c830387 160000
--- a/modules/pvData
+++ b/modules/pvData
@@ -1 +1 @@
-Subproject commit 0fa927afa7d92f490f92eb4906e27046080309e2
+Subproject commit b1c8303870a04f1c3ee5a01a84aad2b2596e918c
diff --git a/modules/pvDatabase b/modules/pvDatabase
index cb5d9f976..09423edea 160000
--- a/modules/pvDatabase
+++ b/modules/pvDatabase
@@ -1 +1 @@
-Subproject commit cb5d9f976a2433f87a48bcd8b3de83dd05d26fcc
+Subproject commit 09423edeabc4b46c0ff3a6a09c8c1268e3de291f
diff --git a/modules/pva2pva b/modules/pva2pva
index 94d1eedc7..b8389ac6a 160000
--- a/modules/pva2pva
+++ b/modules/pva2pva
@@ -1 +1 @@
-Subproject commit 94d1eedc7536f7b5eacdcfb81cf6b8a306b9687f
+Subproject commit b8389ac6a19679fe515fd74cddeb1e02467b1007
diff --git a/modules/pvaClient b/modules/pvaClient
index 7722fdf35..bc9ac8422 160000
--- a/modules/pvaClient
+++ b/modules/pvaClient
@@ -1 +1 @@
-Subproject commit 7722fdf353b54b681a2d883c36374aa0211241ef
+Subproject commit bc9ac8422cb94a38c27385c3c6781aea30c2c8b8
diff --git a/src/template/ext/top/configure/RULES_JAVA b/src/template/ext/top/configure/RULES_JAVA
index b6ffa3f0f..e33ab3ce2 100644
--- a/src/template/ext/top/configure/RULES_JAVA
+++ b/src/template/ext/top/configure/RULES_JAVA
@@ -3,8 +3,8 @@
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
-# EPICS BASE Versions 3.13.7
-# and higher are distributed subject to a Software License Agreement found
+# SPDX-License-Identifier: EPICS
+# EPICS Base is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/EPICS/Copy.pm b/src/tools/EPICS/Copy.pm
index e1ef2a54e..827fe33ca 100644
--- a/src/tools/EPICS/Copy.pm
+++ b/src/tools/EPICS/Copy.pm
@@ -1,6 +1,7 @@
#*************************************************************************
# Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/EPICS/Path.pm b/src/tools/EPICS/Path.pm
index b86c88007..687ef0f17 100644
--- a/src/tools/EPICS/Path.pm
+++ b/src/tools/EPICS/Path.pm
@@ -1,6 +1,7 @@
#*************************************************************************
# Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/EPICS/Readfile.pm b/src/tools/EPICS/Readfile.pm
index c73f1925a..b6235af7f 100644
--- a/src/tools/EPICS/Readfile.pm
+++ b/src/tools/EPICS/Readfile.pm
@@ -1,6 +1,7 @@
#*************************************************************************
# Copyright (c) 2015 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/EPICS/Release.pm b/src/tools/EPICS/Release.pm
index b7135b20c..7caa6f4c6 100644
--- a/src/tools/EPICS/Release.pm
+++ b/src/tools/EPICS/Release.pm
@@ -1,6 +1,7 @@
#*************************************************************************
# Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
@@ -57,12 +58,32 @@ sub readRelease {
while (<$IN>) {
chomp;
s/ \r $//x; # Shouldn't need this, but sometimes...
+ s/^ \s+ //x; # Remove leading whitespace
+ next if m/^ $/x; # Skip blank lines
s/ # .* $//x; # Remove trailing comments
s/ \s+ $//x; # Remove trailing whitespace
- next if m/^ \s* $/x; # Skip blank lines
+
+ # Handle "undefine "
+ my ($uvar) = m/^ undefine \s+ ($MVAR)/x;
+ if ($uvar ne '') {
+ delete $Rmacros->{$uvar};
+ next;
+ }
+
+ # Handle "include " and "-include " syntax
+ my ($op, $path) = m/^ (-? include) \s+ (.*)/x;
+ if ($op ne '') {
+ $path = expandMacros($path, $Rmacros);
+ if (-e $path) {
+ &readRelease($path, $Rmacros, $Rapps, $Ractive);
+ } elsif ($op eq "include") {
+ warn "EPICS/Release.pm: Include file '$path' not found\n";
+ }
+ next;
+ }
# Handle " = " plus the := and ?= variants
- my ($var, $op, $val) = m/^ \s* ($MVAR) \s* ([?:]?=) \s* (.*) /x;
+ my ($var, $op, $val) = m/^ ($MVAR) \s* ([?:]?=) \s* (.*) /x;
if ($var ne '') {
$var = 'TOP' if $var =~ m/^ INSTALL_LOCATION /x;
if (exists $Rmacros->{$var}) {
@@ -74,14 +95,6 @@ sub readRelease {
$Rmacros->{$var} = $val;
next;
}
- # Handle "include " and "-include " syntax
- my ($op, $path) = m/^ \s* (-? include) \s+ (.*)/x;
- $path = expandMacros($path, $Rmacros);
- if (-e $path) {
- &readRelease($path, $Rmacros, $Rapps, $Ractive);
- } elsif ($op eq "include") {
- warn "EPICS/Release.pm: Include file '$path' not found\n";
- }
}
$Ractive->{$file}--;
close $IN;
diff --git a/src/tools/EpicsHostArch.pl b/src/tools/EpicsHostArch.pl
index e8e49bc5e..52c427253 100644
--- a/src/tools/EpicsHostArch.pl
+++ b/src/tools/EpicsHostArch.pl
@@ -2,6 +2,7 @@
#*************************************************************************
# Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
@@ -34,6 +35,7 @@ sub HostArch {
return 'linux-x86_64' if m/^x86_64-linux/;
return 'linux-x86' if m/^i[3-6]86-linux/;
return 'linux-arm' if m/^arm-linux/;
+ return 'linux-aarch64' if m/^aarch64-linux/;
return 'windows-x64' if m/^MSWin32-x64/;
return 'win32-x86' if m/^MSWin32-x86/;
return "cygwin-x86_64" if m/^x86_64-cygwin/;
@@ -44,8 +46,9 @@ sub HostArch {
my ($kernel, $hostname, $release, $version, $cpu) = uname;
if (m/^darwin/) {
for ($cpu) {
- return 'darwin-x86' if m/^(i386|x86_64)/;
- return 'darwin-ppc' if m/Power Macintosh/;
+ return 'darwin-x86' if m/^(i386|x86_64)/;
+ return 'darwin-ppc' if m/Power Macintosh/;
+ return 'darwin-aarch64' if m/arm64/;
}
die "$0: macOS CPU type '$cpu' not recognized\n";
}
diff --git a/src/tools/assembleSnippets.pl b/src/tools/assembleSnippets.pl
index e6f0c77a3..66a085dc1 100644
--- a/src/tools/assembleSnippets.pl
+++ b/src/tools/assembleSnippets.pl
@@ -1,6 +1,7 @@
#!/usr/bin/env perl
#*************************************************************************
# Copyright (c) 2015 ITER Organization.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/convertRelease.pl b/src/tools/convertRelease.pl
index 87a1267c0..3375eb4f2 100644
--- a/src/tools/convertRelease.pl
+++ b/src/tools/convertRelease.pl
@@ -4,6 +4,7 @@
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/cvsclean.pl b/src/tools/cvsclean.pl
index 8dac418d7..e87f3c3f5 100644
--- a/src/tools/cvsclean.pl
+++ b/src/tools/cvsclean.pl
@@ -4,7 +4,8 @@
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
-# This file is distributed subject to a Software License Agreement found
+# SPDX-License-Identifier: EPICS
+# EPICS Base is distributed subject to a Software License Agreement found
# in the file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/depclean.pl b/src/tools/depclean.pl
index cbf6077d1..ac368abea 100644
--- a/src/tools/depclean.pl
+++ b/src/tools/depclean.pl
@@ -2,7 +2,8 @@
#*************************************************************************
# Copyright (c) 2018 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
-# This file is distributed subject to a Software License Agreement found
+# SPDX-License-Identifier: EPICS
+# EPICS Base is distributed subject to a Software License Agreement found
# in the file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/dos2unix.pl b/src/tools/dos2unix.pl
index c88704c4b..cae9e6393 100644
--- a/src/tools/dos2unix.pl
+++ b/src/tools/dos2unix.pl
@@ -4,9 +4,9 @@
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
-# EPICS BASE Versions 3.13.7
-# and higher are distributed subject to a Software License Agreement found
-# in file LICENSE that is included with this distribution.
+# SPDX-License-Identifier: EPICS
+# EPICS Base is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
#*************************************************************************
# Converts text file in DOS CR/LF format to unix ISO format
diff --git a/src/tools/epicsProve.pl b/src/tools/epicsProve.pl
index 65a30dfea..ecfb80584 100644
--- a/src/tools/epicsProve.pl
+++ b/src/tools/epicsProve.pl
@@ -1,8 +1,11 @@
#!/usr/bin/env perl
+#*************************************************************************
+# SPDX-License-Identifier: EPICS
+# EPICS BASE is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
+#*************************************************************************
-# Some Windows Perl installations provide a prove.bat file which
-# doesn't work properly. This also lets us make the output stand
-# out a bit more.
+# Portable test-runner to make the output stand out a bit more.
use strict;
use warnings;
@@ -14,9 +17,9 @@ my $path = abs_path('.');
printf "\n%s\n%s\n", '-' x length($path), $path;
-my $app = App::Prove->new;
-$app->process_args(@ARGV);
-my $res = $app->run;
+my $prover = App::Prove->new;
+$prover->process_args(@ARGV);
+my $res = $prover->run;
print "-------------------\n\n";
diff --git a/src/tools/expandVars.pl b/src/tools/expandVars.pl
index 855aca329..ec4275476 100644
--- a/src/tools/expandVars.pl
+++ b/src/tools/expandVars.pl
@@ -1,5 +1,12 @@
#!/usr/bin/env perl
-#
+#*************************************************************************
+# Copyright (c) 2005 UChicago Argonne LLC, as Operator of Argonne
+# National Laboratory.
+# SPDX-License-Identifier: EPICS
+# EPICS BASE is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
+#*************************************************************************
+
# Tool to expand @VAR@ variables while copying a file.
# The file will *not* be copied if it already exists.
#
diff --git a/src/tools/fullPathName.pl b/src/tools/fullPathName.pl
index 20ef6d231..2688e504f 100644
--- a/src/tools/fullPathName.pl
+++ b/src/tools/fullPathName.pl
@@ -2,6 +2,7 @@
#*************************************************************************
# Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/genVersionHeader.pl b/src/tools/genVersionHeader.pl
index 24e08abf9..2466aef6b 100644
--- a/src/tools/genVersionHeader.pl
+++ b/src/tools/genVersionHeader.pl
@@ -1,6 +1,7 @@
#!/usr/bin/env perl
#*************************************************************************
# Copyright (c) 2014 Brookhaven National Laboratory.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/installEpics.pl b/src/tools/installEpics.pl
index c64324f37..6cd06e801 100644
--- a/src/tools/installEpics.pl
+++ b/src/tools/installEpics.pl
@@ -4,6 +4,7 @@
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/makeAPIheader.pl b/src/tools/makeAPIheader.pl
index 4ebbeea9e..297946ff4 100644
--- a/src/tools/makeAPIheader.pl
+++ b/src/tools/makeAPIheader.pl
@@ -1,4 +1,11 @@
#!/usr/bin/env perl
+#*************************************************************************
+# Copyright (c) 2020 UChicago Argonne LLC, as Operator of Argonne
+# National Laboratory.
+# SPDX-License-Identifier: EPICS
+# EPICS BASE is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
+#*************************************************************************
use strict;
use warnings;
diff --git a/src/tools/makeMakefile.pl b/src/tools/makeMakefile.pl
index 0ba7c82a7..615e356d1 100644
--- a/src/tools/makeMakefile.pl
+++ b/src/tools/makeMakefile.pl
@@ -4,9 +4,9 @@
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
-# EPICS BASE Versions 3.13.7
-# and higher are distributed subject to a Software License Agreement found
-# in file LICENSE that is included with this distribution.
+# SPDX-License-Identifier: EPICS
+# EPICS Base is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
#*************************************************************************
#
# makeMakefile.pl
diff --git a/src/tools/makeRPath.py b/src/tools/makeRPath.py
index 89590e8df..ec024e2a9 100644
--- a/src/tools/makeRPath.py
+++ b/src/tools/makeRPath.py
@@ -1,4 +1,9 @@
#!/usr/bin/env python
+#*************************************************************************
+# SPDX-License-Identifier: EPICS
+# EPICS BASE is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
+#*************************************************************************
from __future__ import print_function
diff --git a/src/tools/makeTestfile.pl b/src/tools/makeTestfile.pl
index 7d298768f..7a8234962 100644
--- a/src/tools/makeTestfile.pl
+++ b/src/tools/makeTestfile.pl
@@ -4,6 +4,7 @@
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
@@ -48,6 +49,28 @@ if( $TA =~ /^win32-x86/ && $HA !~ /^win/ ) {
$exec = "./$exe";
}
+# Ensure that Windows interactive error handling is disabled.
+# This setting is inherited by the test process.
+# Set SEM_FAILCRITICALERRORS (1) Disable critical-error-handler dialog
+# Clear SEM_NOGPFAULTERRORBOX (2) Enabled WER to allow automatic post mortem debugging (AeDebug)
+# Clear SEM_NOALIGNMENTFAULTEXCEPT (4) Allow alignment fixups
+# Set SEM_NOOPENFILEERRORBOX (0x8000) Prevent dialog on some I/O errors
+# https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-seterrormode?redirectedfrom=MSDN
+my $sem = $^O ne 'MSWin32' ? '' : <import(\$sem);
+ };
+ eval {
+ require Win32API::File;
+ Win32API::File->import(\$sem);
+ } if \$@;
+ SetErrorMode(0x8001) unless \$@;
+}
+ENDBEGIN
+
open(my $OUT, '>', $target) or die "Can't create $target: $!\n";
print $OUT <> 8;
+}
+else {
+ exec '$exec' or die "Can't run $exec: \$!\\n";
+}
EOF
close $OUT or die "Can't close $target: $!\n";
diff --git a/src/tools/mkmf.pl b/src/tools/mkmf.pl
index b066edeb4..00483a2f1 100644
--- a/src/tools/mkmf.pl
+++ b/src/tools/mkmf.pl
@@ -5,6 +5,7 @@
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/munch.pl b/src/tools/munch.pl
index f62b579ad..31d814990 100644
--- a/src/tools/munch.pl
+++ b/src/tools/munch.pl
@@ -4,6 +4,7 @@
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in the file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/podRemove.pl b/src/tools/podRemove.pl
index ae77f7b41..e328994e3 100644
--- a/src/tools/podRemove.pl
+++ b/src/tools/podRemove.pl
@@ -2,6 +2,7 @@
#*************************************************************************
# Copyright (c) 2015 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/podToHtml.pl b/src/tools/podToHtml.pl
index a6698dac4..63f4e4a00 100644
--- a/src/tools/podToHtml.pl
+++ b/src/tools/podToHtml.pl
@@ -2,6 +2,7 @@
#*************************************************************************
# Copyright (c) 2013 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/replaceVAR.pl b/src/tools/replaceVAR.pl
index 82c76bb3d..7dd75aef4 100644
--- a/src/tools/replaceVAR.pl
+++ b/src/tools/replaceVAR.pl
@@ -4,8 +4,8 @@
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
-# EPICS BASE Versions 3.13.7
-# and higher are distributed subject to a Software License Agreement found
+# SPDX-License-Identifier: EPICS
+# EPICS Base is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
diff --git a/src/tools/testFailures.pl b/src/tools/testFailures.pl
index 3007957e3..eeddc74a1 100644
--- a/src/tools/testFailures.pl
+++ b/src/tools/testFailures.pl
@@ -1,38 +1,54 @@
#!/usr/bin/env perl
#*************************************************************************
+# SPDX-License-Identifier: EPICS
# EPICS BASE is distributed subject to a Software License Agreement found
# in the file LICENSE that is included with this distribution.
#*************************************************************************
-# This file may appear trivial, but it exists to let the build system
-# fail the 'make test-results' target with a nice output including a
-# summary of the directories where test failures were reported.
-# Test results are collected from the .tap files fed to epicsProve.pl
-# which returns with an exit status of 0 (success) if all tests passed
-# or 1 (failure) if any of the .tap files contained failed tests.
-# When epicsProve.pl indicates a failure, the directory that it was
-# running in is appended to the file $(TOP)/.tests-failed which this
-# program reads in after all the test directories have been visited.
+# This file lets the build system fail a top-level 'make test-results'
+# target with output showing the directories where test failures were
+# reported and the test programs that failed there.
+#
# The exit status of this program is 1 (failure) if any tests failed,
# otherwise 0 (success).
use strict;
use warnings;
-die "Usage: testFailures.pl .tests-failed\n"
- unless @ARGV == 1;
+use File::Basename;
+
+die "Usage: testFailures.pl /path/to/top/.tests-failed.log .taps-failed.log\n"
+ unless @ARGV == 2;
+
+my ($dirlog, $faillog) = @ARGV;
+my $top = dirname($dirlog);
# No file means success.
-open FAILURES, '<', shift or
+open(my $logfile, '<', $dirlog) or
exit 0;
-chomp(my @failures = );
-close FAILURES;
+my @faildirs = dedup(<$logfile>);
+close $logfile;
+chomp @faildirs;
-# A file with just empty lines also mean success
-my @dirs = grep {$_} @failures;
-exit 0 unless @dirs;
+# Empty file also means success.
+exit 0 unless grep {$_} @faildirs;
-print "\nTest failures were reported in:\n",
- (map {" $_\n"} @dirs), "\n\n";
+print "\nTests failed in:\n";
+for my $dir (@faildirs) {
+ my $reldir = $dir;
+ $reldir =~ s($top/)();
+ print " $reldir\n";
+ open(my $taplog, '<', "$dir/$faillog") or next;
+ my @taps = dedup(<$taplog>);
+ close $taplog;
+ chomp @taps;
+ print '', (map {" $_\n"} @taps), "\n";
+}
exit 1;
+
+sub dedup {
+ my %dedup;
+ $dedup{$_}++ for @_;
+ return sort keys %dedup;
+}
diff --git a/src/tools/useManifestTool.pl b/src/tools/useManifestTool.pl
index 9e59e9f1f..513000f7a 100644
--- a/src/tools/useManifestTool.pl
+++ b/src/tools/useManifestTool.pl
@@ -1,4 +1,9 @@
#!/usr/bin/env perl
+#*************************************************************************
+# SPDX-License-Identifier: EPICS
+# EPICS BASE is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
+#*************************************************************************
#
# Use MS Visual C++ compiler version number to determine if
# we want to use the Manifest Tool (status=1) or not (status=0)
diff --git a/startup/EpicsHostArch b/startup/EpicsHostArch
index 99b01d8be..b13d1688d 100755
--- a/startup/EpicsHostArch
+++ b/startup/EpicsHostArch
@@ -1,4 +1,10 @@
#!/bin/sh
+#*************************************************************************
+# SPDX-License-Identifier: EPICS
+# EPICS BASE is distributed subject to a Software License Agreement found
+# in file LICENSE that is included with this distribution.
+#*************************************************************************
+
# Script to find and run the Perl EpicsHostArch.pl script.
# This script is provided for backwards-compatibility only and may be
diff --git a/startup/unix.csh b/startup/unix.csh
index 788a639e6..29a683ba3 100644
--- a/startup/unix.csh
+++ b/startup/unix.csh
@@ -3,8 +3,8 @@
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
-# EPICS BASE Versions 3.13.7
-# and higher are distributed subject to a Software License Agreement found
+# SPDX-License-Identifier: EPICS
+# EPICS Base is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
#
diff --git a/startup/unix.sh b/startup/unix.sh
index a8d8328ec..16b1455dd 100644
--- a/startup/unix.sh
+++ b/startup/unix.sh
@@ -3,8 +3,8 @@
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
-# EPICS BASE Versions 3.13.7
-# and higher are distributed subject to a Software License Agreement found
+# SPDX-License-Identifier: EPICS
+# EPICS Base is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
#
diff --git a/startup/win32.bat b/startup/win32.bat
index 6652fc97c..dc50e6a72 100755
--- a/startup/win32.bat
+++ b/startup/win32.bat
@@ -4,6 +4,7 @@ rem Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne
rem National Laboratory.
rem Copyright (c) 2002 The Regents of the University of California, as
rem Operator of Los Alamos National Laboratory.
+rem SPDX-License-Identifier: EPICS
rem EPICS BASE is distributed subject to a Software License Agreement found
rem in file LICENSE that is included with this distribution.
rem *************************************************************************
@@ -53,7 +54,7 @@ rem Strawberry Perl will be added to PATH.
set _strawberry_perl_home=C:\Strawberry
rem The location of Microsoft Visual Studio (pathname).
-set _visual_studio_home=C:\Program Files (x86)\Microsoft Visual Studio 14.0
+set _visual_studio_home=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community
rem The EPICS host architecture specification for EPICS_HOST_ARCH
rem (-[-] as defined in configure/CONFIG_SITE).
@@ -82,7 +83,7 @@ set "PATH=%PATH%;%_strawberry_perl_home%\perl\bin"
:after_add_strawberry_perl
rem Set the environment for Microsoft Visual Studio
-call "%_visual_studio_home%\VC\vcvarsall.bat" x86
+call "%_visual_studio_home%\VC\Auxiliary\Build\vcvarsall.bat" x86
rem Set the EPICS host architecture specification
set "EPICS_HOST_ARCH=%_epics_host_arch%"
diff --git a/startup/windows.bat b/startup/windows.bat
index 877c0d5a9..a36e43fdb 100644
--- a/startup/windows.bat
+++ b/startup/windows.bat
@@ -4,6 +4,7 @@ rem Copyright (c) 2017 UChicago Argonne LLC, as Operator of Argonne
rem National Laboratory.
rem Copyright (c) 2002 The Regents of the University of California, as
rem Operator of Los Alamos National Laboratory.
+rem SPDX-License-Identifier: EPICS
rem EPICS BASE is distributed subject to a Software License Agreement found
rem in file LICENSE that is included with this distribution.
rem *************************************************************************
@@ -53,7 +54,7 @@ rem Strawberry Perl will be added to PATH.
set _strawberry_perl_home=C:\Strawberry
rem The location of Microsoft Visual Studio (pathname).
-set _visual_studio_home=C:\Program Files (x86)\Microsoft Visual Studio 14.0
+set _visual_studio_home=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community
rem The EPICS host architecture specification for EPICS_HOST_ARCH
rem (-[-] as defined in configure/CONFIG_SITE).
@@ -82,7 +83,7 @@ set "PATH=%PATH%;%_strawberry_perl_home%\perl\bin"
:after_add_strawberry_perl
rem Set the environment for Microsoft Visual Studio
-call "%_visual_studio_home%\VC\vcvarsall.bat" x64
+call "%_visual_studio_home%\VC\Auxiliary\Build\vcvarsall.bat" x64
rem Set the EPICS host architecture specification
set "EPICS_HOST_ARCH=%_epics_host_arch%"
diff --git a/test/tools/Snippets.plt b/test/tools/Snippets.plt
index ed86fdb2e..cee77526d 100644
--- a/test/tools/Snippets.plt
+++ b/test/tools/Snippets.plt
@@ -1,4 +1,9 @@
#!/usr/bin/env perl
+######################################################################
+# SPDX-License-Identifier: EPICS
+# EPICS BASE is distributed subject to a Software License Agreement
+# found in file LICENSE that is included with this distribution.
+######################################################################
use File::Path;
use Sys::Hostname;