1/*
2 * Workaround to make NSAppicationMain more usable from Python.
3 */
4#include <Python.h>
5#include "pyobjc-api.h"
6
7#import <AppKit/AppKit.h>
8
9static PyObject*
10objc_NSApplicationMain(
11	PyObject* self __attribute__((__unused__)),
12	PyObject* args,
13	PyObject* kwds)
14{
15static	char* keywords[] = { "argv", NULL };
16	char** argv = NULL;
17	int    argc;
18	PyObject* arglist;
19	int       i;
20	PyObject* v;
21	int       res;
22
23	if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:NSApplicationMain",
24			keywords, &arglist)) {
25		return NULL;
26	}
27
28	if (!PySequence_Check(arglist)) {
29		PyErr_SetString(PyExc_TypeError,
30			"NSApplicationMain: need list of strings as argument");
31		return NULL;
32	}
33
34	argc = PySequence_Size(arglist);
35	argv = calloc((argc + 1), sizeof(char**));
36	if (argv == NULL) {
37		PyErr_SetString(PyExc_MemoryError,
38			"Out of memory");
39		return NULL;
40	}
41
42	for  (i = 0; i < argc; i++) {
43		v = PySequence_GetItem(arglist, i);
44		if (v == NULL) {
45			goto error_cleanup;
46		}
47		if (PyUnicode_Check(v)) {
48			PyObject* bytes = PyUnicode_AsEncodedString(v,
49					NULL, NULL);
50			if (!bytes) {
51				goto error_cleanup;
52			}
53			argv[i] = strdup(PyBytes_AsString(bytes));
54#if PY_MAJOR_VERSION == 2
55		} else if (PyString_Check(v)) {
56			argv[i] = strdup(PyString_AsString(v));
57#endif
58		} else {
59			PyErr_SetString(PyExc_TypeError,
60				"NSApplicationMain: need list of strings "
61				"as argument");
62			goto error_cleanup;
63		}
64
65		if (argv[i] == NULL) {
66			PyErr_SetString(PyExc_MemoryError,
67				"Out of memory");
68			goto error_cleanup;
69		}
70	}
71
72	argv[argc] = NULL;
73
74	PyObjC_DURING
75		res = NSApplicationMain(argc, (const char**)argv);
76	PyObjC_HANDLER
77		PyObjCErr_FromObjC(localException);
78		res = -1;
79	PyObjC_ENDHANDLER
80
81	for (i = 0; i < argc; i++) {
82		free(argv[i]);
83	}
84	free(argv);
85
86	if (res == -1 && PyErr_Occurred())
87		return NULL;
88	return PyInt_FromLong(res);
89
90error_cleanup:
91	if (argv != NULL) {
92		for (i = 0; i < argc; i++) {
93			if (argv[i] != NULL) {
94				free(argv[i]);
95				argv[i] = NULL;
96			}
97		}
98		free(argv);
99		argv = NULL;
100	}
101
102	return NULL;
103}
104
105
106#define APPKIT_APPMAIN_METHODS \
107	{  							\
108		"NSApplicationMain", 				\
109		(PyCFunction)objc_NSApplicationMain, 		\
110		METH_VARARGS|METH_KEYWORDS, 			\
111		"int NSApplicationMain(int argc, const char *argv[]);" \
112	},
113