yeptris 0.6.34.3-arm-linux-eabihf → 0.6.35.1-arm-linux-eabihf
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/yeptris/3.4/native.so +0 -0
- data/lib/yeptris/cbor.rb +5 -1
- data/lib/yeptris/document.rb +10 -2
- data/lib/yeptris/ffi.rb +1 -0
- data/lib/yeptris/psych/visitors.rb +2 -2
- data/lib/yeptris.rb +1 -1
- data/libyeptris.so +0 -0
- data/vendor/libyeptris/CMakeLists.txt +1 -1
- data/vendor/libyeptris/src/include/yeptris/dom.h +6 -0
- data/vendor/libyeptris/src/yeptris/build.c +16 -0
- data/vendor/libyeptris/src/yeptris/dom/dom.c +6 -6
- data/vendor/libyeptris/src/yeptris/dom/dom.h +5 -0
- data/vendor/libyeptris/src/yeptris/dom/mutate.c +2 -2
- data/vendor/libyeptris/src/yeptris/emit/style.c +15 -0
- data/vendor/libyeptris/src/yeptris/emit/writer.c +7 -1
- data/vendor/libyeptris/src/yeptris/marshal.c +79 -29
- data/vendor/libyeptris/src/yeptris/parse/engine.c +567 -48
- data/vendor/libyeptris/src/yeptris/parse/scalars.c +22 -3
- data/vendor/libyeptris/src/yeptris/resolve/compat11.c +10 -3
- data/vendor/libyeptris/src/yeptris/scan/scan.c +1 -0
- metadata +1 -1
|
@@ -130,11 +130,18 @@ struct yep_engine {
|
|
|
130
130
|
yep_view handle, prefix;
|
|
131
131
|
} tagmap[8];
|
|
132
132
|
int tagmap_n;
|
|
133
|
-
int saw_yaml;
|
|
134
|
-
size_t doc_begin;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
int saw_yaml; /* %YAML seen for the pending document */
|
|
134
|
+
size_t doc_begin; /* #179: first directive line of the pending doc
|
|
135
|
+
* (SIZE_MAX = none) — libyaml's DOCUMENT_START
|
|
136
|
+
* start_mark includes directives. An offset into
|
|
137
|
+
* THIS run's buffer. */
|
|
138
|
+
uint32_t doc_begin_line; /* the same directive line as a stream-
|
|
139
|
+
* absolute LINE: offsets die at a step cut
|
|
140
|
+
* (the tail is memmoved), but a directive
|
|
141
|
+
* line split from its --- must still mark
|
|
142
|
+
* the DOCUMENT_START (#645's neighbor:
|
|
143
|
+
* whole 85:1 vs chunked 86:1) */
|
|
144
|
+
void* step; /* yep_stepstate: resumable stepping (07) */
|
|
138
145
|
|
|
139
146
|
/* Flow single-pair deferral: a sequence entry's events are buffered
|
|
140
147
|
* until we know whether ':' follows ("[a: b]" needs MAP_START before
|
|
@@ -1224,8 +1231,12 @@ static yep_view e_resolve_tag(yep_engine* e, yep_view tag) {
|
|
|
1224
1231
|
return e_tag_uri_decode(e, e_resolve_tag_raw(e, tag));
|
|
1225
1232
|
}
|
|
1226
1233
|
|
|
1227
|
-
/* Parses &anchor / !tag runs at the cursor into *anchor / *tag.
|
|
1234
|
+
/* Parses &anchor / !tag runs at the cursor into *anchor / *tag. A node
|
|
1235
|
+
* carries at most one of each (c-ns-properties): a second property of
|
|
1236
|
+
* the same kind is the suite's 4JVG error. Keeping the last one let a
|
|
1237
|
+
* mutated anchor run read differently from libyaml (catch 156). */
|
|
1228
1238
|
static void e_props(yep_engine* e, yep_view* anchor, yep_view* tag) {
|
|
1239
|
+
int have_anchor = 0, have_tag = 0;
|
|
1229
1240
|
for (;;) {
|
|
1230
1241
|
e_skip_inline_space(e);
|
|
1231
1242
|
if (e->pos >= e->len) {
|
|
@@ -1233,6 +1244,11 @@ static void e_props(yep_engine* e, yep_view* anchor, yep_view* tag) {
|
|
|
1233
1244
|
}
|
|
1234
1245
|
unsigned char c = (unsigned char)e->p[e->pos];
|
|
1235
1246
|
if (c == '&') {
|
|
1247
|
+
if (have_anchor) {
|
|
1248
|
+
e_fail(e, YEP_ERR_UNEXPECTED, e->pos);
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
have_anchor = 1;
|
|
1236
1252
|
size_t start = e->pos + 1;
|
|
1237
1253
|
e->pos = yep_scan_prop_end(e->p, e->len, start);
|
|
1238
1254
|
anchor->p = e->p + start;
|
|
@@ -1257,6 +1273,11 @@ static void e_props(yep_engine* e, yep_view* anchor, yep_view* tag) {
|
|
|
1257
1273
|
return;
|
|
1258
1274
|
}
|
|
1259
1275
|
} else if (c == '!') {
|
|
1276
|
+
if (have_tag) {
|
|
1277
|
+
e_fail(e, YEP_ERR_UNEXPECTED, e->pos);
|
|
1278
|
+
return;
|
|
1279
|
+
}
|
|
1280
|
+
have_tag = 1;
|
|
1260
1281
|
size_t start = e->pos;
|
|
1261
1282
|
e->pos++;
|
|
1262
1283
|
if (e->pos < e->len && e->p[e->pos] == '<') {
|
|
@@ -1478,12 +1499,18 @@ static int e_skip_flow(yep_engine* e) {
|
|
|
1478
1499
|
}
|
|
1479
1500
|
if (c == '[') {
|
|
1480
1501
|
if (n >= e->max_depth) {
|
|
1481
|
-
|
|
1502
|
+
/* NOT-A-KEY deferral (the unterminated-quote law
|
|
1503
|
+
* above): the pre-scan fires before the flow's open
|
|
1504
|
+
* events, while the chunked feed had already streamed
|
|
1505
|
+
* them, so the whole stream lost MAP_START/SEQ_START
|
|
1506
|
+
* (the nightly's run 39502647277). The real parse owns
|
|
1507
|
+
* the depth error after the events. */
|
|
1508
|
+
return 0;
|
|
1482
1509
|
}
|
|
1483
1510
|
stk[n++] = 0;
|
|
1484
1511
|
} else if (c == '{') {
|
|
1485
1512
|
if (n >= e->max_depth) {
|
|
1486
|
-
return
|
|
1513
|
+
return 0; /* the same deferral */
|
|
1487
1514
|
}
|
|
1488
1515
|
stk[n++] = 1;
|
|
1489
1516
|
} else if (c == ']') {
|
|
@@ -2098,6 +2125,8 @@ static void e_flow_frame_init(void* stv, int idx, int kind, int pending_key) {
|
|
|
2098
2125
|
uint8_t just_closed;
|
|
2099
2126
|
uint8_t pair_open;
|
|
2100
2127
|
uint8_t pair_value;
|
|
2128
|
+
uint8_t pair_q; /* the pair opened on an explicit '?': its
|
|
2129
|
+
* JSON-style ':' separator is still ahead */
|
|
2101
2130
|
uint8_t pair_wrap;
|
|
2102
2131
|
uint8_t q_coll; /* seq: an explicit '?' key collection awaits completion */
|
|
2103
2132
|
uint8_t key_coll; /* map: the nested collection opened in key position */
|
|
@@ -2113,6 +2142,7 @@ static void e_flow_frame_init(void* stv, int idx, int kind, int pending_key) {
|
|
|
2113
2142
|
st[idx].key_coll = 0;
|
|
2114
2143
|
st[idx].pair_open = 0;
|
|
2115
2144
|
st[idx].pair_value = 0;
|
|
2145
|
+
st[idx].pair_q = 0;
|
|
2116
2146
|
st[idx].pair_wrap = 0;
|
|
2117
2147
|
st[idx].q_coll = 0;
|
|
2118
2148
|
st[idx].buf_from = -1;
|
|
@@ -2128,6 +2158,8 @@ static int e_flow(yep_engine* e, yep_view anchor, yep_view tag, uint32_t anchor_
|
|
|
2128
2158
|
uint8_t just_closed; /* a nested collection closed here (key candidate) */
|
|
2129
2159
|
uint8_t pair_open; /* seq: a buffered single-pair awaits its MAP_END */
|
|
2130
2160
|
uint8_t pair_value; /* seq: the open pair already has its value */
|
|
2161
|
+
uint8_t pair_q; /* seq: the pair opened on an explicit '?':
|
|
2162
|
+
* its JSON-style ':' separator is still ahead */
|
|
2131
2163
|
uint8_t pair_wrap; /* map frame pushed as a seq single-pair */
|
|
2132
2164
|
uint8_t q_coll; /* seq: an explicit '?' key collection awaits completion */
|
|
2133
2165
|
uint8_t key_coll; /* map: a nested collection opened in key position */
|
|
@@ -2191,6 +2223,31 @@ static int e_flow(yep_engine* e, yep_view anchor, yep_view tag, uint32_t anchor_
|
|
|
2191
2223
|
return e_fail(e, YEP_ERR_BAD_INDENT, e->pos + fl.indent);
|
|
2192
2224
|
}
|
|
2193
2225
|
}
|
|
2226
|
+
if (st[n - 1].pair_open && st[n - 1].pair_q && e->pos < e->len && e->p[e->pos] == ':') {
|
|
2227
|
+
/* "#671: the explicit key's entry separator may sit flush
|
|
2228
|
+
* against the value ("[? &a :b]") -- the JSON-style colon
|
|
2229
|
+
* the map frame's pending-key law consumes; an IMPLICIT
|
|
2230
|
+
* key's separator is already spent here, so its value's
|
|
2231
|
+
* leading ':' stays content ("[s: :v]") */
|
|
2232
|
+
size_t n2 = e->pos + 1;
|
|
2233
|
+
if (n2 >= e->len ||
|
|
2234
|
+
!(e->p[n2] == ' ' || e->p[n2] == '\t' || e->p[n2] == '\n' || e->p[n2] == '\r' ||
|
|
2235
|
+
yep_ct_is((unsigned char)e->p[n2], YEP_CT_FLOW_IND))) {
|
|
2236
|
+
st[n - 1].pair_q = 0;
|
|
2237
|
+
e->pos++;
|
|
2238
|
+
continue;
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
if (st[n - 1].kind == 1 && st[n - 1].pending_key == 2 && e->pos < e->len &&
|
|
2242
|
+
e->p[e->pos] == ':') {
|
|
2243
|
+
/* an explicit '?'-key entry's separator may follow on a
|
|
2244
|
+
* LATER line (s-separate spans breaks in flow: "{?{a}\n:
|
|
2245
|
+
* b}" — the nightly's catch 161); the post-node colon law
|
|
2246
|
+
* never sees a colon at the node start */
|
|
2247
|
+
st[n - 1].pending_key = 1;
|
|
2248
|
+
e->pos++;
|
|
2249
|
+
continue;
|
|
2250
|
+
}
|
|
2194
2251
|
if (e->pos < e->len && e->p[e->pos] != ',' && e->p[e->pos] != ']' && e->p[e->pos] != '}' &&
|
|
2195
2252
|
!(e->p[e->pos] == ':' &&
|
|
2196
2253
|
((st[n - 1].kind == 1 && st[n - 1].pending_key == 1) || st[n - 1].just_closed)) &&
|
|
@@ -2389,6 +2446,7 @@ static int e_flow(yep_engine* e, yep_view anchor, yep_view tag, uint32_t anchor_
|
|
|
2389
2446
|
return -2;
|
|
2390
2447
|
}
|
|
2391
2448
|
st[n - 1].pair_open = 1;
|
|
2449
|
+
st[n - 1].pair_q = (uint8_t)q_key;
|
|
2392
2450
|
continue;
|
|
2393
2451
|
} else {
|
|
2394
2452
|
yep_event mk;
|
|
@@ -2420,6 +2478,7 @@ static int e_flow(yep_engine* e, yep_view anchor, yep_view tag, uint32_t anchor_
|
|
|
2420
2478
|
return -2;
|
|
2421
2479
|
}
|
|
2422
2480
|
st[n - 1].pair_open = 1;
|
|
2481
|
+
st[n - 1].pair_q = (uint8_t)q_key;
|
|
2423
2482
|
if (e->ev_scopes == 0 && e->ev_buf_n > 0) {
|
|
2424
2483
|
int brc = e_buf_send(e, 0);
|
|
2425
2484
|
if (brc != 0) {
|
|
@@ -2500,6 +2559,7 @@ static int e_flow(yep_engine* e, yep_view anchor, yep_view tag, uint32_t anchor_
|
|
|
2500
2559
|
}
|
|
2501
2560
|
st[n - 1].pair_open = 0;
|
|
2502
2561
|
st[n - 1].pair_value = 0;
|
|
2562
|
+
st[n - 1].pair_q = 0;
|
|
2503
2563
|
}
|
|
2504
2564
|
if (st[n - 1].buf_from >= 0) {
|
|
2505
2565
|
st[n - 1].buf_from = -1;
|
|
@@ -2739,6 +2799,12 @@ static int e_flow(yep_engine* e, yep_view anchor, yep_view tag, uint32_t anchor_
|
|
|
2739
2799
|
}
|
|
2740
2800
|
}
|
|
2741
2801
|
st[n - 1].pair_open = 1;
|
|
2802
|
+
/* the wrapped key's own open marked pair_value=1 ("a
|
|
2803
|
+
* VALUE collection completes the pending pair"); as a
|
|
2804
|
+
* KEY it completes nothing — the pair awaits a fresh
|
|
2805
|
+
* value, else the boundary flush skips the null ("[[a]:
|
|
2806
|
+
* ]" lost it, the nightly's round 9) */
|
|
2807
|
+
st[n - 1].pair_value = 0;
|
|
2742
2808
|
continue; /* value next */
|
|
2743
2809
|
}
|
|
2744
2810
|
if (st[n - 1].kind == 0 && n >= 1) {
|
|
@@ -3710,8 +3776,9 @@ static int e_parse_value(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
3710
3776
|
* may align with the '?' column. Flow nodes and property runs
|
|
3711
3777
|
* continue the value even at the parent column ("k:\n!!seq\n[a]"). */
|
|
3712
3778
|
if (ctx == YEP_CTX_AFTER_Q && li.indent == floor_col && li.first == '-' &&
|
|
3713
|
-
li.offset + 1 < li.end && e->p[li.offset +
|
|
3714
|
-
e->p[li.offset + 1] != '\
|
|
3779
|
+
li.offset + li.indent + 1 < li.end && e->p[li.offset + li.indent + 1] != ' ' &&
|
|
3780
|
+
e->p[li.offset + li.indent + 1] != '\t' && e->p[li.offset + li.indent + 1] != '\n' &&
|
|
3781
|
+
e->p[li.offset + li.indent + 1] != '\r') {
|
|
3715
3782
|
/* "-:" and friends: a dash with a non-space follower is a
|
|
3716
3783
|
* PLAIN key ("-" => null), never the pending key's content
|
|
3717
3784
|
* ("?\n-:" lost the null pair, the nightly's run
|
|
@@ -3756,9 +3823,33 @@ static int e_parse_value(yep_engine* e, yep_ctx ctx, uint16_t floor_col) {
|
|
|
3756
3823
|
goto empty_value;
|
|
3757
3824
|
}
|
|
3758
3825
|
}
|
|
3826
|
+
/* A flow collection at the parent column is normally the pending
|
|
3827
|
+
* value ("k:\n[a]"), but a flow followed by a same-line ':' is a
|
|
3828
|
+
* KEY of the parent map: the pending value is empty and the main
|
|
3829
|
+
* loop must own the line (crash-c0169e98: "a:\n{----}: 1" made
|
|
3830
|
+
* the flow a's value and then errored on its key colon). Probe
|
|
3831
|
+
* with the same pre-scan the block flow-key branch uses. */
|
|
3832
|
+
int flow_value = 0;
|
|
3833
|
+
if ((li.first == '[' || li.first == '{') && li.indent == floor_col) {
|
|
3834
|
+
flow_value = 1;
|
|
3835
|
+
size_t fsave = e->pos;
|
|
3836
|
+
uint32_t fline = e->line;
|
|
3837
|
+
size_t fls = e->line_start;
|
|
3838
|
+
e->pos = li.offset + li.indent;
|
|
3839
|
+
if (e_skip_flow(e) == 0) {
|
|
3840
|
+
e_skip_inline_space(e);
|
|
3841
|
+
if (e_colon_at(e, e->pos) && e->line == fline) {
|
|
3842
|
+
flow_value = 0;
|
|
3843
|
+
}
|
|
3844
|
+
} else {
|
|
3845
|
+
yep_error_clear(&e->err); /* e_node re-raises the real error */
|
|
3846
|
+
}
|
|
3847
|
+
e->pos = fsave;
|
|
3848
|
+
e->line = fline;
|
|
3849
|
+
e->line_start = fls;
|
|
3850
|
+
}
|
|
3759
3851
|
if (li.indent > floor_col || e->depth == 0 ||
|
|
3760
|
-
(ctx == YEP_CTX_AFTER_Q && li.indent == floor_col && li.first != ':') ||
|
|
3761
|
-
((li.first == '[' || li.first == '{') && li.indent == floor_col) ||
|
|
3852
|
+
(ctx == YEP_CTX_AFTER_Q && li.indent == floor_col && li.first != ':') || flow_value ||
|
|
3762
3853
|
/* libyaml never validates a block-scalar HEADER's column —
|
|
3763
3854
|
* only the content must out-indent the parent (e_block_scalar
|
|
3764
3855
|
* enforces that), so "|" / ">" at the key's own column is the
|
|
@@ -3941,48 +4032,366 @@ const yep_stopset yep_norm_break_leads = {
|
|
|
3941
4032
|
0x02, 0x00}},
|
|
3942
4033
|
};
|
|
3943
4034
|
|
|
4035
|
+
/* The context walk behind the break normalizer (issue #638): the fold
|
|
4036
|
+
* is quote-aware — NEL (C2 85) folds EVERYWHERE (libyaml's READ_LINE
|
|
4037
|
+
* folds it inside quoted scalars too), LS/PS (E2 80 A8/A9) fold
|
|
4038
|
+
* everywhere EXCEPT inside single/double-quoted regions, where libyaml
|
|
4039
|
+
* keeps them raw as content (the JSON suite's y_string_u+2028_line_sep
|
|
4040
|
+
* / y_string_u+2029_par_sep demand it). The arms mirror step_scan's
|
|
4041
|
+
* context tracking minus the cut/hold machinery — complete input, no
|
|
4042
|
+
* truncation points — with two engine-faithful corrections: the value
|
|
4043
|
+
* position survives spaces (`k: 'x'` opens the quote; a block plain
|
|
4044
|
+
* continuation `a 'b'` does not), and the block-scalar floor is the
|
|
4045
|
+
* header LINE's indent (step_scan's walk-back only serves col-0
|
|
4046
|
+
* headers). Verified against libyaml by the NormLsPs pins and the
|
|
4047
|
+
* fuzz-diff LS/PS comparator. */
|
|
4048
|
+
static int step_bs_header(const char* p, size_t len, size_t i);
|
|
4049
|
+
|
|
4050
|
+
typedef struct yep_norm_ctx {
|
|
4051
|
+
int quote; /* 0 none, else the opening quote char */
|
|
4052
|
+
int in_comment;
|
|
4053
|
+
int in_verbatim;
|
|
4054
|
+
int in_flow;
|
|
4055
|
+
int tok_start;
|
|
4056
|
+
int word_led;
|
|
4057
|
+
int at_break;
|
|
4058
|
+
int bs_open;
|
|
4059
|
+
int bs_content;
|
|
4060
|
+
uint32_t bs_indent; /* the header line's indent; (uint32_t)-1 = the
|
|
4061
|
+
* doc-inline root rule (markers only) */
|
|
4062
|
+
} yep_norm_ctx;
|
|
4063
|
+
|
|
4064
|
+
typedef struct yep_norm_tok {
|
|
4065
|
+
size_t n; /* bytes consumed */
|
|
4066
|
+
int fold_off; /* -1 verbatim, else the offset inside the token
|
|
4067
|
+
* whose bytes become one '\n' */
|
|
4068
|
+
int fold_len;
|
|
4069
|
+
} yep_norm_tok;
|
|
4070
|
+
|
|
4071
|
+
static void norm_break_arms(yep_norm_ctx* c) {
|
|
4072
|
+
c->tok_start = 1;
|
|
4073
|
+
c->word_led = 0;
|
|
4074
|
+
c->at_break = 1;
|
|
4075
|
+
}
|
|
4076
|
+
|
|
4077
|
+
static yep_norm_tok norm_step(yep_norm_ctx* c, const char* p, size_t len, size_t i) {
|
|
4078
|
+
yep_norm_tok t = {1, -1, 0};
|
|
4079
|
+
unsigned char ch = (unsigned char)p[i];
|
|
4080
|
+
int nel = (ch == 0xC2 && i + 1 < len && (unsigned char)p[i + 1] == 0x85);
|
|
4081
|
+
int lps = (ch == 0xE2 && i + 2 < len && (unsigned char)p[i + 1] == 0x80 &&
|
|
4082
|
+
((unsigned char)p[i + 2] & 0xFE) == 0xA8);
|
|
4083
|
+
|
|
4084
|
+
if (c->in_comment) {
|
|
4085
|
+
/* the folds end a comment like any line break (step_scan's
|
|
4086
|
+
* law: the post-break '#' must read as a comment) */
|
|
4087
|
+
if (ch == '\n') {
|
|
4088
|
+
c->in_comment = 0;
|
|
4089
|
+
norm_break_arms(c);
|
|
4090
|
+
} else if (ch == '\r' && (i + 1 >= len || p[i + 1] != '\n')) {
|
|
4091
|
+
c->in_comment = 0;
|
|
4092
|
+
norm_break_arms(c);
|
|
4093
|
+
} else if (nel) {
|
|
4094
|
+
t.n = 2;
|
|
4095
|
+
t.fold_off = 0;
|
|
4096
|
+
t.fold_len = 2;
|
|
4097
|
+
c->in_comment = 0;
|
|
4098
|
+
norm_break_arms(c);
|
|
4099
|
+
} else if (lps) {
|
|
4100
|
+
t.n = 3;
|
|
4101
|
+
t.fold_off = 0;
|
|
4102
|
+
t.fold_len = 3;
|
|
4103
|
+
c->in_comment = 0;
|
|
4104
|
+
norm_break_arms(c);
|
|
4105
|
+
}
|
|
4106
|
+
return t;
|
|
4107
|
+
}
|
|
4108
|
+
if (c->quote != 0) {
|
|
4109
|
+
/* NEL folds inside quotes too; LS/PS stay raw content */
|
|
4110
|
+
if (nel) {
|
|
4111
|
+
t.n = 2;
|
|
4112
|
+
t.fold_off = 0;
|
|
4113
|
+
t.fold_len = 2;
|
|
4114
|
+
return t;
|
|
4115
|
+
}
|
|
4116
|
+
if (lps) {
|
|
4117
|
+
t.n = 3;
|
|
4118
|
+
return t;
|
|
4119
|
+
}
|
|
4120
|
+
if (c->quote == '\'') {
|
|
4121
|
+
if (ch == '\'') {
|
|
4122
|
+
if (i + 1 < len && p[i + 1] == '\'') {
|
|
4123
|
+
t.n = 2; /* '' escaped quote */
|
|
4124
|
+
return t;
|
|
4125
|
+
}
|
|
4126
|
+
c->quote = 0;
|
|
4127
|
+
}
|
|
4128
|
+
return t;
|
|
4129
|
+
}
|
|
4130
|
+
if (ch == '\\') {
|
|
4131
|
+
/* the escape consumes the next byte — but a multibyte
|
|
4132
|
+
* break under the escape still folds (an escaped break is
|
|
4133
|
+
* a fold continuation, and the blind pass folded it) */
|
|
4134
|
+
if (i + 1 >= len) {
|
|
4135
|
+
return t;
|
|
4136
|
+
}
|
|
4137
|
+
unsigned char nx = (unsigned char)p[i + 1];
|
|
4138
|
+
if (nx == 0xC2 && i + 2 < len && (unsigned char)p[i + 2] == 0x85) {
|
|
4139
|
+
t.n = 3;
|
|
4140
|
+
t.fold_off = 1;
|
|
4141
|
+
t.fold_len = 2;
|
|
4142
|
+
return t;
|
|
4143
|
+
}
|
|
4144
|
+
if (nx == 0xE2 && i + 3 < len && (unsigned char)p[i + 2] == 0x80 &&
|
|
4145
|
+
((unsigned char)p[i + 3] & 0xFE) == 0xA8) {
|
|
4146
|
+
t.n = 4;
|
|
4147
|
+
t.fold_off = 1;
|
|
4148
|
+
t.fold_len = 3;
|
|
4149
|
+
return t;
|
|
4150
|
+
}
|
|
4151
|
+
t.n = 2;
|
|
4152
|
+
return t;
|
|
4153
|
+
}
|
|
4154
|
+
if (ch == '"') {
|
|
4155
|
+
c->quote = 0;
|
|
4156
|
+
}
|
|
4157
|
+
return t;
|
|
4158
|
+
}
|
|
4159
|
+
if (c->in_verbatim) {
|
|
4160
|
+
if (ch == '>') {
|
|
4161
|
+
c->in_verbatim = 0;
|
|
4162
|
+
}
|
|
4163
|
+
return t;
|
|
4164
|
+
}
|
|
4165
|
+
if (ch == '\n' || (ch == '\r' && (i + 1 >= len || p[i + 1] != '\n'))) {
|
|
4166
|
+
norm_break_arms(c);
|
|
4167
|
+
return t;
|
|
4168
|
+
}
|
|
4169
|
+
if (nel) {
|
|
4170
|
+
t.n = 2;
|
|
4171
|
+
t.fold_off = 0;
|
|
4172
|
+
t.fold_len = 2;
|
|
4173
|
+
norm_break_arms(c);
|
|
4174
|
+
return t;
|
|
4175
|
+
}
|
|
4176
|
+
if (lps) {
|
|
4177
|
+
t.n = 3;
|
|
4178
|
+
t.fold_off = 0;
|
|
4179
|
+
t.fold_len = 3;
|
|
4180
|
+
norm_break_arms(c);
|
|
4181
|
+
return t;
|
|
4182
|
+
}
|
|
4183
|
+
if (ch == '#' && (i == 0 || c->at_break || p[i - 1] == '\n' || p[i - 1] == '\r' ||
|
|
4184
|
+
p[i - 1] == ' ' || p[i - 1] == '\t')) {
|
|
4185
|
+
c->in_comment = 1;
|
|
4186
|
+
c->at_break = 0;
|
|
4187
|
+
return t;
|
|
4188
|
+
}
|
|
4189
|
+
if (ch == ' ' || ch == '\t') {
|
|
4190
|
+
/* a value position survives spaces in block context ("k: 'x'"
|
|
4191
|
+
* opens; the plain continuation "a 'b'" does not — its word
|
|
4192
|
+
* did not begin with an indicator) */
|
|
4193
|
+
c->tok_start = (c->in_flow > 0) ? 1 : (c->word_led || c->tok_start);
|
|
4194
|
+
return t;
|
|
4195
|
+
}
|
|
4196
|
+
|
|
4197
|
+
int line_start = (i == 0 || c->at_break || p[i - 1] == '\n' || p[i - 1] == '\r');
|
|
4198
|
+
|
|
4199
|
+
/* block scalars: inside the fold no quote opens and every break
|
|
4200
|
+
* keeps its fold; the region ends at a col-0 marker, a %-line
|
|
4201
|
+
* after content, or a dedent to the header line's indent */
|
|
4202
|
+
if (line_start && c->in_flow == 0 && c->bs_open) {
|
|
4203
|
+
size_t k = i;
|
|
4204
|
+
uint32_t ind = 0;
|
|
4205
|
+
while (k < len && p[k] == ' ') {
|
|
4206
|
+
ind++;
|
|
4207
|
+
k++;
|
|
4208
|
+
}
|
|
4209
|
+
if (k >= len) {
|
|
4210
|
+
t.n = len - i;
|
|
4211
|
+
c->at_break = 0;
|
|
4212
|
+
return t; /* a final line without its break */
|
|
4213
|
+
}
|
|
4214
|
+
if (p[k] == '\n' || p[k] == '\r' || p[k] == '#') {
|
|
4215
|
+
size_t e = k;
|
|
4216
|
+
while (e < len && p[e] != '\n') {
|
|
4217
|
+
e++;
|
|
4218
|
+
}
|
|
4219
|
+
t.n = (e < len) ? (e - i + 1) : (len - i);
|
|
4220
|
+
c->at_break = (e < len);
|
|
4221
|
+
return t; /* blank or comment-content line */
|
|
4222
|
+
}
|
|
4223
|
+
int marker = (ind == 0 && k + 2 < len &&
|
|
4224
|
+
((p[k] == '-' && p[k + 1] == '-' && p[k + 2] == '-') ||
|
|
4225
|
+
(p[k] == '.' && p[k + 1] == '.' && p[k + 2] == '.')) &&
|
|
4226
|
+
(k + 3 >= len || p[k + 3] == ' ' || p[k + 3] == '\t' || p[k + 3] == '\n' ||
|
|
4227
|
+
p[k + 3] == '\r'));
|
|
4228
|
+
if (marker || (p[k] == '%' && ind == 0 && c->bs_content) ||
|
|
4229
|
+
(!marker && c->bs_indent != (uint32_t)-1 && ind <= (uint32_t)c->bs_indent)) {
|
|
4230
|
+
c->bs_open = 0; /* the fold ends: this line processes normally */
|
|
4231
|
+
} else {
|
|
4232
|
+
size_t e = k;
|
|
4233
|
+
while (e < len && p[e] != '\n') {
|
|
4234
|
+
e++;
|
|
4235
|
+
}
|
|
4236
|
+
if (p[k] != '#' && p[k] != '\n' && p[k] != '\r') {
|
|
4237
|
+
c->bs_content = 1;
|
|
4238
|
+
}
|
|
4239
|
+
t.n = (e < len) ? (e - i + 1) : (len - i);
|
|
4240
|
+
c->at_break = (e < len);
|
|
4241
|
+
return t;
|
|
4242
|
+
}
|
|
4243
|
+
}
|
|
4244
|
+
|
|
4245
|
+
/* the header: a '>' / '|' at a value position with a valid
|
|
4246
|
+
* follower opens the fold (the engine's own floor is the parent's
|
|
4247
|
+
* column, which the walk cannot know — the header LINE's indent
|
|
4248
|
+
* bounds it from above and the dedent law agrees wherever the
|
|
4249
|
+
* parse succeeds) */
|
|
4250
|
+
if (line_start && c->in_flow == 0 && !c->bs_open && c->tok_start && (ch == '>' || ch == '|') &&
|
|
4251
|
+
(i + 1 >= len || p[i + 1] == ' ' || p[i + 1] == '\t' || p[i + 1] == '\n' ||
|
|
4252
|
+
p[i + 1] == '\r' || (p[i + 1] >= '0' && p[i + 1] <= '9') || p[i + 1] == '+' ||
|
|
4253
|
+
p[i + 1] == '-')) {
|
|
4254
|
+
int hdr = step_bs_header(p, len, i);
|
|
4255
|
+
if (hdr > 0) {
|
|
4256
|
+
size_t ls = i;
|
|
4257
|
+
while (ls > 0 && p[ls - 1] != '\n' && p[ls - 1] != '\r') {
|
|
4258
|
+
ls--;
|
|
4259
|
+
}
|
|
4260
|
+
uint32_t ind = 0;
|
|
4261
|
+
size_t k = ls;
|
|
4262
|
+
while (k < len && p[k] == ' ') {
|
|
4263
|
+
ind++;
|
|
4264
|
+
k++;
|
|
4265
|
+
}
|
|
4266
|
+
c->bs_open = 1;
|
|
4267
|
+
c->bs_indent = ind;
|
|
4268
|
+
c->bs_content = 0;
|
|
4269
|
+
size_t e = i;
|
|
4270
|
+
while (e < len && p[e] != '\n') {
|
|
4271
|
+
e++;
|
|
4272
|
+
}
|
|
4273
|
+
t.n = (e < len) ? (e - i + 1) : (len - i);
|
|
4274
|
+
c->at_break = (e < len);
|
|
4275
|
+
return t;
|
|
4276
|
+
}
|
|
4277
|
+
/* not a header ("| : [" is a mapping key): fall through */
|
|
4278
|
+
}
|
|
4279
|
+
/* the doc-inline twin ("--- |"): the node hangs off the document,
|
|
4280
|
+
* so only a later marker ends its fold (col-0 lines are content) */
|
|
4281
|
+
if (line_start && c->in_flow == 0 && !c->bs_open && ch == '-' && i + 2 < len &&
|
|
4282
|
+
p[i + 1] == '-' && p[i + 2] == '-' &&
|
|
4283
|
+
(i + 3 >= len || p[i + 3] == ' ' || p[i + 3] == '\t' || p[i + 3] == '\n' ||
|
|
4284
|
+
p[i + 3] == '\r')) {
|
|
4285
|
+
size_t k = i + 3;
|
|
4286
|
+
while (k < len && (p[k] == ' ' || p[k] == '\t')) {
|
|
4287
|
+
k++;
|
|
4288
|
+
}
|
|
4289
|
+
if (k < len && (p[k] == '>' || p[k] == '|') &&
|
|
4290
|
+
(k + 1 >= len || p[k + 1] == ' ' || p[k + 1] == '\t' || p[k + 1] == '\n' ||
|
|
4291
|
+
p[k + 1] == '\r' || (p[k + 1] >= '0' && p[k + 1] <= '9') || p[k + 1] == '+' ||
|
|
4292
|
+
p[k + 1] == '-') &&
|
|
4293
|
+
step_bs_header(p, len, k) > 0) {
|
|
4294
|
+
c->bs_open = 1;
|
|
4295
|
+
c->bs_indent = (uint32_t)-1;
|
|
4296
|
+
c->bs_content = 0;
|
|
4297
|
+
size_t e = i;
|
|
4298
|
+
while (e < len && p[e] != '\n') {
|
|
4299
|
+
e++;
|
|
4300
|
+
}
|
|
4301
|
+
t.n = (e < len) ? (e - i + 1) : (len - i);
|
|
4302
|
+
c->at_break = (e < len);
|
|
4303
|
+
return t;
|
|
4304
|
+
}
|
|
4305
|
+
t.n = 3; /* the marker rides; the line's tail processes normally */
|
|
4306
|
+
return t;
|
|
4307
|
+
}
|
|
4308
|
+
|
|
4309
|
+
if (c->tok_start) {
|
|
4310
|
+
c->at_break = 0; /* any content byte ends the line-start state */
|
|
4311
|
+
if (ch == '!' && i + 1 < len && p[i + 1] == '<') {
|
|
4312
|
+
c->in_verbatim = 1;
|
|
4313
|
+
t.n = 2;
|
|
4314
|
+
return t;
|
|
4315
|
+
}
|
|
4316
|
+
c->word_led = (ch == '&' || ch == '*' || ch == '!' || ch == '-' || ch == '?' || ch == ':' ||
|
|
4317
|
+
ch == ',' || ch == '[' || ch == '{' || ch == ']' || ch == '}');
|
|
4318
|
+
if (ch == '\'' || ch == '"') {
|
|
4319
|
+
c->quote = ch; /* a quote at a value position IS a quoted token */
|
|
4320
|
+
c->tok_start = 0;
|
|
4321
|
+
return t;
|
|
4322
|
+
}
|
|
4323
|
+
c->tok_start = 0;
|
|
4324
|
+
}
|
|
4325
|
+
if (ch == ',' || ch == ':' || ch == '[' || ch == '{' || ch == ']' || ch == '}') {
|
|
4326
|
+
c->tok_start = 1; /* flow separators: the next byte may begin a
|
|
4327
|
+
* token with no space ("{\"a\":...") */
|
|
4328
|
+
}
|
|
4329
|
+
if (ch == '[' || ch == '{') {
|
|
4330
|
+
c->in_flow++;
|
|
4331
|
+
} else if (ch == ']' || ch == '}') {
|
|
4332
|
+
if (c->in_flow > 0) {
|
|
4333
|
+
c->in_flow--;
|
|
4334
|
+
}
|
|
4335
|
+
}
|
|
4336
|
+
return t;
|
|
4337
|
+
}
|
|
4338
|
+
|
|
3944
4339
|
char* yep_engine_normalize_breaks(const yep_allocator* sys, const char* p, size_t len,
|
|
3945
4340
|
size_t* out_len) {
|
|
3946
4341
|
const unsigned char* q = (const unsigned char*)p;
|
|
3947
4342
|
const yep_text_kernels* k = yep_text_active();
|
|
3948
4343
|
size_t i = 0;
|
|
3949
|
-
int
|
|
4344
|
+
int exotic = 0;
|
|
3950
4345
|
while (i < len) {
|
|
3951
4346
|
ptrdiff_t hit = k->stopset_find(&yep_norm_break_leads, (const char*)q + i, len - i);
|
|
3952
4347
|
if (hit < 0) {
|
|
3953
4348
|
break;
|
|
3954
4349
|
}
|
|
3955
4350
|
i += (size_t)hit;
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
4351
|
+
exotic = 1; /* any NEL/LS/PS lead byte needs the context walk */
|
|
4352
|
+
break;
|
|
4353
|
+
}
|
|
4354
|
+
if (!exotic) {
|
|
4355
|
+
return NULL;
|
|
4356
|
+
}
|
|
4357
|
+
yep_norm_ctx probe;
|
|
4358
|
+
memset(&probe, 0, sizeof(probe));
|
|
4359
|
+
probe.tok_start = 1;
|
|
4360
|
+
int found = 0;
|
|
4361
|
+
for (size_t j = 0; j < len;) {
|
|
4362
|
+
yep_norm_tok t = norm_step(&probe, p, len, j);
|
|
4363
|
+
if (t.fold_off >= 0) {
|
|
3962
4364
|
found = 1;
|
|
3963
4365
|
break;
|
|
3964
4366
|
}
|
|
3965
|
-
|
|
4367
|
+
j += t.n;
|
|
3966
4368
|
}
|
|
3967
4369
|
if (!found) {
|
|
3968
|
-
return NULL;
|
|
4370
|
+
return NULL; /* the exotic bytes all ride inside quoted regions:
|
|
4371
|
+
* the zero-copy path keeps them raw (the fix) */
|
|
3969
4372
|
}
|
|
3970
4373
|
char* out = yep_alloc(sys, len + 1);
|
|
3971
4374
|
if (out == NULL) {
|
|
3972
4375
|
return NULL;
|
|
3973
4376
|
}
|
|
4377
|
+
yep_norm_ctx cp;
|
|
4378
|
+
memset(&cp, 0, sizeof(cp));
|
|
4379
|
+
cp.tok_start = 1;
|
|
3974
4380
|
size_t o = 0;
|
|
3975
4381
|
for (size_t j = 0; j < len;) {
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
j
|
|
3979
|
-
|
|
3980
|
-
(q[j + 2] == 0xA8 || q[j + 2] == 0xA9)) {
|
|
3981
|
-
out[o++] = '\n';
|
|
3982
|
-
j += 3;
|
|
4382
|
+
yep_norm_tok t = norm_step(&cp, p, len, j);
|
|
4383
|
+
if (t.fold_off < 0) {
|
|
4384
|
+
memcpy(out + o, p + j, t.n);
|
|
4385
|
+
o += t.n;
|
|
3983
4386
|
} else {
|
|
3984
|
-
out
|
|
4387
|
+
memcpy(out + o, p + j, (size_t)t.fold_off);
|
|
4388
|
+
o += (size_t)t.fold_off;
|
|
4389
|
+
out[o++] = '\n';
|
|
4390
|
+
memcpy(out + o, p + j + t.fold_off + t.fold_len,
|
|
4391
|
+
t.n - (size_t)t.fold_off - (size_t)t.fold_len);
|
|
4392
|
+
o += t.n - (size_t)t.fold_off - (size_t)t.fold_len;
|
|
3985
4393
|
}
|
|
4394
|
+
j += t.n;
|
|
3986
4395
|
}
|
|
3987
4396
|
out[o] = '\0';
|
|
3988
4397
|
if (out_len != NULL) {
|
|
@@ -4101,6 +4510,48 @@ void yep_engine_destroy(yep_engine* e) {
|
|
|
4101
4510
|
/* A quote opens a scalar only where a value can begin; anywhere else
|
|
4102
4511
|
* it is literal plain text (the apostrophe in "don't"). This is exact
|
|
4103
4512
|
* on valid YAML: a quote at a value position always opens. */
|
|
4513
|
+
/* A line-start '|' / '>' is a block-scalar header only when the rest
|
|
4514
|
+
* of the line fits the grammar: optional chomping (+/-) and indent
|
|
4515
|
+
* (1-9) indicators in either order, then spaces/tabs, then an optional
|
|
4516
|
+
* space-led comment, then EOL. "| : [" is a plain mapping key whose
|
|
4517
|
+
* value opens a flow — treating it as a header skipped the '[' and let
|
|
4518
|
+
* a '---' cut land inside the still-open flow (#645: whole buffered
|
|
4519
|
+
* that flow to the depth cap, chunked cut and errored at 2:1).
|
|
4520
|
+
* Returns 1 valid, 0 definitely not a header, -1 truncated (the tail
|
|
4521
|
+
* may still complete a valid header). */
|
|
4522
|
+
static int step_bs_header(const char* p, size_t len, size_t i) {
|
|
4523
|
+
size_t k = i + 1;
|
|
4524
|
+
int chomp = 0, indent = 0, space = 0;
|
|
4525
|
+
while (k < len) {
|
|
4526
|
+
char c = p[k];
|
|
4527
|
+
if (c == '+' || c == '-') {
|
|
4528
|
+
if (chomp || space)
|
|
4529
|
+
return 0;
|
|
4530
|
+
chomp = 1;
|
|
4531
|
+
k++;
|
|
4532
|
+
continue;
|
|
4533
|
+
}
|
|
4534
|
+
if (c >= '1' && c <= '9') {
|
|
4535
|
+
if (indent || space)
|
|
4536
|
+
return 0;
|
|
4537
|
+
indent = 1;
|
|
4538
|
+
k++;
|
|
4539
|
+
continue;
|
|
4540
|
+
}
|
|
4541
|
+
if (c == ' ' || c == '\t') {
|
|
4542
|
+
space = 1;
|
|
4543
|
+
k++;
|
|
4544
|
+
continue;
|
|
4545
|
+
}
|
|
4546
|
+
if (c == '\n' || c == '\r')
|
|
4547
|
+
return 1;
|
|
4548
|
+
if (c == '#' && space)
|
|
4549
|
+
return 1; /* a comment needs separation */
|
|
4550
|
+
return 0;
|
|
4551
|
+
}
|
|
4552
|
+
return -1; /* the chunk ended mid-line */
|
|
4553
|
+
}
|
|
4554
|
+
|
|
4104
4555
|
/* Advances quote/flow/comment state over buf[scanned, len) and returns
|
|
4105
4556
|
* the offset of the LAST safe cut (0 = none). When the final bytes'
|
|
4106
4557
|
* meaning depends on bytes not yet fed (a quote that may be doubled,
|
|
@@ -4386,24 +4837,33 @@ static size_t step_scan(yep_stepstate* st) {
|
|
|
4386
4837
|
(i + 1 >= st->len || p[i + 1] == ' ' || p[i + 1] == '\t' || p[i + 1] == '\n' ||
|
|
4387
4838
|
p[i + 1] == '\r' || (p[i + 1] >= '0' && p[i + 1] <= '9') || p[i + 1] == '+' ||
|
|
4388
4839
|
p[i + 1] == '-')) {
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
k--;
|
|
4393
|
-
ind++;
|
|
4394
|
-
}
|
|
4395
|
-
st->bs_open = 1;
|
|
4396
|
-
st->bs_indent = ind;
|
|
4397
|
-
size_t e = i;
|
|
4398
|
-
while (e < st->len && p[e] != '\n') {
|
|
4399
|
-
e++;
|
|
4400
|
-
}
|
|
4401
|
-
if (e >= st->len) {
|
|
4402
|
-
hold = i; /* an incomplete header line */
|
|
4840
|
+
int hdr = step_bs_header(p, st->len, i);
|
|
4841
|
+
if (hdr < 0) {
|
|
4842
|
+
hold = i; /* the header line may still complete */
|
|
4403
4843
|
break;
|
|
4404
4844
|
}
|
|
4405
|
-
|
|
4406
|
-
|
|
4845
|
+
if (hdr > 0) {
|
|
4846
|
+
uint32_t ind = 0;
|
|
4847
|
+
size_t k = i;
|
|
4848
|
+
while (k > 0 && p[k - 1] == ' ') {
|
|
4849
|
+
k--;
|
|
4850
|
+
ind++;
|
|
4851
|
+
}
|
|
4852
|
+
st->bs_open = 1;
|
|
4853
|
+
st->bs_indent = ind;
|
|
4854
|
+
size_t e = i;
|
|
4855
|
+
while (e < st->len && p[e] != '\n') {
|
|
4856
|
+
e++;
|
|
4857
|
+
}
|
|
4858
|
+
if (e >= st->len) {
|
|
4859
|
+
hold = i; /* an incomplete header line */
|
|
4860
|
+
break;
|
|
4861
|
+
}
|
|
4862
|
+
i = e;
|
|
4863
|
+
continue;
|
|
4864
|
+
}
|
|
4865
|
+
/* Not a header ("| : [" is a mapping key): fall through
|
|
4866
|
+
* so the line's flow/quote bytes are counted. */
|
|
4407
4867
|
}
|
|
4408
4868
|
if (c == '-') {
|
|
4409
4869
|
if (i + 3 >= st->len) {
|
|
@@ -4660,9 +5120,23 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
|
|
|
4660
5120
|
p0++;
|
|
4661
5121
|
}
|
|
4662
5122
|
size_t p1 = p0;
|
|
4663
|
-
while (p1 < li.end && e->p[p1] != ' ' && e->p[p1] != '\t'
|
|
5123
|
+
while (p1 < li.end && e->p[p1] != ' ' && e->p[p1] != '\t') {
|
|
4664
5124
|
p1++;
|
|
4665
5125
|
}
|
|
5126
|
+
{
|
|
5127
|
+
/* a '#' inside the prefix token is NOT a comment:
|
|
5128
|
+
* libyaml wants whitespace before a comment and
|
|
5129
|
+
* rejects the glued form ("did not find expected
|
|
5130
|
+
* whitespace or line break while scanning a %TAG
|
|
5131
|
+
* directive"). Treating it as a comment registered
|
|
5132
|
+
* a bogus prefix and split the whole/chunked
|
|
5133
|
+
* verdicts (catch 154). */
|
|
5134
|
+
const char* hash = (const char*)memchr(e->p + p0, '#', p1 - p0);
|
|
5135
|
+
if (hash != NULL) {
|
|
5136
|
+
e_fail(e, YEP_ERR_BAD_DIRECTIVE, (size_t)(hash - e->p));
|
|
5137
|
+
return -1;
|
|
5138
|
+
}
|
|
5139
|
+
}
|
|
4666
5140
|
{
|
|
4667
5141
|
/* libyaml: only blanks and an optional comment may
|
|
4668
5142
|
* follow the prefix ("did not find expected comment
|
|
@@ -4678,6 +5152,36 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
|
|
|
4678
5152
|
return -1;
|
|
4679
5153
|
}
|
|
4680
5154
|
}
|
|
5155
|
+
{
|
|
5156
|
+
/* libyaml validates the handle: "!", "!!", or
|
|
5157
|
+
* "!word!" (word = alnum/-), and a prefix is
|
|
5158
|
+
* required ("did not find expected whitespace
|
|
5159
|
+
* while scanning a %TAG directive"). The lenient
|
|
5160
|
+
* accept registered "!'" and let the whole parse
|
|
5161
|
+
* succeed where the chunked one rejected
|
|
5162
|
+
* (catch 154). */
|
|
5163
|
+
int handle_ok = 0;
|
|
5164
|
+
size_t hl = h1 - h0;
|
|
5165
|
+
if (hl == 1 && e->p[h0] == '!') {
|
|
5166
|
+
handle_ok = 1;
|
|
5167
|
+
} else if (hl == 2 && e->p[h0] == '!' && e->p[h0 + 1] == '!') {
|
|
5168
|
+
handle_ok = 1;
|
|
5169
|
+
} else if (hl >= 3 && e->p[h0] == '!' && e->p[h1 - 1] == '!') {
|
|
5170
|
+
handle_ok = 1;
|
|
5171
|
+
for (size_t k = h0 + 1; k + 1 < h1; k++) {
|
|
5172
|
+
if (!(yep_ct_is((unsigned char)e->p[k], YEP_CT_ALPHA) ||
|
|
5173
|
+
yep_ct_is((unsigned char)e->p[k], YEP_CT_DIGIT) ||
|
|
5174
|
+
e->p[k] == '-')) {
|
|
5175
|
+
handle_ok = 0;
|
|
5176
|
+
break;
|
|
5177
|
+
}
|
|
5178
|
+
}
|
|
5179
|
+
}
|
|
5180
|
+
if (!handle_ok || p1 == p0) {
|
|
5181
|
+
e_fail(e, YEP_ERR_BAD_DIRECTIVE, h0);
|
|
5182
|
+
return -1;
|
|
5183
|
+
}
|
|
5184
|
+
}
|
|
4681
5185
|
if (h1 > h0 && p1 > p0 && e->p[h0] == '!') {
|
|
4682
5186
|
e->tagmap[e->tagmap_n].handle.p = e->p + h0;
|
|
4683
5187
|
e->tagmap[e->tagmap_n].handle.len = (uint32_t)(h1 - h0);
|
|
@@ -4690,6 +5194,7 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
|
|
|
4690
5194
|
e->doc_begin = li.offset; /* libyaml: DOCUMENT_START's
|
|
4691
5195
|
* start_mark includes the
|
|
4692
5196
|
* leading directive lines */
|
|
5197
|
+
e->doc_begin_line = e->line;
|
|
4693
5198
|
}
|
|
4694
5199
|
e_line_done(e, li.end);
|
|
4695
5200
|
continue;
|
|
@@ -4734,10 +5239,19 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
|
|
|
4734
5239
|
}
|
|
4735
5240
|
e_event_init(&ev, YEP_EV_DOCUMENT_START);
|
|
4736
5241
|
ev.style = 1; /* explicit marker */
|
|
4737
|
-
|
|
4738
|
-
|
|
5242
|
+
if (e->doc_begin != (size_t)-1) {
|
|
5243
|
+
e_pos_mark(e, e->doc_begin, &ev.line, &ev.col);
|
|
5244
|
+
} else if (e->doc_begin_line != 0) {
|
|
5245
|
+
/* the directive line was consumed by an EARLIER step
|
|
5246
|
+
* run: its offset is gone, the absolute line is not */
|
|
5247
|
+
ev.line = e->doc_begin_line;
|
|
5248
|
+
ev.col = 1;
|
|
5249
|
+
} else {
|
|
5250
|
+
e_pos_mark(e, li.offset + li.indent, &ev.line, &ev.col);
|
|
5251
|
+
}
|
|
4739
5252
|
e_pos_mark(e, li.offset + li.indent + 3, &ev.end_line, &ev.end_col);
|
|
4740
5253
|
e->doc_begin = (size_t)-1;
|
|
5254
|
+
e->doc_begin_line = 0;
|
|
4741
5255
|
if (emit_now(e, &ev) != 0) {
|
|
4742
5256
|
return -2;
|
|
4743
5257
|
}
|
|
@@ -4816,6 +5330,7 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
|
|
|
4816
5330
|
e->doc_content = 0;
|
|
4817
5331
|
e->saw_yaml = 0;
|
|
4818
5332
|
e->doc_begin = (size_t)-1;
|
|
5333
|
+
e->doc_begin_line = 0;
|
|
4819
5334
|
}
|
|
4820
5335
|
e_line_done(e, li.end);
|
|
4821
5336
|
continue;
|
|
@@ -4825,12 +5340,16 @@ static int engine_run_impl(yep_engine* e, const char* buf, size_t len, const yep
|
|
|
4825
5340
|
e_event_init(&ev, YEP_EV_DOCUMENT_START);
|
|
4826
5341
|
if (e->doc_begin != (size_t)-1) {
|
|
4827
5342
|
e_pos_mark(e, e->doc_begin, &ev.line, &ev.col);
|
|
5343
|
+
} else if (e->doc_begin_line != 0) {
|
|
5344
|
+
ev.line = e->doc_begin_line; /* a directive split across runs */
|
|
5345
|
+
ev.col = 1;
|
|
4828
5346
|
} else {
|
|
4829
5347
|
e_pos_mark(e, li.offset + li.indent, &ev.line, &ev.col);
|
|
4830
5348
|
}
|
|
4831
5349
|
ev.end_line = ev.line;
|
|
4832
5350
|
ev.end_col = ev.col;
|
|
4833
5351
|
e->doc_begin = (size_t)-1;
|
|
5352
|
+
e->doc_begin_line = 0;
|
|
4834
5353
|
if (emit_now(e, &ev) != 0) {
|
|
4835
5354
|
return -2;
|
|
4836
5355
|
}
|