From be7a372a67596072f25c91e0d2f51797fd65f156 Mon Sep 17 00:00:00 2001 From: Jesse van den Kieboom Date: Fri, 23 Dec 2005 16:07:08 +0000 Subject: [PATCH] Initial import --- gnoemoe/parser/Makefile.am | 29 + gnoemoe/parser/ast.c | 480 +++++ gnoemoe/parser/ast.h | 268 +++ gnoemoe/parser/config.h | 334 ++++ gnoemoe/parser/functions.c | 576 ++++++ gnoemoe/parser/functions.h | 137 ++ gnoemoe/parser/gm-parser.c | 131 ++ gnoemoe/parser/gm-parser.h | 22 + gnoemoe/parser/keywords.c | 305 ++++ gnoemoe/parser/keywords.gperf | 94 + gnoemoe/parser/keywords.h | 59 + gnoemoe/parser/list.c | 438 +++++ gnoemoe/parser/list.h | 65 + gnoemoe/parser/numbers.c | 462 +++++ gnoemoe/parser/numbers.h | 51 + gnoemoe/parser/parsen.h | 74 + gnoemoe/parser/parser.c | 3224 +++++++++++++++++++++++++++++++++ gnoemoe/parser/parser.h | 131 ++ gnoemoe/parser/parser.y | 1282 +++++++++++++ gnoemoe/parser/storage.c | 317 ++++ gnoemoe/parser/storage.h | 123 ++ gnoemoe/parser/streams.c | 276 +++ gnoemoe/parser/streams.h | 68 + gnoemoe/parser/structures.h | 195 ++ gnoemoe/parser/sym_table.c | 207 +++ gnoemoe/parser/sym_table.h | 96 + gnoemoe/parser/tokens.h | 43 + gnoemoe/parser/utils.c | 432 +++++ gnoemoe/parser/utils.h | 168 ++ gnoemoe/parser/version.c | 52 + gnoemoe/parser/version.h | 101 ++ 31 files changed, 10240 insertions(+) create mode 100644 gnoemoe/parser/Makefile.am create mode 100644 gnoemoe/parser/ast.c create mode 100644 gnoemoe/parser/ast.h create mode 100644 gnoemoe/parser/config.h create mode 100644 gnoemoe/parser/functions.c create mode 100644 gnoemoe/parser/functions.h create mode 100644 gnoemoe/parser/gm-parser.c create mode 100644 gnoemoe/parser/gm-parser.h create mode 100644 gnoemoe/parser/keywords.c create mode 100644 gnoemoe/parser/keywords.gperf create mode 100644 gnoemoe/parser/keywords.h create mode 100644 gnoemoe/parser/list.c create mode 100644 gnoemoe/parser/list.h create mode 100644 gnoemoe/parser/numbers.c create mode 100644 gnoemoe/parser/numbers.h create mode 100644 gnoemoe/parser/parsen.h create mode 100644 gnoemoe/parser/parser.c create mode 100644 gnoemoe/parser/parser.h create mode 100644 gnoemoe/parser/parser.y create mode 100644 gnoemoe/parser/storage.c create mode 100644 gnoemoe/parser/storage.h create mode 100644 gnoemoe/parser/streams.c create mode 100644 gnoemoe/parser/streams.h create mode 100644 gnoemoe/parser/structures.h create mode 100644 gnoemoe/parser/sym_table.c create mode 100644 gnoemoe/parser/sym_table.h create mode 100644 gnoemoe/parser/tokens.h create mode 100644 gnoemoe/parser/utils.c create mode 100644 gnoemoe/parser/utils.h create mode 100644 gnoemoe/parser/version.c create mode 100644 gnoemoe/parser/version.h diff --git a/gnoemoe/parser/Makefile.am b/gnoemoe/parser/Makefile.am new file mode 100644 index 0000000..51d36b2 --- /dev/null +++ b/gnoemoe/parser/Makefile.am @@ -0,0 +1,29 @@ +INCLUDES = \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ + -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ + -I$(top_srcdir) \ + -I$(top_srcdir)/gnoemoe \ + @PACKAGE_CFLAGS@ + +AM_YFLAGS = -y -d + +noinst_LTLIBRARIES = libparser.la + +libparser_la_SOURCES = \ + parser.y parser.h parsen.h \ + ast.c ast.h \ + functions.c functions.h \ + gm-parser.c gm-parser.h \ + keywords.c keywords.h \ + list.c list.h \ + utils.c utils.h \ + numbers.c numbers.h \ + storage.c storage.h \ + streams.c streams.h \ + sym_table.c sym_table.h \ + version.c version.h \ + structures.h \ + tokens.h + +keywords.c: keywords.gperf + gperf -CtT --ignore-case -k1,3,$$ keywords.gperf > keywords.c diff --git a/gnoemoe/parser/ast.c b/gnoemoe/parser/ast.c new file mode 100644 index 0000000..ecd5537 --- /dev/null +++ b/gnoemoe/parser/ast.c @@ -0,0 +1,480 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#include + +#include "ast.h" +#include "config.h" +#include "list.h" +#include "structures.h" +#include "sym_table.h" +#include "storage.h" +#include "utils.h" + +struct entry { + void *ptr; + Memory_Type type; +}; + +static int pool_size, next_pool_slot; +static struct entry *pool; + +void +begin_code_allocation() +{ + pool_size = 10; + next_pool_slot = 0; + pool = mymalloc(pool_size * sizeof(struct entry), M_AST_POOL); +} + +void +end_code_allocation(int aborted) +{ + if (aborted) { + int i; + + for (i = 0; i < next_pool_slot; i++) { + if (pool[i].ptr != 0) + myfree(pool[i].ptr, pool[i].type); + } + } + myfree(pool, M_AST_POOL); +} + +static void * +allocate(int size, Memory_Type type) +{ + if (next_pool_slot >= pool_size) { /* enlarge the pool */ + struct entry *new_pool; + int i; + + pool_size *= 2; + new_pool = mymalloc(pool_size * sizeof(struct entry), M_AST_POOL); + for (i = 0; i < next_pool_slot; i++) { + new_pool[i] = pool[i]; + } + myfree(pool, M_AST_POOL); + pool = new_pool; + } + pool[next_pool_slot].type = type; + return pool[next_pool_slot++].ptr = mymalloc(size, type); +} + +static void +deallocate(void *ptr) +{ + int i; + + for (i = 0; i < next_pool_slot; i++) { + if (ptr == pool[i].ptr) { + myfree(ptr, pool[i].type); + pool[i].ptr = 0; + return; + } + } +} + +char * +alloc_string(const char *buffer) +{ + char *string = allocate(strlen(buffer) + 1, M_STRING); + + strcpy(string, buffer); + return string; +} + +void +dealloc_string(char *str) +{ + deallocate(str); +} + +double * +alloc_float(double value) +{ + double *d = allocate(sizeof(double), M_FLOAT); + + *d = value; + return d; +} + +void +dealloc_node(void *node) +{ + deallocate(node); +} + +Stmt * +alloc_stmt(enum Stmt_Kind kind) +{ + Stmt *result = allocate(sizeof(Stmt), M_AST); + + result->kind = kind; + result->next = 0; + return result; +} + +Cond_Arm * +alloc_cond_arm(Expr * condition, Stmt * stmt) +{ + Cond_Arm *result = allocate(sizeof(Cond_Arm), M_AST); + + result->condition = condition; + result->stmt = stmt; + result->next = 0; + return result; +} + +Except_Arm * +alloc_except(int id, Arg_List * codes, Stmt * stmt) +{ + Except_Arm *result = allocate(sizeof(Except_Arm), M_AST); + + result->id = id; + result->codes = codes; + result->stmt = stmt; + result->label = 0; + result->next = 0; + return result; +} + +Expr * +alloc_expr(enum Expr_Kind kind) +{ + Expr *result = allocate(sizeof(Expr), M_AST); + + result->kind = kind; + return result; +} + +Expr * +alloc_var(var_type type) +{ + Expr *result = alloc_expr(EXPR_VAR); + + result->e.var.type = type; + return result; +} + +Expr * +alloc_binary(enum Expr_Kind kind, Expr * lhs, Expr * rhs) +{ + Expr *result = alloc_expr(kind); + + result->e.bin.lhs = lhs; + result->e.bin.rhs = rhs; + return result; +} + +Expr * +alloc_verb(Expr * obj, Expr * verb, Arg_List * args) +{ + Expr *result = alloc_expr(EXPR_VERB); + + result->e.verb.obj = obj; + result->e.verb.verb = verb; + result->e.verb.args = args; + return result; +} + +Arg_List * +alloc_arg_list(enum Arg_Kind kind, Expr * expr) +{ + Arg_List *result = allocate(sizeof(Arg_List), M_AST); + + result->kind = kind; + result->expr = expr; + result->next = 0; + return result; +} + +Scatter * +alloc_scatter(enum Scatter_Kind kind, int id, Expr * expr) +{ + Scatter *sc = allocate(sizeof(Scatter), M_AST); + + sc->kind = kind; + sc->id = id; + sc->expr = expr; + sc->next = 0; + sc->label = sc->next_label = 0; + + return sc; +} + +static void free_expr(Expr *); + +static void +free_arg_list(Arg_List * args) +{ + Arg_List *arg, *next_arg; + + for (arg = args; arg; arg = next_arg) { + next_arg = arg->next; + free_expr(arg->expr); + myfree(arg, M_AST); + } +} + +static void +free_scatter(Scatter * sc) +{ + Scatter *next_sc; + + for (; sc; sc = next_sc) { + next_sc = sc->next; + if (sc->expr) + free_expr(sc->expr); + myfree(sc, M_AST); + } +} + +static void +free_expr(Expr * expr) +{ + switch (expr->kind) { + + case EXPR_VAR: + free_var(expr->e.var); + break; + + case EXPR_ID: + case EXPR_LENGTH: + /* Do nothing. */ + break; + + case EXPR_PROP: + case EXPR_INDEX: + case EXPR_PLUS: + case EXPR_MINUS: + case EXPR_TIMES: + case EXPR_DIVIDE: + case EXPR_MOD: + case EXPR_AND: + case EXPR_OR: + case EXPR_EQ: + case EXPR_NE: + case EXPR_LT: + case EXPR_LE: + case EXPR_GT: + case EXPR_GE: + case EXPR_IN: + case EXPR_ASGN: + case EXPR_EXP: + free_expr(expr->e.bin.lhs); + free_expr(expr->e.bin.rhs); + break; + + case EXPR_COND: + free_expr(expr->e.cond.condition); + free_expr(expr->e.cond.consequent); + free_expr(expr->e.cond.alternate); + break; + + case EXPR_VERB: + free_expr(expr->e.verb.obj); + free_expr(expr->e.verb.verb); + free_arg_list(expr->e.verb.args); + break; + + case EXPR_RANGE: + free_expr(expr->e.range.base); + free_expr(expr->e.range.from); + free_expr(expr->e.range.to); + break; + + case EXPR_CALL: + free_arg_list(expr->e.call.args); + break; + + case EXPR_NEGATE: + case EXPR_NOT: + free_expr(expr->e.expr); + break; + + case EXPR_LIST: + free_arg_list(expr->e.list); + break; + + case EXPR_CATCH: + free_expr(expr->e.catch.try); + free_arg_list(expr->e.catch.codes); + if (expr->e.catch.except) + free_expr(expr->e.catch.except); + break; + + case EXPR_SCATTER: + free_scatter(expr->e.scatter); + break; + + default: + break; + } + + myfree(expr, M_AST); +} + +void +free_stmt(Stmt * stmt) +{ + Stmt *next_stmt; + Cond_Arm *arm, *next_arm; + Except_Arm *except, *next_e; + + for (; stmt; stmt = next_stmt) { + next_stmt = stmt->next; + + switch (stmt->kind) { + + case STMT_COND: + for (arm = stmt->s.cond.arms; arm; arm = next_arm) { + next_arm = arm->next; + free_expr(arm->condition); + free_stmt(arm->stmt); + myfree(arm, M_AST); + } + if (stmt->s.cond.otherwise) + free_stmt(stmt->s.cond.otherwise); + break; + + case STMT_LIST: + free_expr(stmt->s.list.expr); + free_stmt(stmt->s.list.body); + break; + + case STMT_RANGE: + free_expr(stmt->s.range.from); + free_expr(stmt->s.range.to); + free_stmt(stmt->s.range.body); + break; + + case STMT_WHILE: + free_expr(stmt->s.loop.condition); + free_stmt(stmt->s.loop.body); + break; + + case STMT_FORK: + free_expr(stmt->s.fork.time); + free_stmt(stmt->s.fork.body); + break; + + case STMT_EXPR: + case STMT_RETURN: + if (stmt->s.expr) + free_expr(stmt->s.expr); + break; + + case STMT_TRY_EXCEPT: + free_stmt(stmt->s.catch.body); + for (except = stmt->s.catch.excepts; except; except = next_e) { + next_e = except->next; + free_arg_list(except->codes); + free_stmt(except->stmt); + myfree(except, M_AST); + } + break; + + case STMT_TRY_FINALLY: + free_stmt(stmt->s.finally.body); + free_stmt(stmt->s.finally.handler); + break; + + case STMT_BREAK: + case STMT_CONTINUE: + break; /* Nothing extra to free */ + + default: + break; + } + + myfree(stmt, M_AST); + } +} + +char rcsid_ast[] = "$Id: ast.c,v 1.1.1.1 2004/02/26 13:13:54 jesse Exp $"; + +/* + * $Log: ast.c,v $ + * Revision 1.1.1.1 2004/02/26 13:13:54 jesse + * Initial import into CVS + * + * Revision 1.3 1998/12/14 13:17:26 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.2 1997/03/03 04:18:21 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:44:59 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.4 1996/02/08 07:11:54 pavel + * Updated copyright notice for 1996. Release 1.8.0beta1 (again). + * + * Revision 2.3 1996/02/08 05:49:08 pavel + * Renamed err/logf() to errlog/oklog(). Added support for floating-point and + * the X^Y expression. Added named WHILE loops and the BREAK and CONTINUE + * statements. Release 1.8.0beta1. + * + * Revision 2.2 1996/01/16 07:11:46 pavel + * Added alloc/free for scatters. Release 1.8.0alpha6. + * + * Revision 2.1 1995/12/31 03:14:13 pavel + * Added EXPR_LENGTH case to free_expr(). Release 1.8.0alpha4. + * + * Revision 2.0 1995/11/30 04:16:25 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.12 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.11 1992/10/23 19:16:20 pavel + * Eliminated all uses of the useless macro NULL. + * + * Revision 1.10 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.9 1992/08/31 22:21:28 pjames + * Changed some `char *'s to `const char *' + * + * Revision 1.8 1992/08/28 23:12:13 pjames + * Added ASGN_RANGE arm of `free_expr()'. + * + * Revision 1.7 1992/08/28 16:11:25 pjames + * Changed myfree(*, M_STRING) to free_str(*). + * Removed free_ast_var. Use free_var instead. + * Removed ak_dealloc_string. Use free_str instead. + * + * Revision 1.6 1992/08/14 00:01:17 pavel + * Converted to a typedef of `var_type' = `enum var_type'. + * + * Revision 1.5 1992/08/10 16:53:07 pjames + * Updated #includes. + * + * Revision 1.4 1992/07/30 21:20:25 pjames + * Checks for NULL before freeing M_STRINGS. + * + * Revision 1.3 1992/07/27 17:57:06 pjames + * Changed myfree(*, M_AST) to (*, M_STRING) when * was a (char *) + * because that is how they are allocated. + * + * Revision 1.2 1992/07/20 23:48:48 pavel + * Added rcsid_ declaration to hold the RCS identification + * string. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/ast.h b/gnoemoe/parser/ast.h new file mode 100644 index 0000000..e823c87 --- /dev/null +++ b/gnoemoe/parser/ast.h @@ -0,0 +1,268 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#ifndef AST_h +#define AST_h 1 + +typedef struct Stmt Stmt; +typedef struct Expr Expr; +typedef struct Arg_List Arg_List; +typedef struct Cond_Arm Cond_Arm; +typedef struct Except_Arm Except_Arm; +typedef struct Scatter Scatter; + +#include "config.h" +#include "structures.h" +#include "parser.h" +#include "sym_table.h" + +struct Expr_Binary { + Expr *lhs, *rhs; +}; + +enum Arg_Kind { + ARG_NORMAL, ARG_SPLICE +}; + +struct Arg_List { + Arg_List *next; + enum Arg_Kind kind; + Expr *expr; +}; + +enum Scatter_Kind { + SCAT_REQUIRED, SCAT_OPTIONAL, SCAT_REST +}; + +struct Scatter { + Scatter *next; + enum Scatter_Kind kind; + int id; + Expr *expr; + /* These fields for convenience during code generation and decompiling */ + int label, next_label; +}; + +struct Expr_Call { + unsigned func; + Arg_List *args; +}; + +struct Expr_Verb { + Expr *obj, *verb; + Arg_List *args; +}; + +struct Expr_Range { + Expr *base, *from, *to; +}; + +struct Expr_Cond { + Expr *condition, *consequent, *alternate; +}; + +struct Expr_Catch { + Expr *try; + Arg_List *codes; + Expr *except; +}; + +enum Expr_Kind { + EXPR_VAR, EXPR_ID, + EXPR_PROP, EXPR_VERB, + EXPR_INDEX, EXPR_RANGE, + EXPR_ASGN, EXPR_CALL, + EXPR_PLUS, EXPR_MINUS, EXPR_TIMES, EXPR_DIVIDE, EXPR_MOD, EXPR_EXP, + EXPR_NEGATE, + EXPR_AND, EXPR_OR, EXPR_NOT, + EXPR_EQ, EXPR_NE, EXPR_LT, EXPR_LE, EXPR_GT, EXPR_GE, + EXPR_IN, EXPR_LIST, EXPR_COND, + EXPR_CATCH, EXPR_LENGTH, EXPR_SCATTER, + SizeOf_Expr_Kind /* The last element is also the number of elements... */ +}; + +union Expr_Data { + Var var; + int id; + struct Expr_Binary bin; + struct Expr_Call call; + struct Expr_Verb verb; + struct Expr_Range range; + struct Expr_Cond cond; + struct Expr_Catch catch; + Expr *expr; + Arg_List *list; + Scatter *scatter; +}; + +struct Expr { + enum Expr_Kind kind; + union Expr_Data e; +}; + +struct Cond_Arm { + Cond_Arm *next; + Expr *condition; + Stmt *stmt; +}; + +struct Except_Arm { + Except_Arm *next; + int id; + Arg_List *codes; + Stmt *stmt; + /* This field is for convenience during code generation and decompiling */ + int label; +}; + +struct Stmt_Cond { + Cond_Arm *arms; + Stmt *otherwise; +}; + +struct Stmt_List { + int id; + Expr *expr; + Stmt *body; +}; + +struct Stmt_Range { + int id; + Expr *from, *to; + Stmt *body; +}; + +struct Stmt_Loop { + int id; + Expr *condition; + Stmt *body; +}; + +struct Stmt_Fork { + int id; + Expr *time; + Stmt *body; +}; + +struct Stmt_Catch { + Stmt *body; + Except_Arm *excepts; +}; + +struct Stmt_Finally { + Stmt *body; + Stmt *handler; +}; + +enum Stmt_Kind { + STMT_COND, STMT_LIST, STMT_RANGE, STMT_WHILE, STMT_FORK, STMT_EXPR, + STMT_RETURN, STMT_TRY_EXCEPT, STMT_TRY_FINALLY, STMT_BREAK, STMT_CONTINUE +}; + +union Stmt_Data { + struct Stmt_Cond cond; + struct Stmt_List list; + struct Stmt_Range range; + struct Stmt_Loop loop; + struct Stmt_Fork fork; + struct Stmt_Catch catch; + struct Stmt_Finally finally; + Expr *expr; + int exit; +}; + +struct Stmt { + Stmt *next; + enum Stmt_Kind kind; + union Stmt_Data s; +}; + + +extern void begin_code_allocation(void); +extern void end_code_allocation(int); + +extern Stmt *alloc_stmt(enum Stmt_Kind); +extern Cond_Arm *alloc_cond_arm(Expr *, Stmt *); +extern Expr *alloc_expr(enum Expr_Kind); +extern Expr *alloc_var(var_type); +extern Expr *alloc_binary(enum Expr_Kind, Expr *, Expr *); +extern Expr *alloc_verb(Expr *, Expr *, Arg_List *); +extern Arg_List *alloc_arg_list(enum Arg_Kind, Expr *); +extern Except_Arm *alloc_except(int, Arg_List *, Stmt *); +extern Scatter *alloc_scatter(enum Scatter_Kind, int, Expr *); +extern char *alloc_string(const char *); +extern double *alloc_float(double); + +extern void dealloc_node(void *); +extern void dealloc_string(char *); +extern void free_stmt(Stmt *); + +#endif /* !AST_h */ + +/* + * $Log: ast.h,v $ + * Revision 1.1.1.1 2004/02/26 13:13:54 jesse + * Initial import into CVS + * + * Revision 1.3 1998/12/14 13:17:28 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.2 1997/03/03 04:18:22 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:02 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.3 1996/02/08 05:59:43 pavel + * Updated copyright notice for 1996. Added exponentiation expression, named + * WHILE loops, BREAK and CONTINUE statements, support for floating-point. + * Release 1.8.0beta1. + * + * Revision 2.2 1996/01/16 07:13:43 pavel + * Add support for scattering assignment. Release 1.8.0alpha6. + * + * Revision 2.1 1995/12/31 03:14:38 pavel + * Added EXPR_LENGTH. Release 1.8.0alpha4. + * + * Revision 2.0 1995/11/30 04:50:19 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.8 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.7 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.6 1992/08/31 22:21:43 pjames + * Changed some `char *'s to `const char *' + * + * Revision 1.5 1992/08/28 23:13:36 pjames + * Added ASGN_RANGE to assignment type enumeration. + * Added range arm to assigment union. + * + * Revision 1.4 1992/08/14 00:15:28 pavel + * Removed trailing comma in an enumeration. + * + * Revision 1.3 1992/08/14 00:01:11 pavel + * Converted to a typedef of `var_type' = `enum var_type'. + * + * Revision 1.2 1992/07/30 21:21:21 pjames + * Removed max_stack from AST structures. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/config.h b/gnoemoe/parser/config.h new file mode 100644 index 0000000..23a0fb3 --- /dev/null +++ b/gnoemoe/parser/config.h @@ -0,0 +1,334 @@ +/* config.h. Generated automatically by configure. */ + +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +/* If you're looking at this as `config.h.in', then this file is full of + * `#undef' preprocessor directives. The `configure' command, which generates + * `config.h' from `config.h.in', replaces appropriate ones of those `#undef's + * with `#define's, depending upon characteristics of the operating system, + * and comments out all of the others. + */ + +#ifndef Config_H +#define Config_H 1 + +/* Some systems require that certain preprocessor symbols be defined in order + * for certain pieces of the C library to be available. If one of the + * following is defined, then your system is one such. + */ + +/* #undef _ALL_SOURCE */ +/* #undef _POSIX_SOURCE */ +/* #undef _MINIX */ +/* #undef _POSIX_1_SOURCE */ +/* #undef _HPUX_SOURCE */ + +/* The following symbols describe whether or not certain functions are declared + * in header files on your system and, if so, where. If, on your system, the + * functions `memcmp', `memcpy', etc. are not declared in , but are + * instead in , then NEED_MEMORY_H will be defined. Similarly, if + * `malloc', `free', etc. are not declared in , but are instead in + * , then NEED_MALLOC_H will be defined. If your system has the file + * , then NEED_BSDTYPES_H will be defined. + * + * The various NDECL_* symbols are defined if the named function or variable is + * not declared in its standard place, which is given in a comment after each + * symbol. In several of the cases below, the absence of a declaration for the + * named function or variable is taken in the server code to imply the similar + * absence of declarations for several other related functions or variables. + */ + +#define NEED_MEMORY_H 1 +/* #undef NEED_MALLOC_H */ +/* #undef NEED_BSDTYPES_H */ +#define NEED_SELECT_H 1 + +/* #undef NDECL_TOLOWER */ /* */ +/* #undef NDECL_FCNTL */ /* */ +/* #undef NDECL_HTONL */ /* */ +/* #undef NDECL_IOCTL */ /* */ +/* #undef NDECL_POLL */ /* */ +/* #undef NDECL_KILL */ /* */ +/* #undef NDECL_SIGEMPTYSET */ /* */ +/* #undef NDECL_SIGPROCMASK */ /* */ +#define NDECL_SIGRELSE 1 /* */ +/* #undef NDECL_ACCEPT */ /* */ +/* #undef NDECL_BIND */ /* */ +/* #undef NDECL_SHUTDOWN */ /* */ +/* #undef NDECL_FSTAT */ /* */ +/* #undef NDECL_FCLOSE */ /* */ +/* #undef NDECL_PERROR */ /* */ +/* #undef NDECL_REMOVE */ /* */ +/* #undef NDECL_VFPRINTF */ /* */ +/* #undef NDECL_RANDOM */ /* */ +/* #undef NDECL_SRANDOM */ /* */ +/* #undef NDECL_STRTOD */ /* */ +/* #undef NDECL_STRTOL */ /* */ +/* #undef NDECL_STRTOUL */ /* */ +/* #undef NDECL_BZERO */ /* */ +/* #undef NDECL_MEMCPY */ /* */ +/* #undef NDECL_MEMSET */ /* */ +/* #undef NDECL_STRERROR */ /* */ +/* #undef NDECL_GETITIMER */ /* */ +/* #undef NDECL_SETITIMER */ /* */ +/* #undef NDECL_SELECT */ /* */ +/* #undef NDECL_STRFTIME */ /* */ +/* #undef NDECL_TIME */ /* */ +/* #undef NDECL_TZNAME */ /* */ +#define NDECL_T_OPEN 1 /* */ +#define NDECL_T_ERRLIST 1 /* */ +/* #undef NDECL_FORK */ /* */ +/* #undef NDECL_WAITPID */ /* */ + +/* Some systems declare bzero() in instead of in . */ + +/* #undef BZERO_IN_STDLIB_H */ + +/* Some header files are only present on certain kinds of UNIXes (e.g., BSD, + * System V, or POSIX). The following symbols are defined only if the named + * header file exists on your system. + */ + +/* #undef HAVE_MACHINE_ENDIAN_H */ +#define HAVE_STDLIB_H 1 +#define HAVE_SYS_CDEFS_H 1 +#define HAVE_UNISTD_H 1 + +/* Some POSIX-standard typedefs are not present in some systems. The following + * symbols are defined as aliases for their usual definitions if they are not + * defined on your system. + */ + +/* #undef pid_t */ +/* #undef mode_t */ +/* #undef size_t */ + +/* To implement the LambdaMOO built-in function `ctime()', which converts a + * number of seconds since the POSIX `epoch' into a human-readable time/date + * string, the server code needs to be able to find out the name of the local + * time zone. This information is available in an obscure way from the ANSI + * standard function `strftime()', but many systems still don't implement it. + * The server has code to cope with this case, though, if your system maintains + * the time-zone name in one of two common places. Appropriate ones of the + * following symbols will be defined to tell the server how to get time-zone + * information on your system. + */ + +#define HAVE_STRFTIME 1 +/* #undef TM_IN_SYS_TIME */ +#define HAVE_TM_ZONE 1 +/* #undef HAVE_TZNAME */ + +/* Some compilers `almost' conform to the ANSI C standard, in that they provide + * the vast majority of the features and constructs used by the server code, + * but one common failing with which the code can cope is the lack of support + * for the `const' keyword. If your compiler doesn't support `const', then + * this symbol will be defined as a macro that expands into nothing, thus + * eliding all uses of the keyword in the code. + */ + +/* #undef const */ + +/* Some sites have installed GCC improperly or incompletely, thereby requiring + * the server to be compiled with the `-traditional' switch. That disables the + * `const', `volatile' or `signed' keywords, which we need. Thus, for GCC, we + * do these little substitutions to always refer to its `hidden' names for + * these keywords. + */ + +#if defined(__GNUC__) && !HAVE_SYS_CDEFS_H +# define const __const__ +# define volatile __volatile__ +# define signed __signed__ +#endif + +/* Certain functions used by the server are `optional', in the sense that the + * server can provide its own definition if necessary. In some cases, there + * are a number of common ways to do the same thing, differing by system type + * (e.g., BSD, System V, or POSIX). The following symbols are defined if your + * system provides the named functions. + */ + +#define HAVE_CRYPT 1 +#define HAVE_MATHERR 1 +#define HAVE_MKFIFO 1 +#define HAVE_REMOVE 1 +#define HAVE_RENAME 1 +#define HAVE_SELECT 1 +#define HAVE_POLL 1 +#define HAVE_STRERROR 1 +#define HAVE_STRTOUL 1 +#define HAVE_RANDOM 1 +#define HAVE_LRAND48 1 +#define HAVE_WAITPID 1 +/* #undef HAVE_WAIT2 */ +#define HAVE_WAIT3 1 +#define HAVE_SIGEMPTYSET 1 +#define HAVE_SIGPROCMASK 1 +#define HAVE_SIGSETMASK 1 +#define HAVE_SIGRELSE 1 + +/* It used to be very much the fashion in UNIX programming to make use of + * certain standard header files depend on the programmer having #include'd + * other standard header files first. This is obviously losing and, amazingly, + * is also losing favor, replaced by the notion that every header file should + * #include whatever other headers it requires, and that all headers should + * take steps to ensure that they are not #include'd more than once if that + * would be bad. The following symbols are defined if the named header files + * fail to adhere to the new style; the server code makes up for them by doing + * its own #include of the usual prerequisite. + */ + +/* #undef ARPA_INET_H_NEEDS_HELP */ +/* #undef SIGNAL_H_NEEDS_HELP */ +/* #undef SYS_SOCKET_H_NEEDS_HELP */ +/* #undef SYS_STAT_H_NEEDS_HELP */ +/* #undef TIME_H_NEEDS_HELP */ + +/* Version 2 of the GNU C compiler includes `built-in' declarations for a + * number of standard functions from the ANSI header file . + * Unfortunately, some systems declare these functions differently (and + * non-standardly) in their native header files, generating a warning about the + * conflict from GCC. If this is the case on your system, the following symbol + * will be defined, indicating that the server code should avoid your system's + * file, using its own version instead. + */ + +/* #undef USE_OWN_STRING_H */ + +/* On some systems, notably AIX, both and define the + * internal macro `_IO' in compatible but different ways. This means that no + * program can #include both files without getting an error. If this is so on + * your machine, then the following symbol will be defined and the server code + * will carefully #undef _IO between inclusions of the two files. + */ + +/* #undef UNDEF_IO_IN_STROPTS_H */ + +/* The NS_SYSV/NP_LOCAL networking configuration of the server makes use of an + * operating system feature called `FIFO's for communication with clients of + * the MOO. In order to do this, the server needs some way to tell whether or + * not there's something ready to be read on a given FIFO at any given time. + * The BSD function `select()' usually works if it's available, but the System + * V equivalent, `poll()', sometimes does and sometimes doesn't, depending on + * the system. The POSIX definers, of course, took the coward's way out and + * didn't define any such function at all. On many systems, however, you can + * use the `fstat()' function to determine the number of bytes of data in a + * FIFO; this allows the use of a somewhat crocky but workable substitute for + * either `poll()' or `select()'. The following symbols are defined if the + * given function works to perform the necessary operation on FIFOs on your + * system. + */ + +/* #undef FSTAT_WORKS_ON_FIFOS */ +#define POLL_WORKS_ON_FIFOS 1 +/* #undef SELECT_WORKS_ON_FIFOS */ + +/* The POSIX standard specifies a nice, simple, reliable method for performing + * non-blocking I/O, and a lot of systems actually implement it. Some systems, + * though (notably Ultrix 4.1), misleadingly define the preprocessor symbols + * that might make you *think* that they've implemented it, but really they + * don't. This symbol is defined if POSIX-style non-blocking actually works on + * your system. + */ + +/* #undef POSIX_NONBLOCKING_WORKS */ + +/* The following code figures out how to express a 32-bit integer type on your + * machine. + */ + +#include + +#if INT_MAX == 2147483647 + typedef int int32; + typedef unsigned unsigned32; +# ifndef INT32_MAX +# define INT32_MAX INT_MAX +# endif +#else +# if LONG_MAX == 2147483647 + typedef long int int32; + typedef unsigned long unsigned32; +# ifndef INT32_MAX +# define INT32_MAX LONG_MAX +# endif +# else +# error I cannot figure out how to express a 32-bit integer on your machine. +# endif +#endif + +#endif /* !Config_H */ + +/* + * $Log: config.h.in,v $ + * Revision 1.2 2005/01/21 20:40:23 jesse + * Fixed CRYPT check + * + * Revision 1.1.1.1 2004/02/26 13:13:54 jesse + * Initial import into CVS + * + * Revision 1.2 1998/12/29 05:26:51 nop + * Fixed one more Log keyword that slipped by. + * + * Revision 1.1.1.1 1997/03/03 03:45:06 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.5 1996/02/11 00:41:40 pavel + * Added check for matherr(). Release 1.8.0beta2. + * + * Revision 2.4 1996/02/08 07:23:16 pavel + * Added NDECL_STRTOD. Updated copyright notice for 1996. + * Release 1.8.0beta1. + * + * Revision 2.3 1996/01/11 07:49:01 pavel + * Added HAVE_CRYPT. Release 1.8.0alpha5. + * + * Revision 2.2 1995/12/31 03:18:30 pavel + * Added SYS_STAT_H_NEEDS_HELP. Release 1.8.0alpha4. + * + * Revision 2.1 1995/12/28 00:57:13 pavel + * Added definition of INT32_MAX. Release 1.8.0alpha3. + * + * Revision 2.0 1995/11/30 05:17:32 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.6 1993/10/11 19:25:17 pavel + * Changed from config.h.in to raw_config.h.in, along with several new tests + * being added. + * + * Revision 1.5 1992/10/28 01:57:38 pavel + * Changed NDECL_VPRINTF to NDECL_VFPRINTF, which is the one we care about... + * + * Revision 1.4 1992/10/23 23:11:21 pavel + * Added copyright notice. + * + * Revision 1.3 1992/10/23 19:19:22 pavel + * Added NEED_MALLOC_H, NDECL_{SIGEMPTYSET,FSTAT,PERROR,REMOVE,VPRINTF,MEMSET, + * FORK,WAITPID}, SELECT_WORKS_ON_FIFOS, and POSIX_NONBLOCKING_WORKS. + * + * Revision 1.2 1992/10/21 03:12:59 pavel + * Fixed up the comment leader string for this file. + * + * Revision 1.1 1992/10/21 03:06:52 pavel + * Initial RCS-controlled version. + */ + +/* Local Variables: */ +/* mode: c */ +/* End: */ diff --git a/gnoemoe/parser/functions.c b/gnoemoe/parser/functions.c new file mode 100644 index 0000000..e87f910 --- /dev/null +++ b/gnoemoe/parser/functions.c @@ -0,0 +1,576 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#include + +#include "config.h" +#include "functions.h" +#include "list.h" +#include "storage.h" +#include "streams.h" +#include "structures.h" +#include "utils.h" + +/***************************************************************************** + * This is the table of procedures that register MOO built-in functions. To + * add new built-in functions to the server, add to the list below the name of + * a C function that will register your new MOO built-ins; your C function will + * be called exactly once, during server initialization. Also add a + * declaration of that C function to `bf_register.h' and add the necessary .c + * files to the `CSRCS' line in the Makefile. + ****************************************************************************/ + +typedef void (*registry) (); + +void register_disassemble(); +void register_execute(); +void register_functions(); +void register_list(); +void register_log(); +void register_numbers(); +void register_objects(); +void register_property(); +void register_server(); +void register_tasks(); +void register_verbs(); +/* Added functions */ +void register_ansi(); +void register_martian(); +void register_files(); + +static registry bi_function_registries[] = +{ + register_disassemble, + register_execute, + register_functions, + register_list, + register_log, + register_numbers, + register_objects, + register_property, + register_server, + register_tasks, + register_verbs, + /* Added functions */ + register_ansi, + register_martian, + register_files +}; + +struct bft_entry { + const char *name; + const char *protect_str; + const char *verb_str; + int minargs; + int maxargs; + var_type *prototype; + bf_type func; + bf_read_type read; + bf_write_type write; + int protected; +}; + +static struct bft_entry bf_table[MAX_FUNC]; +static unsigned top_bf_table = 0; + +void +register_bi_functions() +{ + int loop, num_registries = + sizeof(bi_function_registries) / sizeof(bi_function_registries[0]); + + if (top_bf_table != 0) + return; + + for (loop = 0; loop < num_registries; loop++) + (void) (*(bi_function_registries[loop])) (); +} + +/*** register ***/ + +static unsigned +register_common(const char *name, int minargs, int maxargs, bf_type func, + bf_read_type read, bf_write_type write, va_list args) +{ + int va_index; + int num_arg_types = maxargs == -1 ? minargs : maxargs; + static Stream *s = 0; + + if (!s) + s = new_stream(30); + + if (top_bf_table == MAX_FUNC) { + return 0; + } + bf_table[top_bf_table].name = str_dup(name); + stream_printf(s, "protect_%s", name); + bf_table[top_bf_table].protect_str = str_dup(reset_stream(s)); + stream_printf(s, "bf_%s", name); + bf_table[top_bf_table].verb_str = str_dup(reset_stream(s)); + bf_table[top_bf_table].minargs = minargs; + bf_table[top_bf_table].maxargs = maxargs; + bf_table[top_bf_table].func = func; + bf_table[top_bf_table].read = read; + bf_table[top_bf_table].write = write; + bf_table[top_bf_table].protected = 0; + + if (num_arg_types > 0) + bf_table[top_bf_table].prototype = + mymalloc(num_arg_types * sizeof(var_type), M_PROTOTYPE); + else + bf_table[top_bf_table].prototype = 0; + for (va_index = 0; va_index < num_arg_types; va_index++) + bf_table[top_bf_table].prototype[va_index] = va_arg(args, var_type); + + return top_bf_table++; +} + +unsigned +register_function(const char *name, int minargs, int maxargs, + bf_type func,...) +{ + va_list args; + unsigned ans; + + va_start(args, func); + ans = register_common(name, minargs, maxargs, func, 0, 0, args); + va_end(args); + return ans; +} + +unsigned +register_function_with_read_write(const char *name, int minargs, int maxargs, + bf_type func, bf_read_type read, + bf_write_type write,...) +{ + va_list args; + unsigned ans; + + va_start(args, write); + ans = register_common(name, minargs, maxargs, func, read, write, args); + va_end(args); + return ans; +} + +/*** looking up functions -- by name or num ***/ + +static const char *func_not_found_msg = "no such function"; + +unsigned +number_func_by_name(const char *name) +{ /* used by parser only */ + unsigned i; + + for (i = 0; i < top_bf_table; i++) + if (!mystrcasecmp(name, bf_table[i].name)) + return i; + + return FUNC_NOT_FOUND; +} + +/*** calling built-in functions ***/ + +void +register_functions(void) +{ + register_function("function_info", 0, 1, NULL, TYPE_STR); + register_function("load_server_options", 0, 0, NULL); +} + +void +register_disassemble(void) +{ + register_function("disassemble", 2, 2, NULL, TYPE_OBJ, TYPE_ANY); +} + +void +register_execute(void) +{ + register_function_with_read_write("call_function", 1, -1, NULL, + NULL, NULL, TYPE_STR); + register_function("raise", 1, 3, NULL, TYPE_ANY, TYPE_STR, TYPE_ANY); + register_function("suspend", 0, 1, NULL, TYPE_INT); + register_function("read", 0, 2, NULL, TYPE_OBJ, TYPE_ANY); + + register_function("seconds_left", 0, 0, NULL); + register_function("ticks_left", 0, 0, NULL); + register_function("pass", 0, -1, NULL); + register_function("set_task_perms", 1, 1, NULL, TYPE_OBJ); + register_function("caller_perms", 0, 0, NULL); + register_function("callers", 0, 1, NULL, TYPE_ANY); + register_function("task_stack", 1, 2, NULL, TYPE_INT, TYPE_ANY); +} + +void +register_log(void) +{ + register_function("server_log", 1, 2, NULL, TYPE_STR, TYPE_ANY); +} + +void +register_objects(void) +{ + register_function("toobj", 1, 1, NULL, TYPE_ANY); + register_function("typeof", 1, 1, NULL, TYPE_ANY); + register_function_with_read_write("create", 1, 2, NULL, + NULL, NULL, TYPE_OBJ, TYPE_OBJ); + register_function_with_read_write("recycle", 1, 1, NULL, + NULL, NULL, TYPE_OBJ); + register_function("object_bytes", 1, 1, NULL, TYPE_OBJ); + register_function("valid", 1, 1, NULL, TYPE_OBJ); + register_function("parent", 1, 1, NULL, TYPE_OBJ); + register_function("children", 1, 1, NULL, TYPE_OBJ); + register_function("chparent", 2, 2, NULL, TYPE_OBJ, TYPE_OBJ); + register_function("max_object", 0, 0, NULL); + register_function("players", 0, 0, NULL); + register_function("is_player", 1, 1, NULL, TYPE_OBJ); + register_function("set_player_flag", 2, 2, NULL, + TYPE_OBJ, TYPE_ANY); + register_function_with_read_write("move", 2, 2, NULL, + NULL, NULL, + TYPE_OBJ, TYPE_OBJ); + register_function("is_group", 1, 1, NULL, TYPE_OBJ); + register_function("is_groupmember", 2, 2, NULL, + TYPE_OBJ, TYPE_OBJ); + register_function("set_group_flag", 2, 2, NULL, + TYPE_OBJ, TYPE_ANY); + register_function("groupwise_equiv", 2, 2, NULL, + TYPE_OBJ, TYPE_OBJ); +} + +void +register_property(void) +{ + register_function("properties", 1, 1, NULL, TYPE_OBJ); + register_function("property_info", 2, 2, NULL, + TYPE_OBJ, TYPE_STR); + register_function("set_property_info", 3, 3, NULL, + TYPE_OBJ, TYPE_STR, TYPE_LIST); + register_function("add_property", 4, 4, NULL, + TYPE_OBJ, TYPE_STR, TYPE_ANY, TYPE_LIST); + register_function("delete_property", 2, 2, NULL, + TYPE_OBJ, TYPE_STR); + register_function("clear_property", 2, 2, NULL, + TYPE_OBJ, TYPE_STR); + register_function("is_clear_property", 2, 2, NULL, + TYPE_OBJ, TYPE_STR); + register_function("prop_bytes", 2, 2, NULL, + TYPE_OBJ, TYPE_STR); +} + +void +register_server(void) +{ + register_function("server_version", 0, 0, NULL); + register_function("renumber", 1, 1, NULL, TYPE_OBJ); + register_function("reset_max_object", 0, 0, NULL); + register_function("memory_usage", 0, 0, NULL); + register_function("shutdown", 0, 1, NULL, TYPE_STR); + register_function("dump_database", 0, 0, NULL); + register_function("db_disk_size", 0, 0, NULL); + register_function("open_network_connection", 0, -1, + NULL); + register_function("connected_players", 0, 1, NULL, + TYPE_ANY); + register_function("connected_seconds", 1, 1, NULL, + TYPE_OBJ); + register_function("idle_seconds", 1, 1, NULL, TYPE_OBJ); + register_function("connection_name", 1, 1, NULL, TYPE_OBJ); + register_function("notify", 2, 3, NULL, TYPE_OBJ, TYPE_STR, TYPE_ANY); + register_function("notify_ansi", 2, 3, NULL, TYPE_OBJ, TYPE_STR, +TYPE_ANY); + register_function("boot_player", 1, 1, NULL, TYPE_OBJ); + register_function("set_connection_option", 3, 3, NULL, + TYPE_OBJ, TYPE_STR, TYPE_ANY); + register_function("connection_option", 2, 2, NULL, + TYPE_OBJ, TYPE_STR); + register_function("connection_options", 1, 1, NULL, + TYPE_OBJ); + register_function("listen", 2, 3, NULL, TYPE_OBJ, TYPE_ANY, TYPE_ANY); + register_function("unlisten", 1, 1, NULL, TYPE_ANY); + register_function("listeners", 0, 0, NULL); + register_function("buffered_output_length", 0, 1, + NULL, TYPE_OBJ); +} + +void +register_tasks(void) +{ + register_function("task_id", 0, 0, NULL); + register_function("queued_tasks", 0, 0, NULL); + register_function("kill_task", 1, 1, NULL, TYPE_INT); + register_function("output_delimiters", 1, 1, NULL, + TYPE_OBJ); + register_function("queue_info", 0, 1, NULL, TYPE_OBJ); + register_function("resume", 1, 2, NULL, TYPE_INT, TYPE_ANY); + register_function("force_input", 2, 3, NULL, + TYPE_OBJ, TYPE_STR, TYPE_ANY); + register_function("flush_input", 1, 2, NULL, TYPE_OBJ, TYPE_ANY); +} + +void +register_verbs(void) +{ + register_function("verbs", 1, 1, NULL, TYPE_OBJ); + register_function("verb_info", 2, 2, NULL, TYPE_OBJ, TYPE_ANY); + register_function("set_verb_info", 3, 3, NULL, + TYPE_OBJ, TYPE_ANY, TYPE_LIST); + register_function("verb_args", 2, 2, NULL, TYPE_OBJ, TYPE_ANY); + register_function("set_verb_args", 3, 3, NULL, + TYPE_OBJ, TYPE_ANY, TYPE_LIST); + register_function("add_verb", 3, 3, NULL, + TYPE_OBJ, TYPE_LIST, TYPE_LIST); + register_function("delete_verb", 2, 2, NULL, TYPE_OBJ, TYPE_ANY); + register_function("verb_code", 2, 4, NULL, + TYPE_OBJ, TYPE_ANY, TYPE_ANY, TYPE_ANY); + register_function("set_verb_code", 3, 3, NULL, + TYPE_OBJ, TYPE_ANY, TYPE_LIST); + register_function("eval", 1, 1, NULL, TYPE_STR); + register_function("verb_bytes", 2, 2, NULL, TYPE_OBJ, TYPE_STR); +} + +void +register_ansi(void) +{ + register_function("ansi_delete", 1, 1, NULL, TYPE_STR); + register_function("ansi_escape", 1, 1, NULL, TYPE_STR); + register_function("ansi_cutoff", 3, 3, NULL, TYPE_STR, TYPE_INT, TYPE_INT); +} + +void +register_martian() +{ + register_function("xor", 2, 2, NULL, TYPE_ANY, TYPE_ANY); + register_function("us_time", 0, 0, NULL); + register_function("nprogs", 0, 0, NULL); + register_function("random_of", 1, 1, NULL, TYPE_LIST); + register_function("enlist", 1, 1, NULL, TYPE_ANY); + register_function("explode", 1, 2, NULL, TYPE_STR, TYPE_STR); + register_function("panic", 0, 1, NULL, TYPE_STR); + register_function("isa", 2, 2, NULL, TYPE_OBJ, TYPE_OBJ); +} + +void +register_files(void) +{ + register_function("fileappend", 3, 3, NULL, TYPE_STR, TYPE_STR, TYPE_LIST); + register_function("filechmod", 3, 3, NULL, TYPE_STR, TYPE_STR, TYPE_STR); + register_function("filedelete", 2, 2, NULL, TYPE_STR, TYPE_STR); + register_function("fileerror", 0, 0, NULL); + register_function("fileexists", 2, 2, NULL, TYPE_STR, TYPE_STR); + register_function("fileextract", 4, 5, NULL, TYPE_STR, TYPE_STR, TYPE_STR, TYPE_STR, TYPE_STR); + register_function("filegrep", 3, 4, NULL, TYPE_STR, TYPE_STR, TYPE_STR, TYPE_STR); + register_function("fileinfo", 2, 2, NULL, TYPE_STR, TYPE_STR); + register_function("filelength", 2, 2, NULL, TYPE_STR, TYPE_STR); + register_function("filelist", 1, 2, NULL, TYPE_STR, TYPE_STR); + register_function("filemkdir", 2, 2, NULL, TYPE_STR, TYPE_STR); + register_function("fileread", 2, 4, NULL, TYPE_STR, TYPE_STR, TYPE_INT, TYPE_INT); + register_function("filerename", 3, 3, NULL, TYPE_STR, TYPE_STR, TYPE_STR); + register_function("filermdir", 2, 2, NULL, TYPE_STR, TYPE_STR); + register_function("filerun", 1, -1, NULL, TYPE_STR, TYPE_LIST, TYPE_LIST); + register_function("filesize", 2, 2, NULL, TYPE_STR, TYPE_STR); + register_function("fileversion", 0, 0, NULL); + register_function("filewrite", 3, 5, NULL, TYPE_STR, TYPE_STR, TYPE_LIST, TYPE_INT, TYPE_INT); +} + +void +register_numbers(void) +{ + register_function("toint", 1, 1, NULL, TYPE_ANY); + register_function("tonum", 1, 1, NULL, TYPE_ANY); + register_function("tofloat", 1, 1, NULL, TYPE_ANY); + register_function("min", 1, -1, NULL, TYPE_NUMERIC); + register_function("max", 1, -1, NULL, TYPE_NUMERIC); + register_function("abs", 1, 1, NULL, TYPE_NUMERIC); + register_function("random", 0, 1, NULL, TYPE_INT); + register_function("time", 0, 0, NULL); + register_function("ctime", 0, 1, NULL, TYPE_INT); + register_function("floatstr", 2, 3, NULL, + TYPE_FLOAT, TYPE_INT, TYPE_ANY); + + register_function("sqrt", 1, 1, NULL, TYPE_FLOAT); + register_function("sin", 1, 1, NULL, TYPE_FLOAT); + register_function("cos", 1, 1, NULL, TYPE_FLOAT); + register_function("tan", 1, 1, NULL, TYPE_FLOAT); + register_function("asin", 1, 1, NULL, TYPE_FLOAT); + register_function("acos", 1, 1, NULL, TYPE_FLOAT); + register_function("atan", 1, 2, NULL, TYPE_FLOAT, TYPE_FLOAT); + register_function("sinh", 1, 1, NULL, TYPE_FLOAT); + register_function("cosh", 1, 1, NULL, TYPE_FLOAT); + register_function("tanh", 1, 1, NULL, TYPE_FLOAT); + register_function("exp", 1, 1, NULL, TYPE_FLOAT); + register_function("log", 1, 1, NULL, TYPE_FLOAT); + register_function("log10", 1, 1, NULL, TYPE_FLOAT); + register_function("ceil", 1, 1, NULL, TYPE_FLOAT); + register_function("floor", 1, 1, NULL, TYPE_FLOAT); + register_function("trunc", 1, 1, NULL, TYPE_FLOAT); +} + +void +register_list(void) +{ + register_function("value_bytes", 1, 1, NULL, TYPE_ANY); + register_function("value_hash", 1, 1, NULL, TYPE_ANY); + register_function("string_hash", 1, 1, NULL, TYPE_STR); + register_function("binary_hash", 1, 1, NULL, TYPE_STR); + register_function("decode_binary", 1, 2, NULL, + TYPE_STR, TYPE_ANY); + register_function("encode_binary", 0, -1, NULL); + /* list */ + register_function("length", 1, 1, NULL, TYPE_ANY); + register_function("setadd", 2, 2, NULL, TYPE_LIST, TYPE_ANY); + register_function("setremove", 2, 2, NULL, TYPE_LIST, TYPE_ANY); + register_function("listappend", 2, 3, NULL, + TYPE_LIST, TYPE_ANY, TYPE_INT); + register_function("listinsert", 2, 3, NULL, + TYPE_LIST, TYPE_ANY, TYPE_INT); + register_function("listdelete", 2, 2, NULL, TYPE_LIST, TYPE_INT); + register_function("listset", 3, 3, NULL, + TYPE_LIST, TYPE_ANY, TYPE_INT); + register_function("equal", 2, 2, NULL, TYPE_ANY, TYPE_ANY); + register_function("is_member", 2, 2, NULL, TYPE_ANY, TYPE_LIST); + + /* string */ + register_function("tostr", 0, -1, NULL); + register_function("toliteral", 1, 1, NULL, TYPE_ANY); + + register_function("match", 2, 3, NULL, TYPE_STR, TYPE_STR, TYPE_ANY); + register_function("rmatch", 2, 3, NULL, TYPE_STR, TYPE_STR, TYPE_ANY); + register_function("substitute", 2, 2, NULL, TYPE_STR, TYPE_LIST); + register_function("crypt", 1, 2, NULL, TYPE_STR, TYPE_STR); + register_function("index", 2, 3, NULL, TYPE_STR, TYPE_STR, TYPE_ANY); + register_function("rindex", 2, 3, NULL, TYPE_STR, TYPE_STR, TYPE_ANY); + register_function("strcmp", 2, 2, NULL, TYPE_STR, TYPE_STR); + register_function("strsub", 3, 4, NULL, + TYPE_STR, TYPE_STR, TYPE_STR, TYPE_ANY); +} + +char rcsid_functions[] = "$Id: functions.c,v 1.3 2005/01/21 12:07:31 jesse Exp $"; + +/* + * $Log: functions.c,v $ + * Revision 1.3 2005/01/21 12:07:31 jesse + * Added FUP + * + * Revision 1.2 2004/02/26 14:16:02 jesse + * added martian functions + * + * Revision 1.1.1.1 2004/02/26 13:13:55 jesse + * Initial import into CVS + * + * Revision 1.5 1998/12/14 13:17:53 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.4 1997/07/07 03:24:54 nop + * Merge UNSAFE_OPTS (r5) after extensive testing. + * + * Revision 1.3.2.2 1997/05/12 04:03:21 bjj + * This time for sure! + * + * Revision 1.3.2.1 1997/05/11 04:31:54 bjj + * Missed the place in bf_function_info where TYPE_* constants make it into + * the database. Masked off the complex flag in the obvious place. + * + * Revision 1.3 1997/03/03 05:03:50 nop + * steak2: move protectedness into builtin struct, load_server_options() + * now required for $server_options updates. + * + * Revision 1.2 1997/03/03 04:18:42 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:00 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.6 1996/04/19 01:20:49 pavel + * Fixed bug in how $bf_FOO() verbs are called to override built-in functions. + * Added code to screen out the worst of the problems this bug could + * potentially cause. Added a way for built-in functions to tail-call a MOO + * verb (i.e., to do so without having to handle the verb's returned value). + * Release 1.8.0p4. + * + * Revision 2.5 1996/04/08 01:03:59 pavel + * Moved `protected' verb test to before arg-count and -type checks. + * Release 1.8.0p3. + * + * Revision 2.4 1996/03/19 07:13:04 pavel + * Fixed $bf_FOO() calling to work even for wizards. Release 1.8.0p2. + * + * Revision 2.3 1996/03/10 01:19:49 pavel + * Added support for calling $bf_FOO() when FOO() is wiz-only. Made + * verbs on #0 exempt from the wiz-only check. Release 1.8.0. + * + * Revision 2.2 1996/02/08 07:03:21 pavel + * Renamed err/logf() to errlog/oklog() and TYPE_NUM to TYPE_INT. Added + * support for TYPE_NUMERIC wildcard. Updated copyright notice for 1996. + * Release 1.8.0beta1. + * + * Revision 2.1 1996/01/16 07:27:37 pavel + * Added `function_info()' built-in function. Release 1.8.0alpha6. + * + * Revision 2.0 1995/11/30 04:23:49 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.14 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.13 1992/10/23 19:25:30 pavel + * Eliminated all uses of the useless macro NULL. + * + * Revision 1.12 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.11 1992/10/17 20:31:03 pavel + * Changed return-type of read_bi_func_data() from char to int, for systems + * that use unsigned chars. + * Global rename of strdup->str_dup, strref->str_ref, vardup->var_dup, and + * varref->var_ref. + * Fixed bug in register_common() that sometimes read the wrong number of + * argument-types from the argument list. + * + * Revision 1.10 1992/09/08 22:02:46 pjames + * Updated register_* list to call functions by their new names. + * + * Revision 1.9 1992/08/28 16:01:31 pjames + * Changed myfree(*, M_STRING) to free_str(*). + * + * Revision 1.8 1992/08/14 01:20:25 pavel + * Made it entirely clear how to add new MOO built-in functions to the server. + * + * Revision 1.7 1992/08/14 00:40:31 pavel + * Added missing #include "my-stdarg.h"... + * + * Revision 1.6 1992/08/14 00:01:03 pavel + * Converted to a typedef of `var_type' = `enum var_type'. + * + * Revision 1.5 1992/08/13 21:27:11 pjames + * Added register_bi_functions() which calls all procedures which + * register built in functions. To add another such procedure, just add + * it to the static list and to functions.h + * + * Revision 1.4 1992/08/12 01:48:42 pjames + * Builtin functions may now have as many arguments as desired. + * + * Revision 1.3 1992/08/10 17:39:46 pjames + * Changed registration method to use var_args. Changed 'next' field to + * be func_pc. + * + * Revision 1.2 1992/07/21 00:02:29 pavel + * Added rcsid_ declaration to hold the RCS ident. string. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/functions.h b/gnoemoe/parser/functions.h new file mode 100644 index 0000000..43b24d6 --- /dev/null +++ b/gnoemoe/parser/functions.h @@ -0,0 +1,137 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#ifndef Functions_h +#define Functions_h 1 + +#include + +#include "config.h" +#include "structures.h" + +typedef struct { + enum { + BI_RETURN, /* Normal function return */ + BI_RAISE, /* Raising an error */ + BI_CALL, /* Making a nested verb call */ + BI_SUSPEND /* Suspending the current task */ + } kind; + union { + Var ret; + struct { + Var code; + const char *msg; + Var value; + } raise; + struct { + Byte pc; + void *data; + } call; + struct { + void *data; + } susp; + } u; +} package; + +void register_bi_functions(); + +typedef package(*bf_type) (Var, Byte, void *, Objid); +typedef void (*bf_write_type) (void *vdata); +typedef void *(*bf_read_type) (void); + +#define MAX_FUNC 256 +#define FUNC_NOT_FOUND MAX_FUNC +/* valid function numbers are 0 - 255, or a total of 256 of them. + function number 256 is reserved for func_not_found signal. + hence valid function numbers will fit in one byte but the + func_not_found signal will not */ + +extern const char *name_func_by_num(unsigned); +extern unsigned number_func_by_name(const char *); + +extern unsigned register_function(const char *, int, int, bf_type,...); +extern unsigned register_function_with_read_write(const char *, int, int, + bf_type, bf_read_type, + bf_write_type,...); + +extern package call_bi_func(unsigned, Var, Byte, Objid, void *); +/* will free or use Var arglist */ + +extern void write_bi_func_data(void *vdata, Byte f_id); +extern int read_bi_func_data(Byte f_id, void **bi_func_state, + Byte * bi_func_pc); +extern Byte *pc_for_bi_func_data(void); + +extern void load_server_options(void); + +#endif + +/* + * $Log: functions.h,v $ + * Revision 1.1.1.1 2004/02/26 13:13:55 jesse + * Initial import into CVS + * + * Revision 1.4 1998/12/14 13:17:54 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.3 1997/03/03 05:03:51 nop + * steak2: move protectedness into builtin struct, load_server_options() + * now required for $server_options updates. + * + * Revision 1.2 1997/03/03 04:18:42 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:03 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.2 1996/04/19 01:22:04 pavel + * Added tail_call_pack() declaration and patches to allow generation of the + * new warning in read_bi_func_data(). Release 1.8.0p4. + * + * Revision 2.1 1996/02/08 06:25:15 pavel + * Updated copyright notice for 1996. Release 1.8.0beta1. + * + * Revision 2.0 1995/11/30 04:51:31 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.8 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.7 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.6 1992/10/17 20:31:21 pavel + * Changed return-type of read_bi_func_data() from char to int, for systems + * that use unsigned chars. + * + * Revision 1.5 1992/08/14 00:00:56 pavel + * Converted to a typedef of `var_type' = `enum var_type'. + * + * Revision 1.4 1992/08/13 21:25:52 pjames + * Added register_bi_functions() which registers all bi_functions. + * + * Revision 1.3 1992/08/12 01:49:19 pjames + * Var_types in bft_entry is now a pointer instead of a preallocated array. + * + * Revision 1.2 1992/08/10 17:38:21 pjames + * Added func_pc and func_data to package struct. Built in functions now + * receive an Objid (progr) instead of a Parse_Info. Changed + * registration method to use var_args. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/gm-parser.c b/gnoemoe/parser/gm-parser.c new file mode 100644 index 0000000..38aad56 --- /dev/null +++ b/gnoemoe/parser/gm-parser.c @@ -0,0 +1,131 @@ +#include "parsen.h" +#include "gm-parser.h" +#include "../gm-debug.h" + +typedef struct _ParserState { + GList *code; + gchar *line; + gint cur_line; + gint cur_char; + GList *errors; + GList *warnings; +} ParserState; + +static void +gm_parser_error(void *data, const char *msg) { + ParserState *state = (ParserState *)data; + GmParserError *r = g_new0(GmParserError, 1); + + r->line = state->cur_line; + r->ch = state->cur_char; + r->message = g_strdup(msg); + + state->errors = g_list_append(state->errors, r); +} + +static void +gm_parser_warning(void *data, const char *msg) { + ParserState *state = (ParserState *)data; + GmParserError *r = g_new0(GmParserError, 1); + + r->line = state->cur_line; + r->ch = state->cur_char; + r->message = g_strdup(msg); + + state->warnings = g_list_append(state->warnings, r); +} + +static int +gm_parser_getc(void *data) { + ParserState *state = (ParserState *)data; + guchar c; + gchar *line; + + if (state->line == NULL) { + return EOF; + } else if ((c = state->line[state->cur_char]) == '\n' || c == '\0') { + state->code = state->code->next; + + if (state->code != NULL) { + state->line = (gchar *)(state->code->data); + } else { + state->line = NULL; + } + + ++state->cur_line; + state->cur_char = 0; + return '\n'; + } else { + ++state->cur_char; + return c; + } +} + +void +gm_parser_init_state(ParserState *state) { + state->cur_line = 0; + state->cur_char = 0; + state->errors = NULL; + state->warnings = NULL; +} + +void +gm_parser_init_result(GmParserResult *result) { + result->isOk = TRUE; + result->warnings = NULL; + result->errors = NULL; +} + +static Parser_Client list_parser_client = { + gm_parser_error, + gm_parser_warning, + gm_parser_getc +}; + +GmParserResult * +gm_parser_parse(GList *code) { + ParserState state; + GmParserResult *result = g_new0(GmParserResult, 1); + + gm_parser_init_result(result); + + if (!code) { + return result; + } + + gm_parser_init_state(&state); + state.code = code; + state.line = (gchar *)(code->data); + + parse_program(current_version, list_parser_client, &state); + + result->errors = state.errors; + result->warnings = state.warnings; + result->isOk = (result->errors == NULL && result->warnings == NULL); + + return result; +} + +void +gm_parser_error_free(GmParserError *error) { + g_free(error->message); + g_free(error); +} + +void +gm_parser_result_free(GmParserResult *result) { + GList *item; + + for (item = result->errors; item; item = item->next) { + gm_parser_error_free((GmParserError *)(item->data)); + } + + for (item = result->warnings; item; item = item->next) { + gm_parser_error_free((GmParserError *)(item->data)); + } + + g_list_free(result->errors); + g_list_free(result->warnings); + + g_free(result); +} diff --git a/gnoemoe/parser/gm-parser.h b/gnoemoe/parser/gm-parser.h new file mode 100644 index 0000000..d19c876 --- /dev/null +++ b/gnoemoe/parser/gm-parser.h @@ -0,0 +1,22 @@ +#ifndef __GM_PARSER_H__ +#define __GM_PARSER_H__ + +#include + +typedef struct _GmParserResult { + gboolean isOk; + + GList *errors; + GList *warnings; +} GmParserResult; + +typedef struct _GmParserError { + gchar *message; + gint line; + gint ch; +} GmParserError; + +GmParserResult *gm_parser_parse(GList *code); +void gm_parser_result_free(GmParserResult *result); + +#endif diff --git a/gnoemoe/parser/keywords.c b/gnoemoe/parser/keywords.c new file mode 100644 index 0000000..6a30b52 --- /dev/null +++ b/gnoemoe/parser/keywords.c @@ -0,0 +1,305 @@ +/* C code produced by gperf version 3.0.1 */ +/* Command-line: gperf --language C --ignore-case --readonly-tables -p --struct-type --omit-struct-type -k'1,3,$' --output-file keywords.c keywords.gperf */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +#line 1 "keywords.gperf" + /* -*- C -*- */ + +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#include + +#include "config.h" +#include "keywords.h" +#include "tokens.h" +#include "utils.h" + + +#define TOTAL_KEYWORDS 35 +#define MIN_WORD_LENGTH 2 +#define MAX_WORD_LENGTH 9 +#define MIN_HASH_VALUE 3 +#define MAX_HASH_VALUE 63 +/* maximum key range = 61, duplicates = 0 */ + +#ifndef GPERF_DOWNCASE +#define GPERF_DOWNCASE 1 +static unsigned char gperf_downcase[256] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255 + }; +#endif + +#ifndef GPERF_CASE_STRCMP +#define GPERF_CASE_STRCMP 1 +static int +gperf_case_strcmp (s1, s2) + register const char *s1; + register const char *s2; +{ + for (;;) + { + unsigned char c1 = gperf_downcase[(unsigned char)*s1++]; + unsigned char c2 = gperf_downcase[(unsigned char)*s2++]; + if (c1 != 0 && c1 == c2) + continue; + return (int)c1 - (int)c2; + } +} +#endif + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +hash (str, len) + register const char *str; + register unsigned int len; +{ + static const unsigned char asso_values[] = + { + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 10, 5, 20, 0, 0, + 0, 5, 64, 20, 64, 20, 64, 35, 10, 64, + 5, 25, 0, 35, 5, 64, 10, 0, 64, 20, + 64, 64, 64, 64, 64, 64, 64, 10, 5, 20, + 0, 0, 0, 5, 64, 20, 64, 20, 64, 35, + 10, 64, 5, 25, 0, 35, 5, 64, 10, 0, + 64, 20, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[2]]; + /*FALLTHROUGH*/ + case 2: + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval + asso_values[(unsigned char)str[len - 1]]; +} + +#ifdef __GNUC__ +__inline +#endif +const struct keyword * +in_word_set (str, len) + register const char *str; + register unsigned int len; +{ + static const struct keyword wordlist[] = + { + {""}, {""}, {""}, +#line 34 "keywords.gperf" + {"for", DBV_Prehistory, tFOR}, + {""}, +#line 33 "keywords.gperf" + {"endif", DBV_Prehistory, tENDIF}, +#line 36 "keywords.gperf" + {"endfor", DBV_Prehistory, tENDFOR}, +#line 59 "keywords.gperf" + {"E_RANGE", DBV_Prehistory, tERROR, E_RANGE}, +#line 41 "keywords.gperf" + {"endwhile", DBV_Prehistory, tENDWHILE}, +#line 57 "keywords.gperf" + {"E_RECMOVE", DBV_Prehistory, tERROR, E_RECMOVE}, + {""}, +#line 50 "keywords.gperf" + {"E_TYPE", DBV_Prehistory, tERROR, E_TYPE}, +#line 64 "keywords.gperf" + {"E_FLOAT", DBV_Float, tERROR, E_FLOAT}, +#line 53 "keywords.gperf" + {"E_PROPNF", DBV_Prehistory, tERROR, E_PROPNF}, + {""}, +#line 51 "keywords.gperf" + {"E_DIV", DBV_Prehistory, tERROR, E_DIV}, +#line 49 "keywords.gperf" + {"E_NONE", DBV_Prehistory, tERROR, E_NONE}, +#line 55 "keywords.gperf" + {"E_VARNF", DBV_Prehistory, tERROR, E_VARNF}, +#line 54 "keywords.gperf" + {"E_VERBNF", DBV_Prehistory, tERROR, E_VERBNF}, + {""}, {""}, +#line 39 "keywords.gperf" + {"return", DBV_Prehistory, tRETURN}, +#line 30 "keywords.gperf" + {"if", DBV_Prehistory, tIF}, + {""}, +#line 37 "keywords.gperf" + {"fork", DBV_Prehistory, tFORK}, +#line 40 "keywords.gperf" + {"while", DBV_Prehistory, tWHILE}, +#line 45 "keywords.gperf" + {"endtry", DBV_Exceptions, tENDTRY}, +#line 38 "keywords.gperf" + {"endfork", DBV_Prehistory, tENDFORK}, +#line 56 "keywords.gperf" + {"E_INVIND", DBV_Prehistory, tERROR, E_INVIND}, + {""}, +#line 47 "keywords.gperf" + {"break", DBV_BreakCont, tBREAK}, +#line 43 "keywords.gperf" + {"except", DBV_Exceptions, tEXCEPT}, +#line 35 "keywords.gperf" + {"in", DBV_Prehistory, tIN}, +#line 62 "keywords.gperf" + {"E_INVARG", DBV_Prehistory, tERROR, E_INVARG}, + {""}, {""}, +#line 61 "keywords.gperf" + {"E_NACC", DBV_Prehistory, tERROR, E_NACC}, +#line 44 "keywords.gperf" + {"finally", DBV_Exceptions, tFINALLY}, +#line 48 "keywords.gperf" + {"continue", DBV_BreakCont, tCONTINUE}, +#line 31 "keywords.gperf" + {"else", DBV_Prehistory, tELSE}, + {""}, +#line 32 "keywords.gperf" + {"elseif", DBV_Prehistory, tELSEIF}, +#line 63 "keywords.gperf" + {"E_QUOTA", DBV_Prehistory, tERROR, E_QUOTA}, + {""}, {""}, {""}, +#line 52 "keywords.gperf" + {"E_PERM", DBV_Prehistory, tERROR, E_PERM}, + {""}, +#line 42 "keywords.gperf" + {"try", DBV_Exceptions, tTRY}, + {""}, {""}, +#line 60 "keywords.gperf" + {"E_ARGS", DBV_Prehistory, tERROR, E_ARGS}, + {""}, +#line 46 "keywords.gperf" + {"ANY", DBV_Exceptions, tANY}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, +#line 58 "keywords.gperf" + {"E_MAXREC", DBV_Prehistory, tERROR, E_MAXREC} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register const char *s = wordlist[key].name; + + if ((((unsigned char)*str ^ (unsigned char)*s) & ~32) == 0 && !gperf_case_strcmp (str, s)) + return &wordlist[key]; + } + } + return 0; +} +#line 65 "keywords.gperf" + + +const struct keyword * +find_keyword(const char *word) +{ + return in_word_set(word, strlen(word)); +} + +char rcsid_keywords[] = "$Id: keywords.gperf,v 1.1.1.1 2004/02/26 13:13:56 jesse Exp $"; + +/* $Log: keywords.gperf,v $ +/* Revision 1.1.1.1 2004/02/26 13:13:56 jesse +/* Initial import into CVS +/* +/* Revision 1.1.1.1 1997/03/03 03:45:02 nop +/* LambdaMOO 1.8.0p5 +/* + * Revision 2.2 1996/02/08 06:33:21 pavel + * Added `break', `continue', and E_FLOAT. Updated copyright notice for 1996. + * Release 1.8.0beta1. + * + * Revision 2.1 1995/12/11 08:15:42 pavel + * Added #include "tokens.h" removed from keywords.h. Release 1.8.0alpha2. + * + * Revision 2.0 1995/11/30 05:02:56 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.1 1995/11/30 05:01:47 pavel + * Initial revision + */ diff --git a/gnoemoe/parser/keywords.gperf b/gnoemoe/parser/keywords.gperf new file mode 100644 index 0000000..0507d81 --- /dev/null +++ b/gnoemoe/parser/keywords.gperf @@ -0,0 +1,94 @@ +%{ /* -*- C -*- */ + +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#include + +#include "config.h" +#include "keywords.h" +#include "tokens.h" +#include "utils.h" + +%} +struct keyword {}; /* bogus decl not copied into the output */ +%% +if, DBV_Prehistory, tIF +else, DBV_Prehistory, tELSE +elseif, DBV_Prehistory, tELSEIF +endif, DBV_Prehistory, tENDIF +for, DBV_Prehistory, tFOR +in, DBV_Prehistory, tIN +endfor, DBV_Prehistory, tENDFOR +fork, DBV_Prehistory, tFORK +endfork, DBV_Prehistory, tENDFORK +return, DBV_Prehistory, tRETURN +while, DBV_Prehistory, tWHILE +endwhile, DBV_Prehistory, tENDWHILE +try, DBV_Exceptions, tTRY +except, DBV_Exceptions, tEXCEPT +finally, DBV_Exceptions, tFINALLY +endtry, DBV_Exceptions, tENDTRY +ANY, DBV_Exceptions, tANY +break, DBV_BreakCont, tBREAK +continue, DBV_BreakCont, tCONTINUE +E_NONE, DBV_Prehistory, tERROR, E_NONE +E_TYPE, DBV_Prehistory, tERROR, E_TYPE +E_DIV, DBV_Prehistory, tERROR, E_DIV +E_PERM, DBV_Prehistory, tERROR, E_PERM +E_PROPNF, DBV_Prehistory, tERROR, E_PROPNF +E_VERBNF, DBV_Prehistory, tERROR, E_VERBNF +E_VARNF, DBV_Prehistory, tERROR, E_VARNF +E_INVIND, DBV_Prehistory, tERROR, E_INVIND +E_RECMOVE, DBV_Prehistory, tERROR, E_RECMOVE +E_MAXREC, DBV_Prehistory, tERROR, E_MAXREC +E_RANGE, DBV_Prehistory, tERROR, E_RANGE +E_ARGS, DBV_Prehistory, tERROR, E_ARGS +E_NACC, DBV_Prehistory, tERROR, E_NACC +E_INVARG, DBV_Prehistory, tERROR, E_INVARG +E_QUOTA, DBV_Prehistory, tERROR, E_QUOTA +E_FLOAT, DBV_Float, tERROR, E_FLOAT +%% + +const struct keyword * +find_keyword(const char *word) +{ + return in_word_set(word, strlen(word)); +} + +char rcsid_keywords[] = "$Id: keywords.gperf,v 1.1.1.1 2004/02/26 13:13:56 jesse Exp $"; + +/* $Log: keywords.gperf,v $ +/* Revision 1.1.1.1 2004/02/26 13:13:56 jesse +/* Initial import into CVS +/* +/* Revision 1.1.1.1 1997/03/03 03:45:02 nop +/* LambdaMOO 1.8.0p5 +/* + * Revision 2.2 1996/02/08 06:33:21 pavel + * Added `break', `continue', and E_FLOAT. Updated copyright notice for 1996. + * Release 1.8.0beta1. + * + * Revision 2.1 1995/12/11 08:15:42 pavel + * Added #include "tokens.h" removed from keywords.h. Release 1.8.0alpha2. + * + * Revision 2.0 1995/11/30 05:02:56 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.1 1995/11/30 05:01:47 pavel + * Initial revision + */ diff --git a/gnoemoe/parser/keywords.h b/gnoemoe/parser/keywords.h new file mode 100644 index 0000000..cd08958 --- /dev/null +++ b/gnoemoe/parser/keywords.h @@ -0,0 +1,59 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#include "config.h" +#include "structures.h" +#include "version.h" + +struct keyword { + const char *name; /* the canonical spelling of the keyword */ + DB_Version version; /* the DB version when it was introduced */ + int token; /* the type of token the scanner should use */ + enum error error; /* for token == ERROR, the value */ +}; + +typedef const struct keyword Keyword; + +extern Keyword *find_keyword(const char *); + +/* + * $Log: keywords.h,v $ + * Revision 1.1.1.1 2004/02/26 13:13:56 jesse + * Initial import into CVS + * + * Revision 1.3 1998/12/14 13:17:56 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.2 1997/03/03 04:18:46 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:03 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.2 1996/02/08 06:24:47 pavel + * Fixed type of version number. Updated copyright notice for 1996. + * Release 1.8.0beta1. + * + * Revision 2.1 1995/12/11 08:15:02 pavel + * Removed useless #include "tokens.h". Release 1.8.0alpha2. + * + * Revision 2.0 1995/11/30 05:06:50 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.1 1995/11/30 05:06:40 pavel + * Initial revision + */ diff --git a/gnoemoe/parser/list.c b/gnoemoe/parser/list.c new file mode 100644 index 0000000..b5d05bf --- /dev/null +++ b/gnoemoe/parser/list.c @@ -0,0 +1,438 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#include +#include + +#include "config.h" +#include "functions.h" +#include "list.h" +#include "streams.h" +#include "storage.h" +#include "structures.h" +#include "utils.h" + +Var +new_list(int size) +{ + Var new; + + if (size == 0) { + static Var emptylist; + + if (emptylist.v.list == 0) { + emptylist.type = TYPE_LIST; + emptylist.v.list = mymalloc(1 * sizeof(Var), M_LIST); + emptylist.v.list[0].type = TYPE_INT; + emptylist.v.list[0].v.num = 0; + } + /* give the lucky winner a reference */ + addref(emptylist.v.list); + return emptylist; + } + new.type = TYPE_LIST; + new.v.list = (Var *) mymalloc((size + 1) * sizeof(Var), M_LIST); + new.v.list[0].type = TYPE_INT; + new.v.list[0].v.num = size; + return new; +} + +Var +setadd(Var list, Var value) +{ + if (ismember(value, list, 0)) { + free_var(value); + return list; + } + return listappend(list, value); +} + +Var +setremove(Var list, Var value) +{ + int i; + + if ((i = ismember(value, list, 0)) != 0) { + return listdelete(list, i); + } else { + return list; + } +} + +int +ismember(Var lhs, Var rhs, int case_matters) +{ + int i; + + for (i = 1; i <= rhs.v.list[0].v.num; i++) { + if (equality(lhs, rhs.v.list[i], case_matters)) { + return i; + } + } + return 0; +} + +Var +listset(Var list, Var value, int pos) +{ + free_var(list.v.list[pos]); + list.v.list[pos] = value; + return list; +} + +static Var +doinsert(Var list, Var value, int pos) +{ + Var new; + int i; + int size = list.v.list[0].v.num + 1; + + if (var_refcount(list) == 1 && pos == size) { + list.v.list = (Var *) myrealloc(list.v.list, (size + 1) * sizeof(Var), M_LIST); + list.v.list[0].v.num = size; + list.v.list[pos] = value; + return list; + } + new = new_list(size); + for (i = 1; i < pos; i++) + new.v.list[i] = var_ref(list.v.list[i]); + new.v.list[pos] = value; + for (i = pos; i <= list.v.list[0].v.num; i++) + new.v.list[i + 1] = var_ref(list.v.list[i]); + free_var(list); + return new; +} + +Var +listinsert(Var list, Var value, int pos) +{ + if (pos <= 0) + pos = 1; + else if (pos > list.v.list[0].v.num) + pos = list.v.list[0].v.num + 1; + return doinsert(list, value, pos); +} + +Var +listappend(Var list, Var value) +{ + return doinsert(list, value, list.v.list[0].v.num + 1); +} + +Var +listdelete(Var list, int pos) +{ + Var new; + int i; + + new = new_list(list.v.list[0].v.num - 1); + for (i = 1; i < pos; i++) { + new.v.list[i] = var_ref(list.v.list[i]); + } + for (i = pos + 1; i <= list.v.list[0].v.num; i++) + new.v.list[i - 1] = var_ref(list.v.list[i]); + free_var(list); /* free old list */ + return new; +} + +Var +listconcat(Var first, Var second) +{ + int lsecond = second.v.list[0].v.num; + int lfirst = first.v.list[0].v.num; + Var new; + int i; + + new = new_list(lsecond + lfirst); + for (i = 1; i <= lfirst; i++) + new.v.list[i] = var_ref(first.v.list[i]); + for (i = 1; i <= lsecond; i++) + new.v.list[i + lfirst] = var_ref(second.v.list[i]); + free_var(first); + free_var(second); + + return new; +} + +Var +listrangeset(Var base, int from, int to, Var value) +{ + /* base and value are free'd */ + int index, offset = 0; + int val_len = value.v.list[0].v.num; + int base_len = base.v.list[0].v.num; + int lenleft = (from > 1) ? from - 1 : 0; + int lenmiddle = val_len; + int lenright = (base_len > to) ? base_len - to : 0; + int newsize = lenleft + lenmiddle + lenright; + Var ans; + + ans = new_list(newsize); + for (index = 1; index <= lenleft; index++) + ans.v.list[++offset] = var_ref(base.v.list[index]); + for (index = 1; index <= lenmiddle; index++) + ans.v.list[++offset] = var_ref(value.v.list[index]); + for (index = 1; index <= lenright; index++) + ans.v.list[++offset] = var_ref(base.v.list[to + index]); + free_var(base); + free_var(value); + return ans; +} + +Var +sublist(Var list, int lower, int upper) +{ + if (lower > upper) { + free_var(list); + return new_list(0); + } else { + Var r; + int i; + + r = new_list(upper - lower + 1); + for (i = lower; i <= upper; i++) + r.v.list[i - lower + 1] = var_ref(list.v.list[i]); + free_var(list); + return r; + } +} + +static const char * +list2str(Var * args) +{ + static Stream *str = 0; + int i; + + if (!str) + str = new_stream(100); + + for (i = 1; i <= args[0].v.num; i++) { + switch (args[i].type) { + case TYPE_INT: + stream_printf(str, "%d", args[i].v.num); + break; + case TYPE_OBJ: + stream_printf(str, "#%d", args[i].v.obj); + break; + case TYPE_STR: + stream_add_string(str, args[i].v.str); + break; + case TYPE_ERR: + stream_add_string(str, unparse_error(args[i].v.err)); + break; + case TYPE_FLOAT: + stream_printf(str, "%g", *args[i].v.fnum); + break; + case TYPE_LIST: + stream_add_string(str, "{list}"); + break; + } + } + + return reset_stream(str); +} + +const char * +value2str(Var value) +{ + Var list; + const char *str; + + list = new_list(1); + list.v.list[1] = var_ref(value); + str = list2str(list.v.list); + free_var(list); + return str; +} + +Var +strrangeset(Var base, int from, int to, Var value) +{ + /* base and value are free'd */ + int index, offset = 0; + int val_len = strlen(value.v.str); + int base_len = strlen(base.v.str); + int lenleft = (from > 1) ? from - 1 : 0; + int lenmiddle = val_len; + int lenright = (base_len > to) ? base_len - to : 0; + int newsize = lenleft + lenmiddle + lenright; + + Var ans; + char *s; + + ans.type = TYPE_STR; + s = mymalloc(sizeof(char) * (newsize + 1), M_STRING); + + for (index = 0; index < lenleft; index++) + s[offset++] = base.v.str[index]; + for (index = 0; index < lenmiddle; index++) + s[offset++] = value.v.str[index]; + for (index = 0; index < lenright; index++) + s[offset++] = base.v.str[index + to]; + s[offset] = '\0'; + ans.v.str = s; + free_var(base); + free_var(value); + return ans; +} + +Var +substr(Var str, int lower, int upper) +{ + Var r; + + r.type = TYPE_STR; + if (lower > upper) + r.v.str = str_dup(""); + else { + int loop, index = 0; + char *s = mymalloc(upper - lower + 2, M_STRING); + + for (loop = lower - 1; loop < upper; loop++) + s[index++] = str.v.str[loop]; + s[index] = '\0'; + r.v.str = s; + } + free_var(str); + return r; +} + +Var +strget(Var str, Var i) +{ + Var r; + char *s; + + r.type = TYPE_STR; + s = str_dup(" "); + s[0] = str.v.str[i.v.num - 1]; + r.v.str = s; + return r; +} + +char rcsid_list[] = "$Id: list.c,v 1.1.1.1 2004/02/26 13:13:56 jesse Exp $"; + +/* + * $Log: list.c,v $ + * Revision 1.1.1.1 2004/02/26 13:13:56 jesse + * Initial import into CVS + * + * Revision 1.5 1998/12/14 13:17:57 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.4 1997/07/07 03:24:54 nop + * Merge UNSAFE_OPTS (r5) after extensive testing. + * + * Revision 1.3.2.3 1997/07/03 08:04:01 bjj + * Pattern cache was not storing case_matters flag, causing many patterns to + * be impossible to find in the cache. + * + * Revision 1.3.2.2 1997/05/20 14:55:52 nop + * Include Jason's patch for bf_decode_binary losing on systems where + * char is signed. + * + * Revision 1.3.2.1 1997/03/21 15:22:56 bjj + * doinsert reallocs for appending to refcnt 1 lists. note that this wins + * because it avoids all the var_ref/free_var that's done in the general case, + * not because it avoids malloc/free. the general case could also benefit from + * using memcpy when the refcnt is 1, rather than looping with var_ref. + * + * Revision 1.3 1997/03/03 06:20:04 bjj + * new_list(0) now returns the same empty list to every caller + * + * Revision 1.2 1997/03/03 04:18:46 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:00 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.7 1996/03/11 23:35:17 pavel + * Fixed bad use of possibly-signed characters in decode_binary(). + * Release 1.8.0p1. + * + * Revision 2.6 1996/02/18 23:17:24 pavel + * Added value_hash(), string_hash(), and binary_hash(). Release 1.8.0beta3. + * + * Revision 2.5 1996/02/08 07:02:09 pavel + * Added support for floating-point numbers. Fixed registration of + * decode_binary(). Renamed err/logf() to errlog/oklog() and TYPE_NUM to + * TYPE_INT. Updated copyright notice for 1996. Release 1.8.0beta1. + * + * Revision 2.4 1996/01/16 07:26:56 pavel + * Fixed `case_matters' arguments to strsub(), index(), rindex(), match(), and + * rmatch() to allow values of any type. Release 1.8.0alpha6. + * + * Revision 2.3 1996/01/11 07:42:14 pavel + * Added support for C's crypt() function being unavailable. Fixed potential + * string overread in case of a too-short salt argument to MOO's crypt() + * function. Added built-ins encode_binary() and decode_binary(), in support + * of new binary I/O facilities. Release 1.8.0alpha5. + * + * Revision 2.2 1995/12/31 03:25:04 pavel + * Added missing #include "options.h". Release 1.8.0alpha4. + * + * Revision 2.1 1995/12/11 07:43:20 pavel + * Moved value_bytes built-in function to here. + * + * Release 1.8.0alpha2. + * + * Revision 2.0 1995/11/30 04:24:03 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.12 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.11 1992/10/23 19:27:07 pavel + * Removed a place where a local structure variable was initialized in its + * declaration, since some compilers can't hack that. + * Added the `%%' -> `%' transformation to substitute(). + * + * Revision 1.10 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.9 1992/10/17 20:33:17 pavel + * Global rename of strdup->str_dup, strref->str_ref, vardup->var_dup, and + * varref->var_ref. + * Added some (int) casts to placate over-protective compilers. + * + * Revision 1.8 1992/09/08 22:15:09 pjames + * Updated strrangeset() and listrangeset() to use correct algorithm. + * + * Revision 1.7 1992/09/08 22:03:45 pjames + * Added all code from bf_str_list.c, and some code from bf_type.c. + * + * Revision 1.6 1992/08/31 22:31:47 pjames + * Changed some `char *'s to `const char *' and fixed code accordingly. + * + * Revision 1.5 1992/08/28 23:20:22 pjames + * Added `listrangeset()' and `strrangeset()'. + * + * Revision 1.4 1992/08/28 16:29:10 pjames + * Added some varref()'s. + * Removed some free_var()'s, due to ref-counting. + * Changed some my_free()'s to free_var(). + * Made `substr()' preserve the string it is passed. + * + * Revision 1.3 1992/08/10 16:53:46 pjames + * Updated #includes. + * + * Revision 1.2 1992/07/21 00:04:04 pavel + * Added rcsid_ declaration to hold the RCS ident. string. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/list.h b/gnoemoe/parser/list.h new file mode 100644 index 0000000..d155339 --- /dev/null +++ b/gnoemoe/parser/list.h @@ -0,0 +1,65 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#include "structures.h" + +extern Var listappend(Var list, Var value); +extern Var listinsert(Var list, Var value, int pos); +extern Var listdelete(Var list, int pos); +extern Var listset(Var list, Var value, int pos); +extern Var listrangeset(Var list, int from, int to, Var value); +extern Var listconcat(Var first, Var second); +extern int ismember(Var value, Var list, int case_matters); +extern Var setadd(Var list, Var value); +extern Var setremove(Var list, Var value); +extern Var sublist(Var list, int lower, int upper); +extern Var strrangeset(Var list, int from, int to, Var value); +extern Var substr(Var str, int lower, int upper); +extern Var strget(Var str, Var i); +extern Var new_list(int size); +extern const char *value2str(Var); +extern const char *value_to_literal(Var); + +/* + * $Log: list.h,v $ + * Revision 1.1.1.1 2004/02/26 13:13:56 jesse + * Initial import into CVS + * + * Revision 1.3 1998/12/14 13:17:58 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.2 1997/03/03 04:18:47 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:03 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.1 1996/02/08 06:23:44 pavel + * Updated copyright notice for 1996. Release 1.8.0beta1. + * + * Revision 2.0 1995/11/30 04:51:57 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.3 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.2 1992/08/28 23:20:04 pjames + * Added `listrangeset()' and `strrangeset()'. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/numbers.c b/gnoemoe/parser/numbers.c new file mode 100644 index 0000000..260eee0 --- /dev/null +++ b/gnoemoe/parser/numbers.c @@ -0,0 +1,462 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "functions.h" +#include "storage.h" +#include "structures.h" +#include "utils.h" + +static int +parse_number(const char *str, int *result, int try_floating_point) +{ + char *p; + + *result = strtol(str, &p, 10); + if (try_floating_point && + (p == str || *p == '.' || *p == 'e' || *p == 'E')) + *result = (int) strtod(str, &p); + if (p == str) + return 0; + while (*p) { + if (*p != ' ') + return 0; + p++; + } + return 1; +} + +static int +parse_object(const char *str, Objid * result) +{ + int number; + + while (*str && *str == ' ') + str++; + if (*str == '#') + str++; + if (parse_number(str, &number, 0)) { + *result = number; + return 1; + } else + return 0; +} + +static int +parse_float(const char *str, double *result) +{ + char *p; + int negative = 0; + + while (*str && *str == ' ') + str++; + if (*str == '-') { + str++; + negative = 1; + } + *result = strtod(str, &p); + if (p == str) + return 0; + while (*p) { + if (*p != ' ') + return 0; + p++; + } + if (negative) + *result = -*result; + return 1; +} + +enum error +become_integer(Var in, int *ret, int called_from_tonum) +{ + switch (in.type) { + case TYPE_INT: + *ret = in.v.num; + break; + case TYPE_STR: + if (!(called_from_tonum + ? parse_number(in.v.str, ret, 1) + : parse_object(in.v.str, ret))) + *ret = 0; + break; + case TYPE_OBJ: + *ret = in.v.obj; + break; + case TYPE_ERR: + *ret = in.v.err; + break; + case TYPE_FLOAT: + if (*in.v.fnum < (double) INT_MIN || *in.v.fnum > (double) INT_MAX) + return E_FLOAT; + *ret = (int) *in.v.fnum; + break; + case TYPE_LIST: + return E_TYPE; + } + return E_NONE; +} + +static enum error +become_float(Var in, double *ret) +{ + switch (in.type) { + case TYPE_INT: + *ret = (double) in.v.num; + break; + case TYPE_STR: + if (!parse_float(in.v.str, ret) || !IS_REAL(*ret)) + return E_INVARG; + break; + case TYPE_OBJ: + *ret = (double) in.v.obj; + break; + case TYPE_ERR: + *ret = (double) in.v.err; + break; + case TYPE_FLOAT: + *ret = *in.v.fnum; + break; + case TYPE_LIST: + return E_TYPE; + } + return E_NONE; +} + +Var +new_float(double d) +{ + Var v; + + v.type = TYPE_FLOAT; + v.v.fnum = mymalloc(sizeof(double), M_FLOAT); + *v.v.fnum = d; + + return v; +} + +#if COERCION_IS_EVER_IMPLEMENTED_AND_DESIRED +static int +to_float(Var v, double *dp) +{ + switch (v.type) { + case TYPE_INT: + *dp = (double) v.v.num; + break; + case TYPE_FLOAT: + *dp = *v.v.fnum; + break; + default: + return 0; + } + + return 1; +} +#endif + +#if defined(HAVE_MATHERR) && defined(DOMAIN) && defined(SING) && defined(OVERFLOW) && defined(UNDERFLOW) +/* Required in order to properly handle FP exceptions on SVID3 systems */ +int +matherr(struct exception *x) +{ + switch (x->type) { + case DOMAIN: + case SING: + errno = EDOM; + /* fall thru to... */ + case OVERFLOW: + x->retval = HUGE_VAL; + return 1; + case UNDERFLOW: + x->retval = 0.0; + return 1; + default: + return 0; /* Take default action */ + } +} +#endif + + +/**** opcode implementations ****/ + +/* + * All of the following implementations are strict, not performing any + * coercions between integer and floating-point operands. + */ + +int +do_equals(Var lhs, Var rhs) +{ /* LHS == RHS */ + /* At least one of LHS and RHS is TYPE_FLOAT */ + + if (lhs.type != rhs.type) + return 0; + else + return *lhs.v.fnum == *rhs.v.fnum; +} + +int +compare_integers(int a, int b) +{ + if (a < b) + return -1; + else if (a == b) + return 0; + else + return 1; +} + +Var +compare_numbers(Var a, Var b) +{ + Var ans; + + if (a.type != b.type) { + ans.type = TYPE_ERR; + ans.v.err = E_TYPE; + } else if (a.type == TYPE_INT) { + ans.type = TYPE_INT; + ans.v.num = compare_integers(a.v.num, b.v.num); + } else { + double aa = *a.v.fnum, bb = *b.v.fnum; + + ans.type = TYPE_INT; + if (aa < bb) + ans.v.num = -1; + else if (aa == bb) + ans.v.num = 0; + else + ans.v.num = 1; + } + + return ans; +} + +#define SIMPLE_BINARY(name, op) \ + Var \ + do_ ## name(Var a, Var b) \ + { \ + Var ans; \ + \ + if (a.type != b.type) { \ + ans.type = TYPE_ERR; \ + ans.v.err = E_TYPE; \ + } else if (a.type == TYPE_INT) { \ + ans.type = TYPE_INT; \ + ans.v.num = a.v.num op b.v.num; \ + } else { \ + double d = *a.v.fnum op *b.v.fnum; \ + \ + if (!IS_REAL(d)) { \ + ans.type = TYPE_ERR; \ + ans.v.err = E_FLOAT; \ + } else \ + ans = new_float(d); \ + } \ + \ + return ans; \ + } + +SIMPLE_BINARY(add, +) +SIMPLE_BINARY(subtract, -) +SIMPLE_BINARY(multiply, *) +#define DIVISION_OP(name, iop, fexpr) \ + Var \ + do_ ## name(Var a, Var b) \ + { \ + Var ans; \ + \ + if (a.type != b.type) { \ + ans.type = TYPE_ERR; \ + ans.v.err = E_TYPE; \ + } else if (a.type == TYPE_INT \ + && b.v.num != 0) { \ + ans.type = TYPE_INT; \ + ans.v.num = a.v.num iop b.v.num; \ + } else if (a.type == TYPE_FLOAT \ + && *b.v.fnum != 0.0) { \ + double d = fexpr; \ + \ + if (!IS_REAL(d)) { \ + ans.type = TYPE_ERR; \ + ans.v.err = E_FLOAT; \ + } else \ + ans = new_float(d); \ + } else { \ + ans.type = TYPE_ERR; \ + ans.v.err = E_DIV; \ + } \ + \ + return ans; \ + } + +DIVISION_OP(divide, /, *a.v.fnum / *b.v.fnum) +DIVISION_OP(modulus, %, fmod(*a.v.fnum, *b.v.fnum)) +Var +do_power(Var lhs, Var rhs) +{ /* LHS ^ RHS */ + Var ans; + + if (lhs.type == TYPE_INT) { /* integer exponentiation */ + int a = lhs.v.num, b, r; + + if (rhs.type != TYPE_INT) + goto type_error; + + b = rhs.v.num; + ans.type = TYPE_INT; + if (b < 0) + switch (a) { + case -1: + ans.v.num = (b % 2 == 0 ? 1 : -1); + break; + case 0: + ans.type = TYPE_ERR; + ans.v.err = E_DIV; + break; + case 1: + ans.v.num = 1; + break; + default: + ans.v.num = 0; + } else { + r = 1; + while (b != 0) { + if (b % 2 != 0) + r *= a; + a *= a; + b >>= 1; + } + ans.v.num = r; + } + } else if (lhs.type == TYPE_FLOAT) { /* floating-point exponentiation */ + double d; + + switch (rhs.type) { + case TYPE_INT: + d = (double) rhs.v.num; + break; + case TYPE_FLOAT: + d = *rhs.v.fnum; + break; + default: + goto type_error; + } + errno = 0; + d = pow(*lhs.v.fnum, d); + if (errno != 0 || !IS_REAL(d)) { + ans.type = TYPE_ERR; + ans.v.err = E_FLOAT; + } else + ans = new_float(d); + } else + goto type_error; + + return ans; + + type_error: + ans.type = TYPE_ERR; + ans.v.err = E_TYPE; + return ans; +} + +char rcsid_numbers[] = "$Id: numbers.c,v 1.1.1.1 2004/02/26 13:13:58 jesse Exp $"; + +/* + * $Log: numbers.c,v $ + * Revision 1.1.1.1 2004/02/26 13:13:58 jesse + * Initial import into CVS + * + * Revision 1.4 1998/12/14 13:18:37 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.3 1997/03/08 06:25:42 nop + * 1.8.0p6 merge by hand. + * + * Revision 1.2 1997/03/03 04:19:11 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:00 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.6 1997/03/04 04:34:06 eostrom + * parse_number() now trusts strtol() and strtod() more instead of + * parsing for "-" itself, since a bug in that led to inputs like "--5" + * and "-+5" being treated as valid. + * + * Revision 2.5 1996/03/19 07:15:27 pavel + * Fixed floatstr() to allow DBL_DIG + 4 digits. Release 1.8.0p2. + * + * Revision 2.4 1996/03/10 01:06:49 pavel + * Increased the maximum precision acceptable to floatstr() by two digits. + * Release 1.8.0. + * + * Revision 2.3 1996/02/18 23:16:22 pavel + * Made toint() accept floating-point strings. Made floatstr() reject a + * negative precision argument. Release 1.8.0beta3. + * + * Revision 2.2 1996/02/11 00:43:00 pavel + * Added optional implementation of matherr(), to improve floating-point + * exception handling on SVID3 systems. Added `trunc()' built-in function. + * Release 1.8.0beta2. + * + * Revision 2.1 1996/02/08 06:58:01 pavel + * Added support for floating-point numbers and arithmetic and for the + * standard math functions. Renamed TYPE_NUM to TYPE_INT, become_number() + * to become_integer(). Updated copyright notice for 1996. Release + * 1.8.0beta1. + * + * Revision 2.0 1995/11/30 04:28:59 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.9 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.8 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.7 1992/10/17 20:47:26 pavel + * Global rename of strdup->str_dup, strref->str_ref, vardup->var_dup, and + * varref->var_ref. + * + * Revision 1.6 1992/09/26 18:02:49 pavel + * Fixed bug whereby passing negative numbers to random() failed to evoke + * E_INVARG. + * + * Revision 1.5 1992/09/14 17:31:52 pjames + * Updated #includes. + * + * Revision 1.4 1992/09/08 22:01:42 pjames + * Renamed bf_num.c to numbers.c. Added `become_number()' from bf_type.c + * + * Revision 1.3 1992/08/10 17:36:26 pjames + * Updated #includes. Used new regisration method. Add bf_sqrt(); + * + * Revision 1.2 1992/07/20 23:51:47 pavel + * Added rcsid_ declaration to hold the RCS ident. string. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/numbers.h b/gnoemoe/parser/numbers.h new file mode 100644 index 0000000..84f74c5 --- /dev/null +++ b/gnoemoe/parser/numbers.h @@ -0,0 +1,51 @@ +/****************************************************************************** + Copyright (c) 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#include "structures.h" + +extern Var new_float(double); +extern enum error become_integer(Var, int *, int); + +extern int do_equals(Var, Var); +extern int compare_integers(int, int); +extern Var compare_numbers(Var, Var); + +extern Var do_add(Var, Var); +extern Var do_subtract(Var, Var); +extern Var do_multiply(Var, Var); +extern Var do_divide(Var, Var); +extern Var do_modulus(Var, Var); +extern Var do_power(Var, Var); + +/* + * $Log: numbers.h,v $ + * Revision 1.1.1.1 2004/02/26 13:13:58 jesse + * Initial import into CVS + * + * Revision 1.3 1998/12/14 13:18:38 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.2 1997/03/03 04:19:11 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:04 nop + * LambdaMOO 1.8.0p5 + * + * Revision 1.1 1996/02/08 07:28:25 pavel + * Initial revision + * + */ diff --git a/gnoemoe/parser/parsen.h b/gnoemoe/parser/parsen.h new file mode 100644 index 0000000..192e9ff --- /dev/null +++ b/gnoemoe/parser/parsen.h @@ -0,0 +1,74 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#ifndef Parsen_h +#define Parsen_h 1 + +#include "config.h" +#include "version.h" +#include "structures.h" + +typedef struct { + void (*error) (void *, const char *); + void (*warning) (void *, const char *); + int (*getch) (void *); +} Parser_Client; + +extern void parse_program(DB_Version, Parser_Client, void *); +extern void parse_list_as_program(Var code, Var * errors); + +#endif + +/* + * $Log: parser.h,v $ + * Revision 1.1.1.1 2004/02/26 13:13:58 jesse + * Initial import into CVS + * + * Revision 1.3 1998/12/14 13:18:44 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.2 1997/03/03 04:19:16 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:04 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.2 1996/02/08 06:15:30 pavel + * Removed ungetch() method on Parser_Client, added version number to + * parse_program. Updated copyright notice for 1996. Release 1.8.0beta1. + * + * Revision 2.1 1995/12/28 00:47:29 pavel + * Added support for MOO-compilation warnings. Release 1.8.0alpha3. + * + * Revision 2.0 1995/11/30 04:54:19 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.5 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.4 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.3 1992/10/06 18:26:41 pavel + * Changed name of global Parser_Client to avoid a name clash. + * + * Revision 1.2 1992/09/14 17:42:46 pjames + * Moved db_modification code to db modules. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/parser.c b/gnoemoe/parser/parser.c new file mode 100644 index 0000000..e715a39 --- /dev/null +++ b/gnoemoe/parser/parser.c @@ -0,0 +1,3224 @@ +/* A Bison parser, made by GNU Bison 2.0. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + tINTEGER = 258, + tOBJECT = 259, + tFLOAT = 260, + tSTRING = 261, + tID = 262, + tERROR = 263, + tIF = 264, + tELSE = 265, + tELSEIF = 266, + tENDIF = 267, + tFOR = 268, + tIN = 269, + tENDFOR = 270, + tRETURN = 271, + tFORK = 272, + tENDFORK = 273, + tWHILE = 274, + tENDWHILE = 275, + tTRY = 276, + tENDTRY = 277, + tEXCEPT = 278, + tFINALLY = 279, + tANY = 280, + tBREAK = 281, + tCONTINUE = 282, + tTO = 283, + tARROW = 284, + tAND = 285, + tOR = 286, + tGE = 287, + tLE = 288, + tNE = 289, + tEQ = 290, + tUNARYMINUS = 291 + }; +#endif +#define tINTEGER 258 +#define tOBJECT 259 +#define tFLOAT 260 +#define tSTRING 261 +#define tID 262 +#define tERROR 263 +#define tIF 264 +#define tELSE 265 +#define tELSEIF 266 +#define tENDIF 267 +#define tFOR 268 +#define tIN 269 +#define tENDFOR 270 +#define tRETURN 271 +#define tFORK 272 +#define tENDFORK 273 +#define tWHILE 274 +#define tENDWHILE 275 +#define tTRY 276 +#define tENDTRY 277 +#define tEXCEPT 278 +#define tFINALLY 279 +#define tANY 280 +#define tBREAK 281 +#define tCONTINUE 282 +#define tTO 283 +#define tARROW 284 +#define tAND 285 +#define tOR 286 +#define tGE 287 +#define tLE 288 +#define tNE 289 +#define tEQ 290 +#define tUNARYMINUS 291 + + + + +/* Copy the first part of user declarations. */ +#line 1 "parser.y" + +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +/*************************************************************************/ +/* NOTE: If you add an #include here, make sure you properly update the */ +/* parser.o dependency line in the Makefile. */ +/*************************************************************************/ + +#include +#include +#include +#include + +#include "ast.h" +#include "config.h" +#include "functions.h" +#include "keywords.h" +#include "list.h" +//#include "numbers.h" +//#include "opcode.h" +#include "parser.h" +#include "parsen.h" +//#include "program.h" +#include "storage.h" +#include "streams.h" +#include "structures.h" +//#include "sym_table.h" +#include "utils.h" +#include "version.h" + +static Stmt *prog_start; +static int dollars_ok; +static DB_Version language_version; + +static void error(const char *, const char *); +static void warning(const char *, const char *); +static int find_id(char *name); +static void yyerror(const char *s); +static int yylex(void); +static Scatter *scatter_from_arglist(Arg_List *); +static Scatter *add_scatter_item(Scatter *, Scatter *); +static void vet_scatter(Scatter *); +static void push_loop_name(const char *); +static void pop_loop_name(void); +static void suspend_loop_scope(void); +static void resume_loop_scope(void); + +enum loop_exit_kind { LOOP_BREAK, LOOP_CONTINUE }; + +static void check_loop_name(const char *, enum loop_exit_kind); + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 68 "parser.y" +typedef union YYSTYPE { + Stmt *stmt; + Expr *expr; + int integer; + Objid object; + double *real; + char *string; + enum error error; + Arg_List *args; + Cond_Arm *arm; + Except_Arm *except; + Scatter *scatter; +} YYSTYPE; +/* Line 190 of yacc.c. */ +#line 229 "parser.c" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +/* Line 213 of yacc.c. */ +#line 241 "parser.c" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +# ifndef YYFREE +# define YYFREE free +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# endif + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# else +# define YYSTACK_ALLOC alloca +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short int yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined (__GNUC__) && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short int yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 3 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 1481 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 63 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 24 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 94 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 216 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 291 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 47, 2, 2, 52, 45, 2, 60, + 53, 54, 43, 41, 62, 42, 49, 44, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 50, 56, + 35, 30, 36, 31, 61, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 51, 2, 55, 46, 2, 59, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 57, 32, 58, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 33, 34, 37, 38, 39, + 40, 48 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned short int yyprhs[] = +{ + 0, 0, 3, 5, 6, 9, 18, 19, 29, 30, + 42, 43, 51, 52, 61, 62, 70, 71, 80, 83, + 86, 90, 93, 97, 101, 104, 106, 111, 117, 118, + 125, 126, 129, 132, 133, 138, 144, 145, 147, 149, + 151, 153, 155, 157, 159, 162, 166, 172, 179, 185, + 194, 200, 208, 210, 214, 220, 225, 229, 233, 237, + 241, 245, 249, 253, 257, 261, 265, 269, 273, 277, + 281, 285, 288, 291, 295, 299, 305, 312, 313, 315, + 317, 318, 321, 322, 324, 326, 329, 333, 338, 342, + 346, 350, 355, 357, 360 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yysigned_char yyrhs[] = +{ + 64, 0, -1, 65, -1, -1, 65, 66, -1, 9, + 53, 79, 54, 65, 73, 74, 12, -1, -1, 13, + 7, 14, 53, 79, 54, 67, 65, 15, -1, -1, + 13, 7, 14, 51, 79, 28, 79, 55, 68, 65, + 15, -1, -1, 19, 53, 79, 54, 69, 65, 20, + -1, -1, 19, 7, 53, 79, 54, 70, 65, 20, + -1, -1, 17, 53, 79, 54, 71, 65, 18, -1, + -1, 17, 7, 53, 79, 54, 72, 65, 18, -1, + 79, 56, -1, 26, 56, -1, 26, 7, 56, -1, + 27, 56, -1, 27, 7, 56, -1, 16, 79, 56, + -1, 16, 56, -1, 56, -1, 21, 65, 75, 22, + -1, 21, 65, 24, 65, 22, -1, -1, 73, 11, + 53, 79, 54, 65, -1, -1, 10, 65, -1, 23, + 77, -1, -1, 75, 23, 76, 77, -1, 78, 53, + 81, 54, 65, -1, -1, 7, -1, 3, -1, 5, + -1, 6, -1, 4, -1, 8, -1, 7, -1, 52, + 7, -1, 79, 49, 7, -1, 79, 49, 53, 79, + 54, -1, 79, 50, 7, 53, 83, 54, -1, 52, + 7, 53, 83, 54, -1, 79, 50, 53, 79, 54, + 53, 83, 54, -1, 79, 51, 80, 79, 55, -1, + 79, 51, 80, 79, 28, 79, 55, -1, 52, -1, + 79, 30, 79, -1, 57, 85, 58, 30, 79, -1, + 7, 53, 83, 54, -1, 79, 41, 79, -1, 79, + 42, 79, -1, 79, 43, 79, -1, 79, 44, 79, + -1, 79, 45, 79, -1, 79, 46, 79, -1, 79, + 33, 79, -1, 79, 34, 79, -1, 79, 40, 79, + -1, 79, 39, 79, -1, 79, 35, 79, -1, 79, + 38, 79, -1, 79, 36, 79, -1, 79, 37, 79, + -1, 79, 14, 79, -1, 42, 79, -1, 47, 79, + -1, 53, 79, 54, -1, 57, 83, 58, -1, 79, + 31, 79, 32, 79, -1, 59, 79, 47, 81, 82, + 60, -1, -1, 25, -1, 84, -1, -1, 29, 79, + -1, -1, 84, -1, 79, -1, 61, 79, -1, 84, + 62, 79, -1, 84, 62, 61, 79, -1, 84, 62, + 86, -1, 85, 62, 86, -1, 85, 62, 7, -1, + 85, 62, 61, 7, -1, 86, -1, 31, 7, -1, + 31, 7, 30, 79, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned short int yyrline[] = +{ + 0, 112, 112, 118, 119, 134, 143, 142, 155, 154, + 168, 167, 180, 179, 192, 191, 204, 203, 215, 220, + 226, 232, 238, 244, 249, 254, 256, 262, 272, 273, + 291, 292, 297, 300, 299, 325, 331, 332, 337, 342, + 347, 352, 357, 362, 367, 376, 383, 387, 394, 403, + 407, 412, 420, 426, 448, 456, 477, 481, 485, 489, + 493, 497, 501, 505, 509, 513, 517, 521, 525, 529, + 533, 537, 558, 563, 565, 570, 577, 588, 591, 593, + 598, 599, 604, 605, 610, 612, 614, 628, 645, 654, + 658, 663, 668, 673, 677 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "tINTEGER", "tOBJECT", "tFLOAT", + "tSTRING", "tID", "tERROR", "tIF", "tELSE", "tELSEIF", "tENDIF", "tFOR", + "tIN", "tENDFOR", "tRETURN", "tFORK", "tENDFORK", "tWHILE", "tENDWHILE", + "tTRY", "tENDTRY", "tEXCEPT", "tFINALLY", "tANY", "tBREAK", "tCONTINUE", + "tTO", "tARROW", "'='", "'?'", "'|'", "tAND", "tOR", "'<'", "'>'", "tGE", + "tLE", "tNE", "tEQ", "'+'", "'-'", "'*'", "'/'", "'%'", "'^'", "'!'", + "tUNARYMINUS", "'.'", "':'", "'['", "'$'", "'('", "')'", "']'", "';'", + "'{'", "'}'", "'`'", "'''", "'@'", "','", "$accept", "program", + "statements", "statement", "@1", "@2", "@3", "@4", "@5", "@6", "elseifs", + "elsepart", "excepts", "@7", "except", "opt_id", "expr", "dollars_up", + "codes", "default", "arglist", "ne_arglist", "scatter", "scatter_item", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short int yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 61, 63, 124, 285, 286, 60, 62, 287, 288, 289, + 290, 43, 45, 42, 47, 37, 94, 33, 291, 46, + 58, 91, 36, 40, 41, 93, 59, 123, 125, 96, + 39, 64, 44 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 63, 64, 65, 65, 66, 67, 66, 68, 66, + 69, 66, 70, 66, 71, 66, 72, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 73, 73, + 74, 74, 75, 76, 75, 77, 78, 78, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 80, 81, 81, + 82, 82, 83, 83, 84, 84, 84, 84, 85, 85, + 85, 85, 85, 86, 86 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 1, 0, 2, 8, 0, 9, 0, 11, + 0, 7, 0, 8, 0, 7, 0, 8, 2, 2, + 3, 2, 3, 3, 2, 1, 4, 5, 0, 6, + 0, 2, 2, 0, 4, 5, 0, 1, 1, 1, + 1, 1, 1, 1, 2, 3, 5, 6, 5, 8, + 5, 7, 1, 3, 5, 4, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 2, 2, 3, 3, 5, 6, 0, 1, 1, + 0, 2, 0, 1, 1, 2, 3, 4, 3, 3, + 3, 4, 1, 2, 4 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 3, 0, 2, 1, 38, 41, 39, 40, 43, 42, + 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, + 52, 0, 25, 82, 0, 4, 0, 82, 0, 0, + 24, 0, 0, 0, 0, 0, 0, 0, 19, 0, + 21, 71, 72, 44, 0, 0, 0, 84, 0, 83, + 0, 92, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 77, 18, 0, 83, 0, 0, 23, 0, + 0, 0, 0, 36, 3, 0, 20, 22, 82, 73, + 93, 85, 74, 0, 0, 0, 0, 70, 53, 0, + 62, 63, 66, 68, 69, 67, 65, 64, 56, 57, + 58, 59, 60, 61, 45, 0, 0, 0, 0, 55, + 0, 3, 0, 0, 0, 14, 0, 10, 37, 32, + 0, 0, 26, 33, 0, 0, 0, 86, 88, 0, + 90, 0, 89, 78, 80, 79, 0, 0, 82, 0, + 0, 28, 0, 0, 16, 3, 12, 3, 0, 27, + 36, 48, 94, 87, 54, 91, 0, 0, 75, 46, + 0, 0, 0, 50, 30, 0, 6, 3, 0, 3, + 0, 0, 34, 81, 76, 47, 82, 0, 3, 0, + 0, 0, 3, 0, 15, 0, 11, 3, 0, 51, + 31, 0, 5, 8, 0, 17, 13, 35, 49, 0, + 3, 7, 3, 0, 29, 9 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const short int yydefgoto[] = +{ + -1, 1, 2, 25, 192, 210, 157, 179, 155, 177, + 174, 190, 85, 160, 129, 130, 26, 118, 144, 167, + 48, 75, 50, 51 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -53 +static const short int yypact[] = +{ + -53, 1, 754, -53, -53, -53, -53, -53, -35, -53, + -26, 28, 331, 12, 17, -53, 8, 15, 445, 445, + 37, 445, -53, 149, 445, -53, 784, 26, 445, 52, + -53, 817, 22, 445, 24, 445, 298, 32, -53, 47, + -53, -9, -9, 27, 949, 97, 445, 1379, 51, 43, + -52, -53, 1279, 445, 445, 445, 445, 445, 445, 445, + 445, 445, 445, 445, 445, 445, 445, 445, 445, 445, + 29, 31, -53, -53, 53, 50, 982, -28, -53, 445, + 1015, 445, 1048, 107, -53, 74, -53, -53, 26, -53, + 87, 1379, -53, 180, 92, 6, 209, 49, 1379, 1313, + 1430, 1430, 49, 49, 49, 49, 49, 49, 75, 75, + -42, -42, -42, -42, -53, 445, 77, 445, 445, -53, + 239, -53, 445, 445, 1081, -53, 1114, -53, -53, -53, + 78, 355, -53, -53, 73, 445, 445, 1379, -53, 445, + -53, 126, -53, -53, 105, 50, 445, 1147, 26, 1180, + 850, 754, 1346, 1213, -53, -53, -53, -53, 209, -53, + 107, -53, 1379, 1379, 1379, -53, 445, 76, 1412, -53, + 81, 84, 445, -53, 91, 445, -53, -53, 412, -53, + 469, 89, -53, 1379, -53, -53, 26, 883, -53, 93, + 132, 916, -53, 526, -53, 583, -53, -53, 94, -53, + 754, 445, -53, -53, 640, -53, -53, 754, -53, 1246, + -53, -53, -53, 697, 754, -53 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yysigned_char yypgoto[] = +{ + -53, -53, -15, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -13, -53, -7, -53, -8, -53, + -25, -20, -53, -50 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const short int yytable[] = +{ + 36, 3, 74, 49, 69, 31, 94, 70, 71, 72, + 95, 41, 42, 140, 44, 37, 47, 52, 27, 32, + 47, 76, 39, 122, 34, 123, 80, 28, 82, 4, + 5, 6, 7, 8, 9, 29, 114, 45, 116, 91, + 70, 71, 72, 138, 43, 142, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 134, 38, 33, 77, 141, 18, 131, + 35, 40, 124, 19, 126, 79, 145, 81, 20, 21, + 88, 47, 115, 23, 117, 24, 137, 46, 86, 47, + 64, 65, 66, 67, 68, 69, 132, 133, 70, 71, + 72, 188, 189, 87, 90, 93, 151, 119, 147, 92, + 149, 150, 120, 137, 128, 152, 153, 135, 66, 67, + 68, 69, 139, 170, 70, 71, 72, 161, 162, 163, + 148, 158, 164, 165, 166, 185, 184, 186, 145, 168, + 178, 47, 180, 197, 202, 0, 201, 182, 208, 0, + 181, 47, 4, 5, 6, 7, 8, 9, 0, 183, + 0, 198, 193, 0, 195, 187, 0, 0, 191, 0, + 0, 0, 0, 200, 0, 0, 0, 204, 0, 47, + 45, 0, 207, 4, 5, 6, 7, 8, 9, 0, + 0, 18, 0, 0, 209, 213, 19, 214, 0, 0, + 0, 20, 21, 0, 0, 0, 23, 0, 24, 0, + 46, 45, 4, 5, 6, 7, 8, 9, 0, 0, + 0, 0, 18, 0, 0, 0, 0, 19, 0, 0, + 0, 0, 20, 21, 143, 0, 0, 23, 0, 24, + 0, 136, 4, 5, 6, 7, 8, 9, 0, 0, + 0, 18, 0, 0, 0, 0, 19, 0, 0, 0, + 0, 20, 21, 0, 0, 0, 23, 0, 24, 0, + 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 18, 0, 0, 0, 0, 19, 0, 0, 0, + 0, 20, 21, 0, 0, 0, 23, 0, 24, 0, + 136, 4, 5, 6, 7, 8, 9, 10, 0, 0, + 0, 11, 0, 0, 12, 13, 0, 14, 0, 15, + 0, 83, 84, 0, 16, 17, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, + 18, 0, 0, 0, 0, 19, 0, 0, 0, 0, + 20, 21, 0, 0, 22, 23, 0, 24, 4, 5, + 6, 7, 8, 9, 10, 0, 0, 0, 11, 0, + 0, 12, 13, 18, 14, 0, 15, 159, 19, 0, + 0, 16, 17, 20, 21, 0, 0, 30, 23, 0, + 24, 0, 0, 0, 0, 0, 0, 18, 0, 0, + 0, 0, 19, 0, 0, 0, 0, 20, 21, 0, + 0, 22, 23, 0, 24, 4, 5, 6, 7, 8, + 9, 10, 0, 0, 0, 11, 0, 0, 12, 13, + 194, 14, 0, 15, 0, 0, 0, 0, 16, 17, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 5, + 6, 7, 8, 9, 18, 0, 0, 0, 0, 19, + 0, 0, 0, 0, 20, 21, 0, 0, 22, 23, + 0, 24, 4, 5, 6, 7, 8, 9, 10, 0, + 0, 0, 11, 0, 0, 12, 13, 18, 14, 196, + 15, 0, 19, 0, 0, 16, 17, 20, 21, 0, + 0, 0, 23, 0, 24, 0, 0, 0, 0, 0, + 0, 18, 0, 0, 0, 0, 19, 0, 0, 0, + 0, 20, 21, 0, 0, 22, 23, 0, 24, 4, + 5, 6, 7, 8, 9, 10, 0, 0, 0, 11, + 0, 0, 12, 13, 205, 14, 0, 15, 0, 0, + 0, 0, 16, 17, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, + 0, 0, 0, 19, 0, 0, 0, 0, 20, 21, + 0, 0, 22, 23, 0, 24, 4, 5, 6, 7, + 8, 9, 10, 0, 0, 0, 11, 0, 0, 12, + 13, 0, 14, 206, 15, 0, 0, 0, 0, 16, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, + 19, 0, 0, 0, 0, 20, 21, 0, 0, 22, + 23, 0, 24, 4, 5, 6, 7, 8, 9, 10, + 0, 0, 0, 11, 0, 211, 12, 13, 0, 14, + 0, 15, 0, 0, 0, 0, 16, 17, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 18, 0, 0, 0, 0, 19, 0, 0, + 0, 0, 20, 21, 0, 0, 22, 23, 0, 24, + 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, + 11, 0, 215, 12, 13, 0, 14, 0, 15, 0, + 0, 0, 0, 16, 17, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, + 0, 0, 0, 0, 19, 0, 0, 0, 0, 20, + 21, 0, 0, 22, 23, 0, 24, 4, 5, 6, + 7, 8, 9, 10, 0, 0, 0, 11, 0, 0, + 12, 13, 0, 14, 0, 15, 0, 0, 0, 0, + 16, 17, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 18, 0, 53, 0, + 0, 19, 0, 0, 0, 0, 20, 21, 0, 0, + 22, 23, 0, 24, 54, 55, 0, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 53, 0, 70, 71, 72, 0, 0, 0, 0, + 73, 0, 0, 0, 0, 0, 0, 54, 55, 0, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 53, 0, 70, 71, 72, 0, + 0, 0, 0, 78, 0, 0, 0, 0, 172, 0, + 54, 55, 0, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 53, 0, 70, + 71, 72, 0, 0, 0, 173, 0, 0, 0, 0, + 0, 0, 0, 54, 55, 0, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 53, 0, 70, 71, 72, 0, 0, 0, 199, 0, + 0, 0, 0, 0, 0, 0, 54, 55, 0, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 53, 0, 70, 71, 72, 0, 0, + 0, 203, 0, 0, 0, 0, 0, 0, 0, 54, + 55, 0, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 53, 0, 70, 71, + 72, 0, 0, 89, 0, 0, 0, 0, 0, 0, + 0, 0, 54, 55, 0, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 53, + 0, 70, 71, 72, 0, 0, 121, 0, 0, 0, + 0, 0, 0, 0, 0, 54, 55, 0, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 53, 0, 70, 71, 72, 0, 0, 125, + 0, 0, 0, 0, 0, 0, 0, 0, 54, 55, + 0, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 53, 0, 70, 71, 72, + 0, 0, 127, 0, 0, 0, 0, 0, 0, 0, + 0, 54, 55, 0, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 53, 0, + 70, 71, 72, 0, 0, 154, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 55, 0, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 53, 0, 70, 71, 72, 0, 0, 156, 0, + 0, 0, 0, 0, 0, 0, 0, 54, 55, 0, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 53, 0, 70, 71, 72, 0, + 0, 169, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 55, 0, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 53, 0, 70, + 71, 72, 0, 0, 171, 0, 0, 0, 0, 0, + 0, 0, 0, 54, 55, 0, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 53, 0, 70, 71, 72, 0, 0, 176, 0, 0, + 0, 0, 0, 0, 0, 0, 54, 55, 0, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 53, 0, 70, 71, 72, 0, 0, + 212, 0, 0, 0, 0, 0, 0, 0, 0, 54, + 55, 0, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 96, 53, 70, 71, + 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 54, 55, 146, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 53, 0, 70, 71, 72, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 175, 0, 54, 55, 0, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 53, 0, 70, 71, 72, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, + 55, 0, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 53, 0, 70, 71, + 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -1, 53, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 0, + 0, 70, 71, 72, 0, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 0, 0, 70, + 71, 72 +}; + +static const short int yycheck[] = +{ + 15, 0, 27, 23, 46, 12, 58, 49, 50, 51, + 62, 18, 19, 7, 21, 7, 23, 24, 53, 7, + 27, 28, 7, 51, 7, 53, 33, 53, 35, 3, + 4, 5, 6, 7, 8, 7, 7, 31, 7, 46, + 49, 50, 51, 93, 7, 95, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 88, 56, 53, 14, 61, 42, 84, + 53, 56, 79, 47, 81, 53, 96, 53, 52, 53, + 53, 88, 53, 57, 53, 59, 93, 61, 56, 96, + 41, 42, 43, 44, 45, 46, 22, 23, 49, 50, + 51, 10, 11, 56, 7, 62, 121, 54, 115, 58, + 117, 118, 62, 120, 7, 122, 123, 30, 43, 44, + 45, 46, 30, 148, 49, 50, 51, 54, 135, 136, + 53, 53, 139, 7, 29, 54, 60, 53, 158, 146, + 155, 148, 157, 54, 12, -1, 53, 160, 54, -1, + 158, 158, 3, 4, 5, 6, 7, 8, -1, 166, + -1, 186, 177, -1, 179, 172, -1, -1, 175, -1, + -1, -1, -1, 188, -1, -1, -1, 192, -1, 186, + 31, -1, 197, 3, 4, 5, 6, 7, 8, -1, + -1, 42, -1, -1, 201, 210, 47, 212, -1, -1, + -1, 52, 53, -1, -1, -1, 57, -1, 59, -1, + 61, 31, 3, 4, 5, 6, 7, 8, -1, -1, + -1, -1, 42, -1, -1, -1, -1, 47, -1, -1, + -1, -1, 52, 53, 25, -1, -1, 57, -1, 59, + -1, 61, 3, 4, 5, 6, 7, 8, -1, -1, + -1, 42, -1, -1, -1, -1, 47, -1, -1, -1, + -1, 52, 53, -1, -1, -1, 57, -1, 59, -1, + 61, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 42, -1, -1, -1, -1, 47, -1, -1, -1, + -1, 52, 53, -1, -1, -1, 57, -1, 59, -1, + 61, 3, 4, 5, 6, 7, 8, 9, -1, -1, + -1, 13, -1, -1, 16, 17, -1, 19, -1, 21, + -1, 23, 24, -1, 26, 27, -1, -1, -1, -1, + -1, -1, -1, -1, 3, 4, 5, 6, 7, 8, + 42, -1, -1, -1, -1, 47, -1, -1, -1, -1, + 52, 53, -1, -1, 56, 57, -1, 59, 3, 4, + 5, 6, 7, 8, 9, -1, -1, -1, 13, -1, + -1, 16, 17, 42, 19, -1, 21, 22, 47, -1, + -1, 26, 27, 52, 53, -1, -1, 56, 57, -1, + 59, -1, -1, -1, -1, -1, -1, 42, -1, -1, + -1, -1, 47, -1, -1, -1, -1, 52, 53, -1, + -1, 56, 57, -1, 59, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, 13, -1, -1, 16, 17, + 18, 19, -1, 21, -1, -1, -1, -1, 26, 27, + -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, + 5, 6, 7, 8, 42, -1, -1, -1, -1, 47, + -1, -1, -1, -1, 52, 53, -1, -1, 56, 57, + -1, 59, 3, 4, 5, 6, 7, 8, 9, -1, + -1, -1, 13, -1, -1, 16, 17, 42, 19, 20, + 21, -1, 47, -1, -1, 26, 27, 52, 53, -1, + -1, -1, 57, -1, 59, -1, -1, -1, -1, -1, + -1, 42, -1, -1, -1, -1, 47, -1, -1, -1, + -1, 52, 53, -1, -1, 56, 57, -1, 59, 3, + 4, 5, 6, 7, 8, 9, -1, -1, -1, 13, + -1, -1, 16, 17, 18, 19, -1, 21, -1, -1, + -1, -1, 26, 27, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, + -1, -1, -1, 47, -1, -1, -1, -1, 52, 53, + -1, -1, 56, 57, -1, 59, 3, 4, 5, 6, + 7, 8, 9, -1, -1, -1, 13, -1, -1, 16, + 17, -1, 19, 20, 21, -1, -1, -1, -1, 26, + 27, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, + 47, -1, -1, -1, -1, 52, 53, -1, -1, 56, + 57, -1, 59, 3, 4, 5, 6, 7, 8, 9, + -1, -1, -1, 13, -1, 15, 16, 17, -1, 19, + -1, 21, -1, -1, -1, -1, 26, 27, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 42, -1, -1, -1, -1, 47, -1, -1, + -1, -1, 52, 53, -1, -1, 56, 57, -1, 59, + 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, + 13, -1, 15, 16, 17, -1, 19, -1, 21, -1, + -1, -1, -1, 26, 27, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, + -1, -1, -1, -1, 47, -1, -1, -1, -1, 52, + 53, -1, -1, 56, 57, -1, 59, 3, 4, 5, + 6, 7, 8, 9, -1, -1, -1, 13, -1, -1, + 16, 17, -1, 19, -1, 21, -1, -1, -1, -1, + 26, 27, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 42, -1, 14, -1, + -1, 47, -1, -1, -1, -1, 52, 53, -1, -1, + 56, 57, -1, 59, 30, 31, -1, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 14, -1, 49, 50, 51, -1, -1, -1, -1, + 56, -1, -1, -1, -1, -1, -1, 30, 31, -1, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 14, -1, 49, 50, 51, -1, + -1, -1, -1, 56, -1, -1, -1, -1, 28, -1, + 30, 31, -1, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 14, -1, 49, + 50, 51, -1, -1, -1, 55, -1, -1, -1, -1, + -1, -1, -1, 30, 31, -1, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 14, -1, 49, 50, 51, -1, -1, -1, 55, -1, + -1, -1, -1, -1, -1, -1, 30, 31, -1, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 14, -1, 49, 50, 51, -1, -1, + -1, 55, -1, -1, -1, -1, -1, -1, -1, 30, + 31, -1, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 14, -1, 49, 50, + 51, -1, -1, 54, -1, -1, -1, -1, -1, -1, + -1, -1, 30, 31, -1, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 14, + -1, 49, 50, 51, -1, -1, 54, -1, -1, -1, + -1, -1, -1, -1, -1, 30, 31, -1, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 14, -1, 49, 50, 51, -1, -1, 54, + -1, -1, -1, -1, -1, -1, -1, -1, 30, 31, + -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 14, -1, 49, 50, 51, + -1, -1, 54, -1, -1, -1, -1, -1, -1, -1, + -1, 30, 31, -1, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 14, -1, + 49, 50, 51, -1, -1, 54, -1, -1, -1, -1, + -1, -1, -1, -1, 30, 31, -1, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 14, -1, 49, 50, 51, -1, -1, 54, -1, + -1, -1, -1, -1, -1, -1, -1, 30, 31, -1, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 14, -1, 49, 50, 51, -1, + -1, 54, -1, -1, -1, -1, -1, -1, -1, -1, + 30, 31, -1, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 14, -1, 49, + 50, 51, -1, -1, 54, -1, -1, -1, -1, -1, + -1, -1, -1, 30, 31, -1, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 14, -1, 49, 50, 51, -1, -1, 54, -1, -1, + -1, -1, -1, -1, -1, -1, 30, 31, -1, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 14, -1, 49, 50, 51, -1, -1, + 54, -1, -1, -1, -1, -1, -1, -1, -1, 30, + 31, -1, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 14, 49, 50, + 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 14, -1, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 28, -1, 30, 31, -1, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 14, -1, 49, 50, 51, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 30, + 31, -1, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 14, -1, 49, 50, + 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 31, 14, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, -1, + -1, 49, 50, 51, -1, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, -1, -1, 49, + 50, 51 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 64, 65, 0, 3, 4, 5, 6, 7, 8, + 9, 13, 16, 17, 19, 21, 26, 27, 42, 47, + 52, 53, 56, 57, 59, 66, 79, 53, 53, 7, + 56, 79, 7, 53, 7, 53, 65, 7, 56, 7, + 56, 79, 79, 7, 79, 31, 61, 79, 83, 84, + 85, 86, 79, 14, 30, 31, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 49, 50, 51, 56, 83, 84, 79, 14, 56, 53, + 79, 53, 79, 23, 24, 75, 56, 56, 53, 54, + 7, 79, 58, 62, 58, 62, 47, 79, 79, 79, + 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, + 79, 79, 79, 79, 7, 53, 7, 53, 80, 54, + 62, 54, 51, 53, 79, 54, 79, 54, 7, 77, + 78, 65, 22, 23, 83, 30, 61, 79, 86, 30, + 7, 61, 86, 25, 81, 84, 32, 79, 53, 79, + 79, 65, 79, 79, 54, 71, 54, 69, 53, 22, + 76, 54, 79, 79, 79, 7, 29, 82, 79, 54, + 83, 54, 28, 55, 73, 28, 54, 72, 65, 70, + 65, 81, 77, 79, 60, 54, 53, 79, 10, 11, + 74, 79, 67, 65, 18, 65, 20, 54, 83, 55, + 65, 53, 12, 55, 65, 18, 20, 65, 54, 79, + 68, 15, 54, 65, 65, 15 +}; + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror ("syntax error: cannot back up");\ + YYERROR; \ + } \ +while (0) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (0) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yysymprint (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short int *bottom, short int *top) +#else +static void +yy_stack_print (bottom, top) + short int *bottom; + short int *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (/* Nothing. */; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) + int yyrule; +#endif +{ + int yyi; + unsigned int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + yyrule - 1, yylno); + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) + YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +#endif /* !YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) +#else +static void +yysymprint (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyoutput, ")"); +} + +#endif /* ! YYDEBUG */ +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM); +# else +int yyparse (); +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short int yyssa[YYINITDEPTH]; + short int *yyss = yyssa; + register short int *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + + + +#define YYPOPSTACK (yyvsp--, yyssp--) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + + yyvsp[0] = yylval; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short int *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyoverflowlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + short int *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a look-ahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to look-ahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 113 "parser.y" + { prog_start = (yyvsp[0].stmt); } + break; + + case 3: +#line 118 "parser.y" + { (yyval.stmt) = 0; } + break; + + case 4: +#line 120 "parser.y" + { + if ((yyvsp[-1].stmt)) { + Stmt *tmp = (yyvsp[-1].stmt); + + while (tmp->next) + tmp = tmp->next; + tmp->next = (yyvsp[0].stmt); + (yyval.stmt) = (yyvsp[-1].stmt); + } else + (yyval.stmt) = (yyvsp[0].stmt); + } + break; + + case 5: +#line 135 "parser.y" + { + + (yyval.stmt) = alloc_stmt(STMT_COND); + (yyval.stmt)->s.cond.arms = alloc_cond_arm((yyvsp[-5].expr), (yyvsp[-3].stmt)); + (yyval.stmt)->s.cond.arms->next = (yyvsp[-2].arm); + (yyval.stmt)->s.cond.otherwise = (yyvsp[-1].stmt); + } + break; + + case 6: +#line 143 "parser.y" + { + push_loop_name((yyvsp[-4].string)); + } + break; + + case 7: +#line 147 "parser.y" + { + (yyval.stmt) = alloc_stmt(STMT_LIST); + (yyval.stmt)->s.list.id = find_id((yyvsp[-7].string)); + (yyval.stmt)->s.list.expr = (yyvsp[-4].expr); + (yyval.stmt)->s.list.body = (yyvsp[-1].stmt); + pop_loop_name(); + } + break; + + case 8: +#line 155 "parser.y" + { + push_loop_name((yyvsp[-6].string)); + } + break; + + case 9: +#line 159 "parser.y" + { + (yyval.stmt) = alloc_stmt(STMT_RANGE); + (yyval.stmt)->s.range.id = find_id((yyvsp[-9].string)); + (yyval.stmt)->s.range.from = (yyvsp[-6].expr); + (yyval.stmt)->s.range.to = (yyvsp[-4].expr); + (yyval.stmt)->s.range.body = (yyvsp[-1].stmt); + pop_loop_name(); + } + break; + + case 10: +#line 168 "parser.y" + { + push_loop_name(0); + } + break; + + case 11: +#line 172 "parser.y" + { + (yyval.stmt) = alloc_stmt(STMT_WHILE); + (yyval.stmt)->s.loop.id = -1; + (yyval.stmt)->s.loop.condition = (yyvsp[-4].expr); + (yyval.stmt)->s.loop.body = (yyvsp[-1].stmt); + pop_loop_name(); + } + break; + + case 12: +#line 180 "parser.y" + { + push_loop_name((yyvsp[-3].string)); + } + break; + + case 13: +#line 184 "parser.y" + { + (yyval.stmt) = alloc_stmt(STMT_WHILE); + (yyval.stmt)->s.loop.id = find_id((yyvsp[-6].string)); + (yyval.stmt)->s.loop.condition = (yyvsp[-4].expr); + (yyval.stmt)->s.loop.body = (yyvsp[-1].stmt); + pop_loop_name(); + } + break; + + case 14: +#line 192 "parser.y" + { + suspend_loop_scope(); + } + break; + + case 15: +#line 196 "parser.y" + { + (yyval.stmt) = alloc_stmt(STMT_FORK); + (yyval.stmt)->s.fork.id = -1; + (yyval.stmt)->s.fork.time = (yyvsp[-4].expr); + (yyval.stmt)->s.fork.body = (yyvsp[-1].stmt); + resume_loop_scope(); + } + break; + + case 16: +#line 204 "parser.y" + { + suspend_loop_scope(); + } + break; + + case 17: +#line 208 "parser.y" + { + (yyval.stmt) = alloc_stmt(STMT_FORK); + (yyval.stmt)->s.fork.id = find_id((yyvsp[-6].string)); + (yyval.stmt)->s.fork.time = (yyvsp[-4].expr); + (yyval.stmt)->s.fork.body = (yyvsp[-1].stmt); + resume_loop_scope(); + } + break; + + case 18: +#line 216 "parser.y" + { + (yyval.stmt) = alloc_stmt(STMT_EXPR); + (yyval.stmt)->s.expr = (yyvsp[-1].expr); + } + break; + + case 19: +#line 221 "parser.y" + { + check_loop_name(0, LOOP_BREAK); + (yyval.stmt) = alloc_stmt(STMT_BREAK); + (yyval.stmt)->s.exit = -1; + } + break; + + case 20: +#line 227 "parser.y" + { + check_loop_name((yyvsp[-1].string), LOOP_BREAK); + (yyval.stmt) = alloc_stmt(STMT_BREAK); + (yyval.stmt)->s.exit = find_id((yyvsp[-1].string)); + } + break; + + case 21: +#line 233 "parser.y" + { + check_loop_name(0, LOOP_CONTINUE); + (yyval.stmt) = alloc_stmt(STMT_CONTINUE); + (yyval.stmt)->s.exit = -1; + } + break; + + case 22: +#line 239 "parser.y" + { + check_loop_name((yyvsp[-1].string), LOOP_CONTINUE); + (yyval.stmt) = alloc_stmt(STMT_CONTINUE); + (yyval.stmt)->s.exit = find_id((yyvsp[-1].string)); + } + break; + + case 23: +#line 245 "parser.y" + { + (yyval.stmt) = alloc_stmt(STMT_RETURN); + (yyval.stmt)->s.expr = (yyvsp[-1].expr); + } + break; + + case 24: +#line 250 "parser.y" + { + (yyval.stmt) = alloc_stmt(STMT_RETURN); + (yyval.stmt)->s.expr = 0; + } + break; + + case 25: +#line 255 "parser.y" + { (yyval.stmt) = 0; } + break; + + case 26: +#line 257 "parser.y" + { + (yyval.stmt) = alloc_stmt(STMT_TRY_EXCEPT); + (yyval.stmt)->s.catch.body = (yyvsp[-2].stmt); + (yyval.stmt)->s.catch.excepts = (yyvsp[-1].except); + } + break; + + case 27: +#line 263 "parser.y" + { + (yyval.stmt) = alloc_stmt(STMT_TRY_FINALLY); + (yyval.stmt)->s.finally.body = (yyvsp[-3].stmt); + (yyval.stmt)->s.finally.handler = (yyvsp[-1].stmt); + } + break; + + case 28: +#line 272 "parser.y" + { (yyval.arm) = 0; } + break; + + case 29: +#line 274 "parser.y" + { + Cond_Arm *this_arm = alloc_cond_arm((yyvsp[-2].expr), (yyvsp[0].stmt)); + + if ((yyvsp[-5].arm)) { + Cond_Arm *tmp = (yyvsp[-5].arm); + + while (tmp->next) + tmp = tmp->next; + tmp->next = this_arm; + (yyval.arm) = (yyvsp[-5].arm); + } else + (yyval.arm) = this_arm; + } + break; + + case 30: +#line 291 "parser.y" + { (yyval.stmt) = 0; } + break; + + case 31: +#line 293 "parser.y" + { (yyval.stmt) = (yyvsp[0].stmt); } + break; + + case 32: +#line 298 "parser.y" + { (yyval.except) = (yyvsp[0].except); } + break; + + case 33: +#line 300 "parser.y" + { + Except_Arm *tmp = (yyvsp[-1].except); + int count = 1; + + while (tmp->next) { + tmp = tmp->next; + count++; + } + if (!tmp->codes) + yyerror("Unreachable EXCEPT clause"); + else if (count > 255) + yyerror("Too many EXCEPT clauses (max. 255)"); + } + break; + + case 34: +#line 314 "parser.y" + { + Except_Arm *tmp = (yyvsp[-3].except); + + while (tmp->next) + tmp = tmp->next; + + tmp->next = (yyvsp[0].except); + (yyval.except) = (yyvsp[-3].except); + } + break; + + case 35: +#line 326 "parser.y" + { (yyval.except) = alloc_except((yyvsp[-4].string) ? find_id((yyvsp[-4].string)) : -1, (yyvsp[-2].args), (yyvsp[0].stmt)); } + break; + + case 36: +#line 331 "parser.y" + { (yyval.string) = 0; } + break; + + case 37: +#line 333 "parser.y" + { (yyval.string) = (yyvsp[0].string); } + break; + + case 38: +#line 338 "parser.y" + { + (yyval.expr) = alloc_var(TYPE_INT); + (yyval.expr)->e.var.v.num = (yyvsp[0].integer); + } + break; + + case 39: +#line 343 "parser.y" + { + (yyval.expr) = alloc_var(TYPE_FLOAT); + (yyval.expr)->e.var.v.fnum = (yyvsp[0].real); + } + break; + + case 40: +#line 348 "parser.y" + { + (yyval.expr) = alloc_var(TYPE_STR); + (yyval.expr)->e.var.v.str = (yyvsp[0].string); + } + break; + + case 41: +#line 353 "parser.y" + { + (yyval.expr) = alloc_var(TYPE_OBJ); + (yyval.expr)->e.var.v.obj = (yyvsp[0].object); + } + break; + + case 42: +#line 358 "parser.y" + { + (yyval.expr) = alloc_var(TYPE_ERR); + (yyval.expr)->e.var.v.err = (yyvsp[0].error); + } + break; + + case 43: +#line 363 "parser.y" + { + (yyval.expr) = alloc_expr(EXPR_ID); + (yyval.expr)->e.id = find_id((yyvsp[0].string)); + } + break; + + case 44: +#line 368 "parser.y" + { + /* Treat $foo like #0.("foo") */ + Expr *obj = alloc_var(TYPE_OBJ); + Expr *prop = alloc_var(TYPE_STR); + obj->e.var.v.obj = 0; + prop->e.var.v.str = (yyvsp[0].string); + (yyval.expr) = alloc_binary(EXPR_PROP, obj, prop); + } + break; + + case 45: +#line 377 "parser.y" + { + /* Treat foo.bar like foo.("bar") for simplicity */ + Expr *prop = alloc_var(TYPE_STR); + prop->e.var.v.str = (yyvsp[0].string); + (yyval.expr) = alloc_binary(EXPR_PROP, (yyvsp[-2].expr), prop); + } + break; + + case 46: +#line 384 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_PROP, (yyvsp[-4].expr), (yyvsp[-1].expr)); + } + break; + + case 47: +#line 388 "parser.y" + { + /* treat foo:bar(args) like foo:("bar")(args) */ + Expr *verb = alloc_var(TYPE_STR); + verb->e.var.v.str = (yyvsp[-3].string); + (yyval.expr) = alloc_verb((yyvsp[-5].expr), verb, (yyvsp[-1].args)); + } + break; + + case 48: +#line 395 "parser.y" + { + /* treat $bar(args) like #0:("bar")(args) */ + Expr *obj = alloc_var(TYPE_OBJ); + Expr *verb = alloc_var(TYPE_STR); + obj->e.var.v.obj = 0; + verb->e.var.v.str = (yyvsp[-3].string); + (yyval.expr) = alloc_verb(obj, verb, (yyvsp[-1].args)); + } + break; + + case 49: +#line 404 "parser.y" + { + (yyval.expr) = alloc_verb((yyvsp[-7].expr), (yyvsp[-4].expr), (yyvsp[-1].args)); + } + break; + + case 50: +#line 408 "parser.y" + { + dollars_ok--; + (yyval.expr) = alloc_binary(EXPR_INDEX, (yyvsp[-4].expr), (yyvsp[-1].expr)); + } + break; + + case 51: +#line 413 "parser.y" + { + dollars_ok--; + (yyval.expr) = alloc_expr(EXPR_RANGE); + (yyval.expr)->e.range.base = (yyvsp[-6].expr); + (yyval.expr)->e.range.from = (yyvsp[-3].expr); + (yyval.expr)->e.range.to = (yyvsp[-1].expr); + } + break; + + case 52: +#line 421 "parser.y" + { + if (!dollars_ok) + yyerror("Illegal context for `$' expression."); + (yyval.expr) = alloc_expr(EXPR_LENGTH); + } + break; + + case 53: +#line 427 "parser.y" + { + Expr *e = (yyvsp[-2].expr); + + if (e->kind == EXPR_LIST) { + e->kind = EXPR_SCATTER; + if (e->e.list) { + e->e.scatter = scatter_from_arglist(e->e.list); + vet_scatter(e->e.scatter); + } else + yyerror("Empty list in scattering assignment."); + } else { + if (e->kind == EXPR_RANGE) + e = e->e.range.base; + while (e->kind == EXPR_INDEX) + e = e->e.bin.lhs; + if (e->kind != EXPR_ID && e->kind != EXPR_PROP) + yyerror("Illegal expression on left side of" + " assignment."); + } + (yyval.expr) = alloc_binary(EXPR_ASGN, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 54: +#line 449 "parser.y" + { + Expr *e = alloc_expr(EXPR_SCATTER); + + e->e.scatter = (yyvsp[-3].scatter); + vet_scatter((yyvsp[-3].scatter)); + (yyval.expr) = alloc_binary(EXPR_ASGN, e, (yyvsp[0].expr)); + } + break; + + case 55: +#line 457 "parser.y" + { + unsigned f_no; + + (yyval.expr) = alloc_expr(EXPR_CALL); + if ((f_no = number_func_by_name((yyvsp[-3].string))) == FUNC_NOT_FOUND) { + /* Replace with call_function("$1", @args) */ + Expr *fname = alloc_var(TYPE_STR); + Arg_List *a = alloc_arg_list(ARG_NORMAL, fname); + + fname->e.var.v.str = (yyvsp[-3].string); + a->next = (yyvsp[-1].args); + warning("Unknown built-in function: ", (yyvsp[-3].string)); + (yyval.expr)->e.call.func = number_func_by_name("call_function"); + (yyval.expr)->e.call.args = a; + } else { + (yyval.expr)->e.call.func = f_no; + (yyval.expr)->e.call.args = (yyvsp[-1].args); + dealloc_string((yyvsp[-3].string)); + } + } + break; + + case 56: +#line 478 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_PLUS, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 57: +#line 482 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_MINUS, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 58: +#line 486 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_TIMES, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 59: +#line 490 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_DIVIDE, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 60: +#line 494 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_MOD, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 61: +#line 498 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_EXP, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 62: +#line 502 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 63: +#line 506 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 64: +#line 510 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_EQ, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 65: +#line 514 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_NE, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 66: +#line 518 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_LT, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 67: +#line 522 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_LE, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 68: +#line 526 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_GT, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 69: +#line 530 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_GE, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 70: +#line 534 "parser.y" + { + (yyval.expr) = alloc_binary(EXPR_IN, (yyvsp[-2].expr), (yyvsp[0].expr)); + } + break; + + case 71: +#line 538 "parser.y" + { + if ((yyvsp[0].expr)->kind == EXPR_VAR + && ((yyvsp[0].expr)->e.var.type == TYPE_INT + || (yyvsp[0].expr)->e.var.type == TYPE_FLOAT)) { + switch ((yyvsp[0].expr)->e.var.type) { + case TYPE_INT: + (yyvsp[0].expr)->e.var.v.num = -(yyvsp[0].expr)->e.var.v.num; + break; + case TYPE_FLOAT: + *((yyvsp[0].expr)->e.var.v.fnum) = - (*((yyvsp[0].expr)->e.var.v.fnum)); + break; + default: + break; + } + (yyval.expr) = (yyvsp[0].expr); + } else { + (yyval.expr) = alloc_expr(EXPR_NEGATE); + (yyval.expr)->e.expr = (yyvsp[0].expr); + } + } + break; + + case 72: +#line 559 "parser.y" + { + (yyval.expr) = alloc_expr(EXPR_NOT); + (yyval.expr)->e.expr = (yyvsp[0].expr); + } + break; + + case 73: +#line 564 "parser.y" + { (yyval.expr) = (yyvsp[-1].expr); } + break; + + case 74: +#line 566 "parser.y" + { + (yyval.expr) = alloc_expr(EXPR_LIST); + (yyval.expr)->e.list = (yyvsp[-1].args); + } + break; + + case 75: +#line 571 "parser.y" + { + (yyval.expr) = alloc_expr(EXPR_COND); + (yyval.expr)->e.cond.condition = (yyvsp[-4].expr); + (yyval.expr)->e.cond.consequent = (yyvsp[-2].expr); + (yyval.expr)->e.cond.alternate = (yyvsp[0].expr); + } + break; + + case 76: +#line 578 "parser.y" + { + (yyval.expr) = alloc_expr(EXPR_CATCH); + (yyval.expr)->e.catch.try = (yyvsp[-4].expr); + (yyval.expr)->e.catch.codes = (yyvsp[-2].args); + (yyval.expr)->e.catch.except = (yyvsp[-1].expr); + } + break; + + case 77: +#line 588 "parser.y" + { dollars_ok++; } + break; + + case 78: +#line 592 "parser.y" + { (yyval.args) = 0; } + break; + + case 79: +#line 594 "parser.y" + { (yyval.args) = (yyvsp[0].args); } + break; + + case 80: +#line 598 "parser.y" + { (yyval.expr) = 0; } + break; + + case 81: +#line 600 "parser.y" + { (yyval.expr) = (yyvsp[0].expr); } + break; + + case 82: +#line 604 "parser.y" + { (yyval.args) = 0; } + break; + + case 83: +#line 606 "parser.y" + { (yyval.args) = (yyvsp[0].args); } + break; + + case 84: +#line 611 "parser.y" + { (yyval.args) = alloc_arg_list(ARG_NORMAL, (yyvsp[0].expr)); } + break; + + case 85: +#line 613 "parser.y" + { (yyval.args) = alloc_arg_list(ARG_SPLICE, (yyvsp[0].expr)); } + break; + + case 86: +#line 615 "parser.y" + { + Arg_List *this_arg = alloc_arg_list(ARG_NORMAL, (yyvsp[0].expr)); + + if ((yyvsp[-2].args)) { + Arg_List *tmp = (yyvsp[-2].args); + + while (tmp->next) + tmp = tmp->next; + tmp->next = this_arg; + (yyval.args) = (yyvsp[-2].args); + } else + (yyval.args) = this_arg; + } + break; + + case 87: +#line 629 "parser.y" + { + Arg_List *this_arg = alloc_arg_list(ARG_SPLICE, (yyvsp[0].expr)); + + if ((yyvsp[-3].args)) { + Arg_List *tmp = (yyvsp[-3].args); + + while (tmp->next) + tmp = tmp->next; + tmp->next = this_arg; + (yyval.args) = (yyvsp[-3].args); + } else + (yyval.args) = this_arg; + } + break; + + case 88: +#line 646 "parser.y" + { + Scatter *sc = scatter_from_arglist((yyvsp[-2].args)); + + if (sc) + (yyval.scatter) = add_scatter_item(sc, (yyvsp[0].scatter)); + else + (yyval.scatter) = (yyvsp[0].scatter); + } + break; + + case 89: +#line 655 "parser.y" + { + (yyval.scatter) = add_scatter_item((yyvsp[-2].scatter), (yyvsp[0].scatter)); + } + break; + + case 90: +#line 659 "parser.y" + { + (yyval.scatter) = add_scatter_item((yyvsp[-2].scatter), alloc_scatter(SCAT_REQUIRED, + find_id((yyvsp[0].string)), 0)); + } + break; + + case 91: +#line 664 "parser.y" + { + (yyval.scatter) = add_scatter_item((yyvsp[-3].scatter), alloc_scatter(SCAT_REST, + find_id((yyvsp[0].string)), 0)); + } + break; + + case 92: +#line 669 "parser.y" + { (yyval.scatter) = (yyvsp[0].scatter); } + break; + + case 93: +#line 674 "parser.y" + { + (yyval.scatter) = alloc_scatter(SCAT_OPTIONAL, find_id((yyvsp[0].string)), 0); + } + break; + + case 94: +#line 678 "parser.y" + { + (yyval.scatter) = alloc_scatter(SCAT_OPTIONAL, find_id((yyvsp[-2].string)), (yyvsp[0].expr)); + } + break; + + + } + +/* Line 1037 of yacc.c. */ +#line 2396 "parser.c" + + yyvsp -= yylen; + yyssp -= yylen; + + + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + const char* yyprefix; + char *yymsg; + int yyx; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 0; + + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); + yycount += 1; + if (yycount == 5) + { + yysize = 0; + break; + } + } + yysize += (sizeof ("syntax error, unexpected ") + + yystrlen (yytname[yytype])); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); + + if (yycount < 5) + { + yyprefix = ", expecting "; + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + yyp = yystpcpy (yyp, yyprefix); + yyp = yystpcpy (yyp, yytname[yyx]); + yyprefix = " or "; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("syntax error; also virtual memory exhausted"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror ("syntax error"); + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* If at end of input, pop the error token, + then the rest of the stack, then return failure. */ + if (yychar == YYEOF) + for (;;) + { + + YYPOPSTACK; + if (yyssp == yyss) + YYABORT; + yydestruct ("Error: popping", + yystos[*yyssp], yyvsp); + } + } + else + { + yydestruct ("Error: discarding", yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + +#ifdef __GNUC__ + /* Pacify GCC when the user code never invokes YYERROR and the label + yyerrorlab therefore never appears in user code. */ + if (0) + goto yyerrorlab; +#endif + +yyvsp -= yylen; + yyssp -= yylen; + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", yystos[yystate], yyvsp); + YYPOPSTACK; + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yydestruct ("Error: discarding lookahead", + yytoken, &yylval); + yychar = YYEMPTY; + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 683 "parser.y" + + +static int lineno, nerrors, must_rename_keywords; +static Parser_Client client; +static void *client_data; +static Names *local_names; + +static int +find_id(char *name) +{ + int slot = find_or_add_name(&local_names, name); + + dealloc_string(name); + return slot; +} + +static void +yyerror(const char *s) +{ + error(s, 0); +} + +static const char * +fmt_error(const char *s, const char *t) +{ + static Stream *str = 0; + + if (str == 0) + str = new_stream(100); + if (t) + stream_printf(str, "Line %d: %s%s", lineno, s, t); + else + stream_printf(str, "Line %d: %s", lineno, s); + return reset_stream(str); +} + +static void +error(const char *s, const char *t) +{ + nerrors++; + (*(client.error))(client_data, fmt_error(s, t)); +} + +static void +warning(const char *s, const char *t) +{ + if (client.warning) + (*(client.warning))(client_data, fmt_error(s, t)); + else + error(s, t); +} + +static int unget_buffer[5], unget_count; + +static int +lex_getc(void) +{ + if (unget_count > 0) + return unget_buffer[--unget_count]; + else + return (*(client.getch))(client_data); +} + +static void +lex_ungetc(int c) +{ + unget_buffer[unget_count++] = c; +} + +static int +follow(int expect, int ifyes, int ifno) /* look ahead for >=, etc. */ +{ + int c = lex_getc(); + + if (c == expect) + return ifyes; + lex_ungetc(c); + return ifno; +} + +static Stream *token_stream = 0; + +static int +yylex(void) +{ + int c; + + reset_stream(token_stream); + +start_over: + + do { + c = lex_getc(); + if (c == '\n') lineno++; + } while (isspace(c)); + + if (c == '/') { + c = lex_getc(); + if (c == '*') { + for (;;) { + c = lex_getc(); + if (c == '*') { + c = lex_getc(); + if (c == '/') + goto start_over; + } + if (c == EOF) { + yyerror("End of program while in a comment"); + return c; + } + } + } else { + lex_ungetc(c); + return '/'; + } + } + + if (c == '#') { + int negative = 0; + Objid oid = 0; + + c = lex_getc(); + if (c == '-') { + negative = 1; + c = lex_getc(); + } + if (!isdigit(c)) { + yyerror("Malformed object number"); + lex_ungetc(c); + return 0; + } + do { + oid = oid * 10 + (c - '0'); + c = lex_getc(); + } while (isdigit(c)); + lex_ungetc(c); + + yylval.object = negative ? -oid : oid; + return tOBJECT; + } + + if (isdigit(c) || (c == '.' && language_version >= DBV_Float)) { + int n = 0; + int type = tINTEGER; + + while (isdigit(c)) { + n = n * 10 + (c - '0'); + stream_add_char(token_stream, c); + c = lex_getc(); + } + + if (language_version >= DBV_Float && c == '.') { + /* maybe floating-point (but maybe `..') */ + int cc; + + lex_ungetc(cc = lex_getc()); /* peek ahead */ + if (isdigit(cc)) { /* definitely floating-point */ + type = tFLOAT; + do { + stream_add_char(token_stream, c); + c = lex_getc(); + } while (isdigit(c)); + } else if (stream_length(token_stream) == 0) + /* no digits before or after `.'; not a number at all */ + goto normal_dot; + else if (cc != '.') { + /* Some digits before dot, not `..' */ + type = tFLOAT; + stream_add_char(token_stream, c); + c = lex_getc(); + } + } + + if (language_version >= DBV_Float && (c == 'e' || c == 'E')) { + /* better be an exponent */ + type = tFLOAT; + stream_add_char(token_stream, c); + c = lex_getc(); + if (c == '+' || c == '-') { + stream_add_char(token_stream, c); + c = lex_getc(); + } + if (!isdigit(c)) { + yyerror("Malformed floating-point literal"); + lex_ungetc(c); + return 0; + } + do { + stream_add_char(token_stream, c); + c = lex_getc(); + } while (isdigit(c)); + } + + lex_ungetc(c); + + if (type == tINTEGER) + yylval.integer = n; + else { + double d; + + d = strtod(reset_stream(token_stream), 0); + if (!IS_REAL(d)) { + yyerror("Floating-point literal out of range"); + d = 0.0; + } + yylval.real = alloc_float(d); + } + return type; + } + + if (isalpha(c) || c == '_') { + char *buf; + Keyword *k; + + stream_add_char(token_stream, c); + while (isalnum(c = lex_getc()) || c == '_') + stream_add_char(token_stream, c); + lex_ungetc(c); + buf = reset_stream(token_stream); + + k = find_keyword(buf); + if (k) { + if (k->version <= language_version) { + int t = k->token; + + if (t == tERROR) + yylval.error = k->error; + return t; + } else { /* New keyword being used as an identifier */ + if (!must_rename_keywords) + warning("Renaming old use of new keyword: ", buf); + must_rename_keywords = 1; + } + } + + yylval.string = alloc_string(buf); + return tID; + } + + if (c == '"') { + while(1) { + c = lex_getc(); + if (c == '"') + break; + if (c == '\\') + c = lex_getc(); + if (c == '\n' || c == EOF) { + yyerror("Missing quote"); + break; + } + stream_add_char(token_stream, c); + } + yylval.string = alloc_string(reset_stream(token_stream)); + return tSTRING; + } + + switch(c) { + case '>': return follow('=', tGE, '>'); + case '<': return follow('=', tLE, '<'); + case '=': return ((c = follow('=', tEQ, 0)) + ? c + : follow('>', tARROW, '=')); + case '!': return follow('=', tNE, '!'); + case '|': return follow('|', tOR, '|'); + case '&': return follow('&', tAND, '&'); + normal_dot: + case '.': return follow('.', tTO, '.'); + default: return c; + } +} + +static Scatter * +add_scatter_item(Scatter *first, Scatter *last) +{ + Scatter *tmp = first; + + while (tmp->next) + tmp = tmp->next; + tmp->next = last; + + return first; +} + +static Scatter * +scatter_from_arglist(Arg_List *a) +{ + Scatter *sc = 0, **scp; + Arg_List *anext; + + for (scp = ≻ a; a = anext, scp = &((*scp)->next)) { + if (a->expr->kind == EXPR_ID) { + *scp = alloc_scatter(a->kind == ARG_NORMAL ? SCAT_REQUIRED + : SCAT_REST, + a->expr->e.id, 0); + anext = a->next; + dealloc_node(a->expr); + dealloc_node(a); + } else { + yyerror("Scattering assignment targets must be simple variables."); + return 0; + } + } + + return sc; +} + +static void +vet_scatter(Scatter *sc) +{ + int seen_rest = 0, count = 0; + + for (; sc; sc = sc->next) { + if (sc->kind == SCAT_REST) { + if (seen_rest) + yyerror("More than one `@' target in scattering assignment."); + else + seen_rest = 1; + } + count++; + } + + if (count > 255) + yyerror("Too many targets in scattering assignment."); +} + +struct loop_entry { + struct loop_entry *next; + const char *name; + int is_barrier; +}; + +static struct loop_entry *loop_stack; + +static void +push_loop_name(const char *name) +{ + struct loop_entry *entry = mymalloc(sizeof(struct loop_entry), M_AST); + + entry->next = loop_stack; + entry->name = (name ? str_dup(name) : 0); + entry->is_barrier = 0; + loop_stack = entry; +} + +static void +pop_loop_name(void) +{ + if (loop_stack && loop_stack->is_barrier) { + struct loop_entry *entry = loop_stack; + + loop_stack = loop_stack->next; + if (entry->name) + free_str(entry->name); + myfree(entry, M_AST); + } +} + +static void +suspend_loop_scope(void) +{ + struct loop_entry *entry = mymalloc(sizeof(struct loop_entry), M_AST); + + entry->next = loop_stack; + entry->name = 0; + entry->is_barrier = 1; + loop_stack = entry; +} + +static void +resume_loop_scope(void) +{ + if (loop_stack && loop_stack->is_barrier){ + struct loop_entry *entry = loop_stack; + + loop_stack = loop_stack->next; + myfree(entry, M_AST); + } +} + +static void +check_loop_name(const char *name, enum loop_exit_kind kind) +{ + struct loop_entry *entry; + + if (!name) { + if (!loop_stack || loop_stack->is_barrier) { + if (kind == LOOP_BREAK) + yyerror("No enclosing loop for `break' statement"); + else + yyerror("No enclosing loop for `continue' statement"); + } + return; + } + + for (entry = loop_stack; entry && !entry->is_barrier; entry = entry->next) + if (entry->name && mystrcasecmp(entry->name, name) == 0) + return; + + if (kind == LOOP_BREAK) + error("Invalid loop name in `break' statement: ", name); + else + error("Invalid loop name in `continue' statement: ", name); +} + +void +parse_program(DB_Version version, Parser_Client c, void *data) +{ + extern int yyparse(); + + if (token_stream == 0) + token_stream = new_stream(1024); + unget_count = 0; + nerrors = 0; + must_rename_keywords = 0; + lineno = 1; + client = c; + client_data = data; + local_names = new_builtin_names(version); + dollars_ok = 0; + loop_stack = 0; + language_version = version; + + begin_code_allocation(); + yyparse(); + end_code_allocation(nerrors > 0); + if (loop_stack) { + while (loop_stack) { + struct loop_entry *entry = loop_stack; + + loop_stack = loop_stack->next; + if (entry->name) + free_str(entry->name); + myfree(entry, M_AST); + } + } +} + +struct parser_state { + Var code; /* a list of strings */ + int cur_string; /* which string? */ + int cur_char; /* which character in that string? */ + Var errors; /* a list of strings */ +}; + +static void +my_error(void *data, const char *msg) +{ + struct parser_state *state = (struct parser_state *) data; + Var v; + + v.type = TYPE_STR; + v.v.str = str_dup(msg); + state->errors = listappend(state->errors, v); +} + +static int +my_getc(void *data) +{ + struct parser_state *state = (struct parser_state *) data; + Var code; + unsigned char c; + + code = state->code; + if (state->cur_string > code.v.list[0].v.num) + return EOF; + else if (!(c = code.v.list[state->cur_string].v.str[state->cur_char])) { + state->cur_string++; + state->cur_char = 0; + return '\n'; + } else { + state->cur_char++; + return c; + } +} + +static Parser_Client list_parser_client = { my_error, 0, my_getc }; + +void +parse_list_as_program(Var code, Var *errors) +{ + struct parser_state state; + state.code = code; + state.cur_string = 1; + state.cur_char = 0; + state.errors = new_list(0); + parse_program(current_version, list_parser_client, &state); + *errors = state.errors; +} + +char rcsid_parser[] = "$Id: parser.y,v 1.1.1.1 2004/02/26 13:13:58 jesse Exp $"; + +/* + * $Log: parser.y,v $ + * Revision 1.1.1.1 2004/02/26 13:13:58 jesse + * Initial import into CVS + * + * Revision 1.8.1fa 2004/01/02 + * my_getc, changed char c to unsigned; + * + * Revision 1.2 1998/12/14 13:18:45 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.1.1.1 1997/03/03 03:45:02 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.11 1996/05/12 21:28:37 pavel + * Removed non-backward-compatible parse error for negating a non-numeric + * literal. Made certain aspects of floating-point literal parsing be + * language-version-dependent, to maintain backward compatibility with DBs + * written by pre-float servers. Release 1.8.0p5. + * + * Revision 2.10 1996/04/19 01:26:38 pavel + * Fixed potential memory smash when `$' expression occurs in an illegal + * context. Release 1.8.0p4. + * + * Revision 2.9 1996/03/10 01:08:01 pavel + * Removed bogus `call_function("foo", ...)' --> `foo(...)' conversion. + * Fixed line numbers of renamed-variable warnings. Release 1.8.0. + * + * Revision 2.8 1996/02/18 23:14:54 pavel + * Liberalized parsing of floating-point numbers to accept `3.' and `3.e1'. + * Changed parsing to replace call_function("foo", @args) with foo(@args) if + * foo is a known function. Release 1.8.0beta3. + * + * Revision 2.7 1996/02/11 00:46:01 pavel + * Liberalized parsing of floating-point literals to accept `.02' and the + * like. Fixed a bug where `1E6' and the like would be parsed as an integer. + * Release 1.8.0beta2. + * + * Revision 2.6 1996/02/08 06:32:48 pavel + * Added support for floating-point literals, exponentiation expression, named + * WHILE loops, and BREAK and CONTINUE statements. Generalized support for + * version-dependent compilation. Renamed TYPE_NUM to TYPE_INT. Removed use + * of ungetch() method on Parser_Client. Updated copyright notice for 1996. + * Release 1.8.0beta1. + * + * Revision 2.5 1996/01/16 07:17:05 pavel + * Add support for scattering assignment. Release 1.8.0alpha6. + * + * Revision 2.4 1996/01/11 07:50:49 pavel + * Added missing #include "my-string.h". Release 1.8.0alpha5. + * + * Revision 2.3 1995/12/31 00:09:40 pavel + * Removed unused tokens tRAISE and tFORLIST (huh?). Added `$' expression. + * Release 1.8.0alpha4. + * + * Revision 2.2 1995/12/28 00:43:25 pavel + * Added some support for MOO-compilation warnings. Changed `unknown built-in + * function' error into a warning with recovery. Changed identifier-renaming + * log message into a warning. Release 1.8.0alpha3. + * + * Revision 2.1 1995/12/11 08:01:26 pavel + * Added support for `$foo(...)' syntax. Release 1.8.0alpha2. + * + * Revision 2.0 1995/11/30 04:48:11 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.13 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.12 1992/10/23 22:21:43 pavel + * Eliminated all uses of the useless macro NULL. + * + * Revision 1.11 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.10 1992/08/31 22:25:51 pjames + * Changed some `char *'s to `const char *' + * + * Revision 1.9 1992/08/28 23:18:38 pjames + * Added ASGN_RANGE parsing code. Fixed tiny memory leak. + * + * Revision 1.8 1992/08/28 16:16:52 pjames + * Changed `ak_dealloc_string()' to `free_str()'. + * + * Revision 1.7 1992/08/12 01:49:58 pjames + * Negative literals are now accepted (instead of negated positive literals). + * + * Revision 1.6 1992/08/10 16:55:59 pjames + * Updated #includes. + * + * Revision 1.5 1992/07/30 21:22:08 pjames + * Removed max_stack calculations (moved to vector.c). + * + * Revision 1.4 1992/07/29 18:05:12 pjames + * $$ no longer = NULL when there is an illegal left hand side of an + * expression. + * + * Revision 1.3 1992/07/27 18:12:41 pjames + * Changed name of ct_env to var_names and const_env to literals. + * Modified call to vectorize to use new argument format. + * Assignment statements now check left hand side properly for allowable + * expressions, and now frees memory from reused expressions. + * + * Revision 1.2 1992/07/21 00:05:16 pavel + * Added rcsid_ declaration to hold the RCS ident. string. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ + diff --git a/gnoemoe/parser/parser.h b/gnoemoe/parser/parser.h new file mode 100644 index 0000000..eb722b0 --- /dev/null +++ b/gnoemoe/parser/parser.h @@ -0,0 +1,131 @@ +/* A Bison parser, made by GNU Bison 2.0. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + tINTEGER = 258, + tOBJECT = 259, + tFLOAT = 260, + tSTRING = 261, + tID = 262, + tERROR = 263, + tIF = 264, + tELSE = 265, + tELSEIF = 266, + tENDIF = 267, + tFOR = 268, + tIN = 269, + tENDFOR = 270, + tRETURN = 271, + tFORK = 272, + tENDFORK = 273, + tWHILE = 274, + tENDWHILE = 275, + tTRY = 276, + tENDTRY = 277, + tEXCEPT = 278, + tFINALLY = 279, + tANY = 280, + tBREAK = 281, + tCONTINUE = 282, + tTO = 283, + tARROW = 284, + tAND = 285, + tOR = 286, + tGE = 287, + tLE = 288, + tNE = 289, + tEQ = 290, + tUNARYMINUS = 291 + }; +#endif +#define tINTEGER 258 +#define tOBJECT 259 +#define tFLOAT 260 +#define tSTRING 261 +#define tID 262 +#define tERROR 263 +#define tIF 264 +#define tELSE 265 +#define tELSEIF 266 +#define tENDIF 267 +#define tFOR 268 +#define tIN 269 +#define tENDFOR 270 +#define tRETURN 271 +#define tFORK 272 +#define tENDFORK 273 +#define tWHILE 274 +#define tENDWHILE 275 +#define tTRY 276 +#define tENDTRY 277 +#define tEXCEPT 278 +#define tFINALLY 279 +#define tANY 280 +#define tBREAK 281 +#define tCONTINUE 282 +#define tTO 283 +#define tARROW 284 +#define tAND 285 +#define tOR 286 +#define tGE 287 +#define tLE 288 +#define tNE 289 +#define tEQ 290 +#define tUNARYMINUS 291 + + + + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 68 "parser.y" +typedef union YYSTYPE { + Stmt *stmt; + Expr *expr; + int integer; + Objid object; + double *real; + char *string; + enum error error; + Arg_List *args; + Cond_Arm *arm; + Except_Arm *except; + Scatter *scatter; +} YYSTYPE; +/* Line 1318 of yacc.c. */ +#line 123 "parser.h" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +extern YYSTYPE yylval; + + + diff --git a/gnoemoe/parser/parser.y b/gnoemoe/parser/parser.y new file mode 100644 index 0000000..b431dc0 --- /dev/null +++ b/gnoemoe/parser/parser.y @@ -0,0 +1,1282 @@ +%{ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +/*************************************************************************/ +/* NOTE: If you add an #include here, make sure you properly update the */ +/* parser.o dependency line in the Makefile. */ +/*************************************************************************/ + +#include +#include +#include +#include + +#include "ast.h" +#include "config.h" +#include "functions.h" +#include "keywords.h" +#include "list.h" +//#include "numbers.h" +//#include "opcode.h" +#include "parser.h" +#include "parsen.h" +//#include "program.h" +#include "storage.h" +#include "streams.h" +#include "structures.h" +//#include "sym_table.h" +#include "utils.h" +#include "version.h" + +static Stmt *prog_start; +static int dollars_ok; +static DB_Version language_version; + +static void error(const char *, const char *); +static void warning(const char *, const char *); +static int find_id(char *name); +static void yyerror(const char *s); +static int yylex(void); +static Scatter *scatter_from_arglist(Arg_List *); +static Scatter *add_scatter_item(Scatter *, Scatter *); +static void vet_scatter(Scatter *); +static void push_loop_name(const char *); +static void pop_loop_name(void); +static void suspend_loop_scope(void); +static void resume_loop_scope(void); + +enum loop_exit_kind { LOOP_BREAK, LOOP_CONTINUE }; + +static void check_loop_name(const char *, enum loop_exit_kind); +%} + +%union { + Stmt *stmt; + Expr *expr; + int integer; + Objid object; + double *real; + char *string; + enum error error; + Arg_List *args; + Cond_Arm *arm; + Except_Arm *except; + Scatter *scatter; +} + +%type statements statement elsepart +%type elseifs +%type expr default +%type arglist ne_arglist codes +%type except excepts +%type opt_id +%type scatter scatter_item + +%token tINTEGER +%token tOBJECT +%token tFLOAT +%token tSTRING tID +%token tERROR +%token tIF tELSE tELSEIF tENDIF tFOR tIN tENDFOR tRETURN tFORK tENDFORK +%token tWHILE tENDWHILE tTRY tENDTRY tEXCEPT tFINALLY tANY tBREAK tCONTINUE + +%token tTO tARROW + +%right '=' +%nonassoc '?' '|' +%left tOR tAND +%left tEQ tNE '<' tLE '>' tGE tIN +%left '+' '-' +%left '*' '/' '%' +%right '^' +%left '!' tUNARYMINUS +%nonassoc '.' ':' '[' '$' + +%% + +program: statements + { prog_start = $1; } + ; + +statements: + /* NOTHING */ + { $$ = 0; } + | statements statement + { + if ($1) { + Stmt *tmp = $1; + + while (tmp->next) + tmp = tmp->next; + tmp->next = $2; + $$ = $1; + } else + $$ = $2; + } + ; + +statement: + tIF '(' expr ')' statements elseifs elsepart tENDIF + { + + $$ = alloc_stmt(STMT_COND); + $$->s.cond.arms = alloc_cond_arm($3, $5); + $$->s.cond.arms->next = $6; + $$->s.cond.otherwise = $7; + } + | tFOR tID tIN '(' expr ')' + { + push_loop_name($2); + } + statements tENDFOR + { + $$ = alloc_stmt(STMT_LIST); + $$->s.list.id = find_id($2); + $$->s.list.expr = $5; + $$->s.list.body = $8; + pop_loop_name(); + } + | tFOR tID tIN '[' expr tTO expr ']' + { + push_loop_name($2); + } + statements tENDFOR + { + $$ = alloc_stmt(STMT_RANGE); + $$->s.range.id = find_id($2); + $$->s.range.from = $5; + $$->s.range.to = $7; + $$->s.range.body = $10; + pop_loop_name(); + } + | tWHILE '(' expr ')' + { + push_loop_name(0); + } + statements tENDWHILE + { + $$ = alloc_stmt(STMT_WHILE); + $$->s.loop.id = -1; + $$->s.loop.condition = $3; + $$->s.loop.body = $6; + pop_loop_name(); + } + | tWHILE tID '(' expr ')' + { + push_loop_name($2); + } + statements tENDWHILE + { + $$ = alloc_stmt(STMT_WHILE); + $$->s.loop.id = find_id($2); + $$->s.loop.condition = $4; + $$->s.loop.body = $7; + pop_loop_name(); + } + | tFORK '(' expr ')' + { + suspend_loop_scope(); + } + statements tENDFORK + { + $$ = alloc_stmt(STMT_FORK); + $$->s.fork.id = -1; + $$->s.fork.time = $3; + $$->s.fork.body = $6; + resume_loop_scope(); + } + | tFORK tID '(' expr ')' + { + suspend_loop_scope(); + } + statements tENDFORK + { + $$ = alloc_stmt(STMT_FORK); + $$->s.fork.id = find_id($2); + $$->s.fork.time = $4; + $$->s.fork.body = $7; + resume_loop_scope(); + } + | expr ';' + { + $$ = alloc_stmt(STMT_EXPR); + $$->s.expr = $1; + } + | tBREAK ';' + { + check_loop_name(0, LOOP_BREAK); + $$ = alloc_stmt(STMT_BREAK); + $$->s.exit = -1; + } + | tBREAK tID ';' + { + check_loop_name($2, LOOP_BREAK); + $$ = alloc_stmt(STMT_BREAK); + $$->s.exit = find_id($2); + } + | tCONTINUE ';' + { + check_loop_name(0, LOOP_CONTINUE); + $$ = alloc_stmt(STMT_CONTINUE); + $$->s.exit = -1; + } + | tCONTINUE tID ';' + { + check_loop_name($2, LOOP_CONTINUE); + $$ = alloc_stmt(STMT_CONTINUE); + $$->s.exit = find_id($2); + } + | tRETURN expr ';' + { + $$ = alloc_stmt(STMT_RETURN); + $$->s.expr = $2; + } + | tRETURN ';' + { + $$ = alloc_stmt(STMT_RETURN); + $$->s.expr = 0; + } + | ';' + { $$ = 0; } + | tTRY statements excepts tENDTRY + { + $$ = alloc_stmt(STMT_TRY_EXCEPT); + $$->s.catch.body = $2; + $$->s.catch.excepts = $3; + } + | tTRY statements tFINALLY statements tENDTRY + { + $$ = alloc_stmt(STMT_TRY_FINALLY); + $$->s.finally.body = $2; + $$->s.finally.handler = $4; + } + ; + +elseifs: + /* NOTHING */ + { $$ = 0; } + | elseifs tELSEIF '(' expr ')' statements + { + Cond_Arm *this_arm = alloc_cond_arm($4, $6); + + if ($1) { + Cond_Arm *tmp = $1; + + while (tmp->next) + tmp = tmp->next; + tmp->next = this_arm; + $$ = $1; + } else + $$ = this_arm; + } + ; + +elsepart: + /* NOTHING */ + { $$ = 0; } + | tELSE statements + { $$ = $2; } + ; + +excepts: + tEXCEPT except + { $$ = $2; } + | excepts tEXCEPT + { + Except_Arm *tmp = $1; + int count = 1; + + while (tmp->next) { + tmp = tmp->next; + count++; + } + if (!tmp->codes) + yyerror("Unreachable EXCEPT clause"); + else if (count > 255) + yyerror("Too many EXCEPT clauses (max. 255)"); + } + except + { + Except_Arm *tmp = $1; + + while (tmp->next) + tmp = tmp->next; + + tmp->next = $4; + $$ = $1; + } + ; +except: + opt_id '(' codes ')' statements + { $$ = alloc_except($1 ? find_id($1) : -1, $3, $5); } + ; + +opt_id: + /* NOTHING */ + { $$ = 0; } + | tID + { $$ = $1; } + ; + +expr: + tINTEGER + { + $$ = alloc_var(TYPE_INT); + $$->e.var.v.num = $1; + } + | tFLOAT + { + $$ = alloc_var(TYPE_FLOAT); + $$->e.var.v.fnum = $1; + } + | tSTRING + { + $$ = alloc_var(TYPE_STR); + $$->e.var.v.str = $1; + } + | tOBJECT + { + $$ = alloc_var(TYPE_OBJ); + $$->e.var.v.obj = $1; + } + | tERROR + { + $$ = alloc_var(TYPE_ERR); + $$->e.var.v.err = $1; + } + | tID + { + $$ = alloc_expr(EXPR_ID); + $$->e.id = find_id($1); + } + | '$' tID + { + /* Treat $foo like #0.("foo") */ + Expr *obj = alloc_var(TYPE_OBJ); + Expr *prop = alloc_var(TYPE_STR); + obj->e.var.v.obj = 0; + prop->e.var.v.str = $2; + $$ = alloc_binary(EXPR_PROP, obj, prop); + } + | expr '.' tID + { + /* Treat foo.bar like foo.("bar") for simplicity */ + Expr *prop = alloc_var(TYPE_STR); + prop->e.var.v.str = $3; + $$ = alloc_binary(EXPR_PROP, $1, prop); + } + | expr '.' '(' expr ')' + { + $$ = alloc_binary(EXPR_PROP, $1, $4); + } + | expr ':' tID '(' arglist ')' + { + /* treat foo:bar(args) like foo:("bar")(args) */ + Expr *verb = alloc_var(TYPE_STR); + verb->e.var.v.str = $3; + $$ = alloc_verb($1, verb, $5); + } + | '$' tID '(' arglist ')' + { + /* treat $bar(args) like #0:("bar")(args) */ + Expr *obj = alloc_var(TYPE_OBJ); + Expr *verb = alloc_var(TYPE_STR); + obj->e.var.v.obj = 0; + verb->e.var.v.str = $2; + $$ = alloc_verb(obj, verb, $4); + } + | expr ':' '(' expr ')' '(' arglist ')' + { + $$ = alloc_verb($1, $4, $7); + } + | expr '[' dollars_up expr ']' + { + dollars_ok--; + $$ = alloc_binary(EXPR_INDEX, $1, $4); + } + | expr '[' dollars_up expr tTO expr ']' + { + dollars_ok--; + $$ = alloc_expr(EXPR_RANGE); + $$->e.range.base = $1; + $$->e.range.from = $4; + $$->e.range.to = $6; + } + | '$' + { + if (!dollars_ok) + yyerror("Illegal context for `$' expression."); + $$ = alloc_expr(EXPR_LENGTH); + } + | expr '=' expr + { + Expr *e = $1; + + if (e->kind == EXPR_LIST) { + e->kind = EXPR_SCATTER; + if (e->e.list) { + e->e.scatter = scatter_from_arglist(e->e.list); + vet_scatter(e->e.scatter); + } else + yyerror("Empty list in scattering assignment."); + } else { + if (e->kind == EXPR_RANGE) + e = e->e.range.base; + while (e->kind == EXPR_INDEX) + e = e->e.bin.lhs; + if (e->kind != EXPR_ID && e->kind != EXPR_PROP) + yyerror("Illegal expression on left side of" + " assignment."); + } + $$ = alloc_binary(EXPR_ASGN, $1, $3); + } + | '{' scatter '}' '=' expr + { + Expr *e = alloc_expr(EXPR_SCATTER); + + e->e.scatter = $2; + vet_scatter($2); + $$ = alloc_binary(EXPR_ASGN, e, $5); + } + | tID '(' arglist ')' + { + unsigned f_no; + + $$ = alloc_expr(EXPR_CALL); + if ((f_no = number_func_by_name($1)) == FUNC_NOT_FOUND) { + /* Replace with call_function("$1", @args) */ + Expr *fname = alloc_var(TYPE_STR); + Arg_List *a = alloc_arg_list(ARG_NORMAL, fname); + + fname->e.var.v.str = $1; + a->next = $3; + warning("Unknown built-in function: ", $1); + $$->e.call.func = number_func_by_name("call_function"); + $$->e.call.args = a; + } else { + $$->e.call.func = f_no; + $$->e.call.args = $3; + dealloc_string($1); + } + } + | expr '+' expr + { + $$ = alloc_binary(EXPR_PLUS, $1, $3); + } + | expr '-' expr + { + $$ = alloc_binary(EXPR_MINUS, $1, $3); + } + | expr '*' expr + { + $$ = alloc_binary(EXPR_TIMES, $1, $3); + } + | expr '/' expr + { + $$ = alloc_binary(EXPR_DIVIDE, $1, $3); + } + | expr '%' expr + { + $$ = alloc_binary(EXPR_MOD, $1, $3); + } + | expr '^' expr + { + $$ = alloc_binary(EXPR_EXP, $1, $3); + } + | expr tAND expr + { + $$ = alloc_binary(EXPR_AND, $1, $3); + } + | expr tOR expr + { + $$ = alloc_binary(EXPR_OR, $1, $3); + } + | expr tEQ expr + { + $$ = alloc_binary(EXPR_EQ, $1, $3); + } + | expr tNE expr + { + $$ = alloc_binary(EXPR_NE, $1, $3); + } + | expr '<' expr + { + $$ = alloc_binary(EXPR_LT, $1, $3); + } + | expr tLE expr + { + $$ = alloc_binary(EXPR_LE, $1, $3); + } + | expr '>' expr + { + $$ = alloc_binary(EXPR_GT, $1, $3); + } + | expr tGE expr + { + $$ = alloc_binary(EXPR_GE, $1, $3); + } + | expr tIN expr + { + $$ = alloc_binary(EXPR_IN, $1, $3); + } + | '-' expr %prec tUNARYMINUS + { + if ($2->kind == EXPR_VAR + && ($2->e.var.type == TYPE_INT + || $2->e.var.type == TYPE_FLOAT)) { + switch ($2->e.var.type) { + case TYPE_INT: + $2->e.var.v.num = -$2->e.var.v.num; + break; + case TYPE_FLOAT: + *($2->e.var.v.fnum) = - (*($2->e.var.v.fnum)); + break; + default: + break; + } + $$ = $2; + } else { + $$ = alloc_expr(EXPR_NEGATE); + $$->e.expr = $2; + } + } + | '!' expr + { + $$ = alloc_expr(EXPR_NOT); + $$->e.expr = $2; + } + | '(' expr ')' + { $$ = $2; } + | '{' arglist '}' + { + $$ = alloc_expr(EXPR_LIST); + $$->e.list = $2; + } + | expr '?' expr '|' expr + { + $$ = alloc_expr(EXPR_COND); + $$->e.cond.condition = $1; + $$->e.cond.consequent = $3; + $$->e.cond.alternate = $5; + } + | '`' expr '!' codes default '\'' + { + $$ = alloc_expr(EXPR_CATCH); + $$->e.catch.try = $2; + $$->e.catch.codes = $4; + $$->e.catch.except = $5; + } + ; + +dollars_up: + /* NOTHING */ + { dollars_ok++; } + ; +codes: + tANY + { $$ = 0; } + | ne_arglist + { $$ = $1; } + ; +default: + /* NOTHING */ + { $$ = 0; } + | tARROW expr + { $$ = $2; } + ; +arglist: + /* NOTHING */ + { $$ = 0; } + | ne_arglist + { $$ = $1; } + ; + +ne_arglist: + expr + { $$ = alloc_arg_list(ARG_NORMAL, $1); } + | '@' expr + { $$ = alloc_arg_list(ARG_SPLICE, $2); } + | ne_arglist ',' expr + { + Arg_List *this_arg = alloc_arg_list(ARG_NORMAL, $3); + + if ($1) { + Arg_List *tmp = $1; + + while (tmp->next) + tmp = tmp->next; + tmp->next = this_arg; + $$ = $1; + } else + $$ = this_arg; + } + | ne_arglist ',' '@' expr + { + Arg_List *this_arg = alloc_arg_list(ARG_SPLICE, $4); + + if ($1) { + Arg_List *tmp = $1; + + while (tmp->next) + tmp = tmp->next; + tmp->next = this_arg; + $$ = $1; + } else + $$ = this_arg; + } + ; + +scatter: + ne_arglist ',' scatter_item + { + Scatter *sc = scatter_from_arglist($1); + + if (sc) + $$ = add_scatter_item(sc, $3); + else + $$ = $3; + } + | scatter ',' scatter_item + { + $$ = add_scatter_item($1, $3); + } + | scatter ',' tID + { + $$ = add_scatter_item($1, alloc_scatter(SCAT_REQUIRED, + find_id($3), 0)); + } + | scatter ',' '@' tID + { + $$ = add_scatter_item($1, alloc_scatter(SCAT_REST, + find_id($4), 0)); + } + | scatter_item + { $$ = $1; } + ; + +scatter_item: + '?' tID + { + $$ = alloc_scatter(SCAT_OPTIONAL, find_id($2), 0); + } + | '?' tID '=' expr + { + $$ = alloc_scatter(SCAT_OPTIONAL, find_id($2), $4); + } + ; + +%% + +static int lineno, nerrors, must_rename_keywords; +static Parser_Client client; +static void *client_data; +static Names *local_names; + +static int +find_id(char *name) +{ + int slot = find_or_add_name(&local_names, name); + + dealloc_string(name); + return slot; +} + +static void +yyerror(const char *s) +{ + error(s, 0); +} + +static const char * +fmt_error(const char *s, const char *t) +{ + static Stream *str = 0; + + if (str == 0) + str = new_stream(100); + if (t) + stream_printf(str, "Line %d: %s%s", lineno, s, t); + else + stream_printf(str, "Line %d: %s", lineno, s); + return reset_stream(str); +} + +static void +error(const char *s, const char *t) +{ + nerrors++; + (*(client.error))(client_data, fmt_error(s, t)); +} + +static void +warning(const char *s, const char *t) +{ + if (client.warning) + (*(client.warning))(client_data, fmt_error(s, t)); + else + error(s, t); +} + +static int unget_buffer[5], unget_count; + +static int +lex_getc(void) +{ + if (unget_count > 0) + return unget_buffer[--unget_count]; + else + return (*(client.getch))(client_data); +} + +static void +lex_ungetc(int c) +{ + unget_buffer[unget_count++] = c; +} + +static int +follow(int expect, int ifyes, int ifno) /* look ahead for >=, etc. */ +{ + int c = lex_getc(); + + if (c == expect) + return ifyes; + lex_ungetc(c); + return ifno; +} + +static Stream *token_stream = 0; + +static int +yylex(void) +{ + int c; + + reset_stream(token_stream); + +start_over: + + do { + c = lex_getc(); + if (c == '\n') lineno++; + } while (isspace(c)); + + if (c == '/') { + c = lex_getc(); + if (c == '*') { + for (;;) { + c = lex_getc(); + if (c == '*') { + c = lex_getc(); + if (c == '/') + goto start_over; + } + if (c == EOF) { + yyerror("End of program while in a comment"); + return c; + } + } + } else { + lex_ungetc(c); + return '/'; + } + } + + if (c == '#') { + int negative = 0; + Objid oid = 0; + + c = lex_getc(); + if (c == '-') { + negative = 1; + c = lex_getc(); + } + if (!isdigit(c)) { + yyerror("Malformed object number"); + lex_ungetc(c); + return 0; + } + do { + oid = oid * 10 + (c - '0'); + c = lex_getc(); + } while (isdigit(c)); + lex_ungetc(c); + + yylval.object = negative ? -oid : oid; + return tOBJECT; + } + + if (isdigit(c) || (c == '.' && language_version >= DBV_Float)) { + int n = 0; + int type = tINTEGER; + + while (isdigit(c)) { + n = n * 10 + (c - '0'); + stream_add_char(token_stream, c); + c = lex_getc(); + } + + if (language_version >= DBV_Float && c == '.') { + /* maybe floating-point (but maybe `..') */ + int cc; + + lex_ungetc(cc = lex_getc()); /* peek ahead */ + if (isdigit(cc)) { /* definitely floating-point */ + type = tFLOAT; + do { + stream_add_char(token_stream, c); + c = lex_getc(); + } while (isdigit(c)); + } else if (stream_length(token_stream) == 0) + /* no digits before or after `.'; not a number at all */ + goto normal_dot; + else if (cc != '.') { + /* Some digits before dot, not `..' */ + type = tFLOAT; + stream_add_char(token_stream, c); + c = lex_getc(); + } + } + + if (language_version >= DBV_Float && (c == 'e' || c == 'E')) { + /* better be an exponent */ + type = tFLOAT; + stream_add_char(token_stream, c); + c = lex_getc(); + if (c == '+' || c == '-') { + stream_add_char(token_stream, c); + c = lex_getc(); + } + if (!isdigit(c)) { + yyerror("Malformed floating-point literal"); + lex_ungetc(c); + return 0; + } + do { + stream_add_char(token_stream, c); + c = lex_getc(); + } while (isdigit(c)); + } + + lex_ungetc(c); + + if (type == tINTEGER) + yylval.integer = n; + else { + double d; + + d = strtod(reset_stream(token_stream), 0); + if (!IS_REAL(d)) { + yyerror("Floating-point literal out of range"); + d = 0.0; + } + yylval.real = alloc_float(d); + } + return type; + } + + if (isalpha(c) || c == '_') { + char *buf; + Keyword *k; + + stream_add_char(token_stream, c); + while (isalnum(c = lex_getc()) || c == '_') + stream_add_char(token_stream, c); + lex_ungetc(c); + buf = reset_stream(token_stream); + + k = find_keyword(buf); + if (k) { + if (k->version <= language_version) { + int t = k->token; + + if (t == tERROR) + yylval.error = k->error; + return t; + } else { /* New keyword being used as an identifier */ + if (!must_rename_keywords) + warning("Renaming old use of new keyword: ", buf); + must_rename_keywords = 1; + } + } + + yylval.string = alloc_string(buf); + return tID; + } + + if (c == '"') { + while(1) { + c = lex_getc(); + if (c == '"') + break; + if (c == '\\') + c = lex_getc(); + if (c == '\n' || c == EOF) { + yyerror("Missing quote"); + break; + } + stream_add_char(token_stream, c); + } + yylval.string = alloc_string(reset_stream(token_stream)); + return tSTRING; + } + + switch(c) { + case '>': return follow('=', tGE, '>'); + case '<': return follow('=', tLE, '<'); + case '=': return ((c = follow('=', tEQ, 0)) + ? c + : follow('>', tARROW, '=')); + case '!': return follow('=', tNE, '!'); + case '|': return follow('|', tOR, '|'); + case '&': return follow('&', tAND, '&'); + normal_dot: + case '.': return follow('.', tTO, '.'); + default: return c; + } +} + +static Scatter * +add_scatter_item(Scatter *first, Scatter *last) +{ + Scatter *tmp = first; + + while (tmp->next) + tmp = tmp->next; + tmp->next = last; + + return first; +} + +static Scatter * +scatter_from_arglist(Arg_List *a) +{ + Scatter *sc = 0, **scp; + Arg_List *anext; + + for (scp = ≻ a; a = anext, scp = &((*scp)->next)) { + if (a->expr->kind == EXPR_ID) { + *scp = alloc_scatter(a->kind == ARG_NORMAL ? SCAT_REQUIRED + : SCAT_REST, + a->expr->e.id, 0); + anext = a->next; + dealloc_node(a->expr); + dealloc_node(a); + } else { + yyerror("Scattering assignment targets must be simple variables."); + return 0; + } + } + + return sc; +} + +static void +vet_scatter(Scatter *sc) +{ + int seen_rest = 0, count = 0; + + for (; sc; sc = sc->next) { + if (sc->kind == SCAT_REST) { + if (seen_rest) + yyerror("More than one `@' target in scattering assignment."); + else + seen_rest = 1; + } + count++; + } + + if (count > 255) + yyerror("Too many targets in scattering assignment."); +} + +struct loop_entry { + struct loop_entry *next; + const char *name; + int is_barrier; +}; + +static struct loop_entry *loop_stack; + +static void +push_loop_name(const char *name) +{ + struct loop_entry *entry = mymalloc(sizeof(struct loop_entry), M_AST); + + entry->next = loop_stack; + entry->name = (name ? str_dup(name) : 0); + entry->is_barrier = 0; + loop_stack = entry; +} + +static void +pop_loop_name(void) +{ + if (loop_stack && loop_stack->is_barrier) { + struct loop_entry *entry = loop_stack; + + loop_stack = loop_stack->next; + if (entry->name) + free_str(entry->name); + myfree(entry, M_AST); + } +} + +static void +suspend_loop_scope(void) +{ + struct loop_entry *entry = mymalloc(sizeof(struct loop_entry), M_AST); + + entry->next = loop_stack; + entry->name = 0; + entry->is_barrier = 1; + loop_stack = entry; +} + +static void +resume_loop_scope(void) +{ + if (loop_stack && loop_stack->is_barrier){ + struct loop_entry *entry = loop_stack; + + loop_stack = loop_stack->next; + myfree(entry, M_AST); + } +} + +static void +check_loop_name(const char *name, enum loop_exit_kind kind) +{ + struct loop_entry *entry; + + if (!name) { + if (!loop_stack || loop_stack->is_barrier) { + if (kind == LOOP_BREAK) + yyerror("No enclosing loop for `break' statement"); + else + yyerror("No enclosing loop for `continue' statement"); + } + return; + } + + for (entry = loop_stack; entry && !entry->is_barrier; entry = entry->next) + if (entry->name && mystrcasecmp(entry->name, name) == 0) + return; + + if (kind == LOOP_BREAK) + error("Invalid loop name in `break' statement: ", name); + else + error("Invalid loop name in `continue' statement: ", name); +} + +void +parse_program(DB_Version version, Parser_Client c, void *data) +{ + extern int yyparse(); + + if (token_stream == 0) + token_stream = new_stream(1024); + unget_count = 0; + nerrors = 0; + must_rename_keywords = 0; + lineno = 1; + client = c; + client_data = data; + local_names = new_builtin_names(version); + dollars_ok = 0; + loop_stack = 0; + language_version = version; + + begin_code_allocation(); + yyparse(); + end_code_allocation(nerrors > 0); + if (loop_stack) { + while (loop_stack) { + struct loop_entry *entry = loop_stack; + + loop_stack = loop_stack->next; + if (entry->name) + free_str(entry->name); + myfree(entry, M_AST); + } + } +} + +struct parser_state { + Var code; /* a list of strings */ + int cur_string; /* which string? */ + int cur_char; /* which character in that string? */ + Var errors; /* a list of strings */ +}; + +static void +my_error(void *data, const char *msg) +{ + struct parser_state *state = (struct parser_state *) data; + Var v; + + v.type = TYPE_STR; + v.v.str = str_dup(msg); + state->errors = listappend(state->errors, v); +} + +static int +my_getc(void *data) +{ + struct parser_state *state = (struct parser_state *) data; + Var code; + unsigned char c; + + code = state->code; + if (state->cur_string > code.v.list[0].v.num) + return EOF; + else if (!(c = code.v.list[state->cur_string].v.str[state->cur_char])) { + state->cur_string++; + state->cur_char = 0; + return '\n'; + } else { + state->cur_char++; + return c; + } +} + +static Parser_Client list_parser_client = { my_error, 0, my_getc }; + +void +parse_list_as_program(Var code, Var *errors) +{ + struct parser_state state; + state.code = code; + state.cur_string = 1; + state.cur_char = 0; + state.errors = new_list(0); + parse_program(current_version, list_parser_client, &state); + *errors = state.errors; +} + +char rcsid_parser[] = "$Id: parser.y,v 1.1.1.1 2004/02/26 13:13:58 jesse Exp $"; + +/* + * $Log: parser.y,v $ + * Revision 1.1.1.1 2004/02/26 13:13:58 jesse + * Initial import into CVS + * + * Revision 1.8.1fa 2004/01/02 + * my_getc, changed char c to unsigned; + * + * Revision 1.2 1998/12/14 13:18:45 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.1.1.1 1997/03/03 03:45:02 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.11 1996/05/12 21:28:37 pavel + * Removed non-backward-compatible parse error for negating a non-numeric + * literal. Made certain aspects of floating-point literal parsing be + * language-version-dependent, to maintain backward compatibility with DBs + * written by pre-float servers. Release 1.8.0p5. + * + * Revision 2.10 1996/04/19 01:26:38 pavel + * Fixed potential memory smash when `$' expression occurs in an illegal + * context. Release 1.8.0p4. + * + * Revision 2.9 1996/03/10 01:08:01 pavel + * Removed bogus `call_function("foo", ...)' --> `foo(...)' conversion. + * Fixed line numbers of renamed-variable warnings. Release 1.8.0. + * + * Revision 2.8 1996/02/18 23:14:54 pavel + * Liberalized parsing of floating-point numbers to accept `3.' and `3.e1'. + * Changed parsing to replace call_function("foo", @args) with foo(@args) if + * foo is a known function. Release 1.8.0beta3. + * + * Revision 2.7 1996/02/11 00:46:01 pavel + * Liberalized parsing of floating-point literals to accept `.02' and the + * like. Fixed a bug where `1E6' and the like would be parsed as an integer. + * Release 1.8.0beta2. + * + * Revision 2.6 1996/02/08 06:32:48 pavel + * Added support for floating-point literals, exponentiation expression, named + * WHILE loops, and BREAK and CONTINUE statements. Generalized support for + * version-dependent compilation. Renamed TYPE_NUM to TYPE_INT. Removed use + * of ungetch() method on Parser_Client. Updated copyright notice for 1996. + * Release 1.8.0beta1. + * + * Revision 2.5 1996/01/16 07:17:05 pavel + * Add support for scattering assignment. Release 1.8.0alpha6. + * + * Revision 2.4 1996/01/11 07:50:49 pavel + * Added missing #include "my-string.h". Release 1.8.0alpha5. + * + * Revision 2.3 1995/12/31 00:09:40 pavel + * Removed unused tokens tRAISE and tFORLIST (huh?). Added `$' expression. + * Release 1.8.0alpha4. + * + * Revision 2.2 1995/12/28 00:43:25 pavel + * Added some support for MOO-compilation warnings. Changed `unknown built-in + * function' error into a warning with recovery. Changed identifier-renaming + * log message into a warning. Release 1.8.0alpha3. + * + * Revision 2.1 1995/12/11 08:01:26 pavel + * Added support for `$foo(...)' syntax. Release 1.8.0alpha2. + * + * Revision 2.0 1995/11/30 04:48:11 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.13 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.12 1992/10/23 22:21:43 pavel + * Eliminated all uses of the useless macro NULL. + * + * Revision 1.11 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.10 1992/08/31 22:25:51 pjames + * Changed some `char *'s to `const char *' + * + * Revision 1.9 1992/08/28 23:18:38 pjames + * Added ASGN_RANGE parsing code. Fixed tiny memory leak. + * + * Revision 1.8 1992/08/28 16:16:52 pjames + * Changed `ak_dealloc_string()' to `free_str()'. + * + * Revision 1.7 1992/08/12 01:49:58 pjames + * Negative literals are now accepted (instead of negated positive literals). + * + * Revision 1.6 1992/08/10 16:55:59 pjames + * Updated #includes. + * + * Revision 1.5 1992/07/30 21:22:08 pjames + * Removed max_stack calculations (moved to vector.c). + * + * Revision 1.4 1992/07/29 18:05:12 pjames + * $$ no longer = NULL when there is an illegal left hand side of an + * expression. + * + * Revision 1.3 1992/07/27 18:12:41 pjames + * Changed name of ct_env to var_names and const_env to literals. + * Modified call to vectorize to use new argument format. + * Assignment statements now check left hand side properly for allowable + * expressions, and now frees memory from reused expressions. + * + * Revision 1.2 1992/07/21 00:05:16 pavel + * Added rcsid_ declaration to hold the RCS ident. string. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/storage.c b/gnoemoe/parser/storage.c new file mode 100644 index 0000000..6db3a04 --- /dev/null +++ b/gnoemoe/parser/storage.c @@ -0,0 +1,317 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#include +#include + +#include "config.h" +#include "list.h" +#include "storage.h" +#include "structures.h" +#include "utils.h" + +static unsigned alloc_num[Sizeof_Memory_Type]; +#ifdef USE_GNU_MALLOC +static unsigned alloc_size[Sizeof_Memory_Type], alloc_real_size[Sizeof_Memory_Type]; +#endif + +static inline int +refcount_overhead(Memory_Type type) +{ + /* These are the only allocation types that are addref()'d. + * As long as we're living on the wild side, avoid getting the + * refcount slot for allocations that won't need it. + */ + switch (type) { + case M_FLOAT: + /* for systems with picky double alignment */ + return MAX(sizeof(int), sizeof(double)); + case M_STRING: + return sizeof(int); + case M_LIST: + /* for systems with picky pointer alignment */ + return MAX(sizeof(int), sizeof(Var *)); + default: + return 0; + } +} + +void * +mymalloc(unsigned size, Memory_Type type) +{ + char *memptr; + char msg[100]; + int offs; + + if (size == 0) /* For queasy systems */ + size = 1; + + offs = refcount_overhead(type); + memptr = (char *) malloc(size + offs); + if (!memptr) { + sprintf(msg, "memory allocation (size %u) failed!", size); + } + alloc_num[type]++; +#ifdef USE_GNU_MALLOC + { + extern unsigned malloc_real_size(void *ptr); + extern unsigned malloc_size(void *ptr); + + alloc_size[type] += malloc_size(memptr); + alloc_real_size[type] += malloc_real_size(memptr); + } +#endif + + if (offs) { + memptr += offs; + ((int *) memptr)[-1] = 1; + } + return memptr; +} + +const char * +str_ref(const char *s) +{ + addref(s); + return s; +} + +char * +str_dup(const char *s) +{ + char *r; + + if (s == 0 || *s == '\0') { + static char *emptystring; + + if (!emptystring) { + emptystring = (char *) mymalloc(1, M_STRING); + *emptystring = '\0'; + } + addref(emptystring); + return emptystring; + } else { + r = (char *) mymalloc(strlen(s) + 1, M_STRING); + strcpy(r, s); + } + return r; +} + +void * +myrealloc(void *ptr, unsigned size, Memory_Type type) +{ + int offs = refcount_overhead(type); + static char msg[100]; + +#ifdef USE_GNU_MALLOC + { + extern unsigned malloc_real_size(void *ptr); + extern unsigned malloc_size(void *ptr); + + alloc_size[type] -= malloc_size(ptr); + alloc_real_size[type] -= malloc_real_size(ptr); +#endif + + ptr = realloc((char *) ptr - offs, size + offs); + if (!ptr) { + sprintf(msg, "memory re-allocation (size %u) failed!", size); + } + +#ifdef USE_GNU_MALLOC + alloc_size[type] += malloc_size(ptr); + alloc_real_size[type] += malloc_real_size(ptr); + } +#endif + + return (char *)ptr + offs; +} + +void +myfree(void *ptr, Memory_Type type) +{ + alloc_num[type]--; +#ifdef USE_GNU_MALLOC + { + extern unsigned malloc_real_size(void *ptr); + extern unsigned malloc_size(void *ptr); + + alloc_size[type] -= malloc_size(ptr); + alloc_real_size[type] -= malloc_real_size(ptr); + } +#endif + + free((char *) ptr - refcount_overhead(type)); +} + +#ifdef USE_GNU_MALLOC +struct mstats_value { + int blocksize; + int nfree; + int nused; +}; + +extern struct mstats_value malloc_stats(int size); +#endif + +/* XXX stupid fix for non-gcc compilers, already in storage.h */ +#ifdef NEVER +void +free_str(const char *s) +{ + if (delref(s) == 0) + myfree((void *) s, M_STRING); +} +#endif + +Var +memory_usage(void) +{ + Var r; + +#ifdef USE_GNU_MALLOC + int nsizes, i; + + /* Discover how many block sizes there are. */ + for (nsizes = 0;; nsizes++) { + struct mstats_value v; + + v = malloc_stats(nsizes); + if (v.blocksize <= 0) + break; + } + + /* Get all of the allocation out of the way before getting the stats. */ + r = new_list(nsizes); + for (i = 1; i <= nsizes; i++) + r.v.list[i] = new_list(3); + + for (i = 0; i < nsizes; i++) { + struct mstats_value v; + Var l; + + v = malloc_stats(i); + l = r.v.list[i + 1]; + l.v.list[1].type = l.v.list[2].type = l.v.list[3].type = TYPE_INT; + l.v.list[1].v.num = v.blocksize; + l.v.list[2].v.num = v.nused; + l.v.list[3].v.num = v.nfree; + } +#else + r = new_list(0); +#endif + + return r; +} + +char rcsid_storage[] = "$Id: storage.c,v 1.1.1.1 2004/02/26 13:14:00 jesse Exp $"; + +/* + * $Log: storage.c,v $ + * Revision 1.1.1.1 2004/02/26 13:14:00 jesse + * Initial import into CVS + * + * Revision 1.5 1998/12/14 13:18:59 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.4 1997/07/07 03:24:55 nop + * Merge UNSAFE_OPTS (r5) after extensive testing. + * + * Revision 1.3.2.3 1997/05/29 20:47:32 nop + * Stupid hack to allow non-gcc compilers to use -Dinline= to make the server + * compile. + * + * Revision 1.3.2.2 1997/03/21 15:19:23 bjj + * add myrealloc interface, inline free_str + * + * Revision 1.3.2.1 1997/03/20 18:59:26 bjj + * Allocate refcounts with objects that can be addref()'d (strings, lists, + * floats). Use macros to manipulate those counts. This completely replaces + * the external hash table addref and friends. + * + * Revision 1.3 1997/03/03 06:32:10 bjj + * str_dup("") now returns the same empty string to every caller + * + * Revision 1.2 1997/03/03 04:19:26 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:01 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.1 1996/02/08 06:51:20 pavel + * Renamed TYPE_NUM to TYPE_INT. Updated copyright notice for 1996. + * Release 1.8.0beta1. + * + * Revision 2.0 1995/11/30 04:31:30 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.16 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.15 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.14 1992/10/17 20:52:37 pavel + * Global rename of strdup->str_dup, strref->str_ref, vardup->var_dup, and + * varref->var_ref. + * + * Revision 1.13 1992/09/14 18:38:42 pjames + * Updated #includes. Moved rcsid to bottom. + * + * Revision 1.12 1992/09/14 17:41:16 pjames + * Moved db_modification code to db modules. + * + * Revision 1.11 1992/09/03 16:26:29 pjames + * Added TYPE_CLEAR handling. + * Changed property definition manipulating to work with arrays. + * + * Revision 1.10 1992/08/31 22:25:27 pjames + * Changed some `char *'s to `const char *' + * + * Revision 1.9 1992/08/28 16:21:13 pjames + * Changed vardup to varref. + * Changed myfree(*, M_STRING) to free_str(*). + * Added `strref()' and `free_str()' + * + * Revision 1.8 1992/08/21 00:42:18 pavel + * Renamed include file "parse_command.h" to "parse_cmd.h". + * + * Changed to conditionalize on the option USE_GNU_MALLOC instead of + * USE_SYSTEM_MALLOC. + * + * Removed use of worthless constant DB_INITIAL_SIZE, defined in config.h. + * + * Revision 1.7 1992/08/14 00:00:45 pavel + * Converted to a typedef of `var_type' = `enum var_type'. + * + * Revision 1.6 1992/08/10 16:52:45 pjames + * Updated #includes. + * + * Revision 1.5 1992/07/30 21:23:10 pjames + * Casted malloc to (void *) because of a problem with some system. + * + * Revision 1.4 1992/07/27 19:05:18 pjames + * Removed a debugging statement. + * + * Revision 1.3 1992/07/27 18:17:41 pjames + * Changed name of ct_env to var_names and M_CT_ENV to M_NAMES. + * + * Revision 1.2 1992/07/21 00:06:38 pavel + * Added rcsid_ declaration to hold the RCS ident. string. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/storage.h b/gnoemoe/parser/storage.h new file mode 100644 index 0000000..08a6fc8 --- /dev/null +++ b/gnoemoe/parser/storage.h @@ -0,0 +1,123 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#ifndef Storage_h +#define Storage_h 1 + +#include "config.h" +#include "structures.h" + +typedef enum Memory_Type { + M_AST_POOL, M_AST, M_PROGRAM, M_PVAL, M_NETWORK, M_STRING, M_VERBDEF, + M_LIST, M_PREP, M_PROPDEF, M_OBJECT_TABLE, M_OBJECT, M_FLOAT, + M_STREAM, M_NAMES, M_ENV, M_TASK, M_PATTERN, + + M_BYTECODES, M_FORK_VECTORS, M_LIT_LIST, + M_PROTOTYPE, M_CODE_GEN, M_DISASSEMBLE, M_DECOMPILE, + + M_RT_STACK, M_RT_ENV, M_BI_FUNC_DATA, M_VM, + + M_REF_ENTRY, M_REF_TABLE, M_VC_ENTRY, M_VC_TABLE, M_STRING_PTRS, + M_INTERN_POINTER, M_INTERN_ENTRY, M_INTERN_HUNK, + + Sizeof_Memory_Type + +} Memory_Type; + +extern char *str_dup(const char *); +extern const char *str_ref(const char *); +extern Var memory_usage(void); + +extern void myfree(void *where, Memory_Type type); +extern void *mymalloc(unsigned size, Memory_Type type); +extern void *myrealloc(void *where, unsigned size, Memory_Type type); + +static inline void /* XXX was extern, fix for non-gcc compilers */ +free_str(const char *s) +{ + if (delref(s) == 0) + myfree((void *) s, M_STRING); +} + +#endif /* Storage_h */ + +/* + * $Log: storage.h,v $ + * Revision 1.1.1.1 2004/02/26 13:14:00 jesse + * Initial import into CVS + * + * Revision 1.5 1998/12/14 13:19:00 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.4 1998/02/19 07:36:17 nop + * Initial string interning during db load. + * + * Revision 1.3 1997/07/07 03:24:55 nop + * Merge UNSAFE_OPTS (r5) after extensive testing. + * + * Revision 1.2.2.4 1997/05/29 20:47:33 nop + * Stupid hack to allow non-gcc compilers to use -Dinline= to make the server + * compile. + * + * Revision 1.2.2.3 1997/05/20 03:01:34 nop + * parse_into_words was allocating pointers to strings as strings. Predictably, + * the refcount prepend code was not prepared for this, causing unaligned memory + * access on the Alpha. Added new M_STRING_PTRS allocation class that could + * be renamed to something better, perhaps. + * + * Revision 1.2.2.2 1997/03/21 15:19:24 bjj + * add myrealloc interface, inline free_str + * + * Revision 1.2.2.1 1997/03/20 07:26:04 nop + * First pass at the new verb cache. Some ugly code inside. + * + * Revision 1.2 1997/03/03 04:19:27 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:04 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.1 1996/02/08 06:13:09 pavel + * Added M_FLOAT, removed unused M_PI. Updated copyright notice for 1996. + * Release 1.8.0beta1. + * + * Revision 2.0 1995/11/30 04:55:11 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.7 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.6 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.5 1992/10/17 20:53:28 pavel + * Global rename of strdup->str_dup, strref->str_ref, vardup->var_dup, and + * varref->var_ref, to avoid conflict on systems that provide their own + * definition of strdup(). + * + * Revision 1.4 1992/09/14 17:39:30 pjames + * Moved db_modification code to db modules. + * + * Revision 1.3 1992/08/31 22:23:29 pjames + * Changed some `char *'s to `const char *' + * + * Revision 1.2 1992/08/28 16:25:17 pjames + * Added memory types for refcount module. Added `strref()' and `free_str()'. + * + * Revision 1.1 1992/08/10 16:20:00 pjames + * Initial RCS-controlled version + */ diff --git a/gnoemoe/parser/streams.c b/gnoemoe/parser/streams.c new file mode 100644 index 0000000..1ac3760 --- /dev/null +++ b/gnoemoe/parser/streams.c @@ -0,0 +1,276 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#include +#include +#include +#include + +#include "config.h" +#include "storage.h" +#include "streams.h" + +Stream * +new_stream(int size) +{ + Stream *s = mymalloc(sizeof(Stream), M_STREAM); + + s->buffer = mymalloc(size, M_STREAM); + s->buflen = size; + s->current = 0; + + return s; +} + +static void +grow(Stream * s, int newlen) +{ + char *newbuf; + + newbuf = mymalloc(newlen, M_STREAM); + memcpy(newbuf, s->buffer, s->current); + myfree(s->buffer, M_STREAM); + s->buffer = newbuf; + s->buflen = newlen; +} + +void +stream_add_char(Stream * s, char c) +{ + if (s->current + 1 >= s->buflen) + grow(s, s->buflen * 2); + + s->buffer[s->current++] = c; +} + +void +stream_add_string(Stream * s, const char *string) +{ + int len = strlen(string); + + if (s->current + len >= s->buflen) { + int newlen = s->buflen * 2; + + if (newlen <= s->current + len) + newlen = s->current + len + 1; + grow(s, newlen); + } + strcpy(s->buffer + s->current, string); + s->current += len; +} + +static const char * +itoa(int n, int radix) +{ + if (n == 0) /* zero produces "" below. */ + return "0"; + else if (n == -2147483647 - 1) /* min. integer won't work below. */ + switch (radix) { + case 16: + return "-7FFFFFFF"; + case 10: + return "-2147483648"; + case 8: + return "-17777777777"; + default: + return "0"; + } else { + static char buffer[20]; + char *ptr = buffer + 19; + int neg = 0; + + if (n < 0) { + neg = 1; + n = -n; + } + *(ptr) = '\0'; + while (n != 0) { + int digit = n % radix; + *(--ptr) = (digit < 10 ? '0' + digit : 'A' + digit - 10); + n /= radix; + } + if (neg) + *(--ptr) = '-'; + return ptr; + } +} + +static const char * +dbl_fmt(void) +{ + static const char *fmt = 0; + static char buffer[10]; + + if (!fmt) { + sprintf(buffer, "%%.%dg", DBL_DIG); + fmt = buffer; + } + return fmt; +} + +void +stream_printf(Stream * s, const char *fmt,...) +{ + char buffer[40]; + va_list args; + + va_start(args, fmt); + while (*fmt) { + char c = *fmt; + + if (c == '%') { + char pad = ' '; + int width = 0, base; + const char *string = ""; /* initialized to silence warning */ + + while ((c = *(++fmt)) != '\0') { + switch (c) { + case 's': + string = va_arg(args, char *); + break; + case 'x': + base = 16; + goto finish_number; + case 'o': + base = 8; + goto finish_number; + case 'd': + base = 10; + finish_number: + string = itoa(va_arg(args, int), base); + break; + case 'g': + sprintf(buffer, dbl_fmt(), va_arg(args, double)); + if (!strchr(buffer, '.') && !strchr(buffer, 'e')) + strcat(buffer, ".0"); /* make it look floating */ + string = buffer; + break; + case '0': + if (width == 0) { + pad = '0'; + continue; + } + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + width = width * 10 + c - '0'; + continue; + default: + goto abort; + } + break; + } + + if (width && (width -= strlen(string)) > 0) + while (width--) + stream_add_char(s, pad); + stream_add_string(s, string); + } else + stream_add_char(s, *fmt); + + fmt++; + } + + abort: + va_end(args); +} + +void +free_stream(Stream * s) +{ + myfree(s->buffer, M_STREAM); + myfree(s, M_STREAM); +} + +char * +reset_stream(Stream * s) +{ + s->buffer[s->current] = '\0'; + s->current = 0; + return s->buffer; +} + +char * +stream_contents(Stream * s) +{ + s->buffer[s->current] = '\0'; + return s->buffer; +} + +int +stream_length(Stream * s) +{ + return s->current; +} + +char rcsid_streams[] = "$Id: streams.c,v 1.1.1.1 2004/02/26 13:14:00 jesse Exp $"; + +/* + * $Log: streams.c,v $ + * Revision 1.1.1.1 2004/02/26 13:14:00 jesse + * Initial import into CVS + * + * Revision 1.3 1998/12/14 13:19:01 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.2 1997/03/03 04:19:28 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:01 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.5 1996/03/19 07:14:02 pavel + * Fixed default printing of floating-point numbers. Release 1.8.0p2. + * + * Revision 2.4 1996/03/11 23:33:04 pavel + * Added support for hexadecimal to stream_printf(). Release 1.8.0p1. + * + * Revision 2.3 1996/03/10 01:04:38 pavel + * Increased the precision of printed floating-point numbers by two digits. + * Release 1.8.0. + * + * Revision 2.2 1996/02/08 06:50:39 pavel + * Added support for %g conversion in stream_printf(). Renamed err/logf() to + * errlog/oklog(). Updated copyright notice for 1996. Release 1.8.0beta1. + * + * Revision 2.1 1996/01/11 07:43:01 pavel + * Added support for `%o' to stream_printf(). Release 1.8.0alpha5. + * + * Revision 2.0 1995/11/30 04:31:43 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.5 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.4 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.3 1992/08/10 16:52:24 pjames + * Updated #includes. + * + * Revision 1.2 1992/07/21 00:06:51 pavel + * Added rcsid_ declaration to hold the RCS ident. string. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/streams.h b/gnoemoe/parser/streams.h new file mode 100644 index 0000000..2d5245d --- /dev/null +++ b/gnoemoe/parser/streams.h @@ -0,0 +1,68 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#ifndef Stream_h +#define Stream_h 1 + +#include "config.h" + +typedef struct { + char *buffer; + int buflen; + int current; +} Stream; + +extern Stream *new_stream(int size); +extern void stream_add_char(Stream *, char); +extern void stream_add_string(Stream *, const char *); +extern void stream_printf(Stream *, const char *,...); +extern void free_stream(Stream *); +extern char *stream_contents(Stream *); +extern char *reset_stream(Stream *); +extern int stream_length(Stream *); + +#endif + +/* + * $Log: streams.h,v $ + * Revision 1.1.1.1 2004/02/26 13:14:00 jesse + * Initial import into CVS + * + * Revision 1.3 1998/12/14 13:19:02 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.2 1997/03/03 04:19:28 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:04 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.1 1996/02/08 06:12:33 pavel + * Updated copyright notice for 1996. Release 1.8.0beta1. + * + * Revision 2.0 1995/11/30 04:55:31 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.3 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.2 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/structures.h b/gnoemoe/parser/structures.h new file mode 100644 index 0000000..3600bac --- /dev/null +++ b/gnoemoe/parser/structures.h @@ -0,0 +1,195 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#ifndef Structures_h +#define Structures_h 1 + +#include +#include +#include + +#include "config.h" + +typedef int32 Objid; +typedef unsigned char Byte; +#define IS_REAL(x) (-DBL_MAX <= (x) && (x) <= DBL_MAX) + +#define addref(X) (++((int *)(X))[-1]) +#define delref(X) (--((int *)(X))[-1]) +#define refcount(X) (((int *)(X))[-1]) + +/* + * Special Objid's + */ +#define SYSTEM_OBJECT 0 +#define NOTHING -1 +#define AMBIGUOUS -2 +#define FAILED_MATCH -3 + +/* Do not reorder or otherwise modify this list, except to add new elements at + * the end, since the order here defines the numeric equivalents of the error + * values, and those equivalents are both DB-accessible knowledge and stored in + * raw form in the DB. + */ +enum error { + E_NONE, E_TYPE, E_DIV, E_PERM, E_PROPNF, E_VERBNF, E_VARNF, E_INVIND, + E_RECMOVE, E_MAXREC, E_RANGE, E_ARGS, E_NACC, E_INVARG, E_QUOTA, E_FLOAT +}; + +/* Do not reorder or otherwise modify this list, except to add new elements at + * the end, since the order here defines the numeric equivalents of the type + * values, and those equivalents are both DB-accessible knowledge and stored in + * raw form in the DB. + */ +typedef enum { + TYPE_INT, TYPE_OBJ, _TYPE_STR, TYPE_ERR, _TYPE_LIST, /* user-visible */ + TYPE_CLEAR, /* in clear properties' value slot */ + TYPE_NONE, /* in uninitialized MOO variables */ + TYPE_CATCH, /* on-stack marker for an exception handler */ + TYPE_FINALLY, /* on-stack marker for a TRY-FINALLY clause */ + _TYPE_FLOAT /* floating-point number; user-visible */ +} var_type; + +/* Types which have external data should be marked with the TYPE_COMPLEX_FLAG + * so that free_var/var_ref/var_dup can recognize them easily. This flag is + * only set in memory. The original _TYPE values are used in the database + * file and returned to verbs calling typeof(). This allows the inlines to + * be extremely cheap (both in space and time) for simple types like oids + * and ints. + */ +#define TYPE_DB_MASK 0x7f +#define TYPE_COMPLEX_FLAG 0x80 + +#define TYPE_STR (_TYPE_STR | TYPE_COMPLEX_FLAG) +#define TYPE_FLOAT (_TYPE_FLOAT | TYPE_COMPLEX_FLAG) +#define TYPE_LIST (_TYPE_LIST | TYPE_COMPLEX_FLAG) + +#define TYPE_ANY ((var_type) -1) /* wildcard for use in declaring built-ins */ +#define TYPE_NUMERIC ((var_type) -2) /* wildcard for (integer or float) */ + +typedef struct Var Var; + +/* Experimental. On the Alpha, DEC cc allows us to specify certain + * pointers to be 32 bits, but only if we compile and link with "-taso + * -xtaso" in CFLAGS, which limits us to a 31-bit address space. This + * could be a win if your server is thrashing. Running JHM's db, SIZE + * went from 50M to 42M. No doubt these pragmas could be applied + * elsewhere as well, but I know this at least manages to load and run + * a non-trivial db. + */ + +/* #define SHORT_ALPHA_VAR_POINTERS 1 */ + +#ifdef SHORT_ALPHA_VAR_POINTERS +#pragma pointer_size save +#pragma pointer_size short +#endif + +struct Var { + union { + const char *str; /* STR */ + int32 num; /* NUM, CATCH, FINALLY */ + Objid obj; /* OBJ */ + enum error err; /* ERR */ + Var *list; /* LIST */ + double *fnum; /* FLOAT */ + } v; + var_type type; +}; + +#ifdef SHORT_ALPHA_VAR_POINTERS +#pragma pointer_size restore +#endif + +extern Var zero; /* useful constant */ + +#endif /* !Structures_h */ + +/* + * $Log: structures.h,v $ + * Revision 1.1.1.1 2004/02/26 13:14:00 jesse + * Initial import into CVS + * + * Revision 1.4 1998/12/14 13:19:04 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.3 1997/07/07 03:24:55 nop + * Merge UNSAFE_OPTS (r5) after extensive testing. + * + * Revision 1.2.2.2 1997/05/23 07:01:30 nop + * Added experimental support for 32-bit pointer model on Alpha with DEC cc. + * + * Revision 1.2.2.1 1997/03/20 18:07:52 bjj + * Add a flag to the in-memory type identifier so that inlines can cheaply + * identify Vars that need actual work done to ref/free/dup them. Add the + * appropriate inlines to utils.h and replace old functions in utils.c with + * complex_* functions which only handle the types with external storage. + * + * Revision 1.2 1997/03/03 04:19:29 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:04 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.1 1996/02/08 06:12:21 pavel + * Added E_FLOAT, TYPE_FLOAT, and TYPE_NUMERIC. Renamed TYPE_NUM to TYPE_INT. + * Updated copyright notice for 1996. Release 1.8.0beta1. + * + * Revision 2.0 1995/11/30 04:55:46 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.12 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.11 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.10 1992/09/14 17:40:51 pjames + * Moved db_modification code to db modules. + * + * Revision 1.9 1992/09/04 01:17:29 pavel + * Added support for the `f' (for `fertile') bit on objects. + * + * Revision 1.8 1992/09/03 16:25:12 pjames + * Added TYPE_CLEAR for Var. + * Changed Property definition lists to be arrays instead of linked lists. + * + * Revision 1.7 1992/08/31 22:25:04 pjames + * Changed some `char *'s to `const char *' + * + * Revision 1.6 1992/08/14 00:00:36 pavel + * Converted to a typedef of `var_type' = `enum var_type'. + * + * Revision 1.5 1992/08/10 16:52:00 pjames + * Moved several types/procedure declarations to storage.h + * + * Revision 1.4 1992/07/30 21:24:31 pjames + * Added M_COND_ARM_STACK and M_STMT_STACK for vector.c + * + * Revision 1.3 1992/07/28 17:18:48 pjames + * Added M_COND_ARM_STACK for unparse.c + * + * Revision 1.2 1992/07/27 18:21:34 pjames + * Changed name of ct_env to var_names, const_env to literals and + * f_vectors to fork_vectors, removed M_CT_ENV, M_LOCAL_ENV, and + * M_LABEL_MAPS, changed M_CONST_ENV to M_LITERALS, M_IM_STACK to + * M_EXPR_STACK, M_F_VECTORS to M_FORK_VECTORS, M_ID_LIST to M_VL_LIST + * and M_ID_VALUE to M_VL_VALUE. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/sym_table.c b/gnoemoe/parser/sym_table.c new file mode 100644 index 0000000..c958645 --- /dev/null +++ b/gnoemoe/parser/sym_table.c @@ -0,0 +1,207 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#include + +#include "ast.h" +#include "config.h" +#include "storage.h" +#include "structures.h" +#include "sym_table.h" +#include "utils.h" +#include "version.h" + +static Names * +new_names(unsigned max_size) +{ + Names *names = mymalloc(sizeof(Names), M_NAMES); + + names->names = mymalloc(sizeof(char *) * max_size, M_NAMES); + names->max_size = max_size; + names->size = 0; + + return names; +} + +static Names * +copy_names(Names * old) +{ + Names *new = new_names(old->size); + unsigned i; + + new->size = old->size; + for (i = 0; i < new->size; i++) + new->names[i] = str_ref(old->names[i]); + + return new; +} + +int +first_user_slot(DB_Version version) +{ + int count = 16; /* DBV_Prehistory count */ + + if (version >= DBV_Float) + count += 2; + + return count; +} + +Names * +new_builtin_names(DB_Version version) +{ + static Names *builtins[Num_DB_Versions]; + + if (builtins[version] == 0) { + Names *bi = new_names(first_user_slot(version)); + + builtins[version] = bi; + bi->size = bi->max_size; + + bi->names[SLOT_NUM] = str_dup("NUM"); + bi->names[SLOT_OBJ] = str_dup("OBJ"); + bi->names[SLOT_STR] = str_dup("STR"); + bi->names[SLOT_LIST] = str_dup("LIST"); + bi->names[SLOT_ERR] = str_dup("ERR"); + bi->names[SLOT_PLAYER] = str_dup("player"); + bi->names[SLOT_THIS] = str_dup("this"); + bi->names[SLOT_CALLER] = str_dup("caller"); + bi->names[SLOT_VERB] = str_dup("verb"); + bi->names[SLOT_ARGS] = str_dup("args"); + bi->names[SLOT_ARGSTR] = str_dup("argstr"); + bi->names[SLOT_DOBJ] = str_dup("dobj"); + bi->names[SLOT_DOBJSTR] = str_dup("dobjstr"); + bi->names[SLOT_PREPSTR] = str_dup("prepstr"); + bi->names[SLOT_IOBJ] = str_dup("iobj"); + bi->names[SLOT_IOBJSTR] = str_dup("iobjstr"); + + if (version >= DBV_Float) { + bi->names[SLOT_INT] = str_dup("INT"); + bi->names[SLOT_FLOAT] = str_dup("FLOAT"); + } + } + return copy_names(builtins[version]); +} + +int +find_name(Names * names, const char *str) +{ + unsigned i; + + for (i = 0; i < names->size; i++) + if (!mystrcasecmp(names->names[i], str)) + return i; + return -1; +} + +unsigned +find_or_add_name(Names ** names, const char *str) +{ + unsigned i; + + for (i = 0; i < (*names)->size; i++) + if (!mystrcasecmp((*names)->names[i], str)) { /* old name */ + return i; + } + if ((*names)->size == (*names)->max_size) { + unsigned old_max = (*names)->max_size; + Names *new = new_names(old_max * 2); + unsigned i; + + for (i = 0; i < old_max; i++) + new->names[i] = (*names)->names[i]; + new->size = old_max; + myfree((*names)->names, M_NAMES); + myfree(*names, M_NAMES); + *names = new; + } + (*names)->names[(*names)->size] = str_dup(str); + return (*names)->size++; +} + +void +free_names(Names * names) +{ + unsigned i; + + for (i = 0; i < names->size; i++) + free_str(names->names[i]); + myfree(names->names, M_NAMES); + myfree(names, M_NAMES); +} + +char rcsid_sym_table[] = "$Id: sym_table.c,v 1.1.1.1 2004/02/26 13:14:00 jesse Exp $"; + +/* + * $Log: sym_table.c,v $ + * Revision 1.1.1.1 2004/02/26 13:14:00 jesse + * Initial import into CVS + * + * Revision 1.3 1998/12/14 13:19:05 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.2 1997/03/03 04:19:29 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:01 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.2 1996/03/10 01:16:32 pavel + * Removed a bunch of obsolete unused functions. Release 1.8.0. + * + * Revision 2.1 1996/02/08 06:49:24 pavel + * Made new_builtin_names() and first_user_slot() version-dependent. Renamed + * TYPE_NUM to TYPE_INT. Updated copyright notice for 1996. + * Release 1.8.0beta1. + * + * Revision 2.0 1995/11/30 04:31:53 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.10 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.9 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.8 1992/10/17 20:54:04 pavel + * Global rename of strdup->str_dup, strref->str_ref, vardup->var_dup, and + * varref->var_ref. + * + * Revision 1.7 1992/09/08 21:58:33 pjames + * Updated #includes. + * + * Revision 1.6 1992/08/31 22:24:18 pjames + * Changed some `char *'s to `const char *' + * + * Revision 1.5 1992/08/28 16:07:24 pjames + * Changed vardup to varref. + * Changed some strref's to strdup. + * Changed myfree(*, M_STRING) to free_str(*). + * + * Revision 1.4 1992/08/10 16:50:28 pjames + * Updated #includes. + * + * Revision 1.3 1992/07/27 18:23:48 pjames + * Changed M_CT_ENV to M_NAMES. Freed some memory that wasn't being + * freed when growing or freeing a list of names. + * + * Revision 1.2 1992/07/21 00:07:06 pavel + * Added rcsid_ declaration to hold the RCS ident. string. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/sym_table.h b/gnoemoe/parser/sym_table.h new file mode 100644 index 0000000..dc7624e --- /dev/null +++ b/gnoemoe/parser/sym_table.h @@ -0,0 +1,96 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#ifndef Sym_Table_h +#define Sym_Table_h 1 + +#include "config.h" +#include "version.h" + +typedef struct { + unsigned max_size; + unsigned size; + const char **names; +} Names; + +extern Names *new_builtin_names(DB_Version); +extern int first_user_slot(DB_Version); +extern unsigned find_or_add_name(Names **, const char *); +extern int find_name(Names *, const char *); +extern void free_names(Names *); + +/* Environment slots for built-in variables */ +#define SLOT_NUM 0 +#define SLOT_OBJ 1 +#define SLOT_STR 2 +#define SLOT_LIST 3 +#define SLOT_ERR 4 +#define SLOT_PLAYER 5 +#define SLOT_THIS 6 +#define SLOT_CALLER 7 +#define SLOT_VERB 8 +#define SLOT_ARGS 9 +#define SLOT_ARGSTR 10 +#define SLOT_DOBJ 11 +#define SLOT_DOBJSTR 12 +#define SLOT_PREPSTR 13 +#define SLOT_IOBJ 14 +#define SLOT_IOBJSTR 15 + +/* Added in DBV_Float: */ +#define SLOT_INT 16 +#define SLOT_FLOAT 17 + +#endif /* !Sym_Table_h */ + +/* + * $Log: sym_table.h,v $ + * Revision 1.1.1.1 2004/02/26 13:14:00 jesse + * Initial import into CVS + * + * Revision 1.3 1998/12/14 13:19:06 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.2 1997/03/03 04:19:30 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:04 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.2 1996/03/10 01:15:53 pavel + * Removed a number of obsolete declarations. Release 1.8.0. + * + * Revision 2.1 1996/02/08 06:11:23 pavel + * Made new_builtin_names() and first_user_slot() version-dependent to support + * version numbers on suspended-task frames. Added SLOT_INT and SLOT_FLOAT. + * Updated copyright notice for 1996. Release 1.8.0beta1. + * + * Revision 2.0 1995/11/30 04:55:57 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.4 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.3 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.2 1992/08/31 22:24:26 pjames + * Changed some `char *'s to `const char *' + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/tokens.h b/gnoemoe/parser/tokens.h new file mode 100644 index 0000000..8259f99 --- /dev/null +++ b/gnoemoe/parser/tokens.h @@ -0,0 +1,43 @@ +/****************************************************************************** + Copyright (c) 1994 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#ifndef tENDWHILE + +#include "ast.h" +#include "structures.h" + +#include "parser.h" + +#endif + +/* + * $Log: tokens.h,v $ + * Revision 1.1.1.1 2004/02/26 13:14:00 jesse + * Initial import into CVS + * + * Revision 1.2 1998/12/14 13:19:11 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.1.1.1 1997/03/03 03:45:04 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.0 1995/11/30 05:08:14 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.1 1995/11/30 05:08:05 pavel + * Initial revision + */ diff --git a/gnoemoe/parser/utils.c b/gnoemoe/parser/utils.c new file mode 100644 index 0000000..b8abe2d --- /dev/null +++ b/gnoemoe/parser/utils.c @@ -0,0 +1,432 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#include +#include +#include + +#include "config.h" +#include "numbers.h" +#include "list.h" +#include "storage.h" +#include "streams.h" +#include "structures.h" +#include "utils.h" + +/* + * These versions of strcasecmp() and strncasecmp() depend on ASCII. + * We implement them here because neither one is in the ANSI standard. + */ + +static const char cmap[] = +"\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017" +"\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +"\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057" +"\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077" +"\100\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157" +"\160\161\162\163\164\165\166\167\170\171\172\133\134\135\136\137" +"\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157" +"\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177" +"\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217" +"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237" +"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257" +"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277" +"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317" +"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337" +"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357" +"\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"; + +int +mystrcasecmp(const char *ss, const char *tt) +{ + const unsigned char *s = (const unsigned char *) ss; + const unsigned char *t = (const unsigned char *) tt; + + if (ss == tt) { + return 0; + } + while (cmap[*s] == cmap[*t++]) { + if (!*s++) + return 0; + } + return (cmap[*s] - cmap[*--t]); +} + +int +mystrncasecmp(const char *ss, const char *tt, int n) +{ + const unsigned char *s = (const unsigned char *) ss; + const unsigned char *t = (const unsigned char *) tt; + + if (!n || ss == tt) + return 0; + while (cmap[*s] == cmap[*t++]) { + if (!*s++ || !--n) + return 0; + } + return (cmap[*s] - cmap[*--t]); +} + +/* could be inlined and use complex_etc like the others, but this should + * usually be called in a context where we already konw the type. + */ +int +var_refcount(Var v) +{ + switch ((int) v.type) { + case TYPE_STR: + return refcount(v.v.str); + break; + case TYPE_LIST: + return refcount(v.v.list); + break; + case TYPE_FLOAT: + return refcount(v.v.fnum); + break; + } + return 1; +} + +int +is_true(Var v) +{ + return ((v.type == TYPE_INT && v.v.num != 0) + || (v.type == TYPE_FLOAT && *v.v.fnum != 0.0) + || (v.type == TYPE_STR && v.v.str && *v.v.str != '\0') + || (v.type == TYPE_LIST && v.v.list[0].v.num != 0)); +} + +int +equality(Var lhs, Var rhs, int case_matters) +{ + if (lhs.type == TYPE_FLOAT || rhs.type == TYPE_FLOAT) + return do_equals(lhs, rhs); + else if (lhs.type != rhs.type) + return 0; + else { + switch (lhs.type) { + case TYPE_INT: + return lhs.v.num == rhs.v.num; + case TYPE_OBJ: + return lhs.v.obj == rhs.v.obj; + case TYPE_ERR: + return lhs.v.err == rhs.v.err; + case TYPE_STR: + if (case_matters) + return !strcmp(lhs.v.str, rhs.v.str); + else + return !mystrcasecmp(lhs.v.str, rhs.v.str); + case TYPE_LIST: + if (lhs.v.list[0].v.num != rhs.v.list[0].v.num) + return 0; + else { + int i; + + if (lhs.v.list == rhs.v.list) { + return 1; + } + for (i = 1; i <= lhs.v.list[0].v.num; i++) { + if (!equality(lhs.v.list[i], rhs.v.list[i], case_matters)) + return 0; + } + return 1; + } + } + } + return 0; +} + +const char * +unparse_error(enum error e) +{ + switch (e) { + case E_NONE: + return "No error"; + case E_TYPE: + return "Type mismatch"; + case E_DIV: + return "Division by zero"; + case E_PERM: + return "Permission denied"; + case E_PROPNF: + return "Property not found"; + case E_VERBNF: + return "Verb not found"; + case E_VARNF: + return "Variable not found"; + case E_INVIND: + return "Invalid indirection"; + case E_RECMOVE: + return "Recursive move"; + case E_MAXREC: + return "Too many verb calls"; + case E_RANGE: + return "Range error"; + case E_ARGS: + return "Incorrect number of arguments"; + case E_NACC: + return "Move refused by destination"; + case E_INVARG: + return "Invalid argument"; + case E_QUOTA: + return "Resource limit exceeded"; + case E_FLOAT: + return "Floating-point arithmetic error"; + } + + return "Unknown Error"; +} + +const char * +error_name(enum error e) +{ + switch (e) { + case E_NONE: + return "E_NONE"; + case E_TYPE: + return "E_TYPE"; + case E_DIV: + return "E_DIV"; + case E_PERM: + return "E_PERM"; + case E_PROPNF: + return "E_PROPNF"; + case E_VERBNF: + return "E_VERBNF"; + case E_VARNF: + return "E_VARNF"; + case E_INVIND: + return "E_INVIND"; + case E_RECMOVE: + return "E_RECMOVE"; + case E_MAXREC: + return "E_MAXREC"; + case E_RANGE: + return "E_RANGE"; + case E_ARGS: + return "E_ARGS"; + case E_NACC: + return "E_NACC"; + case E_INVARG: + return "E_INVARG"; + case E_QUOTA: + return "E_QUOTA"; + case E_FLOAT: + return "E_FLOAT"; + } + + return "E_?"; +} + +void +complex_free_var(Var v) +{ + int i; + + switch ((int) v.type) { + case TYPE_STR: + if (v.v.str) + free_str(v.v.str); + break; + case TYPE_LIST: + if (delref(v.v.list) == 0) { + Var *pv; + + for (i = v.v.list[0].v.num, pv = v.v.list + 1; i > 0; i--, pv++) + free_var(*pv); + myfree(v.v.list, M_LIST); + } + break; + case TYPE_FLOAT: + if (delref(v.v.fnum) == 0) + myfree(v.v.fnum, M_FLOAT); + break; + } +} + +Var +complex_var_ref(Var v) +{ + switch ((int) v.type) { + case TYPE_STR: + addref(v.v.str); + break; + case TYPE_LIST: + addref(v.v.list); + break; + case TYPE_FLOAT: + addref(v.v.fnum); + break; + } + return v; +} + +Var +complex_var_dup(Var v) +{ + int i; + Var newlist; + + switch ((int) v.type) { + case TYPE_STR: + v.v.str = str_dup(v.v.str); + break; + case TYPE_LIST: + newlist = new_list(v.v.list[0].v.num); + for (i = 1; i <= v.v.list[0].v.num; i++) { + newlist.v.list[i] = var_ref(v.v.list[i]); + } + v.v.list = newlist.v.list; + break; + case TYPE_FLOAT: + v = new_float(*v.v.fnum); + break; + } + return v; +} + +unsigned +str_hash(const char *s) +{ + unsigned ans = 0; + int i, len = strlen(s), offset = 0; + + for (i = 0; i < len; i++) { + ans = ans ^ (cmap[(unsigned char) s[i]] << offset++); + if (offset == 25) + offset = 0; + } + return ans; +} + +char rcsid_utils[] = "$Id: utils.c,v 1.1.1.1 2004/02/26 13:14:00 jesse Exp $"; + +/* + * $Log: utils.c,v $ + * Revision 1.1.1.1 2004/02/26 13:14:00 jesse + * Initial import into CVS + * + * Revision 1.5 1999/08/09 02:36:33 nop + * Shortcut various equality tests if we have pointer equality. + * + * Revision 1.4 1998/12/14 13:19:14 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.3 1997/07/07 03:24:55 nop + * Merge UNSAFE_OPTS (r5) after extensive testing. + * + * Revision 1.2.2.3 1997/03/21 15:11:22 bjj + * add var_refcount interface + * + * Revision 1.2.2.2 1997/03/21 14:29:03 bjj + * Some code bumming in complex_free_var (3rd most expensive function!) + * + * Revision 1.2.2.1 1997/03/20 18:07:48 bjj + * Add a flag to the in-memory type identifier so that inlines can cheaply + * identify Vars that need actual work done to ref/free/dup them. Add the + * appropriate inlines to utils.h and replace old functions in utils.c with + * complex_* functions which only handle the types with external storage. + * + * Revision 1.2 1997/03/03 04:19:36 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:01 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.8 1996/04/08 00:43:09 pavel + * Changed definition of `value_bytes()' to add in `sizeof(Var)'. + * Release 1.8.0p3. + * + * Revision 2.7 1996/03/11 23:34:41 pavel + * Changed %X to %x in a stream_printf call, since I don't want to support + * both upper- and lower-case. Release 1.8.0p1. + * + * Revision 2.6 1996/03/10 01:14:16 pavel + * Change the format of binary strings to use hex instead of octal. + * Release 1.8.0. + * + * Revision 2.5 1996/02/08 06:41:04 pavel + * Added support for floating-point. Moved compare_ints() to numbers.c. + * Renamed err/logf() to errlog/oklog() and TYPE_NUM to TYPE_INT. Updated + * copyright notice for 1996. Release 1.8.0beta1. + * + * Revision 2.4 1996/01/16 07:24:48 pavel + * Removed special format for `~' in binary strings. Release 1.8.0alpha6. + * + * Revision 2.3 1996/01/11 07:40:01 pavel + * Added raw_bytes_to_binary() and binary_to_raw_bytes(), in support of binary + * I/O facilities. Release 1.8.0alpha5. + * + * Revision 2.2 1995/12/28 00:38:54 pavel + * Neatened up implementation of case-folding string comparison functions. + * Release 1.8.0alpha3. + * + * Revision 2.1 1995/12/11 08:09:31 pavel + * Account for newly-clarified reference-counting behavior for built-in + * properties. Add `value_bytes()' from elsewhere. Release 1.8.0alpha2. + * + * Revision 2.0 1995/11/30 04:43:24 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.13 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.12 1992/10/23 22:23:18 pavel + * Eliminated all uses of the useless macro NULL. + * + * Revision 1.11 1992/10/17 20:57:08 pavel + * Global rename of strdup->str_dup, strref->str_ref, vardup->var_dup, and + * varref->var_ref. + * Removed useless #ifdef of STRCASE. + * + * Revision 1.10 1992/09/14 17:39:53 pjames + * Moved db_modification code to db modules. + * + * Revision 1.9 1992/09/08 21:55:47 pjames + * Updated #includes. + * + * Revision 1.8 1992/09/03 16:23:49 pjames + * Make cmap[] visible. Added TYPE_CLEAR handling. + * + * Revision 1.7 1992/08/28 16:23:41 pjames + * Changed vardup to varref. + * Changed myfree(*, M_STRING) to free_str(*). + * Added `varref()'. + * Changed `free_var()' to check `delref()' before freeing. + * Removed `copy_pi()'. + * + * Revision 1.6 1992/08/18 00:54:40 pavel + * Fixed typo. + * + * Revision 1.5 1992/08/18 00:41:14 pavel + * Fixed boundary-condition bugs in index() and rindex(), when the search string + * is empty. + * + * Revision 1.4 1992/08/11 17:26:56 pjames + * Removed read/write Parse_Info procedures. + * + * Revision 1.3 1992/08/10 16:40:20 pjames + * Added is_true (from execute.c) and *_activ_as_pi routines. Added a + * check for null parse_info in write_pi, because parse_infos are no + * longer stored in each activation. + * + * Revision 1.2 1992/07/21 00:07:48 pavel + * Added rcsid_ declaration to hold the RCS ident. string. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/utils.h b/gnoemoe/parser/utils.h new file mode 100644 index 0000000..e73ac80 --- /dev/null +++ b/gnoemoe/parser/utils.h @@ -0,0 +1,168 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#ifndef Utils_h +#define Utils_h 1 + +#include + +#include "config.h" + +#undef MAX +#undef MIN +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#define MIN(A, B) ((A) < (B) ? (A) : (B)) + +#define Arraysize(x) (sizeof(x) / sizeof(*x)) + +extern int mystrcasecmp(const char *, const char *); +extern int mystrncasecmp(const char *, const char *, int); + +extern int verbcasecmp(const char *verb, const char *word); + +extern unsigned str_hash(const char *); + +extern void complex_free_var(Var); +extern Var complex_var_ref(Var); +extern Var complex_var_dup(Var); +extern int var_refcount(Var); + +static inline void +free_var(Var v) +{ + if (v.type & TYPE_COMPLEX_FLAG) + complex_free_var(v); +} + +static inline Var +var_ref(Var v) +{ + if (v.type & TYPE_COMPLEX_FLAG) + return complex_var_ref(v); + else + return v; +} + +static inline Var +var_dup(Var v) +{ + if (v.type & TYPE_COMPLEX_FLAG) + return complex_var_dup(v); + else + return v; +} + +const char *unparse_error(enum error e); +extern int equality(Var lhs, Var rhs, int case_matters); +extern int is_true(Var v); + +extern char *strsub(const char *, const char *, const char *, int); +extern int strindex(const char *, const char *, int); +extern int strrindex(const char *, const char *, int); + +extern Var get_system_property(const char *); +extern Objid get_system_object(const char *); + +extern int value_bytes(Var); + +extern const char *raw_bytes_to_binary(const char *buffer, int buflen); +extern const char *binary_to_raw_bytes(const char *binary, int *rawlen); + +#endif + +/* + * $Log: utils.h,v $ + * Revision 1.1.1.1 2004/02/26 13:14:00 jesse + * Initial import into CVS + * + * Revision 1.6 1998/12/14 13:19:15 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.5 1997/07/07 03:24:55 nop + * Merge UNSAFE_OPTS (r5) after extensive testing. + * + * Revision 1.4.2.2 1997/03/21 15:11:22 bjj + * add var_refcount interface + * + * Revision 1.4.2.1 1997/03/20 18:07:49 bjj + * Add a flag to the in-memory type identifier so that inlines can cheaply + * identify Vars that need actual work done to ref/free/dup them. Add the + * appropriate inlines to utils.h and replace old functions in utils.c with + * complex_* functions which only handle the types with external storage. + * + * Revision 1.4 1997/03/05 08:20:51 bjj + * With 1.2 (oops) add MIN/MAX macros that do the obvious thing, with undef to + * avoid clashing with system definitions. + * + * Revision 1.3 1997/03/05 08:15:55 bjj + * *** empty log message *** + * + * Revision 1.2 1997/03/03 04:19:37 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:04 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.4 1996/02/08 06:08:07 pavel + * Moved become_number and compare_ints to number.h. Updated copyright notice + * for 1996. Release 1.8.0beta1. + * + * Revision 2.3 1996/01/11 07:46:18 pavel + * Added raw_bytes_to_binary() and binary_to_raw_bytes(), in support of binary + * I/O facilities. Release 1.8.0alpha5. + * + * Revision 2.2 1995/12/28 00:39:38 pavel + * Removed declaration for private variable `cmap'. Release 1.8.0alpha3. + * + * Revision 2.1 1995/12/11 08:09:56 pavel + * Add `value_bytes()'. Release 1.8.0alpha2. + * + * Revision 2.0 1995/11/30 04:56:31 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.10 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.9 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.8 1992/10/17 20:57:30 pavel + * Global rename of strdup->str_dup, strref->str_ref, vardup->var_dup, and + * varref->var_ref. + * Removed useless #ifdef of STRCASE. + * + * Revision 1.7 1992/09/08 21:55:12 pjames + * Added `become_number()' (from bf_num.c). + * + * Revision 1.6 1992/09/03 16:23:16 pjames + * Make cmap[] visible. + * + * Revision 1.5 1992/08/31 22:22:05 pjames + * Changed some `char *'s to `const char *' + * + * Revision 1.4 1992/08/28 16:24:15 pjames + * Added `varref()'. Removed `copy_pi()'. + * + * Revision 1.3 1992/08/10 16:38:28 pjames + * Added is_true (from execute.h) and *_activ_as_pi routines. + * + * Revision 1.2 1992/07/27 18:03:48 pjames + * Changed name of ct_env to var_names + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */ diff --git a/gnoemoe/parser/version.c b/gnoemoe/parser/version.c new file mode 100644 index 0000000..dcb6b74 --- /dev/null +++ b/gnoemoe/parser/version.c @@ -0,0 +1,52 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +/* + * The server_version is a character string containing three decimal numbers + * separated by periods: + * + * .. + * + * The major version number changes very slowly, only when existing MOO code + * might stop working, due to an incompatible change in the syntax or + * semantics of the programming language, or when an incompatible change is + * made to the database format. + * + * The minor version number changes more quickly, whenever an upward- + * compatible change is made in the programming language syntax or semantics. + * The most common cause of this is the addition of a new kind of expression, + * statement, or built-in function. + * + * The release version number changes as frequently as bugs are fixed in the + * server code. Changes in the release number indicate changes that should + * only be visible to users as bug fixes, if at all. + * + */ + +#include "config.h" +#include "version.h" + +const char *server_version = "1.8.1fc+ipv6+fup1.8"; +const char *FUP_version = "1.8"; + +int +check_version(DB_Version version) +{ + return version < Num_DB_Versions; +} + +char rcsid_version[] = "$Id: version.c,v 1.3 2005/01/21 12:07:31 jesse Exp $"; diff --git a/gnoemoe/parser/version.h b/gnoemoe/parser/version.h new file mode 100644 index 0000000..a9ccfe8 --- /dev/null +++ b/gnoemoe/parser/version.h @@ -0,0 +1,101 @@ +/****************************************************************************** + Copyright (c) 1992, 1995, 1996 Xerox Corporation. All rights reserved. + Portions of this code were written by Stephen White, aka ghond. + Use and copying of this software and preparation of derivative works based + upon this software are permitted. Any distribution of this software or + derivative works must comply with all applicable United States export + control laws. This software is made available AS IS, and Xerox Corporation + makes no warranty about the software, its performance or its conformity to + any specification. Any person obtaining a copy of this software is requested + to send their name and post office or electronic mail address to: + Pavel Curtis + Xerox PARC + 3333 Coyote Hill Rd. + Palo Alto, CA 94304 + Pavel@Xerox.Com + *****************************************************************************/ + +#ifndef Version_H +#define Version_H 1 + +#include "config.h" + +extern const char *server_version; +extern const char *FUP_version; + +/* The following list must never be reordered, only appended to. There is one + * element per version of the database format (including incompatible changes + * to the language, such as the addition of new keywords). The integer value + * of each element is used in the DB header on disk to identify the format + * version in use in that file. + */ +typedef enum { + DBV_Prehistory, /* Before format versions */ + DBV_Exceptions, /* Addition of the `try', `except', `finally', + * and `endtry' keywords. + */ + DBV_BreakCont, /* Addition of the `break' and `continue' + * keywords. + */ + DBV_Float, /* Addition of `FLOAT' and `INT' variables and + * the `E_FLOAT' keyword, along with version + * numbers on each frame of a suspended task. + */ + DBV_BFBugFixed, /* Bug in built-in function overrides fixed by + * making it use tail-calling. This DB_Version + * change exists solely to turn off special + * bug handling in read_bi_func_data(). + */ + Num_DB_Versions /* Special: the current version is this - 1. */ +} DB_Version; + +#define current_version ((DB_Version) (Num_DB_Versions - 1)) + +extern int check_version(DB_Version); + /* Returns true iff given version is within the + * known range. + */ + +#endif /* !Version_H */ + +/* + * $Log: version.h,v $ + * Revision 1.2 2005/01/21 12:07:31 jesse + * Added FUP + * + * Revision 1.1.1.1 2004/02/26 13:14:00 jesse + * Initial import into CVS + * + * Revision 1.3 1998/12/14 13:19:19 nop + * Merge UNSAFE_OPTS (ref fixups); fix Log tag placement to fit CVS whims + * + * Revision 1.2 1997/03/03 04:19:39 nop + * GNU Indent normalization + * + * Revision 1.1.1.1 1997/03/03 03:45:04 nop + * LambdaMOO 1.8.0p5 + * + * Revision 2.3 1996/04/19 01:25:21 pavel + * Added somewhat bogus DBV_BFBugFixed version. Release 1.8.0p4. + * + * Revision 2.2 1996/02/08 06:07:10 pavel + * Added DBV_BreakCont and DBV_Float versions, check_version(). Moved + * db_in_version to db_io.h and renamed db_out_version to current_version. + * Updated copyright notice for 1996. Release 1.8.0beta1. + * + * Revision 2.1 1995/12/28 00:48:42 pavel + * Fixed list of new keywords in comment to remove transient `raise' keyword. + * Release 1.8.0alpha3. + * + * Revision 2.0 1995/11/30 04:56:42 pavel + * New baseline version, corresponding to release 1.8.0alpha1. + * + * Revision 1.3 1992/10/23 23:03:47 pavel + * Added copyright notice. + * + * Revision 1.2 1992/10/21 03:02:35 pavel + * Converted to use new automatic configuration system. + * + * Revision 1.1 1992/07/20 23:23:12 pavel + * Initial RCS-controlled version. + */