#define LISTING__C #include #include #include #include #include "listing.h" /* my own definitions */ #include "util.h" #include "assemble_globals.h" /* GLOBAL VARIABLES */ int list_md = 1; /* option to list macro/rept definition = yes */ int list_me = 1; /* option to list macro/rept expansion = yes */ int list_bex = 1; /* option to show binary */ int list_level = 1; /* Listing control level. .LIST increments; .NLIST decrements */ static char *listline; /* Source lines */ static char *binline; /* for octal expansion */ FILE *lstfile = NULL; int list_pass_0 = 0;/* Also list what happens during the first pass */ static int errline = 0; /* Set if current line has an error */ /* maybe_list returns TRUE if listing may happen for this line. */ static int can_list( void) { int ok = lstfile != NULL && (pass > 0 || list_pass_0); return ok; } /* do_list returns TRUE if listing is enabled. */ static int dolist( void) { int ok = can_list () && (list_level > 0 || errline); return ok; } /* list_source saves a text line for later listing by list_flush */ void list_source( STREAM *str, char *cp) { if (can_list()) { int len = strcspn(cp, "\n"); /* Not an error yet */ errline = 0; /* Save the line text away for later... */ if (listline) free(listline); listline = memcheck(malloc(len + 1)); memcpy(listline, cp, len); listline[len] = 0; if (!binline) binline = memcheck(malloc(sizeof(LSTFORMAT) + 16)); sprintf(binline, "%*s%*d", (int)SIZEOF_MEMBER(LSTFORMAT, flag), "", (int)SIZEOF_MEMBER(LSTFORMAT, line_number), str->line); } } /* list_flush produces a buffered list line. */ void list_flush( void) { if (dolist()) { padto(binline, offsetof(LSTFORMAT, source)); fputs(binline, lstfile); fputs(listline, lstfile); fputc('\n', lstfile); listline[0] = 0; binline[0] = 0; } } /* list_fit checks to see if a word will fit in the current listing line. If not, it flushes and prepares another line. */ static void list_fit( STREAM *str, unsigned addr) { size_t col1 = offsetof(LSTFORMAT, source); size_t col2 = offsetof(LSTFORMAT, pc); if (strlen(binline) >= col1) { list_flush(); listline[0] = 0; binline[0] = 0; sprintf(binline, "%*s %6.6o", (int)offsetof(LSTFORMAT, pc), "", addr); padto(binline, offsetof(LSTFORMAT, words)); } else if (strlen(binline) <= col2) { sprintf(binline, "%*s%*d %6.6o", (int)SIZEOF_MEMBER(LSTFORMAT, flag), "", (int)SIZEOF_MEMBER(LSTFORMAT, line_number), str->line, addr); padto(binline, offsetof(LSTFORMAT, words)); } } /* list_value is used to show a computed value */ void list_value( STREAM *str, unsigned word) { if (dolist()) { /* Print the value and go */ binline[0] = 0; sprintf(binline, "%*s%*d %6.6o", (int)SIZEOF_MEMBER(LSTFORMAT, flag), "", (int)SIZEOF_MEMBER(LSTFORMAT, line_number), str->line, word & 0177777); } } /* Print a word to the listing file */ void list_word( STREAM *str, unsigned addr, unsigned value, int size, char *flags) { if (dolist()) { list_fit(str, addr); if (size == 1) sprintf(binline + strlen(binline), " %3.3o%1.1s ", value & 0377, flags); else sprintf(binline + strlen(binline), "%6.6o%1.1s ", value & 0177777, flags); } } /* Print just a line with the address to the listing file */ void list_location( STREAM *str, unsigned addr) { if (dolist()) { list_fit(str, addr); } } /* reports errors */ void report( STREAM *str, char *fmt, ...) { va_list ap; char *name = "**"; int line = 0; if (!pass && list_pass_0 < 2) return; /* Don't report now. */ errline = 1; if (str) { name = str->name; line = str->line; } fprintf(stderr, "%s:%d: ***ERROR ", name, line); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); if (lstfile) { fprintf(lstfile, "%s:%d: ***ERROR ", name, line); va_start(ap, fmt); vfprintf(lstfile, fmt, ap); va_end(ap); } }