@@ -175,6 +175,10 @@ static const char line_feed[ZONE_BLOCK_SIZE] = { '\n', '\0' };
175
175
// special constant used as data on errors
176
176
static const char end_of_file [ZONE_BLOCK_SIZE ] = { '\0' };
177
177
178
+ #define READ_ALL_DATA (1)
179
+ #define NO_MORE_DATA (2)
180
+ #define MISSING_QUOTE (3)
181
+
178
182
extern int32_t zone_open_file (
179
183
parser_t * , const char * path , size_t length , zone_file_t * * );
180
184
@@ -213,6 +217,8 @@ static never_inline int32_t raise_error(
213
217
return raise_error((parser), (code), __VA_ARGS__); \
214
218
} while (0)
215
219
220
+ #define SYNTAX_ERROR (parser , ...) \
221
+ RAISE_ERROR((parser), ZONE_SYNTAX_ERROR, __VA_ARGS__)
216
222
#define OUT_OF_MEMORY (parser , ...) \
217
223
RAISE_ERROR((parser), ZONE_OUT_OF_MEMORY, __VA_ARGS__)
218
224
#define READ_ERROR (parser , ...) \
@@ -240,14 +246,14 @@ warn_unused_result
240
246
static really_inline int32_t refill (parser_t * parser )
241
247
{
242
248
// refill if possible (i.e. not if string or if file is empty)
243
- if (parser -> file -> end_of_file != ZONE_HAVE_DATA )
249
+ if (parser -> file -> end_of_file )
244
250
return 0 ;
245
251
246
252
// move unread data to start of buffer
247
253
char * data = parser -> file -> buffer .data + parser -> file -> buffer .index ;
248
254
// account for non-terminated character-strings
249
- if (* parser -> file -> fields .head )
250
- data = (char * )* parser -> file -> fields .head ;
255
+ if (* parser -> file -> fields .head [ 0 ] != '\0' )
256
+ data = (char * )parser -> file -> fields .head [ 0 ] ;
251
257
252
258
* parser -> file -> fields .head = parser -> file -> buffer .data ;
253
259
// account for unread data left in buffer
@@ -305,20 +311,27 @@ static really_inline int32_t advance(parser_t *parser)
305
311
parser -> file -> fields .tape [0 ] = parser -> file -> fields .tail [1 ];
306
312
parser -> file -> fields .head = parser -> file -> fields .tape ;
307
313
parser -> file -> fields .tail =
308
- parser -> file -> fields .tape + (!! parser -> file -> fields .tape [0 ]);
314
+ parser -> file -> fields .tape + (* parser -> file -> fields .tape [0 ] != '\0' );
309
315
// reset delimiters
310
316
parser -> file -> delimiters .head = parser -> file -> delimiters .tape ;
311
317
parser -> file -> delimiters .tail = parser -> file -> delimiters .tape ;
312
318
319
+ // delayed syntax error
320
+ if (parser -> file -> end_of_file == MISSING_QUOTE )
321
+ SYNTAX_ERROR (parser , "Missing closing quote" );
313
322
if ((code = refill (parser )) < 0 )
314
323
return code ;
315
324
316
325
if (reindex (parser )) {
317
326
// save non-terminated token
318
327
parser -> file -> fields .tail [0 ] = parser -> file -> fields .tail [-1 ];
319
328
parser -> file -> fields .tail -- ;
329
+ // delay syntax error so correct line number is available
330
+ if (parser -> file -> end_of_file == NO_MORE_DATA &&
331
+ * parser -> file -> fields .tail [1 ] == '"' )
332
+ parser -> file -> end_of_file = MISSING_QUOTE ;
320
333
} else {
321
- parser -> file -> fields .tail [1 ] = NULL ;
334
+ parser -> file -> fields .tail [1 ] = end_of_file ;
322
335
}
323
336
324
337
// FIXME: if tail is still equal to tape, refill immediately?!
@@ -331,7 +344,6 @@ static really_inline int32_t advance(parser_t *parser)
331
344
// start-of-line must be false if start of tape is not start of buffer
332
345
if (* parser -> file -> fields .head != parser -> file -> buffer .data )
333
346
parser -> file -> start_of_line = false;
334
- //parser->file->start_of_line = start_of_line;
335
347
return 0 ;
336
348
}
337
349
@@ -378,6 +390,7 @@ static really_inline bool is_end_of_file(const token_t *token)
378
390
}
379
391
380
392
393
+ #undef SYNTAX_ERROR
381
394
#define SYNTAX_ERROR (parser , token , ...) \
382
395
do { \
383
396
zone_log((parser), ZONE_ERROR, __VA_ARGS__); \
@@ -425,7 +438,7 @@ static never_inline void maybe_take(parser_t *parser, token_t *token)
425
438
return ;
426
439
} else if (token -> code == END_OF_FILE ) {
427
440
int32_t code ;
428
- if (parser -> file -> end_of_file == ZONE_NO_MORE_DATA ) {
441
+ if (parser -> file -> end_of_file == NO_MORE_DATA ) {
429
442
if (parser -> file -> grouped )
430
443
SYNTAX_ERROR (parser , token , "Missing closing brace" );
431
444
token -> data = end_of_file ;
@@ -565,7 +578,7 @@ static never_inline int32_t maybe_take_contiguous(
565
578
parser -> file -> delimiters .head ++ ;
566
579
return 0 ;
567
580
} else if (token -> code == END_OF_FILE ) {
568
- if (parser -> file -> end_of_file == ZONE_NO_MORE_DATA )
581
+ if (parser -> file -> end_of_file == NO_MORE_DATA )
569
582
SYNTAX_ERROR (parser , token , "Missing %s in %s" , NAME (field ), NAME (type ));
570
583
if ((code = advance (parser )) < 0 )
571
584
ERROR (parser , token , code );
@@ -666,7 +679,7 @@ static never_inline int32_t maybe_take_quoted(
666
679
parser -> file -> delimiters .head ++ ;
667
680
return 0 ;
668
681
} else if (token -> code == END_OF_FILE ) {
669
- if (parser -> file -> end_of_file == ZONE_NO_MORE_DATA )
682
+ if (parser -> file -> end_of_file == NO_MORE_DATA )
670
683
SYNTAX_ERROR (parser , token , "Missing %s in %s" , NAME (field ), NAME (type ));
671
684
if ((code = advance (parser )) < 0 )
672
685
ERROR (parser , token , code );
@@ -773,7 +786,7 @@ static never_inline int32_t maybe_take_contiguous_or_quoted(
773
786
parser -> file -> delimiters .head ++ ;
774
787
return 0 ;
775
788
} else if (token -> code == END_OF_FILE ) {
776
- if (parser -> file -> end_of_file == ZONE_NO_MORE_DATA )
789
+ if (parser -> file -> end_of_file == NO_MORE_DATA )
777
790
SYNTAX_ERROR (parser , token , "Missing %s in %s" , NAME (field ), NAME (type ));
778
791
if ((code = advance (parser )) < 0 )
779
792
ERROR (parser , token , code );
@@ -894,7 +907,7 @@ static never_inline int32_t maybe_take_delimiter(
894
907
return 0 ;
895
908
}
896
909
} else if (token -> code == END_OF_FILE ) {
897
- if (parser -> file -> end_of_file == ZONE_NO_MORE_DATA ) {
910
+ if (parser -> file -> end_of_file == NO_MORE_DATA ) {
898
911
if (parser -> file -> grouped )
899
912
SYNTAX_ERROR (parser , token , "Missing closing brace" );
900
913
token -> data = end_of_file ;
0 commit comments