mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
39bf41f4eb
- Python static hello world now 1.8mb - Python static fully loaded now 10mb - Python HTTPS client now uses MbedTLS - Python REPL now completes import stmts - Increase stack size for Python for now - Begin synthesizing posixpath and ntpath - Restore Python \N{UNICODE NAME} support - Restore Python NFKD symbol normalization - Add optimized code path for Intel SHA-NI - Get more Python unit tests passing faster - Get Python help() pagination working on NT - Python hashlib now supports MbedTLS PBKDF2 - Make memcpy/memmove/memcmp/bcmp/etc. faster - Add Mersenne Twister and Vigna to LIBC_RAND - Provide privileged __printf() for error code - Fix zipos opendir() so that it reports ENOTDIR - Add basic chmod() implementation for Windows NT - Add Cosmo's best functions to Python cosmo module - Pin function trace indent depth to that of caller - Show memory diagram on invalid access in MODE=dbg - Differentiate stack overflow on crash in MODE=dbg - Add stb_truetype and tools for analyzing font files - Upgrade to UNICODE 13 and reduce its binary footprint - COMPILE.COM now logs resource usage of build commands - Start implementing basic poll() support on bare metal - Set getauxval(AT_EXECFN) to GetModuleFileName() on NT - Add descriptions to strerror() in non-TINY build modes - Add COUNTBRANCH() macro to help with micro-optimizations - Make error / backtrace / asan / memory code more unbreakable - Add fast perfect C implementation of μ-Law and a-Law audio codecs - Make strtol() functions consistent with other libc implementations - Improve Linenoise implementation (see also github.com/jart/bestline) - COMPILE.COM now suppresses stdout/stderr of successful build commands
157 lines
5.5 KiB
C
157 lines
5.5 KiB
C
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│
|
|
│vi: set net 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/bits/bits.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"
|
|
#include "libc/runtime/gc.internal.h"
|
|
#include "libc/runtime/runtime.h"
|
|
#include "libc/sysv/consts/o.h"
|
|
#include "libc/x/x.h"
|
|
#include "third_party/getopt/getopt.h"
|
|
#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"
|
|
#include "third_party/python/Include/ucnhash.h"
|
|
#include "third_party/python/Include/yoink.h"
|
|
#include "tool/build/lib/stripcomponents.h"
|
|
/* clang-format off */
|
|
|
|
STATIC_YOINK("_PyUnicode_GetCode");
|
|
|
|
#define MANUAL "\
|
|
SYNOPSIS\n\
|
|
\n\
|
|
pycomp.com [FLAGS] SOURCE\n\
|
|
\n\
|
|
OVERVIEW\n\
|
|
\n\
|
|
Python Compiler\n\
|
|
\n\
|
|
FLAGS\n\
|
|
\n\
|
|
-o PATH specified output pyc file\n\
|
|
-O0 don't optimize [default]\n\
|
|
-O1 remove debug statements\n\
|
|
-O2 remove debug statements and docstrings\n\
|
|
-n do nothing\n\
|
|
-h help\n\
|
|
\n\
|
|
EXAMPLE\n\
|
|
\n\
|
|
pycomp.com -o foo/__pycache__/__init__.cpython-3.6.pyc foo/__init__.py\n\
|
|
\n"
|
|
|
|
int optimize;
|
|
char *inpath;
|
|
char *outpath;
|
|
|
|
void
|
|
GetOpts(int argc, char *argv[])
|
|
{
|
|
int opt;
|
|
char *outdir;
|
|
while ((opt = getopt(argc, argv, "hnO:o:")) != -1) {
|
|
switch (opt) {
|
|
case 'O':
|
|
optimize = atoi(optarg);
|
|
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) {
|
|
outpath = xasprintf("%sc", inpath);
|
|
}
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
int fd;
|
|
char *name;
|
|
ssize_t rc;
|
|
size_t i, n;
|
|
struct stat st;
|
|
char *s, *p, m[12];
|
|
PyObject *code, *marshalled;
|
|
ShowCrashReports();
|
|
GetOpts(argc, argv);
|
|
marshalled = 0;
|
|
if (stat(inpath, &st) == -1) perror(inpath), exit(1);
|
|
CHECK_NOTNULL((p = gc(xslurp(inpath, &n))));
|
|
Py_NoUserSiteDirectory++;
|
|
Py_NoSiteFlag++;
|
|
Py_IgnoreEnvironmentFlag++;
|
|
Py_FrozenFlag++;
|
|
/* Py_VerboseFlag++; */
|
|
Py_SetProgramName(gc(utf8toutf32(argv[0], -1, 0)));
|
|
_Py_InitializeEx_Private(1, 0);
|
|
name = gc(xjoinpaths("/zip/.python", StripComponents(inpath, 3)));
|
|
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)));
|
|
WRITE16LE(m+0, 3379); /* Python 3.6rc1 */
|
|
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;
|
|
}
|