sxpr_parser.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 1,003 行 · 第 1/2 页

C
1,003
字号
static int get_escape(char c, char *d){    int err = 0;    switch(c){    case 'a':            *d = '\a'; break;    case 'b':            *d = '\b'; break;    case 'f':            *d = '\f'; break;    case 'n':            *d = '\n'; break;    case 'r':            *d = '\r'; break;    case 't':            *d = '\t'; break;    case 'v':            *d = '\v'; break;    case c_escape:       *d = c_escape; break;    case c_single_quote: *d = c_single_quote; break;    case c_double_quote: *d = c_double_quote; break;    default:        err = -EINVAL;    }    return err;}int Parser_ready(Parser *p){    return CONSP(p->val) || (p->start_state && CONSP(p->start_state->val));}Sxpr Parser_get_val(Parser *p){    Sxpr v = ONONE, w = ONONE;    if(CONSP(p->val)){    } else if (p->start_state && CONSP(p->start_state->val)){        p->val = p->start_state->val;        p->val = nrev(p->val);        p->start_state->val = ONULL;    }  else {        goto exit;    }    w = p->val;    v = CAR(w);    p->val = CDR(w);    hfree(w);  exit:    return v;}Sxpr Parser_get_all(Parser *p){    Sxpr v = ONULL;    if(CONSP(p->val)){        v = p->val;        p->val = ONONE;    } else if(p->start_state && CONSP(p->start_state->val)){        v = p->start_state->val;        p->start_state->val = ONULL;        v = nrev(v);    }    return v;}static int state_comment(Parser *p, char c){    int err = 0;    if(c == '\n' || Parser_at_eof(p)){        Parser_pop(p);    } else {        err = input_char(p, c);    }    return err;}static int begin_comment(Parser *p, char c){    int err = 0;    err = Parser_push(p, state_comment, "comment");    if(err) goto exit;    err = input_char(p, c);  exit:    return err;}static int end_string(Parser *p){    int err = 0;    err = Parser_string(p);    if(err) goto exit;    err = Parser_return(p);  exit:    return err;}static int octaldone(Parser *p){    int err = 0;    char d = (char)(p->state->ival & 0xff);    Parser_pop(p);    err = Parser_input_char(p, d);    return err;}static int octaldigit(Parser *p, int d){    int err = 0;    p->state->ival *= 8;    p->state->ival += d;     p->state->count++;    if(err) goto exit;    if(p->state->ival < 0 || p->state->ival > 0xff){        err = Parser_error(p);        goto exit;    }    if(p->state->count == 3){        err = octaldone(p);    }  exit:    return err;}static int state_octal(Parser *p, char c){    int err = 0;    if(Parser_at_eof(p)){        err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF);        goto exit;    } else if('0' <= c && c <= '7'){        err = octaldigit(p, c - '0');    } else {        err = octaldone(p);        if(err) goto exit;        Parser_input_char(p, c);    }  exit:    return err;}static int hexdone(Parser *p){    int err = 0;    char d = (char)(p->state->ival & 0xff);    Parser_pop(p);    err = Parser_input_char(p, d);    return err;}    static int hexdigit(Parser *p, int d){    int err = 0;    p->state->ival *= 16;    p->state->ival += d;     p->state->count++;    if(err) goto exit;    if(p->state->ival < 0 || p->state->ival > 0xff){        err = Parser_error(p);        goto exit;    }    if(p->state->count == 2){        err = hexdone(p);    }  exit:    return err;}    static int state_hex(Parser *p, char c){    int err = 0;    if(Parser_at_eof(p)){        err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF);        goto exit;    } else if('0' <= c && c <= '9'){        err = hexdigit(p, c - '0');    } else if('A' <= c && c <= 'F'){        err = hexdigit(p, c - 'A' + 10);    } else if('a' <= c && c <= 'f'){        err = hexdigit(p, c - 'a' + 10);    } else if(p->state->count){        err = hexdone(p);        if(err) goto exit;        Parser_input_char(p, c);    }  exit:    return err;}static int state_escape(Parser *p, char c){    int err = 0;    char d;    if(Parser_at_eof(p)){        err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF);        goto exit;    }    if(get_escape(c, &d) == 0){        err = save_char(p, d);        if(err) goto exit;        Parser_pop(p);    } else if(c == 'x'){        p->state->fn = state_hex;        p->state->ival = 0;        p->state->count = 0;    } else {        p->state->fn = state_octal;        p->state->ival = 0;        p->state->count = 0;        err = Parser_input_char(p, c);    }  exit:    return err;}static int state_string(Parser *p, char c){    int err = 0;    if(Parser_at_eof(p)){        err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF);    } else if(c == p->state->delim){        err = end_string(p);    } else if(c == '\\'){        err = Parser_push(p, state_escape, "escape");    } else {        err = save_char(p, c);    }    return err;}static int begin_string(Parser *p, char c){    int err = 0;    err = Parser_push(p, state_string, "string");    if(err) goto exit;    new_token(p);    p->state->delim = c;  exit:    return err;}static int end_atom(Parser *p){    int err = 0;    err = Parser_atom(p);    if(err) goto exit;    err = Parser_return(p);  exit:    return err;}static int state_atom(Parser *p, char c){    int err = 0;    if(Parser_at_eof(p)){        err = end_atom(p);    } else if(is_separator(p, c) ||              in_space_class(c) ||              in_comment_class(c)){        err = end_atom(p);        if(err) goto exit;        err = Parser_input_char(p, c);    } else {        err = save_char(p, c);    }  exit:    return err;}static int begin_atom(Parser *p, char c){    int err = 0;    err = Parser_push(p, state_atom, "atom");    if(err) goto exit;    new_token(p);    err = save_char(p, c);  exit:    return err;}static int end_data(Parser *p){    int err = 0;    err = Parser_data(p);    if(err) goto exit;    err = Parser_return(p);  exit:    return err;}static int counted_data(Parser *p, char c){    int err = 0;    err = save_char(p, c);    if(err) goto exit;    if(token_len(p) == p->state->count){        err = end_data(p);    }  exit:    return err;}static int counted_data_count(Parser *p, char c){    int err = 0;    if(c == p->state->delim){        new_token(p);        p->state->count = p->state->ival;        p->state->fn = counted_data;    } else if('0' <= c && c <= '9'){        p->state->ival *= 10;        p->state->ival += c - '0';    } else {        err = -EINVAL;    }    return err;}static int quoted_data(Parser *p, char c){    int err = 0;    int count = p->state->count;    err = save_char(p, c);    if(err) goto exit;    // Check that buf is longer than delim and    // ends with delim. If so, trim delim off and return.    if((token_len(p) >= count) &&       !memcmp(p->tok_end - count, p->buf, count)){        p->tok_end -= count;        end_data(p);    }  exit:    return err;}static int quoted_data_delim(Parser *p, char c){    // Saves the delim in the token buffer.    int err = 0;    err = save_char(p, c);    if(err) goto exit;    if(c == p->state->delim){        p->state->fn = quoted_data;        p->state->count = token_len(p);        // Advance the token pointer past the delim.        p->tok = p->tok_end;    }  exit:    return err;}static int state_data(Parser *p, char c){    // Quoted data:    // <<delim< anything not containing delimiter<delim<    // Where 'delim' is anything not containing '<'.    // Counted data:    // <*nnn..* N bytes    // Where nnn... is N in decimal (    int err = 0;    switch(c){    case c_data_count:        p->state->delim = c;        p->state->fn = counted_data_count;        p->state->ival = 0;        new_token(p);        break;    case c_data_quote:        p->state->delim = c;        p->state->fn = quoted_data_delim;        new_token(p);        err = save_char(p, c);        break;    default:        err = Parser_error(p);        break;    }    return err;}static int begin_data(Parser *p, char c){    int err = 0;    err = Parser_push(p, state_data, "data");    if(err) goto exit;    new_token(p);  exit:    return err;}static int state_list(Parser *p, char c){    int err = 0;    dprintf(">\n");    if(Parser_at_eof(p)){        err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF);    } else if(c == c_list_close){        p->state->val = nrev(p->state->val);        err = Parser_return(p);    } else {        err = state_start(p, c);    }    dprintf("< err=%d\n", err);    return err;    }static int begin_list(Parser *p, char c){    return Parser_push(p, state_list, "list");}static int state_start(Parser *p, char c){    int err = 0;    dprintf(">\n");    if(Parser_at_eof(p)){        err = Parser_return(p);    } else if(in_space_class(c)){        //skip    } else if(in_comment_class(c)){        begin_comment(p, c);    } else if(c == c_list_open){        begin_list(p, c);    } else if(c == c_list_close){        err = Parser_error(p);    } else if(in_string_quote_class(c)){        begin_string(p, c);    } else if(c == c_data_open){        begin_data(p, c);    } else if(in_printable_class(c)){        begin_atom(p, c);    } else if(c == 0x04){        //ctrl-D, EOT: end-of-text.        Parser_input_eof(p);    } else {        err = Parser_error(p);    }    dprintf("< err=%d\n", err);    return err;}int begin_start(Parser *p, char c){    int err = 0;    dprintf(">\n");    err = Parser_push(p, state_start, "start");    if(err) goto exit;    p->start_state = p->state;  exit:    dprintf("< err=%d\n", err);    return err;}int Parser_input_char(Parser *p, char c){    int err = 0;    if(Parser_at_eof(p)){        //skip;    } else {        input_char(p, c);    }    if(!p->state){        err = p->begin(p, c);        if(err) goto exit;    }    err = p->state->fn(p, c);  exit:    return err;}int Parser_input_eof(Parser *p){    int err = 0;    p->eof = 1;    err = Parser_input_char(p, IOSTREAM_EOF);    return err;}int Parser_input(Parser *p, char *buf, int buf_n){    int err = 0;    int i = 0;    dprintf("> buf_n=%d\n", buf_n);    if(buf_n <= 0){        buf_n = 0;        err = Parser_input_eof(p);        goto exit;    }    dprintf("> buf=|%*s|\n", buf_n, buf);    for(i = 0; i < buf_n; i++){        err = Parser_input_char(p, buf[i]);        if(err) goto exit;    }  exit:    err = (err < 0 ? err : buf_n);    dprintf("< err=%d\n", err);    return err;}#ifdef SXPR_PARSER_MAIN/* Stuff for standalone testing. */#include "file_stream.h"//#include "string_stream.h"/** Main program for testing. * Parses input and prints it. * * @param argc number of arguments * @param argv arguments * @return error code */int main(int argc, char *argv[]){    Parser *pin;    int err = 0;    char buf[1024];    int k;    Sxpr obj;    int i = 0;    pin = Parser_new();    Parser_set_error_stream(pin, iostdout);    dprintf("> parse...\n");    while(1){        k = fread(buf, 1, 100, stdin);        if(k>=0){            buf[k+1] = '\0';        }        err = Parser_input(pin, buf, k);        while(Parser_ready(pin)){            obj = Parser_get_val(pin);            printf("obj %d\n", i++);            objprint(iostdout, obj, 0); printf("\n");        }        if(k <= 0) break;    }    dprintf("> err=%d\n", err);    return 0;}#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?