1 #!/usr/bin/env python 2 """ 3 Create a C file for embedding one or more Cython source files. 4 Requires Cython 0.11.2 (or perhaps newer). 5 6 See Demos/freeze/README.txt for more details. 7 """ 8 9 import optparse 10 from os.path import splitext, basename 11 12 usage= '%prog [-o outfile] [-p] module [module ...]' 13 description = 'Create a C file for embedding Cython modules.' 14 p = optparse.OptionParser(usage=usage, description=description) 15 p.add_option('-o', '--output', metavar='FILE', 16 help='write output to FILE instead of standard output') 17 p.add_option('-p', '--pymain', action='store_true', default=False, 18 help='do not automatically run the first module as __main__') 19 20 options, args = p.parse_args() 21 22 if len(args) < 1: 23 p.print_help() 24 p.exit(1) 25 26 if options.output: 27 import sys 28 old_stdout = sys.stdout 29 sys.stdout = open(options.output, 'w') 30 31 modules = [basename(splitext(x)[0]).replace('.', '_') for x in args] 32 33 print """\ 34 #include <Python.h> 35 #include <locale.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 39 #ifdef __FreeBSD__ 40 #include <floatingpoint.h> 41 #endif 42 43 #if PY_MAJOR_VERSION < 3 44 # define MODINIT(name) init ## name 45 #else 46 # define MODINIT(name) PyInit_ ## name 47 #endif 48 """ 49 50 for name in modules: 51 print "PyMODINIT_FUNC MODINIT(%s) (void);" % name 52 53 print """ 54 static struct _inittab inittab[] = {""" 55 56 for name in modules: 57 print ' {"%(name)s", MODINIT(%(name)s)},' % {'name' : name} 58 59 print """ {NULL, NULL} 60 }; 61 """, 62 63 if not options.pymain: 64 print "\nextern int __pyx_module_is_main_%s;" % modules[0] 65 66 print """ 67 #if PY_MAJOR_VERSION < 3 68 int main(int argc, char** argv) { 69 #elif defined(WIN32) || defined(MS_WINDOWS) 70 int wmain(int argc, wchar_t **argv) { 71 #else 72 static int python_main(int argc, wchar_t **argv) { 73 #endif 74 """, 75 if not options.pymain: 76 print """\ 77 PyObject *m = NULL; 78 int r = 0; 79 """, 80 print """\ 81 /* 754 requires that FP exceptions run in "no stop" mode by default, 82 * and until C vendors implement C99's ways to control FP exceptions, 83 * Python requires non-stop mode. Alas, some platforms enable FP 84 * exceptions by default. Here we disable them. 85 */ 86 #ifdef __FreeBSD__ 87 fp_except_t m; 88 89 m = fpgetmask(); 90 fpsetmask(m & ~FP_X_OFL); 91 #endif 92 if (PyImport_ExtendInittab(inittab)) { 93 fprintf(stderr, "No memory\\n"); 94 exit(1); 95 } 96 """, 97 if options.pymain: 98 print """\ 99 return Py_Main(argc, argv); 100 } 101 """ 102 else: 103 print """\ 104 Py_SetProgramName(argv[0]); 105 Py_Initialize(); 106 PySys_SetArgv(argc, argv); 107 __pyx_module_is_main_%(main)s = 1; 108 m = PyImport_ImportModule(inittab[0].name); 109 if (!m) { 110 r = 1; 111 PyErr_Print(); /* This exits with the right code if SystemExit. */ 112 #if PY_MAJOR_VERSION < 3 113 if (Py_FlushLine()) 114 PyErr_Clear(); 115 #endif 116 } 117 Py_XDECREF(m); 118 Py_Finalize(); 119 return r; 120 } 121 """ % {'main' : modules[0]}, 122 123 print r""" 124 #if PY_MAJOR_VERSION >= 3 && !defined(WIN32) && !defined(MS_WINDOWS) 125 static wchar_t* 126 char2wchar(char* arg) 127 { 128 wchar_t *res; 129 #ifdef HAVE_BROKEN_MBSTOWCS 130 /* Some platforms have a broken implementation of 131 * mbstowcs which does not count the characters that 132 * would result from conversion. Use an upper bound. 133 */ 134 size_t argsize = strlen(arg); 135 #else 136 size_t argsize = mbstowcs(NULL, arg, 0); 137 #endif 138 size_t count; 139 unsigned char *in; 140 wchar_t *out; 141 #ifdef HAVE_MBRTOWC 142 mbstate_t mbs; 143 #endif 144 if (argsize != (size_t)-1) { 145 res = (wchar_t *)malloc((argsize+1)*sizeof(wchar_t)); 146 if (!res) 147 goto oom; 148 count = mbstowcs(res, arg, argsize+1); 149 if (count != (size_t)-1) { 150 wchar_t *tmp; 151 /* Only use the result if it contains no 152 surrogate characters. */ 153 for (tmp = res; *tmp != 0 && 154 (*tmp < 0xd800 || *tmp > 0xdfff); tmp++) 155 ; 156 if (*tmp == 0) 157 return res; 158 } 159 free(res); 160 } 161 /* Conversion failed. Fall back to escaping with surrogateescape. */ 162 #ifdef HAVE_MBRTOWC 163 /* Try conversion with mbrtwoc (C99), and escape non-decodable bytes. */ 164 165 /* Overallocate; as multi-byte characters are in the argument, the 166 actual output could use less memory. */ 167 argsize = strlen(arg) + 1; 168 res = malloc(argsize*sizeof(wchar_t)); 169 if (!res) goto oom; 170 in = (unsigned char*)arg; 171 out = res; 172 memset(&mbs, 0, sizeof mbs); 173 while (argsize) { 174 size_t converted = mbrtowc(out, (char*)in, argsize, &mbs); 175 if (converted == 0) 176 /* Reached end of string; null char stored. */ 177 break; 178 if (converted == (size_t)-2) { 179 /* Incomplete character. This should never happen, 180 since we provide everything that we have - 181 unless there is a bug in the C library, or I 182 misunderstood how mbrtowc works. */ 183 fprintf(stderr, "unexpected mbrtowc result -2\n"); 184 return NULL; 185 } 186 if (converted == (size_t)-1) { 187 /* Conversion error. Escape as UTF-8b, and start over 188 in the initial shift state. */ 189 *out++ = 0xdc00 + *in++; 190 argsize--; 191 memset(&mbs, 0, sizeof mbs); 192 continue; 193 } 194 if (*out >= 0xd800 && *out <= 0xdfff) { 195 /* Surrogate character. Escape the original 196 byte sequence with surrogateescape. */ 197 argsize -= converted; 198 while (converted--) 199 *out++ = 0xdc00 + *in++; 200 continue; 201 } 202 /* successfully converted some bytes */ 203 in += converted; 204 argsize -= converted; 205 out++; 206 } 207 #else 208 /* Cannot use C locale for escaping; manually escape as if charset 209 is ASCII (i.e. escape all bytes > 128. This will still roundtrip 210 correctly in the locale's charset, which must be an ASCII superset. */ 211 res = malloc((strlen(arg)+1)*sizeof(wchar_t)); 212 if (!res) goto oom; 213 in = (unsigned char*)arg; 214 out = res; 215 while(*in) 216 if(*in < 128) 217 *out++ = *in++; 218 else 219 *out++ = 0xdc00 + *in++; 220 *out = 0; 221 #endif 222 return res; 223 oom: 224 fprintf(stderr, "out of memory\n"); 225 return NULL; 226 } 227 228 int 229 main(int argc, char **argv) 230 { 231 wchar_t **argv_copy = (wchar_t **)malloc(sizeof(wchar_t*)*argc); 232 /* We need a second copies, as Python might modify the first one. */ 233 wchar_t **argv_copy2 = (wchar_t **)malloc(sizeof(wchar_t*)*argc); 234 int i, res; 235 char *oldloc; 236 if (!argv_copy || !argv_copy2) { 237 fprintf(stderr, "out of memory\n"); 238 return 1; 239 } 240 oldloc = strdup(setlocale(LC_ALL, NULL)); 241 setlocale(LC_ALL, ""); 242 for (i = 0; i < argc; i++) { 243 argv_copy2[i] = argv_copy[i] = char2wchar(argv[i]); 244 if (!argv_copy[i]) 245 return 1; 246 } 247 setlocale(LC_ALL, oldloc); 248 free(oldloc); 249 res = python_main(argc, argv_copy); 250 for (i = 0; i < argc; i++) { 251 free(argv_copy2[i]); 252 } 253 free(argv_copy); 254 free(argv_copy2); 255 return res; 256 } 257 #endif""" 258