ยปCore Development>Code coverage>Programs/_freeze_importlib.c

Python code coverage for Programs/_freeze_importlib.c

#countcontent
1n/a/* This is built as a stand-alone executable by the Makefile, and helps turn
2n/a Lib/importlib/_bootstrap.py into a frozen module in Python/importlib.h
3n/a*/
4n/a
5n/a#include <Python.h>
6n/a#include <marshal.h>
7n/a
8n/a#include <stdio.h>
9n/a#include <sys/types.h>
10n/a#include <sys/stat.h>
11n/a#ifndef MS_WINDOWS
12n/a#include <unistd.h>
13n/a#endif
14n/a
15n/a/* To avoid a circular dependency on frozen.o, we create our own structure
16n/a of frozen modules instead, left deliberately blank so as to avoid
17n/a unintentional import of a stale version of _frozen_importlib. */
18n/a
19n/astatic const struct _frozen _PyImport_FrozenModules[] = {
20n/a {0, 0, 0} /* sentinel */
21n/a};
22n/a
23n/a#ifndef MS_WINDOWS
24n/a/* On Windows, this links with the regular pythonXY.dll, so this variable comes
25n/a from frozen.obj. In the Makefile, frozen.o is not linked into this executable,
26n/a so we define the variable here. */
27n/aconst struct _frozen *PyImport_FrozenModules;
28n/a#endif
29n/a
30n/aconst char header[] = "/* Auto-generated by Programs/_freeze_importlib.c */";
31n/a
32n/aint
33n/amain(int argc, char *argv[])
34n/a{
35n/a char *inpath, *outpath, *code_name;
36n/a FILE *infile = NULL, *outfile = NULL;
37n/a struct _Py_stat_struct status;
38n/a size_t text_size, data_size, n;
39n/a char *text = NULL;
40n/a unsigned char *data;
41n/a PyObject *code = NULL, *marshalled = NULL;
42n/a int is_bootstrap = 1;
43n/a
44n/a PyImport_FrozenModules = _PyImport_FrozenModules;
45n/a
46n/a if (argc != 3) {
47n/a fprintf(stderr, "need to specify input and output paths\n");
48n/a return 2;
49n/a }
50n/a inpath = argv[1];
51n/a outpath = argv[2];
52n/a infile = fopen(inpath, "rb");
53n/a if (infile == NULL) {
54n/a fprintf(stderr, "cannot open '%s' for reading\n", inpath);
55n/a goto error;
56n/a }
57n/a if (_Py_fstat_noraise(fileno(infile), &status)) {
58n/a fprintf(stderr, "cannot fstat '%s'\n", inpath);
59n/a goto error;
60n/a }
61n/a text_size = (size_t)status.st_size;
62n/a text = (char *) malloc(text_size + 1);
63n/a if (text == NULL) {
64n/a fprintf(stderr, "could not allocate %ld bytes\n", (long) text_size);
65n/a goto error;
66n/a }
67n/a n = fread(text, 1, text_size, infile);
68n/a fclose(infile);
69n/a infile = NULL;
70n/a if (n < text_size) {
71n/a fprintf(stderr, "read too short: got %ld instead of %ld bytes\n",
72n/a (long) n, (long) text_size);
73n/a goto error;
74n/a }
75n/a text[text_size] = '\0';
76n/a
77n/a Py_NoUserSiteDirectory++;
78n/a Py_NoSiteFlag++;
79n/a Py_IgnoreEnvironmentFlag++;
80n/a Py_FrozenFlag++;
81n/a
82n/a Py_SetProgramName(L"./_freeze_importlib");
83n/a /* Don't install importlib, since it could execute outdated bytecode. */
84n/a _Py_InitializeEx_Private(1, 0);
85n/a
86n/a if (strstr(inpath, "_external") != NULL) {
87n/a is_bootstrap = 0;
88n/a }
89n/a
90n/a code_name = is_bootstrap ?
91n/a "<frozen importlib._bootstrap>" :
92n/a "<frozen importlib._bootstrap_external>";
93n/a code = Py_CompileStringExFlags(text, code_name, Py_file_input, NULL, 0);
94n/a if (code == NULL)
95n/a goto error;
96n/a free(text);
97n/a text = NULL;
98n/a
99n/a marshalled = PyMarshal_WriteObjectToString(code, Py_MARSHAL_VERSION);
100n/a Py_CLEAR(code);
101n/a if (marshalled == NULL)
102n/a goto error;
103n/a
104n/a assert(PyBytes_CheckExact(marshalled));
105n/a data = (unsigned char *) PyBytes_AS_STRING(marshalled);
106n/a data_size = PyBytes_GET_SIZE(marshalled);
107n/a
108n/a /* Open the file in text mode. The hg checkout should be using the eol extension,
109n/a which in turn should cause the EOL style match the C library's text mode */
110n/a outfile = fopen(outpath, "w");
111n/a if (outfile == NULL) {
112n/a fprintf(stderr, "cannot open '%s' for writing\n", outpath);
113n/a goto error;
114n/a }
115n/a fprintf(outfile, "%s\n", header);
116n/a if (is_bootstrap)
117n/a fprintf(outfile, "const unsigned char _Py_M__importlib[] = {\n");
118n/a else
119n/a fprintf(outfile,
120n/a "const unsigned char _Py_M__importlib_external[] = {\n");
121n/a for (n = 0; n < data_size; n += 16) {
122n/a size_t i, end = Py_MIN(n + 16, data_size);
123n/a fprintf(outfile, " ");
124n/a for (i = n; i < end; i++) {
125n/a fprintf(outfile, "%d,", (unsigned int) data[i]);
126n/a }
127n/a fprintf(outfile, "\n");
128n/a }
129n/a fprintf(outfile, "};\n");
130n/a
131n/a Py_CLEAR(marshalled);
132n/a
133n/a Py_Finalize();
134n/a if (outfile) {
135n/a if (ferror(outfile)) {
136n/a fprintf(stderr, "error when writing to '%s'\n", outpath);
137n/a goto error;
138n/a }
139n/a fclose(outfile);
140n/a }
141n/a return 0;
142n/a
143n/aerror:
144n/a PyErr_Print();
145n/a Py_Finalize();
146n/a if (infile)
147n/a fclose(infile);
148n/a if (outfile)
149n/a fclose(outfile);
150n/a if (text)
151n/a free(text);
152n/a if (marshalled)
153n/a Py_DECREF(marshalled);
154n/a return 1;
155n/a}