Author: Andy Green Date: Sat Sep 12 17:09:07 2026 +0100 lejp: opt in to '#' comments for .sai.json and the /etc/sai conf parsers lws 7144156ef made lejp's '#' to-end-of-line comment extension opt-in (LEJP_FLAG_FEAT_COMMENTS), so sai-server built against current lws rejects every notification whose .sai.json carries a comment: sai_notification_file_upload_cb: saifile JSON 1 decode failed 'Expected '"'' (-4) README-sai-json.md documents that comments are allowed, and the builder / device / power / virt conf files are the same hand-edited style, so set the flag on those parsers via a sai_lejp_enable_comments() helper that is a no-op on older lws without the flag. The server and web confs already go through lws's lwsws config parser, which opts in itself. Co-Authored-By: Claude Fable 5.1 diff --git a/src/builder/b-conf.c b/src/builder/b-conf.c index 397ea41..8e237f0 100644 --- a/src/builder/b-conf.c +++ b/src/builder/b-conf.c @@ -367,6 +367,7 @@ saib_config_global(struct sai_builder *builder, const char *d) lwsl_info("%s: %s\n", __func__, (char *)buf); lejp_construct(&ctx, saib_conf_global_cb, &a, paths_global, LWS_ARRAY_SIZE(paths_global)); + sai_lejp_enable_comments(&ctx); do { n = (int)read(fd, buf, sizeof(buf)); @@ -407,6 +408,7 @@ saib_config(struct sai_builder *builder, const char *d) } lwsl_notice("%s: %s\n", __func__, (char *)buf); lejp_construct(&ctx, saib_conf_cb, &a, paths, LWS_ARRAY_SIZE(paths)); + sai_lejp_enable_comments(&ctx); do { n = (int)read(fd, buf, sizeof(buf)); diff --git a/src/common/include/private.h b/src/common/include/private.h index e33b865..fbd2787 100644 --- a/src/common/include/private.h +++ b/src/common/include/private.h @@ -23,6 +23,17 @@ #include +/* + * lws made lejp '#' to-end-of-line comments opt-in (LEJP_FLAG_FEAT_COMMENTS); + * .sai.json and the /etc/sai conf files document comment support, so opt + * their parsers in. Older lws accepted comments unconditionally. + */ +#if defined(LEJP_FLAG_FEAT_COMMENTS) +#define sai_lejp_enable_comments(_ctx) ((_ctx)->flags |= LEJP_FLAG_FEAT_COMMENTS) +#else +#define sai_lejp_enable_comments(_ctx) do { (void)(_ctx); } while (0) +#endif + #if defined(WIN32) #define HAVE_STRUCT_TIMESPEC #endif diff --git a/src/device/d-conf.c b/src/device/d-conf.c index 6be89d0..6469726 100644 --- a/src/device/d-conf.c +++ b/src/device/d-conf.c @@ -215,6 +215,7 @@ said_config_global(struct sai_devices *devices, const char *d) lwsl_info("%s: %s\n", __func__, (char *)buf); lejp_construct(&ctx, said_conf_global_cb, &a, paths_global, LWS_ARRAY_SIZE(paths_global)); + sai_lejp_enable_comments(&ctx); do { n = (int)read(fd, buf, sizeof(buf)); diff --git a/src/power/p-conf.c b/src/power/p-conf.c index a5dddc4..95eaec5 100644 --- a/src/power/p-conf.c +++ b/src/power/p-conf.c @@ -143,6 +143,7 @@ saip_config_global(struct sai_power *power, const char *d) lwsl_info("%s: %s\n", __func__, (char *)buf); lejp_construct(&ctx, saip_conf_global_cb, &a, paths_global, LWS_ARRAY_SIZE(paths_global)); + sai_lejp_enable_comments(&ctx); do { n = (int)read(fd, buf, sizeof(buf)); diff --git a/src/server/s-notification.c b/src/server/s-notification.c index 8ed2ef6..a56afa5 100644 --- a/src/server/s-notification.c +++ b/src/server/s-notification.c @@ -1075,6 +1075,7 @@ sai_notification_file_upload_cb(void *data, const char *name, pss->dry = 1; lejp_construct(&saictx, sai_saifile_lejp_cb, pss, saifile_paths, LWS_ARRAY_SIZE(saifile_paths)); + sai_lejp_enable_comments(&saictx); m = lejp_parse(&saictx, (uint8_t *)pss->sn.saifile, (int)pss->sn.saifile_out_pos); sai_event_db_close(&pss->vhd->sqlite3_cache, (sqlite3 **)&pss->sn.e.pdb); @@ -1109,6 +1110,7 @@ sai_notification_file_upload_cb(void *data, const char *name, pss->dry = 0; lejp_construct(&saictx, sai_saifile_lejp_cb, pss, saifile_paths, LWS_ARRAY_SIZE(saifile_paths)); + sai_lejp_enable_comments(&saictx); m = lejp_parse(&saictx, (uint8_t *)pss->sn.saifile, (int)pss->sn.saifile_out_pos); diff --git a/src/virt/v-conf.c b/src/virt/v-conf.c index 33a663e..eb2360c 100644 --- a/src/virt/v-conf.c +++ b/src/virt/v-conf.c @@ -103,6 +103,7 @@ saiv_conf_dir_cb(const char *dirpath, void *user, struct lws_dir_entry *lde) memset(&vctx, 0, sizeof(vctx)); lejp_construct(&ctx, saiv_conf_plat_cb, &vctx, paths_plat, LWS_ARRAY_SIZE(paths_plat)); + sai_lejp_enable_comments(&ctx); while ((n = read(fd, buf, sizeof(buf))) > 0) { m = lejp_parse(&ctx, buf, (int)n); @@ -188,6 +189,7 @@ saiv_config_global(struct sai_virt *virt, const char *filepath) } lejp_construct(&ctx, saiv_conf_global_cb, virt, paths_global, LWS_ARRAY_SIZE(paths_global)); + sai_lejp_enable_comments(&ctx); while ((n = read(fd, buf, sizeof(buf))) > 0) { m = lejp_parse(&ctx, buf, (int)n);