Commit 3f5da24e authored by Guido van Rossum's avatar Guido van Rossum

"Compiling" version

parent 226d79eb
/* "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 *));
/* Built-in module interface */
extern object *getbuiltin PROTO((char *));
/* 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 *));
......@@ -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 *));
......
/* 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 *));
......@@ -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));
/* 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 *));
......@@ -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));
/* 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));
......@@ -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])
......@@ -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 *));
/* 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 *));
......@@ -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 *));
......@@ -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 *));
#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
......@@ -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 *));
/* 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)
/* 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));
/* 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 *));
......@@ -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));
/* 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));
/* 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 *));
......@@ -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));
/* 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 *));
......@@ -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])
......@@ -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
......
......@@ -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.
......
/* 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;
......
/* 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 !!! */
......
......@@ -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 */
......
/* 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 */
......
/* 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*/
......
......@@ -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*/
};
......@@ -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));
......
/* 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;
}
/* 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*/
......
/* 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();
}
else {
NEWREF(op);
op->ob_type = &Inttype;
op->ob_ival = ival;
register intobject *v;
if (free_list == NULL) {
if ((free_list = fill_free_list()) == NULL)
return NULL;
}
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*/
......
/* 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)
......
/* 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;
}
/* 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*/
};
/* 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"
int StopPrint; /* Flag to indicate printing must be stopped */
#ifdef REF_DEBUG
long ref_total;
#endif
/* 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);
}
......
/* 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)
......
/* 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)
......
/* 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*/
};
/* 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
}
/* Bitset primitives */
/* Bitset primitives used by the parser generator */
#include "PROTO.h"
#include "malloc.h"
#include "pgenheaders.h"
#include "bitset.h"
bitset
......
/* 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);
}
}
/* 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]);
}
/* Grammar subroutines needed by parser */
#include "PROTO.h"
#define NULL 0
#include "pgenheaders.h"
#include "assert.h"
#include "grammar.h"
#include "token.h"
......
......@@ -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>
......
/* 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);
}
#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},
......
/* 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);
}
}
......@@ -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;
}
......
......@@ -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));
/* 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;
/* Parse input coming from the given tokenizer structure.
Return error code. */
static int
parsetok(tok, g, start, n_ret)
struct tok_state *tok;
grammar *g;
int start;
node **n_ret;
{
parser_state *ps;
int ret;
if ((ps = newparser(g, start)) == NULL) {
fprintf(stderr, "no mem for new parser\n");
return E_NOMEM;
}
for (;;) {
char *a, *b;
int type;
int len;
char *str;
type = tok_get(tok, &a, &b);
if (type == ERRORTOKEN) {
ret = tok->done;
break;
}
len = b - a;
str = NEW(char, len + 1);
if (str == NULL) {
fprintf(stderr, "no mem for next token\n");
ret = E_NOMEM;
break;
}
strncpy(str, a, len);
str[len] = '\0';
ret = addtoken(ps, (int)type, str);
if (ret != E_OK) {
if (ret == E_DONE) {
*n_ret = ps->p_tree;
ps->p_tree = NULL;
}
else if (tok->lineno <= 1 && tok->done == E_EOF)
ret = E_EOF;
break;
}
}
delparser(ps);
return ret;
}
/* Forward */
static int parsetok PROTO((struct tok_state *, grammar *, int, node **));
/* Parse input coming from a string. Return error code. */
/* Parse input coming from a string. Return error code, print some errors. */
int
parsestring(s, g, start, n_ret)
......@@ -94,11 +39,12 @@ parsestring(s, g, start, n_ret)
}
/* Parse input coming from a file. Return error code. */
/* Parse input coming from a file. Return error code, print some errors. */
int
parsefile(fp, g, start, ps1, ps2, n_ret)
parsefile(fp, filename, g, start, ps1, ps2, n_ret)
FILE *fp;
char *filename;
grammar *g;
int start;
char *ps1, *ps2;
......@@ -114,7 +60,8 @@ parsefile(fp, g, start, ps1, ps2, n_ret)
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);
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';
......@@ -130,3 +77,58 @@ parsefile(fp, g, start, ps1, ps2, n_ret)
tok_free(tok);
return ret;
}
/* Parse input coming from the given tokenizer structure.
Return error code. */
static int
parsetok(tok, g, start, n_ret)
struct tok_state *tok;
grammar *g;
int start;
node **n_ret;
{
parser_state *ps;
int ret;
if ((ps = newparser(g, start)) == NULL) {
fprintf(stderr, "no mem for new parser\n");
return E_NOMEM;
}
for (;;) {
char *a, *b;
int type;
int len;
char *str;
type = tok_get(tok, &a, &b);
if (type == ERRORTOKEN) {
ret = tok->done;
break;
}
len = b - a;
str = NEW(char, len + 1);
if (str == NULL) {
fprintf(stderr, "no mem for next token\n");
ret = E_NOMEM;
break;
}
strncpy(str, a, len);
str[len] = '\0';
ret = addtoken(ps, (int)type, str, tok->lineno);
if (ret != E_OK) {
if (ret == E_DONE) {
*n_ret = ps->p_tree;
ps->p_tree = NULL;
}
else if (tok->lineno <= 1 && tok->done == E_EOF)
ret = E_EOF;
break;
}
}
delparser(ps);
return ret;
}
/* 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"
......
......@@ -3,4 +3,4 @@
extern grammar gram;
extern grammar *meta_grammar PROTO((void));
extern grammar *pgen PROTO((node *));
extern grammar *pgen PROTO((struct _node *));
/* 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,24 +16,51 @@
int debugging;
/* Forward */
grammar *getgrammar PROTO((char *filename));
#ifdef THINK_C
char *
askfile()
int main PROTO((int, char **));
char *askfile PROTO((void));
#endif
int
main(argc, argv)
int argc;
char **argv;
{
char buf[256];
static char name[256];
printf("Input file name: ");
if (fgets(buf, sizeof buf, stdin) == NULL) {
printf("EOF\n");
grammar *g;
node *n;
FILE *fp;
char *filename;
#ifdef THINK_C
filename = askfile();
#else
if (argc != 2) {
fprintf(stderr, "usage: %s grammar\n", argv[0]);
exit(2);
}
filename = argv[1];
#endif
g = getgrammar(filename);
fp = fopen("graminit.c", "w");
if (fp == NULL) {
perror("graminit.c");
exit(1);
}
if (sscanf(buf, " %s ", name) != 1) {
printf("No file\n");
printf("Writing graminit.c ...\n");
printgrammar(g, fp);
fclose(fp);
fp = fopen("graminit.h", "w");
if (fp == NULL) {
perror("graminit.h");
exit(1);
}
return name;
printf("Writing graminit.h ...\n");
printnonterminals(g, fp);
fclose(fp);
exit(0);
}
#endif
grammar *
getgrammar(filename)
......@@ -44,7 +77,7 @@ getgrammar(filename)
}
g0 = meta_grammar();
n = NULL;
parsefile(fp, g0, g0->g_start, (char *)NULL, (char *)NULL, &n);
parsefile(fp, filename, g0, g0->g_start, (char *)NULL, (char *)NULL, &n);
fclose(fp);
if (n == NULL) {
fprintf(stderr, "Parsing error.\n");
......@@ -58,43 +91,25 @@ getgrammar(filename)
return g;
}
main(argc, argv)
int argc;
char **argv;
{
grammar *g;
node *n;
FILE *fp;
char *filename;
#ifdef THINK_C
filename = askfile();
#else
if (argc != 2) {
fprintf(stderr, "usage: %s grammar\n", argv[0]);
exit(2);
}
filename = argv[1];
#endif
g = getgrammar(filename);
fp = fopen("graminit.c", "w");
if (fp == NULL) {
perror("graminit.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);
}
printf("Writing graminit.c ...\n");
printgrammar(g, fp);
fclose(fp);
fp = fopen("graminit.h", "w");
if (fp == NULL) {
perror("graminit.h");
/* XXX The (unsigned char *) case is needed by THINK C */
if (sscanf((unsigned char *)buf, " %s ", name) != 1) {
printf("No file\n");
exit(1);
}
printf("Writing graminit.h ...\n");
printnonterminals(g, fp);
fclose(fp);
exit(0);
return name;
}
#endif
void
fatal(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)
*/
/* 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);
}
......@@ -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;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -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;
}
}
#include "PROTO.h"
#include "pgenheaders.h"
#include "grammar.h"
static arc arcs_0_0[3] = {
{2, 1},
......
/* 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;
object *d;
FILE *fp;
node *n;
int err;
object *mtab;
object *save_locals, *save_globals;
char namebuf[256];
mtab = sysget("modules");
if (mtab == NULL || !is_dictobject(mtab)) {
errno = EBADF;
return NULL;
}
fp = open_module(name, ".py");
fp = open_module(name, ".py", namebuf);
if (fp == NULL) {
name_error(ctx, name);
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);
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 */
err_input(err);
return NULL;
}
m = dictlookup(mtab, name);
if (m == NULL) {
error(ctx, "module not defined after loading");
return 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(ctx, name)
context *ctx;
import_module(name)
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);
}
if ((m = dictlookup(modules, name)) == NULL)
m = load_module(name);
return m;
}
object *
reload_module(ctx, m)
context *ctx;
reload_module(m)
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");
err_setstr(TypeError, "reload() argument must be module");
return NULL;
}
/* XXX Ought to check for builtin module */
name = getmodulename(m);
fp = open_module(name, ".py");
if (fp == NULL) {
error(ctx, "reload() cannot find module source file");
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);
}
err = parseinput(fp, file_input, &n);
fclose(fp);
if (err != E_DONE) {
input_error(ctx, err);
return NULL;
}
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);
}
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;
DECREF(modules);
}
/* 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;
}
......
/* 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 */
initall();
setpythonpath(getpythonpath());
setpythonargv(argc-1, argv+1);
goaway(run(fp, filename == NULL ? "<stdin>" : filename));
/*NOTREACHED*/
}
/* Initialize all */
void
initall()
{
static int inited;
if (inited)
return;
initimport();
initsys(argc-1, argv+1);
initbuiltin(); /* Also initializes builtin exceptions */
initsys();
inittime();
initmath();
setpythonpath(getpythonpath());
initcalls(); /* Configuration-dependent initializations */
initrun();
initcalls();
initintr(); /* For intrcheck() */
if (!isatty(fileno(fp))) {
ret = runfile(fp, file_input, (char *)NULL, (char *)NULL);
inited = 1;
}
/* Parse input from a file and execute it */
int
run(fp, filename)
FILE *fp;
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 {
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;
}
v = NULL;
ps1 = "";
}
goaway(ret == E_DONE || ret == E_EOF ? 0 : 1);
/*NOTREACHED*/
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 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
closerun();
donecalls();
#ifdef TRACE_REFS
if (askyesno("Print left references?")) {
#ifdef THINK_C
Click_On(1);
#endif
printrefs(stderr);
}
#endif /* TRACE_REFS */
exit(sts);
/*NOTREACHED*/
}
/* Parse input from a file and execute it */
static int
runfile(fp, start, ps1, ps2)
FILE *fp;
int start;
char *ps1, *ps2;
static
finaloutput()
{
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;
#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" */
/* 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;
}
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment