Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fc61adb

Browse files
committed
Merged with Steve Miale's version
1 parent 3cfe6fa commit fc61adb

1 file changed

Lines changed: 145 additions & 79 deletions

File tree

Python/modsupport.c

Lines changed: 145 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,36 @@ initmodule(name, methods)
6767
}
6868

6969

70+
/* Helper for getargs() and mkvalue() to scan the length of a format */
71+
72+
static int countformat PROTO((char *format, int endchar));
73+
static int countformat(format, endchar)
74+
char *format;
75+
int endchar;
76+
{
77+
int count = 0;
78+
int level = 0;
79+
while (level > 0 || *format != endchar) {
80+
if (*format == '\0') {
81+
/* Premature end */
82+
err_setstr(SystemError, "unmatched paren in format");
83+
return -1;
84+
}
85+
else if (*format == '(') {
86+
if (level == 0)
87+
count++;
88+
level++;
89+
}
90+
else if (*format == ')')
91+
level--;
92+
else if (level == 0 && *format != '#')
93+
count++;
94+
format++;
95+
}
96+
return count;
97+
}
98+
99+
70100
/* Generic argument list parser */
71101

72102
static int do_arg PROTO((object *arg, char** p_format, va_list *p_va));
@@ -97,7 +127,16 @@ do_arg(arg, p_format, p_va)
97127
return 0;
98128
break;
99129
}
100-
130+
131+
case 'b': /* byte -- very short int */ {
132+
char *p = va_arg(va, char *);
133+
if (is_intobject(arg))
134+
*p = getintvalue(arg);
135+
else
136+
return 0;
137+
break;
138+
}
139+
101140
case 'h': /* short int */ {
102141
short *p = va_arg(va, short *);
103142
if (is_intobject(arg))
@@ -339,78 +378,76 @@ getshortlistarg(args, a, n)
339378
return 1;
340379
}
341380

381+
382+
/* Generic function to create a value -- the inverse of getargs() */
383+
/* After an original idea and first implementation by Steven Miale */
384+
385+
static object *do_mktuple PROTO((char**, va_list *, int, int));
386+
static object *do_mkvalue PROTO((char**, va_list *));
387+
342388
static object *
343-
do_mkval(char **p_format, va_list *p_va) {
389+
do_mktuple(p_format, p_va, endchar, n)
390+
char **p_format;
391+
va_list *p_va;
392+
int endchar;
393+
int n;
394+
{
344395
object *v;
396+
int i;
397+
if (n < 0)
398+
return NULL;
399+
if ((v = newtupleobject(n)) == NULL)
400+
return NULL;
401+
for (i = 0; i < n; i++) {
402+
object *w = do_mkvalue(p_format, p_va);
403+
if (w == NULL) {
404+
DECREF(v);
405+
return NULL;
406+
}
407+
settupleitem(v, i, w);
408+
}
409+
if (v != NULL && **p_format != endchar) {
410+
DECREF(v);
411+
v = NULL;
412+
err_setstr(SystemError, "Unmatched paren in format");
413+
}
414+
else if (endchar)
415+
++*p_format;
416+
return v;
417+
}
418+
419+
static object *
420+
do_mkvalue(p_format, p_va) {
345421

346422
switch (*(*p_format)++) {
347423

348424
case '(':
349-
{
350-
int n = 0;
351-
char *p = *p_format;
352-
int level = 0;
353-
int i;
354-
while (level > 0 || *p != ')') {
355-
if (*p == '\0') {
356-
err_setstr(SystemError, "missing ')' in mkvalue format");
357-
return NULL;
358-
}
359-
else if (*p == '(') {
360-
if (level == 0)
361-
n++;
362-
level++;
363-
}
364-
else if (*p == ')')
365-
level--;
366-
else if (level == 0 && *p != '#')
367-
n++;
368-
p++;
369-
}
370-
v = newtupleobject(n);
371-
if (v == NULL)
372-
break;
373-
for (i = 0; i < n; i++) {
374-
object *w = do_mkval(p_format, p_va);
375-
if (w == NULL) {
376-
DECREF(v);
377-
v = NULL;
378-
break;
379-
}
380-
settupleitem(v, i, w);
381-
}
382-
if (v != NULL && *(*p_format)++ != ')') {
383-
/* "Cannot happen" */
384-
err_setstr(SystemError, "inconsistent format in mkvalue???");
385-
DECREF(v);
386-
v = NULL;
387-
}
388-
}
389-
break;
390-
425+
return do_mktuple(p_format, p_va, ')',
426+
countformat(*p_format, ')'));
427+
428+
case 'b':
391429
case 'h':
392-
v = newintobject((long)va_arg(*p_va, short));
393-
break;
394-
395430
case 'i':
396-
v = newintobject((long)va_arg(*p_va, int));
397-
break;
431+
return newintobject((long)va_arg(*p_va, int));
398432

399433
case 'l':
400-
v = newintobject((long)va_arg(*p_va, long));
401-
break;
434+
return newintobject((long)va_arg(*p_va, long));
402435

403436
case 'f':
404-
v = newfloatobject((double)va_arg(*p_va, float));
405-
break;
406-
407437
case 'd':
408-
v = newfloatobject((double)va_arg(*p_va, double));
409-
break;
438+
return newfloatobject((double)va_arg(*p_va, double));
439+
440+
case 'c':
441+
{
442+
char p[1];
443+
p[0] = va_arg(*p_va, int);
444+
return newsizedstringobject(p, 1);
445+
}
410446

411447
case 's':
412448
case 'z':
413449
{
450+
object *v;
414451
char *str = va_arg(*p_va, char *);
415452
int n;
416453
if (**p_format == '#') {
@@ -428,40 +465,69 @@ do_mkval(char **p_format, va_list *p_va) {
428465
n = strlen(str);
429466
v = newsizedstringobject(str, n);
430467
}
468+
return v;
431469
}
432-
break;
433470

434471
case 'S':
435472
case 'O':
436-
v = va_arg(*p_va, object *);
437-
if (v == NULL) {
438-
if (!err_occurred())
439-
err_setstr(SystemError, "NULL object passed to mkvalue");
473+
{
474+
object *v;
475+
v = va_arg(*p_va, object *);
476+
if (v != NULL)
477+
INCREF(v);
478+
else if (!err_occurred())
479+
/* If a NULL was passed because a call
480+
that should have constructed a value
481+
failed, that's OK, and we pass the error
482+
on; but if no error occurred it's not
483+
clear that the caller knew what she
484+
was doing. */
485+
err_setstr(SystemError,
486+
"NULL object passed to mkvalue");
487+
return v;
440488
}
441-
else
442-
INCREF(v);
443-
break;
444489

445490
default:
446491
err_setstr(SystemError, "bad format char passed to mkvalue");
447-
v = NULL;
448-
break;
492+
return NULL;
449493

450494
}
451-
452-
return v;
453495
}
454496

455-
object *
456-
mkvalue(char *format, ...)
497+
#ifdef USE_STDARG
498+
/* VARARGS 2 */
499+
object *mkvalue(char *format, ...)
500+
#else
501+
/* VARARGS */
502+
object *mkvalue(va_alist) va_dcl
503+
#endif
457504
{
458-
char *fmt = format;
459-
object *v;
460-
va_list p;
461-
va_start(p, format);
462-
v = do_mkval(&fmt, &p);
463-
va_end(p);
464-
if (v == NULL)
465-
fprintf(stderr, "mkvalue: format = \"%s\" \"%s\"\n", format, fmt);
466-
return v;
505+
int n;
506+
char *f;
507+
va_list va;
508+
object* retval;
509+
#ifdef USE_STDARG
510+
va_start(va, format);
511+
#else
512+
char *format;
513+
514+
va_start(va);
515+
format = va_arg(va, char *);
516+
#endif
517+
f = format;
518+
n = countformat(f, '\0');
519+
if (n < 0)
520+
retval = NULL; /* Error in the format */
521+
else if (n == 0) {
522+
retval = None;
523+
INCREF(retval);
524+
}
525+
else if (n == 1)
526+
retval = do_mkvalue(&f, &va);
527+
else
528+
retval = do_mktuple(&f, &va, '\0', n);
529+
va_end(va);
530+
if (retval == NULL)
531+
fprintf(stderr, "format \"%s\", f \"%s\"\n", format, f);
532+
return retval;
467533
}

0 commit comments

Comments
 (0)