mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
339 lines
8.9 KiB
C
339 lines
8.9 KiB
C
/* Distributed under the OSI-approved BSD 3-Clause License.
|
|
See accompanying file LICENSE.rst for details. */
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "llpkgc_file.h"
|
|
|
|
#define CALLBACK_MAYBE(PARSER, NAME) \
|
|
do { \
|
|
const llpkgc_file_settings_t* settings; \
|
|
settings = \
|
|
(const llpkgc_file_settings_t*) (PARSER)->llpkgc_file__settings; \
|
|
if(settings == NULL || settings->NAME == NULL) { \
|
|
err = 0; \
|
|
break; \
|
|
} \
|
|
err = settings->NAME((PARSER)); \
|
|
} while(0)
|
|
|
|
#define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN) \
|
|
do { \
|
|
const llpkgc_file_settings_t* settings; \
|
|
settings = \
|
|
(const llpkgc_file_settings_t*) (PARSER)->llpkgc_file__settings; \
|
|
if(settings == NULL || settings->NAME == NULL) { \
|
|
err = 0; \
|
|
break; \
|
|
} \
|
|
err = settings->NAME((PARSER), (START), (LEN)); \
|
|
if(err == -1) { \
|
|
err = PFCE_USER; \
|
|
llpkgc_file_set_error_reason((PARSER), "Span callback error in " #NAME); \
|
|
} \
|
|
} while(0)
|
|
|
|
enum llpkgc_file_unfinished_state {
|
|
PFUS_NONE = 0,
|
|
PFUS_IDENT = 1,
|
|
PFUS_BAREWORDS = 2,
|
|
PFUS_EXPECT_VALUE = 3,
|
|
PFUS_VALUE = 4,
|
|
PFUS_VALUE_LITERAL = 5,
|
|
PFUS_VALUE_SUBSTITUTION = 6,
|
|
};
|
|
|
|
void llpkgc_file_init(llpkgc_file_t* parser,
|
|
const llpkgc_file_settings_t* settings) {
|
|
llpkgc_file__internal_init(parser);
|
|
|
|
parser->llpkgc_file__settings = (void*) settings;
|
|
}
|
|
|
|
void llpkgc_file_reset(llpkgc_file_t* parser) {
|
|
llpkgc_file_settings_t* settings = parser->llpkgc_file__settings;
|
|
void* data = parser->data;
|
|
|
|
llpkgc_file__internal_init(parser);
|
|
|
|
parser->llpkgc_file__settings = settings;
|
|
parser->data = data;
|
|
}
|
|
|
|
void llpkgc_file_settings_init(llpkgc_file_settings_t* settings) {
|
|
memset(settings, 0, sizeof(*settings));
|
|
}
|
|
|
|
llpkgc_file_errno_t llpkgc_file_execute(llpkgc_file_t* parser, const char* data,
|
|
size_t len) {
|
|
return llpkgc_file__internal_execute(parser, data, data + len);
|
|
}
|
|
|
|
int llpkgc_file__line_begin(llpkgc_file_t* s, const char* p, const char* endp);
|
|
int llpkgc_file__ident_span(llpkgc_file_t* s, const char* p, const char* endp);
|
|
|
|
llpkgc_file_errno_t llpkgc_file_finish(llpkgc_file_t* parser) {
|
|
int err = PFCE_OK;
|
|
|
|
if(parser->error == PFCE_LOOKAHEAD) {
|
|
if(parser->error_pos == NULL) {
|
|
parser->error = PFCE_INTERNAL;
|
|
parser->reason = "Missing lookahead error position";
|
|
return parser->error;
|
|
}
|
|
|
|
parser->llpkgc_file__eof = 1;
|
|
llpkgc_file_resume(parser);
|
|
err = llpkgc_file_execute(parser, parser->error_pos, 1);
|
|
parser->llpkgc_file__eof = 0;
|
|
|
|
if(err != PFCE_OK) {
|
|
return err;
|
|
}
|
|
|
|
parser->llpkgc_file__lookahead = 0;
|
|
} else if(parser->error != 0) {
|
|
return parser->error;
|
|
}
|
|
|
|
switch(parser->llpkgc_file__unfinished) {
|
|
case PFUS_IDENT:
|
|
case PFUS_BAREWORDS:
|
|
CALLBACK_MAYBE(parser, on_barewords_complete);
|
|
if(err != PFCE_OK) {
|
|
parser->error = err;
|
|
return err;
|
|
}
|
|
|
|
CALLBACK_MAYBE(parser, on_value_complete);
|
|
if(err != PFCE_OK) {
|
|
parser->error = err;
|
|
return err;
|
|
}
|
|
break;
|
|
|
|
case PFUS_EXPECT_VALUE:
|
|
case PFUS_VALUE:
|
|
CALLBACK_MAYBE(parser, on_value_complete);
|
|
if(err != PFCE_OK) {
|
|
parser->error = err;
|
|
return err;
|
|
}
|
|
break;
|
|
|
|
case PFUS_VALUE_LITERAL:
|
|
CALLBACK_MAYBE(parser, on_value_literal_complete);
|
|
if(err != PFCE_OK) {
|
|
parser->error = err;
|
|
return err;
|
|
}
|
|
|
|
CALLBACK_MAYBE(parser, on_value_complete);
|
|
if(err != PFCE_OK) {
|
|
parser->error = err;
|
|
return err;
|
|
}
|
|
break;
|
|
|
|
case PFUS_VALUE_SUBSTITUTION:
|
|
parser->reason = "Invalid EOF state";
|
|
parser->error = PFCE_UNFINISHED;
|
|
return PFCE_UNFINISHED;
|
|
|
|
case PFUS_NONE:
|
|
break;
|
|
}
|
|
|
|
CALLBACK_MAYBE(parser, on_pkgc_complete);
|
|
return err;
|
|
}
|
|
|
|
void llpkgc_file_pause(llpkgc_file_t* parser) {
|
|
if(parser->error != PFCE_OK) {
|
|
return;
|
|
}
|
|
|
|
parser->error = PFCE_PAUSED;
|
|
parser->reason = "Paused";
|
|
}
|
|
|
|
void llpkgc_file_resume(llpkgc_file_t* parser) {
|
|
if(parser->error != PFCE_PAUSED && parser->error != PFCE_LOOKAHEAD) {
|
|
return;
|
|
}
|
|
|
|
parser->error = 0;
|
|
}
|
|
|
|
llpkgc_file_errno_t llpkgc_file_get_errno(const llpkgc_file_t* parser) {
|
|
return parser->error;
|
|
}
|
|
|
|
const char* llpkgc_file_get_error_reason(const llpkgc_file_t* parser) {
|
|
return parser->reason;
|
|
}
|
|
|
|
void llpkgc_file_set_error_reason(llpkgc_file_t* parser, const char* reason) {
|
|
parser->reason = reason;
|
|
}
|
|
|
|
const char* llpkgc_file_get_error_pos(const llpkgc_file_t* parser) {
|
|
return parser->error_pos;
|
|
}
|
|
|
|
const char* llpkgc_file_errno_name(llpkgc_file_errno_t err) {
|
|
switch(err) {
|
|
case PFCE_OK:
|
|
return "PFCE_OK";
|
|
case PFCE_INTERNAL:
|
|
return "PFCE_INTERNAL";
|
|
case PFCE_PAUSED:
|
|
return "PFCE_PAUSED";
|
|
case PFCE_USER:
|
|
return "PFCE_USER";
|
|
case PFCE_UNFINISHED:
|
|
return "PFCE_UNFINISHED";
|
|
case PFCE_LOOKAHEAD:
|
|
return "PFCE_LOOKAHEAD";
|
|
}
|
|
return "INVALID_ERRNO";
|
|
}
|
|
|
|
int llpkgc_file__lookahead(llpkgc_file_t* s, const char* p, const char* endp) {
|
|
if(p == endp) {
|
|
llpkgc_file_set_error_reason(s, "Invalid lookahead state");
|
|
return PFCE_INTERNAL;
|
|
}
|
|
|
|
if(p + 1 == endp) {
|
|
if(s->llpkgc_file__eof != 0) {
|
|
s->llpkgc_file__lookahead = 0;
|
|
return 3;
|
|
}
|
|
|
|
s->llpkgc_file__lookahead = (uint8_t) *p;
|
|
return PFCE_LOOKAHEAD;
|
|
}
|
|
|
|
s->llpkgc_file__lookahead = 0;
|
|
|
|
if(*p != '$') {
|
|
llpkgc_file_set_error_reason(s, "Invalid lookahead state");
|
|
return PFCE_INTERNAL;
|
|
}
|
|
|
|
switch(p[1]) {
|
|
case '{':
|
|
return 1;
|
|
case '$':
|
|
return 2;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int llpkgc_file__lookahead_backslash(llpkgc_file_t* s, const char* p,
|
|
const char* endp) {
|
|
if(p == endp) {
|
|
llpkgc_file_set_error_reason(s, "Invalid lookahead state");
|
|
return PFCE_INTERNAL;
|
|
}
|
|
|
|
if(p + 1 == endp) {
|
|
if(s->llpkgc_file__eof != 0) {
|
|
s->llpkgc_file__lookahead = 0;
|
|
return 4;
|
|
}
|
|
|
|
s->llpkgc_file__lookahead = (uint8_t) *p;
|
|
return 5;
|
|
}
|
|
|
|
s->llpkgc_file__lookahead = 0;
|
|
|
|
if(*p != '\\') {
|
|
llpkgc_file_set_error_reason(s, "Invalid lookahead state");
|
|
return PFCE_INTERNAL;
|
|
}
|
|
|
|
switch(p[1]) {
|
|
case '\r':
|
|
case '\n':
|
|
return 1;
|
|
case '#':
|
|
return 2;
|
|
case '\\':
|
|
return 3;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int llpkgc_file__line_begin(llpkgc_file_t* s, const char* p, const char* endp) {
|
|
int err;
|
|
CALLBACK_MAYBE(s, on_line_begin);
|
|
return err;
|
|
}
|
|
|
|
int llpkgc_file__ident_span(llpkgc_file_t* s, const char* p, const char* endp) {
|
|
int err;
|
|
SPAN_CALLBACK_MAYBE(s, on_ident, p, endp - p);
|
|
return err;
|
|
}
|
|
|
|
int llpkgc_file__prop_decl_complete(llpkgc_file_t* s, const char* p,
|
|
const char* endp) {
|
|
int err;
|
|
CALLBACK_MAYBE(s, on_property_complete);
|
|
return err;
|
|
}
|
|
|
|
int llpkgc_file__var_decl_complete(llpkgc_file_t* s, const char* p,
|
|
const char* endp) {
|
|
int err;
|
|
CALLBACK_MAYBE(s, on_variable_complete);
|
|
return err;
|
|
}
|
|
|
|
int llpkgc_file__barewords_decl_complete(llpkgc_file_t* s, const char* p,
|
|
const char* endp) {
|
|
int err;
|
|
CALLBACK_MAYBE(s, on_barewords_complete);
|
|
return err;
|
|
}
|
|
|
|
int llpkgc_file__lit_span(llpkgc_file_t* s, const char* p, const char* endp) {
|
|
int err;
|
|
SPAN_CALLBACK_MAYBE(s, on_value_literal, p, endp - p);
|
|
return err;
|
|
}
|
|
|
|
int llpkgc_file__lit_complete(llpkgc_file_t* s, const char* p,
|
|
const char* endp) {
|
|
int err;
|
|
CALLBACK_MAYBE(s, on_value_literal_complete);
|
|
return err;
|
|
}
|
|
|
|
int llpkgc_file__sub_span(llpkgc_file_t* s, const char* p, const char* endp) {
|
|
int err;
|
|
SPAN_CALLBACK_MAYBE(s, on_value_substitution, p, endp - p);
|
|
return err;
|
|
}
|
|
|
|
int llpkgc_file__sub_complete(llpkgc_file_t* s, const char* p,
|
|
const char* endp) {
|
|
int err;
|
|
CALLBACK_MAYBE(s, on_value_substitution_complete);
|
|
return err;
|
|
}
|
|
|
|
int llpkgc_file__val_complete(llpkgc_file_t* s, const char* p,
|
|
const char* endp) {
|
|
int err;
|
|
CALLBACK_MAYBE(s, on_value_complete);
|
|
return err;
|
|
}
|