2021-08-19 04:57:11 +00:00
|
|
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
|
|
|
|
│ vi: set et ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi │
|
|
|
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
|
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
|
|
|
│ │
|
|
|
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
|
|
│ any purpose with or without fee is hereby granted, provided that the │
|
|
|
|
│ above copyright notice and this permission notice appear in all copies. │
|
|
|
|
│ │
|
|
|
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
|
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
|
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
|
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
|
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
|
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
|
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
|
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
|
|
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
|
|
#include "libc/assert.h"
|
|
|
|
#include "libc/calls/calls.h"
|
|
|
|
#include "libc/calls/struct/iovec.h"
|
|
|
|
#include "libc/calls/struct/stat.h"
|
|
|
|
#include "libc/fmt/conv.h"
|
|
|
|
#include "libc/log/check.h"
|
|
|
|
#include "libc/log/log.h"
|
2022-09-13 06:10:38 +00:00
|
|
|
#include "libc/mem/gc.h"
|
2021-08-19 04:57:11 +00:00
|
|
|
#include "libc/runtime/runtime.h"
|
|
|
|
#include "libc/sysv/consts/o.h"
|
|
|
|
#include "libc/x/x.h"
|
2022-09-13 06:10:38 +00:00
|
|
|
#include "libc/x/xasprintf.h"
|
2023-07-03 02:57:43 +00:00
|
|
|
#include "third_party/getopt/getopt.internal.h"
|
2021-08-19 04:57:11 +00:00
|
|
|
#include "third_party/python/Include/bytesobject.h"
|
|
|
|
#include "third_party/python/Include/compile.h"
|
|
|
|
#include "third_party/python/Include/fileutils.h"
|
|
|
|
#include "third_party/python/Include/import.h"
|
|
|
|
#include "third_party/python/Include/marshal.h"
|
|
|
|
#include "third_party/python/Include/pydebug.h"
|
|
|
|
#include "third_party/python/Include/pylifecycle.h"
|
|
|
|
#include "third_party/python/Include/pymacro.h"
|
|
|
|
#include "third_party/python/Include/pythonrun.h"
|
2021-09-07 18:40:11 +00:00
|
|
|
#include "third_party/python/Include/ucnhash.h"
|
|
|
|
#include "third_party/python/Include/yoink.h"
|
2023-11-28 22:24:28 +00:00
|
|
|
#include "libc/serialize.h"
|
2021-09-04 22:44:00 +00:00
|
|
|
#include "tool/build/lib/stripcomponents.h"
|
2021-08-19 04:57:11 +00:00
|
|
|
|
2023-07-26 20:54:49 +00:00
|
|
|
__static_yoink("_PyUnicode_GetCode");
|
2021-09-28 05:58:51 +00:00
|
|
|
|
2021-08-19 04:57:11 +00:00
|
|
|
#define MANUAL "\
|
|
|
|
SYNOPSIS\n\
|
|
|
|
\n\
|
2024-03-03 00:57:56 +00:00
|
|
|
pycomp [FLAGS] SOURCE\n\
|
2021-08-19 04:57:11 +00:00
|
|
|
\n\
|
|
|
|
OVERVIEW\n\
|
|
|
|
\n\
|
|
|
|
Python Compiler\n\
|
|
|
|
\n\
|
|
|
|
FLAGS\n\
|
|
|
|
\n\
|
|
|
|
-o PATH specified output pyc file\n\
|
2021-08-18 21:21:30 +00:00
|
|
|
-O0 don't optimize [default]\n\
|
|
|
|
-O1 remove debug statements\n\
|
|
|
|
-O2 remove debug statements and docstrings\n\
|
2021-08-19 04:57:11 +00:00
|
|
|
-n do nothing\n\
|
|
|
|
-h help\n\
|
|
|
|
\n\
|
|
|
|
EXAMPLE\n\
|
|
|
|
\n\
|
2024-03-03 00:57:56 +00:00
|
|
|
pycomp -o foo/__pycache__/__init__.cpython-3.6.pyc foo/__init__.py\n\
|
2021-08-19 04:57:11 +00:00
|
|
|
\n"
|
|
|
|
|
2021-08-18 21:21:30 +00:00
|
|
|
int optimize;
|
2021-08-19 04:57:11 +00:00
|
|
|
char *inpath;
|
|
|
|
char *outpath;
|
|
|
|
|
|
|
|
void
|
|
|
|
GetOpts(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
int opt;
|
2021-08-18 21:21:30 +00:00
|
|
|
while ((opt = getopt(argc, argv, "hnO:o:")) != -1) {
|
2021-08-19 04:57:11 +00:00
|
|
|
switch (opt) {
|
|
|
|
case 'O':
|
2021-08-18 21:21:30 +00:00
|
|
|
optimize = atoi(optarg);
|
2021-08-19 04:57:11 +00:00
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
outpath = optarg;
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
exit(0);
|
|
|
|
case 'h':
|
|
|
|
fputs(MANUAL, stdout);
|
|
|
|
exit(0);
|
|
|
|
default:
|
|
|
|
fputs(MANUAL, stderr);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (argc - optind != 1) {
|
|
|
|
fputs("error: need one input file\n", stderr);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
inpath = argv[optind];
|
|
|
|
if (!outpath) {
|
2021-08-18 21:21:30 +00:00
|
|
|
outpath = xasprintf("%sc", inpath);
|
2021-08-19 04:57:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
char *name;
|
|
|
|
ssize_t rc;
|
|
|
|
size_t i, n;
|
|
|
|
struct stat st;
|
2023-09-02 03:49:13 +00:00
|
|
|
char *p, m[12];
|
2021-08-19 04:57:11 +00:00
|
|
|
PyObject *code, *marshalled;
|
2021-08-18 21:21:30 +00:00
|
|
|
ShowCrashReports();
|
2021-08-19 04:57:11 +00:00
|
|
|
GetOpts(argc, argv);
|
|
|
|
marshalled = 0;
|
|
|
|
if (stat(inpath, &st) == -1) perror(inpath), exit(1);
|
2024-01-08 18:07:35 +00:00
|
|
|
CHECK_NOTNULL((p = gc(xslurp(inpath, &n))));
|
2021-08-19 04:57:11 +00:00
|
|
|
Py_NoUserSiteDirectory++;
|
|
|
|
Py_NoSiteFlag++;
|
|
|
|
Py_IgnoreEnvironmentFlag++;
|
|
|
|
Py_FrozenFlag++;
|
2021-09-07 18:40:11 +00:00
|
|
|
/* Py_VerboseFlag++; */
|
2024-01-08 18:07:35 +00:00
|
|
|
Py_SetProgramName(gc(utf8to32(argv[0], -1, 0)));
|
2021-08-19 04:57:11 +00:00
|
|
|
_Py_InitializeEx_Private(1, 0);
|
2024-01-08 18:07:35 +00:00
|
|
|
name = gc(xjoinpaths("/zip/.python", StripComponents(inpath, 3)));
|
2021-08-19 04:57:11 +00:00
|
|
|
code = Py_CompileStringExFlags(p, name, Py_file_input, NULL, optimize);
|
|
|
|
if (!code) goto error;
|
|
|
|
marshalled = PyMarshal_WriteObjectToString(code, Py_MARSHAL_VERSION);
|
|
|
|
Py_CLEAR(code);
|
|
|
|
if (!marshalled) goto error;
|
|
|
|
assert(PyBytes_CheckExact(marshalled));
|
|
|
|
p = PyBytes_AS_STRING(marshalled);
|
|
|
|
n = PyBytes_GET_SIZE(marshalled);
|
|
|
|
CHECK_NE(-1, (fd = open(outpath, O_CREAT|O_TRUNC|O_WRONLY, 0644)));
|
2022-05-13 12:05:12 +00:00
|
|
|
WRITE16LE(m+0, 3390); /* Python 3.7a1 */
|
2021-08-19 04:57:11 +00:00
|
|
|
WRITE16LE(m+2, READ16LE("\r\n"));
|
|
|
|
WRITE32LE(m+4, st.st_mtim.tv_sec); /* tsk tsk y2038 */
|
|
|
|
WRITE32LE(m+8, n);
|
|
|
|
CHECK_EQ(sizeof(m), write(fd, m, sizeof(m)));
|
|
|
|
for (i = 0; i < n; i += rc) {
|
|
|
|
CHECK_NE(-1, (rc = write(fd, p + i, n - i)));
|
|
|
|
}
|
|
|
|
CHECK_NE(-1, close(fd));
|
|
|
|
Py_CLEAR(marshalled);
|
|
|
|
Py_Finalize();
|
|
|
|
return 0;
|
|
|
|
error:
|
|
|
|
PyErr_Print();
|
|
|
|
Py_Finalize();
|
|
|
|
if (marshalled) Py_DECREF(marshalled);
|
|
|
|
return 1;
|
|
|
|
}
|