📄 libexo.cc
字号:
/* * libexo.c - EXO library main line routines * * This file is a part of the SimpleScalar tool suite written by * Todd M. Austin as a part of the Multiscalar Research Project. * * The tool suite is currently maintained by Doug Burger and Todd M. Austin. * * Copyright (C) 1997 by Todd M. Austin * * This source file is distributed "as is" in the hope that it will be * useful. The tool set comes with no warranty, and no author or * distributor accepts any responsibility for the consequences of its * use. * * Everyone is granted permission to copy, modify and redistribute * this tool set under the following conditions: * * This source code is distributed for non-commercial use only. * Please contact the maintainer for restrictions applying to * commercial use. * * Permission is granted to anyone to make or distribute copies * of this source code, either as received or modified, in any * medium, provided that all copyright notices, permission and * nonwarranty notices are preserved, and that the distributor * grants the recipient permission for further redistribution as * permitted by this document. * * Permission is granted to distribute this file in compiled * or executable form under the same conditions that apply for * source code, provided that either: * * A. it is accompanied by the corresponding machine-readable * source code, * 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 that they received concurrently. * * In other words, you are welcome to use, share and improve this * source file. You are forbidden to forbid anyone else to use, share * and improve what you give them. * * INTERNET: dburger@cs.wisc.edu * US Mail: 1210 W. Dayton Street, Madison, WI 53706 * */#include <ctype.h>#include <limits.h>#include <errno.h>#include <assert.h>#include <stdarg.h>#include <iostream>#include <string>#include "base/cprintf.hh"#include "base/misc.hh"#include "encumbered/eio/libexo.h"#include "sim/host.hh"using namespace std;/* EXO term classes print strings */char *exo_class_str[ec_NUM] = { "integer", "address", "float", "char", "string" "list", "array", "token", "blob"};#define ULL_MAX (ULL(9223372036854775807) * ULL(2) + 1)/* convert a string to a unsigned result */uint64_tmyatoq(char *nptr, char **endp, int base){ char *s, *save; int overflow; uint64_t cutoff, cutlim, i; unsigned char c; if (!nptr || !*nptr) panic("strtoll() passed a NULL string"); s = nptr; /* skip white space */ while (isspace((int)(*s))) ++s; if (*s == '\0') goto noconv; if (base == 0) { if (s[0] == '0' && toupper((int)s[1]) == 'X') base = 16; else base = 10; } if (base <= 1 || base > 36) panic("bogus base: %d", base); if (base == 16 && s[0] == '0' && toupper((int)s[1]) == 'X') s += 2; /* save the pointer so we can check later if anything happened */ save = s; cutoff = ULL_MAX / (unsigned long int) base; cutlim = ULL_MAX % (unsigned long int) base; overflow = 0; i = 0; for (c = *s; c != '\0'; c = *++s) { if (isdigit (c)) c -= '0'; else if (isalpha (c)) c = toupper(c) - 'A' + 10; else break; if (c >= base) break; /* check for overflow */ if (i > cutoff || (i == cutoff && c > cutlim)) overflow = 1; else { i *= (unsigned long int) base; i += c; } } /* check if anything actually happened */ if (s == save) goto noconv; /* store in ENDP the address of one character past the last character we converted */ if (endp != NULL) *endp = (char *) s; if (overflow) { errno = ERANGE; return ULL_MAX; } else { errno = 0; /* return the result of the appropriate sign */ return i; }noconv: /* there was no number to convert */ if (endp != NULL) *endp = (char *) nptr; return 0;}/* 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))); return value;}static voidprint_char(unsigned char c, ostream &stream){ switch (c) { case '\n': stream << "\\n"; break; case '\\': stream << "\\\\"; break; case '\'': stream << "\\'"; break; case '\t': stream << "\\t"; break; case '\r': stream << "\\r"; break; case '\f': stream << "\\f"; break; case '\b': stream << "\\b"; break; case '\a': stream << "\\a"; break; case '\v': stream << "\\v"; break; default: if (isprint(c)) stream << c; else ccprintf(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 = (char *)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, ostream &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 = strdup(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 *)strdup(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 = (unsigned char *)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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -