📄 libexo.c
字号:
/* libexo.c - EXO library main line routines *//* SimpleScalar(TM) Tool Suite * Copyright (C) 1994-2003 by Todd M. Austin, Ph.D. and SimpleScalar, LLC. * All Rights Reserved. * * THIS IS A LEGAL DOCUMENT, BY USING SIMPLESCALAR, * YOU ARE AGREEING TO THESE TERMS AND CONDITIONS. * * No portion of this work may be used by any commercial entity, or for any * commercial purpose, without the prior, written permission of SimpleScalar, * LLC (info@simplescalar.com). Nonprofit and noncommercial use is permitted * as described below. * * 1. SimpleScalar is provided AS IS, with no warranty of any kind, express * or implied. The user of the program accepts full responsibility for the * application of the program and the use of any results. * * 2. Nonprofit and noncommercial use is encouraged. SimpleScalar may be * downloaded, compiled, executed, copied, and modified solely for nonprofit, * educational, noncommercial research, and noncommercial scholarship * purposes provided that this notice in its entirety accompanies all copies. * Copies of the modified software can be delivered to persons who use it * solely for nonprofit, educational, noncommercial research, and * noncommercial scholarship purposes provided that this notice in its * entirety accompanies all copies. * * 3. ALL COMMERCIAL USE, AND ALL USE BY FOR PROFIT ENTITIES, IS EXPRESSLY * PROHIBITED WITHOUT A LICENSE FROM SIMPLESCALAR, LLC (info@simplescalar.com). * * 4. No nonprofit user may place any restrictions on the use of this software, * including as modified by the user, by any other authorized user. * * 5. Noncommercial and nonprofit users may distribute copies of SimpleScalar * in compiled or executable form as set forth in Section 2, provided that * either: (A) it is accompanied by the corresponding machine-readable source * code, or (B) it is accompanied by a written offer, with no time limit, to * give anyone a machine-readable copy of the corresponding source code in * return for reimbursement of the cost of distribution. This written offer * must permit verbatim duplication by anyone, or (C) it is distributed by * someone who received only the executable form, and is accompanied by a * copy of the written offer of source code. * * 6. SimpleScalar was developed by Todd M. Austin, Ph.D. The tool suite is * currently maintained by SimpleScalar LLC (info@simplescalar.com). US Mail: * 2395 Timbercrest Court, Ann Arbor, MI 48105. * * Copyright (C) 1994-2003 by Todd M. Austin, Ph.D. and SimpleScalar, LLC. */#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <ctype.h>#include <limits.h>#include <errno.h>#include <assert.h>#include "../host.h"#include "../misc.h"#include "../machine.h"#include "libexo.h"/* EXO term classes print strings */char *exo_class_str[ec_NUM] = { "integer", "address", "float", "char", "string" "list", "array", "token", "blob"};/* return the value of an escape sequence, ESCAPE is a pointer to the first character following '\', sets NEXT to first character after escape *//* A2.5.2 */static intintern_escape(char *esc, char **next){ int c, value, empty, count; switch (c = *esc++) { case 'x': /* \xhh hex value */ value = 0; empty = TRUE; while (1) { c = *esc++; if (!(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F') && !(c >= '0' && c <= '9')) { esc--; break; } value *=16; if (c >= 'a' && c <= 'f') value += c - 'a' + 10; if (c >= 'A' && c <= 'F') value += c - 'A' + 10; if (c >= '0' && c <= '9') value += c - '0'; empty = FALSE; } if (empty) fatal("\\x used with no trailing hex digits"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': /* \ooo octal value */ value = 0; count = 0; while ((c <= '7') && (c >= '0') && (count++ < 3)) { value = (value * 8) + (c - '0'); c = *esc++; } esc--; break; case '\\': case '\'': case '"': value = c; break; case 'n': value = '\n'; break; case 't': value = '\t'; break; case 'r': value = '\r'; break; case 'f': value = '\f'; break; case 'b': value = '\b'; break; case 'a': value = '\a'; break; case 'v': value = '\v'; break; case '?': value = c; break; case '(': case '{': case '[': case '%': value = c; warn("non-ANSI escape sequence `\\%c'", c); break; default: fatal("unknown escape, '\\' followed by char %x (`%c')", (int)c, c); } if (*next) *next = esc; return value;}/* return the value of an character literal sequence *//* A2.5.2 */static intintern_char(char *s, char **next){ unsigned char value; if (s[0] != '\'' || s[strlen(s)-1] != '\'') panic("mal-formed string constant"); if (s[1] != '\\') { value = (unsigned)s[1]; if (s[2] != '\'') panic("mal-formed string constant"); if (next) *next = s + 2; } else { /* escaped char constant */ value = intern_escape(s+2, next); } /* map to a signed char value */ value = (signed int)((unsigned char)((unsigned char)((unsigned int)value))); if (UCHAR_MAX < value) fatal("character constant out of range"); return value;}static voidprint_char(unsigned char c, FILE *stream){ switch (c) { case '\n': fprintf(stream, "\\n"); break; case '\\': fprintf(stream, "\\\\"); break; case '\'': fprintf(stream, "\\'"); break; case '\t': fprintf(stream, "\\t"); break; case '\r': fprintf(stream, "\\r"); break; case '\f': fprintf(stream, "\\f"); break; case '\b': fprintf(stream, "\\b"); break; case '\a': fprintf(stream, "\\a"); break; case '\v': fprintf(stream, "\\v"); break; default: if (isprint(c)) fprintf(stream, "%c", c); else fprintf(stream, "\\x%02x", c); }}/* expand all escapes in string STR, return pointer to allocation w/ result */static char *intern_string(char *str){ char *s, *istr; /* resulting string cannot be longer than STR */ s = istr = malloc(strlen(str)+1); if (!str || !*str || *str != '\"') /* " */ panic("mal-formed string constant"); /* skip `"' */ /* " */ str++; while (*str) { if (*str == '\\') *s++ = intern_escape(str+1, &str); else { /* A2.6 */ if (*str == '\n') warn("ANSI C forbids newline in character constant"); /* A2.6 */ if (*str == '"' && str[1] != '\0') panic("encountered `\"' embedded in string constant"); if (*str != '\"') /* " */ *s++ = *str; str++; } } *s = '\0'; return istr;}static voidprint_string(unsigned char *s, FILE *stream){ while (*s) { print_char(*s, stream); s++; }}/* bogus token value */#define TOKEN_BOGON 0static int token_id = TOKEN_BOGON + 1;#define TOKEN_HASH_SIZE 1024struct exo_token_t *token_hash[TOKEN_HASH_SIZE];/* hash a string */static unsigned longhash_str(char *s){ unsigned h = 0; while (*s) h = (h << 1) + *s++; return (h % TOKEN_HASH_SIZE);}/* intern token TOKEN_STR */struct exo_token_t *exo_intern(char *token_str) /* string to intern */{ int index; struct exo_token_t *ent; index = hash_str(token_str); for (ent=token_hash[index]; ent != NULL; ent=ent->next) { if (!strcmp(token_str, ent->str)) { /* got a match, return token entry */ return ent; } } /* not found, create a new entry */ ent = (struct exo_token_t *)calloc(1, sizeof(struct exo_token_t)); if (!ent) fatal("out of virtual memory"); ent->str = mystrdup(token_str); ent->token = token_id++; ent->next = token_hash[index]; token_hash[index] = ent; return ent;}/* intern token TOKEN_STR as value TOKEN */struct exo_token_t *exo_intern_as(char *token_str, /* string to intern */ int token) /* internment value */{ struct exo_token_t *ent;#if 0 if (token_id > token) fatal("token value is already in use");#endif ent = exo_intern(token_str); /* overide the default value */ ent->token = token;#if 0 if (ent->token != token) fatal("symbol `%s' was previously interned", token_str);#endif return ent;}/* allocate an EXO node, fill in its type */static struct exo_term_t *exo_alloc(enum exo_class_t ec){ struct exo_term_t *exo; exo = (struct exo_term_t *)calloc(1, sizeof(struct exo_term_t)); if (!exo) fatal("out of virtual memory"); exo->next = NULL; exo->ec = ec; return exo;}/* * create a new EXO term, usage: * * exo_new(ec_integer, (exo_integer_t)<int>); * exo_new(ec_address, (exo_integer_t)<int>); * exo_new(ec_float, (exo_float_t)<float>); * exo_new(ec_char, (int)<char>); * exo_new(ec_string, "<string>"); * exo_new(ec_list, <list_ent>..., NULL); * exo_new(ec_array, <size>, <array_ent>..., NULL); * exo_new(ec_token, "<token>"); */struct exo_term_t *exo_new(enum exo_class_t ec, ...){ struct exo_term_t *exo; va_list v; va_start(v, ec); exo = exo_alloc(ec); switch (ec) { case ec_integer: exo->as_integer.val = va_arg(v, exo_integer_t); break; case ec_address: exo->as_address.val = va_arg(v, exo_address_t); break; case ec_float: exo->as_float.val = va_arg(v, exo_float_t); break; case ec_char: exo->as_char.val = va_arg(v, int); break; case ec_string: { char *str; str = va_arg(v, char *); exo->as_string.str = (unsigned char *)mystrdup(str); } break; case ec_list: { struct exo_term_t *ent; exo->as_list.head = NULL; do { ent = va_arg(v, struct exo_term_t *); exo->as_list.head = exo_chain(exo->as_list.head, ent); } while (ent != NULL); } break; case ec_array: { int i; struct exo_term_t *ent; exo->as_array.size = va_arg(v, int); exo->as_array.array = (struct exo_term_t **) calloc(exo->as_array.size, sizeof(struct exo_term_t *)); if (!exo->as_array.array) fatal("out of virtual memory"); i = 0; do { ent = va_arg(v, struct exo_term_t *); if (ent != NULL) { if (i == exo->as_array.size) fatal("array constructor overflow"); SET_EXO_ARR(exo, i, ent); } i++; } while (ent != NULL); } break; case ec_token: { char *str; str = va_arg(v, char *); exo->as_token.ent = exo_intern(str); } break; case ec_blob: { unsigned size; unsigned char *data; size = va_arg(v, unsigned); data = va_arg(v, unsigned char *); exo->as_blob.size = size; exo->as_blob.data = malloc(size); if (data != NULL) memcpy(exo->as_blob.data, data, size); else memset(exo->as_blob.data, 0, size); } break; case ec_null: break; default: panic("bogus EXO class"); } va_end(v); return exo;}/* release an EXO term */voidexo_delete(struct exo_term_t *exo){ exo->next = NULL; switch (exo->ec) { case ec_integer: /* no extra storage */ exo->as_integer.val = 0; break; case ec_address: /* no extra storage */ exo->as_address.val = 0; break; case ec_float: /* no extra storage */ exo->as_float.val = 0.0; break; case ec_char: /* no extra storage */ exo->as_char.val = '\0'; break; case ec_string: free(exo->as_string.str); 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -