2 // RMAC - Reboot's Macro Assembler for the Atari Jaguar Console System
3 // LISTING.C - Listing Output
4 // Copyright (C) 199x Landon Dyer, 2011-2012 Reboot and Friends
5 // RMAC derived from MADMAC v1.07 Written by Landon Dyer, 1986
6 // Source Utilised with the Kind Permission of Landon Dyer
8 // --------------------------------------------------------------------------
9 // 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7
10 // 012345678901234567890123456789012345678901234567890123456789012345678901234567
11 // filename.... Reboot's Macro Assembler N.N.NN (Unknown)
12 // nnnnn aaaaaaaa dddddddddddddddddddd T source code
13 // nnnnn aaaaaaaa dddddddddddddddd
23 char * list_fname; // Listing filename
24 char subttl[TITLESIZ]; // Current subtitle
25 int listing; // Listing level
26 int pagelen = 61; // Lines on a page
27 int nlines; // #lines on page so far
28 LONG lsloc; // `sloc' at start of line
31 static int lcursect; // `cursect' at start of line
32 static int llineno; // `curlineno' at start of line
33 static int pageno; // Current page number
34 static int pagewidth; // #columns on a page
35 static int subflag; // 0, don't do .eject on subttl (set 1)
36 static char lnimage[IMAGESIZ]; // Image of output line
37 static char title[TITLESIZ]; // Current title
38 static char datestr[20]; // Current date dd-mon-yyyy
39 static char timestr[20]; // Current time hh:mm:ss [am|pm]
40 static char buf[IMAGESIZ]; // Buffer for numbers
41 static long unused; // For supressing 'write' warnings
43 static char * month[16] = {
44 "", "Jan", "Feb", "Mar",
45 "Apr", "May", "Jun", "Jul",
46 "Aug", "Sep", "Oct", "Nov",
51 // Eject the Page (Print Empty Lines), Reset the Line Count and Bump the Page Number
66 // Return GEMDOS Format Date
75 tm = localtime(&tloc);
76 v = ((tm->tm_year - 80) << 9) | ((tm->tm_mon+1) << 5) | tm->tm_mday;
83 // Return GEMDOS Format Time
92 tm = localtime(&tloc);
93 v = (tm->tm_hour << 11) | (tm->tm_min) << 5 | tm->tm_sec;
100 // Generate a Time String
102 void time_string(char * buf, VALUE time)
117 sprintf(buf, "%d:%02d:%02d %s",
118 hour, (int)((time >> 5) & 0x3F), (int)((time & 0x1F) << 1), ampm);
123 // Generate a Date String
125 void date_string(char * buf, VALUE date)
127 sprintf(buf, "%d-%s-%d",
128 (int)(date & 0x1F), month[(date >> 5) & 0xF], (int)((date >> 9) + 1980));
133 // Copy `n' Characters from `src' to `dest' (also stops on EOS in src).
134 // Does not null-terminate dest.
136 void scopy(char *dest, char *src, int len)
139 len = 1000; // Some large number [Shamus: wha...?]
141 while (len-- && *src)
147 // Transform letters a-f in the address and data columns of the listing to
148 // uppercase. (People seem to like uppercase hex better in assembly-language
151 void uc_ln(char * ln)
156 for(i=LOC_COL; i<SRC_COL; ++i)
158 if ((j = ln[i]) >= 'a' && j <= 'f')
159 ln[i] = (char)(j - 0x20);
165 // Fill Region `dest' with `len' Characters `c' and Null Terminate the Region
167 void lnfill(char * dest, int len, char chr)
177 // Create Listing File with the Appropriate Name
179 void list_setup(void)
183 strcpy(fnbuf, list_fname);
187 strcpy(fnbuf, firstfname);
188 fext(fnbuf, ".prn", 1);
193 if ((list_fd = open(fnbuf, _OPEN_FLAGS, _PERM_MODE)) < 0)
199 // Tag Listing with a Character, Typically for Errors or Warnings
201 void taglist(char chr)
203 lnimage[TAG_COL+1] = chr;
208 // Print a Line to the Listing File
210 void println(const char * ln)
214 // Create listing file, if necessary
215 if (list_fname != NULL)
219 unused = write(list_fd, ln, length);
220 unused = write(list_fd, "\n", 1L);
225 // Ship Line `ln' Out; Do Page Breaks and Title Stuff
227 void ship_ln(const char * ln)
229 // If listing level is <= 0, then don't print anything
233 // Notice bottom of page
234 if (nlines >= pagelen - BOT_MAR)
237 // Print title, boilerplate, and subtitle at top of page
242 date_string(datestr, dos_date());
243 time_string(timestr, dos_time());
245 "%-40s%-20s Page %-4d %s %s RMAC %01i.%01i.%02i (%s)",
246 title, curfname, pageno, timestr, datestr, MAJOR, MINOR, PATCH, PLATFORM);
248 sprintf(buf, "%s", subttl);
260 // Initialize Listing Generator
262 void InitListing(void)
264 extern VALUE dos_date(), dos_time();
273 date_string(datestr, dos_date());
274 time_string(timestr, dos_time());
289 DEBUG printf("~list: lsloc=$%ux sloc=$%ux\n", lsloc, sloc);
293 sprintf(buf, "%08ux", lsloc);
294 scopy(lnimage+LOC_COL, buf, 8);
297 if (llineno != curlineno)
299 sprintf(buf, "%5d", llineno);
300 scopy(lnimage+LN_COL, buf, 5);
303 // List bytes only when section stayed the same and the section is not a
304 // "no-data" (SBSS) section. An extra annoyance is caused by "ds.b" in a
305 // microprocessor mode, which prints out bytes of zero as if they had been
306 // deposited with dcb. The fix (kludge) is an extra variable which records
307 // the fact that a 'ds.x' directive generated all the data, and it
308 // shouldn't be listed
309 savsect(); // Update section variables
311 if (lcursect == cursect && (sect[lcursect].scattr & SBSS) == 0
312 && lsloc != sloc && just_bss == 0)
314 ch = sect[lcursect].sfcode;
316 for(; ch!=NULL; ch=ch->chnext)
318 if (lsloc >= ch->chloc && lsloc < (ch->chloc + ch->ch_size))
322 // Fatal: Can't find chunk holding code
326 interror(6); // Can't find generated code in section
329 p = ch->chptr + (lsloc - ch->chloc);
333 for(count=sloc-lsloc; count--; col+=2, ++lsloc)
340 lnfill(lnimage, SRC_COL, SPACE); // Fill with spaces
341 sprintf(buf, "%08ux", lsloc);
342 scopy(lnimage+LOC_COL, buf, 8);
345 if (lsloc >= (ch->chloc + ch->ch_size))
347 if ((ch = ch->chnext) == NULL)
354 fixcount = fixtest(lcursect, lsloc);
360 ++p; // Advance anyway
363 sprintf(buf, "%02x", *p++ & 0xff);
365 scopy(lnimage+col, buf, 2);
368 // Flush partial line
384 // Copy Current (Saved) Line to Output Buffer and Tag it with a Character
386 void lstout(char tag)
395 lnfill(lnimage, SRC_COL, SPACE); // Fill with spaces
396 lnimage[TAG_COL] = tag;
398 // Copy line image and handle control characters
399 d = lnimage + SRC_COL;
401 for(s=lnbuf; *s; ++s)
403 if (*s >= 0x20 || *s == '\t')
408 *d++ = (char)(*s + 0x40);
417 // Output a Value to Listing
419 int listvalue(VALUE v)
421 sprintf(buf, "=%08ux", v);
422 scopy(lnimage + DATA_COL - 1, buf, 9);
428 * .subttl [-] "string"
431 * o leading '-' supresses page eject
432 * o don't .eject on first .subttl, but do so on all other ones,
433 * o arrange not to print the .subttl directive
448 return error("missing string");
450 // strcpy(subttl, (char *)tok[1]);
451 strcpy(subttl, string[tok[1]]);
455 // Always eject on pages 2+
456 if (ejectok && (subflag || pageno > 1))
466 // Set title on titles not on the first page, do an eject and clobber the subtitle
471 return error("missing string");
473 // strcpy(title, (char*)tok[1]);
474 strcpy(title, string[tok[1]]);