📄 libexo.c.svn-base
字号:
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 = 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 *)mystrdup((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 = 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 */
void
exo_print(struct exo_term_t *exo, FILE *stream)
{
if (!stream)
stream = stderr;
switch (exo->ec)
{
case ec_integer:
if (sizeof(exo_integer_t) == 4)
myfprintf(stream, "%u", exo->as_integer.val);
else
myfprintf(stream, "%lu", exo->as_integer.val);
break;
case ec_address:
if (sizeof(exo_address_t) == 4)
myfprintf(stream, "0x%x", exo->as_integer.val);
else
myfprintf(stream, "0x%lx", exo->as_integer.val);
break;
case ec_float:
fprintf(stream, "%f", exo->as_float.val);
break;
case ec_char:
fprintf(stream, "'");
print_char(exo->as_char.val, stream);
fprintf(stream, "'");
break;
case ec_string:
fprintf(stream, "\"");
print_string(exo->as_string.str, stream);
fprintf(stream, "\"");
break;
case ec_list:
{
struct exo_term_t *ent;
fprintf(stream, "(");
for (ent=exo->as_list.head; ent != NULL; ent=ent->next)
{
exo_print(ent, stream);
if (ent->next)
fprintf(stream, ", ");
}
fprintf(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 */
fprintf(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
fprintf(stream, " ");
if (i != exo->as_array.size-1 && i != last)
fprintf(stream, ", ");
}
fprintf(stream, "]");
}
break;
case ec_token:
fprintf(stream, "%s", exo->as_token.ent->str);
break;
case ec_blob:
{
int i, cr;
fprintf(stream, "{%d}<\n", exo->as_blob.size);
for (i=0; i < exo->as_blob.size; i++)
{
cr = FALSE;
if (i != 0 && (i % 38) == 0)
{
fprintf(stream, "\n");
cr = TRUE;
}
fprintf(stream, "%02x", exo->as_blob.data[i]);
}
if (!cr)
fprintf(stream, "\n");
fprintf(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 void
exo_err(char *err)
{
extern int line;
fprintf(stderr, "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 int errno;
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;
#ifdef HOST_HAS_QWORD
int_val = myatoq(tok_buf, &endp, /* parse base */10);
#else /* !HOST_HAS_QWORD */
int_val = strtoul(tok_buf, &endp, /* parse base */10);
#endif /* HOST_HAS_QWORD */
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;
#ifdef HOST_HAS_QWORD
addr_val = myatoq(tok_buf, &endp, /* parse base */16);
#else /* !HOST_HAS_QWORD */
addr_val = strtoul(tok_buf, &endp, /* parse base */16);
#endif /* HOST_HAS_QWORD */
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 + -