"Compiling" version

This commit is contained in:
Guido van Rossum 1990-12-20 15:06:42 +00:00
parent 226d79eb4a
commit 3f5da24ea3
72 changed files with 3363 additions and 2061 deletions

26
Include/allobjects.h Normal file
View File

@ -0,0 +1,26 @@
/* "allobjects.c" -- Source for precompiled header "allobjects.h" */
#include <stdio.h>
#include "string.h"
#include "PROTO.h"
#include "object.h"
#include "objimpl.h"
#include "intobject.h"
#include "floatobject.h"
#include "stringobject.h"
#include "tupleobject.h"
#include "listobject.h"
#include "dictobject.h"
#include "methodobject.h"
#include "moduleobject.h"
#include "funcobject.h"
#include "classobject.h"
#include "fileobject.h"
#include "errors.h"
#include "malloc.h"
extern char *strdup PROTO((const char *));

3
Include/bltinmodule.h Normal file
View File

@ -0,0 +1,3 @@
/* Built-in module interface */
extern object *getbuiltin PROTO((char *));

9
Include/ceval.h Normal file
View File

@ -0,0 +1,9 @@
/* Interface to execute compiled code */
/* This header depends on "compile.h" */
object *eval_code PROTO((codeobject *, object *, object *, object *));
object *getglobals PROTO((void));
object *getlocals PROTO((void));
void printtraceback PROTO((FILE *));

View File

@ -12,7 +12,7 @@ extern typeobject Classtype, Classmembertype, Classmethodtype;
#define is_classmemberobject(op) ((op)->ob_type == &Classmembertype)
#define is_classmethodobject(op) ((op)->ob_type == &Classmethodtype)
extern object *newclassobject PROTO((node *, object *, object *));
extern object *newclassobject PROTO((object *, object *));
extern object *newclassmemberobject PROTO((object *));
extern object *newclassmethodobject PROTO((object *, object *));

23
Include/compile.h Normal file
View File

@ -0,0 +1,23 @@
/* Definitions for compiled intermediate code */
/* An intermediate code fragment contains:
- a string that encodes the instructions,
- a list of the constants,
- and a list of the names used. */
typedef struct {
OB_HEAD
stringobject *co_code; /* instruction opcodes */
object *co_consts; /* list of immutable constant objects */
object *co_names; /* list of stringobjects */
object *co_filename; /* string */
} codeobject;
extern typeobject Codetype;
#define is_codeobject(op) ((op)->ob_type == &Codetype)
/* Public interface */
codeobject *compile PROTO((struct _node *, char *));

View File

@ -7,7 +7,7 @@ int err_occurred PROTO((void));
void err_get PROTO((object **, object **));
void err_clear PROTO((void));
/* Predefined exceptions (in run.c) */
/* Predefined exceptions */
extern object *RuntimeError;
extern object *EOFError;
@ -29,5 +29,6 @@ extern object *KeyboardInterrupt;
extern int err_badarg PROTO((void));
extern object *err_nomem PROTO((void));
extern object *err_errno PROTO((object *));
extern void err_input PROTO((int));
extern void err_badcall PROTO((void));

56
Include/frameobject.h Normal file
View File

@ -0,0 +1,56 @@
/* Frame object interface */
typedef struct {
int b_type; /* what kind of block this is */
int b_handler; /* where to jump to find handler */
int b_level; /* value stack level to pop to */
} block;
typedef struct _frame {
OB_HEAD
struct _frame *f_back; /* previous frame, or NULL */
codeobject *f_code; /* code segment */
object *f_globals; /* global symbol table (dictobject) */
object *f_locals; /* local symbol table (dictobject) */
object **f_valuestack; /* malloc'ed array */
block *f_blockstack; /* malloc'ed array */
int f_nvalues; /* size of f_valuestack */
int f_nblocks; /* size of f_blockstack */
int f_iblock; /* index in f_blockstack */
} frameobject;
/* Standard object interface */
extern typeobject Frametype;
#define is_frameobject(op) ((op)->ob_type == &Frametype)
frameobject * newframeobject PROTO(
(frameobject *, codeobject *, object *, object *, int, int));
/* The rest of the interface is specific for frame objects */
/* List access macros */
#ifdef NDEBUG
#define GETITEM(v, i) GETLISTITEM((listobject *)(v), (i))
#define GETITEMNAME(v, i) GETSTRINGVALUE((stringobject *)GETITEM((v), (i)))
#else
#define GETITEM(v, i) getlistitem((v), (i))
#define GETITEMNAME(v, i) getstringvalue(getlistitem((v), (i)))
#endif
#define GETUSTRINGVALUE(s) ((unsigned char *)GETSTRINGVALUE(s))
/* Code access macros */
#define Getconst(f, i) (GETITEM((f)->f_code->co_consts, (i)))
#define Getname(f, i) (GETITEMNAME((f)->f_code->co_names, (i)))
/* Block management functions */
void setup_block PROTO((frameobject *, int, int, int));
block *pop_block PROTO((frameobject *));

View File

@ -76,3 +76,6 @@ void translatelabels PROTO((grammar *g));
void addfirstsets PROTO((grammar *g));
void addaccellerators PROTO((grammar *g));
void printgrammar PROTO((grammar *g, FILE *fp));
void printnonterminals PROTO((grammar *g, FILE *fp));

View File

@ -1,5 +1,7 @@
/* Module definition and import interface */
object *new_module PROTO((char *name));
object *import_module PROTO((struct _context *ctx, char *name));
object *reload_module PROTO((struct _context *ctx, object *m));
object *get_modules PROTO((void));
object *add_module PROTO((char *name));
object *import_module PROTO((char *name));
object *reload_module PROTO((object *m));
void doneimport PROTO((void));

View File

@ -14,6 +14,11 @@ inserted in the list. Similarly, getlistitem does not increment the
returned item's reference count.
*/
typedef struct {
OB_VARHEAD
object **ob_item;
} listobject;
extern typeobject Listtype;
#define is_listobject(op) ((op)->ob_type == &Listtype)
@ -25,3 +30,6 @@ extern int setlistitem PROTO((object *, int, object *));
extern int inslistitem PROTO((object *, int, object *));
extern int addlistitem PROTO((object *, object *));
extern int sortlist PROTO((object *));
/* Macro, trading safety for speed */
#define GETLISTITEM(op, i) ((op)->ob_item[i])

View File

@ -9,3 +9,10 @@ typedef object *(*method) FPROTO((object *, object *));
extern object *newmethodobject PROTO((char *, method, object *));
extern method getmethod PROTO((object *));
extern object *getself PROTO((object *));
struct methodlist {
char *ml_name;
method ml_meth;
};
extern object *findmethod PROTO((struct methodlist *, object *, char *));

View File

@ -1,9 +1,3 @@
/* Module support interface */
struct methodlist {
char *ml_name;
method ml_meth;
};
extern object *findmethod PROTO((struct methodlist *, object *, char *));
extern object *initmodule PROTO((char *, struct methodlist *));

View File

@ -6,5 +6,4 @@ extern typeobject Moduletype;
extern object *newmoduleobject PROTO((char *));
extern object *getmoduledict PROTO((object *));
extern int setmoduledict PROTO((object *, object *));
extern char *getmodulename PROTO((object *));

View File

@ -3,13 +3,14 @@
typedef struct _node {
int n_type;
char *n_str;
int n_lineno;
int n_nchildren;
struct _node *n_child;
} node;
extern node *newnode PROTO((int type));
extern node *addchild PROTO((node *n, int type, char *str));
extern void freenode PROTO((node *n));
extern node *newtree PROTO((int type));
extern node *addchild PROTO((node *n, int type, char *str, int lineno));
extern void freetree PROTO((node *n));
/* Node access functions */
#define NCH(n) ((n)->n_nchildren)
@ -28,3 +29,6 @@ extern void freenode PROTO((node *n));
abort(); \
} }
#endif
extern void listtree PROTO((node *));
extern void listnode PROTO((FILE *, node *));

View File

@ -1,3 +1,4 @@
#define NDEBUG
/* Object and type object interface */
/*
@ -47,11 +48,15 @@ whose size is determined when the object is allocated.
123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
*/
#ifdef THINK_C
/* Debugging options for THINK_C (which has no -D compiler option): */
/*#define TRACE_REFS*/
/*#define REF_DEBUG*/
#endif
#ifndef NDEBUG
/* Turn on heavy reference debugging */
#define TRACE_REFS
/* Turn on reference counting */
#define REF_DEBUG
#endif /* NDEBUG */
#ifdef TRACE_REFS
#define OB_HEAD \
@ -147,9 +152,12 @@ extern typeobject Typetype; /* The type of type objects */
#define is_typeobject(op) ((op)->ob_type == &Typetype)
/* Generic operations on objects */
extern void printobject PROTO((object *, FILE *, int));
extern object * reprobject PROTO((object *));
extern int cmpobject PROTO((object *, object *));
extern object *getattr PROTO((object *, char *));
extern int setattr PROTO((object *, char *, object *));
/* Flag bits for printing: */
#define PRINT_RAW 1 /* No string quotes etc. */
@ -215,6 +223,10 @@ extern long ref_total;
DELREF(op)
#endif
/* Macros to use in case the object pointer may be NULL: */
#define XINCREF(op) if ((op) == NULL) ; else INCREF(op)
#define XDECREF(op) if ((op) == NULL) ; else DECREF(op)
/* Definition of NULL, so you don't have to include <stdio.h> */
@ -252,22 +264,12 @@ Failure Modes
-------------
Functions may fail for a variety of reasons, including running out of
memory. This is communicated to the caller in two ways: 'errno' is set
to indicate the error, and the function result differs: functions that
normally return a pointer return nil for failure, functions returning
an integer return -1 (which can be a legal return value too!), and
other functions return 0 for success and the error number for failure.
Callers should always check for errors before using the result. The
following error codes are used:
EBADF bad object type (first argument only)
EINVAL bad argument type (second and further arguments)
ENOMEM no memory (malloc failed)
ENOENT key not found in dictionary
EDOM index out of range or division by zero
ERANGE result not representable
XXX any others?
memory. This is communicated to the caller in two ways: an error string
is set (see errors.h), and the function result differs: functions that
normally return a pointer return NULL for failure, functions returning
an integer return -1 (which could be a legal return value too!), and
other functions return 0 for success and -1 for failure.
Callers should always check for errors before using the result.
Reference Counts
----------------
@ -296,16 +298,3 @@ times.
123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
*/
/* Error number interface */
#include <errno.h>
#ifndef errno
extern int errno;
#endif
#ifdef THINK_C
/* Lightspeed C doesn't define these in <errno.h> */
#define EDOM 33
#define ERANGE 34
#endif

View File

@ -24,8 +24,3 @@ extern varobject *newvarobject PROTO((typeobject *, unsigned int));
#define NEWVAROBJ(type, typeobj, n) ((type *) newvarobject(typeobj, n))
extern int StopPrint; /* Set when printing is interrupted */
/* Malloc interface */
#include "malloc.h"
extern char *strdup PROTO((const char *));

View File

@ -1,9 +1,10 @@
/* Instruction opcodes for compiled code */
#define DUP_TOP 0
#define STOP_CODE 0
#define POP_TOP 1
#define ROT_TWO 2
#define ROT_THREE 3
#define DUP_TOP 4
#define UNARY_POSITIVE 10
#define UNARY_NEGATIVE 11
@ -76,5 +77,9 @@
#define SETUP_EXCEPT 121 /* "" */
#define SETUP_FINALLY 122 /* "" */
#define SET_LINENO 127 /* Current line number */
/* Comparison operator codes (argument to COMPARE_OP) */
enum cmp_op {LT, LE, EQ, NE, GT, GE, IN, NOT_IN, IS, IS_NOT, EXC_MATCH, BAD};
#define HAS_ARG(op) ((op) >= HAVE_ARGUMENT)

View File

@ -1,9 +1,5 @@
/* Parser-tokenizer link interface */
#if 0
extern int parsetok PROTO((struct tok_state *, grammar *, int start,
node **n_ret));
#endif
extern int parsestring PROTO((char *, grammar *, int start, node **n_ret));
extern int parsefile PROTO((FILE *, grammar *, int start,
extern int parsefile PROTO((FILE *, char *, grammar *, int start,
char *ps1, char *ps2, node **n_ret));

15
Include/pgenheaders.h Normal file
View File

@ -0,0 +1,15 @@
/* Include files and extern declarations used by most of the parser.
This is a precompiled header for THINK C. */
#include <stdio.h>
#ifdef THINK_C
#define label label_
#include <proto.h>
#undef label
#endif
#include "PROTO.h"
#include "malloc.h"
extern void fatal PROTO((char *));

View File

@ -7,7 +7,7 @@ int err_occurred PROTO((void));
void err_get PROTO((object **, object **));
void err_clear PROTO((void));
/* Predefined exceptions (in run.c) */
/* Predefined exceptions */
extern object *RuntimeError;
extern object *EOFError;
@ -29,5 +29,6 @@ extern object *KeyboardInterrupt;
extern int err_badarg PROTO((void));
extern object *err_nomem PROTO((void));
extern object *err_errno PROTO((object *));
extern void err_input PROTO((int));
extern void err_badcall PROTO((void));

23
Include/pythonrun.h Normal file
View File

@ -0,0 +1,23 @@
/* Interfaces to parse and execute pieces of python code */
void initall PROTO((void));
int run PROTO((FILE *, char *));
int run_script PROTO((FILE *, char *));
int run_tty_1 PROTO((FILE *, char *));
int run_tty_loop PROTO((FILE *, char *));
int parse_string PROTO((char *, int, struct _node **));
int parse_file PROTO((FILE *, char *, int, struct _node **));
object *eval_node PROTO((struct _node *, char *, object *, object *));
object *run_string PROTO((char *, int, object *, object *));
object *run_file PROTO((FILE *, char *, int, object *, object *));
object *run_err_node PROTO((int, struct _node *, char *, object *, object *));
object *run_node PROTO((struct _node *, char *, object *, object *));
void print_error PROTO((void));
void goaway PROTO((int));

40
Include/structmember.h Normal file
View File

@ -0,0 +1,40 @@
/* Interface to map C struct members to Python object attributes */
/* The offsetof() macro calculates the offset of a structure member
in its structure. Unfortunately this cannot be written down
portably, hence it is provided by a Standard C header file.
For pre-Standard C compilers, here is a version that usually works
(but watch out!): */
#ifndef offsetof
#define offsetof(type, member) ( (int) & ((type*)0) -> member )
#endif
/* An array of memberlist structures defines the name, type and offset
of selected members of a C structure. These can be read by
getmember() and set by setmember() (except if their READONLY flag
is set). The array must be terminated with an entry whose name
pointer is NULL. */
struct memberlist {
char *name;
int type;
int offset;
int readonly;
};
/* Types */
#define T_SHORT 0
#define T_INT 1
#define T_LONG 2
#define T_FLOAT 3
#define T_DOUBLE 4
#define T_STRING 5
#define T_OBJECT 6
/* Readonly flag */
#define READONLY 1
#define RO READONLY /* Shorthand */
object *getmember PROTO((char *, struct memberlist *, char *));
int setmember PROTO((char *, struct memberlist *, char *, object *));

View File

@ -3,4 +3,4 @@
object *sysget PROTO((char *));
int sysset PROTO((char *, object *));
FILE *sysgetfile PROTO((char *, FILE *));
void initsys PROTO((int, char **));
void initsys PROTO((void));

6
Include/traceback.h Normal file
View File

@ -0,0 +1,6 @@
/* Traceback interface */
int tb_here PROTO((struct _frame *, int, int));
object *tb_fetch PROTO((void));
int tb_store PROTO((object *));
int tb_print PROTO((object *, FILE *));

View File

@ -14,6 +14,11 @@ inserted in the tuple. Similarly, gettupleitem does not increment the
returned item's reference count.
*/
typedef struct {
OB_VARHEAD
object *ob_item[1];
} tupleobject;
extern typeobject Tupletype;
#define is_tupleobject(op) ((op)->ob_type == &Tupletype)
@ -22,3 +27,6 @@ extern object *newtupleobject PROTO((int size));
extern int gettuplesize PROTO((object *));
extern object *gettupleitem PROTO((object *, int));
extern int settupleitem PROTO((object *, int, object *));
/* Macro, trading safety for speed */
#define GETTUPLEITEM(op, i) ((op)->ob_item[i])

View File

@ -33,8 +33,8 @@ digits = '0123456789'
#
def getnum(s):
n = ''
while s[:1] in digits:
n = n + s[:1]
while s and s[0] in digits:
n = n + s[0]
s = s[1:]
return n, s

View File

@ -25,24 +25,13 @@ Each definition must be contained on one line:
N*retval
*/
#include <stdio.h>
#include <gl.h>
#include <device.h>
#include "PROTO.h"
#include "object.h"
#include "intobject.h"
#include "floatobject.h"
#include "listobject.h"
#include "tupleobject.h"
#include "dictobject.h"
#include "methodobject.h"
#include "moduleobject.h"
#include "objimpl.h"
#include "allobjects.h"
#include "import.h"
#include "sigtype.h"
#include "modsupport.h"
#include "cgensupport.h"
#include "errors.h"
/*
Some stubs are too complicated for the stub generator.

View File

@ -1,20 +1,11 @@
/* Math module -- standard C math library functions, pi and e */
#include <stdio.h>
#include <math.h>
#include "allobjects.h"
#include "PROTO.h"
#include "object.h"
#include "intobject.h"
#include "tupleobject.h"
#include "floatobject.h"
#include "dictobject.h"
#include "methodobject.h"
#include "moduleobject.h"
#include "objimpl.h"
#include "import.h"
#include "modsupport.h"
#include <math.h>
static int
getdoublearg(args, px)
register object *args;

View File

@ -1,6 +1,5 @@
/* POSIX module implementation */
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <setjmp.h>
@ -14,20 +13,8 @@
#include <sys/dir.h>
#endif
#include "PROTO.h"
#include "object.h"
#include "intobject.h"
#include "stringobject.h"
#include "tupleobject.h"
#include "listobject.h"
#include "dictobject.h"
#include "methodobject.h"
#include "moduleobject.h"
#include "objimpl.h"
#include "import.h"
#include "sigtype.h"
#include "allobjects.h"
#include "modsupport.h"
#include "errors.h"
extern char *strerror PROTO((int));
@ -140,7 +127,6 @@ posix_do_stat(self, args, statfunc)
v = newtupleobject(10);
if (v == NULL)
return NULL;
errno = 0;
#define SET(i, st_member) settupleitem(v, i, newintobject((long)st.st_member))
SET(0, st_mode);
SET(1, st_ino);
@ -153,9 +139,9 @@ posix_do_stat(self, args, statfunc)
SET(8, st_mtime);
SET(9, st_ctime);
#undef SET
if (errno != 0) {
if (err_occurred()) {
DECREF(v);
return err_nomem();
return NULL;
}
return v;
}
@ -335,6 +321,8 @@ posix_utimes(self, args)
#ifdef NO_GETCWD
#include "errno.h"
/* Quick hack to get posix.getcwd() working for pure BSD 4.3 */
/* XXX This assumes MAXPATHLEN = 1024 !!! */

View File

@ -38,22 +38,11 @@
XXX more?
*/
#include <stdio.h>
#include "stdwin.h"
#include "allobjects.h"
#include "PROTO.h"
#include "object.h"
#include "intobject.h"
#include "stringobject.h"
#include "tupleobject.h"
#include "dictobject.h"
#include "methodobject.h"
#include "moduleobject.h"
#include "objimpl.h"
#include "import.h"
#include "modsupport.h"
#include "errors.h"
#include "stdwin.h"
/* Window and menu object types declared here because of forward references */

View File

@ -1,6 +1,11 @@
/* Time module */
#include <stdio.h>
#include "allobjects.h"
#include "modsupport.h"
#include "sigtype.h"
#include <signal.h>
#include <setjmp.h>
@ -11,18 +16,6 @@ typedef unsigned long time_t;
extern time_t time();
#endif /* !__STDC__ */
#include "PROTO.h"
#include "object.h"
#include "intobject.h"
#include "dictobject.h"
#include "methodobject.h"
#include "moduleobject.h"
#include "objimpl.h"
#include "import.h"
#include "sigtype.h"
#include "modsupport.h"
#include "errors.h"
/* Time methods */

View File

@ -1,28 +1,17 @@
/* Class object implementation */
#include <stdio.h>
#include "allobjects.h"
#include "PROTO.h"
#include "node.h"
#include "object.h"
#include "stringobject.h"
#include "tupleobject.h"
#include "dictobject.h"
#include "funcobject.h"
#include "classobject.h"
#include "objimpl.h"
#include "errors.h"
#include "structmember.h"
typedef struct {
OB_HEAD
node *cl_tree; /* The entire classdef parse tree */
object *cl_bases; /* A tuple */
object *cl_methods; /* A dictionary */
} classobject;
object *
newclassobject(tree, bases, methods)
node *tree;
newclassobject(bases, methods)
object *bases; /* NULL or tuple of classobjects! */
object *methods;
{
@ -30,7 +19,6 @@ newclassobject(tree, bases, methods)
op = NEWOBJ(classobject, &Classtype);
if (op == NULL)
return NULL;
op->cl_tree = tree;
if (bases != NULL)
INCREF(bases);
op->cl_bases = bases;
@ -70,6 +58,7 @@ class_getattr(op, name)
v = class_getattr(gettupleitem(op->cl_bases, i), name);
if (v != NULL)
return v;
err_clear();
}
}
err_setstr(NameError, name);
@ -242,6 +231,22 @@ classmethodgetself(cm)
/* Class method methods */
#define OFF(x) offsetof(classmethodobject, x)
static struct memberlist classmethod_memberlist[] = {
{"cm_func", T_OBJECT, OFF(cm_func)},
{"cm_self", T_OBJECT, OFF(cm_self)},
{NULL} /* Sentinel */
};
static object *
classmethod_getattr(cm, name)
register classmethodobject *cm;
char *name;
{
return getmember((char *)cm, classmethod_memberlist, name);
}
static void
classmethod_dealloc(cm)
register classmethodobject *cm;
@ -259,7 +264,7 @@ typeobject Classmethodtype = {
0,
classmethod_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
classmethod_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/

View File

@ -2,19 +2,16 @@
/* XXX This should become a built-in module 'io'. It should support more
functionality, better exception handling for invalid calls, etc.
(Especially reading on a write-only file or vice versa!)
It should also cooperate with posix to support popen(), which should
share most code but have a special close function. */
#include <stdio.h>
#include "allobjects.h"
#include "PROTO.h"
#include "object.h"
#include "stringobject.h"
#include "intobject.h"
#include "fileobject.h"
#include "methodobject.h"
#include "objimpl.h"
#include "errors.h"
#include "errno.h"
#ifndef errno
extern int errno;
#endif
typedef struct {
OB_HEAD
@ -29,7 +26,7 @@ getfilefile(f)
object *f;
{
if (!is_fileobject(f)) {
errno = EBADF;
err_badcall();
return NULL;
}
return ((fileobject *)f)->f_fp;
@ -49,7 +46,6 @@ newopenfileobject(fp, name, mode)
f->f_mode = newstringobject(mode);
if (f->f_name == NULL || f->f_mode == NULL) {
DECREF(f);
errno = ENOMEM;
return NULL;
}
f->f_fp = fp;
@ -67,6 +63,7 @@ newfileobject(name, mode)
return NULL;
if ((f->f_fp = fopen(name, mode)) == NULL) {
DECREF(f);
err_errno(RuntimeError); /* XXX Should use another error */
return NULL;
}
return (object *)f;
@ -75,7 +72,7 @@ newfileobject(name, mode)
/* Methods */
static void
filedealloc(f)
file_dealloc(f)
fileobject *f;
{
if (f->f_fp != NULL)
@ -88,7 +85,7 @@ filedealloc(f)
}
static void
fileprint(f, fp, flags)
file_print(f, fp, flags)
fileobject *f;
FILE *fp;
int flags;
@ -101,11 +98,11 @@ fileprint(f, fp, flags)
}
static object *
filerepr(f)
file_repr(f)
fileobject *f;
{
char buf[300];
/* XXX This differs from fileprint if the filename contains
/* XXX This differs from file_print if the filename contains
quotes or other funny characters. */
sprintf(buf, "<%s file '%.256s', mode '%.10s'>",
f->f_fp == NULL ? "closed" : "open",
@ -115,12 +112,12 @@ filerepr(f)
}
static object *
fileclose(f, args)
file_close(f, args)
fileobject *f;
object *args;
{
if (args != NULL) {
errno = EINVAL;
err_badarg();
return NULL;
}
if (f->f_fp != NULL) {
@ -132,30 +129,28 @@ fileclose(f, args)
}
static object *
fileread(f, args)
file_read(f, args)
fileobject *f;
object *args;
{
int n;
object *v;
if (f->f_fp == NULL) {
errno = EBADF;
err_badarg();
return NULL;
}
if (args == NULL || !is_intobject(args)) {
errno = EINVAL;
err_badarg();
return NULL;
}
n = getintvalue(args);
if (n < 0) {
errno = EDOM;
err_badarg();
return NULL;
}
v = newsizedstringobject((char *)NULL, n);
if (v == NULL) {
errno = ENOMEM;
if (v == NULL)
return NULL;
}
n = fread(getstringvalue(v), 1, n, f->f_fp);
/* EOF is reported as an empty string */
/* XXX should detect real I/O errors? */
@ -166,14 +161,14 @@ fileread(f, args)
/* XXX Should this be unified with raw_input()? */
static object *
filereadline(f, args)
file_readline(f, args)
fileobject *f;
object *args;
{
int n;
object *v;
if (f->f_fp == NULL) {
errno = EBADF;
err_badarg();
return NULL;
}
if (args == NULL) {
@ -181,21 +176,23 @@ filereadline(f, args)
}
else if (is_intobject(args)) {
n = getintvalue(args);
if (n < 0 || n > 0x7fff /*XXX*/ ) {
errno = EDOM;
if (n < 0) {
err_badarg();
return NULL;
}
}
else {
errno = EINVAL;
err_badarg();
return NULL;
}
v = newsizedstringobject((char *)NULL, n);
if (v == NULL) {
errno = ENOMEM;
if (v == NULL)
return NULL;
}
if (fgets(getstringvalue(v), n+1, f->f_fp) == NULL) {
#ifndef THINK_C
/* XXX Think C reads n characters, others read n-1 characters... */
n = n+1;
#endif
if (fgets(getstringvalue(v), n, f->f_fp) == NULL) {
/* EOF is reported as an empty string */
/* XXX should detect real I/O errors? */
n = 0;
@ -208,17 +205,17 @@ filereadline(f, args)
}
static object *
filewrite(f, args)
file_write(f, args)
fileobject *f;
object *args;
{
int n, n2;
if (f->f_fp == NULL) {
errno = EBADF;
err_badarg();
return NULL;
}
if (args == NULL || !is_stringobject(args)) {
errno = EINVAL;
err_badarg();
return NULL;
}
errno = 0;
@ -226,36 +223,27 @@ filewrite(f, args)
if (n2 != n) {
if (errno == 0)
errno = EIO;
err_errno(RuntimeError);
return NULL;
}
INCREF(None);
return None;
}
static struct methodlist {
char *ml_name;
method ml_meth;
} filemethods[] = {
{"write", filewrite},
{"read", fileread},
{"readline", filereadline},
{"close", fileclose},
static struct methodlist file_methods[] = {
{"write", file_write},
{"read", file_read},
{"readline", file_readline},
{"close", file_close},
{NULL, NULL} /* sentinel */
};
static object *
filegetattr(f, name)
file_getattr(f, name)
fileobject *f;
char *name;
{
struct methodlist *ml = filemethods;
for (; ml->ml_name != NULL; ml++) {
if (strcmp(name, ml->ml_name) == 0)
return newmethodobject(ml->ml_name, ml->ml_meth,
(object *)f);
}
err_setstr(NameError, name);
return NULL;
return findmethod(file_methods, (object *)f, name);
}
typeobject Filetype = {
@ -264,10 +252,10 @@ typeobject Filetype = {
"file",
sizeof(fileobject),
0,
filedealloc, /*tp_dealloc*/
fileprint, /*tp_print*/
filegetattr, /*tp_getattr*/
file_dealloc, /*tp_dealloc*/
file_print, /*tp_print*/
file_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
filerepr, /*tp_repr*/
file_repr, /*tp_repr*/
};

View File

@ -3,16 +3,10 @@
/* XXX There should be overflow checks here, but it's hard to check
for any kind of float exception without losing portability. */
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include "allobjects.h"
#include "PROTO.h"
#include "object.h"
#include "floatobject.h"
#include "stringobject.h"
#include "objimpl.h"
#include "errors.h"
#include <ctype.h>
#include <math.h>
#ifndef THINK_C
extern double fmod PROTO((double, double));

132
Objects/frameobject.c Normal file
View File

@ -0,0 +1,132 @@
/* Frame object implementation */
#include "allobjects.h"
#include "compile.h"
#include "frameobject.h"
#include "opcode.h"
#include "structmember.h"
#define OFF(x) offsetof(frameobject, x)
static struct memberlist frame_memberlist[] = {
{"f_back", T_OBJECT, OFF(f_back)},
{"f_code", T_OBJECT, OFF(f_code)},
{"f_globals", T_OBJECT, OFF(f_globals)},
{"f_locals", T_OBJECT, OFF(f_locals)},
{NULL} /* Sentinel */
};
static object *
frame_getattr(f, name)
frameobject *f;
char *name;
{
return getmember((char *)f, frame_memberlist, name);
}
static void
frame_dealloc(f)
frameobject *f;
{
XDECREF(f->f_back);
XDECREF(f->f_code);
XDECREF(f->f_globals);
XDECREF(f->f_locals);
XDEL(f->f_valuestack);
XDEL(f->f_blockstack);
DEL(f);
}
typeobject Frametype = {
OB_HEAD_INIT(&Typetype)
0,
"frame",
sizeof(frameobject),
0,
frame_dealloc, /*tp_dealloc*/
0, /*tp_print*/
frame_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
};
frameobject *
newframeobject(back, code, globals, locals, nvalues, nblocks)
frameobject *back;
codeobject *code;
object *globals;
object *locals;
int nvalues;
int nblocks;
{
frameobject *f;
if ((back != NULL && !is_frameobject(back)) ||
code == NULL || !is_codeobject(code) ||
globals == NULL || !is_dictobject(globals) ||
locals == NULL || !is_dictobject(locals) ||
nvalues < 0 || nblocks < 0) {
err_badcall();
return NULL;
}
f = NEWOBJ(frameobject, &Frametype);
if (f != NULL) {
if (back)
INCREF(back);
f->f_back = back;
INCREF(code);
f->f_code = code;
INCREF(globals);
f->f_globals = globals;
INCREF(locals);
f->f_locals = locals;
f->f_valuestack = NEW(object *, nvalues+1);
f->f_blockstack = NEW(block, nblocks+1);
f->f_nvalues = nvalues;
f->f_nblocks = nblocks;
f->f_iblock = 0;
if (f->f_valuestack == NULL || f->f_blockstack == NULL) {
err_nomem();
DECREF(f);
f = NULL;
}
}
return f;
}
/* Block management */
void
setup_block(f, type, handler, level)
frameobject *f;
int type;
int handler;
int level;
{
block *b;
if (f->f_iblock >= f->f_nblocks) {
fprintf(stderr, "XXX block stack overflow\n");
abort();
}
b = &f->f_blockstack[f->f_iblock++];
b->b_type = type;
b->b_level = level;
b->b_handler = handler;
}
block *
pop_block(f)
frameobject *f;
{
block *b;
if (f->f_iblock <= 0) {
fprintf(stderr, "XXX block stack underflow\n");
abort();
}
b = &f->f_blockstack[--f->f_iblock];
return b;
}

View File

@ -1,11 +1,8 @@
/* Function object implementation */
#include <stdio.h>
#include "allobjects.h"
#include "PROTO.h"
#include "object.h"
#include "funcobject.h"
#include "objimpl.h"
#include "structmember.h"
typedef struct {
OB_HEAD
@ -52,8 +49,24 @@ getfuncglobals(op)
/* Methods */
#define OFF(x) offsetof(funcobject, x)
static struct memberlist func_memberlist[] = {
{"func_code", T_OBJECT, OFF(func_code)},
{"func_globals",T_OBJECT, OFF(func_globals)},
{NULL} /* Sentinel */
};
static object *
func_getattr(op, name)
funcobject *op;
char *name;
{
return getmember((char *)op, func_memberlist, name);
}
static void
funcdealloc(op)
func_dealloc(op)
funcobject *op;
{
DECREF(op->func_code);
@ -67,9 +80,9 @@ typeobject Functype = {
"function",
sizeof(funcobject),
0,
funcdealloc, /*tp_dealloc*/
func_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
func_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/

View File

@ -1,19 +1,14 @@
/* Integer object implementation */
#include <stdio.h>
#include "PROTO.h"
#include "object.h"
#include "intobject.h"
#include "stringobject.h"
#include "objimpl.h"
#include "errors.h"
#include "allobjects.h"
/* Standard Booleans */
intobject FalseObject = {
OB_HEAD_INIT(&Inttype)
0
};
intobject TrueObject = {
OB_HEAD_INIT(&Inttype)
1
@ -33,21 +28,58 @@ err_zdiv()
return NULL;
}
/* Integers are quite normal objects, to make object handling uniform.
(Using odd pointers to represent integers would save much space
but require extra checks for this special case throughout the code.)
Since, a typical Python program spends much of its time allocating
and deallocating integers, these operations should be very fast.
Therefore we use a dedicated allocation scheme with a much lower
overhead (in space and time) than straight malloc(): a simple
dedicated free list, filled when necessary with memory from malloc().
*/
#define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */
#define N_INTOBJECTS (BLOCK_SIZE / sizeof(intobject))
static intobject *
fill_free_list()
{
intobject *p, *q;
p = NEW(intobject, N_INTOBJECTS);
if (p == NULL)
return (intobject *)err_nomem();
q = p + N_INTOBJECTS;
while (--q > p)
*(intobject **)q = q-1;
*(intobject **)q = NULL;
return p + N_INTOBJECTS - 1;
}
static intobject *free_list = NULL;
object *
newintobject(ival)
long ival;
{
/* For efficiency, this code is copied from newobject() */
register intobject *op = (intobject *) malloc(sizeof(intobject));
if (op == NULL) {
err_nomem();
register intobject *v;
if (free_list == NULL) {
if ((free_list = fill_free_list()) == NULL)
return NULL;
}
else {
NEWREF(op);
op->ob_type = &Inttype;
op->ob_ival = ival;
}
return (object *) op;
v = free_list;
free_list = *(intobject **)free_list;
NEWREF(v);
v->ob_type = &Inttype;
v->ob_ival = ival;
return (object *) v;
}
static void
int_dealloc(v)
intobject *v;
{
*(intobject **)v = free_list;
free_list = v;
}
long
@ -65,7 +97,7 @@ getintvalue(op)
/* Methods */
static void
intprint(v, fp, flags)
int_print(v, fp, flags)
intobject *v;
FILE *fp;
int flags;
@ -74,7 +106,7 @@ intprint(v, fp, flags)
}
static object *
intrepr(v)
int_repr(v)
intobject *v;
{
char buf[20];
@ -83,7 +115,7 @@ intrepr(v)
}
static int
intcompare(v, w)
int_compare(v, w)
intobject *v, *w;
{
register long i = v->ob_ival;
@ -92,7 +124,7 @@ intcompare(v, w)
}
static object *
intadd(v, w)
int_add(v, w)
intobject *v;
register object *w;
{
@ -110,7 +142,7 @@ intadd(v, w)
}
static object *
intsub(v, w)
int_sub(v, w)
intobject *v;
register object *w;
{
@ -128,7 +160,7 @@ intsub(v, w)
}
static object *
intmul(v, w)
int_mul(v, w)
intobject *v;
register object *w;
{
@ -147,7 +179,7 @@ intmul(v, w)
}
static object *
intdiv(v, w)
int_div(v, w)
intobject *v;
register object *w;
{
@ -161,7 +193,7 @@ intdiv(v, w)
}
static object *
intrem(v, w)
int_rem(v, w)
intobject *v;
register object *w;
{
@ -175,7 +207,7 @@ intrem(v, w)
}
static object *
intpow(v, w)
int_pow(v, w)
intobject *v;
register object *w;
{
@ -203,7 +235,7 @@ intpow(v, w)
}
static object *
intneg(v)
int_neg(v)
intobject *v;
{
register long a, x;
@ -215,7 +247,7 @@ intneg(v)
}
static object *
intpos(v)
int_pos(v)
intobject *v;
{
INCREF(v);
@ -223,14 +255,14 @@ intpos(v)
}
static number_methods int_as_number = {
intadd, /*tp_add*/
intsub, /*tp_subtract*/
intmul, /*tp_multiply*/
intdiv, /*tp_divide*/
intrem, /*tp_remainder*/
intpow, /*tp_power*/
intneg, /*tp_negate*/
intpos, /*tp_plus*/
int_add, /*tp_add*/
int_sub, /*tp_subtract*/
int_mul, /*tp_multiply*/
int_div, /*tp_divide*/
int_rem, /*tp_remainder*/
int_pow, /*tp_power*/
int_neg, /*tp_negate*/
int_pos, /*tp_plus*/
};
typeobject Inttype = {
@ -239,12 +271,12 @@ typeobject Inttype = {
"int",
sizeof(intobject),
0,
free, /*tp_dealloc*/
intprint, /*tp_print*/
int_dealloc, /*tp_dealloc*/
int_print, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
intcompare, /*tp_compare*/
intrepr, /*tp_repr*/
int_compare, /*tp_compare*/
int_repr, /*tp_repr*/
&int_as_number, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/

View File

@ -1,22 +1,6 @@
/* List object implementation */
#include <stdio.h>
#include "PROTO.h"
#include "object.h"
#include "intobject.h"
#include "stringobject.h"
#include "tupleobject.h"
#include "methodobject.h"
#include "listobject.h"
#include "objimpl.h"
#include "modsupport.h"
#include "errors.h"
typedef struct {
OB_VARHEAD
object **ob_item;
} listobject;
#include "allobjects.h"
object *
newlistobject(size)

View File

@ -1,15 +1,8 @@
/* Method object implementation */
#include <stdio.h>
#include "allobjects.h"
#include "PROTO.h"
#include "object.h"
#include "node.h"
#include "stringobject.h"
#include "methodobject.h"
#include "objimpl.h"
#include "token.h"
#include "errors.h"
typedef struct {
OB_HEAD
@ -75,11 +68,10 @@ meth_print(m, fp, flags)
int flags;
{
if (m->m_self == NULL)
fprintf(fp, "<%s method>", m->m_name);
fprintf(fp, "<built-in function '%s'>", m->m_name);
else
fprintf(fp, "<%s method of %s object at %lx>",
m->m_name, m->m_self->ob_type->tp_name,
(long)m->m_self);
fprintf(fp, "<built-in method '%s' of some %s object>",
m->m_name, m->m_self->ob_type->tp_name);
}
static object *
@ -88,11 +80,11 @@ meth_repr(m)
{
char buf[200];
if (m->m_self == NULL)
sprintf(buf, "<%.80s method>", m->m_name);
sprintf(buf, "<built-in function '%.80s'>", m->m_name);
else
sprintf(buf, "<%.80s method of %.80s object at %lx>",
m->m_name, m->m_self->ob_type->tp_name,
(long)m->m_self);
sprintf(buf,
"<built-in method '%.80s' of some %.80s object>",
m->m_name, m->m_self->ob_type->tp_name);
return newstringobject(buf);
}
@ -112,3 +104,20 @@ typeobject Methodtype = {
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
};
/* Find a method in a module's method table.
Usually called from an object's getattr method. */
object *
findmethod(ml, op, name)
struct methodlist *ml;
object *op;
char *name;
{
for (; ml->ml_name != NULL; ml++) {
if (strcmp(name, ml->ml_name) == 0)
return newmethodobject(ml->ml_name, ml->ml_meth, op);
}
err_setstr(NameError, name);
return NULL;
}

View File

@ -1,14 +1,6 @@
/* Module object implementation */
#include <stdio.h>
#include "PROTO.h"
#include "object.h"
#include "stringobject.h"
#include "dictobject.h"
#include "moduleobject.h"
#include "objimpl.h"
#include "errors.h"
#include "allobjects.h"
typedef struct {
OB_HEAD
@ -37,31 +29,12 @@ getmoduledict(m)
object *m;
{
if (!is_moduleobject(m)) {
err_badarg();
err_badcall();
return NULL;
}
return ((moduleobject *)m) -> md_dict;
}
int
setmoduledict(m, v)
object *m;
object *v;
{
if (!is_moduleobject(m)) {
err_badarg();
return -1;
}
if (!is_dictobject(v)) {
err_badarg();
return -1;
}
DECREF(((moduleobject *)m) -> md_dict);
INCREF(v);
((moduleobject *)m) -> md_dict = v;
return 0;
}
char *
getmodulename(m)
object *m;
@ -76,7 +49,7 @@ getmodulename(m)
/* Methods */
static void
moduledealloc(m)
module_dealloc(m)
moduleobject *m;
{
if (m->md_name != NULL)
@ -87,33 +60,37 @@ moduledealloc(m)
}
static void
moduleprint(m, fp, flags)
module_print(m, fp, flags)
moduleobject *m;
FILE *fp;
int flags;
{
fprintf(fp, "<module %s>", getstringvalue(m->md_name));
fprintf(fp, "<module '%s'>", getstringvalue(m->md_name));
}
static object *
modulerepr(m)
module_repr(m)
moduleobject *m;
{
char buf[100];
sprintf(buf, "<module %.80s>", getstringvalue(m->md_name));
sprintf(buf, "<module '%.80s'>", getstringvalue(m->md_name));
return newstringobject(buf);
}
static object *
modulegetattr(m, name)
module_getattr(m, name)
moduleobject *m;
char *name;
{
object *res;
if (strcmp(name, "__dict") == 0) {
if (strcmp(name, "__dict__") == 0) {
INCREF(m->md_dict);
return m->md_dict;
}
if (strcmp(name, "__name__") == 0) {
INCREF(m->md_name);
return m->md_name;
}
res = dictlookup(m->md_dict, name);
if (res == NULL)
err_setstr(NameError, name);
@ -123,15 +100,13 @@ modulegetattr(m, name)
}
static int
modulesetattr(m, name, v)
module_setattr(m, name, v)
moduleobject *m;
char *name;
object *v;
{
if (strcmp(name, "__dict") == 0) {
/* Can't allow assignment to __dict, it would screw up
module's functions which still use the old dictionary. */
err_setstr(NameError, "__dict is a reserved member name");
if (strcmp(name, "__dict__") == 0 || strcmp(name, "__name__") == 0) {
err_setstr(NameError, "can't assign to reserved member name");
return NULL;
}
if (v == NULL)
@ -146,10 +121,10 @@ typeobject Moduletype = {
"module", /*tp_name*/
sizeof(moduleobject), /*tp_size*/
0, /*tp_itemsize*/
moduledealloc, /*tp_dealloc*/
moduleprint, /*tp_print*/
modulegetattr, /*tp_getattr*/
modulesetattr, /*tp_setattr*/
0, /*tp_compare*/
modulerepr, /*tp_repr*/
module_dealloc, /*tp_dealloc*/
module_print, /*tp_print*/
module_getattr, /*tp_getattr*/
module_setattr, /*tp_setattr*/
0, /*tp_compare*/
module_repr, /*tp_repr*/
};

View File

@ -1,16 +1,14 @@
/* Object implementation; and 'noobject' implementation */
/* Generic object operations; and implementation of None (NoObject) */
#include <stdio.h>
#include "allobjects.h"
#include "PROTO.h"
#include "object.h"
#include "stringobject.h"
#include "objimpl.h"
#include "errors.h"
#ifdef REF_DEBUG
long ref_total;
#endif
int StopPrint; /* Flag to indicate printing must be stopped */
/* Object allocation routines used by NEWOBJ and NEWVAROBJ macros */
/* Object allocation routines used by NEWOBJ and NEWVAROBJ macros.
These are used by the individual routines for object creation.
Do not call them otherwise, they do not initialize the object! */
object *
newobject(tp)
@ -43,6 +41,8 @@ newvarobject(tp, size)
#endif
int StopPrint; /* Flag to indicate printing must be stopped */
static int prlevel;
void
@ -52,6 +52,7 @@ printobject(op, fp, flags)
int flags;
{
/* Hacks to make printing a long or recursive object interruptible */
/* XXX Interrupts should leave a more permanent error */
prlevel++;
if (!StopPrint && intrcheck()) {
fprintf(fp, "\n[print interrupted]\n");
@ -61,12 +62,16 @@ printobject(op, fp, flags)
if (op == NULL) {
fprintf(fp, "<nil>");
}
else if (op->ob_type->tp_print == NULL) {
fprintf(fp, "<%s object at %lx>",
op->ob_type->tp_name, (long)op);
}
else {
(*op->ob_type->tp_print)(op, fp, flags);
if (op->ob_refcnt <= 0)
fprintf(fp, "(refcnt %d):", op->ob_refcnt);
if (op->ob_type->tp_print == NULL) {
fprintf(fp, "<%s object at %lx>",
op->ob_type->tp_name, (long)op);
}
else {
(*op->ob_type->tp_print)(op, fp, flags);
}
}
}
prlevel--;
@ -78,17 +83,16 @@ object *
reprobject(v)
object *v;
{
object *w;
object *w = NULL;
/* Hacks to make converting a long or recursive object interruptible */
prlevel++;
if (!StopPrint && intrcheck()) {
StopPrint = 1;
w = NULL;
err_set(KeyboardInterrupt);
}
if (!StopPrint) {
if (v == NULL) {
w = newstringobject("<nil>");
w = newstringobject("<NULL>");
}
else if (v->ob_type->tp_repr == NULL) {
char buf[100];
@ -99,6 +103,10 @@ reprobject(v)
else {
w = (*v->ob_type->tp_repr)(v);
}
if (StopPrint) {
XDECREF(w);
w = NULL;
}
}
prlevel--;
if (prlevel == 0)
@ -124,30 +132,76 @@ cmpobject(v, w)
return ((*tp->tp_compare)(v, w));
}
object *
getattr(v, name)
object *v;
char *name;
{
if (v->ob_type->tp_getattr == NULL) {
err_setstr(TypeError, "attribute-less object");
return NULL;
}
else {
return (*v->ob_type->tp_getattr)(v, name);
}
}
int
setattr(v, name, w)
object *v;
char *name;
object *w;
{
if (v->ob_type->tp_setattr == NULL) {
if (v->ob_type->tp_getattr == NULL)
err_setstr(TypeError, "attribute-less object");
else
err_setstr(TypeError, "object has read-only attributes");
return NULL;
}
else {
return (*v->ob_type->tp_setattr)(v, name, w);
}
}
/*
NoObject is usable as a non-NULL undefined value, used by the macro None.
There is (and should be!) no way to create other objects of this type,
so there is exactly one.
so there is exactly one (which is indestructible, by the way).
*/
static void
noprint(op, fp, flags)
none_print(op, fp, flags)
object *op;
FILE *fp;
int flags;
{
fprintf(fp, "<no value>");
fprintf(fp, "None");
}
static object *
none_repr(op)
object *op;
{
return newstringobject("None");
}
static typeobject Notype = {
OB_HEAD_INIT(&Typetype)
0,
"novalue",
"None",
0,
0,
0, /*tp_dealloc*/ /*never called*/
noprint, /*tp_print*/
none_print, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
none_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
};
object NoObject = {
@ -170,15 +224,30 @@ NEWREF(op)
refchain._ob_next = op;
}
DELREF(op)
object *op;
UNREF(op)
register object *op;
{
register object *p;
if (op->ob_refcnt < 0) {
fprintf(stderr, "negative refcnt\n");
fprintf(stderr, "UNREF negative refcnt\n");
abort();
}
for (p = refchain._ob_next; p != &refchain; p = p->_ob_next) {
if (p == op)
break;
}
if (p == &refchain) { /* Not found */
fprintf(stderr, "UNREF unknown object\n");
abort();
}
op->_ob_next->_ob_prev = op->_ob_prev;
op->_ob_prev->_ob_next = op->_ob_next;
}
DELREF(op)
object *op;
{
UNREF(op);
(*(op)->ob_type->tp_dealloc)(op);
}

View File

@ -1,13 +1,6 @@
/* String object implementation */
#include <stdio.h>
#include "PROTO.h"
#include "object.h"
#include "stringobject.h"
#include "intobject.h"
#include "objimpl.h"
#include "errors.h"
#include "allobjects.h"
object *
newsizedstringobject(str, size)

View File

@ -1,19 +1,6 @@
/* Tuple object implementation */
#include <stdio.h>
#include "PROTO.h"
#include "object.h"
#include "stringobject.h"
#include "tupleobject.h"
#include "intobject.h"
#include "objimpl.h"
#include "errors.h"
typedef struct {
OB_VARHEAD
object *ob_item[1];
} tupleobject;
#include "allobjects.h"
object *
newtupleobject(size)

View File

@ -1,16 +1,11 @@
/* Type object implementation */
#include <stdio.h>
#include "PROTO.h"
#include "object.h"
#include "stringobject.h"
#include "objimpl.h"
#include "allobjects.h"
/* Type object implementation */
static void
typeprint(v, fp, flags)
type_print(v, fp, flags)
typeobject *v;
FILE *fp;
int flags;
@ -19,7 +14,7 @@ typeprint(v, fp, flags)
}
static object *
typerepr(v)
type_repr(v)
typeobject *v;
{
char buf[100];
@ -27,21 +22,16 @@ typerepr(v)
return newstringobject(buf);
}
typedef struct {
OB_HEAD
long ob_ival;
} intobject;
typeobject Typetype = {
OB_HEAD_INIT(&Typetype)
0, /* Number of items for varobject */
"type", /* Name of this type */
sizeof(typeobject), /* Basic object size */
0, /* Item size for varobject */
0, /*tp_dealloc*/
typeprint, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
typerepr, /*tp_repr*/
0, /*tp_dealloc*/
type_print, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
type_repr, /*tp_repr*/
};

View File

@ -1,11 +1,52 @@
/* Parser accelerator module */
#include <stdio.h>
/* The parser as originally conceived had disappointing performance.
This module does some precomputation that speeds up the selection
of a DFA based upon a token, turning a search through an array
into a simple indexing operation. The parser now cannot work
without the accelerators installed. Note that the accelerators
are installed dynamically when the parser is initialized, they
are not part of the static data structure written on graminit.[ch]
by the parser generator. */
#include "PROTO.h"
#include "pgenheaders.h"
#include "grammar.h"
#include "token.h"
#include "malloc.h"
#include "parser.h"
/* Forward references */
static void fixdfa PROTO((grammar *, dfa *));
static void fixstate PROTO((grammar *, dfa *, state *));
void
addaccelerators(g)
grammar *g;
{
dfa *d;
int i;
#ifdef DEBUG
printf("Adding parser accellerators ...\n");
#endif
d = g->g_dfa;
for (i = g->g_ndfas; --i >= 0; d++)
fixdfa(g, d);
g->g_accel = 1;
#ifdef DEBUG
printf("Done.\n");
#endif
}
static void
fixdfa(g, d)
grammar *g;
dfa *d;
{
state *s;
int j;
s = d->d_state;
for (j = 0; j < d->d_nstates; j++, s++)
fixstate(g, d, s);
}
static void
fixstate(g, d, s)
@ -69,33 +110,3 @@ fixstate(g, d, s)
}
DEL(accel);
}
static void
fixdfa(g, d)
grammar *g;
dfa *d;
{
state *s;
int j;
s = d->d_state;
for (j = 0; j < d->d_nstates; j++, s++)
fixstate(g, d, s);
}
void
addaccelerators(g)
grammar *g;
{
dfa *d;
int i;
#ifdef DEBUG
printf("Adding parser accellerators ...\n");
#endif
d = g->g_dfa;
for (i = g->g_ndfas; --i >= 0; d++)
fixdfa(g, d);
g->g_accel = 1;
#ifdef DEBUG
printf("Done.\n");
#endif
}

View File

@ -1,7 +1,6 @@
/* Bitset primitives */
/* Bitset primitives used by the parser generator */
#include "PROTO.h"
#include "malloc.h"
#include "pgenheaders.h"
#include "bitset.h"
bitset

View File

@ -1,14 +1,29 @@
/* Computation of FIRST stets */
#include <stdio.h>
#include "PROTO.h"
#include "malloc.h"
#include "pgenheaders.h"
#include "grammar.h"
#include "token.h"
extern int debugging;
/* Forward */
static void calcfirstset PROTO((grammar *, dfa *));
void
addfirstsets(g)
grammar *g;
{
int i;
dfa *d;
printf("Adding FIRST sets ...\n");
for (i = 0; i < g->g_ndfas; i++) {
d = &g->g_dfa[i];
if (d->d_first == NULL)
calcfirstset(g, d);
}
}
static void
calcfirstset(g, d)
grammar *g;
@ -92,18 +107,3 @@ calcfirstset(g, d)
printf(" }\n");
}
}
void
addfirstsets(g)
grammar *g;
{
int i;
dfa *d;
printf("Adding FIRST sets ...\n");
for (i = 0; i < g->g_ndfas; i++) {
d = &g->g_dfa[i];
if (d->d_first == NULL)
calcfirstset(g, d);
}
}

View File

@ -1,10 +1,9 @@
/* Grammar implementation */
#include <stdio.h>
#include "pgenheaders.h"
#include <ctype.h>
#include "PROTO.h"
#include "malloc.h"
#include "assert.h"
#include "token.h"
#include "grammar.h"
@ -127,6 +126,21 @@ findlabel(ll, type, str)
abort();
}
/* Forward */
static void translabel PROTO((grammar *, label *));
void
translatelabels(g)
grammar *g;
{
int i;
printf("Translating labels ...\n");
/* Don't translate EMPTY */
for (i = EMPTY+1; i < g->g_ll.ll_nlabels; i++)
translabel(g, &g->g_ll.ll_label[i]);
}
static void
translabel(g, lb)
grammar *g;
@ -193,15 +207,3 @@ translabel(g, lb)
else
printf("Can't translate label '%s'\n", labelrepr(lb));
}
void
translatelabels(g)
grammar *g;
{
int i;
printf("Translating labels ...\n");
/* Don't translate EMPTY */
for (i = EMPTY+1; i < g->g_ll.ll_nlabels; i++)
translabel(g, &g->g_ll.ll_label[i]);
}

View File

@ -1,7 +1,6 @@
/* Grammar subroutines needed by parser */
#include "PROTO.h"
#define NULL 0
#include "pgenheaders.h"
#include "assert.h"
#include "grammar.h"
#include "token.h"

View File

@ -2,7 +2,7 @@
#ifdef MSDOS
/* This might work for MS-DOS: */
/* This might work for MS-DOS (untested though): */
void
initintr()
@ -37,7 +37,7 @@ initintr()
int
intrcheck()
{
/* Static to make it faster(?) only */
/* Static to make it faster only */
static EventRecord e;
/* XXX This fails if the user first types ahead and then
@ -59,7 +59,7 @@ intrcheck()
#ifndef OK
/* Default version -- should work for Unix and Standard C */
/* Default version -- for real operating systems and for Standard C */
#include <stdio.h>
#include <signal.h>

View File

@ -1,13 +1,31 @@
/* List a node on a file */
#include <stdio.h>
#include "PROTO.h"
#include "pgenheaders.h"
#include "token.h"
#include "node.h"
/* Forward */
static void list1node PROTO((FILE *, node *));
void
listtree(n)
node *n;
{
listnode(stdout, n);
}
static int level, atbol;
void
listnode(fp, n)
FILE *fp;
node *n;
{
level = 0;
atbol = 1;
list1node(fp, n);
}
static void
list1node(fp, n)
FILE *fp;
@ -49,20 +67,3 @@ list1node(fp, n)
else
fprintf(fp, "? ");
}
void
listnode(fp, n)
FILE *fp;
node *n;
{
level = 0;
atbol = 1;
list1node(fp, n);
}
void
listtree(n)
node *n;
{
listnode(stdout, n);
}

View File

@ -1,6 +1,7 @@
#include "PROTO.h"
#include "pgenheaders.h"
#include "metagrammar.h"
#include "grammar.h"
#include "pgen.h"
static arc arcs_0_0[3] = {
{2, 0},
{3, 0},

View File

@ -1,11 +1,10 @@
/* Parse tree node implementation */
#include "PROTO.h"
#include "malloc.h"
#include "pgenheaders.h"
#include "node.h"
node *
newnode(type)
newtree(type)
int type;
{
node *n = NEW(node, 1);
@ -13,6 +12,7 @@ newnode(type)
return NULL;
n->n_type = type;
n->n_str = NULL;
n->n_lineno = 0;
n->n_nchildren = 0;
n->n_child = NULL;
return n;
@ -22,10 +22,11 @@ newnode(type)
#define XXXROUNDUP(n) ((n) == 1 ? 1 : ((n) + XXX - 1) / XXX * XXX)
node *
addchild(n1, type, str)
addchild(n1, type, str, lineno)
register node *n1;
int type;
char *str;
int lineno;
{
register int nch = n1->n_nchildren;
register int nch1 = nch+1;
@ -41,11 +42,26 @@ addchild(n1, type, str)
n = &n1->n_child[n1->n_nchildren++];
n->n_type = type;
n->n_str = str;
n->n_lineno = lineno;
n->n_nchildren = 0;
n->n_child = NULL;
return n;
}
/* Forward */
static void freechildren PROTO((node *));
void
freetree(n)
node *n;
{
if (n != NULL) {
freechildren(n);
DEL(n);
}
}
static void
freechildren(n)
node *n;
@ -58,13 +74,3 @@ freechildren(n)
if (STR(n) != NULL)
DEL(STR(n));
}
void
freenode(n)
node *n;
{
if (n != NULL) {
freechildren(n);
DEL(n);
}
}

View File

@ -4,20 +4,17 @@
/* XXX To do: error recovery */
#include <stdio.h>
#include "pgenheaders.h"
#include "assert.h"
#include "PROTO.h"
#include "malloc.h"
#include "token.h"
#include "grammar.h"
#include "node.h"
#include "parser.h"
#include "errcode.h"
extern int debugging;
#ifdef DEBUG
extern int debugging;
#define D(x) if (!debugging); else x
#else
#define D(x)
@ -94,7 +91,7 @@ newparser(g, start)
if (ps == NULL)
return NULL;
ps->p_grammar = g;
ps->p_tree = newnode(start);
ps->p_tree = newtree(start);
if (ps->p_tree == NULL) {
DEL(ps);
return NULL;
@ -110,24 +107,25 @@ delparser(ps)
{
/* NB If you want to save the parse tree,
you must set p_tree to NULL before calling delparser! */
freenode(ps->p_tree);
freetree(ps->p_tree);
DEL(ps);
}
/* PARSER STACK OPERATIONS */
static int shift PROTO((stack *, int, char *, int));
static int shift PROTO((stack *, int, char *, int, int));
static int
shift(s, type, str, newstate)
shift(s, type, str, newstate, lineno)
register stack *s;
int type;
char *str;
int newstate;
int lineno;
{
assert(!s_empty(s));
if (addchild(s->s_top->s_parent, type, str) == NULL) {
if (addchild(s->s_top->s_parent, type, str, lineno) == NULL) {
fprintf(stderr, "shift: no mem in addchild\n");
return -1;
}
@ -135,19 +133,20 @@ shift(s, type, str, newstate)
return 0;
}
static int push PROTO((stack *, int, dfa *, int));
static int push PROTO((stack *, int, dfa *, int, int));
static int
push(s, type, d, newstate)
push(s, type, d, newstate, lineno)
register stack *s;
int type;
dfa *d;
int newstate;
int lineno;
{
register node *n;
n = s->s_top->s_parent;
assert(!s_empty(s));
if (addchild(n, type, (char *)NULL) == NULL) {
if (addchild(n, type, (char *)NULL, lineno) == NULL) {
fprintf(stderr, "push: no mem in addchild\n");
return -1;
}
@ -198,10 +197,11 @@ classify(g, type, str)
}
int
addtoken(ps, type, str)
addtoken(ps, type, str, lineno)
register parser_state *ps;
register int type;
char *str;
int lineno;
{
register int ilabel;
@ -230,7 +230,8 @@ addtoken(ps, type, str)
int nt = (x >> 8) + NT_OFFSET;
int arrow = x & ((1<<7)-1);
dfa *d1 = finddfa(ps->p_grammar, nt);
if (push(&ps->p_stack, nt, d1, arrow) < 0) {
if (push(&ps->p_stack, nt, d1,
arrow, lineno) < 0) {
D(printf(" MemError: push.\n"));
return E_NOMEM;
}
@ -239,7 +240,8 @@ addtoken(ps, type, str)
}
/* Shift the token */
if (shift(&ps->p_stack, type, str, x) < 0) {
if (shift(&ps->p_stack, type, str,
x, lineno) < 0) {
D(printf(" MemError: shift.\n"));
return E_NOMEM;
}

View File

@ -5,7 +5,7 @@
typedef struct _stackentry {
int s_state; /* State in current DFA */
dfa *s_dfa; /* Current DFA */
node *s_parent; /* Where to add next node */
struct _node *s_parent; /* Where to add next node */
} stackentry;
typedef struct _stack {
@ -22,4 +22,5 @@ typedef struct {
parser_state *newparser PROTO((struct _grammar *g, int start));
void delparser PROTO((parser_state *ps));
int addtoken PROTO((parser_state *ps, int type, char *str));
int addtoken PROTO((parser_state *ps, int type, char *str, int lineno));
void addaccelerators PROTO((grammar *g));

View File

@ -1,16 +1,82 @@
/* Parser-tokenizer link implementation */
#include <stdio.h>
#include "PROTO.h"
#include "malloc.h"
#include "pgenheaders.h"
#include "tokenizer.h"
#include "node.h"
#include "grammar.h"
#include "parser.h"
#include "parsetok.h"
#include "errcode.h"
extern int debugging;
/* Forward */
static int parsetok PROTO((struct tok_state *, grammar *, int, node **));
/* Parse input coming from a string. Return error code, print some errors. */
int
parsestring(s, g, start, n_ret)
char *s;
grammar *g;
int start;
node **n_ret;
{
struct tok_state *tok = tok_setups(s);
int ret;
if (tok == NULL) {
fprintf(stderr, "no mem for tok_setups\n");
return E_NOMEM;
}
ret = parsetok(tok, g, start, n_ret);
if (ret == E_TOKEN || ret == E_SYNTAX) {
fprintf(stderr, "String parsing error at line %d\n",
tok->lineno);
}
tok_free(tok);
return ret;
}
/* Parse input coming from a file. Return error code, print some errors. */
int
parsefile(fp, filename, g, start, ps1, ps2, n_ret)
FILE *fp;
char *filename;
grammar *g;
int start;
char *ps1, *ps2;
node **n_ret;
{
struct tok_state *tok = tok_setupf(fp, ps1, ps2);
int ret;
if (tok == NULL) {
fprintf(stderr, "no mem for tok_setupf\n");
return E_NOMEM;
}
ret = parsetok(tok, g, start, n_ret);
if (ret == E_TOKEN || ret == E_SYNTAX) {
char *p;
fprintf(stderr, "Parsing error: file %s, line %d:\n",
filename, tok->lineno);
*tok->inp = '\0';
if (tok->inp > tok->buf && tok->inp[-1] == '\n')
tok->inp[-1] = '\0';
fprintf(stderr, "%s\n", tok->buf);
for (p = tok->buf; p < tok->cur; p++) {
if (*p == '\t')
putc('\t', stderr);
else
putc(' ', stderr);
}
fprintf(stderr, "^\n");
}
tok_free(tok);
return ret;
}
/* Parse input coming from the given tokenizer structure.
@ -51,7 +117,7 @@ parsetok(tok, g, start, n_ret)
}
strncpy(str, a, len);
str[len] = '\0';
ret = addtoken(ps, (int)type, str);
ret = addtoken(ps, (int)type, str, tok->lineno);
if (ret != E_OK) {
if (ret == E_DONE) {
*n_ret = ps->p_tree;
@ -66,67 +132,3 @@ parsetok(tok, g, start, n_ret)
delparser(ps);
return ret;
}
/* Parse input coming from a string. Return error code. */
int
parsestring(s, g, start, n_ret)
char *s;
grammar *g;
int start;
node **n_ret;
{
struct tok_state *tok = tok_setups(s);
int ret;
if (tok == NULL) {
fprintf(stderr, "no mem for tok_setups\n");
return E_NOMEM;
}
ret = parsetok(tok, g, start, n_ret);
if (ret == E_TOKEN || ret == E_SYNTAX) {
fprintf(stderr, "String parsing error at line %d\n",
tok->lineno);
}
tok_free(tok);
return ret;
}
/* Parse input coming from a file. Return error code. */
int
parsefile(fp, g, start, ps1, ps2, n_ret)
FILE *fp;
grammar *g;
int start;
char *ps1, *ps2;
node **n_ret;
{
struct tok_state *tok = tok_setupf(fp, ps1, ps2);
int ret;
if (tok == NULL) {
fprintf(stderr, "no mem for tok_setupf\n");
return E_NOMEM;
}
ret = parsetok(tok, g, start, n_ret);
if (ret == E_TOKEN || ret == E_SYNTAX) {
char *p;
fprintf(stderr, "Parsing error at line %d:\n", tok->lineno);
*tok->inp = '\0';
if (tok->inp > tok->buf && tok->inp[-1] == '\n')
tok->inp[-1] = '\0';
fprintf(stderr, "%s\n", tok->buf);
for (p = tok->buf; p < tok->cur; p++) {
if (*p == '\t')
putc('\t', stderr);
else
putc(' ', stderr);
}
fprintf(stderr, "^\n");
}
tok_free(tok);
return ret;
}

View File

@ -1,12 +1,10 @@
/* Parser generator */
/* XXX This file is not yet fully PROTOized */
/* For a description, see the comments at end of this file */
#include <stdio.h>
#include "pgenheaders.h"
#include "assert.h"
#include "PROTO.h"
#include "malloc.h"
#include "token.h"
#include "node.h"
#include "grammar.h"

View File

@ -3,4 +3,4 @@
extern grammar gram;
extern grammar *meta_grammar PROTO((void));
extern grammar *pgen PROTO((node *));
extern grammar *pgen PROTO((struct _node *));

View File

@ -1,8 +1,14 @@
/* Parser generator main program */
#include <stdio.h>
/* This expects a filename containing the grammar as argv[1] (UNIX)
or asks the console for such a file name (THINK C).
It writes its output on two files in the current directory:
- "graminit.c" gets the grammar as a bunch of initialized data
- "graminit.h" gets the grammar's non-terminals as #defines.
Error messages and status info during the generation process are
written to stdout, or sometimes to stderr. */
#include "PROTO.h"
#include "pgenheaders.h"
#include "grammar.h"
#include "node.h"
#include "parsetok.h"
@ -10,54 +16,14 @@
int debugging;
/* Forward */
grammar *getgrammar PROTO((char *filename));
#ifdef THINK_C
char *
askfile()
{
char buf[256];
static char name[256];
printf("Input file name: ");
if (fgets(buf, sizeof buf, stdin) == NULL) {
printf("EOF\n");
exit(1);
}
if (sscanf(buf, " %s ", name) != 1) {
printf("No file\n");
exit(1);
}
return name;
}
int main PROTO((int, char **));
char *askfile PROTO((void));
#endif
grammar *
getgrammar(filename)
char *filename;
{
FILE *fp;
node *n;
grammar *g0, *g;
fp = fopen(filename, "r");
if (fp == NULL) {
perror(filename);
exit(1);
}
g0 = meta_grammar();
n = NULL;
parsefile(fp, g0, g0->g_start, (char *)NULL, (char *)NULL, &n);
fclose(fp);
if (n == NULL) {
fprintf(stderr, "Parsing error.\n");
exit(1);
}
g = pgen(n);
if (g == NULL) {
printf("Bad grammar.\n");
exit(1);
}
return g;
}
int
main(argc, argv)
int argc;
char **argv;
@ -96,6 +62,55 @@ main(argc, argv)
exit(0);
}
grammar *
getgrammar(filename)
char *filename;
{
FILE *fp;
node *n;
grammar *g0, *g;
fp = fopen(filename, "r");
if (fp == NULL) {
perror(filename);
exit(1);
}
g0 = meta_grammar();
n = NULL;
parsefile(fp, filename, g0, g0->g_start, (char *)NULL, (char *)NULL, &n);
fclose(fp);
if (n == NULL) {
fprintf(stderr, "Parsing error.\n");
exit(1);
}
g = pgen(n);
if (g == NULL) {
printf("Bad grammar.\n");
exit(1);
}
return g;
}
#ifdef THINK_C
char *
askfile()
{
char buf[256];
static char name[256];
printf("Input file name: ");
if (fgets(buf, sizeof buf, stdin) == NULL) {
printf("EOF\n");
exit(1);
}
/* XXX The (unsigned char *) case is needed by THINK C */
if (sscanf((unsigned char *)buf, " %s ", name) != 1) {
printf("No file\n");
exit(1);
}
return name;
}
#endif
void
fatal(msg)
char *msg;
@ -104,8 +119,6 @@ fatal(msg)
exit(1);
}
/* TO DO:
- improve user interface
- check for duplicate definitions of names (instead of fatal err)
/* XXX TO DO:
- check for duplicate definitions of names (instead of fatal err)
*/

View File

@ -1,10 +1,44 @@
/* Print a bunch of C initializers that represent a grammar */
#include <stdio.h>
#include "PROTO.h"
#include "pgenheaders.h"
#include "grammar.h"
/* Forward */
static void printarcs PROTO((int, dfa *, FILE *));
static void printstates PROTO((grammar *, FILE *));
static void printdfas PROTO((grammar *, FILE *));
static void printlabels PROTO((grammar *, FILE *));
void
printgrammar(g, fp)
grammar *g;
FILE *fp;
{
fprintf(fp, "#include \"pgenheaders.h\"\n");
fprintf(fp, "#include \"grammar.h\"\n");
printdfas(g, fp);
printlabels(g, fp);
fprintf(fp, "grammar gram = {\n");
fprintf(fp, "\t%d,\n", g->g_ndfas);
fprintf(fp, "\tdfas,\n");
fprintf(fp, "\t{%d, labels},\n", g->g_ll.ll_nlabels);
fprintf(fp, "\t%d\n", g->g_start);
fprintf(fp, "};\n");
}
void
printnonterminals(g, fp)
grammar *g;
FILE *fp;
{
dfa *d;
int i;
d = g->g_dfa;
for (i = g->g_ndfas; --i >= 0; d++)
fprintf(fp, "#define %s %d\n", d->d_name, d->d_type);
}
static void
printarcs(i, d, fp)
int i;
@ -89,33 +123,3 @@ printlabels(g, fp)
}
fprintf(fp, "};\n");
}
void
printgrammar(g, fp)
grammar *g;
FILE *fp;
{
fprintf(fp, "#include \"PROTO.h\"\n");
fprintf(fp, "#include \"grammar.h\"\n");
printdfas(g, fp);
printlabels(g, fp);
fprintf(fp, "grammar gram = {\n");
fprintf(fp, "\t%d,\n", g->g_ndfas);
fprintf(fp, "\tdfas,\n");
fprintf(fp, "\t{%d, labels},\n", g->g_ll.ll_nlabels);
fprintf(fp, "\t%d\n", g->g_start);
fprintf(fp, "};\n");
}
void
printnonterminals(g, fp)
grammar *g;
FILE *fp;
{
dfa *d;
int i;
d = g->g_dfa;
for (i = g->g_ndfas; --i >= 0; d++)
fprintf(fp, "#define %s %d\n", d->d_name, d->d_type);
}

View File

@ -2,13 +2,14 @@
/* XXX This is rather old, should be restructured perhaps */
/* XXX Need a better interface to report errors than writing to stderr */
/* XXX Should use editor resource to fetch true tab size on Macintosh */
#include "pgenheaders.h"
#include <stdio.h>
#include <ctype.h>
#include "string.h"
#include "PROTO.h"
#include "malloc.h"
#include "fgetsintr.h"
#include "tokenizer.h"
#include "errcode.h"
@ -20,6 +21,11 @@
#define TABSIZE 8
#endif
/* Forward */
static struct tok_state *tok_new PROTO((void));
static int tok_nextc PROTO((struct tok_state *tok));
static void tok_backup PROTO((struct tok_state *tok, int c));
/* Token names */
char *tok_name[] = {
@ -352,7 +358,9 @@ tok_get(tok, p_start, p_end)
This is also recognized by vi, when it occurs near the
beginning or end of the file. (Will vi never die...?) */
int x;
if (sscanf(tok->cur, " vi:set tabsize=%d:", &x) == 1 &&
/* XXX The case to (unsigned char *) is needed by THINK C */
if (sscanf((unsigned char *)tok->cur,
" vi:set tabsize=%d:", &x) == 1 &&
x >= 1 && x <= 40) {
fprintf(stderr, "# vi:set tabsize=%d:\n", x);
tok->tabsize = x;

535
Python/bltinmodule.c Normal file
View File

@ -0,0 +1,535 @@
/* Built-in functions */
#include "allobjects.h"
#include "node.h"
#include "graminit.h"
#include "errcode.h"
#include "sysmodule.h"
#include "builtinmodule.h"
#include "import.h"
#include "pythonrun.h"
#include "compile.h" /* For ceval.h */
#include "ceval.h"
#include "modsupport.h"
static object *
builtin_abs(self, v)
object *self;
object *v;
{
/* XXX This should be a method in the as_number struct in the type */
if (v == NULL) {
/* */
}
else if (is_intobject(v)) {
long x = getintvalue(v);
if (x < 0)
x = -x;
return newintobject(x);
}
else if (is_floatobject(v)) {
double x = getfloatvalue(v);
if (x < 0)
x = -x;
return newfloatobject(x);
}
err_setstr(TypeError, "abs() argument must be float or int");
return NULL;
}
static object *
builtin_chr(self, v)
object *self;
object *v;
{
long x;
char s[1];
if (v == NULL || !is_intobject(v)) {
err_setstr(TypeError, "chr() must have int argument");
return NULL;
}
x = getintvalue(v);
if (x < 0 || x >= 256) {
err_setstr(RuntimeError, "chr() arg not in range(256)");
return NULL;
}
s[0] = x;
return newsizedstringobject(s, 1);
}
static object *
builtin_dir(self, v)
object *self;
object *v;
{
object *d;
if (v == NULL) {
d = getlocals();
}
else {
if (!is_moduleobject(v)) {
err_setstr(TypeError,
"dir() argument, must be module or absent");
return NULL;
}
d = getmoduledict(v);
}
v = getdictkeys(d);
if (sortlist(v) != 0) {
DECREF(v);
v = NULL;
}
return v;
}
static object *
builtin_divmod(self, v)
object *self;
object *v;
{
object *x, *y;
long xi, yi, xdivy, xmody;
if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
err_setstr(TypeError, "divmod() requires 2 int arguments");
return NULL;
}
x = gettupleitem(v, 0);
y = gettupleitem(v, 1);
if (!is_intobject(x) || !is_intobject(y)) {
err_setstr(TypeError, "divmod() requires 2 int arguments");
return NULL;
}
xi = getintvalue(x);
yi = getintvalue(y);
if (yi == 0) {
err_setstr(TypeError, "divmod() division by zero");
return NULL;
}
if (yi < 0) {
xdivy = -xi / -yi;
}
else {
xdivy = xi / yi;
}
xmody = xi - xdivy*yi;
if (xmody < 0 && yi > 0 || xmody > 0 && yi < 0) {
xmody += yi;
xdivy -= 1;
}
v = newtupleobject(2);
x = newintobject(xdivy);
y = newintobject(xmody);
if (v == NULL || x == NULL || y == NULL ||
settupleitem(v, 0, x) != 0 ||
settupleitem(v, 1, y) != 0) {
XDECREF(v);
XDECREF(x);
XDECREF(y);
return NULL;
}
return v;
}
static object *
exec_eval(v, start)
object *v;
int start;
{
object *str = NULL, *globals = NULL, *locals = NULL;
int n;
if (v != NULL) {
if (is_stringobject(v))
str = v;
else if (is_tupleobject(v) &&
((n = gettuplesize(v)) == 2 || n == 3)) {
str = gettupleitem(v, 0);
globals = gettupleitem(v, 1);
if (n == 3)
locals = gettupleitem(v, 2);
}
}
if (str == NULL || !is_stringobject(str) ||
globals != NULL && !is_dictobject(globals) ||
locals != NULL && !is_dictobject(locals)) {
err_setstr(TypeError,
"exec/eval arguments must be string[,dict[,dict]]");
return NULL;
}
return run_string(getstringvalue(str), start, globals, locals);
}
static object *
builtin_eval(self, v)
object *self;
object *v;
{
return exec_eval(v, eval_input);
}
static object *
builtin_exec(self, v)
object *self;
object *v;
{
return exec_eval(v, file_input);
}
static object *
builtin_float(self, v)
object *self;
object *v;
{
if (v == NULL) {
/* */
}
else if (is_floatobject(v)) {
INCREF(v);
return v;
}
else if (is_intobject(v)) {
long x = getintvalue(v);
return newfloatobject((double)x);
}
err_setstr(TypeError, "float() argument must be float or int");
return NULL;
}
static object *
builtin_input(self, v)
object *self;
object *v;
{
FILE *in = sysgetfile("stdin", stdin);
FILE *out = sysgetfile("stdout", stdout);
node *n;
int err;
object *m, *d;
flushline();
if (v != NULL)
printobject(v, out, PRINT_RAW);
m = add_module("__main__");
d = getmoduledict(m);
return run_file(in, "<stdin>", expr_input, d, d);
}
static object *
builtin_int(self, v)
object *self;
object *v;
{
if (v == NULL) {
/* */
}
else if (is_intobject(v)) {
INCREF(v);
return v;
}
else if (is_floatobject(v)) {
double x = getfloatvalue(v);
return newintobject((long)x);
}
err_setstr(TypeError, "int() argument must be float or int");
return NULL;
}
static object *
builtin_len(self, v)
object *self;
object *v;
{
long len;
typeobject *tp;
if (v == NULL) {
err_setstr(TypeError, "len() without argument");
return NULL;
}
tp = v->ob_type;
if (tp->tp_as_sequence != NULL) {
len = (*tp->tp_as_sequence->sq_length)(v);
}
else if (tp->tp_as_mapping != NULL) {
len = (*tp->tp_as_mapping->mp_length)(v);
}
else {
err_setstr(TypeError, "len() of unsized object");
return NULL;
}
return newintobject(len);
}
static object *
min_max(v, sign)
object *v;
int sign;
{
int i, n, cmp;
object *w, *x;
sequence_methods *sq;
if (v == NULL) {
err_setstr(TypeError, "min() or max() without argument");
return NULL;
}
sq = v->ob_type->tp_as_sequence;
if (sq == NULL) {
err_setstr(TypeError, "min() or max() of non-sequence");
return NULL;
}
n = (*sq->sq_length)(v);
if (n == 0) {
err_setstr(RuntimeError, "min() or max() of empty sequence");
return NULL;
}
w = (*sq->sq_item)(v, 0); /* Implies INCREF */
for (i = 1; i < n; i++) {
x = (*sq->sq_item)(v, i); /* Implies INCREF */
cmp = cmpobject(x, w);
if (cmp * sign > 0) {
DECREF(w);
w = x;
}
else
DECREF(x);
}
return w;
}
static object *
builtin_min(self, v)
object *self;
object *v;
{
return min_max(v, -1);
}
static object *
builtin_max(self, v)
object *self;
object *v;
{
return min_max(v, 1);
}
static object *
builtin_open(self, v)
object *self;
object *v;
{
object *name, *mode;
if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2 ||
!is_stringobject(name = gettupleitem(v, 0)) ||
!is_stringobject(mode = gettupleitem(v, 1))) {
err_setstr(TypeError, "open() requires 2 string arguments");
return NULL;
}
v = newfileobject(getstringvalue(name), getstringvalue(mode));
return v;
}
static object *
builtin_ord(self, v)
object *self;
object *v;
{
if (v == NULL || !is_stringobject(v)) {
err_setstr(TypeError, "ord() must have string argument");
return NULL;
}
if (getstringsize(v) != 1) {
err_setstr(RuntimeError, "ord() arg must have length 1");
return NULL;
}
return newintobject((long)(getstringvalue(v)[0] & 0xff));
}
static object *
builtin_range(self, v)
object *self;
object *v;
{
static char *errmsg = "range() requires 1-3 int arguments";
int i, n;
long ilow, ihigh, istep;
if (v != NULL && is_intobject(v)) {
ilow = 0; ihigh = getintvalue(v); istep = 1;
}
else if (v == NULL || !is_tupleobject(v)) {
err_setstr(TypeError, errmsg);
return NULL;
}
else {
n = gettuplesize(v);
if (n < 1 || n > 3) {
err_setstr(TypeError, errmsg);
return NULL;
}
for (i = 0; i < n; i++) {
if (!is_intobject(gettupleitem(v, i))) {
err_setstr(TypeError, errmsg);
return NULL;
}
}
if (n == 3) {
istep = getintvalue(gettupleitem(v, 2));
--n;
}
else
istep = 1;
ihigh = getintvalue(gettupleitem(v, --n));
if (n > 0)
ilow = getintvalue(gettupleitem(v, 0));
else
ilow = 0;
}
if (istep == 0) {
err_setstr(RuntimeError, "zero step for range()");
return NULL;
}
/* XXX ought to check overflow of subtraction */
if (istep > 0)
n = (ihigh - ilow + istep - 1) / istep;
else
n = (ihigh - ilow + istep + 1) / istep;
if (n < 0)
n = 0;
v = newlistobject(n);
if (v == NULL)
return NULL;
for (i = 0; i < n; i++) {
object *w = newintobject(ilow);
if (w == NULL) {
DECREF(v);
return NULL;
}
setlistitem(v, i, w);
ilow += istep;
}
return v;
}
static object *
builtin_raw_input(self, v)
object *self;
object *v;
{
FILE *in = sysgetfile("stdin", stdin);
FILE *out = sysgetfile("stdout", stdout);
char *p;
int err;
int n = 1000;
flushline();
if (v != NULL)
printobject(v, out, PRINT_RAW);
v = newsizedstringobject((char *)NULL, n);
if (v != NULL) {
if ((err = fgets_intr(getstringvalue(v), n+1, in)) != E_OK) {
err_input(err);
DECREF(v);
return NULL;
}
else {
n = strlen(getstringvalue(v));
if (n > 0 && getstringvalue(v)[n-1] == '\n')
n--;
resizestring(&v, n);
}
}
return v;
}
static object *
builtin_reload(self, v)
object *self;
object *v;
{
return reload_module(v);
}
static object *
builtin_type(self, v)
object *self;
object *v;
{
if (v == NULL) {
err_setstr(TypeError, "type() requres an argument");
return NULL;
}
v = (object *)v->ob_type;
INCREF(v);
return v;
}
static struct methodlist builtin_methods[] = {
{"abs", builtin_abs},
{"chr", builtin_chr},
{"dir", builtin_dir},
{"divmod", builtin_divmod},
{"eval", builtin_eval},
{"exec", builtin_exec},
{"float", builtin_float},
{"input", builtin_input},
{"int", builtin_int},
{"len", builtin_len},
{"min", builtin_min},
{"max", builtin_max},
{"open", builtin_open}, /* XXX move to OS module */
{"ord", builtin_ord},
{"range", builtin_range},
{"raw_input", builtin_raw_input},
{"reload", builtin_reload},
{"type", builtin_type},
{NULL, NULL},
};
static object *builtin_dict;
object *
getbuiltin(name)
char *name;
{
return dictlookup(builtin_dict, name);
}
/* Predefined exceptions */
object *RuntimeError;
object *EOFError;
object *TypeError;
object *MemoryError;
object *NameError;
object *SystemError;
object *KeyboardInterrupt;
static object *
newstdexception(name, message)
char *name, *message;
{
object *v = newstringobject(message);
if (v == NULL || dictinsert(builtin_dict, name, v) != 0)
fatal("no mem for new standard exception");
return v;
}
static void
initerrors()
{
RuntimeError = newstdexception("RuntimeError", "run-time error");
EOFError = newstdexception("EOFError", "end-of-file read");
TypeError = newstdexception("TypeError", "type error");
MemoryError = newstdexception("MemoryError", "out of memory");
NameError = newstdexception("NameError", "undefined name");
SystemError = newstdexception("SystemError", "system error");
KeyboardInterrupt =
newstdexception("KeyboardInterrupt", "keyboard interrupt");
}
void
initbuiltin()
{
object *m;
m = initmodule("builtin", builtin_methods);
builtin_dict = getmoduledict(m);
INCREF(builtin_dict);
initerrors();
(void) dictinsert(builtin_dict, "None", None);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +1,49 @@
/* Compile an expression node to intermediate code */
#include <stdio.h>
#include <ctype.h>
#include "string.h"
/* XXX TO DO:
XXX Compute maximum needed stack sizes while compiling
XXX Generate simple jump for break/return outside 'try...finally'
XXX Include function name in code (and module names?)
*/
#include "allobjects.h"
#include "PROTO.h"
#include "object.h"
#include "objimpl.h"
#include "intobject.h"
#include "floatobject.h"
#include "stringobject.h"
#include "listobject.h"
#include "node.h"
#include "token.h"
#include "graminit.h"
#include "errors.h"
#include "compile.h"
#include "opcode.h"
#include "structmember.h"
#include <ctype.h>
#define OFF(x) offsetof(codeobject, x)
static struct memberlist code_memberlist[] = {
{"co_code", T_OBJECT, OFF(co_code)},
{"co_consts", T_OBJECT, OFF(co_consts)},
{"co_names", T_OBJECT, OFF(co_names)},
{"co_filename", T_OBJECT, OFF(co_filename)},
{NULL} /* Sentinel */
};
static object *
code_getattr(co, name)
codeobject *co;
char *name;
{
return getmember((char *)co, code_memberlist, name);
}
static void
code_dealloc(c)
codeobject *c;
code_dealloc(co)
codeobject *co;
{
XDECREF(c->co_code);
XDECREF(c->co_consts);
XDECREF(c->co_names);
DEL(c);
XDECREF(co->co_code);
XDECREF(co->co_consts);
XDECREF(co->co_names);
XDECREF(co->co_filename);
DEL(co);
}
typeobject Codetype = {
@ -36,7 +54,7 @@ typeobject Codetype = {
0,
code_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
code_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
@ -45,13 +63,14 @@ typeobject Codetype = {
0, /*tp_as_mapping*/
};
static codeobject *newcodeobject PROTO((object *, object *, object *));
static codeobject *newcodeobject PROTO((object *, object *, object *, char *));
static codeobject *
newcodeobject(code, consts, names)
newcodeobject(code, consts, names, filename)
object *code;
object *consts;
object *names;
char *filename;
{
codeobject *co;
int i;
@ -78,6 +97,10 @@ newcodeobject(code, consts, names)
co->co_consts = consts;
INCREF(names);
co->co_names = names;
if ((co->co_filename = newstringobject(filename)) == NULL) {
DECREF(co);
co = NULL;
}
}
return co;
}
@ -90,10 +113,13 @@ struct compiling {
object *c_names; /* list of strings (names) */
int c_nexti; /* index into c_code */
int c_errors; /* counts errors occurred */
int c_infunction; /* set when compiling a function */
int c_loops; /* counts nested loops */
char *c_filename; /* filename of current node */
};
/* Prototypes */
static int com_init PROTO((struct compiling *));
static int com_init PROTO((struct compiling *, char *));
static void com_free PROTO((struct compiling *));
static void com_done PROTO((struct compiling *));
static void com_node PROTO((struct compiling *, struct _node *));
@ -108,8 +134,9 @@ static int com_addname PROTO((struct compiling *, object *));
static void com_addopname PROTO((struct compiling *, int, node *));
static int
com_init(c)
com_init(c, filename)
struct compiling *c;
char *filename;
{
if ((c->c_code = newsizedstringobject((char *)NULL, 0)) == NULL)
goto fail_3;
@ -119,6 +146,9 @@ com_init(c)
goto fail_1;
c->c_nexti = 0;
c->c_errors = 0;
c->c_infunction = 0;
c->c_loops = 0;
c->c_filename = filename;
return 1;
fail_1:
@ -153,6 +183,8 @@ com_addbyte(c, byte)
{
int len;
if (byte < 0 || byte > 255) {
fprintf(stderr, "XXX compiling bad byte: %d\n", byte);
abort();
err_setstr(SystemError, "com_addbyte: byte out of range");
c->c_errors++;
}
@ -1076,6 +1108,10 @@ com_return_stmt(c, n)
node *n;
{
REQ(n, return_stmt); /* 'return' [testlist] NEWLINE */
if (!c->c_infunction) {
err_setstr(TypeError, "'return' outside function");
c->c_errors++;
}
if (NCH(n) == 2)
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
else
@ -1134,6 +1170,9 @@ com_if_stmt(c, n)
/*'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] */
for (i = 0; i+3 < NCH(n); i+=4) {
int a = 0;
node *ch = CHILD(n, i+1);
if (i > 0)
com_addoparg(c, SET_LINENO, ch->n_lineno);
com_node(c, CHILD(n, i+1));
com_addfwref(c, JUMP_IF_FALSE, &a);
com_addbyte(c, POP_TOP);
@ -1158,10 +1197,13 @@ com_while_stmt(c, n)
REQ(n, while_stmt); /* 'while' test ':' suite ['else' ':' suite] */
com_addfwref(c, SETUP_LOOP, &break_anchor);
begin = c->c_nexti;
com_addoparg(c, SET_LINENO, n->n_lineno);
com_node(c, CHILD(n, 1));
com_addfwref(c, JUMP_IF_FALSE, &anchor);
com_addbyte(c, POP_TOP);
c->c_loops++;
com_node(c, CHILD(n, 3));
c->c_loops--;
com_addoparg(c, JUMP_ABSOLUTE, begin);
com_backpatch(c, anchor);
com_addbyte(c, POP_TOP);
@ -1190,9 +1232,12 @@ com_for_stmt(c, n)
com_addoparg(c, LOAD_CONST, com_addconst(c, v));
XDECREF(v);
begin = c->c_nexti;
com_addoparg(c, SET_LINENO, n->n_lineno);
com_addfwref(c, FOR_LOOP, &anchor);
com_assign(c, CHILD(n, 1), 1/*assigning*/);
c->c_loops++;
com_node(c, CHILD(n, 5));
c->c_loops--;
com_addoparg(c, JUMP_ABSOLUTE, begin);
com_backpatch(c, anchor);
com_addbyte(c, POP_BLOCK);
@ -1225,7 +1270,6 @@ com_for_stmt(c, n)
<code for S>
POP_BLOCK
LOAD_CONST <nil>
LOAD_CONST <nil>
L: <code for Sf>
END_FINALLY
@ -1242,13 +1286,9 @@ com_for_stmt(c, n)
stack until its level is the same as indicated on the
block stack. (The label is ignored.)
END_FINALLY:
Pops two entries from the *value* stack and re-raises
the exception they specify. If the top entry is nil,
no exception is raised. If it is a number, a pseudo
exception is raised ('return' or 'break'). Otherwise,
a real exception (specified by a string) is raised.
The second entry popped from the is the value that goes
with the exception (or the return value).
Pops a variable number of entries from the *value* stack
and re-raises the exception they specify. The number of
entries popped depends on the (pseudo) exception type.
The block stack is unwound when an exception is raised:
when a SETUP_FINALLY entry is found, the exception is pushed
@ -1257,6 +1297,9 @@ com_for_stmt(c, n)
stack.
Code generated for "try: S except E1, V1: S1 except E2, V2: S2 ...":
(The contents of the value stack is shown in [], with the top
at the right; 'tb' is trace-back info, 'val' the exception's
associated value, and 'exc' the exception.)
Value stack Label Instruction Argument
[] SETUP_EXCEPT L1
@ -1264,22 +1307,23 @@ com_for_stmt(c, n)
[] POP_BLOCK
[] JUMP_FORWARD L0
[val, exc] L1: DUP
[val, exc, exc] <evaluate E1>
[val, exc, exc, E1] COMPARE_OP EXC_MATCH
[val, exc, 1-or-0] JUMP_IF_FALSE L2
[val, exc, 1] POP
[val, exc] POP
[val] <assign to V1>
[tb, val, exc] L1: DUP )
[tb, val, exc, exc] <evaluate E1> )
[tb, val, exc, exc, E1] COMPARE_OP EXC_MATCH ) only if E1
[tb, val, exc, 1-or-0] JUMP_IF_FALSE L2 )
[tb, val, exc, 1] POP )
[tb, val, exc] POP
[tb, val] <assign to V1> (or POP if no V1)
[tb] POP
[] <code for S1>
JUMP_FORWARD L0
[val, exc, 0] L2: POP
[val, exc] DUP
[tb, val, exc, 0] L2: POP
[tb, val, exc] DUP
.............................etc.......................
[val, exc, 0] Ln+1: POP
[val, exc] END_FINALLY # re-raise exception
[tb, val, exc, 0] Ln+1: POP
[tb, val, exc] END_FINALLY # re-raise exception
[] L0: <next statement>
@ -1323,6 +1367,7 @@ com_try_stmt(c, n)
break;
}
except_anchor = 0;
com_addoparg(c, SET_LINENO, ch->n_lineno);
if (NCH(ch) > 1) {
com_addbyte(c, DUP_TOP);
com_node(c, CHILD(ch, 1));
@ -1335,6 +1380,7 @@ com_try_stmt(c, n)
com_assign(c, CHILD(ch, 3), 1/*assigning*/);
else
com_addbyte(c, POP_TOP);
com_addbyte(c, POP_TOP);
com_node(c, CHILD(n, i+2));
com_addfwref(c, JUMP_FORWARD, &end_anchor);
if (except_anchor) {
@ -1346,11 +1392,13 @@ com_try_stmt(c, n)
com_backpatch(c, end_anchor);
}
if (finally_anchor) {
node *ch;
com_addbyte(c, POP_BLOCK);
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
com_backpatch(c, finally_anchor);
com_node(c, CHILD(n, NCH(n)-1));
ch = CHILD(n, NCH(n)-1);
com_addoparg(c, SET_LINENO, ch->n_lineno);
com_node(c, ch);
com_addbyte(c, END_FINALLY);
}
}
@ -1382,7 +1430,7 @@ com_funcdef(c, n)
{
object *v;
REQ(n, funcdef); /* funcdef: 'def' NAME parameters ':' suite */
v = (object *)compile(n);
v = (object *)compile(n, c->c_filename);
if (v == NULL)
c->c_errors++;
else {
@ -1426,7 +1474,7 @@ com_classdef(c, n)
com_bases(c, CHILD(n, 4));
else
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
v = (object *)compile(n);
v = (object *)compile(n, c->c_filename);
if (v == NULL)
c->c_errors++;
else {
@ -1459,9 +1507,13 @@ com_node(c, n)
/* Trivial parse tree nodes */
case stmt:
case simple_stmt:
case flow_stmt:
com_node(c, CHILD(n, 0));
break;
case simple_stmt:
case compound_stmt:
com_addoparg(c, SET_LINENO, n->n_lineno);
com_node(c, CHILD(n, 0));
break;
@ -1479,6 +1531,10 @@ com_node(c, n)
case pass_stmt:
break;
case break_stmt:
if (c->c_loops == 0) {
err_setstr(TypeError, "'break' outside loop");
c->c_errors++;
}
com_addbyte(c, BREAK_LOOP);
break;
case return_stmt:
@ -1608,48 +1664,50 @@ compile_funcdef(c, n)
com_addbyte(c, REQUIRE_ARGS);
com_fplist(c, ch);
}
c->c_infunction = 1;
com_node(c, CHILD(n, 4));
c->c_infunction = 0;
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
com_addbyte(c, RETURN_VALUE);
}
static void
compile_classdef(c, n)
struct compiling *c;
node *n;
{
node *ch;
REQ(n, classdef);
/*
classdef: 'class' NAME parameters ['=' baselist] ':' suite
*/
com_addbyte(c, REFUSE_ARGS);
com_node(c, CHILD(n, NCH(n)-1));
com_addbyte(c, LOAD_LOCALS);
com_addbyte(c, RETURN_VALUE);
}
static void
compile_node(c, n)
struct compiling *c;
node *n;
{
com_addoparg(c, SET_LINENO, n->n_lineno);
switch (TYPE(n)) {
case single_input:
/* NEWLINE | simple_stmt | compound_stmt NEWLINE */
com_addbyte(c, REFUSE_ARGS);
n = CHILD(n, 0);
if (TYPE(n) != NEWLINE)
com_node(c, n);
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
com_addbyte(c, RETURN_VALUE);
break;
case file_input:
com_addbyte(c, REFUSE_ARGS);
com_file_input(c, n);
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
com_addbyte(c, RETURN_VALUE);
break;
case expr_input:
case eval_input:
com_addbyte(c, REFUSE_ARGS);
com_node(c, CHILD(n, 0));
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
com_addbyte(c, RETURN_VALUE);
break;
case eval_input:
com_addbyte(c, REFUSE_ARGS);
com_node(c, CHILD(n, 0));
com_addbyte(c, RETURN_VALUE);
break;
case funcdef:
@ -1657,7 +1715,11 @@ compile_node(c, n)
break;
case classdef:
compile_classdef(c, n);
/* 'class' NAME parameters ['=' baselist] ':' suite */
com_addbyte(c, REFUSE_ARGS);
com_node(c, CHILD(n, NCH(n)-1));
com_addbyte(c, LOAD_LOCALS);
com_addbyte(c, RETURN_VALUE);
break;
default:
@ -1668,17 +1730,18 @@ compile_node(c, n)
}
codeobject *
compile(n)
compile(n, filename)
node *n;
char *filename;
{
struct compiling sc;
codeobject *co;
if (!com_init(&sc))
if (!com_init(&sc, filename))
return NULL;
compile_node(&sc, n);
com_done(&sc);
if (sc.c_errors == 0)
co = newcodeobject(sc.c_code, sc.c_consts, sc.c_names);
co = newcodeobject(sc.c_code, sc.c_consts, sc.c_names, filename);
else
co = NULL;
com_free(&sc);

View File

@ -11,12 +11,11 @@
return value and then calls puterrno(ctx) to turn the errno value
into a true exception. Problems with this approach are:
- it used standard errno values to indicate Python-specific errors,
but this means that when such an error code is reported by UNIX the
user gets a confusing message
but this means that when such an error code is reported by a system
call (e.g., in module posix), the user gets a confusing message
- errno is a global variable, which makes extensions to a multi-
threading environment difficult; e.g., in IRIX, multi-threaded
programs must use the function getoserror() (sp.?) instead of
looking in errno
programs must use the function oserror() instead of looking in errno
- there is no portable way to add new error numbers for specic
situations -- the value space for errno is reserved to the OS, yet
the way to turn module-specific errors into a module-specific
@ -25,21 +24,18 @@
error.
The new interface solves all these problems. To return an error, a
built-in function calls err_set(exception), err_set(valexception,
built-in function calls err_set(exception), err_setval(exception,
value) or err_setstr(exception, string), and returns NULL. These
functions save the value for later use by puterrno(). To adapt this
scheme to a multi-threaded environment, only the implementation of
err_setval() has to be changed.
*/
#include <stdio.h>
#include "errno.h"
#include "PROTO.h"
#include "object.h"
#include "intobject.h"
#include "stringobject.h"
#include "tupleobject.h"
#include "errors.h"
#include "allobjects.h"
#include "errcode.h"
extern char *strerror PROTO((int));
@ -53,16 +49,12 @@ err_setval(exception, value)
object *exception;
object *value;
{
if (last_exception != NULL)
DECREF(last_exception);
if (exception != NULL)
INCREF(exception);
XDECREF(last_exception);
XINCREF(exception);
last_exception = exception;
if (last_exc_val != NULL)
DECREF(last_exc_val);
if (value != NULL)
INCREF(value);
XDECREF(last_exc_val);
XINCREF(value);
last_exc_val = value;
}
@ -80,8 +72,7 @@ err_setstr(exception, string)
{
object *value = newstringobject(string);
err_setval(exception, value);
if (value != NULL)
DECREF(value);
XDECREF(value);
}
int
@ -104,14 +95,10 @@ err_get(p_exc, p_val)
void
err_clear()
{
if (last_exception != NULL) {
DECREF(last_exception);
last_exception = NULL;
}
if (last_exc_val != NULL) {
DECREF(last_exc_val);
last_exc_val = NULL;
}
XDECREF(last_exception);
last_exception = NULL;
XDECREF(last_exc_val);
last_exc_val = NULL;
}
/* Convenience functions to set a type error exception and return 0 */
@ -126,7 +113,7 @@ err_badarg()
object *
err_nomem()
{
err_setstr(MemoryError, "in built-in function");
err_set(MemoryError);
return NULL;
}
@ -140,8 +127,7 @@ err_errno(exc)
settupleitem(v, 1, newstringobject(strerror(errno)));
}
err_setval(exc, v);
if (v != NULL)
DECREF(v);
XDECREF(v);
return NULL;
}
@ -150,3 +136,34 @@ err_badcall()
{
err_setstr(SystemError, "bad argument to internal function");
}
/* Set the error appropriate to the given input error code (see errcode.h) */
void
err_input(err)
int err;
{
switch (err) {
case E_DONE:
case E_OK:
break;
case E_SYNTAX:
err_setstr(RuntimeError, "syntax error");
break;
case E_TOKEN:
err_setstr(RuntimeError, "illegal token");
break;
case E_INTR:
err_set(KeyboardInterrupt);
break;
case E_NOMEM:
err_nomem();
break;
case E_EOF:
err_set(EOFError);
break;
default:
err_setstr(RuntimeError, "unknown input error");
break;
}
}

View File

@ -1,4 +1,4 @@
#include "PROTO.h"
#include "pgenheaders.h"
#include "grammar.h"
static arc arcs_0_0[3] = {
{2, 1},

View File

@ -1,153 +1,67 @@
/* Module definition and import implementation */
#include <stdio.h>
#include "string.h"
#include "allobjects.h"
#include "PROTO.h"
#include "object.h"
#include "stringobject.h"
#include "listobject.h"
#include "dictobject.h"
#include "moduleobject.h"
#include "node.h"
#include "context.h"
#include "token.h"
#include "graminit.h"
#include "run.h"
#include "support.h"
#include "import.h"
#include "errcode.h"
#include "sysmodule.h"
#include "pythonrun.h"
/* Define pathname separator and delimiter in $PYTHONPATH */
/* Define pathname separator used in file names */
#ifdef THINK_C
#define SEP ':'
#define DELIM ' '
#endif
#ifndef SEP
#define SEP '/'
#endif
#ifndef DELIM
#define DELIM ':'
#endif
static object *modules;
/* Initialization */
void
initimport()
{
object *v;
if ((v = newdictobject()) == NULL)
fatal("no mem for module table");
if (sysset("modules", v) != 0)
fatal("can't assign sys.modules");
DECREF(v);
if ((modules = newdictobject()) == NULL)
fatal("no mem for dictionary of modules");
}
object *
new_module(name)
get_modules()
{
return modules;
}
object *
add_module(name)
char *name;
{
object *m;
object *mtab;
mtab = sysget("modules");
if (mtab == NULL || !is_dictobject(mtab)) {
errno = EBADF;
return NULL;
}
if ((m = dictlookup(modules, name)) != NULL && is_moduleobject(m))
return m;
m = newmoduleobject(name);
if (m == NULL)
return NULL;
if (dictinsert(mtab, name, m) != 0) {
if (dictinsert(modules, name, m) != 0) {
DECREF(m);
return NULL;
}
DECREF(m); /* Yes, it still exists, in modules! */
return m;
}
static void
use_module(ctx, d)
context *ctx;
object *d;
{
INCREF(d);
DECREF(ctx->ctx_locals);
ctx->ctx_locals = d;
INCREF(d);
DECREF(ctx->ctx_globals);
ctx->ctx_globals = d;
}
static void
define_module(ctx, name)
context *ctx;
char *name;
{
object *m;
m = new_module(name);
if (m == NULL) {
puterrno(ctx);
return;
}
use_module(ctx, getmoduledict(m));
DECREF(m);
}
static object *
parsepath(path, delim)
char *path;
int delim;
{
int i, n;
char *p;
object *v, *w;
n = 1;
p = path;
while ((p = strchr(p, delim)) != NULL) {
n++;
p++;
}
v = newlistobject(n);
if (v == NULL)
return NULL;
for (i = 0; ; i++) {
p = strchr(path, delim);
if (p == NULL)
p = strchr(path, '\0'); /* End of string */
w = newsizedstringobject(path, (int) (p - path));
if (w == NULL) {
DECREF(v);
return NULL;
}
setlistitem(v, i, w);
if (*p == '\0')
break;
path = p+1;
}
return v;
}
void
setpythonpath(path)
char *path;
{
object *v;
if ((v = parsepath(path, DELIM)) != NULL) {
if (sysset("path", v) != 0)
fatal("can't assign sys.path");
DECREF(v);
}
}
static FILE *
open_module(name, suffix)
open_module(name, suffix, namebuf)
char *name;
char *suffix;
char *namebuf; /* XXX No buffer overflow checks! */
{
object *path;
char namebuf[256];
FILE *fp;
path = sysget("path");
@ -169,8 +83,8 @@ open_module(name, suffix)
len = getstringsize(v);
if (len > 0 && namebuf[len-1] != SEP)
namebuf[len++] = SEP;
strcpy(namebuf+len, name); /* XXX check for overflow */
strcat(namebuf, suffix); /* XXX ditto */
strcpy(namebuf+len, name);
strcat(namebuf, suffix);
fp = fopen(namebuf, "r");
if (fp != NULL)
break;
@ -180,119 +94,113 @@ open_module(name, suffix)
}
static object *
load_module(ctx, name)
context *ctx;
get_module(m, name, m_ret)
/*module*/object *m;
char *name;
object **m_ret;
{
object *m;
char **p;
FILE *fp;
node *n;
int err;
object *mtab;
object *save_locals, *save_globals;
mtab = sysget("modules");
if (mtab == NULL || !is_dictobject(mtab)) {
errno = EBADF;
return NULL;
}
fp = open_module(name, ".py");
if (fp == NULL) {
name_error(ctx, name);
return NULL;
}
err = parseinput(fp, file_input, &n);
fclose(fp);
if (err != E_DONE) {
input_error(ctx, err);
return NULL;
}
save_locals = ctx->ctx_locals;
INCREF(save_locals);
save_globals = ctx->ctx_globals;
INCREF(save_globals);
define_module(ctx, name);
exec_node(ctx, n);
DECREF(ctx->ctx_locals);
ctx->ctx_locals = save_locals;
DECREF(ctx->ctx_globals);
ctx->ctx_globals = save_globals;
/* XXX need to free the tree n here; except referenced defs */
if (ctx->ctx_exception) {
dictremove(mtab, name); /* Undefine the module */
return NULL;
}
m = dictlookup(mtab, name);
if (m == NULL) {
error(ctx, "module not defined after loading");
return NULL;
}
return m;
}
object *
import_module(ctx, name)
context *ctx;
char *name;
{
object *m;
object *mtab;
mtab = sysget("modules");
if (mtab == NULL || !is_dictobject(mtab)) {
error(ctx, "bad sys.modules");
return NULL;
}
if ((m = dictlookup(mtab, name)) == NULL) {
m = load_module(ctx, name);
}
return m;
}
object *
reload_module(ctx, m)
context *ctx;
object *m;
{
char *name;
FILE *fp;
node *n;
int err;
object *d;
object *save_locals, *save_globals;
if (m == NULL || !is_moduleobject(m)) {
type_error(ctx, "reload() argument must be module");
return NULL;
}
/* XXX Ought to check for builtin module */
name = getmodulename(m);
fp = open_module(name, ".py");
FILE *fp;
node *n;
int err;
char namebuf[256];
fp = open_module(name, ".py", namebuf);
if (fp == NULL) {
error(ctx, "reload() cannot find module source file");
if (m == NULL)
err_setstr(NameError, name);
else
err_setstr(RuntimeError, "no module source file");
return NULL;
}
err = parseinput(fp, file_input, &n);
err = parse_file(fp, namebuf, file_input, &n);
fclose(fp);
if (err != E_DONE) {
input_error(ctx, err);
err_input(err);
return NULL;
}
d = newdictobject();
if (d == NULL)
return NULL;
setmoduledict(m, d);
save_locals = ctx->ctx_locals;
INCREF(save_locals);
save_globals = ctx->ctx_globals;
INCREF(save_globals);
use_module(ctx, d);
exec_node(ctx, n);
DECREF(ctx->ctx_locals);
ctx->ctx_locals = save_locals;
DECREF(ctx->ctx_globals);
ctx->ctx_globals = save_globals;
if (ctx->ctx_exception)
return NULL;
INCREF(None);
return None;
if (m == NULL) {
m = add_module(name);
if (m == NULL) {
freetree(n);
return NULL;
}
*m_ret = m;
}
d = getmoduledict(m);
return run_node(n, namebuf, d, d);
}
static object *
load_module(name)
char *name;
{
object *m, *v;
v = get_module((object *)NULL, name, &m);
if (v == NULL)
return NULL;
DECREF(v);
return m;
}
object *
import_module(name)
char *name;
{
object *m;
if ((m = dictlookup(modules, name)) == NULL)
m = load_module(name);
return m;
}
object *
reload_module(m)
object *m;
{
if (m == NULL || !is_moduleobject(m)) {
err_setstr(TypeError, "reload() argument must be module");
return NULL;
}
/* XXX Ought to check for builtin modules -- can't reload these... */
return get_module(m, getmodulename(m), (object **)NULL);
}
static void
cleardict(d)
object *d;
{
int i;
for (i = getdictsize(d); --i >= 0; ) {
char *k;
k = getdictkey(d, i);
if (k != NULL)
(void) dictremove(d, k);
}
}
void
doneimport()
{
if (modules != NULL) {
int i;
/* Explicitly erase all modules; this is the safest way
to get rid of at least *some* circular dependencies */
for (i = getdictsize(modules); --i >= 0; ) {
char *k;
k = getdictkey(modules, i);
if (k != NULL) {
object *m;
m = dictlookup(modules, k);
if (m != NULL && is_moduleobject(m)) {
object *d;
d = getmoduledict(m);
if (d != NULL && is_dictobject(d)) {
cleardict(d);
}
}
}
}
cleardict(modules);
}
DECREF(modules);
}

View File

@ -1,36 +1,8 @@
/* Module support implementation */
#include <stdio.h>
#include "PROTO.h"
#include "object.h"
#include "intobject.h"
#include "stringobject.h"
#include "tupleobject.h"
#include "listobject.h"
#include "methodobject.h"
#include "moduleobject.h"
#include "allobjects.h"
#include "modsupport.h"
#include "import.h"
#include "errors.h"
/* Find a method in a module's method table.
Usually called from a module's getattr method. */
object *
findmethod(ml, op, name)
struct methodlist *ml;
object *op;
char *name;
{
for (; ml->ml_name != NULL; ml++) {
if (strcmp(name, ml->ml_name) == 0)
return newmethodobject(ml->ml_name, ml->ml_meth, op);
}
err_setstr(NameError, name);
return NULL;
}
object *
@ -40,21 +12,24 @@ initmodule(name, methods)
{
object *m, *d, *v;
struct methodlist *ml;
if ((m = new_module(name)) == NULL) {
char namebuf[256];
if ((m = add_module(name)) == NULL) {
fprintf(stderr, "initializing module: %s\n", name);
fatal("can't create a module");
}
d = getmoduledict(m);
for (ml = methods; ml->ml_name != NULL; ml++) {
v = newmethodobject(ml->ml_name, ml->ml_meth, (object *)NULL);
sprintf(namebuf, "%s.%s", name, ml->ml_name);
v = newmethodobject(strdup(namebuf), ml->ml_meth,
(object *)NULL);
/* XXX The strdup'ed memory is never freed */
if (v == NULL || dictinsert(d, ml->ml_name, v) != 0) {
fprintf(stderr, "initializing module: %s\n", name);
fatal("can't initialize module");
}
DECREF(v);
}
DECREF(m);
return m; /* Yes, it still exists, in sys.modules... */
return m;
}

View File

@ -1,24 +1,25 @@
/* Python interpreter main program */
#include <stdio.h>
#include <ctype.h>
#include "string.h"
#include "allobjects.h"
extern char *getpythonpath();
#include "PROTO.h"
#include "grammar.h"
#include "node.h"
#include "parsetok.h"
#include "graminit.h"
#include "errcode.h"
#include "object.h"
#include "stringobject.h"
#include "sysmodule.h"
#include "compile.h"
#include "ceval.h"
#include "pythonrun.h"
#include "import.h"
extern char *getpythonpath();
extern grammar gram; /* From graminit.c */
int debugging;
#ifdef DEBUG
int debugging; /* Needed by parser.c */
#endif
main(argc, argv)
int argc;
@ -26,15 +27,12 @@ main(argc, argv)
{
char *filename = NULL;
FILE *fp = stdin;
int ret;
initargs(&argc, &argv);
initintr(); /* For intrcheck() */
initargs(&argc, &argv);
if (argc > 1 && strcmp(argv[1], "-") != 0)
filename = argv[1];
if (filename != NULL) {
if ((fp = fopen(filename, "r")) == NULL) {
fprintf(stderr, "python: can't open file '%s'\n",
@ -43,89 +41,339 @@ main(argc, argv)
}
}
/* XXX what is the ideal initialization order? */
/* XXX exceptions are initialized by initrun but this
may be too late */
initsys(argc-1, argv+1);
inittime();
initmath();
initall();
setpythonpath(getpythonpath());
setpythonargv(argc-1, argv+1);
initrun();
initcalls();
if (!isatty(fileno(fp))) {
ret = runfile(fp, file_input, (char *)NULL, (char *)NULL);
}
else {
object *v, *w;
sysset("ps1", v = newstringobject(">>> "));
sysset("ps2", w = newstringobject("... "));
DECREF(v);
DECREF(w);
for (;;) {
char *ps1 = NULL, *ps2 = NULL;
v = sysget("ps1");
w = sysget("ps2");
if (v != NULL && is_stringobject(v)) {
INCREF(v);
ps1 = getstringvalue(v);
}
else
v = NULL;
if (w != NULL && is_stringobject(w)) {
INCREF(w);
ps2 = getstringvalue(w);
}
else
w = NULL;
ret = runfile(fp, single_input, ps1, ps2);
if (v != NULL)
DECREF(v);
if (w != NULL)
DECREF(w);
if (ret == E_EOF || ret == E_NOMEM)
break;
}
}
goaway(ret == E_DONE || ret == E_EOF ? 0 : 1);
goaway(run(fp, filename == NULL ? "<stdin>" : filename));
/*NOTREACHED*/
}
goaway(sts)
int sts;
/* Initialize all */
void
initall()
{
#ifdef THINK_C
if (sts == 0)
Click_On(0);
#endif
closerun();
donecalls();
exit(sts);
/*NOTREACHED*/
static int inited;
if (inited)
return;
initimport();
initbuiltin(); /* Also initializes builtin exceptions */
initsys();
inittime();
initmath();
initcalls(); /* Configuration-dependent initializations */
initintr(); /* For intrcheck() */
inited = 1;
}
/* Parse input from a file and execute it */
static int
runfile(fp, start, ps1, ps2)
int
run(fp, filename)
FILE *fp;
int start;
char *filename;
{
if (filename == NULL)
filename = "???";
if (isatty(fileno(fp)))
return run_tty_loop(fp, filename);
else
return run_script(fp, filename);
}
int
run_tty_loop(fp, filename)
FILE *fp;
char *filename;
{
object *v;
int ret;
v = sysget("ps1");
if (v == NULL) {
sysset("ps1", v = newstringobject(">>> "));
XDECREF(v);
}
v = sysget("ps2");
if (v == NULL) {
sysset("ps2", v = newstringobject("... "));
XDECREF(v);
}
for (;;) {
ret = run_tty_1(fp, filename);
#ifdef REF_DEBUG
fprintf(stderr, "[%ld refs]\n", ref_total);
#endif
if (ret == E_EOF)
return 0;
/*
if (ret == E_NOMEM)
return -1;
*/
}
}
int
run_tty_1(fp, filename)
FILE *fp;
char *filename;
{
object *m, *d, *v, *w;
node *n;
char *ps1, *ps2;
int err;
v = sysget("ps1");
w = sysget("ps2");
if (v != NULL && is_stringobject(v)) {
INCREF(v);
ps1 = getstringvalue(v);
}
else {
v = NULL;
ps1 = "";
}
if (w != NULL && is_stringobject(w)) {
INCREF(w);
ps2 = getstringvalue(w);
}
else {
w = NULL;
ps2 = "";
}
err = parsefile(fp, filename, &gram, single_input, ps1, ps2, &n);
XDECREF(v);
XDECREF(w);
if (err == E_EOF)
return E_EOF;
if (err != E_DONE) {
err_input(err);
print_error();
return err;
}
m = add_module("__main__");
if (m == NULL)
return -1;
d = getmoduledict(m);
v = run_node(n, filename, d, d);
flushline();
if (v == NULL) {
print_error();
return -1;
}
DECREF(v);
return 0;
}
int
run_script(fp, filename)
FILE *fp;
char *filename;
{
object *m, *d, *v;
m = add_module("__main__");
if (m == NULL)
return -1;
d = getmoduledict(m);
v = run_file(fp, filename, file_input, d, d);
flushline();
if (v == NULL) {
print_error();
return -1;
}
DECREF(v);
return 0;
}
void
print_error()
{
object *exception, *v;
err_get(&exception, &v);
fprintf(stderr, "Unhandled exception: ");
printobject(exception, stderr, PRINT_RAW);
if (v != NULL && v != None) {
fprintf(stderr, ": ");
printobject(v, stderr, PRINT_RAW);
}
fprintf(stderr, "\n");
XDECREF(exception);
XDECREF(v);
printtraceback(stderr);
}
object *
run_string(str, start, globals, locals)
char *str;
int start;
/*dict*/object *globals, *locals;
{
node *n;
int ret;
ret = parsefile(fp, &gram, start, ps1, ps2, &n);
if (ret != E_DONE)
return ret;
return execute(n) == 0 ? E_DONE : E_ERROR;
int err;
err = parse_string(str, start, &n);
return run_err_node(err, n, "<string>", globals, locals);
}
object *
run_file(fp, filename, start, globals, locals)
FILE *fp;
char *filename;
int start;
/*dict*/object *globals, *locals;
{
node *n;
int err;
err = parse_file(fp, filename, start, &n);
return run_err_node(err, n, filename, globals, locals);
}
object *
run_err_node(err, n, filename, globals, locals)
int err;
node *n;
char *filename;
/*dict*/object *globals, *locals;
{
if (err != E_DONE) {
err_input(err);
return NULL;
}
return run_node(n, filename, globals, locals);
}
object *
run_node(n, filename, globals, locals)
node *n;
char *filename;
/*dict*/object *globals, *locals;
{
if (globals == NULL) {
globals = getglobals();
if (locals == NULL)
locals = getlocals();
}
else {
if (locals == NULL)
locals = globals;
}
return eval_node(n, filename, globals, locals);
}
object *
eval_node(n, filename, globals, locals)
node *n;
char *filename;
object *globals;
object *locals;
{
codeobject *co;
object *v;
co = compile(n, filename);
freetree(n);
if (co == NULL)
return NULL;
v = eval_code(co, globals, locals, (object *)NULL);
DECREF(co);
return v;
}
/* Simplified interface to parsefile */
int
parse_file(fp, filename, start, n_ret)
FILE *fp;
char *filename;
int start;
node **n_ret;
{
return parsefile(fp, filename, &gram, start,
(char *)0, (char *)0, n_ret);
}
/* Simplified interface to parsestring */
int
parse_string(str, start, n_ret)
char *str;
int start;
node **n_ret;
{
int err = parsestring(str, &gram, start, n_ret);
/* Don't confuse early end of string with early end of input */
if (err == E_EOF)
err = E_SYNTAX;
return err;
}
/* Print fatal error message and abort */
void
fatal(msg)
char *msg;
{
fprintf(stderr, "Fatal error: %s\n", msg);
abort();
}
/* Clean up and exit */
void
goaway(sts)
int sts;
{
flushline();
/* XXX Call doneimport() before donecalls(), since donecalls()
calls wdone(), and doneimport() may close windows */
doneimport();
donecalls();
err_clear();
#ifdef REF_DEBUG
fprintf(stderr, "[%ld refs]\n", ref_total);
#endif
#ifdef THINK_C
if (sts == 0)
Click_On(0);
#endif
#ifdef TRACE_REFS
if (askyesno("Print left references?")) {
#ifdef THINK_C
Click_On(1);
#endif
printrefs(stderr);
}
#endif /* TRACE_REFS */
exit(sts);
/*NOTREACHED*/
}
static
finaloutput()
{
#ifdef TRACE_REFS
if (!askyesno("Print left references?"))
return;
#ifdef THINK_C
Click_On(1);
#endif /* THINK_C */
printrefs(stderr);
#endif /* TRACE_REFS */
}
/* Ask a yes/no question */
int
static int
askyesno(prompt)
char *prompt;
{
@ -151,15 +399,14 @@ isatty(fd)
#endif
/* WISH LIST
/* XXX WISH LIST
- improved per-module error handling; different use of errno
- possible new types:
- iterator (for range, keys, ...)
- improve interpreter error handling, e.g., true tracebacks
- release parse trees when no longer needed (make them objects?)
- faster parser (for long modules)
- save precompiled modules on file?
- fork threads, locking
- allow syntax extensions
*/
/* "Floccinaucinihilipilification" */

134
Python/structmember.c Normal file
View File

@ -0,0 +1,134 @@
/* Map C struct members to Python object attributes */
#include "allobjects.h"
#include "structmember.h"
object *
getmember(addr, mlist, name)
char *addr;
struct memberlist *mlist;
char *name;
{
struct memberlist *l;
for (l = mlist; l->name != NULL; l++) {
if (strcmp(l->name, name) == 0) {
object *v;
addr += l->offset;
switch (l->type) {
case T_SHORT:
v = newintobject((long) *(short*)addr);
break;
case T_INT:
v = newintobject((long) *(int*)addr);
break;
case T_LONG:
v = newintobject(*(long*)addr);
break;
case T_FLOAT:
v = newfloatobject((double)*(float*)addr);
break;
case T_DOUBLE:
v = newfloatobject(*(double*)addr);
break;
case T_STRING:
if (*(char**)addr == NULL) {
INCREF(None);
v = None;
}
else
v = newstringobject(*(char**)addr);
break;
case T_OBJECT:
v = *(object **)addr;
if (v == NULL)
v = None;
INCREF(v);
break;
default:
err_setstr(SystemError, "bad memberlist type");
v = NULL;
}
return v;
}
}
err_setstr(NameError, name);
return NULL;
}
int
setmember(addr, mlist, name, v)
char *addr;
struct memberlist *mlist;
char *name;
object *v;
{
struct memberlist *l;
for (l = mlist; l->name != NULL; l++) {
if (strcmp(l->name, name) == 0) {
if (l->readonly || l->type == T_STRING) {
err_setstr(RuntimeError, "readonly attribute");
return -1;
}
addr += l->offset;
switch (l->type) {
case T_SHORT:
if (!is_intobject(v)) {
err_badarg();
return -1;
}
*(short*)addr = getintvalue(v);
break;
case T_INT:
if (!is_intobject(v)) {
err_badarg();
return -1;
}
*(int*)addr = getintvalue(v);
break;
case T_LONG:
if (!is_intobject(v)) {
err_badarg();
return -1;
}
*(long*)addr = getintvalue(v);
break;
case T_FLOAT:
if (is_intobject(v))
*(float*)addr = getintvalue(v);
else if (is_floatobject(v))
*(float*)addr = getfloatvalue(v);
else {
err_badarg();
return -1;
}
break;
case T_DOUBLE:
if (is_intobject(v))
*(double*)addr = getintvalue(v);
else if (is_floatobject(v))
*(double*)addr = getfloatvalue(v);
else {
err_badarg();
return -1;
}
break;
case T_OBJECT:
XDECREF(*(object **)addr);
XINCREF(v);
*(object **)addr = v;
break;
default:
err_setstr(SystemError, "bad memberlist type");
return -1;
}
return 0;
}
}
err_setstr(NameError, name);
return NULL;
}

View File

@ -3,31 +3,31 @@
/*
Various bits of information used by the interpreter are collected in
module 'sys'.
Function member:
- exit(sts): call (C, POSIX) exit(sts)
Data members:
- stdin, stdout, stderr: standard file objects
- ps1, ps2: primary and secondary prompts (strings)
- path: module search path (list of strings)
- modules: the table of modules (dictionary)
Function members:
- exit(sts): call exit()
- path: module search path (list of strings)
- argv: script arguments (list of strings)
- ps1, ps2: optional primary and secondary prompts (strings)
*/
#include <stdio.h>
#include "allobjects.h"
#include "PROTO.h"
#include "object.h"
#include "stringobject.h"
#include "listobject.h"
#include "dictobject.h"
#include "fileobject.h"
#include "moduleobject.h"
#include "sysmodule.h"
#include "node.h" /* For context.h */
#include "context.h" /* For import.h */
#include "import.h"
#include "methodobject.h"
#include "modsupport.h"
#include "errors.h"
/* Define delimiter used in $PYTHONPATH */
#ifdef THINK_C
#define DELIM ' '
#endif
#ifndef DELIM
#define DELIM ':'
#endif
static object *sysdict;
@ -63,34 +63,6 @@ sysset(name, v)
return dictinsert(sysdict, name, v);
}
static object *
makeargv(argc, argv)
int argc;
char **argv;
{
int i;
object *av, *v;
if (argc < 0 || argv == NULL)
argc = 0;
av = newlistobject(argc);
if (av != NULL) {
for (i = 0; i < argc; i++) {
v = newstringobject(argv[i]);
if (v == NULL) {
DECREF(av);
av = NULL;
break;
}
setlistitem(av, i, v);
}
}
if (av == NULL)
fatal("no mem for sys.argv");
return av;
}
/* sys.exit method */
static object *
sys_exit(self, args)
object *self;
@ -104,88 +76,115 @@ sys_exit(self, args)
/* NOTREACHED */
}
static struct methodlist sys_methods[] = {
{"exit", sys_exit},
{NULL, NULL} /* sentinel */
};
static object *sysin, *sysout, *syserr;
void
initsys(argc, argv)
int argc;
char **argv;
initsys()
{
object *v;
object *exit;
if ((sysdict = newdictobject()) == NULL)
fatal("can't create sys dict");
object *m = initmodule("sys", sys_methods);
sysdict = getmoduledict(m);
INCREF(sysdict);
/* NB keep an extra ref to the std files to avoid closing them
when the user deletes them */
/* XXX File objects should have a "don't close" flag instead */
sysin = newopenfileobject(stdin, "<stdin>", "r");
sysout = newopenfileobject(stdout, "<stdout>", "w");
syserr = newopenfileobject(stderr, "<stderr>", "w");
v = makeargv(argc, argv);
exit = newmethodobject("exit", sys_exit, (object *)NULL);
if (err_occurred())
fatal("can't create sys.* objects");
fatal("can't create sys.std* file objects");
dictinsert(sysdict, "stdin", sysin);
dictinsert(sysdict, "stdout", sysout);
dictinsert(sysdict, "stderr", syserr);
dictinsert(sysdict, "argv", v);
dictinsert(sysdict, "exit", exit);
dictinsert(sysdict, "modules", get_modules());
if (err_occurred())
fatal("can't insert sys.* objects in sys dict");
DECREF(exit);
DECREF(v);
/* The other symbols are added elsewhere */
/* Only now can we initialize the import stuff, after which
we can turn ourselves into a module */
initimport();
if ((v = new_module("sys")) == NULL)
fatal("can't create sys module");
if (setmoduledict(v, sysdict) != 0)
fatal("can't assign sys dict to sys module");
DECREF(v);
}
static void
cleardict(d)
object *d;
static object *
makepathobject(path, delim)
char *path;
int delim;
{
int i;
for (i = getdictsize(d); --i >= 0; ) {
char *k;
k = getdictkey(d, i);
if (k != NULL) {
(void) dictremove(d, k);
}
int i, n;
char *p;
object *v, *w;
n = 1;
p = path;
while ((p = strchr(p, delim)) != NULL) {
n++;
p++;
}
v = newlistobject(n);
if (v == NULL)
return NULL;
for (i = 0; ; i++) {
p = strchr(path, delim);
if (p == NULL)
p = strchr(path, '\0'); /* End of string */
w = newsizedstringobject(path, (int) (p - path));
if (w == NULL) {
DECREF(v);
return NULL;
}
setlistitem(v, i, w);
if (*p == '\0')
break;
path = p+1;
}
return v;
}
void
closesys()
setpythonpath(path)
char *path;
{
object *modules;
modules = sysget("modules");
if (modules != NULL && is_dictobject(modules)) {
int i;
/* Explicitly erase all modules; this is the safest way
to get rid of at least *some* circular dependencies */
INCREF(modules);
for (i = getdictsize(modules); --i >= 0; ) {
char *k;
k = getdictkey(modules, i);
if (k != NULL) {
object *m;
m = dictlookup(modules, k);
if (m != NULL && is_moduleobject(m)) {
object *d;
d = getmoduledict(m);
if (d != NULL && is_dictobject(d)) {
cleardict(d);
}
}
}
}
cleardict(modules);
DECREF(modules);
}
DECREF(sysdict);
object *v;
if ((v = makepathobject(path, DELIM)) == NULL)
fatal("can't create sys.path");
if (sysset("path", v) != 0)
fatal("can't assign sys.path");
DECREF(v);
}
static object *
makeargvobject(argc, argv)
int argc;
char **argv;
{
object *av;
if (argc < 0 || argv == NULL)
argc = 0;
av = newlistobject(argc);
if (av != NULL) {
int i;
for (i = 0; i < argc; i++) {
object *v = newstringobject(argv[i]);
if (v == NULL) {
DECREF(av);
av = NULL;
break;
}
setlistitem(av, i, v);
}
}
return av;
}
void
setpythonargv(argc, argv)
int argc;
char **argv;
{
object *av = makeargvobject(argc, argv);
if (av == NULL)
fatal("no mem for sys.argv");
if (sysset("argv", av) != 0)
fatal("can't assign sys.argv");
DECREF(av);
}

193
Python/traceback.c Normal file
View File

@ -0,0 +1,193 @@
/* Traceback implementation */
#include "allobjects.h"
#include "compile.h"
#include "frameobject.h"
#include "traceback.h"
#include "structmember.h"
typedef struct _tracebackobject {
OB_HEAD
struct _tracebackobject *tb_next;
frameobject *tb_frame;
int tb_lasti;
int tb_lineno;
} tracebackobject;
#define OFF(x) offsetof(tracebackobject, x)
static struct memberlist tb_memberlist[] = {
{"tb_next", T_OBJECT, OFF(tb_next)},
{"tb_frame", T_OBJECT, OFF(tb_frame)},
{"tb_lasti", T_INT, OFF(tb_lasti)},
{"tb_lineno", T_INT, OFF(tb_lineno)},
{NULL} /* Sentinel */
};
static object *
tb_getattr(tb, name)
tracebackobject *tb;
char *name;
{
return getmember((char *)tb, tb_memberlist, name);
}
static void
tb_dealloc(tb)
tracebackobject *tb;
{
XDECREF(tb->tb_next);
XDECREF(tb->tb_frame);
DEL(tb);
}
static typeobject Tracebacktype = {
OB_HEAD_INIT(&Typetype)
0,
"traceback",
sizeof(tracebackobject),
0,
tb_dealloc, /*tp_dealloc*/
0, /*tp_print*/
tb_getattr, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
};
#define is_tracebackobject(v) ((v)->ob_type == &Tracebacktype)
static tracebackobject *
newtracebackobject(next, frame, lasti, lineno)
tracebackobject *next;
frameobject *frame;
int lasti, lineno;
{
tracebackobject *tb;
if ((next != NULL && !is_tracebackobject(next)) ||
frame == NULL || !is_frameobject(frame)) {
err_badcall();
return NULL;
}
tb = NEWOBJ(tracebackobject, &Tracebacktype);
if (tb != NULL) {
XINCREF(next);
tb->tb_next = next;
XINCREF(frame);
tb->tb_frame = frame;
tb->tb_lasti = lasti;
tb->tb_lineno = lineno;
}
return tb;
}
static tracebackobject *tb_current = NULL;
int
tb_here(frame, lasti, lineno)
frameobject *frame;
int lasti;
int lineno;
{
tracebackobject *tb;
tb = newtracebackobject(tb_current, frame, lasti, lineno);
if (tb == NULL)
return -1;
XDECREF(tb_current);
tb_current = tb;
return 0;
}
object *
tb_fetch()
{
object *v;
v = (object *)tb_current;
tb_current = NULL;
return v;
}
int
tb_store(v)
object *v;
{
if (v != NULL && !is_tracebackobject(v)) {
err_badcall();
return -1;
}
XDECREF(tb_current);
XINCREF(v);
tb_current = (tracebackobject *)v;
return 0;
}
static void
tb_displayline(fp, filename, lineno)
FILE *fp;
char *filename;
int lineno;
{
FILE *xfp;
char buf[1000];
int i;
if (filename[0] == '<' && filename[strlen(filename)-1] == '>')
return;
xfp = fopen(filename, "r");
if (xfp == NULL) {
fprintf(fp, " (cannot open \"%s\")\n", filename);
return;
}
for (i = 0; i < lineno; i++) {
if (fgets(buf, sizeof buf, xfp) == NULL)
break;
}
if (i == lineno) {
char *p = buf;
while (*p == ' ' || *p == '\t')
p++;
fprintf(fp, " %s", p);
if (strchr(p, '\n') == NULL)
fprintf(fp, "\n");
}
fclose(xfp);
}
static void
tb_printinternal(tb, fp)
tracebackobject *tb;
FILE *fp;
{
while (tb != NULL) {
if (intrcheck()) {
fprintf(fp, "[interrupted]\n");
break;
}
fprintf(fp, " File \"");
printobject(tb->tb_frame->f_code->co_filename, fp, PRINT_RAW);
fprintf(fp, "\", line %d\n", tb->tb_lineno);
tb_displayline(fp,
getstringvalue(tb->tb_frame->f_code->co_filename),
tb->tb_lineno);
tb = tb->tb_next;
}
}
int
tb_print(v, fp)
object *v;
FILE *fp;
{
if (v == NULL)
return 0;
if (!is_tracebackobject(v)) {
err_badcall();
return -1;
}
sysset("last_traceback", v);
tb_printinternal((tracebackobject *)v, fp);
return 0;
}