/* This is built as a stand-alone executable by the Makefile, and helps turn
   Lib/importlib/_bootstrap.py into a frozen module in Python/importlib.h
*/

#include <Python.h>
#include <marshal.h>

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifndef MS_WINDOWS
#include <unistd.h>
#endif

/* To avoid a circular dependency on frozen.o, we create our own structure
   of frozen modules instead, left deliberately blank so as to avoid
   unintentional import of a stale version of _frozen_importlib. */

static const struct _frozen _PyImport_FrozenModules[] = {
    {0, 0, 0} /* sentinel */
};

#ifndef MS_WINDOWS
/* On Windows, this links with the regular pythonXY.dll, so this variable comes
   from frozen.obj. In the Makefile, frozen.o is not linked into this executable,
   so we define the variable here. */
const struct _frozen *PyImport_FrozenModules;
#endif

static const char header[] =
    "/* Auto-generated by Programs/_freeze_importlib.c */";

int
main(int argc, char *argv[])
{
    const char *name, *inpath, *outpath;
    char buf[100];
    FILE *infile = NULL, *outfile = NULL;
    struct _Py_stat_struct status;
    size_t text_size, data_size, i, n;
    char *text = NULL;
    unsigned char *data;
    PyObject *code = NULL, *marshalled = NULL;

    PyImport_FrozenModules = _PyImport_FrozenModules;

    if (argc != 4) {
        fprintf(stderr, "need to specify the name, input and output paths\n");
        return 2;
    }
    name = argv[1];
    inpath = argv[2];
    outpath = argv[3];
    infile = fopen(inpath, "rb");
    if (infile == NULL) {
        fprintf(stderr, "cannot open '%s' for reading\n", inpath);
        goto error;
    }
    if (_Py_fstat_noraise(fileno(infile), &status)) {
        fprintf(stderr, "cannot fstat '%s'\n", inpath);
        goto error;
    }
    text_size = (size_t)status.st_size;
    text = (char *) malloc(text_size + 1);
    if (text == NULL) {
        fprintf(stderr, "could not allocate %ld bytes\n", (long) text_size);
        goto error;
    }
    n = fread(text, 1, text_size, infile);
    fclose(infile);
    infile = NULL;
    if (n < text_size) {
        fprintf(stderr, "read too short: got %ld instead of %ld bytes\n",
                (long) n, (long) text_size);
        goto error;
    }
    text[text_size] = '\0';

    _PyCoreConfig config = _PyCoreConfig_INIT;
    config.user_site_directory = 0;
    config.site_import = 0;
    config.use_environment = 0;
    config.program_name = L"./_freeze_importlib";
    /* Don't install importlib, since it could execute outdated bytecode. */
    config._install_importlib = 0;
    config._frozen = 1;

    _PyInitError err = _Py_InitializeFromConfig(&config);
    /* No need to call _PyCoreConfig_Clear() since we didn't allocate any
       memory: program_name is a constant string. */
    if (_Py_INIT_FAILED(err)) {
        _Py_FatalInitError(err);
    }

    sprintf(buf, "<frozen %s>", name);
    code = Py_CompileStringExFlags(text, buf, Py_file_input, NULL, 0);
    if (code == NULL)
        goto error;
    free(text);
    text = NULL;

    marshalled = PyMarshal_WriteObjectToString(code, Py_MARSHAL_VERSION);
    Py_CLEAR(code);
    if (marshalled == NULL)
        goto error;

    assert(PyBytes_CheckExact(marshalled));
    data = (unsigned char *) PyBytes_AS_STRING(marshalled);
    data_size = PyBytes_GET_SIZE(marshalled);

    /* Open the file in text mode. The hg checkout should be using the eol extension,
       which in turn should cause the EOL style match the C library's text mode */
    outfile = fopen(outpath, "w");
    if (outfile == NULL) {
        fprintf(stderr, "cannot open '%s' for writing\n", outpath);
        goto error;
    }
    fprintf(outfile, "%s\n", header);
    for (i = n = 0; name[i] != '\0'; i++) {
        if (name[i] != '.') {
            buf[n++] = name[i];
        }
    }
    buf[n] = '\0';
    fprintf(outfile, "const unsigned char _Py_M__%s[] = {\n", buf);
    for (n = 0; n < data_size; n += 16) {
        size_t i, end = Py_MIN(n + 16, data_size);
        fprintf(outfile, "    ");
        for (i = n; i < end; i++) {
            fprintf(outfile, "%d,", (unsigned int) data[i]);
        }
        fprintf(outfile, "\n");
    }
    fprintf(outfile, "};\n");

    Py_CLEAR(marshalled);

    Py_Finalize();
    if (outfile) {
        if (ferror(outfile)) {
            fprintf(stderr, "error when writing to '%s'\n", outpath);
            goto error;
        }
        fclose(outfile);
    }
    return 0;

error:
    PyErr_Print();
    Py_Finalize();
    if (infile)
        fclose(infile);
    if (outfile)
        fclose(outfile);
    if (text)
        free(text);
    if (marshalled)
        Py_DECREF(marshalled);
    return 1;
}
