reimplement tcl_vfprintf()
This commit is contained in:
parent
c4d0feb6cc
commit
c9e2a21a9c
114
src/tclspice.c
114
src/tclspice.c
|
|
@ -2648,13 +2648,21 @@ Spice_Init(Tcl_Interp *interp)
|
||||||
int
|
int
|
||||||
tcl_vfprintf(FILE *f, const char *fmt, va_list args)
|
tcl_vfprintf(FILE *f, const char *fmt, va_list args)
|
||||||
{
|
{
|
||||||
#define ostr_sz 128
|
char buf[1024];
|
||||||
static char outstr[ostr_sz] = "puts -nonewline std";
|
char *p, *s;
|
||||||
//outstr a buffer initialised with tcl print command
|
int size, nchars, escapes, result;
|
||||||
// offset for out: 19
|
|
||||||
#define ostr_off 19
|
const char * const escape_chars = "$[]\"\\";
|
||||||
char *outptr, *bigstr = NULL, *finalstr = NULL;
|
|
||||||
int i, nchars, result, escapes = 0;
|
const char * const prolog =
|
||||||
|
(f == stderr)
|
||||||
|
? "puts -nonewline stderr \""
|
||||||
|
: "puts -nonewline stdout \"";
|
||||||
|
|
||||||
|
const char * const epilog = "\"";
|
||||||
|
|
||||||
|
const int prolog_len = strlen(prolog);
|
||||||
|
const int epilog_len = strlen(epilog);
|
||||||
|
|
||||||
if ((fileno(f) != STDOUT_FILENO && fileno(f) != STDERR_FILENO &&
|
if ((fileno(f) != STDOUT_FILENO && fileno(f) != STDERR_FILENO &&
|
||||||
f != stderr && f != stdout)
|
f != stderr && f != stdout)
|
||||||
|
|
@ -2664,51 +2672,69 @@ tcl_vfprintf(FILE *f, const char *fmt, va_list args)
|
||||||
)
|
)
|
||||||
return vfprintf(f, fmt, args);
|
return vfprintf(f, fmt, args);
|
||||||
|
|
||||||
strcpy (outstr + ostr_off, (f == stderr) ? "err \"" : "out \"");
|
p = buf;
|
||||||
//5 characters for ->out "<-
|
|
||||||
outptr = outstr;
|
|
||||||
nchars = vsnprintf(outptr + ostr_off + 5, ostr_sz - 5 - ostr_off, fmt, args);
|
|
||||||
if (nchars >= ostr_sz - 5 - ostr_off) {
|
|
||||||
bigstr = Tcl_Alloc(nchars + 26);
|
|
||||||
strncpy(bigstr, outptr, 24);
|
|
||||||
outptr = bigstr;
|
|
||||||
vsnprintf(outptr + 24, nchars + 2, fmt, args);
|
|
||||||
}
|
|
||||||
else if (nchars == -1) {
|
|
||||||
nchars = 126;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 24; *(outptr + i) != '\0'; i++)
|
// size: how much ist left for chars and terminating '\0'
|
||||||
if (*(outptr + i) == '\"' || *(outptr + i) == '[' ||
|
size = sizeof(buf) - prolog_len - epilog_len;
|
||||||
*(outptr + i) == ']' || *(outptr + i) == '\\')
|
// assert(size > 0);
|
||||||
escapes++;
|
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
nchars = vsnprintf(p + prolog_len, size, fmt, args);
|
||||||
|
|
||||||
if (escapes > 0) {
|
if(nchars == -1) { /* compatibility to old implementations */
|
||||||
finalstr = Tcl_Alloc(nchars + escapes + 26);
|
size *= 2;
|
||||||
strncpy(finalstr, outptr, 24);
|
} else if (size < nchars + 1) {
|
||||||
escapes = 0;
|
size = nchars + 1;
|
||||||
for (i = 24; *(outptr + i) != '\0'; i++) {
|
} else {
|
||||||
if (*(outptr + i) == '\"' || *(outptr + i) == '[' ||
|
break;
|
||||||
*(outptr + i) == ']' || *(outptr + i) == '\\')
|
|
||||||
{
|
|
||||||
*(finalstr + i + escapes) = '\\';
|
|
||||||
escapes++;
|
|
||||||
}
|
|
||||||
*(finalstr + i + escapes) = *(outptr + i);
|
|
||||||
}
|
}
|
||||||
outptr = finalstr;
|
|
||||||
|
if(p == buf)
|
||||||
|
p = Tcl_Alloc(prolog_len + size + epilog_len);
|
||||||
|
else
|
||||||
|
p = Tcl_Realloc(p, prolog_len + size + epilog_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
*(outptr + 24 + nchars + escapes) = '\"';
|
strncpy(p, prolog, prolog_len);
|
||||||
*(outptr + 25 + nchars + escapes) = '\0';
|
|
||||||
|
|
||||||
result = Tcl_Eval(spice_interp, outptr);
|
s = p + prolog_len;
|
||||||
|
for (escapes = 0; ; escapes++) {
|
||||||
|
s = strpbrk(s, escape_chars);
|
||||||
|
if (!s)
|
||||||
|
break;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (escapes) {
|
||||||
|
|
||||||
|
int new_size = prolog_len + nchars + escapes + epilog_len + 1;
|
||||||
|
char *src, *dst;
|
||||||
|
|
||||||
|
if (p != buf) {
|
||||||
|
p = Tcl_Realloc(p, new_size);
|
||||||
|
} else if (new_size > sizeof(buf)) {
|
||||||
|
p = Tcl_Alloc(new_size);
|
||||||
|
strcpy(p, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
src = p + prolog_len + nchars;
|
||||||
|
dst = src + escapes;
|
||||||
|
|
||||||
|
while (dst > src) {
|
||||||
|
char c = *--src;
|
||||||
|
*--dst = c;
|
||||||
|
if (strchr(escape_chars, c))
|
||||||
|
*--dst = '\\';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(p + prolog_len + nchars + escapes, epilog);
|
||||||
|
|
||||||
|
result = Tcl_Eval(spice_interp, p);
|
||||||
|
|
||||||
|
if (p != buf)
|
||||||
|
Tcl_Free(p);
|
||||||
|
|
||||||
if (bigstr != NULL)
|
|
||||||
Tcl_Free(bigstr);
|
|
||||||
if (finalstr != NULL)
|
|
||||||
Tcl_Free(finalstr);
|
|
||||||
return nchars;
|
return nchars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue