Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit db3165e

Browse files
committed
* bltinmodule.c: removed exec() built-in function.
* Grammar: add exec statement; allow testlist in expr statement. * ceval.c, compile.c, opcode.h: support exec statement; avoid optimizing locals when it is used * fileobject.{c,h}: add getfilename() internal function.
1 parent cacd957 commit db3165e

9 files changed

Lines changed: 585 additions & 436 deletions

File tree

Grammar/Grammar

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
# Change log:
44

5+
# 18-Oct-93:
6+
# Use testlist instead of exprlist in expr_stmt
7+
# Add exec statement
8+
59
# 19-May-93:
610
# Add access statement
711

@@ -87,8 +91,8 @@ fplist: fpdef (',' fpdef)* [',']
8791

8892
stmt: simple_stmt | compound_stmt
8993
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
90-
small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | access_stmt
91-
expr_stmt: (exprlist '=')* exprlist
94+
small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | access_stmt | exec_stmt
95+
expr_stmt: (testlist '=')* testlist
9296
# For assignments, additional restrictions enforced by the interpreter
9397
print_stmt: 'print' (test ',')* [test]
9498
del_stmt: 'del' exprlist
@@ -104,6 +108,7 @@ access_stmt: 'access' ('*' | NAME (',' NAME)*) ':' accesstype (',' accesstype)*
104108
accesstype: NAME+
105109
# accesstype should be ('public' | 'protected' | 'private') ['read'] ['write']
106110
# but can't be because that would create undesirable reserved words!
111+
exec_stmt: 'exec' expr ['in' expr [',' expr]]
107112

108113
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
109114
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]

Include/fileobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ extern object *newfileobject PROTO((char *, char *));
3838
extern object *newopenfileobject
3939
PROTO((FILE *, char *, char *, int (*)FPROTO((FILE *))));
4040
extern FILE *getfilefile PROTO((object *));
41+
extern object *getfilename PROTO((object *));
4142
extern object *filegetline PROTO((object *, int));
4243

4344
#ifdef __cplusplus

Include/graminit.h

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,30 @@
2323
#define global_stmt 278
2424
#define access_stmt 279
2525
#define accesstype 280
26-
#define compound_stmt 281
27-
#define if_stmt 282
28-
#define while_stmt 283
29-
#define for_stmt 284
30-
#define try_stmt 285
31-
#define except_clause 286
32-
#define suite 287
33-
#define test 288
34-
#define and_test 289
35-
#define not_test 290
36-
#define comparison 291
37-
#define comp_op 292
38-
#define expr 293
39-
#define xor_expr 294
40-
#define and_expr 295
41-
#define shift_expr 296
42-
#define arith_expr 297
43-
#define term 298
44-
#define factor 299
45-
#define atom 300
46-
#define trailer 301
47-
#define subscript 302
48-
#define exprlist 303
49-
#define testlist 304
50-
#define dictmaker 305
51-
#define classdef 306
26+
#define exec_stmt 281
27+
#define compound_stmt 282
28+
#define if_stmt 283
29+
#define while_stmt 284
30+
#define for_stmt 285
31+
#define try_stmt 286
32+
#define except_clause 287
33+
#define suite 288
34+
#define test 289
35+
#define and_test 290
36+
#define not_test 291
37+
#define comparison 292
38+
#define comp_op 293
39+
#define expr 294
40+
#define xor_expr 295
41+
#define and_expr 296
42+
#define shift_expr 297
43+
#define arith_expr 298
44+
#define term 299
45+
#define factor 300
46+
#define atom 301
47+
#define trailer 302
48+
#define subscript 303
49+
#define exprlist 304
50+
#define testlist 305
51+
#define dictmaker 306
52+
#define classdef 307

Include/opcode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
7878
#define RAISE_EXCEPTION 81
7979
#define LOAD_LOCALS 82
8080
#define RETURN_VALUE 83
81+
#define LOAD_GLOBALS 84
82+
#define EXEC_STMT 85
8183

8284
#define BUILD_FUNCTION 86
8385
#define POP_BLOCK 87

Objects/fileobject.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ getfilefile(f)
5151
return ((fileobject *)f)->f_fp;
5252
}
5353

54+
object *
55+
getfilename(f)
56+
object *f;
57+
{
58+
if (f == NULL || !is_fileobject(f))
59+
return NULL;
60+
else
61+
return ((fileobject *)f)->f_name;
62+
}
63+
5464
object *
5565
newopenfileobject(fp, name, mode, close)
5666
FILE *fp;

Python/bltinmodule.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -232,14 +232,6 @@ builtin_eval(self, v)
232232
return exec_eval(v, eval_input);
233233
}
234234

235-
static object *
236-
builtin_exec(self, v)
237-
object *self;
238-
object *v;
239-
{
240-
return exec_eval(v, file_input);
241-
}
242-
243235
static object *
244236
builtin_execfile(self, v)
245237
object *self;
@@ -755,7 +747,6 @@ static struct methodlist builtin_methods[] = {
755747
{"dir", builtin_dir},
756748
{"divmod", builtin_divmod},
757749
{"eval", builtin_eval},
758-
{"exec", builtin_exec},
759750
{"execfile", builtin_execfile},
760751
{"float", builtin_float},
761752
{"getattr", builtin_getattr},

Python/ceval.c

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3535
#include "opcode.h"
3636
#include "bltinmodule.h"
3737
#include "traceback.h"
38+
#include "graminit.h"
39+
#include "pythonrun.h"
3840

3941
/* Turn this on if your compiler chokes on the big switch: */
4042
/* #define CASE_TOO_BIG 1 /**/
@@ -91,6 +93,7 @@ static object *build_class PROTO((object *, object *, object *));
9193
static void locals_2_fast PROTO((frameobject *, int));
9294
static void fast_2_locals PROTO((frameobject *));
9395
static int access_statement PROTO((object *, object *, frameobject *));
96+
static int exec_statement PROTO((object *, object *, object *));
9497

9598

9699
/* Pointer to current frame, used to link new frames to */
@@ -712,6 +715,22 @@ eval_code(co, globals, locals, owner, arg)
712715
retval = POP();
713716
why = WHY_RETURN;
714717
break;
718+
719+
case LOAD_GLOBALS:
720+
v = f->f_locals;
721+
INCREF(v);
722+
PUSH(v);
723+
break;
724+
725+
case EXEC_STMT:
726+
w = POP();
727+
v = POP();
728+
u = POP();
729+
err = exec_statement(u, v, w);
730+
DECREF(u);
731+
DECREF(v);
732+
DECREF(w);
733+
break;
715734

716735
case BUILD_FUNCTION:
717736
v = POP();
@@ -2489,3 +2508,62 @@ access_statement(name, vmode, f)
24892508
}
24902509
return ret;
24912510
}
2511+
2512+
static int
2513+
exec_statement(prog, globals, locals)
2514+
object *prog;
2515+
object *globals;
2516+
object *locals;
2517+
{
2518+
char *s;
2519+
int n;
2520+
2521+
if (is_tupleobject(prog) && globals == None && locals == None &&
2522+
((n = gettuplesize(prog)) == 2 || n == 3)) {
2523+
/* Backward compatibility hack */
2524+
globals = gettupleitem(prog, 1);
2525+
if (n == 3)
2526+
locals = gettupleitem(prog, 2);
2527+
prog = gettupleitem(prog, 0);
2528+
}
2529+
if (globals == None) {
2530+
globals = getglobals();
2531+
if (locals == None)
2532+
locals = getlocals();
2533+
}
2534+
else if (locals == None)
2535+
locals = globals;
2536+
if (!is_stringobject(prog) &&
2537+
!is_codeobject(prog) &&
2538+
!is_fileobject(prog)) {
2539+
err_setstr(TypeError,
2540+
"exec 1st arg must be string, code or file object");
2541+
return -1;
2542+
}
2543+
if (!is_dictobject(globals) || !is_dictobject(locals)) {
2544+
err_setstr(TypeError,
2545+
"exec 2nd/3rd args must be dict or None");
2546+
return -1;
2547+
}
2548+
if (is_codeobject(prog)) {
2549+
if (eval_code((codeobject *) prog, globals, locals,
2550+
(object *)NULL, (object *)NULL) == NULL)
2551+
return -1;
2552+
return 0;
2553+
}
2554+
if (is_fileobject(prog)) {
2555+
FILE *fp = getfilefile(prog);
2556+
char *name = getstringvalue(getfilename(prog));
2557+
if (run_file(fp, name, file_input, globals, locals) == NULL)
2558+
return -1;
2559+
return 0;
2560+
}
2561+
s = getstringvalue(prog);
2562+
if (strlen(s) != getstringsize(prog)) {
2563+
err_setstr(ValueError, "embedded '\\0' in exec string");
2564+
return -1;
2565+
}
2566+
if (run_string(s, file_input, globals, locals) == NULL)
2567+
return -1;
2568+
return 0;
2569+
}

Python/compile.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1305,7 +1305,7 @@ com_expr_stmt(c, n)
13051305
struct compiling *c;
13061306
node *n;
13071307
{
1308-
REQ(n, expr_stmt); /* exprlist ('=' exprlist)* */
1308+
REQ(n, expr_stmt); /* testlist ('=' testlist)* */
13091309
com_node(c, CHILD(n, NCH(n)-1));
13101310
if (NCH(n) == 1) {
13111311
com_addbyte(c, PRINT_EXPR);
@@ -1466,6 +1466,25 @@ com_access_stmt(c, n)
14661466
}
14671467
}
14681468

1469+
static void
1470+
com_exec_stmt(c, n)
1471+
struct compiling *c;
1472+
node *n;
1473+
{
1474+
REQ(n, exec_stmt);
1475+
/* exec_stmt: 'exec' expr ['in' expr [',' expr]] */
1476+
com_node(c, CHILD(n, 1));
1477+
if (NCH(n) >= 4)
1478+
com_node(c, CHILD(n, 3));
1479+
else
1480+
com_addoparg(c, LOAD_CONST, com_addconst(c, None));
1481+
if (NCH(n) >= 6)
1482+
com_node(c, CHILD(n, 5));
1483+
else
1484+
com_addbyte(c, DUP_TOP);
1485+
com_addbyte(c, EXEC_STMT);
1486+
}
1487+
14691488
static void
14701489
com_if_stmt(c, n)
14711490
struct compiling *c;
@@ -1909,6 +1928,9 @@ com_node(c, n)
19091928
case access_stmt:
19101929
com_access_stmt(c, n);
19111930
break;
1931+
case exec_stmt:
1932+
com_exec_stmt(c, n);
1933+
break;
19121934
case if_stmt:
19131935
com_if_stmt(c, n);
19141936
break;
@@ -2183,6 +2205,8 @@ optimize(c)
21832205
opcode = NEXTOP();
21842206
if (opcode == STOP_CODE)
21852207
break;
2208+
if (opcode == EXEC_STMT)
2209+
goto end; /* Don't optimize if exec present */
21862210
if (HAS_ARG(opcode))
21872211
oparg = NEXTARG();
21882212
if (opcode == STORE_NAME || opcode == DELETE_NAME ||

0 commit comments

Comments
 (0)