/* * Assembler for Emu10k1 * Copyright (C) 4Front Technologies 2001. All rights reserved */ #include #include #include #include #include #include #ifdef USERLAND #define oss_native_word unsigned long #define oss_mutex_t unsigned long #define oss_device_t unsigned long #define ac97_devc unsigned long #define oss_midi_inputbyte_t char #define uart401_devc unsigned long typedef int oss_mutex; typedef void *oss_dma_handle_t; #else #include "../../../kernel/framework/include/os.h" #endif /* USERLAND */ #include "../../../kernel/drv/oss_sblive/sblive.h" #define MAX_NAME 64 #define MAX_SYMBOLS 1024 int is_audigy = 0; int gpr_base = 0x100; int input_base = 0x10; int output_base = 0x20; static char line[4096] = "", *lineptr = line; static char lastline[4096]; typedef struct { char name[MAX_NAME]; int type; #define SY_DUMMY 0 #define SY_GPR 1 #define SY_INPUT 2 #define SY_OUTPUT 3 #define SY_CONST 4 #define SY_FX 5 #define SY_ACCUM 6 #define SY_PARM 7 int arg; } sym_t; typedef struct { char *name; int opcode; } instruction_t; static instruction_t instructions[] = { {"MACS", 0x0}, {"MACS1", 0x1}, {"MACW", 0x2}, {"MACW1", 0x3}, {"MACINTS", 0x4}, {"MACIINTW", 0x5}, {"SUM", 0x6}, {"ACC3", 0x6}, {"MACMV", 0x7}, {"ANDXOR", 0x8}, {"TSTNEG", 0x9}, {"LIMIT", 0xa}, {"LIMIT1", 0xb}, {"LOG", 0xc}, {"EXP", 0xd}, {"INTERP", 0xe}, {"SKIP", 0xf}, {NULL, 0} }; static sym_t symtab[MAX_SYMBOLS]; static int nsyms = 0; static int group_created = 0; int lineno = 0, errors = 0; static emu10k1_file fle; static int pc; static int ngpr = 0; static char * agetline (char *buf, int len) { char *s; if (*lineptr == 0) { lineptr = line; if (fgets (line, sizeof (line), stdin) == NULL) return NULL; if (*line != '#') lineno++; strcpy(lastline, line); } s = buf; while (*lineptr && *lineptr != ';') { *s++ = *lineptr++; } *s = 0; if (*lineptr == ';') *lineptr++ = 0; /* printf("%s\n", buf); */ return buf; } static void error (char *msg) { fprintf (stderr, "%s\n", lastline); fprintf (stderr, "Error '%s' on line %d\n", msg, lineno); errors++; } static sym_t * find_symbol (char *name) { int i; for (i = 0; i < nsyms; i++) if (strcmp (symtab[i].name, name) == 0) { return &symtab[i]; } return NULL; } static void add_symbol (char *name, int type, int arg) { sym_t *sym; #if 0 /* This is not needed any more */ if (is_audigy) { if (type == SY_CONST) arg += 0x80; } #endif /* printf("'%s' = %d/%x\n", name, type, arg); */ if (nsyms >= MAX_SYMBOLS) { error ("Symbol table full"); exit (-1); } if (find_symbol (name) != NULL) { error ("Dublicate symbol"); return; } if (strlen (name) >= MAX_NAME) { error ("Too long symbol name"); exit (-1); } sym = &symtab[nsyms++]; strcpy (sym->name, name); sym->type = type; sym->arg = arg; } static void compile_gpr (char *parms) { char *p = parms; while (*p && *p != ' ') p++; if (*p == ' ') { error ("Too many parameters"); return; } if (ngpr >= MAX_GPR) error ("Too many GPR variables"); add_symbol (parms, SY_GPR, gpr_base + ngpr++); } static void declare_const (unsigned int gpr, char *value) { int n, intv; float v; n = fle.consts.nconst; if (n >= MAX_CONST_PARMS) { error ("Too many constant parameters"); return; } if (*value == 'I') { if (sscanf (&value[1], "%g", &v) != 1) { error ("Bad floating point value"); return; } intv = (int) v; /* printf("%s/%g -> %08x -> %g\n", value, v, intv, (float)intv); */ } else if (*value == '0' && value[1] == 'x') { if (sscanf (&value[2], "%x", &intv) != 1) { error ("Bad hexadecimal value"); return; } /* printf("%s/%g -> %08x -> %g\n", value, v, intv, (float)intv); */ } else { if (sscanf (value, "%g", &v) != 1) { error ("Bad floating point value"); return; } intv = (int) (v * 0x7fffffff); /* printf("%s/%g -> %08x -> %g\n", value, v, intv, (float)intv / (float)0x7fffffff); */ } fle.consts.consts[n].gpr = gpr; fle.consts.consts[n].value = intv; fle.consts.nconst = n + 1; } static void compile_const (char *parms) { char *p = parms; char *value; while (*p && *p != ' ') p++; if (*p == 0) { error ("Too few parameters"); return; } *p++ = 0; while (*p == ' ') p++; if (*p == 0) { error ("Too few parameters"); return; } value = p; while (*p && *p != ' ') p++; if (*p == ' ') { error ("Too many parameters"); return; } if (ngpr >= MAX_GPR) error ("Too many GPR variables"); declare_const (ngpr, value); add_symbol (parms, SY_GPR, gpr_base + ngpr++); } static void define_parm (char *parms, char *name, int num, char *typ) { int n; /* printf("Parameter '%s/%s' = GPR %d (%d), typ=%s\n", parms, name, ngpr, num, typ); */ n = fle.parms.ngpr; if (n >= MAX_GPR_PARMS) { error ("Too many GPR parameters"); return; } if (strcmp (typ, "group") == 0) { strcpy (fle.parms.gpr[n].name, parms); fle.parms.gpr[n].num = 0; fle.parms.gpr[n].type = MIXT_GROUP; fle.parms.gpr[n].def = 0; fle.parms.ngpr = n + 1; group_created = 1; return; } #if 0 if (!group_created) { strcpy (fle.parms.gpr[n].name, "EFX"); fle.parms.gpr[n].num = 0; fle.parms.gpr[n].type = MIXT_GROUP; fle.parms.gpr[n].def = 0; fle.parms.ngpr = n + 1; group_created = 1; } #endif if (strcmp (typ, "stereo") == 0) { char tmp[128]; strcpy (fle.parms.gpr[n].name, name); fle.parms.gpr[n].num = ngpr; fle.parms.gpr[n].type = MIXT_STEREOSLIDER; fle.parms.gpr[n].def = num | (num << 8); fle.parms.ngpr = n + 1; sprintf (tmp, "%s_L", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_R", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); return; } if (strcmp (typ, "stereopeak") == 0) { char tmp[128]; strcpy (fle.parms.gpr[n].name, name); fle.parms.gpr[n].num = ngpr; fle.parms.gpr[n].type = MIXT_STEREOPEAK; fle.parms.gpr[n].def = num | (num << 8); fle.parms.ngpr = n + 1; sprintf (tmp, "%s_L", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_R", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); return; } if (strcmp (typ, "onoff") == 0) { char tmp[128]; strcpy (fle.parms.gpr[n].name, name); fle.parms.gpr[n].num = ngpr; fle.parms.gpr[n].type = MIXT_ONOFF; fle.parms.gpr[n].def = num; fle.parms.ngpr = n + 1; sprintf (tmp, "%s_ON", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_OFF", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); return; } if (strcmp (typ, "eq1") == 0) { char tmp[128]; strcpy (fle.parms.gpr[n].name, name); fle.parms.gpr[n].num = ngpr; fle.parms.gpr[n].type = EMU_MIXT_EQ1; fle.parms.gpr[n].def = num; fle.parms.ngpr = n + 1; /* printf("EQ1, GPR=%d\n", ngpr); */ sprintf (tmp, "%s_CST_0", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_1", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_2", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_3", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_4", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); return; } if (strcmp (typ, "eq2") == 0) { char tmp[128]; strcpy (fle.parms.gpr[n].name, name); fle.parms.gpr[n].num = ngpr; fle.parms.gpr[n].type = EMU_MIXT_EQ2; fle.parms.gpr[n].def = num; fle.parms.ngpr = n + 1; /* printf("EQ2, GPR=%d\n", ngpr); */ sprintf (tmp, "%s_CST_0", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_1", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_2", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_3", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_4", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); return; } if (strcmp (typ, "eq3") == 0) { char tmp[128]; strcpy (fle.parms.gpr[n].name, name); fle.parms.gpr[n].num = ngpr; fle.parms.gpr[n].type = EMU_MIXT_EQ3; fle.parms.gpr[n].def = num; fle.parms.ngpr = n + 1; /* printf("EQ3, GPR=%d\n", ngpr); */ sprintf (tmp, "%s_CST_0", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_1", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_2", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_3", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_4", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); return; } if (strcmp (typ, "eq4") == 0) { char tmp[128]; strcpy (fle.parms.gpr[n].name, name); fle.parms.gpr[n].num = ngpr; fle.parms.gpr[n].type = EMU_MIXT_EQ4; fle.parms.gpr[n].def = num; fle.parms.ngpr = n + 1; /* printf("EQ4, GPR=%d\n", ngpr); */ sprintf (tmp, "%s_CST_0", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_1", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_2", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_3", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); sprintf (tmp, "%s_CST_4", parms); add_symbol (tmp, SY_PARM, gpr_base + ngpr++); return; } strcpy (fle.parms.gpr[n].name, name); fle.parms.gpr[n].num = ngpr; fle.parms.gpr[n].type = MIXT_SLIDER; fle.parms.gpr[n].def = num; fle.parms.ngpr = n + 1; add_symbol (parms, SY_PARM, gpr_base + ngpr++); } static void compile_parm (char *parms) { char *p = parms, *def, *typ, *name; int n; int num; while (*p && *p != ' ') p++; if (*p != ' ') { error ("Too few parameters"); return; } *p++ = 0; while (*p && *p == ' ') p++; if (*p == 0) { error ("Too few parameters"); return; } def = p; while (*p && *p != ' ') p++; if (*p != 0) { *p++ = 0; while (*p == ' ' || *p == '\t') p++; } if (*p == 0) typ = ""; else { typ = p; while (*p && *p != ' ' && *p != '\t') p++; if (*p != 0) *p++ = 0; } while (*p == ' ' || *p == '\t') p++; name = p; while (*p && *p != ' ' && *p != '\t') p++; *p = 0; if (*name == 0) name = parms; if (sscanf (def, "%d", &num) != 1) { error ("Bad integer value"); return; } define_parm (parms, name, num, typ); } static void compile_input (char *parms) { char *p = parms, *s; int num; while (*p && *p != ' ') p++; if (*p != ' ') { error ("Too few parameters"); return; } *p++ = 0; while (*p && *p == ' ') p++; if (*p == 0) { error ("Too few parameters"); return; } s = p; while (*p && *p != ' ') p++; if (*p == ' ') { error ("Too many parameters"); return; } if (sscanf (s, "%d", &num) != 1) { error ("Bad integer value"); return; } add_symbol (parms, SY_INPUT, input_base + num); } static void compile_send (char *parms) { char *p = parms, *s; int num; while (*p && *p != ' ') p++; if (*p != ' ') { error ("Too few parameters"); return; } *p++ = 0; while (*p && *p == ' ') p++; if (*p == 0) { error ("Too few parameters"); return; } s = p; while (*p && *p != ' ') p++; if (*p == ' ') { error ("Too many parameters"); return; } if (sscanf (s, "%d", &num) != 1) { error ("Bad integer value"); return; } add_symbol (parms, SY_FX, num); } static void compile_output (char *parms) { char *p = parms, *s; int num; while (*p && *p != ' ') p++; if (*p != ' ') { error ("Too few parameters"); return; } *p++ = 0; while (*p && *p == ' ') p++; if (*p == 0) { error ("Too few parameters"); return; } s = p; while (*p && *p != ' ') p++; if (*p == ' ') { error ("Too many parameters"); return; } if (sscanf (s, "%d", &num) != 1) { error ("Bad integer value"); return; } add_symbol (parms, SY_OUTPUT, output_base + num); } static void compile_directive (char *line) { char *p = line; while (*p && *p != ' ') p++; if (*p != ' ') { error ("Missing parameter"); return; } *p++ = 0; while (*p == ' ') p++; if (strcmp (line, ".gpr") == 0) { compile_gpr (p); return; } if (strcmp (line, ".const") == 0) { compile_const (p); return; } if (strcmp (line, ".parm") == 0) { compile_parm (p); return; } if (strcmp (line, ".input") == 0) { compile_input (p); return; } if (strcmp (line, ".send") == 0) { compile_send (p); return; } if (strcmp (line, ".output") == 0) { compile_output (p); return; } error ("Unknown directive"); } static void compile_asm (char *iline) { char line[4096], *s, *p; char *parms[4]; sym_t *symbols[4]; #define EMIT(o, r, a, x, y) \ fle.code[pc*2] = ((x) << 10) | (y); \ fle.code[pc*2+1] = ((o) << 20) | ((r) << 10) | a;pc++ #define EMIT_AUDIGY(o, r, a, x, y) \ fle.code[pc*2] = ((x) << 12) | (y); \ fle.code[pc*2+1] = ((o) << 24) | ((r) << 12) | a;pc++ int i, n = 0, nerr = 0; int ninputs = 0; s = iline; p = line; /* Remove all spaces and the trailing ')' */ while (*s) { if (*s != ' ' && *s != ')' && *s != '#') *p++ = *s; s++; } *p = 0; /* Replace ',' and '(' characters by spaces */ p = line; while (*p) { if (*p == ',' || *p == '(') *p = ' '; p++; } p = line; while (*p && *p != ' ') p++; if (*p != ' ') { error ("Too few parameters"); return; } *p++ = 0; while (*p && n < 4) { parms[n++] = p; while (*p && *p != ' ') p++; if (*p == ' ') *p++ = 0; } if (*p != 0) { error ("Too many parameters"); return; } if (n != 4) { error ("Too few parameters"); return; } for (i = 0; i < 4; i++) { if ((symbols[i] = find_symbol (parms[i])) == NULL) { fprintf (stderr, "%s\n", parms[i]); nerr++; error ("Undefined symbol"); continue; } if (symbols[i]->type == SY_INPUT) ninputs++; if (symbols[i]->type == SY_ACCUM && i != 1) error ("Bad usage of 'accum' operand."); } if (nerr > 0) return; if (ninputs > 1) { error ("Attempt to access more than one input GPRs by the same instruction"); } for (i = 0; i < strlen (line); i++) if (line[i] >= 'a' && line[i] <= 'z') line[i] -= 32; /* Upshift */ for (i = 0; instructions[i].name != NULL; i++) if (strcmp (line, instructions[i].name) == 0) { #if 0 printf ("Instruction %x: ", instructions[i].opcode); printf ("%03x ", symbols[0]->arg); printf ("%03x ", symbols[1]->arg); printf ("%03x ", symbols[2]->arg); printf ("%03x ", symbols[3]->arg); printf ("\n"); #endif if (is_audigy) { EMIT_AUDIGY (instructions[i].opcode, symbols[0]->arg, symbols[1]->arg, symbols[2]->arg, symbols[3]->arg); } else { EMIT (instructions[i].opcode, symbols[0]->arg, symbols[1]->arg, symbols[2]->arg, symbols[3]->arg); } return; } fprintf (stderr, "%s\n", line); error ("Unrecognized instruction"); } static void init_compiler (void) { char tmp[100]; int i; memset (&fle, 0, sizeof (fle)); /* * Initialize few predefined GPR parameter registers. These definitions * have to be in sync with the GPR_* macros in . */ /* ;.parm AC97VOL 0 mono AC97 ;.parm AC97MONVU 0 stereopeak - ;.parm PCM 100 stereo ;.parm MAIN 100 stereo VOL ;.parm VU 0 stereopeak - */ add_symbol ("NULL", SY_DUMMY, gpr_base + ngpr++); add_symbol ("NULL_", SY_DUMMY, gpr_base + ngpr++); define_parm ("PCM", "PCM", 100, "stereo"); define_parm ("MAIN", "VOL", 100, "stereo"); pc = 0; if (is_audigy) { /* Initialize the code array with NOPs (AUDIGY) */ for (i = 0; i < 512; i++) { fle.code[i * 2 + 0] = (0xc0 << 12) | 0xc0; fle.code[i * 2 + 1] = (0x06 << 24) | (0xc0 << 12) | 0xc0; } for (i = 0; i < 32; i++) { sprintf (tmp, "fx%d", i); add_symbol (tmp, SY_FX, i); } } else { /* Initialize the code array with NOPs (LIVE) */ for (i = 0; i < 512; i++) { fle.code[i * 2 + 0] = 0x10040; fle.code[i * 2 + 1] = 0x610040; } for (i = 0; i < 16; i++) { sprintf (tmp, "fx%d", i); add_symbol (tmp, SY_FX, i); } } /* * Constants */ if (is_audigy) { /* Audigy symbols */ add_symbol ("0", SY_CONST, 0x0c0); add_symbol ("1", SY_CONST, 0x0c1); add_symbol ("2", SY_CONST, 0x0c2); add_symbol ("3", SY_CONST, 0x0c3); add_symbol ("4", SY_CONST, 0x0c4); add_symbol ("8", SY_CONST, 0x0c5); add_symbol ("16", SY_CONST, 0x0c6); add_symbol ("32", SY_CONST, 0x0c7); add_symbol ("256", SY_CONST, 0x0c8); add_symbol ("65536", SY_CONST, 0x0c9); add_symbol ("2048", SY_CONST, 0x0ca); add_symbol ("0x800", SY_CONST, 0x0ca); add_symbol ("2^28", SY_CONST, 0x0cb); add_symbol ("0x10000000", SY_CONST, 0x0cb); add_symbol ("2^29", SY_CONST, 0x0cc); add_symbol ("0x20000000", SY_CONST, 0x0cc); add_symbol ("2^30", SY_CONST, 0x0cd); add_symbol ("0x40000000", SY_CONST, 0x0cd); add_symbol ("2^31", SY_CONST, 0x0ce); add_symbol ("0x80000000", SY_CONST, 0x0ce); add_symbol ("0x7fffffff", SY_CONST, 0x0cf); add_symbol ("0xffffffff", SY_CONST, 0x0d0); add_symbol ("-1", SY_CONST, 0x0d0); add_symbol ("0xfffffffe", SY_CONST, 0x0d1); add_symbol ("-2", SY_CONST, 0x0d1); add_symbol ("0xc0000000", SY_CONST, 0x0d2); add_symbol ("0x4f1bbcdc", SY_CONST, 0x0d3); add_symbol ("0x5a7ef9db", SY_CONST, 0x0d4); add_symbol ("0x100000", SY_CONST, 0x0d5); add_symbol ("accum", SY_ACCUM, 0x0d6); add_symbol ("CCR", SY_CONST, 0x0d7); add_symbol ("noise_L", SY_CONST, 0x0d8); add_symbol ("noise_R", SY_CONST, 0x0d9); add_symbol ("IRQREQ", SY_CONST, 0x0da); } else { /* SB Live symbols */ add_symbol ("0", SY_CONST, 0x040); add_symbol ("1", SY_CONST, 0x041); add_symbol ("2", SY_CONST, 0x042); add_symbol ("3", SY_CONST, 0x043); add_symbol ("4", SY_CONST, 0x044); add_symbol ("8", SY_CONST, 0x045); add_symbol ("16", SY_CONST, 0x046); add_symbol ("32", SY_CONST, 0x047); add_symbol ("256", SY_CONST, 0x048); add_symbol ("65536", SY_CONST, 0x049); add_symbol ("2^23", SY_CONST, 0x04a); add_symbol ("0x80000", SY_CONST, 0x04a); add_symbol ("2^28", SY_CONST, 0x04b); add_symbol ("0x10000000", SY_CONST, 0x04b); add_symbol ("2^29", SY_CONST, 0x04c); add_symbol ("0x20000000", SY_CONST, 0x04c); add_symbol ("2^30", SY_CONST, 0x04d); add_symbol ("0x40000000", SY_CONST, 0x04d); add_symbol ("2^31", SY_CONST, 0x04e); add_symbol ("0x80000000", SY_CONST, 0x04e); add_symbol ("0x7fffffff", SY_CONST, 0x04f); add_symbol ("0xffffffff", SY_CONST, 0x050); add_symbol ("-1", SY_CONST, 0x050); add_symbol ("0xfffffffe", SY_CONST, 0x051); add_symbol ("-2", SY_CONST, 0x051); add_symbol ("accum", SY_ACCUM, 0x056); add_symbol ("CCR", SY_CONST, 0x057); add_symbol ("noise_L", SY_CONST, 0x058); add_symbol ("noise_R", SY_CONST, 0x059); add_symbol ("IRQREQ", SY_CONST, 0x05a); } } static void produce_map (char *name) { char fname[1024]; int i; FILE *f; sprintf (fname, "%s.map", name); if ((f = fopen (fname, "w")) == NULL) { perror (fname); return; } fprintf (f, "%d\n", fle.size); for (i = 0; i < nsyms; i++) { fprintf (f, "%04x %x %s\n", symtab[i].arg, symtab[i].type, symtab[i].name); } fclose (f); } static void produce_output (char *fname) { int fd; if ((fd = creat (fname, 0644)) == -1) { perror (fname); exit (-1); } if (is_audigy) { fle.magic = EMU10K2_MAGIC; fle.feature_mask = SB_AUDIGY; } else { fle.magic = EMU10K1_MAGIC; fle.feature_mask = SB_LIVE; } fle.size = pc; fprintf (stderr, "%d instructions out of 512 produced\n", pc); if (write (fd, &fle, sizeof (fle)) != sizeof (fle)) { perror (fname); exit (-1); } close (fd); } int main (int argc, char *argv[]) { char iline[4096], line[4096], *p, *s, *outfile; if (argc < 2) { fprintf (stderr, "No output\n"); exit (-1); } outfile = argv[1]; if (argc > 2) if (strcmp (argv[2], "-2") == 0) { is_audigy = 1; gpr_base = 0x400; input_base = 0x40; output_base = 0x60; printf ("Compiling for SB Audigy\n"); } else printf ("Compiling for SB Live family\n"); init_compiler (); while (agetline (iline, sizeof (iline) - 1) != NULL) { if (*iline == '#') { if (iline[1] == ' ') if (sscanf (&iline[1], "%d", &lineno) == 1) lineno--; continue; } /* * Fix for HP-UX cpp. Strip all '#' characters from input. */ s = iline; p = line; while (*s) { if (*s != '#') *p++ = *s; s++; } *p = 0; p = line; while (*p && *p != '\n' && *p != '/') p++; *p = 0; if (*line == 0) /* Empty line */ continue; p = &line[strlen (line) - 1]; while (p > line && (*p == ' ' || *p == '\t')) p--; p[1] = 0; p = line; while (*p) { if (*p == '\t') *p = ' '; p++; } p = line; while (*p && (*p == ' ' || *p == '\t')) p++; if (*p == 0) /* Empty line */ continue; if (*p == '.') compile_directive (p); else compile_asm (p); } if (lineno < 1) { fprintf (stderr, "Empty input\n"); errors++; } if (errors == 0) { produce_output (outfile); produce_map (outfile); } if (errors > 0) { fprintf (stderr, "%d errors - compile failed\n", errors); exit (-1); } fprintf (stderr, "No errors detected - Output written to %s\n", outfile); exit (0); }