1 /* ".LST" file output for gpasm
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
3 James Bowman, Craig Franklin
4 Copyright (C) 2012 Borut Razem
5
6 Copyright (C) 2016 Molnar Karoly
7
8 This file is part of gputils.
9
10 gputils is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 gputils is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with gputils; see the file COPYING. If not, write to
22 the Free Software Foundation, 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
24
25 #include "stdhdr.h"
26
27 #include "libgputils.h"
28 #include "directive.h"
29 #include "gpasm.h"
30 #include "cod.h"
31 #include "coff.h"
32 #include "lst.h"
33
34 #if !HAVE_DECL_STRVERSCMP
35 #include "libiberty.h"
36 #endif
37
38 #ifdef STDC_HEADERS
39 #include <stdarg.h>
40 #endif
41
42 #define STRINGIFY(s) _str(s)
43 #define _str(s) #s
44
45 #define IS_EEPROM ((IS_EEPROM8) || (IS_EEPROM16))
46 #define IS_BYTE ((IS_PIC16E_CORE) || (IS_EEPROM))
47
48 #define MEM_USED_CHAR 'X'
49 #define MEM_UNUSED_CHAR '-'
50
51 #define MAC_PARM_STR_MAX_LENGTH 256
52
53 typedef struct {
54 const symbol_t *sym;
55 enum lst_sym_type_e {
56 LST_SYMBOL,
57 LST_DEFINITION,
58 LST_MACRO
59 } type;
60 } lst_symbol_t;
61
62 /*------------------------------------------------------------------------------------------------*/
63
64 static void
_lst_check_page_start(void)65 _lst_check_page_start(void)
66 {
67 if ((state.lst.lines_per_page != 0) &&
68 ((state.lst.line_of_page == 0) || (state.lst.line_of_page > state.lst.lines_per_page))) {
69 lst_page_start();
70 }
71 }
72
73 /*------------------------------------------------------------------------------------------------*/
74
75 static unsigned int
_lst_spaces(unsigned int Num)76 _lst_spaces(unsigned int Num)
77 {
78 unsigned int i = Num;
79
80 _lst_check_page_start();
81 while (i-- != 0) {
82 putc(' ', state.lst.f);
83 }
84
85 return Num;
86 }
87
88 /*------------------------------------------------------------------------------------------------*/
89
90 static void
_lst_eol(void)91 _lst_eol(void)
92 {
93 if (state.lst.f != NULL) {
94 putc('\n', state.lst.f);
95 state.lst.line_number++;
96 state.lst.line_of_page++;
97 cod_lst_line(COD_NORMAL_LST_LINE);
98 }
99 }
100
101 /*------------------------------------------------------------------------------------------------*/
102
103 /* Print part of a line. Output must not contain newline. Needs call to lst_eol at end of line. */
104
105 static unsigned int
_lst_printf(const char * Format,...)106 _lst_printf(const char *Format, ...)
107 {
108 int r = 0;
109 va_list args;
110
111 if (state.lst.f != NULL) {
112 _lst_check_page_start();
113 va_start(args, Format);
114 r = vfprintf(state.lst.f, Format, args);
115 va_end(args);
116 }
117
118 assert(r >= 0);
119 return (unsigned int)r;
120 }
121
122 /*------------------------------------------------------------------------------------------------*/
123
124 static void
_lst_putc(char Ch)125 _lst_putc(char Ch)
126 {
127 if (state.lst.f != NULL) {
128 putc(Ch, state.lst.f);
129 }
130 }
131
132 /*------------------------------------------------------------------------------------------------*/
133
134 /* find relocation by address */
135
136 static gp_reloc_t *
_find_reloc_by_address(uint16_t Address)137 _find_reloc_by_address(uint16_t Address)
138 {
139 gp_reloc_t *p;
140
141 for (p = state.obj.section->relocation_list.first; p != NULL; p = p->next) {
142 if (p->address == Address) {
143 break;
144 }
145 }
146
147 return p;
148 }
149
150 /*------------------------------------------------------------------------------------------------*/
151
152 /* get previous relocation type */
153
154 static uint16_t
_prev_reloc_type(void)155 _prev_reloc_type(void)
156 {
157 gp_reloc_t *p;
158
159 if (state.obj.section->relocation_list.first == state.obj.section->relocation_list.last) {
160 return 0;
161 }
162
163 p = state.obj.section->relocation_list.last->prev;
164 assert(p != NULL);
165 return ((p->address == p->next->address) ? p->type : 0);
166 }
167
168 /*------------------------------------------------------------------------------------------------*/
169
170 /* print word value with undefined nibbles replaced by "?" */
171 /* enable assertions
172 * #define DO_ASSERT */
173 /* disable assertions */
174 #undef DO_ASSERT
175
176 #ifdef DO_ASSERT
177 #define ASSERT(expr) assert(expr)
178 #else
179 #define ASSERT(expr) ((void)0)
180 #endif
181
182 static unsigned int
_print_reloc(uint16_t Type,uint16_t Current_value,unsigned int Index)183 _print_reloc(uint16_t Type, uint16_t Current_value, unsigned int Index)
184 {
185 proc_class_t class = state.device.class;
186
187 switch (Type) {
188 case RELOC_CALL: {
189 if ((class == PROC_CLASS_PIC12) || (class == PROC_CLASS_PIC12E) || (class == PROC_CLASS_PIC12I) ||
190 (class == PROC_CLASS_SX) || (class == PROC_CLASS_PIC16E)) {
191 ASSERT((Current_value & PIC12_BMSK_CALL) == 0);
192 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
193 }
194 else if ((class == PROC_CLASS_PIC14) || (class == PROC_CLASS_PIC14E) || (class == PROC_CLASS_PIC14EX)) {
195 ASSERT((Current_value & PIC14_BMSK_CALL) == 0);
196 return _lst_printf("%X??? ", (Current_value & 0xf000) >> 12);
197 }
198 else if (class == PROC_CLASS_PIC16) {
199 ASSERT((Current_value & PIC16_BMSK_CALL) == 0);
200 return _lst_printf("???? ");
201 }
202 else if (class == PROC_CLASS_PIC16E) {
203 ASSERT((Current_value & PIC16E_BMSK_CALL0) == 0);
204 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
205 }
206 else {
207 ASSERT(0);
208 return 0;
209 }
210
211 break;
212 }
213
214 /*..................................*/
215
216 case RELOC_GOTO: {
217 if ((class == PROC_CLASS_PIC12) || (class == PROC_CLASS_PIC12E) || (class == PROC_CLASS_PIC12I) ||
218 (class == PROC_CLASS_SX)) {
219 ASSERT((Current_value & PIC12_BMSK_GOTO) == 0);
220 return _lst_printf("%X??? ", (Current_value & 0xf000) >> 12);
221 }
222 else if ((class == PROC_CLASS_PIC14) || (class == PROC_CLASS_PIC14E) || (class == PROC_CLASS_PIC14EX)) {
223 ASSERT((Current_value & PIC14_BMSK_GOTO) == 0);
224 return _lst_printf("%X??? ", (Current_value & 0xf000) >> 12);
225 }
226 else if (class == PROC_CLASS_PIC16) {
227 ASSERT((Current_value & PIC16_BMSK_GOTO) == 0);
228 return _lst_printf("???? ");
229 }
230 else if (class == PROC_CLASS_PIC16E) {
231 ASSERT((Current_value & PIC16E_BMSK_GOTO0) == 0);
232 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
233 }
234 else {
235 ASSERT(0);
236 return 0;
237 }
238
239 break;
240 }
241
242 /*..................................*/
243
244 case RELOC_LOW:
245 /* On non-16bits devices DB directive generates values with
246 * low byte != 0 if more then one byte is defined, for example
247 * DB 0x12, 0x34 generates 0x1234, so the following assertion fails
248 * in such cases.
249 * TODO: This should be solved in DB directive handling function
250 * do_db(), file directive.c.
251 * ASSERT((Current_value & 0xff) == 0); */
252 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
253 break;
254
255 /*..................................*/
256
257 case RELOC_HIGH:
258 case RELOC_LFSR2:
259 case RELOC_UPPER:
260 case RELOC_CONDBRA:
261 ASSERT((Current_value & 0xff) == 0);
262 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
263 break;
264
265 /*..................................*/
266
267 case RELOC_P: {
268 char buf[5] = "????";
269
270 if (RELOC_F != _prev_reloc_type()) {
271 sprintf(&buf[2], "%02X", Current_value & 0x00ff);
272 }
273
274 ASSERT((Current_value & 0x1f00) == 0);
275 return _lst_printf("%s ", buf);
276 break;
277 }
278
279 /*..................................*/
280
281 case RELOC_BANKSEL: {
282 if (class == PROC_CLASS_PIC12) {
283 ASSERT((Current_value & PIC12_BMSK_BxF) == 0); /* 04A4-04E4 or 05A4-05E4 */
284 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
285 }
286 else if ((class == PROC_CLASS_PIC12E) || (class == PROC_CLASS_PIC12I)) {
287 ASSERT((Current_value & PIC12E_BMSK_MOVLB) == 0);
288 return _lst_printf("%03X? ", (Current_value & 0x0fff0) >> 4);
289 }
290 else if (class == PROC_CLASS_PIC14) {
291 ASSERT((Current_value & PIC14_BMSK_BxF) == 0); /* 1283-1303 or 1683-1703 */
292 return _lst_printf("%X??? ", (Current_value & 0xf000) >> 12);
293 }
294 else if (class == PROC_CLASS_PIC14E) {
295 ASSERT((Current_value & PIC14E_BMSK_MOVLB) == 0); /* 0020-003F */
296 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
297 }
298 else if (class == PROC_CLASS_PIC14EX) {
299 ASSERT((Current_value & PIC14EX_BMSK_MOVLB) == 0); /* 0140-017F */
300 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
301 }
302 else if (class == PROC_CLASS_PIC16) {
303 ASSERT((Current_value & PIC16_BMSK_MOVLB) == 0); /* 0100-010F */
304 return _lst_printf("%03X? ", (Current_value & 0xfff0) >> 4);
305 }
306 else if (class == PROC_CLASS_PIC16E) {
307 ASSERT((Current_value & PIC16E_BMSK_MOVLB) == 0); /* 0100-010F */
308 return _lst_printf("%03X? ", (Current_value & 0xfff0) >> 4);
309 }
310 return _lst_printf("???? ");
311 break;
312 }
313
314 /*..................................*/
315
316 case RELOC_ALL:
317 return _lst_printf("???? ");
318 break;
319
320 /*..................................*/
321
322 case RELOC_IBANKSEL: {
323 if (class == PROC_CLASS_PIC14) {
324 ASSERT((Current_value & PIC12_BMSK_BxF) == 0);
325 return _lst_printf("1?83 "); /* 1383 or 1783 */
326 }
327 else if ((class == PROC_CLASS_PIC14E) || (class == PROC_CLASS_PIC14EX)) {
328 ASSERT((Current_value & PIC12_BMSK_BxF) == 0);
329 return _lst_printf("%X??? ", (Current_value & 0xf000) >> 12); /* 120A-118A or 160A-158A */
330 }
331 else if (class == PROC_CLASS_PIC16) {
332 ASSERT((Current_value & 0x00ff) == 0);
333 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
334 }
335 else {
336 ASSERT(0);
337 return 0;
338 }
339
340 break;
341 }
342
343 /*..................................*/
344
345 case RELOC_F: {
346 if (class == PROC_CLASS_SX) {
347 ASSERT((Current_value & 0x0007) == 0);
348 return _lst_printf("%03X? ", (Current_value & 0xfff0) >> 4);
349 }
350 else if ((class == PROC_CLASS_PIC12) || (class == PROC_CLASS_PIC12E) || (class == PROC_CLASS_PIC12I)) {
351 ASSERT((Current_value & MASK_PIC12_FILE) == 0);
352 }
353 else if ((class == PROC_CLASS_PIC14) || (class == PROC_CLASS_PIC14E) || (class == PROC_CLASS_PIC14EX)) {
354 ASSERT((Current_value & MASK_PIC14_FILE) == 0);
355 }
356 else if ((class == PROC_CLASS_PIC16) || (class == PROC_CLASS_PIC16E)) {
357 ASSERT((Current_value & MASK_PIC16_FILE) == 0);
358 }
359 else {
360 ASSERT(0);
361 return 0;
362 }
363 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
364 break;
365 }
366
367 /*..................................*/
368
369 case RELOC_TRIS_3BIT:
370 ASSERT((Current_value & PIC12_BMSK_TRIS) == 0);
371 return _lst_printf("%03X? ", (Current_value & 0x00f0) >> 4);
372 break;
373
374 /*..................................*/
375
376 case RELOC_TRIS:
377 ASSERT((Current_value & 0x001f) == 0);
378 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
379 break;
380
381 /*..................................*/
382
383 case RELOC_MOVLR: {
384 if (class == PROC_CLASS_PIC16) {
385 ASSERT((Current_value & PIC16_BMSK_MOVLR) == 0);
386 return _lst_printf("%02X?%X ", (Current_value & 0xff00) >> 8, Current_value & 0x000f); /* 010.-01F. */
387 }
388 else {
389 ASSERT(0);
390 return 0;
391 }
392
393 break;
394 }
395
396 /*..................................*/
397
398 case RELOC_MOVLB: {
399 if ((class == PROC_CLASS_PIC12E) || (class == PROC_CLASS_PIC12I)) {
400 ASSERT((Current_value & PIC12E_BMSK_MOVLB) == 0);
401 return _lst_printf("%03X? ", (Current_value & 0xfff0) >> 4);
402 }
403 else if (class == PROC_CLASS_PIC14E) {
404 ASSERT((Current_value & PIC14E_BMSK_MOVLB) == 0);
405 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
406 }
407 else if (class == PROC_CLASS_PIC14EX) {
408 ASSERT((Current_value & PIC14EX_BMSK_MOVLB) == 0);
409 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
410 }
411 else if (class == PROC_CLASS_PIC16) {
412 ASSERT((Current_value & PIC16_BMSK_MOVLB) == 0);
413 return _lst_printf("%03X? ", (Current_value & 0xfff0) >> 4); /* 01.0-01.F */
414 }
415 else if (class == PROC_CLASS_PIC16E) {
416 ASSERT((Current_value & PIC16E_BMSK_MOVLB) == 0);
417 return _lst_printf("%03X? ", (Current_value & 0xfff0) >> 4);
418 }
419 else {
420 ASSERT(0);
421 return 0;
422 }
423
424 break;
425 }
426
427 /*..................................*/
428
429 case RELOC_GOTO2:
430 /* This is only used for PIC16E (pic18). */
431 case RELOC_FF1:
432 case RELOC_FF2:
433 /* removed assertion since it fails during sdcc pic16 library
434 * compilation: do_insn, case INSN_CLASS_FF
435 * ASSERT((Current_value & 0x0fff) == 0); */
436 return _lst_printf("%X??? ", (Current_value & 0xf000) >> 12);
437 break;
438
439 /*..................................*/
440
441 case RELOC_LFSR1:
442 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
443 break;
444
445 /*..................................*/
446
447 case RELOC_BRA: {
448 if ((class == PROC_CLASS_PIC14E) || (class == PROC_CLASS_PIC14EX)) {
449 ASSERT((Current_value & PIC14E_BMSK_RBRA9) == 0);
450 }
451 else if (class == PROC_CLASS_PIC16E) {
452 ASSERT((Current_value & PIC16E_BMSK_RBRA11) == 0);
453 }
454 else {
455 ASSERT(0);
456 return 0;
457 }
458 return _lst_printf("%X??? ", (Current_value & 0xf000) >> 12);
459 break;
460 }
461
462 /*..................................*/
463
464 case RELOC_ACCESS: {
465 if (class == PROC_CLASS_PIC16E) {
466 ASSERT((Current_value & 0x00ff) == 0);
467 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
468 }
469 else {
470 ASSERT(0);
471 return 0;
472 }
473 break;
474 }
475
476 /*..................................*/
477
478 case RELOC_PAGESEL_WREG: {
479 if (Index == 0) {
480 /* movlw PAGE_VALUE */
481 if ((class == PROC_CLASS_PIC12) || (class == PROC_CLASS_PIC12E) || (class == PROC_CLASS_PIC12I)) {
482 ASSERT((Current_value & PIC12_BMSK_MOVLW) == 0);
483 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8); /* 0C00 -- movlw ... */
484 }
485 else if (class == PROC_CLASS_PIC14) {
486 ASSERT((Current_value & PIC14_BMSK_MOVLW) == 0);
487 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8); /* 3000 -- movlw ... */
488 }
489 else {
490 ASSERT(0);
491 return 0;
492 }
493 }
494 else {
495 /* movwf register */
496 if ((class == PROC_CLASS_PIC12) || (class == PROC_CLASS_PIC12E) || (class == PROC_CLASS_PIC12I)) {
497 ASSERT((Current_value & PIC12_BMSK_FILE) == 0);
498 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8); /* 0023 -- movwf STATUS */
499 }
500 else if (class == PROC_CLASS_PIC14) {
501 ASSERT((Current_value & PIC14_BMSK_FILE) == 0);
502 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8); /* 008A -- movwf PCLATH */
503 }
504 else {
505 ASSERT(0);
506 return 0;
507 }
508 }
509
510 break;
511 }
512
513 /*..................................*/
514
515 case RELOC_PAGESEL_BITS: {
516 if ((class == PROC_CLASS_PIC12) || (class == PROC_CLASS_PIC12E) || (class == PROC_CLASS_PIC12I)) {
517 ASSERT((Current_value & PIC12_BMSK_BxF) == 0);
518 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8); /* 04A3-04E3 or 05A3-05E3 */
519 }
520 else if (class == PROC_CLASS_PIC14) {
521 ASSERT((Current_value & PIC14_BMSK_BxF) == 0);
522 return _lst_printf("%X??? ", (Current_value & 0xf000) >> 12); /* 120A-118A or 160A-158A */
523 }
524 else {
525 ASSERT(0);
526 return 0;
527 }
528
529 break;
530 }
531
532 /*..................................*/
533
534 case RELOC_PAGESEL_MOVLP: {
535 if ((class == PROC_CLASS_PIC14E) || (class == PROC_CLASS_PIC14EX)) {
536 ASSERT((Current_value & PIC14E_BMSK_MOVLP) == 0);
537 return _lst_printf("%02X?? ", (Current_value & 0xff00) >> 8);
538 }
539 else {
540 ASSERT(0);
541 return 0;
542 }
543
544 break;
545 }
546
547 /*..................................*/
548
549 /* unimplemented relocations */
550 case RELOC_PAGESEL:
551 case RELOC_SCNSZ_LOW:
552 case RELOC_SCNSZ_HIGH:
553 case RELOC_SCNSZ_UPPER:
554 case RELOC_SCNEND_LOW:
555 case RELOC_SCNEND_HIGH:
556 case RELOC_SCNEND_UPPER:
557 case RELOC_SCNEND_LFSR1:
558 case RELOC_SCNEND_LFSR2:
559 default:
560 return 0;
561 }
562 }
563
564 /*------------------------------------------------------------------------------------------------*/
565
566 static unsigned int
_lst_data(unsigned int Position,MemBlock_t * M,unsigned int Byte_addr,unsigned int Bytes_emitted,uint16_t Reloc_type)567 _lst_data(unsigned int Position, MemBlock_t *M, unsigned int Byte_addr, unsigned int Bytes_emitted,
568 uint16_t Reloc_type)
569 {
570 uint8_t emit_byte;
571 uint16_t emit_word;
572 unsigned int start_addr;
573 unsigned int lst_bytes;
574 gp_boolean is_eeprom_area;
575 unsigned int n;
576
577 lst_bytes = 0;
578 is_eeprom_area = (gp_processor_is_eeprom_byte_addr(state.processor, Byte_addr) >= 0) ? true : false;
579 /* When in a idata or byte packed section or eeprom area, print byte by byte. */
580 if (IS_EEPROM8 || is_eeprom_area || (state.obj.new_sect_flags & (STYP_DATA | STYP_BPACK))) {
581 while ((Bytes_emitted > lst_bytes) && ((Position + 3) <= LST_LINENUM_POS)) {
582 gp_mem_b_get(M, Byte_addr, &emit_byte, NULL, NULL);
583 Position += _lst_printf("%02X ", emit_byte);
584 ++Byte_addr;
585 ++lst_bytes;
586 }
587 }
588 else { /* non-code pack section */
589 /* list first byte on odd address */
590 if ((Bytes_emitted != 0) && (Byte_addr & 1)) {
591 gp_mem_b_get(M, Byte_addr, &emit_byte, NULL, NULL);
592 Position += _lst_printf("%02X ", emit_byte);
593 ++Byte_addr;
594 ++lst_bytes;
595 }
596 /* list full words */
597 start_addr = Byte_addr;
598 while (((Bytes_emitted - lst_bytes) > 1) && ((Position + 5) <= LST_LINENUM_POS)) {
599 state.device.class->i_memory_get(M, Byte_addr, &emit_word, NULL, NULL);
600
601 /* Display '?' for undefined bytes if it is a relocatable code. */
602 if (Reloc_type != 0) {
603 n = _print_reloc(Reloc_type, emit_word, (Byte_addr - start_addr) / 2);
604
605 Position += (n == 0) ? _lst_printf("%04X ", emit_word) : n;
606 }
607 else {
608 Position += _lst_printf("%04X ", emit_word);
609 }
610
611 Byte_addr += 2;
612 lst_bytes += 2;
613 }
614
615 if (((Bytes_emitted - lst_bytes) == 1) && ((Position + 3) <= LST_LINENUM_POS)) {
616 gp_mem_b_get(M, Byte_addr, &emit_byte, NULL, NULL);
617 Position += _lst_printf("%02X ", emit_byte);
618 ++Byte_addr;
619 ++lst_bytes;
620 }
621 }
622
623 /* append appropriate spacing */
624 _lst_spaces(LST_LINENUM_POS - Position);
625
626 return lst_bytes;
627 }
628
629 /*------------------------------------------------------------------------------------------------*/
630
631 static void
_cod_symbol_table(void)632 _cod_symbol_table(void)
633 {
634 const symbol_t **lst;
635 size_t sym_count;
636
637 sym_count = gp_sym_get_symbol_count(state.stGlobal);
638
639 if (sym_count == 0) {
640 return;
641 }
642
643 if (!state.mpasm_compatible) {
644 lst = gp_sym_clone_symbol_array(state.stGlobal, gp_sym_version_compare_fn);
645 }
646 else {
647 lst = gp_sym_clone_symbol_array(state.stGlobal, gp_sym_compare_fn);
648 }
649
650 assert(lst != NULL);
651
652 cod_write_symbols(lst, sym_count);
653 free(lst);
654 }
655
656 /*------------------------------------------------------------------------------------------------*/
657
658 void
lst_init(void)659 lst_init(void)
660 {
661 state.lst.line_of_page = 0;
662 state.lst.page = 0;
663 state.lst.lines_per_page = 59;
664 state.lst.line_number = 1;
665 state.lst.memory_map = true;
666 state.lst.symbol_table = true;
667 state.lst.lst_state = LST_IN_MEM;
668
669 /* Determine state.start_date. */
670 gp_date_string(state.lst.start_date, sizeof(state.lst.start_date));
671
672 if (!state.cmd_line.macro_expand){
673 state.lst.expand = true;
674 }
675
676 state.lst.force = state.cmd_line.lst_force;
677 state.lst.config_address = 0;
678 state.lst.title_name[0] = '\0';
679 state.lst.subtitle_name[0] = '\0';
680 state.lst.tabstop = 8; /* Default tabstop every 8. */
681 state.lst.line_width = 132; /* Default line width is 132. */
682
683 if (state.lst_file != OUT_NAMED) {
684 snprintf(state.lst_file_name, sizeof(state.lst_file_name), "%s.lst", state.base_file_name);
685 }
686
687 if (state.lst_file == OUT_SUPPRESS) {
688 state.lst.f = NULL;
689 state.lst.enabled = false;
690 unlink(state.lst_file_name);
691 }
692 else {
693 state.lst.f = fopen(state.lst_file_name, "wt");
694
695 if (state.lst.f == NULL) {
696 perror(state.lst_file_name);
697 exit(1);
698 }
699 state.lst.enabled = true;
700 }
701
702 cod_lst_line(COD_FIRST_LST_LINE);
703 }
704
705 /*------------------------------------------------------------------------------------------------*/
706
707 void
lst_close(void)708 lst_close(void)
709 {
710 cod_lst_line(COD_LAST_LST_LINE);
711
712 state.lst.lst_state = LST_IN_NONE;
713
714 if (state.lst.f != NULL) {
715 lst_line(NULL);
716 lst_line("Errors : %5d", state.num.errors);
717 lst_line("Warnings : %5d reported, %5d suppressed", state.num.warnings, state.num.warnings_suppressed);
718 lst_line("Messages : %5d reported, %5d suppressed", state.num.messages, state.num.messages_suppressed);
719 lst_line(NULL);
720 putc('\f', state.lst.f);
721
722 fclose(state.lst.f);
723 state.lst.f = NULL;
724 }
725 }
726
727 /*------------------------------------------------------------------------------------------------*/
728
729 void
lst_throw(void)730 lst_throw(void)
731 {
732 if (state.lst.f != NULL) {
733 state.lst.page++;
734 fprintf(state.lst.f,
735 "%s%s %*.*s %-28sPAGE %2d\n%s\n%s\n",
736 (state.lst.page == 1) ? "" : "\f",
737 GPASM_VERSION_STRING,
738 (int)(45 - sizeof(GPASM_VERSION_STRING)),
739 (int)(45 - sizeof(GPASM_VERSION_STRING)),
740 state.src_file_name,
741 state.lst.start_date,
742 state.lst.page,
743 state.lst.title_name,
744 state.lst.subtitle_name);
745
746 state.lst.line_of_page = 4;
747 cod_lst_line(COD_NORMAL_LST_LINE);
748 cod_lst_line(COD_NORMAL_LST_LINE);
749 cod_lst_line(COD_NORMAL_LST_LINE);
750 state.lst.line_number += 3;
751 }
752 }
753
754 /*------------------------------------------------------------------------------------------------*/
755
756 static void
_mem_header(void)757 _mem_header(void)
758 {
759 lst_line("LOC OBJECT CODE LINE SOURCE TEXT");
760 lst_line(" VALUE");
761 }
762
763 /*------------------------------------------------------------------------------------------------*/
764
765 static void
_symbol_table_header(void)766 _symbol_table_header(void)
767 {
768 lst_line("SYMBOL TABLE");
769
770 if (!state.mpasm_compatible) {
771 lst_line("%-32s %-10s %-8s %-11s %s", " LABEL", " TYPE", " VALUE", " VALUE", " VALUE");
772 lst_line("%-32s %-10s %-8s %-11s %s", "", "", " (hex)", " (dec)", " (text)");
773 }
774 else {
775 lst_line("%-32s %-8s", " LABEL", " VALUE");
776 }
777 }
778
779 /*------------------------------------------------------------------------------------------------*/
780
781 static void
_memory_map_header(void)782 _memory_map_header(void)
783 {
784 lst_line("MEMORY USAGE MAP ('%c' = Used, '%c' = Unused)", MEM_USED_CHAR, MEM_UNUSED_CHAR);
785 }
786
787 /*------------------------------------------------------------------------------------------------*/
788
789 void
lst_page_start(void)790 lst_page_start(void)
791 {
792 lst_throw();
793 switch (state.lst.lst_state) {
794 case LST_IN_MEM:
795 _mem_header();
796 break;
797
798 case LST_IN_SYMTAB:
799 _symbol_table_header();
800 break;
801
802 case LST_IN_MAP:
803 _memory_map_header();
804 break;
805
806 default:
807 lst_line(NULL);
808 break;
809 }
810
811 lst_line(NULL);
812 }
813
814 /*------------------------------------------------------------------------------------------------*/
815
816 void
lst_line(const char * Format,...)817 lst_line(const char *Format, ...)
818 {
819 va_list args;
820
821 if (state.lst.f != NULL) {
822 if (Format != NULL) {
823 _lst_check_page_start();
824 va_start(args, Format);
825 vfprintf(state.lst.f, Format, args);
826 va_end(args);
827 }
828 _lst_eol();
829 }
830 }
831
832 /*------------------------------------------------------------------------------------------------*/
833
834 void
lst_err_line(const char * Type,unsigned int Code,const char * Format,va_list Args)835 lst_err_line(const char *Type, unsigned int Code, const char *Format, va_list Args)
836 {
837 if (state.lst.f != NULL) {
838 _lst_check_page_start();
839 fprintf(state.lst.f, "%s[%03d]%s: ", Type, Code, (strcmp(Type, "Error") == 0) ? " " : "");
840 vfprintf(state.lst.f, Format, Args);
841 _lst_eol();
842 }
843 }
844
845 /*------------------------------------------------------------------------------------------------*/
846
847 #define MEM_IS_USED(M, I) \
848 (((M)->memory != NULL) ? (IS_BYTE ? (gp_mem_b_offset_is_used(M, I)) : \
849 (gp_mem_i_offset_is_used_le(M, (I) * 2) == W_USED_ALL)) : false)
850
851 #define NUM_PER_LINE 64
852 #define NUM_PER_BLOCK 16
853
854 void
lst_memory_map(MemBlock_t * M)855 lst_memory_map(MemBlock_t *M)
856 {
857 unsigned int max_mem;
858 unsigned int base;
859 unsigned int i;
860 unsigned int j;
861 int addr_digits;
862 gp_boolean row_is_used;
863 char row_map[NUM_PER_LINE];
864 char ch;
865 unsigned int used;
866
867 state.lst.lst_state = LST_IN_MAP;
868 lst_line(NULL);
869 lst_line(NULL);
870 _memory_map_header();
871 lst_line(NULL);
872
873 addr_digits = (state.device.class != NULL) ? state.device.class->addr_digits : 4;
874
875 while (M != NULL) {
876 max_mem = I_MEM_MAX >> !IS_BYTE;
877 base = IMemAddrFromBase(M->base) >> !IS_BYTE;
878
879 for (i = 0; i < max_mem; i += NUM_PER_LINE) {
880 row_is_used = false;
881
882 for (j = 0; j < NUM_PER_LINE; j++) {
883 if (MEM_IS_USED(M, i + j)) {
884 ch = MEM_USED_CHAR;
885 row_is_used = true;
886 }
887 else {
888 ch = MEM_UNUSED_CHAR;
889 }
890
891 row_map[j] = ch;
892 }
893
894 if (row_is_used) {
895 if (state.show_full_addr && (IS_PIC16E_CORE)) {
896 /* Gpasm mode: Print all address digits. */
897 _lst_printf("%0*X :", addr_digits, (i + base));
898 }
899 else {
900 /* MPASM(X) compatible: Print only lower 4 address digits. */
901 _lst_printf("%04X :", (i + base) & 0xffff);
902 }
903
904 for (j = 0; j < NUM_PER_LINE; j++) {
905 if ((j % NUM_PER_BLOCK) == 0) {
906 _lst_putc(' ');
907 }
908
909 _lst_putc(row_map[j]);
910 }
911
912 _lst_eol();
913 _lst_check_page_start();
914 }
915 }
916
917 M = M->next;
918 }
919
920 lst_line(NULL);
921 lst_line("All other memory blocks unused.");
922 lst_line(NULL);
923
924 /* it seems that MPASM includes config bytes into program memory usage
925 * count for 16 bit cores. See gpasm testsuite:
926 * gpasm/testsuite/gpasm.mchip/listfiles/configX.lst */
927 #define IS_PIC16 (IS_PIC16_CORE) || (IS_PIC16E_CORE)
928
929 if (IS_EEPROM) {
930 lst_line("Memory Bytes Used: %5i", gp_mem_b_used(state.i_memory));
931 }
932 else {
933 used = gp_processor_insn_from_byte_p(state.processor, (!(IS_PIC16) && (state.processor != NULL)) ?
934 b_range_memory_used(state.i_memory, 0,
935 gp_processor_byte_from_insn_c(state.device.class,
936 state.processor->prog_mem_size)) :
937 gp_mem_b_used(state.i_memory));
938
939 lst_line("Program Memory %s Used: %5i", IS_BYTE ? "Bytes" : "Words", used);
940
941 if ((state.processor != NULL) && (state.processor->prog_mem_size >= 0)) {
942 lst_line("Program Memory %s Free: %5u",
943 IS_BYTE ? "Bytes" : "Words",
944 (used <= state.processor->prog_mem_size) ? (state.processor->prog_mem_size - used) : 0);
945 }
946 }
947
948 lst_line(NULL);
949 }
950
951 /*------------------------------------------------------------------------------------------------*/
952
953 #define ADDR_LEN 7
954
955 void
lst_format_line(const char * Src_line,unsigned int Value)956 lst_format_line(const char *Src_line, unsigned int Value)
957 {
958 unsigned int emitted;
959 unsigned int emitted_lines;
960 unsigned int byte_addr;
961 unsigned int bytes_emitted;
962 unsigned int lst_bytes;
963 const char *addr_fmt;
964 unsigned int pos;
965 uint16_t reloc_type;
966 MemBlock_t *m;
967 uint32_t addr;
968 uint16_t word;
969 gp_reloc_t *reloc;
970
971 assert(Src_line != NULL);
972
973 emitted = 0;
974 emitted_lines = 0;
975 bytes_emitted = 0;
976 addr_fmt = (IS_PIC16E_CORE) ? "%06X " : (IS_EEPROM ? "%04X " : "%04X ");
977 pos = 0;
978 m = state.i_memory;
979
980 byte_addr = state.lst.line.was_byte_addr;
981
982 if ((state.mode == MODE_RELOCATABLE) && (state.obj.section != NULL) &&
983 (state.obj.new_sect_flags & STYP_TEXT) && (state.obj.section->relocation_list.last != NULL)) {
984 addr = state.obj.section->address + state.obj.section->relocation_list.last->address;
985
986 if (addr > byte_addr) {
987 /* already passed it, go back to the history */
988 reloc = _find_reloc_by_address(byte_addr);
989 reloc_type = (reloc != NULL) ? reloc->type : 0;
990 }
991 else if (addr == byte_addr) {
992 reloc_type = state.obj.section->relocation_list.last->type;
993 }
994 else {
995 reloc_type = 0;
996 }
997 }
998 else {
999 reloc_type = 0;
1000 }
1001
1002 switch (state.lst.line.linetype) {
1003 case LTY_INSN:
1004 emitted_lines = emitted = state.byte_addr - byte_addr;
1005 break;
1006
1007 case LTY_DATA: {
1008 emitted = state.byte_addr - byte_addr;
1009
1010 if ((SECTION_FLAGS & (STYP_TEXT | (state.mpasm_compatible ? STYP_BPACK : 0))) == STYP_TEXT) {
1011 /* generate line numbers for data directives in program memory;
1012 * in mpasm compatibility mode code_pack doesn't generate line numbers */
1013 emitted_lines = emitted;
1014 }
1015 break;
1016 }
1017
1018 case LTY_RES: {
1019 if (SECTION_FLAGS & STYP_DATA) {
1020 /* generate data listing for idata */
1021 emitted = state.byte_addr - byte_addr;
1022 }
1023 else if (!IS_RAM_ORG) {
1024 /* generate line numbers for res directives in program memory */
1025 emitted_lines = emitted = state.byte_addr - byte_addr;
1026 }
1027 break;
1028 }
1029
1030 case LTY_IDLOCS:
1031 /* always 8 bytes (4 words) */
1032 emitted = 8;
1033 break;
1034
1035 default:
1036 break;
1037 }
1038
1039 coff_add_linenum(emitted_lines);
1040
1041 /* Don't write to file if list is disabled with NOLIST directive */
1042 if (!state.lst.enabled) {
1043 return;
1044 }
1045
1046 byte_addr = 0;
1047 switch (state.lst.line.linetype) {
1048 case LTY_EQU:
1049 case LTY_SET:
1050 pos += _lst_printf(" %08X", Value);
1051 _lst_spaces(LST_LINENUM_POS - pos);
1052 break;
1053
1054 case LTY_SET4:
1055 pos += _lst_printf(" %04X", Value & 0xffff);
1056 _lst_spaces(LST_LINENUM_POS - pos);
1057 break;
1058
1059 case LTY_ORG:
1060 pos += _lst_printf(addr_fmt, gp_processor_insn_from_byte_p(state.processor, state.byte_addr));
1061 _lst_spaces(LST_LINENUM_POS - pos);
1062 break;
1063
1064 case LTY_IDLOCS:
1065 /* not used for 16 bit devices, config is used */
1066 m = state.c_memory;
1067 pos += _lst_printf(addr_fmt, gp_processor_insn_from_byte_p(state.processor, state.device.id_location));
1068 lst_bytes = _lst_data(pos, m, state.device.id_location, emitted, reloc_type);
1069 byte_addr = state.device.id_location + lst_bytes;
1070 bytes_emitted = emitted - lst_bytes;
1071 break;
1072
1073 case LTY_DATA:
1074 case LTY_RES:
1075 pos += _lst_printf(addr_fmt, state.lst.line.was_byte_addr);
1076 goto lst_data;
1077
1078 case LTY_INSN:
1079 pos += _lst_printf(addr_fmt, gp_processor_insn_from_byte_p(state.processor, state.lst.line.was_byte_addr));
1080
1081 lst_data:
1082
1083 lst_bytes = _lst_data(pos, m, state.lst.line.was_byte_addr, emitted, reloc_type);
1084 byte_addr = state.lst.line.was_byte_addr + lst_bytes;
1085 bytes_emitted = emitted - lst_bytes;
1086 break;
1087
1088 case LTY_CONFIG: {
1089 if (IS_PIC16E_CORE) {
1090 /* The config data is byte addressable, but we only want to print words in the list file. */
1091 if (state.lst.config_address == CONFIG4L) {
1092 /* Special case */
1093 state.device.class->i_memory_get(state.c_memory, state.lst.config_address, &word, NULL, NULL);
1094 pos += _lst_printf(addr_fmt, state.lst.config_address);
1095 pos += _lst_printf("%04X", word);
1096 _lst_spaces(LST_LINENUM_POS - pos);
1097 }
1098 else if ((state.lst.config_address & 1) == 0) {
1099 /* if it is an even address don't print anything */
1100 _lst_spaces(LST_LINENUM_POS);
1101 }
1102 else {
1103 state.device.class->i_memory_get(state.c_memory, state.lst.config_address - 1, &word, NULL, NULL);
1104 pos += _lst_printf(addr_fmt, state.lst.config_address - 1);
1105 pos += _lst_printf("%04X", word);
1106 _lst_spaces(LST_LINENUM_POS - pos);
1107 }
1108 }
1109 else {
1110 state.device.class->i_memory_get(state.c_memory, state.lst.config_address, &word, NULL, NULL);
1111 pos += _lst_printf(addr_fmt, gp_processor_insn_from_byte_p(state.processor, state.lst.config_address));
1112 pos += _lst_printf("%04X", word);
1113 _lst_spaces(LST_LINENUM_POS - pos);
1114 }
1115 break;
1116 }
1117
1118 case LTY_SEC:
1119 case LTY_DIR:
1120 case LTY_NONE:
1121 default:
1122 _lst_spaces(LST_LINENUM_POS);
1123 break;
1124 }
1125
1126 if (state.stGlobal == state.stTop) {
1127 _lst_printf("%05d ", state.src_list.last->line_number);
1128 }
1129 else {
1130 _lst_printf(" M ");
1131 }
1132
1133 /* Now copy source line to listing, expanding tabs as required. */
1134 {
1135 int src_column = 0; /* current source line column */
1136 int lst_column = LST_SRC_POS; /* current listing column after the SRC_POS */
1137 const char *p = Src_line;
1138
1139 while (*p != '\0') {
1140 if (*p == '\t') {
1141 int len = state.lst.tabstop - (src_column % state.lst.tabstop);
1142
1143 while (len-- > 0) {
1144 if (lst_column >= state.lst.line_width) {
1145 _lst_eol();
1146 _lst_spaces(LST_SRC_POS);
1147 lst_column = LST_SRC_POS;
1148 }
1149 ++lst_column;
1150 ++src_column;
1151 putc(' ', state.lst.f);
1152 }
1153 }
1154 else {
1155 if (lst_column >= state.lst.line_width) {
1156 _lst_eol();
1157 _lst_spaces(LST_SRC_POS);
1158 lst_column = LST_SRC_POS;
1159 }
1160
1161 ++lst_column;
1162 ++src_column;
1163 putc(*p, state.lst.f);
1164 }
1165 ++p;
1166 }
1167 }
1168
1169 /* Tell the .cod file that the next line(s) has an opcode(s) */
1170 state.cod.emitting = emitted;
1171
1172 _lst_eol();
1173
1174 if (bytes_emitted > 0) {
1175 while (bytes_emitted > 0) {
1176 /* data left to print on separate lines */
1177
1178 pos = _lst_spaces(ADDR_LEN);
1179 lst_bytes = _lst_data(pos, m, byte_addr, bytes_emitted, reloc_type);
1180 byte_addr += lst_bytes;
1181 bytes_emitted -= lst_bytes;
1182 _lst_eol();
1183 }
1184 state.cod.emitting = 0;
1185 }
1186 }
1187
1188 /*------------------------------------------------------------------------------------------------*/
1189
1190 static int
_lst_symbol_verscmp(const void * P0,const void * P1)1191 _lst_symbol_verscmp(const void *P0, const void *P1)
1192 {
1193 return strverscmp(gp_sym_get_symbol_name(((const lst_symbol_t *)P0)->sym),
1194 gp_sym_get_symbol_name(((const lst_symbol_t *)P1)->sym));
1195 }
1196
1197 /*------------------------------------------------------------------------------------------------*/
1198
1199 static int
_lst_symbol_cmp(const void * P0,const void * P1)1200 _lst_symbol_cmp(const void *P0, const void *P1)
1201 {
1202 return strcmp(gp_sym_get_symbol_name(((const lst_symbol_t *)P0)->sym),
1203 gp_sym_get_symbol_name(((const lst_symbol_t *)P1)->sym));
1204 }
1205
1206 /*------------------------------------------------------------------------------------------------*/
1207
1208 /* append the symbol table to the .lst file */
1209
1210 void
lst_symbol_table(void)1211 lst_symbol_table(void)
1212 {
1213 const pnode_t *list;
1214 const pnode_t *head;
1215 const char *string;
1216 const symbol_t **clone;
1217 size_t sym_count;
1218 lst_symbol_t *lst;
1219 lst_symbol_t *ps;
1220 size_t count;
1221 size_t i;
1222 const char *name;
1223 const void *ptr;
1224 const variable_t *var;
1225 numstring_t num_type;
1226 long val;
1227 const macro_head_t *hd;
1228 char *mac_parms;
1229 size_t mac_parm_length;
1230
1231 state.lst.lst_state = LST_IN_SYMTAB;
1232 _symbol_table_header();
1233 lst_line(NULL);
1234
1235 _cod_symbol_table();
1236
1237 count = gp_sym_get_symbol_count(state.stGlobal) + gp_sym_get_symbol_count(state.stDefines) +
1238 gp_sym_get_symbol_count(state.stMacros);
1239 if (count == 0) {
1240 return;
1241 }
1242
1243 ps = lst = GP_Malloc(count * sizeof(lst_symbol_t));
1244
1245 clone = gp_sym_clone_symbol_array(state.stGlobal, NULL);
1246 if (clone != NULL) {
1247 sym_count = gp_sym_get_symbol_count(state.stGlobal);
1248 for (i = 0; i < sym_count; i++) {
1249 ps->sym = clone[i];
1250 ps->type = LST_SYMBOL;
1251 ++ps;
1252 }
1253
1254 free(clone);
1255 }
1256
1257 clone = gp_sym_clone_symbol_array(state.stDefines, NULL);
1258 if (clone != NULL) {
1259 sym_count = gp_sym_get_symbol_count(state.stDefines);
1260 for (i = 0; i < sym_count; i++) {
1261 ps->sym = clone[i];
1262 ps->type = LST_DEFINITION;
1263 ++ps;
1264 }
1265
1266 free(clone);
1267 }
1268
1269 clone = gp_sym_clone_symbol_array(state.stMacros, NULL);
1270 if (clone != NULL) {
1271 sym_count = gp_sym_get_symbol_count(state.stMacros);
1272 for (i = 0; i < sym_count; i++) {
1273 ps->sym = clone[i];
1274 ps->type = LST_MACRO;
1275 ++ps;
1276 }
1277
1278 free(clone);
1279 }
1280
1281 assert(ps == &lst[count]);
1282
1283 if (!state.mpasm_compatible) {
1284 qsort(lst, count, sizeof(lst_symbol_t), _lst_symbol_verscmp);
1285 }
1286 else {
1287 qsort(lst, count, sizeof(lst_symbol_t), _lst_symbol_cmp);
1288 }
1289
1290 for (i = 0; i < count; i++) {
1291 name = gp_sym_get_symbol_name(lst[i].sym);
1292 ptr = gp_sym_get_symbol_annotation(lst[i].sym);
1293
1294 switch (lst[i].type) {
1295 case LST_SYMBOL: {
1296 /* symbol */
1297 var = (const variable_t *)ptr;
1298
1299 if (!state.mpasm_compatible) {
1300 if (var != NULL) {
1301 if (FlagIsClr(var->flags, VATRR_HAS_NO_VALUE)) {
1302 lst_line("%-32s %-10s %08X %11d", name, value_type_to_str(var, false), var->value, var->value);
1303 }
1304 else {
1305 lst_line("%-32s %-10s %8s %-11s", name, value_type_to_str(var, false), "HAS NO", "HAS NO");
1306 }
1307 }
1308 else {
1309 lst_line("%-32s", name);
1310 }
1311 }
1312 else {
1313 lst_line("%-32s %08X", name, (var != NULL) ? var->value : 0);
1314 }
1315 break;
1316 }
1317
1318 case LST_DEFINITION: {
1319 /* define */
1320 list = (const pnode_t *)ptr;
1321
1322 if (list != NULL) {
1323 assert(PnIsList(list));
1324 head = PnListHead(list);
1325
1326 assert(PnIsString(head));
1327 string = PnString(head);
1328 }
1329 else {
1330 string = NULL;
1331 }
1332
1333 if (!state.mpasm_compatible) {
1334 if (string != NULL) {
1335 val = gp_strtol(string, &num_type);
1336
1337 if (num_type != NUM_STR_UNKNOWN) {
1338 /* This definition contains is just a decimal number. */
1339 lst_line("%-32s %-10s %08lX %11ld %s", name, "DEFINITION", val, val, string);
1340 }
1341 else {
1342 /* This definition contains a general text (not just number). */
1343 lst_line("%-32s %-10s %8s %11s %s", name, "DEFINITION", "", "", string);
1344 }
1345 }
1346 else {
1347 lst_line("%-32s %-10s", name, "DEFINITION");
1348 }
1349 } /* if (!state.mpasm_compatible) */
1350 else {
1351 lst_line("%-32s %s", name, (string != NULL) ? string : "");
1352 }
1353 break;
1354 }
1355
1356 case LST_MACRO: {
1357 /* define */
1358 if (!state.mpasm_compatible) {
1359 hd = (const macro_head_t *)ptr;
1360
1361 if (hd != NULL) {
1362 mac_parm_length = 0;
1363 mac_parms = macro_params_to_string(NULL, MAC_PARM_STR_MAX_LENGTH, &mac_parm_length, hd->parms);
1364
1365 if (mac_parms != NULL) {
1366 if (mac_parm_length > 0) {
1367 lst_line("%-32s %-10s %8s %11s %s", name, "MACRO", "", "", mac_parms);
1368 }
1369 else {
1370 lst_line("%-32s %-10s", name, "MACRO");
1371 }
1372
1373 free(mac_parms);
1374 }
1375 else {
1376 lst_line("%-32s %-10s", name, "MACRO");
1377 }
1378 }
1379 else {
1380 lst_line("%-32s %-10s", name, "MACRO");
1381 }
1382 }
1383 else {
1384 lst_line("%-32s", name);
1385 }
1386 break;
1387 }
1388 }
1389 }
1390
1391 free(lst);
1392 }
1393
1394
1395 /*------------------------------------------------------------------------------------------------*/
1396
1397 /*
1398 * Preprocessed file generator.
1399 */
1400
1401 void
preproc_init(void)1402 preproc_init(void)
1403 {
1404 const char *name;
1405
1406 name = state.preproc.preproc_file_name;
1407 if (name != NULL) {
1408 if ((name[0] == '-') && (name[1] == '\0')) {
1409 state.preproc.f = stdout;
1410 }
1411 else if ((state.preproc.f = fopen(name, "wt")) == NULL) {
1412 perror(name);
1413 exit(1);
1414 }
1415 }
1416 }
1417
1418 /*------------------------------------------------------------------------------------------------*/
1419
1420 void
preproc_emit(void)1421 preproc_emit(void)
1422 {
1423 if (state.preproc.f != NULL) {
1424 if (state.preproc.do_emit && asm_enabled()) {
1425 fprintf(state.preproc.f, "%s\n", state.preproc.curr_src_line.line);
1426 }
1427 else {
1428 state.preproc.do_emit = true;
1429 }
1430 }
1431 }
1432