struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / sdas / linksrc / lkout.c
blob5b36024065bf827e44db4ba2ba673031fcc2c580
1 /* lkout.c */
3 /*
4 * Copyright (C) 1989-2017 Alan R. Baldwin
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * Alan R. Baldwin
21 * 721 Berkeley St.
22 * Kent, Ohio 44240
24 * With enhancements by
26 * G. Osborn
27 * gary@s-4.com.
30 #include "aslink.h"
32 /*)Module lkout.c
34 * The module lkout.c contains the dispatch
35 * function to create the relocated object
36 * code output in the required format.
38 * lkout.c contains the following functions:
39 * VOID lkout()
40 * VOID lkflush()
41 * VOID ixx()
42 * VOID iflush()
43 * VOID sxx()
44 * VOID sflush()
45 * VOID dbx()
46 * VOID dflush()
48 * lkout.c contains no local variables.
51 /*)Function lkout(i)
53 * int i 1 - process data
54 * 0 - end of data
56 * The function lkout() dispatches to the
57 * required output format routine.
59 * local variables:
60 * none
62 * global variables:
63 * int oflag output type flag
64 * int obj_flag Output enabled flag
65 * a_uint pc Current relocation address
66 * int pcb Current pc bytes per address
68 * functions called:
69 * VOID ixx() lkout.c
70 * VOID sxx() lkout.c
71 * VOID dbx() lkout.c
73 * side effects:
74 * The REL data is output in the required format.
77 VOID
78 lkout(i)
79 int i;
81 int j;
83 if (i && obj_flag) { return; }
84 if (ofp == NULL) { return; }
87 * Create the Byte Output Address
89 for (j=1; j<pcb; j++) {
90 adb_xb(pc, 0);
94 * Intel Formats
96 if (oflag == 1) {
97 ixx(i);
98 } else
100 * Motorola Formats
102 if (oflag == 2) {
103 sxx(i);
104 } else
106 * Disk Basic Formats
108 if (oflag == 3) {
109 dbx(i);
110 } else
112 * Elf Formats
114 if (oflag == 4) {
115 elf(i);
120 /*)Function lkflush()
122 * The function lkflush() dispatches
123 * to the required data flushing routine.
125 * local variables:
126 * none
128 * global variables:
129 * int oflag output type flag
130 * FILE * ofp output file handle
132 * functions called:
133 * VOID iflush() lkout.c
134 * VOID sflush() lkout.c
135 * VOID dflush() lkout.c
137 * side effects:
138 * Any remaining REL data is flushed
139 * to the output file.
142 VOID
143 lkflush()
145 if (ofp == NULL) { return; }
148 * Intel Formats
150 if (oflag == 1) {
151 iflush();
152 } else
154 * Motorola Formats
156 if (oflag == 2) {
157 sflush();
158 } else
160 * Disk Basic Formats
162 if (oflag == 3) {
163 dflush();
168 /*Intel Format
169 * Record Mark Field - This field signifies the start of a
170 * record, and consists of an ascii colon
171 * (:).
173 * Record Length Field - This field consists of two ascii
174 * characters which indicate the number of
175 * data bytes in this record. The
176 * characters are the result of converting
177 * the number of bytes in binary to two
178 * ascii characters, high digit first. An
179 * End of File record contains two ascii
180 * zeros in this field.
182 * Load Address Field - This field consists of the four ascii
183 * characters which result from converting
184 * the the binary value of the address in
185 * which to begin loading this record. The
186 * order is as follows:
188 * High digit of high byte of address.
189 * Low digit of high byte of address.
190 * High digit of low byte of address.
191 * Low digit of low byte of address.
193 * In an End of File record this field con-
194 * sists of four ascii zeros, in a start
195 * address record this is the program entry
196 * address (low), or in a segment record
197 * this is the high order address.
199 * Record Type Field - This field identifies the record type,
200 * which is either 0 for data records, 1
201 * for an End of File record, 3 for a
202 * start address, or 4 for a
203 * segment record. It consists
204 * of two ascii characters, with the high
205 * digit of the record type first, followed
206 * by the low digit of the record type.
208 * Data Field - This field consists of the actual data,
209 * converted to two ascii characters, high
210 * digit first. There are no data bytes in
211 * the End of File record.
213 * Checksum Field - The checksum field is the 8 bit binary
214 * sum of the record length field, the load
215 * address field, the record type field,
216 * and the data field. This sum is then
217 * negated (2's complement) and converted
218 * to two ascii characters, high digit
219 * first.
222 /*)Function ixx(i)
224 * int i 1 - process data
225 * 0 - end of data
227 * The function ixx() loads the output buffer with
228 * the relocated data.
230 * local variables:
231 * a_uint chksum byte checksum
232 * a_uint lo_addr address within segment
233 * a_uint hi_addr segment number
234 * int i loop counter
235 * a_uint j temporary
236 * int k loop counter
237 * struct sym *sp symbol pointer
238 * a_uint symadr symbol address
240 * global variables:
241 * int a_bytes T Line Address Bytes
242 * int hilo byte order
243 * FILE * ofp output file handle
244 * int rtaflg first output flag
245 * int rtcnt count of data words
246 * int rtflg[] output the data flag
247 * a_uint rtval[] relocated data
248 * char rtbuf[] output buffer
249 * a_uint rtadr0 address temporary
250 * a_uint rtadr1 address temporary
251 * a_uint rtadr2 address temporary
253 * functions called:
254 * int fprintf() c_library
255 * VOID iflush() lkout.c
257 * side effects:
258 * The data is placed into the output buffer.
262 * The number of Data Field bytes is:
264 * 1 Record Mark Field
265 * 2 Record Length Field
266 * 4 Load Address Field
267 * 2 Record Type Field
268 * 2 Checksum Field
270 * Plus 32 data bytes (64 characters)
273 VOID
274 ixx(int i)
276 int k;
277 struct sym *sp;
278 a_uint j, symadr, chksum;
280 if (i) {
281 if (TARGET_IS_6808 && ap->a_flag & A_NOLOAD)
282 return;
284 if (hilo == 0) {
285 switch(a_bytes){
286 default:
287 case 2:
288 j = rtval[0];
289 rtval[0] = rtval[1];
290 rtval[1] = j;
291 break;
292 case 3:
293 j = rtval[0];
294 rtval[0] = rtval[2];
295 rtval[2] = j;
296 break;
297 case 4:
298 j = rtval[0];
299 rtval[0] = rtval[3];
300 rtval[3] = j;
301 j = rtval[2];
302 rtval[2] = rtval[1];
303 rtval[1] = j;
304 break;
307 for (i=0,rtadr2=0; i<a_bytes; i++) {
308 rtadr2 = (rtadr2 << 8) | rtval[i];
310 if ((rtadr2 != rtadr1) || rtaflg) {
312 * data bytes not contiguous between records
314 iflush();
315 rtadr0 = rtadr1 = rtadr2;
316 rtaflg = 0;
318 for (k=a_bytes; k<rtcnt; k++) {
319 if (rtflg[k]) {
320 rtbuf[(int) (rtadr1++ - rtadr0)] = rtval[k];
321 if ((rtadr1 & 0xffff) == 0) {
322 iflush();
324 if (rtadr1 - rtadr0 == IXXMAXBYTES) {
325 iflush();
329 } else {
330 sp = lkpsym(".__.END.", 0);
331 if (sp && (sp->s_axp->a_bap->a_ofp == ofp)) {
332 symadr = symval(sp);
333 chksum = 0x04;
334 chksum += 0x05;
335 chksum += symadr;
336 chksum += symadr >> 8;
337 chksum += symadr >> 16;
338 chksum += symadr >> 24;
339 #ifdef LONGINT
340 fprintf(ofp, ":04000005%08lX%02lX\n", symadr, (~chksum + 1) & 0x00ff);
341 #else
342 fprintf(ofp, ":04000005%08X%02X\n", symadr, (~chksum + 1) & 0x00ff);
343 #endif
346 fprintf(ofp, ":00000001FF\n");
351 /*)Function iflush()
353 * The function iflush() outputs the relocated data
354 * in the standard Intel format.
356 * local variables:
357 * a_uint chksum byte checksum
358 * a_uint lo_addr address within segment
359 * a_uint hi_addr segment number
360 * int i loop counter
361 * int max number of data bytes
362 * int reclen record length
364 * global variables:
365 * int a_bytes T Line Address Bytes
366 * FILE * ofp output file handle
367 * int rtaflg first output flag
368 * char rtbuf[] output buffer
369 * a_uint rtadr0 address temporary
370 * a_uint rtadr1 address temporary
372 * functions called:
373 * int fprintf() c_library
375 * side effects:
376 * The data is output to the file defined by ofp.
380 * This function derived from the work
381 * of G. Osborn, gary@s-4.com.
382 * The new version concatenates the assembler
383 * output records when they represent contiguous
384 * memory segments to produce IXXMAXBYTES data byte
385 * Intel Hex output lines whenever possible, resulting
386 * in a substantial reduction in file size.
387 * More importantly, the download time
388 * to the target system is much improved.
391 VOID
392 iflush()
394 int i, max, reclen;
395 a_uint chksum, lo_addr, hi_addr;
396 // rom addresses, calculated based on the virtual ones
397 a_uint rrtadr0 = rtadr0;
398 // translate virtual addresses for gameboy
399 if(TARGET_IS_GB){
400 if(rrtadr0 > 0x10000)
401 rrtadr0 = (rrtadr0>>16) * 0x4000 + (rrtadr0&0xffff) - 0x4000;
404 max = (int) (rtadr1 - rtadr0);
405 if (max) {
406 if (a_bytes > 2) {
407 static a_uint prev_hi_addr = 0;
409 hi_addr = (rrtadr0 >> 16) & 0xffff;
410 if ((hi_addr != prev_hi_addr) || rtaflg) {
411 chksum = 0x02;
412 chksum += 0x04;
413 chksum += hi_addr;
414 chksum += hi_addr >> 8;
415 #ifdef LONGINT
416 fprintf(ofp, ":02000004%04lX%02lX\n", hi_addr, (~chksum + 1) & 0x00ff);
417 #else
418 fprintf(ofp, ":02000004%04X%02X\n", hi_addr, (~chksum + 1) & 0x00ff);
419 #endif
420 prev_hi_addr = hi_addr;
425 * Only the ":" and the checksum itself are excluded
426 * from the checksum. The record length includes
427 * only the data bytes.
429 lo_addr = rrtadr0 & 0xffff;
430 reclen = max;
431 chksum = reclen;
432 chksum += lo_addr;
433 chksum += lo_addr >> 8;
434 #ifdef LONGINT
435 fprintf(ofp, ":%02X%04lX00", reclen, lo_addr);
436 #else
437 fprintf(ofp, ":%02X%04X00", reclen, lo_addr);
438 #endif
439 for (i=0; i<max; i++) {
440 chksum += rtbuf[i];
441 fprintf(ofp, "%02X", rtbuf[i] & 0x00ff);
444 * 2's complement
446 #ifdef LONGINT
447 fprintf(ofp, "%02lX\n", (~chksum + 1) & 0x00ff);
448 #else
449 fprintf(ofp, "%02X\n", (~chksum + 1) & 0x00ff);
450 #endif
451 rtadr0 = rtadr1;
457 /*)S19/S28/S37 Formats
458 * Record Type Field - This field signifies the start of a
459 * record and identifies the the record
460 * type as follows:
462 * 2-Byte Address: Ascii S1 - Data Record
463 * Ascii S9 - End of File Record
464 * 3-Byte Address: Ascii S2 - Data Record
465 * Ascii S8 - End of File Record
466 * 4-Byte Address: Ascii S3 - Data Record
467 * Ascii S7 - End of File Record
469 * Record Length Field - This field specifies the record length
470 * which includes the address, data, and
471 * checksum fields. The 8 bit record
472 * length value is converted to two ascii
473 * characters, high digit first.
475 * Load Address Field - This field consists of the 4/6/8 ascii
476 * characters which result from converting
477 * the the binary value of the address in
478 * which to begin loading this record. The
479 * order is as follows:
481 * S37: High digit of fourth byte of address.
482 * Low digit of fourth byte of address.
483 * S28/S37: High digit of third byte of address.
484 * Low digit of third byte of address.
485 * S19/S28/S37: High digit of high byte of address.
486 * Low digit of high byte of address.
487 * High digit of low byte of address.
488 * Low digit of low byte of address.
490 * In an End of File record this field con-
491 * sists of either 4/6/8 ascii zeros or the
492 * program entry address.
494 * Data Field - This field consists of the actual data,
495 * converted to two ascii characters, high
496 * digit first. There are no data bytes in
497 * the End of File record.
499 * Checksum Field - The checksum field is the 8 bit binary
500 * sum of the record length field, the load
501 * address field, and the data field. This
502 * sum is then complemented (1's comple-
503 * ment) and converted to two ascii
504 * characters, high digit first.
507 /*)Function sxx(i)
509 * int i 1 - process data
510 * 0 - end of data
512 * The function s19() loads the output buffer with
513 * the relocated data.
515 * local variables:
516 * a_uint addr address temporary
517 * a_uint chksum byte checksum
518 * char * frmt format string pointer
519 * int i loop counter
520 * a_uint j temporary
521 * int k loop counter
522 * int max number of data bytes
523 * int reclen record length
524 * struct sym *sp symbol pointer
525 * a_uint symadr symbol address
527 * global variables:
528 * int a_bytes T Line Address Bytes
529 * int hilo byte order
530 * FILE * ofp output file handle
531 * int rtcnt count of data words
532 * int rtflg[] output the data flag
533 * a_uint rtval[] relocated data
534 * char rtbuf[] output buffer
535 * a_uint rtadr0 address temporary
536 * a_uint rtadr1 address temporary
537 * a_uint rtadr2 address temporary
539 * functions called:
540 * int fprintf() c_library
541 * VOID sflush() lkout.c
543 * side effects:
544 * The data is placed into the output buffer.
548 * Number of Data Field bytes is:
550 * 2 Record Type Field
551 * 2 Record Length Field
552 * 4/6/8 Load Address Field
553 * 2 Checksum Field
555 * Plus 32 data bytes (64 characters)
558 VOID
559 sxx(i)
560 int i;
562 struct sym *sp;
563 char *frmt;
564 int k, reclen;
565 a_uint j, addr, symadr, chksum;
567 if (i) {
568 if (hilo == 0) {
569 switch(a_bytes){
570 default:
571 case 2:
572 j = rtval[0];
573 rtval[0] = rtval[1];
574 rtval[1] = j;
575 break;
576 case 3:
577 j = rtval[0];
578 rtval[0] = rtval[2];
579 rtval[2] = j;
580 break;
581 case 4:
582 j = rtval[0];
583 rtval[0] = rtval[3];
584 rtval[3] = j;
585 j = rtval[2];
586 rtval[2] = rtval[1];
587 rtval[1] = j;
588 break;
591 for (i=0,rtadr2=0; i<a_bytes; i++) {
592 rtadr2 = (rtadr2 << 8) | rtval[i];
595 if (rtadr2 != rtadr1) {
597 * data bytes not contiguous between records
599 sflush();
600 rtadr0 = rtadr1 = rtadr2;
602 for (k=a_bytes; k<rtcnt; k++) {
603 if (rtflg[k]) {
604 rtbuf[(int) (rtadr1++ - rtadr0)] = rtval[k];
605 if (rtadr1 - rtadr0 == SXXMAXBYTES) {
606 sflush();
610 } else {
612 * Only the "S_" and the checksum itself are excluded
613 * from the checksum. The record length does not
614 * include "S_" and the pair count. It does
615 * include the address bytes, the data bytes,
616 * and the checksum.
618 reclen = 1 + a_bytes;
619 chksum = reclen;
620 sp = lkpsym(".__.END.", 0);
621 if (sp && (sp->s_axp->a_bap->a_ofp == ofp)) {
622 symadr = symval(sp);
623 for (i=0,addr=symadr; i<a_bytes; i++,addr>>=8) {
624 chksum += addr;
626 } else {
627 symadr = 0;
629 #ifdef LONGINT
630 switch(a_bytes) {
631 default:
632 case 2: frmt = "S9%02X%04lX"; addr = symadr & 0x0000ffffl; break;
633 case 3: frmt = "S8%02X%06lX"; addr = symadr & 0x00ffffffl; break;
634 case 4: frmt = "S7%02X%08lX"; addr = symadr & 0xffffffffl; break;
636 #else
637 switch(a_bytes) {
638 default:
639 case 2: frmt = "S9%02X%04X"; addr = symadr & 0x0000ffff; break;
640 case 3: frmt = "S8%02X%06X"; addr = symadr & 0x00ffffff; break;
641 case 4: frmt = "S7%02X%08X"; addr = symadr & 0xffffffff; break;
643 #endif
644 fprintf(ofp, frmt, reclen, addr);
646 * 1's complement
648 #ifdef LONGINT
649 fprintf(ofp, "%02lX\n", (~chksum) & 0x00ff);
650 #else
651 fprintf(ofp, "%02X\n", (~chksum) & 0x00ff);
652 #endif
657 /*)Function sflush()
659 * The function sflush() outputs the relocated data
660 * in the standard Motorola format.
662 * local variables:
663 * a_uint addr address temporary
664 * a_uint chksum byte checksum
665 * char * frmt format string pointer
666 * int i loop counter
667 * int max number of data bytes
668 * int reclen record length
670 * global variables:
671 * int a_bytes T Line Address Bytes
672 * FILE * ofp output file handle
673 * char rtbuf[] output buffer
674 * a_uint rtadr0 address temporary
675 * a_uint rtadr1 address temporary
677 * functions called:
678 * int fprintf() c_library
680 * side effects:
681 * The data is output to the file defined by ofp.
685 * Written by G. Osborn, gary@s-4.com, 6-17-98.
686 * The new version concatenates the assembler
687 * output records when they represent contiguous
688 * memory segments to produce SXXMAXBYTES data byte
689 * S_ output lines whenever possible, resulting
690 * in a substantial reduction in file size.
691 * More importantly, the download time
692 * to the target system is much improved.
695 VOID
696 sflush()
698 char *frmt;
699 int i, max, reclen;
700 a_uint addr, chksum;
702 max = (int) (rtadr1 - rtadr0);
703 if (max == 0) {
704 return;
708 * Only the "S_" and the checksum itself are excluded
709 * from the checksum. The record length does not
710 * include "S_" and the pair count. It does
711 * include the address bytes, the data bytes,
712 * and the checksum.
714 reclen = max + 1 + a_bytes;
715 chksum = reclen;
716 for (i=0,addr=rtadr0; i<a_bytes; i++,addr>>=8) {
717 chksum += addr;
719 #ifdef LONGINT
720 switch(a_bytes) {
721 default:
722 case 2: frmt = "S1%02X%04lX"; addr = rtadr0 & 0x0000ffffl; break;
723 case 3: frmt = "S2%02X%06lX"; addr = rtadr0 & 0x00ffffffl; break;
724 case 4: frmt = "S3%02X%08lX"; addr = rtadr0 & 0xffffffffl; break;
726 #else
727 switch(a_bytes) {
728 default:
729 case 2: frmt = "S1%02X%04X"; addr = rtadr0 & 0x0000ffff; break;
730 case 3: frmt = "S2%02X%06X"; addr = rtadr0 & 0x00ffffff; break;
731 case 4: frmt = "S3%02X%08X"; addr = rtadr0 & 0xffffffff; break;
733 #endif
734 fprintf(ofp, frmt, reclen, addr);
735 for (i=0; i<max; i++) {
736 chksum += rtbuf[i];
737 fprintf(ofp, "%02X", rtbuf[i] & 0x00ff);
740 * 1's complement
742 #ifdef LONGINT
743 fprintf(ofp, "%02lX\n", (~chksum) & 0x00ff);
744 #else
745 fprintf(ofp, "%02X\n", (~chksum) & 0x00ff);
746 #endif
747 rtadr0 = rtadr1;
751 /*)Disk BASIC Format
753 * Each code segment starts with the following record:
755 * Record Preamble - This field is either $00 (for start of new
756 * record) or $FF (for last record in file).
758 * Record Length Field - This field specifies the record length
759 * that follows the Load Address Field.
761 * 16-Bit Length - 2-bytes
762 * 24-Bit Length - 3-bytes
763 * 32-Bit Length - 4-bytes
765 * Load Address Field - This field consists of the address where
766 * the record will be loaded into memory.
768 * 16-Bit Address - 2-bytes
769 * 24-Bit Address - 3-bytes
770 * 32-Bit Address - 4-bytes
772 * Binary Data Bytes - Record Length data bytes.
774 * After the last code segment, a final record like the one above is
775 * placed. In this final segment, the Record Preamble is $FF, the
776 * Record Length Field is $0000 and the Load Adress Field is the
777 * execution address.
780 /*)Function dbx(i)
782 * int i 1 - process data
783 * 0 - end of data
785 * The function decb() loads the output buffer with
786 * the relocated data.
788 * local variables:
789 * int k loop counter
790 * struct sym *sp symbol pointer
791 * a_uint symadr start address
793 * global variables:
794 * int a_bytes T Line Address Bytes
795 * FILE * ofp output file handle
796 * int rtcnt count of data words
797 * int rtflg[] output the data flag
798 * a_uint rtval[] relocated data
799 * char rtbuf[] output buffer
800 * a_uint rtadr0 address temporary
801 * a_uint rtadr1 address temporary
802 * a_uint rtadr2 address temporary
804 * functions called:
805 * int putc() c_library
806 * VOID dflush() lkout.c
808 * side effects:
809 * The data is placed into the output buffer.
812 VOID
813 dbx(i)
814 int i;
816 struct sym *sp;
817 int k;
818 a_uint j, symadr;
820 if (i) {
821 if (hilo == 0) {
822 switch(a_bytes){
823 default:
824 case 2:
825 j = rtval[0];
826 rtval[0] = rtval[1];
827 rtval[1] = j;
828 break;
829 case 3:
830 j = rtval[0];
831 rtval[0] = rtval[2];
832 rtval[2] = j;
833 break;
834 case 4:
835 j = rtval[0];
836 rtval[0] = rtval[3];
837 rtval[3] = j;
838 j = rtval[2];
839 rtval[2] = rtval[1];
840 rtval[1] = j;
841 break;
844 for (i=0,rtadr2=0; i<a_bytes; i++) {
845 rtadr2 = (rtadr2 << 8) | rtval[i];
848 if (rtadr2 != rtadr1) {
850 * data bytes not contiguous between records
852 dflush();
853 rtadr0 = rtadr1 = rtadr2;
855 for (k=a_bytes; k<rtcnt; k++) {
856 if (rtflg[k]) {
857 rtbuf[(int) (rtadr1++ - rtadr0)] = rtval[k];
858 if (rtadr1 - rtadr0 == (unsigned) (DBXMAXBYTES - (2 * a_bytes) - 1)) {
859 dflush();
863 } else {
864 /* Disk BASIC BIN Trailer */
865 sp = lkpsym(".__.END.", 0);
866 if (sp && (sp->s_axp->a_bap->a_ofp == ofp)) {
867 symadr = symval(sp);
868 } else {
869 symadr = 0;
871 /* Terminator */
872 putc(0xFF, ofp);
874 /* Size (0) */
875 switch(a_bytes) {
876 case 4: putc((int) (0 >> 24) & 0xFF, ofp);
877 case 3: putc((int) (0 >> 16) & 0xFF, ofp);
878 default:
879 case 2: putc((int) (0 >> 8) & 0xFF, ofp);
880 putc((int) (0 >> 0) & 0xFF, ofp);
881 break;
884 /* Starting Address */
885 switch(a_bytes) {
886 case 4: putc((int) (symadr >> 24) & 0xFF, ofp);
887 case 3: putc((int) (symadr >> 16) & 0xFF, ofp);
888 default:
889 case 2: putc((int) (symadr >> 8) & 0xFF, ofp);
890 putc((int) (symadr >> 0) & 0xFF, ofp);
891 break;
897 /*)Function dflush()
899 * The function dflush() outputs the relocated data
900 * in the Disk BASIC loadable format
902 * local variables:
903 * int i loop counter
904 * int max number of data bytes
906 * global variables:
907 * FILE * ofp output file handle
908 * char rtbuf[] output buffer
909 * a_uint rtadr0 address temporary
910 * a_uint rtadr1 address temporary
912 * functions called:
913 * int putc() c_library
915 * side effects:
916 * The data is output to the file defined by ofp.
920 * Written by Boisy G. Pitre, boisy@boisypitre.com, 6-7-04
923 VOID
924 dflush()
926 int i, max;
928 max = (int) (rtadr1 - rtadr0);
929 if (max == 0) {
930 return;
933 /* Preamble Byte */
934 putc(0, ofp);
936 /* Record Size */
937 switch(a_bytes){
938 case 4: putc((int) (max >> 24) & 0xFF, ofp);
939 case 3: putc((int) (max >> 16) & 0xFF, ofp);
940 default:
941 case 2: putc((int) (max >> 8) & 0xFF, ofp);
942 putc((int) (max >> 0) & 0xFF, ofp);
943 break;
946 /* Load Address */
947 switch(a_bytes){
948 case 4: putc((int) (rtadr0 >> 24) & 0xFF, ofp);
949 case 3: putc((int) (rtadr0 >> 16) & 0xFF, ofp);
950 default:
951 case 2: putc((int) (rtadr0 >> 8) & 0xFF, ofp);
952 putc((int) (rtadr0 >> 0) & 0xFF, ofp);
953 break;
956 for (i = 0; i < max; i++) {
957 putc(rtbuf[i], ofp);
960 rtadr0 = rtadr1;