* listing.c, config/obj-aout.c: added intermixed
[binutils-gdb.git] / gas / listing.c
1 /* listing.c - mainting assembly listings
2 Copyright (C) 1991, 1992 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS 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 2, or (at your option)
9 any later version.
10
11 GAS 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.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /*
21 Contributed by Steve Chamberlain
22 sac@cygnus.com
23
24
25 A listing page looks like:
26
27 LISTING_HEADER sourcefilename pagenumber
28 TITLE LINE
29 SUBTITLE LINE
30 linenumber address data source
31 linenumber address data source
32 linenumber address data source
33 linenumber address data source
34
35 If not overridden, the listing commands are:
36
37 .title "stuff"
38 Put "stuff" onto the title line
39 .sbttl "stuff"
40 Put stuff onto the subtitle line
41
42 If these commands come within 10 lines of the top of the page, they
43 will affect the page they are on, as well as any subsequent page
44
45 .eject
46 Thow a page
47 .list
48 Increment the enable listing counter
49 .nolist
50 Decrement the enable listing counter
51
52 .psize Y[,X]
53 Set the paper size to X wide and Y high. Setting a psize Y of
54 zero will suppress form feeds except where demanded by .eject
55
56 If the counter goes below zero, listing is suppressed.
57
58
59 Listings are a maintained by read calling various listing_<foo>
60 functions. What happens most is that the macro NO_LISTING is not
61 defined (from the Makefile), then the macro LISTING_NEWLINE expands
62 into a call to listing_newline. The call is done from read.c, every
63 time it sees a newline, and -l is on the command line.
64
65 The function listing_newline remembers the frag associated with the
66 newline, and creates a new frag - note that this is wasteful, but not
67 a big deal, since listing slows things down a lot anyway. The
68 function also rememebers when the filename changes.
69
70 When all the input has finished, and gas has had a chance to settle
71 down, the listing is output. This is done by running down the list of
72 frag/source file records, and opening the files as needed and printing
73 out the bytes and chars associated with them.
74
75 The only things which the architecture can change about the listing
76 are defined in these macros:
77
78 LISTING_HEADER The name of the architecture
79 LISTING_WORD_SIZE The make of the number of bytes in a word, this determines
80 the clumping of the output data. eg a value of
81 2 makes words look like 1234 5678, whilst 1
82 would make the same value look like 12 34 56
83 78
84 LISTING_LHS_WIDTH Number of words of above size for the lhs
85
86 LISTING_LHS_WIDTH_SECOND Number of words for the data on the lhs
87 for the second line
88
89 LISTING_LHS_CONT_LINES Max number of lines to use up for a continutation
90 LISTING_RHS_WIDTH Number of chars from the input file to print
91 on a line
92 */
93
94 #include "as.h"
95 #include <obstack.h>
96 #include "input-file.h"
97 #include "targ-cpu.h"
98
99 #ifndef NO_LISTING
100 #ifndef LISTING_HEADER
101 #define LISTING_HEADER "GAS LISTING"
102 #endif
103 #ifndef LISTING_WORD_SIZE
104 #define LISTING_WORD_SIZE 4
105 #endif
106 #ifndef LISTING_LHS_WIDTH
107 #define LISTING_LHS_WIDTH 1
108 #endif
109 #ifndef LISTING_LHS_WIDTH_SECOND
110 #define LISTING_LHS_WIDTH_SECOND 1
111 #endif
112 #ifndef LISTING_RHS_WIDTH
113 #define LISTING_RHS_WIDTH 100
114 #endif
115 #ifndef LISTING_LHS_CONT_LINES
116 #define LISTING_LHS_CONT_LINES 4
117 #endif
118
119
120
121
122 /* This structure remembers which .s were used */
123 typedef struct file_info_struct
124 {
125 char *filename;
126 int linenum;
127 FILE *file;
128 struct file_info_struct *next;
129 } file_info_type ;
130
131
132 /* this structure rememebrs which line from which file goes into which
133 frag */
134 typedef struct list_info_struct
135 {
136 /* Frag which this line of source is nearest to */
137 fragS *frag;
138 /* The actual line in the source file */
139 unsigned int line;
140 /* Pointer to the file info struct for the file which this line
141 belongs to */
142 file_info_type *file;
143
144 /* Next in list */
145 struct list_info_struct *next;
146
147
148 /* Pointer to the file info struct for the high level language
149 source line that belongs here */
150 file_info_type *hll_file;
151
152 /* High level language source line */
153 unsigned int hll_line;
154
155
156 /* Pointer to any error message associated with this line */
157 char *message;
158
159 enum
160 {
161 EDICT_NONE,
162 EDICT_SBTTL,
163 EDICT_TITLE,
164 EDICT_NOLIST,
165 EDICT_LIST,
166 EDICT_EJECT
167 } edict;
168 char *edict_arg;
169
170 } list_info_type;
171
172
173 static struct list_info_struct *head;
174 struct list_info_struct *listing_tail;
175 extern int listing;
176 extern unsigned int physical_input_line;
177 extern fragS *frag_now;
178
179
180 static int paper_width = 200;
181 static int paper_height = 60;
182
183
184 /* this static array is used to keep the text of data to be printed
185 before the start of the line.
186 It is stored so we can give a bit more info on the next line. To much, and large
187 initialized arrays will use up lots of paper.
188 */
189
190 static char data_buffer[100];
191 static unsigned int data_buffer_size;
192
193
194 static void
195 DEFUN(listing_message,(name, message),
196 char *name AND
197 char *message)
198 {
199 unsigned int l = strlen(name) + strlen(message)+1;
200 char *n = malloc(l);
201 strcpy(n,name);
202 strcat(n,message);
203 if(listing_tail != (list_info_type *)NULL)
204 {
205 listing_tail->message = n;
206 }
207
208 }
209
210
211
212
213 void
214 DEFUN(listing_warning,(message),
215 char *message)
216 {
217 listing_message("Warning:", message);
218 }
219
220 void
221 DEFUN(listing_error,(message),
222 char *message)
223 {
224 listing_message("Error:", message);
225 }
226
227
228
229
230 static file_info_type *file_info_head;
231
232 static file_info_type *
233 DEFUN(file_info, (file_name),
234 char *file_name)
235 {
236 /* Find an entry with this file name */
237 file_info_type *p = file_info_head;
238
239 while (p != (file_info_type *)NULL)
240 {
241 if (strcmp(p->filename, file_name) == 0)
242 return p;
243 p = p->next;
244 }
245
246 /* Make new entry */
247
248 p = (file_info_type *)xmalloc(sizeof(file_info_type));
249 p->next = file_info_head;
250 file_info_head = p;
251 p->filename = xmalloc(strlen(file_name)+1);
252 strcpy(p->filename, file_name);
253 p->linenum = 0;
254 p->file = fopen(p->filename,"r");
255 return p;
256
257 }
258
259
260 static void
261 DEFUN_VOID(new_frag)
262 {
263
264 frag_wane(frag_now);
265 frag_new(0);
266
267 }
268
269 void
270 DEFUN(listing_newline,(ps),
271 char *ps)
272 {
273 char *s = ps;
274 extern char *file_name;
275 static unsigned int last_line =0xffff ;
276
277
278 list_info_type *new;
279 if (physical_input_line != last_line)
280 {
281 last_line = physical_input_line;
282 new_frag();
283
284 new = (list_info_type *)malloc(sizeof(list_info_type));
285 new->frag = frag_now;
286 new->line = physical_input_line ;
287 new->file = file_info(file_name);
288
289 if (listing_tail)
290 {
291 listing_tail->next = new;
292 }
293 else
294 {
295 head = new;
296 }
297 listing_tail = new;
298 new->next = (list_info_type *)NULL;
299 new->message = (char *)NULL;
300 new->edict = EDICT_NONE;
301 new_frag();
302 }
303 }
304
305
306
307
308 static char *
309 DEFUN(buffer_line,(file, line, size),
310 file_info_type *file AND
311 char *line AND
312 unsigned int size)
313 {
314 unsigned int count = 0;
315 int c;
316
317 char *p = line;
318 if (file->file == (FILE*)NULL)
319 {
320 return "";
321 }
322
323 c = fgetc(file->file);
324 size -= 1; /* leave room for null */
325 while (c != EOF && c != '\n')
326 {
327 if (count < size)
328 *p++ = c;
329 count++;
330
331 c= fgetc(file->file);
332 }
333 if (c == EOF)
334 {
335 rewind(file->file);
336 file->linenum = 0;
337
338 }
339 file->linenum++;
340 *p++ = 0;
341 return line;
342 }
343
344
345 static char *fn;
346
347 static unsigned int eject; /* Eject pending */
348 static unsigned int page; /* Current page number */
349 static char *title; /* current title */
350 static char *subtitle; /* current subtitle */
351 static unsigned int on_page; /* number of lines printed on current page */
352
353
354 static void
355 DEFUN(listing_page,(list),
356 list_info_type *list)
357 {
358 /* Grope around, see if we can see a title or subtitle edict coming up
359 soon (we look down 10 lines of the page and see if it's there)*/
360 if ((eject || (on_page >= paper_height)) && paper_height != 0)
361 {
362 unsigned int c = 10;
363 int had_title = 0;
364 int had_subtitle = 0;
365
366 page++;
367
368 while (c != 0 && list)
369 {
370 if (list->edict == EDICT_SBTTL && !had_subtitle)
371 {
372 had_subtitle = 1;
373 subtitle = list->edict_arg;
374 }
375 if (list->edict == EDICT_TITLE && !had_title)
376 {
377 had_title = 1;
378 title = list->edict_arg;
379 }
380 list = list->next;
381 c--;
382 }
383
384
385 if (page > 1)
386 {
387 printf("\f");
388 }
389
390 printf("%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
391 printf("%s\n", title);
392 printf("%s\n", subtitle);
393 on_page = 3;
394 eject = 0;
395 }
396 }
397
398
399 static unsigned int
400 DEFUN(calc_hex,(list),
401 list_info_type *list)
402 {
403 list_info_type *first = list;
404 list_info_type *last = first;
405 unsigned int address = ~0;
406
407 fragS *frag;
408 fragS *frag_ptr;
409
410 unsigned int byte_in_frag = 0;
411
412 int anything = 0;
413
414 /* Find first frag which says it belongs to this line */
415 frag = list->frag;
416 while (frag && frag->line != list)
417 frag = frag->fr_next;
418
419 frag_ptr = frag;
420
421 data_buffer_size = 0;
422
423 /* Dump all the frags which belong to this line */
424 while (frag_ptr != (fragS *)NULL && frag_ptr->line == first)
425 {
426 /* Print as many bytes from the fixed part as is sensible */
427 while(byte_in_frag < frag_ptr->fr_fix && data_buffer_size < sizeof(data_buffer)-10)
428 {
429 if (address == ~0)
430 {
431 address = frag_ptr->fr_address;
432 }
433
434 sprintf(data_buffer + data_buffer_size, "%02X",(frag_ptr->fr_literal[byte_in_frag]) & 0xff);
435 data_buffer_size += 2;
436 byte_in_frag++;
437 }
438 /* Print as many bytes from the variable part as is sensible */
439 while (byte_in_frag < frag_ptr->fr_var * frag_ptr->fr_offset
440 && data_buffer_size < sizeof(data_buffer)-10)
441 {
442 if (address == ~0)
443 {
444 address = frag_ptr->fr_address;
445 }
446 data_buffer[data_buffer_size++] = '*';
447 data_buffer[data_buffer_size++] = '*';
448
449 byte_in_frag++;
450 }
451 frag_ptr = frag_ptr->fr_next;
452 }
453 data_buffer[data_buffer_size++] = 0;
454 return address;
455 }
456
457
458
459
460
461
462 static void
463 DEFUN(print_lines,(list, string, address),
464 list_info_type *list AND
465 char *string AND
466 unsigned int address)
467 {
468 unsigned int idx;
469 unsigned int nchars;
470 unsigned int lines;
471 unsigned int byte_in_word =0;
472 char *src = data_buffer;
473
474 /* Print the stuff on the first line */
475 listing_page(list);
476 nchars = (LISTING_WORD_SIZE*2 +1) * LISTING_LHS_WIDTH ;
477 /* Print the hex for the first line */
478 if (address == ~0)
479 {
480 printf("% 4d ", list->line);
481 for (idx = 0; idx < nchars; idx++)
482 printf(" ");
483
484 printf("\t%s\n", string ? string : "");
485 on_page++;
486 listing_page(0);
487
488 }
489 else
490 {
491 if (had_errors())
492 {
493 printf("% 4d ???? ", list->line);
494 }
495 else
496 {
497 printf("% 4d %04x ", list->line, address);
498 }
499
500 /* And the data to go along with it */
501 idx = 0;
502
503 while (*src && idx < nchars)
504 {
505 printf("%c%c", src[0], src[1]);
506 src += 2;
507 byte_in_word++;
508 if (byte_in_word == LISTING_WORD_SIZE)
509 {
510 printf(" ");
511 idx++;
512 byte_in_word = 0;
513 }
514 idx+=2;
515 }
516
517 for (;idx < nchars; idx++)
518 printf(" ");
519
520 printf("\t%s\n", string ? string : "");
521 on_page++;
522 listing_page(list);
523 if (list->message)
524 {
525 printf("**** %s\n",list->message);
526 listing_page(list);
527 on_page++;
528 }
529
530 for (lines = 0;
531 lines < LISTING_LHS_CONT_LINES
532 && *src;
533 lines++) {
534 nchars = ((LISTING_WORD_SIZE*2) +1) * LISTING_LHS_WIDTH_SECOND -1;
535 idx = 0;
536 /* Print any more lines of data, but more compactly */
537 printf("% 4d ", list->line);
538
539 while (*src && idx < nchars)
540 {
541 printf("%c%c", src[0], src[1]);
542 src+=2;
543 idx+=2;
544 byte_in_word++;
545 if (byte_in_word == LISTING_WORD_SIZE)
546 {
547 printf(" ");
548 idx++;
549 byte_in_word = 0;
550 }
551 }
552
553 printf("\n");
554 on_page++;
555 listing_page(list);
556
557 }
558
559
560 }
561 }
562
563
564
565
566
567
568 static void
569 DEFUN_VOID(list_symbol_table)
570 {
571 extern symbolS *symbol_rootP;
572
573 symbolS *ptr ;
574 eject = 1;
575 listing_page(0);
576 printf("DEFINED SYMBOLS\n");
577 on_page++;
578
579 for (ptr = symbol_rootP; ptr != (symbolS*)NULL; ptr = symbol_next(ptr))
580 {
581 if (ptr->sy_frag->line)
582 {
583 printf("%20s:%-5d %2d:%08x %s \n",
584 ptr->sy_frag->line->file->filename,
585 ptr->sy_frag->line->line,
586 S_GET_SEGMENT(ptr),
587 S_GET_VALUE(ptr),
588 S_GET_NAME(ptr));
589 on_page++;
590 listing_page(0);
591
592 }
593
594 }
595 printf("\n");
596 on_page++;
597 listing_page(0);
598 printf("UNDEFINED SYMBOLS\n");
599 on_page++;
600 listing_page(0);
601
602 for (ptr = symbol_rootP; ptr != (symbolS*)NULL; ptr = symbol_next(ptr))
603 {
604 if (strlen(S_GET_NAME(ptr)) != 0)
605 {
606 if (ptr->sy_frag->line == 0)
607 {
608
609 printf("%s\n", S_GET_NAME(ptr));
610 on_page++;
611 listing_page(0);
612 }
613 }
614 }
615 }
616
617 void
618 DEFUN(print_source,(current_file, list, buffer, width),
619 file_info_type *current_file AND
620 list_info_type *list AND
621 char *buffer AND
622 unsigned int width)
623 {
624 if (current_file->file) {
625 while (current_file->linenum < list->hll_line)
626 {
627 char* p = buffer_line(current_file, buffer, width);
628 printf("%4d:%-13s **** %s\n", current_file->linenum, current_file->filename, p);
629 on_page++;
630 listing_page(list);
631 }
632 }
633 }
634
635 void
636 DEFUN(listing_listing,(name),
637 char *name)
638 {
639 list_info_type *list = head;
640 file_info_type *current_hll_file = (file_info_type *)NULL;
641
642 unsigned int page= 1;
643 unsigned int prev = 0;
644 char *message;
645 char *buffer;
646 char *p;
647 unsigned int addr = 0;
648 int on_page = 0;
649 int show_listing = 1;
650 unsigned int width;
651
652 buffer = malloc(LISTING_RHS_WIDTH);
653 eject = 1;
654 list = head;
655
656 while (list != (list_info_type *)NULL && 0)
657 {
658 if (list->next)
659 list->frag = list->next->frag;
660 list = list->next;
661
662 }
663
664 list = head->next;
665
666
667 while ( list)
668 {
669 width = LISTING_RHS_WIDTH > paper_width ? paper_width :
670 LISTING_RHS_WIDTH;
671
672 switch (list->edict) {
673 case EDICT_LIST:
674 show_listing++;
675 break;
676 case EDICT_NOLIST:
677 show_listing--;
678 break;
679 case EDICT_EJECT:
680 break;
681 case EDICT_NONE:
682 break;
683 case EDICT_TITLE:
684 title = list->edict_arg;
685 break;
686 case EDICT_SBTTL:
687 subtitle = list->edict_arg;
688 break;
689 default:
690 abort();
691 }
692
693 if (show_listing > 0)
694 {
695 /* Scan down the list and print all the stuff which can be done
696 with this line (or lines) */
697 message = 0;
698
699 if (list->hll_file)
700 {
701 current_hll_file = list->hll_file;
702 }
703
704 if (current_hll_file && list->hll_line && listing & LISTING_HLL)
705 {
706 print_source(current_hll_file, list, buffer, width);
707 }
708
709 p = buffer_line(list->file, buffer, width);
710
711 print_lines(list, p, calc_hex(list));
712
713 if (list->edict == EDICT_EJECT)
714 {
715 eject = 1;
716 }
717 }
718 else
719 {
720
721 p = buffer_line(list->file, buffer, width);
722 }
723
724 list = list->next;
725 }
726 free(buffer);
727 }
728
729 void
730 DEFUN(listing_print,(name),
731 char *name)
732 {
733 title = "";
734 subtitle = "";
735
736 if (listing & LISTING_NOFORM)
737 {
738 paper_height = 0;
739 }
740
741 if (listing & LISTING_LISTING)
742 {
743 listing_listing(name);
744
745 }
746 if (listing & LISTING_SYMBOLS)
747 {
748 list_symbol_table();
749 }
750 }
751
752
753 void
754 DEFUN(listing_file,(name),
755 char *name)
756 {
757 fn = name;
758 }
759
760 void
761 DEFUN_VOID(listing_eject)
762 {
763 listing_tail->edict = EDICT_EJECT;
764 }
765
766 void
767 DEFUN_VOID(listing_flags)
768 {
769
770 }
771 void
772 DEFUN(listing_list,(on),
773 unsigned int on)
774 {
775 listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
776 }
777
778
779 void
780 DEFUN_VOID(listing_psize)
781 {
782 paper_height = get_absolute_expression();
783
784 if (paper_height < 0 || paper_height > 1000)
785 {
786 paper_height = 0;
787 as_warn("strantge paper height, set to no form");
788 }
789 if (*input_line_pointer == ',')
790 {
791 input_line_pointer++;
792 paper_width = get_absolute_expression();
793 }
794 }
795
796
797 void
798 DEFUN(listing_title,(depth),
799 unsigned int depth)
800 {
801 char *start;
802 char *title;
803 unsigned int length;
804
805 SKIP_WHITESPACE();
806 if (*input_line_pointer=='\"') {
807 input_line_pointer++;
808 start = input_line_pointer;
809
810 while (*input_line_pointer)
811 {
812 if (*input_line_pointer == '\"')
813 {
814 length = input_line_pointer - start;
815 title = malloc(length + 1);
816 memcpy(title, start, length);
817 title[length] = 0;
818 listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
819 listing_tail->edict_arg = title;
820 input_line_pointer++;
821 demand_empty_rest_of_line();
822 return;
823 }
824 else if (*input_line_pointer == '\n')
825 {
826 as_bad("New line in title");
827 demand_empty_rest_of_line();
828 return;
829 }
830 else
831 {
832 input_line_pointer++;
833 }
834 }
835 }
836 else
837 {
838 as_bad("expecting title in quotes");
839 }
840 }
841
842
843
844 void
845 DEFUN(listing_source_line,(line),
846 unsigned int line)
847 {
848 new_frag();
849 listing_tail->hll_line = line;
850 new_frag();
851
852 }
853
854 void
855 DEFUN(listing_source_file,(file),
856 char *file)
857 {
858 listing_tail->hll_file = file_info(file);
859 }
860
861
862
863 #else
864
865
866 /* Dummy functions for when compiled without listing enabled */
867
868 void
869 DEFUN_VOID(listing_flags)
870 {
871 s_ignore();
872 }
873
874 void DEFUN_VOID(listing_list)
875 {
876 s_ignore();
877 }
878
879 void DEFUN_VOID(listing_eject)
880 {
881 s_ignore();
882 }
883 void DEFUN(listing_psize)
884 {
885 s_ignore();
886 }
887
888 void DEFUN(listing_title, (depth),
889 unsigned int depth)
890 {
891 s_ignore();
892 }
893 void
894 DEFUN(listing_file,(name),
895 char *name)
896 {
897
898 }
899
900 void DEFUN(listing_newline,(name),
901 char *name)
902 {
903
904 }
905
906 void DEFUN(listing_source_line,(n),
907 unsigned int n)
908 {
909
910 }
911 void DEFUN(listing_source_file, (n),
912 char *n)
913 {
914
915 }
916
917
918
919 #endif
920