I attach a working replacement of ccall (renamed to ccall_js, to avoid 
Google attachment issues) that uses a varargs specification string of the 
form "[d,i,s, ...]" to process varargs. So you can do this:

Module.ccall("miniprintf", "null", ["string", "[d,i,s,i,s,d]"], ["%f %d %s 
%d %s %f\n", 1.234, 2, "foo", 3, "goo", -100.100])
1.23399999999999 2 foo 3 goo -100.09999999999999


(miniprintf also attached in calljs.c)

The varargs spec repeats if there are extra arguments, which would be our 
typical astrophysics case with hundreds of vararg doubles making annuli:

Module.ccall("miniprintf", "null", ["string", "[d]"], ["%f %f %f %f\n", 
1.234, 2, 3.14, -100])
1.23399999999999 2 3.14 -100


but it repeats as a whole, so you can do this:

Module.ccall("miniprintf", "null", ["string", "[d i s]"], ["%f %d %s %f %d 
%s\n", 1.234, 2, "foo", 3.14, -100, "goo"])
1.23399999999999 2 foo 3.14 -100 goo


You will see that I speak Javascript with a heavy C accent, so I am not 
suggesting it as a PR. Just let me know whether you want to pursue this 
angle ...

Thanks,

Eric



-- 
You received this message because you are subscribed to the Google Groups 
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to emscripten-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
// emcc -O0 -s ASSERTIONS=1 -s EXPORTED_FUNCTIONS="['_miniprintf']" calljs.c -o calljs.js

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include<math.h>
#if __EMSCRIPTEN__
#include <emscripten.h>
#endif

/* 
 * Double to ASCII
 */
static double PRECISION = 0.00000000000001;
char * dtoa(char *s, double n) {
    // handle special cases
    if (isnan(n)) {
        strcpy(s, "nan");
    } else if (isinf(n)) {
        strcpy(s, "inf");
    } else if (n == 0.0) {
        strcpy(s, "0");
    } else {
        int digit, m, m1;
        char *c = s;
        int neg = (n < 0);
        if (neg)
            n = -n;
        // calculate magnitude
        m = log10(n);
        int useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
        if (neg)
            *(c++) = '-';
        // set up for scientific notation
        if (useExp) {
            if (m < 0)
               m -= 1.0;
            n = n / pow(10.0, m);
            m1 = m;
            m = 0;
        }
        if (m < 1.0) {
            m = 0;
        }
        // convert the number
        while (n > PRECISION || m >= 0) {
            double weight = pow(10.0, m);
            if (weight > 0 && !isinf(weight)) {
                digit = floor(n / weight);
                n -= (digit * weight);
                *(c++) = '0' + digit;
            }
            if (m == 0 && n > 0)
                *(c++) = '.';
            m--;
        }
        if (useExp) {
            // convert the exponent
            int i, j;
            *(c++) = 'e';
            if (m1 > 0) {
                *(c++) = '+';
            } else {
                *(c++) = '-';
                m1 = -m1;
            }
            m = 0;
            while (m1 > 0) {
                *(c++) = '0' + m1 % 10;
                m1 /= 10;
                m++;
            }
            c -= m;
            for (i = 0, j = m-1; i<j; i++, j--) {
                // swap without temporary
                c[i] ^= c[j];
                c[j] ^= c[i];
                c[i] ^= c[j];
            }
            c += m;
        }
        *(c) = '\0';
    }
    return s;
}

char *baseconv(unsigned int num, int base){
	static char retbuf[33];
	char *p;

	if(base < 2 || base > 16)
		return NULL;

	p = &retbuf[sizeof(retbuf)-1];
	*p = '\0';

	do {
		*--p = "0123456789abcdef"[num % base];
		num /= base;
	} while(num != 0);

	return p;
}


void miniprintf(const char *fmt, ...){
	const char *p;
	int i;
	double d;
	unsigned int u;
	char *s;
        char tbuf[1024];
	va_list argp;

	va_start(argp, fmt);

	for(p = fmt; *p != '\0'; p++) {
		if(*p != '%') {
			putchar(*p);
			continue;
		}

		switch(*++p) {
		case 'c':
			i = va_arg(argp, int);
			/* *not* va_arg(argp, char); see Q 15.10 */
			putchar(i);
			break;

		case 'd':
			i = va_arg(argp, int);
			if(i < 0) {
				/* XXX won't handle INT_MIN */
				i = -i;
				putchar('-');
			}
			fputs(baseconv(i, 10), stdout);
			break;

		case 'f':
			d = va_arg(argp, double);
			dtoa(tbuf, d);
			fputs(tbuf, stdout);
			break;

		case 'o':
			u = va_arg(argp, unsigned int);
			fputs(baseconv(u, 8), stdout);
			break;

		case 's':
			s = va_arg(argp, char *);
			fputs(s, stdout);
			break;

		case 'u':
			u = va_arg(argp, unsigned int);
			fputs(baseconv(u, 10), stdout);
			break;

		case 'x':
			u = va_arg(argp, unsigned int);
			fputs(baseconv(u, 16), stdout);
			break;

		case '%':
			putchar('%');
			break;
		}
	}

	va_end(argp);
}

#ifndef __EMSCRIPTEN__

int main(int argc, char **argv){
	miniprintf("Hello, %s!\n", "world");
	miniprintf("%c %d %s %f\n", '1', 2, "three", 4.4);
	miniprintf("%o %d %x %f\n", 10, 10, 10, -10.10);
	miniprintf("%u\n", 0xffff);
	return 0;
}

#endif

Attachment: ccall_js
Description: Binary data

Reply via email to