#include "common.h"
#include "asm.h"
+#ifdef _WIN32
+ // for O_BINARY in _pipe()
+# include <fcntl.h>
+# include <io.h>
+#else
+ // for pipe and close
+# include <unistd.h>
+#endif
+
/* A 'token' is like !blah or %24f and is under the programmers
control. */
#define MAX_TOKEN_LEN 64
// Append a string onto another, and update the pointer to the end of
// the new string.
static char *
-_appendAt (char *at, char *onto, const char *sz)
+_appendAt (char *at, char *onto, const char *sz, size_t *max)
{
wassert (at && onto && sz);
- strcpy (at, sz);
- return at + strlen (sz);
+ strncpyz (at, sz, *max);
+ *max -= strlen (at);
+ return at + strlen (at);
}
void
-tvsprintf (char *buffer, const char *format, va_list ap)
+tvsprintf (char *buffer, size_t len, const char *format, va_list ap)
{
// Under Linux PPC va_list is a structure instead of a primitive type,
// and doesnt like being passed around. This version turns everything
// This is acheived by expanding the tokens and zero arg formats into
// one big format string, which is passed to the native printf.
- static int count;
- char noTokens[INITIAL_INLINEASM];
- char newFormat[INITIAL_INLINEASM];
- char *pInto = noTokens;
- char *p;
- char token[MAX_TOKEN_LEN];
- const char *sz = format;
+ static int count;
+ char noTokens[INITIAL_INLINEASM];
+ char newFormat[INITIAL_INLINEASM];
+ char *pInto = noTokens;
+ size_t pIntoLen = sizeof(noTokens);
+ char *p;
+ char token[MAX_TOKEN_LEN];
+ const char *sz = format;
// NULL terminate it to let strlen work.
*pInto = '\0';
/* First pass: expand all of the macros */
- while (*sz)
+ while (pIntoLen && *sz)
{
if (*sz == '!')
{
/* Now find the token in the token list */
if ((t = _findMapping (token)))
{
- pInto = _appendAt (pInto, noTokens, t);
+ pInto = _appendAt (pInto, noTokens, t, &pIntoLen);
}
else
{
else
{
*pInto++ = *sz++;
+ pIntoLen--;
}
}
+ if (!pIntoLen)
+ {
+ fprintf(stderr,
+ "Internal error: tvsprintf overflowed on pass one.\n");
+ // Might as well go on...
+ }
+
*pInto = '\0';
/* Second pass: Expand any macros that we own */
sz = noTokens;
pInto = newFormat;
+ pIntoLen = sizeof(newFormat);
- while (*sz)
+ while (pIntoLen && *sz)
{
if (*sz == '%')
{
{
case 'C':
// Code segment name.
- pInto = _appendAt (pInto, newFormat, CODE_NAME);
+ pInto = _appendAt (pInto, newFormat, CODE_NAME, &pIntoLen);
sz++;
break;
case 'F':
// Source file name.
- pInto = _appendAt (pInto, newFormat, srcFileName);
+ pInto = _appendAt (pInto, newFormat, fullSrcFileName, &pIntoLen);
sz++;
break;
case 'N':
// Current function name.
- pInto = _appendAt (pInto, newFormat, currFunc->rname);
+ pInto = _appendAt (pInto, newFormat, currFunc->rname, &pIntoLen);
sz++;
break;
case 'I':
{
// Unique ID.
char id[20];
- sprintf (id, "%u", ++count);
- pInto = _appendAt (pInto, newFormat, id);
+ SNPRINTF (id, sizeof(id), "%u", ++count);
+ pInto = _appendAt (pInto, newFormat, id, &pIntoLen);
sz++;
break;
}
default:
// Not one of ours. Copy until the end.
*pInto++ = '%';
- while (!isalpha (*sz))
+ pIntoLen--;
+ while (pIntoLen && !isalpha (*sz))
{
*pInto++ = *sz++;
+ pIntoLen--;
+ }
+ if (pIntoLen)
+ {
+ *pInto++ = *sz++;
+ pIntoLen--;
}
- *pInto++ = *sz++;
}
}
else
{
*pInto++ = *sz++;
+ pIntoLen--;
}
}
+ if (!pIntoLen)
+ {
+ fprintf(stderr,
+ "Internal error: tvsprintf overflowed on pass two.\n");
+ // Might as well go on...
+ }
+
*pInto = '\0';
// Now do the actual printing
- vsprintf (buffer, newFormat, ap);
+#if defined(HAVE_VSNPRINTF)
+ {
+ int wrlen;
+ wrlen = vsnprintf (buffer, len, newFormat, ap);
+
+ if (wrlen < 0 || wrlen >= len)
+ {
+ fprintf(stderr, "Internal error: tvsprintf truncated.\n");
+ }
+ }
+
+#else
+ vsprintf (buffer, newFormat, ap);
+ if (strlen(buffer) >= len)
+ {
+ fprintf(stderr, "Internal error: tvsprintf overflowed.\n");
+ }
+#endif
}
void
char buffer[INITIAL_INLINEASM];
va_start (ap, szFormat);
- tvsprintf (buffer, szFormat, ap);
+ tvsprintf (buffer, INITIAL_INLINEASM, szFormat, ap);
+ va_end(ap);
fputs (buffer, fp);
}
void
-tsprintf (char *buffer, const char *szFormat,...)
+tsprintf (char *buffer, size_t len, const char *szFormat,...)
{
va_list ap;
va_start (ap, szFormat);
- tvsprintf (buffer, szFormat, ap);
+ tvsprintf (buffer, len, szFormat, ap);
+ va_end(ap);
}
void
}
/*-----------------------------------------------------------------*/
-/* printCLine - try to find the c-code for this lineno */
+/* printILine - return the readable i-code for this ic */
+/* */
+/* iCodePrint wants a file stream so we need a pipe to fool it */
+/*-----------------------------------------------------------------*/
+static char verbalICode[1024];
+
+char *printILine (iCode *ic) {
+ int filedes[2];
+ FILE *pipeStream;
+ iCodeTable *icTab=getTableEntry(ic->op);
+ int res;
+
+#ifdef _WIN32
+ res = _pipe(filedes, 256, O_BINARY);
+#else
+ res = pipe(filedes);
+#endif
+ assert(res != -1); // forget it
+ if (res == -1)
+ return ""; // return empty line if pipe creation failed
+
+ // stuff the pipe with the readable icode
+ pipeStream=fdopen(filedes[1],"w");
+ icTab->iCodePrint(pipeStream, ic, icTab->printName);
+ // it really needs an extra push
+ fflush(pipeStream);
+ // now swallow it
+ pipeStream=fdopen(filedes[0],"r");
+ fgets(verbalICode, sizeof(verbalICode), pipeStream);
+ // clean up the mess, we'll return here for all icodes!!
+ assert(!close (filedes[0]));
+ assert(!close (filedes[1]));
+ // kill the trailing NL
+ verbalICode[strlen(verbalICode)-1]='\0';
+ // and throw it up
+ return verbalICode;
+}
+
+/*-----------------------------------------------------------------*/
+/* printCLine - return the c-code for this lineno */
/*-----------------------------------------------------------------*/
static FILE *inFile=NULL;
static char inLineString[1024];
static int inLineNo=0;
+static char lastSrcFile[PATH_MAX];
int rewinds=0;
char *printCLine (char *srcFile, int lineno) {
char *ilsP=inLineString;
+
+ if (inFile) {
+ if (strcmp (lastSrcFile, srcFile) != 0) {
+ fclose (inFile);
+ inFile = NULL;
+ inLineNo = 0;
+ }
+ }
if (!inFile) {
inFile=fopen(srcFile, "r");
if (!inFile) {
perror ("printCLine");
exit (1);
}
+ strncpyz (lastSrcFile, srcFile, PATH_MAX);
}
if (lineno<inLineNo) {
fseek (inFile, 0, SEEK_SET);