7
#define PY_POPT_VERSION "0.2"
9
static const char *rcs_id = "$Id: poptmodule.c,v 1.1.2.4 2001/08/27 18:38:26 jbj Exp $";
11
static char *module_doc = "Python bindings for the popt library\n\
13
The popt library provides useful command-line parsing functions.\n\
14
The latest version of the popt library is distributed with rpm\n\
15
and is always available from ftp://ftp.rpm.org/pub/rpm/dist";
23
#define debug(x, y) { printf("%s: %s\n", x, y); }
25
#define debug(x, y) {}
28
/* Functins and datatypes needed for the context object */
29
typedef struct poptContext_s {
31
struct poptOption *options;
34
/* The index of the option retrieved with getNextOpt()*/
39
static PyObject *pypoptError;
42
void __printPopt(struct poptOption *opts)
44
printf("+++++++++++\n");
45
printf("Long name: %s\n", opts->longName);
46
printf("Short name: %c\n", opts->shortName);
47
printf("argInfo: %d\n", opts->argInfo);
48
printf("Val: %d\n", opts->val);
49
printf("-----------\n");
52
static PyObject * __poptOptionValue2PyObject(const struct poptOption *option)
55
/* This shouldn't really happen */
56
PyErr_BadInternalCall();
59
if (option->arg == NULL) {
63
switch(option->argInfo) {
64
case POPT_ARG_INCLUDE_TABLE:
69
if (*(char **)(option->arg) == NULL) {
73
return PyString_FromString(*(char **)(option->arg));
76
return PyFloat_FromDouble(*(double *)(option->arg));
79
return PyInt_FromLong(*(long *)(option->arg));
83
return PyInt_FromLong(*(int *)(option->arg));
86
/* This shouldn't really happen */
87
PyErr_BadInternalCall();
91
static PyObject * ctxReset(poptContextObject *self, PyObject *args)
93
if (!PyArg_ParseTuple(args, ""))
95
poptResetContext(self->ctx);
101
static PyObject * ctxGetNextOpt(poptContextObject *self, PyObject *args)
103
if (!PyArg_ParseTuple(args, ""))
105
self->opt = poptGetNextOpt(self->ctx);
106
return PyInt_FromLong(self->opt);
109
static PyObject * ctxGetOptArg(poptContextObject *self, PyObject *args)
112
if (!PyArg_ParseTuple(args, ""))
114
opt = poptGetOptArg(self->ctx);
119
return PyString_FromString(opt);
122
static PyObject * ctxGetArg(poptContextObject *self, PyObject *args)
125
if (!PyArg_ParseTuple(args, ""))
127
arg = poptGetArg(self->ctx);
132
return PyString_FromString(arg);
135
static PyObject * ctxPeekArg(poptContextObject *self, PyObject *args)
138
if (!PyArg_ParseTuple(args, ""))
140
arg = poptPeekArg(self->ctx);
145
return PyString_FromString(arg);
148
static PyObject * ctxGetArgs(poptContextObject *self, PyObject *argsFoo)
153
if (!PyArg_ParseTuple(argsFoo, ""))
155
args = poptGetArgs(self->ctx);
160
/* Compute the list size */
161
for (size = 0; args[size]; size++);
162
/* Create the list */
163
list = PyList_New(size);
166
for (i = 0; i < size; i++)
167
PyList_SetItem(list, i, PyString_FromString(args[i]));
171
static PyObject * ctxBadOption(poptContextObject *self, PyObject *args)
174
const char *badOption;
175
if (!PyArg_ParseTuple(args, "|i", &flags))
177
badOption = poptBadOption(self->ctx, flags);
178
if (badOption == NULL) {
182
return PyString_FromString(badOption);
185
static PyObject * ctxReadDefaultConfig(poptContextObject *self, PyObject *args)
188
if (!PyArg_ParseTuple(args, "|i", &flags))
190
return PyInt_FromLong(poptReadDefaultConfig(self->ctx, flags));
193
static PyObject * ctxReadConfigFile(poptContextObject *self, PyObject *args)
195
const char *filename;
196
if (!PyArg_ParseTuple(args, "s", &filename))
198
return PyInt_FromLong(poptReadConfigFile(self->ctx, filename));
201
static PyObject * ctxSetOtherOptionHelp(poptContextObject *self, PyObject *args)
204
if (!PyArg_ParseTuple(args, "s", &option))
206
poptSetOtherOptionHelp(self->ctx, option);
211
static PyObject * ctxPrintHelp(poptContextObject *self, PyObject *args)
216
if (!PyArg_ParseTuple(args, "|O!i", &PyFile_Type, &file, &flags))
218
f = PyFile_AsFile(file);
221
poptPrintHelp(self->ctx, f, flags);
226
static PyObject * ctxPrintUsage(poptContextObject *self, PyObject *args)
231
if (!PyArg_ParseTuple(args, "|O!i", &PyFile_Type, &file, &flags))
233
f = PyFile_AsFile(file);
236
poptPrintUsage(self->ctx, f, flags);
243
/* XXX callbackType */
245
/*******************************/
246
/* Added ctxGetOptValues */
247
/*******************************/
248
/* Builds a list of values corresponding to each option */
249
static PyObject * ctxGetOptValues(poptContextObject *self, PyObject *args)
253
if (!PyArg_ParseTuple(args, ""))
255
/* Create the list */
256
list = PyList_New(self->optionsNo);
259
for (i = 0; i < self->optionsNo; i++) {
261
item = __poptOptionValue2PyObject(self->options + i);
262
item = __poptOptionValue2PyObject(self->options + i);
265
PyList_SetItem(list, i, item);
270
static PyObject * ctxGetOptValue(poptContextObject *self, PyObject *args)
273
if (!PyArg_ParseTuple(args, ""))
280
/* Look for the option that returned this value */
281
for (i = 0; i < self->optionsNo; i++)
282
if (self->options[i].val == self->opt) {
283
/* Cool, this is the one */
284
return __poptOptionValue2PyObject(self->options + i);
291
static struct PyMethodDef ctxMethods[] = {
292
{"reset", (PyCFunction)ctxReset, METH_VARARGS},
293
{"getNextOpt", (PyCFunction)ctxGetNextOpt, METH_VARARGS},
294
{"getOptArg", (PyCFunction)ctxGetOptArg, METH_VARARGS},
295
{"getArg", (PyCFunction)ctxGetArg, METH_VARARGS},
296
{"peekArg", (PyCFunction)ctxPeekArg, METH_VARARGS},
297
{"getArgs", (PyCFunction)ctxGetArgs, METH_VARARGS},
298
{"badOption", (PyCFunction)ctxBadOption, METH_VARARGS},
299
{"readDefaultConfig", (PyCFunction)ctxReadDefaultConfig, METH_VARARGS},
300
{"readConfigFile", (PyCFunction)ctxReadConfigFile, METH_VARARGS},
301
{"setOtherOptionHelp", (PyCFunction)ctxSetOtherOptionHelp, METH_VARARGS},
302
{"printHelp", (PyCFunction)ctxPrintHelp, METH_VARARGS},
303
{"printUsage", (PyCFunction)ctxPrintUsage, METH_VARARGS},
305
{"addAlias", (PyCFunction)ctxAddAlias},
306
{"stuffArgs", (PyCFunction)ctxStuffArgs},
307
{"callbackType", (PyCFunction)ctxCallbackType},
309
{"getOptValues", (PyCFunction)ctxGetOptValues, METH_VARARGS},
310
{"getOptValue", (PyCFunction)ctxGetOptValue, METH_VARARGS},
314
static PyObject * ctxGetAttr(poptContextObject *s, char *name)
316
return Py_FindMethod(ctxMethods, (PyObject *)s, name);
319
static void ctxDealloc(poptContextObject *self, PyObject *args)
321
if (self->options != NULL) {
323
for (i = 0; i < self->optionsNo; i++) {
324
struct poptOption *o = self->options + i;
325
if (o->argInfo != POPT_ARG_INCLUDE_TABLE && o->arg)
329
self->options = NULL;
331
poptFreeContext(self->ctx);
335
static PyTypeObject poptContextType = {
336
PyObject_HEAD_INIT(&PyType_Type)
338
"poptContext", /* tp_name */
339
sizeof(poptContextObject), /* tp_basicsize */
341
(destructor)ctxDealloc, /* tp_dealloc */
342
(printfunc)NULL, /* tp_print */
343
(getattrfunc)ctxGetAttr, /* tp_getattr */
344
(setattrfunc)NULL, /* tp_setattr */
345
(cmpfunc)NULL, /* tp_compare */
346
(reprfunc)NULL, /* tp_repr */
347
NULL, /* tp_as_number */
348
NULL, /* tp_as_sequence */
349
NULL /* tp_as_mapping */
352
/* Functions and datatypes needed for the popt module */
354
#define AUTOHELP "autohelp"
355
static const struct poptOption __autohelp[] = {
361
int __setPoptOption(PyObject *list, struct poptOption *opt)
367
/* Look for autohelp stuff first */
368
if (PyString_Check(list)) {
369
if (!strcmp(AUTOHELP, PyString_AsString(list))) {
371
*opt = __autohelp[0];
374
PyErr_SetString(pypoptError, "Expected list or autohelp");
377
if (!PyList_Check(list)) {
378
PyErr_SetString(pypoptError, "List expected");
381
listSize = PyList_Size(list);
383
PyErr_SetString(pypoptError, "List is too short");
388
o = PyList_GetItem(list, 0);
391
opt->longName = NULL;
393
if (!PyString_Check(o)) {
394
PyErr_SetString(pypoptError, "Long name should be a string");
397
opt->longName = PyString_AsString(o);
401
o = PyList_GetItem(list, 1);
404
opt->shortName = '\0';
406
if (!PyString_Check(o)) {
407
PyErr_SetString(pypoptError, "Short name should be a string");
410
s = PyString_AsString(o);
411
/* If s is the empty string, we set the short name to '\0', which is
412
* the expected behaviour */
413
opt->shortName = s[0];
416
/* Make sure they have specified at least one of the long name or short
417
* name; we don't allow for table inclusions and callbacks for now, even
418
* if it would be nice to have them. The table inclusion is broken anyway
419
* unless I find a good way to pass the second table as a reference; I
420
* would normally have to pass it thru the arg field, but I don't pass
421
* that in the python table */
422
if (opt->longName == NULL && opt->shortName == '\0') {
423
PyErr_SetString(pypoptError, "At least one of the short name and long name must be specified");
428
o = PyList_GetItem(list, 2);
430
if (!PyInt_Check(o)) {
431
PyErr_SetString(pypoptError, "argInfo is not an int");
434
opt->argInfo = PyInt_AsLong(o);
436
/* Initialize the rest of the arguments with safe defaults */
437
switch(opt->argInfo) {
438
case POPT_ARG_STRING:
439
objsize = sizeof(char *);
441
case POPT_ARG_DOUBLE:
442
objsize = sizeof(double);
446
objsize = sizeof(int);
449
objsize = sizeof(long);
452
PyErr_SetString(pypoptError, "Wrong value for argInfo");
455
opt->arg = (void *)malloc(objsize);
456
if (opt->arg == NULL) {
460
memset(opt->arg, '\0', objsize);
463
opt->argDescrip = NULL;
464
/* If nothing left, end the stuff here */
469
o = PyList_GetItem(list, 3);
474
if (!PyInt_Check(o)) {
475
PyErr_SetString(pypoptError, "Val should be int or None");
478
opt->val = PyInt_AsLong(o);
480
/* If nothing left, end the stuff here */
485
o = PyList_GetItem(list, 4);
487
if (!PyString_Check(o) && o != Py_None) {
488
PyErr_SetString(pypoptError, "Invalid value passed for the description");
494
opt->descrip = PyString_AsString(o);
495
/* If nothing left, end the stuff here */
500
o = PyList_GetItem(list, 5);
502
if (!PyString_Check(o) && o != Py_None) {
503
PyErr_SetString(pypoptError, "Invalid value passed for the argument description");
507
opt->argDescrip = NULL;
509
opt->argDescrip = PyString_AsString(o);
513
struct poptOption * __getPoptOptions(PyObject *list, int *count)
515
int listSize, item, totalmem;
516
struct poptOption *opts;
517
struct poptOption sentinel = POPT_TABLEEND;
518
if (!PyList_Check(list)) {
519
PyErr_SetString(pypoptError, "List expected");
522
listSize = PyList_Size(list);
523
/* Malloc exactly the size of the list */
524
totalmem = (1 + listSize) * sizeof(struct poptOption);
525
opts = (struct poptOption *)malloc(totalmem);
530
memset(opts, '\0', totalmem);
531
for (item = 0; item < listSize; item++) {
533
/* Retrieve the item */
534
PyObject *o = PyList_GetItem(list, item);
535
ret = __setPoptOption(o, opts + item);
537
/* Presumably we pass the error from the previous level */
540
//__printPopt(opts + item);
543
opts[listSize] = sentinel;
548
char ** __getArgv(PyObject *list, int *argc)
550
int listSize, item, totalmem;
552
listSize = PyList_Size(list);
553
/* Malloc exactly the size of the list */
554
totalmem = (1 + listSize) * sizeof(char *);
555
argv = (char **)malloc(totalmem);
560
memset(argv, '\0', totalmem);
561
for (item = 0; item < listSize; item++) {
562
/* Retrieve the item */
563
PyObject *o = PyList_GetItem(list, item);
564
if (!PyString_Check(o)) {
565
PyErr_SetString(pypoptError, "Expected a string as value for the argument");
568
argv[item] = PyString_AsString(o);
569
//debug("getArgv", argv[item]);
572
argv[listSize] = NULL;
578
static PyObject * getContext(PyObject *self, PyObject *args)
583
int argc, count, flags = 0;
584
struct poptOption *opts;
585
poptContextObject *c;
586
/* We should receive name, argv and a list */
587
if (!PyArg_ParseTuple(args, "zO!O!|i", &name, &PyList_Type, &a,
588
&PyList_Type, &o, &flags))
591
argv = __getArgv(a, &argc);
596
opts = __getPoptOptions(o, &count);
598
/* Presumably they've set the exception at a previous level */
601
c = PyObject_NEW(poptContextObject, &poptContextType);
603
c->optionsNo = count;
605
c->ctx = poptGetContext(name, argc, (const char **)argv, opts, flags);
606
return (PyObject *)c;
609
struct _pyIntConstant {
614
static PyObject * _strerror(PyObject *self, PyObject *args)
617
if (!PyArg_ParseTuple(args, "i", &error)) {
620
return PyString_FromString(poptStrerror(error));
623
/* Methods for the popt module */
624
static struct PyMethodDef poptModuleMethods[] = {
625
{"getContext", (PyCFunction)getContext, METH_VARARGS, NULL},
626
{"strerror", (PyCFunction)_strerror, METH_VARARGS, NULL},
630
#define ADD_INT(NAME) {#NAME, NAME}
631
static const struct _pyIntConstant intConstants[] = {
633
ADD_INT(POPT_ARG_NONE),
634
ADD_INT(POPT_ARG_STRING),
635
{"POPT_ARG_INT", POPT_ARG_LONG},
636
ADD_INT(POPT_ARG_VAL),
637
{"POPT_ARG_FLOAT", POPT_ARG_DOUBLE},
639
ADD_INT(POPT_ARGFLAG_OR),
640
ADD_INT(POPT_ARGFLAG_AND),
641
ADD_INT(POPT_ARGFLAG_XOR),
642
ADD_INT(POPT_ARGFLAG_NOT),
643
ADD_INT(POPT_ARGFLAG_ONEDASH),
644
ADD_INT(POPT_ARGFLAG_DOC_HIDDEN),
645
ADD_INT(POPT_ARGFLAG_OPTIONAL),
647
ADD_INT(POPT_CONTEXT_NO_EXEC),
648
ADD_INT(POPT_CONTEXT_KEEP_FIRST),
649
ADD_INT(POPT_CONTEXT_POSIXMEHARDER),
651
ADD_INT(POPT_ERROR_NOARG),
652
ADD_INT(POPT_ERROR_BADOPT),
653
ADD_INT(POPT_ERROR_OPTSTOODEEP),
654
ADD_INT(POPT_ERROR_BADQUOTE),
655
ADD_INT(POPT_ERROR_BADNUMBER),
656
ADD_INT(POPT_ERROR_OVERFLOW),
657
ADD_INT(POPT_ERROR_ERRNO),
659
ADD_INT(POPT_BADOPTION_NOALIAS),
665
PyObject *dict, *module;
666
const struct _pyIntConstant *c;
667
module = Py_InitModule3("popt", poptModuleMethods, module_doc);
668
/* Init the constants */
669
dict = PyModule_GetDict(module);
670
PyDict_SetItemString(dict, "__version__",
671
PyString_FromString(PY_POPT_VERSION));
672
PyDict_SetItemString(dict, "cvsid", PyString_FromString(rcs_id));
673
for (c = intConstants; c->name; c++) {
674
PyObject *val = PyInt_FromLong(c->value);
675
PyDict_SetItemString(dict, c->name, val);
678
/* Add the autohelp stuff */
680
PyObject *val = PyString_FromString(AUTOHELP);
681
PyDict_SetItemString(dict, "POPT_AUTOHELP", val);
685
pypoptError = PyErr_NewException("popt.error", NULL, NULL);
686
PyDict_SetItemString(dict, "error", pypoptError);