📄 libexo.cc
字号:
exo->as_string.str = NULL; break; case ec_list: { struct exo_term_t *ent, *next_ent; for (ent=exo->as_list.head; ent != NULL; ent = next_ent) { next_ent = ent->next; exo_delete(ent); } exo->as_list.head = NULL; } break; case ec_array: { int i; for (i=0; i < exo->as_array.size; i++) { if (exo->as_array.array[i] != NULL) exo_delete(exo->as_array.array[i]); } free(exo->as_array.array); exo->as_array.array = NULL; exo->as_array.size = 0; } break; case ec_token: /* no extra storage */ exo->as_token.ent = NULL; break; case ec_blob: /* free the blob data */ free(exo->as_blob.data); exo->as_blob.data = NULL; break; case ec_null: /* no extra storage */ break; default: panic("bogus EXO class"); } exo->ec = (enum exo_class_t)0; /* release the node */ free(exo);}/* chain two EXO lists together, FORE is attached on the end of AFT */struct exo_term_t *exo_chain(struct exo_term_t *fore, struct exo_term_t *aft){ struct exo_term_t *exo, *prev; if (!fore && !aft) return NULL; if (!fore) return aft; /* find the tail of FORE */ for (prev=NULL,exo=fore; exo != NULL; prev=exo,exo=exo->next) /* nada */; assert(prev); /* link onto the tail of FORE */ prev->next = aft; return fore;}/* copy an EXO node */struct exo_term_t *exo_copy(struct exo_term_t *exo){ struct exo_term_t *new_exo; /* NULL copy */ if (!exo) return NULL; new_exo = exo_alloc(exo->ec); *new_exo = *exo; /* the next link is always blown away on a copy */ new_exo->next = NULL; switch (new_exo->ec) { case ec_integer: case ec_address: case ec_float: case ec_char: case ec_string: case ec_list: case ec_token: /* no internal parts to copy */ break; case ec_array: { int i; /* copy the array */ new_exo->as_array.array = (struct exo_term_t **) calloc(new_exo->as_array.size, sizeof(struct exo_term_t *)); for (i=0; i<new_exo->as_array.size; i++) { SET_EXO_ARR(new_exo, i, EXO_ARR(exo, i)); } } break; case ec_blob: new_exo->as_blob.data = (unsigned char *)malloc(new_exo->as_array.size); memcpy(new_exo->as_blob.data, exo->as_blob.data, new_exo->as_array.size); break; default: panic("bogus EXO class"); } return new_exo;}/* deep copy an EXO structure */struct exo_term_t *exo_deepcopy(struct exo_term_t *exo){ struct exo_term_t *new_exo; /* NULL copy */ if (!exo) return NULL; new_exo = exo_copy(exo); switch (new_exo->ec) { case ec_integer: case ec_address: case ec_float: case ec_char: case ec_token: /* exo_copy() == exo_deepcopy() for these node classes */ break; case ec_string: /* copy the referenced string */ new_exo->as_string.str = (unsigned char *)strdup((char *)exo->as_string.str); break; case ec_list: /* copy all list elements */ { struct exo_term_t *elt, *new_elt, *new_list; new_list = NULL; for (elt=new_exo->as_list.head; elt != NULL; elt=elt->next) { new_elt = exo_deepcopy(elt); new_list = exo_chain(new_list, new_elt); } new_exo->as_list.head = new_list; } break; case ec_array: /* copy all array elements */ { int i; for (i=0; i<new_exo->as_array.size; i++) { SET_EXO_ARR(new_exo, i, exo_deepcopy(EXO_ARR(exo, i))); } } break; case ec_blob: new_exo->as_blob.data = (unsigned char *)malloc(new_exo->as_array.size); memcpy(new_exo->as_blob.data, exo->as_blob.data, new_exo->as_array.size); break; default: panic("bogus EXO class"); } return new_exo;}/* print an EXO term */voidexo_print(struct exo_term_t *exo, ostream &stream){ switch (exo->ec) { case ec_integer: ccprintf(stream, "%u", exo->as_integer.val); break; case ec_address: ccprintf(stream, "%#x", exo->as_integer.val); break; case ec_float: ccprintf(stream, "%f", exo->as_float.val); break; case ec_char: stream << "'"; print_char(exo->as_char.val, stream); stream << "'"; break; case ec_string: stream << "\""; print_string(exo->as_string.str, stream); stream << "\""; break; case ec_list: { struct exo_term_t *ent; stream << "("; for (ent=exo->as_list.head; ent != NULL; ent=ent->next) { exo_print(ent, stream); if (ent->next) stream << ", "; } stream << ")"; } break; case ec_array: { int i, last; /* search for last first non-NULL entry */ for (last=exo->as_array.size-1; last >= 0; last--) if (EXO_ARR(exo, last) != NULL) break; /* LAST == index of last non-NULL array entry */ ccprintf(stream, "{%d}[", exo->as_array.size); for (i = 0; i < exo->as_array.size && i <= last; i++) { if (exo->as_array.array[i] != NULL) exo_print(exo->as_array.array[i], stream); else stream << " "; if (i != exo->as_array.size-1 && i != last) stream << ", "; } stream << "]"; } break; case ec_token: stream << exo->as_token.ent->str; break; case ec_blob: { int i, cr = 0; ccprintf(stream, "{%d}<\n", exo->as_blob.size); for (i = 0; i < exo->as_blob.size; i++) { cr = false; if (i != 0 && (i % 38) == 0) { stream << "\n"; cr = true; } ccprintf(stream, "%02x", exo->as_blob.data[i]); } if (!cr) stream << "\n"; stream << ">"; } break; default: panic("bogus EXO class"); }}/* (f)lex external defs */extern int yylex(void);extern int yy_nextchar(void);extern char *yytext;extern FILE *yyin;static voidexo_err(char *err){ extern int line; ccprintf(cerr, "EXO parse error: line %d: %s\n", line, err); exit(1);}/* read one EXO term from STREAM */struct exo_term_t *exo_read(FILE *stream){ int tok; char tok_buf[1024], *endp; struct exo_term_t *ent = NULL; extern void yy_setstream(FILE *); /* make sure we have a valid stream */ if (!stream) stream = stdin; yy_setstream(stream); /* make local copies of everything, allows arbitrary recursion */ tok = yylex(); strcpy(tok_buf, yytext); switch (tok) { case lex_integer: { exo_integer_t int_val; /* attempt integer conversion */ errno = 0; int_val = myatoq(tok_buf, &endp, /* parse base */10); if (!errno && !*endp) { /* good conversion */ ent = exo_new(ec_integer, int_val); } else exo_err("cannot parse integer literal"); } break; case lex_address: { exo_address_t addr_val; /* attempt address conversion */ errno = 0; addr_val = myatoq(tok_buf, &endp, /* parse base */16); if (!errno && !*endp) { /* good conversion */ ent = exo_new(ec_address, addr_val); } else exo_err("cannot parse address literal"); } break; case lex_float: { exo_float_t float_val; /* attempt double conversion */ errno = 0; float_val = strtod(tok_buf, &endp); if (!errno && !*endp) { /* good conversion */ ent = exo_new(ec_float, float_val); } else exo_err("cannot parse floating point literal"); } break; case lex_char: { int c; c = intern_char(tok_buf, &endp); if (!endp) exo_err("cannot convert character literal"); ent = exo_new(ec_char, c); } break; case lex_string: { char *s; s = intern_string(tok_buf); ent = exo_new(ec_string, s); free(s); } break; case lex_token: ent = exo_new(ec_token, tok_buf); break; case lex_byte: exo_err("unexpected blob byte encountered"); break; case '(': { struct exo_term_t *elt; ent = exo_new(ec_list, NULL); if (yy_nextchar() != ')') { /* not an empty list */ do { elt = exo_read(stream); if (!elt) exo_err("unexpected end-of-file"); ent->as_list.head = exo_chain(ent->as_list.head, elt); /* consume optional commas */ if (yy_nextchar() == ',') yylex(); } while (yy_nextchar() != ')'); } /* read tail delimiter */ tok = yylex(); if (tok != ')') exo_err("expected ')'"); } break; case ')': exo_err("unexpected ')' encountered"); break; case '<': exo_err("unexpected '<' encountered"); break; case '>': exo_err("unexpected '>' encountered"); break; case '{': { int cnt, size; struct exo_term_t *elt; /* get the size */ elt = exo_read(stream); if (!elt || elt->ec != ec_integer) exo_err("badly formed array size"); /* record the size of the array/blob */ size = (int)elt->as_integer.val; /* done with the EXO integer */ exo_delete(elt); /* read the array delimiters */ tok = yylex(); if (tok != '}') exo_err("expected '}'"); tok = yylex(); switch (tok) { case '[': /* array definition */ /* allocate an array definition */ ent = exo_new(ec_array, size, NULL); /* read until array is full or tail delimiter encountered */ if (yy_nextchar() != ']') { /* not an empty array */ cnt = 0; do { if (cnt == ent->as_array.size) exo_err("too many initializers for array"); /* NULL element? */ if (yy_nextchar() == ',') { elt = NULL; } else { elt = exo_read(stream); if (!elt) exo_err("unexpected end-of-file"); } SET_EXO_ARR(ent, cnt, elt); cnt++; /* consume optional commas */ if (yy_nextchar() == ',') yylex(); } while (yy_nextchar() != ']'); } /* read tail delimiter */ tok = yylex(); if (tok != ']') exo_err("expected ']'"); break; case '<': /* blob definition */ /* allocate an array definition */ ent = exo_new(ec_blob, size, /* zero contents */NULL); /* read until blob is full */ if (yy_nextchar() != '>') { unsigned int byte_val; /* not an empty array */ cnt = 0; for (;;) { /* read next blob byte */ tok = yylex(); if (tok == lex_byte) { if (cnt == ent->as_blob.size) exo_err("too many initializers for blob"); /* attempt hex conversion */ errno = 0; byte_val = strtoul(yytext, &endp, /* parse base */16); if (errno != 0 || *endp != '\0') exo_err("cannot parse blob byte literal"); if (byte_val > 255) panic("bogus byte value"); ent->as_blob.data[cnt] = byte_val; cnt++; } else if (tok == '>') break; else exo_err("unexpected character in blob"); } }#if 0 /* zero tail is OK... */ if (cnt != ent->as_blob.size) exo_err("not enough initializers for blob");#endif break; default: exo_err("expected '[' or '<'"); } } break; case '}': exo_err("unexpected '}' encountered"); break; case ',': exo_err("unexpected ',' encountered"); break; case '[': { int i, cnt; struct exo_term_t *list, *elt, *next_elt; /* compute the array size */ list = NULL; if (yy_nextchar() == ']') exo_err("unsized array has no initializers"); cnt = 0; do { /* NULL element? */ if (yy_nextchar() == ',') { elt = exo_new(ec_null); } else { elt = exo_read(stream); if (!elt) exo_err("unexpected end-of-file"); } cnt++; list = exo_chain(list, elt); /* consume optional commas */ if (yy_nextchar() == ',') yylex(); } while (yy_nextchar() != ']'); /* read tail delimiter */ tok = yylex(); if (tok != ']') exo_err("expected ']'"); /* create the array */ assert(cnt > 0); ent = exo_new(ec_array, cnt, NULL); /* fill up the array */ for (i=0,elt=list; i<cnt; i++,elt=next_elt) { assert(elt != NULL); next_elt = elt->next; if (elt->ec == ec_null) { SET_EXO_ARR(ent, cnt, NULL); exo_delete(ent); } else { SET_EXO_ARR(ent, cnt, elt); elt->next = NULL; } } } break; case ']': exo_err("unexpected ']' encountered"); break; case lex_eof: /* nothing to read */ ent = NULL; break; default: panic("bogus token"); } return ent;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -