+typedef struct {
+ const char *szName;
+ const char *szFormat;
+} TOKEN;
+
+static TOKEN _tokens[] = {
+ { "area", ".area %s" },
+ { "global", ".globl %s" },
+ { "labeldef", "%s::" },
+ { "tlabeldef", "%05d$:" },
+ { "fileprelude", "; Generated using the default tokens." },
+ { "functionheader",
+ "; ---------------------------------\n"
+ "; Function %s\n"
+ "; ---------------------------------"
+ },
+ { "functionlabeldef", "%s:" },
+ { "pusha",
+ "\tpush af\n"
+ "\tpush bc\n"
+ "\tpush de\n"
+ "\tpush hl"
+ },
+ { "di", "\tdi" },
+ { "adjustsp", "\tlda sp,-%d(sp)" },
+ { "prelude", "\tpush bc" },
+ { "leave",
+ "\tpop bc\n"
+ "\tret"
+ },
+ { "leavex",
+ "\tlda sp,%d(sp)\n"
+ "\tpop bc\n"
+ "\tret"
+ },
+ { "hli", "(hl+) ; 2" },
+ { "*hl", "(hl) ; 1" },
+ { "ldahlsp", "lda hl,%d(sp)" },
+ { "ldaspsp", "lda sp,%d(sp)" },
+};
+
+/* Z80:
+ { "adjustsp",
+ "\tld hl,#-%d\n"
+ "\tadd hl,sp\n"
+ "\tld sp,hl"
+ }
+ { "prelude",
+ "push bc"
+ "push de"
+ "push ix"
+ "ld ix,#0"
+ "add ix,sp"
+ { "leave"
+ emitcode("ld", "sp,ix");
+ emitcode("pop", "ix");
+ emitcode("pop", "de");
+ }
+}
+*/
+
+#define NUM_TOKENS (sizeof(_tokens)/sizeof(_tokens[0]))
+
+static const TOKEN *_findToken(const char *szName)
+{
+ int i;
+ for (i=0; i < NUM_TOKENS; i++) {
+ if (!strcmp(_tokens[i].szName, szName))
+ return _tokens + i;
+ }
+ return NULL;
+}
+
+static va_list _iprintf(char *pInto, const char *szFormat, va_list ap)
+{
+ char *pStart = pInto;
+ char *sz = _strdup(szFormat);
+
+ while (*sz) {
+ if (*sz == '%') {
+ switch (*++sz) {
+ /* See if it's a special emitter */
+ case 'r':
+ wassert(0);
+ break;
+ default:
+ {
+ /* Scan out the arg and pass it on to sprintf */
+ char *p = sz-1, tmp;
+ while (isdigit(*sz))
+ sz++;
+ /* Skip the format */
+ tmp = *++sz;
+ *sz = '\0';
+ vsprintf(pInto, p, ap);
+ /* PENDING: Assume that the arg length was an int */
+ va_arg(ap, int);
+ *sz = tmp;
+ }
+ }
+ pInto = pStart + strlen(pStart);
+ }
+ else {
+ *pInto++ = *sz++;
+ }
+ }
+ *pInto = '\0';
+
+ return ap;
+}
+
+static void vtprintf(char *buffer, const char *szFormat, va_list ap)
+{
+ char *sz = _strdup(szFormat);
+ char *pInto = buffer, *p;
+
+ buffer[0] = '\0';
+
+ while (*sz) {
+ if (*sz == '!') {
+ /* Start of a token. Search until the first
+ [non alplha, *] and call it a token. */
+ char old;
+ const TOKEN *t;
+ p = ++sz;
+ while (isalpha(*sz) || *sz == '*') {
+ sz++;
+ }
+ old = *sz;
+ *sz = '\0';
+ /* Now find the token in the token list */
+ if ((t = _findToken(p))) {
+ ap = _iprintf(pInto, t->szFormat, ap);
+ pInto = buffer + strlen(buffer);
+ }
+ else {
+ printf("Cant find token \"%s\"\n", p);
+ wassert(0);
+ }
+ }
+ else {
+ *pInto++ = *sz++;
+ }
+ }
+ *pInto = '\0';
+}
+
+static void tprintf(char *buffer, const char *szFormat, ...)
+{
+ va_list ap;
+
+ va_start(ap, szFormat);
+ vtprintf(buffer, szFormat, ap);
+}
+
+static void emit2(const char *szFormat, ...)
+{
+ char buffer[256];
+ va_list ap;
+
+ va_start(ap, szFormat);
+
+ vtprintf(buffer, szFormat, ap);
+
+ lineCurr = (lineCurr ?
+ connectLine(lineCurr,newLineNode(buffer)) :
+ (lineHead = newLineNode(buffer)));
+
+ lineCurr->isInline = inLine;
+ lineCurr->isDebug = debugLine;
+}
+