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