this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include <cstring>
3
4#include "cpython-data.h"
5#include "cpython-func.h"
6#include "cpython-types.h"
7
8extern "C" {
9// Python-ast.h is an internal header. Redeclare the only things we need from
10// it instead of including it.
11typedef struct _mod* mod_ty;
12PyObject* PyAST_mod2obj(mod_ty t);
13}
14
15static const char* source_as_string(PyObject* cmd, PyCompilerFlags* cf,
16 PyObject** cmd_copy) {
17 Py_buffer view;
18 Py_ssize_t size;
19 const char* str;
20 *cmd_copy = nullptr;
21 if (PyUnicode_Check(cmd)) {
22 cf->cf_flags |= PyCF_IGNORE_COOKIE;
23 str = PyUnicode_AsUTF8AndSize(cmd, &size);
24 if (str == nullptr) return nullptr;
25 } else if (PyBytes_Check(cmd)) {
26 str = PyBytes_AS_STRING(cmd);
27 size = PyBytes_GET_SIZE(cmd);
28 } else if (PyByteArray_Check(cmd)) {
29 str = PyByteArray_AS_STRING(cmd);
30 size = PyByteArray_GET_SIZE(cmd);
31 } else if (PyObject_GetBuffer(cmd, &view, PyBUF_SIMPLE) == 0) {
32 // Copy to NUL-terminated buffer.
33 *cmd_copy = PyBytes_FromStringAndSize(
34 const_cast<const char*>(reinterpret_cast<char*>(view.buf)), view.len);
35 PyBuffer_Release(&view);
36 if (*cmd_copy == nullptr) {
37 return nullptr;
38 }
39 str = PyBytes_AS_STRING(*cmd_copy);
40 size = PyBytes_GET_SIZE(*cmd_copy);
41 } else {
42 PyErr_Format(PyExc_TypeError,
43 "parse() arg 1 must be a string, bytes or AST object");
44 return nullptr;
45 }
46
47 if (strlen(str) != static_cast<size_t>(size)) {
48 PyErr_SetString(PyExc_ValueError,
49 "source code string cannot contain null bytes");
50 Py_CLEAR(*cmd_copy);
51 return nullptr;
52 }
53 return str;
54}
55
56static PyObject* parse(PyObject* /* module */, PyObject** args,
57 Py_ssize_t nargs, PyObject* kwnames) {
58 static const char* const parser_kwnames[] = {"source", "filename", "mode",
59 "flags", nullptr};
60 static _PyArg_Parser parser = {"OO&s|i:compile", parser_kwnames, nullptr};
61 PyObject* source;
62 PyObject* filename;
63 const char* mode;
64 int flags = 0;
65 if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &parser, &source,
66 PyUnicode_FSDecoder, &filename, &mode,
67 &flags)) {
68 return nullptr;
69 }
70
71 int compile_mode = -1;
72 if (std::strcmp(mode, "exec") == 0) {
73 compile_mode = 0;
74 } else if (std::strcmp(mode, "eval") == 0) {
75 compile_mode = 1;
76 } else if (std::strcmp(mode, "single") == 0) {
77 compile_mode = 2;
78 } else {
79 PyErr_SetString(PyExc_ValueError,
80 "parse() mode must be 'exec', 'eval' or 'single'");
81 Py_DECREF(filename);
82 return nullptr;
83 }
84
85 PyCompilerFlags cf = _PyCompilerFlags_INIT;
86 cf.cf_flags = flags | PyCF_SOURCE_IS_UTF8;
87 PyArena* arena = PyArena_New();
88 if (arena == nullptr) return nullptr;
89
90 PyObject* source_copy;
91 const char* str = source_as_string(source, &cf, &source_copy);
92 if (str == nullptr) {
93 Py_DECREF(filename);
94 PyArena_Free(arena);
95 return nullptr;
96 }
97
98 static const int start[] = {Py_file_input, Py_eval_input, Py_single_input};
99 mod_ty mod = PyParser_ASTFromStringObject(str, filename, start[compile_mode],
100 &cf, arena);
101 if (mod == nullptr) {
102 Py_XDECREF(source_copy);
103 PyArena_Free(arena);
104 return nullptr;
105 }
106 PyObject* result = PyAST_mod2obj(mod);
107 Py_XDECREF(source_copy);
108 PyArena_Free(arena);
109 return result;
110}
111
112static PyMethodDef _parse_methods[] = {
113 {"parse",
114 reinterpret_cast<PyCFunction>(reinterpret_cast<void (*)()>(parse)),
115 METH_FASTCALL | METH_KEYWORDS, ""},
116 {nullptr, nullptr}};
117
118static struct PyModuleDef _parsermodule = {
119 PyModuleDef_HEAD_INIT,
120 "_parser",
121 "",
122 0,
123 _parse_methods,
124 nullptr,
125 nullptr,
126 nullptr,
127 nullptr,
128};
129
130PyMODINIT_FUNC PyInit__parser() {
131 PyObject* module = PyState_FindModule(&_parsermodule);
132 if (module != nullptr) {
133 Py_INCREF(module);
134 return module;
135 }
136 module = PyModule_Create(&_parsermodule);
137 if (module == nullptr) {
138 return nullptr;
139 }
140
141 PyState_AddModule(module, &_parsermodule);
142 return module;
143}