diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9d293c59bed95ba8d1c32dd1253ca2f5d08b13f7..aac825245144652278e0d006106456361a5ffbcd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -79,7 +79,7 @@ ubuntu_14.04_i386_deb: - echo "" | sudo -S DEBIAN_FRONTEND=noninteractive dpkg --force-all -i pd-l2ork*.deb > /dev/null - cd scripts - valgrind pd-l2ork -noprefs -nostdpath -nogui -nrt -noaudio -send "init dollarzero \$0" regression_control.pd - - valgrind pd-l2ork -noprefs -nostdpath -nogui -nrt -noaudio scripts/regression_tilde.pd + - valgrind pd-l2ork -noprefs -nostdpath -nogui -nrt -noaudio regression_tilde.pd - valgrind pd-l2ork -noprefs -nostdpath -nogui -nrt -noaudio external-tests.pd artifacts: name: "$CI_RUNNER_DESCRIPTION" @@ -102,7 +102,7 @@ ubuntu_14.04_x86_64_deb: - echo "" | sudo -S DEBIAN_FRONTEND=noninteractive dpkg --force-all -i pd-l2ork*.deb > /dev/null - cd scripts - valgrind pd-l2ork -noprefs -nostdpath -nogui -nrt -noaudio -send "init dollarzero \$0" regression_control.pd - - valgrind pd-l2ork -noprefs -nostdpath -nogui -nrt -noaudio scripts/regression_tilde.pd + - valgrind pd-l2ork -noprefs -nostdpath -nogui -nrt -noaudio regression_tilde.pd - valgrind pd-l2ork -noprefs -nostdpath -nogui -nrt -noaudio external-tests.pd artifacts: name: "$CI_RUNNER_DESCRIPTION" @@ -125,7 +125,7 @@ ubuntu_16.04_x86_64_deb: - echo "" | sudo -S DEBIAN_FRONTEND=noninteractive dpkg --force-all -i pd-l2ork*.deb > /dev/null - cd scripts - valgrind pd-l2ork -noprefs -nostdpath -nogui -nrt -noaudio -send "init dollarzero \$0" regression_control.pd - - valgrind pd-l2ork -noprefs -nostdpath -nogui -nrt -noaudio scripts/regression_tilde.pd + - valgrind pd-l2ork -noprefs -nostdpath -nogui -nrt -noaudio regression_tilde.pd - valgrind pd-l2ork -noprefs -nostdpath -nogui -nrt -noaudio external-tests.pd artifacts: name: "$CI_RUNNER_DESCRIPTION" diff --git a/pd/src/x_connective.c b/pd/src/x_connective.c index 2e61671dcb9802030c7657e506a822c148e5c137..76850ed09c383f9a3d80b013e459e5ab79f3733f 100644 --- a/pd/src/x_connective.c +++ b/pd/src/x_connective.c @@ -1449,21 +1449,25 @@ static void until_setup(void) static t_class *makefilename_class; +typedef enum { + NONE = 0, + INT, + FLOAT, + STRING, + POINTER, +} t_printtype; + typedef struct _makefilename { t_object x_obj; t_symbol *x_format; - t_atomtype x_accept; - int x_intconvert; + t_printtype x_accept; } t_makefilename; -static void makefilename_scanformat(t_makefilename *x) +static const char* _formatscan(const char*str, t_printtype*typ) { int infmt=0; - char *str; - if (!x->x_format) return; - x->x_accept = A_NULL; - for (str=x->x_format->s_name; *str; str++) + for (; *str; str++) { if (!infmt && *str=='%') { @@ -1472,31 +1476,78 @@ static void makefilename_scanformat(t_makefilename *x) } if (infmt) { + if (*str=='%') + { + infmt=0; + continue; + } if (strchr("-.#0123456789",*str)!=0) continue; if (*str=='s') { - x->x_accept = A_SYMBOL; - x->x_intconvert = 0; - break; + *typ = STRING; + return str; } if (strchr("fgGeE",*str)!=0) { - x->x_accept = A_FLOAT; - x->x_intconvert = 0; - break; + *typ = FLOAT; + return str; } if (strchr("xXdiouc",*str)!=0) { - x->x_accept = A_FLOAT; - x->x_intconvert = 1; - break; + *typ = INT; + return str; } - infmt=0; + if (strchr("p",*str)!=0) + { + *typ = POINTER; + return str; + } + } + } + *typ = NONE; + return str; +} + +static void makefilename_scanformat(t_makefilename *x) +{ + const char *str; + t_printtype typ; + if (!x->x_format) return; + str = x->x_format->s_name; + str = _formatscan(str, &typ); + x->x_accept = typ; + if (str && (typ != NONE)) + { + /* try again, to see if there's another format specifier + (which we forbid) */ + str = _formatscan(str, &typ); + if (NONE != typ) + { + pd_error(x, "makefilename: invalid format string '%s' " + "(too many format specifiers)", x->x_format->s_name); + x->x_format = 0; + return; } } } +static void makefilename_printf(t_makefilename *x, char *buf, + const char *fmt, ...) +{ + int size_minus_one; + va_list ap; + va_start(ap, fmt); + size_minus_one = vsnprintf(buf, MAXPDSTRING, fmt, ap); + va_end(ap); + if (size_minus_one >= MAXPDSTRING) + { + pd_error(x, "makefilename: truncating output greater than %d bytes", + MAXPDSTRING); + buf[MAXPDSTRING-1] = '\0'; + } +} + static void *makefilename_new(t_symbol *s) { t_makefilename *x = (t_makefilename *)pd_new(makefilename_class); @@ -1504,8 +1555,7 @@ static void *makefilename_new(t_symbol *s) s = gensym("file.%d"); outlet_new(&x->x_obj, &s_symbol); x->x_format = s; - x->x_accept = A_NULL; - x->x_intconvert = 0; + x->x_accept = NONE; makefilename_scanformat(x); return (x); } @@ -1513,31 +1563,89 @@ static void *makefilename_new(t_symbol *s) static void makefilename_float(t_makefilename *x, t_floatarg f) { char buf[MAXPDSTRING]; - if (x->x_accept == A_FLOAT) + if (!x->x_format) { - if (x->x_intconvert) - sprintf(buf, x->x_format->s_name, (int)f); - else sprintf(buf, x->x_format->s_name, f); + pd_error(x, "makefilename: no format specifier given"); + return; } - else + switch(x->x_accept) + { + case NONE: + makefilename_printf(x, buf, "%s", x->x_format->s_name); + break; + case INT: case POINTER: + makefilename_printf(x, buf, x->x_format->s_name, (int)f); + break; + case FLOAT: + makefilename_printf(x, buf, x->x_format->s_name, f); + break; + case STRING: { char buf2[MAXPDSTRING]; - sprintf(buf2, "%g", f); - sprintf(buf, x->x_format->s_name, buf2); + makefilename_printf(x, buf2, "%g", f); + makefilename_printf(x, buf, x->x_format->s_name, buf2); + break; + } + default: + makefilename_printf(x, buf, "%s", x->x_format->s_name); } if (buf[0]!=0) - outlet_symbol(x->x_obj.ob_outlet, gensym(buf)); + outlet_symbol(x->x_obj.ob_outlet, gensym(buf)); } static void makefilename_symbol(t_makefilename *x, t_symbol *s) { char buf[MAXPDSTRING]; - if (x->x_accept == A_SYMBOL) - sprintf(buf, x->x_format->s_name, s->s_name); - else - sprintf(buf, x->x_format->s_name, 0); + if (!x->x_format) + { + pd_error(x, "makefilename: no format specifier given"); + return; + } + switch (x->x_accept) + { + case STRING: case POINTER: + makefilename_printf(x, buf, x->x_format->s_name, s->s_name); + break; + case INT: + makefilename_printf(x, buf, x->x_format->s_name, 0); + break; + case FLOAT: + makefilename_printf(x, buf, x->x_format->s_name, 0.); + break; + case NONE: + makefilename_printf(x, buf, "%s", x->x_format->s_name); + break; + default: + makefilename_printf(x, buf, "%s", x->x_format->s_name); + } + if (buf[0]!=0) + outlet_symbol(x->x_obj.ob_outlet, gensym(buf)); +} + +static void makefilename_bang(t_makefilename *x) +{ + char buf[MAXPDSTRING]; + if (!x->x_format) + { + pd_error(x, "makefilename: no format specifier given"); + return; + } + switch(x->x_accept) + { + case INT: + makefilename_printf(x, buf, x->x_format->s_name, 0); + break; + case FLOAT: + makefilename_printf(x, buf, x->x_format->s_name, 0.); + break; + case NONE: + makefilename_printf(x, buf, "%s", x->x_format->s_name); + break; + default: + makefilename_printf(x, buf, "%s", x->x_format->s_name); + } if (buf[0]!=0) - outlet_symbol(x->x_obj.ob_outlet, gensym(buf)); + outlet_symbol(x->x_obj.ob_outlet, gensym(buf)); } static void makefilename_set(t_makefilename *x, t_symbol *s) @@ -1553,6 +1661,7 @@ static void makefilename_setup(void) sizeof(t_makefilename), 0, A_DEFSYM, 0); class_addfloat(makefilename_class, makefilename_float); class_addsymbol(makefilename_class, makefilename_symbol); + class_addbang(makefilename_class, makefilename_bang); class_addmethod(makefilename_class, (t_method)makefilename_set, gensym("set"), A_SYMBOL, 0); }