ce0983caba3a642ef4c315a15d85487b53659cb3
[deliverable/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 if (strlen(S_GET_NAME(ptr)))
584 {
585 printf("%20s:%-5d %2d:%08x %s \n",
586 ptr->sy_frag->line->file->filename,
587 ptr->sy_frag->line->line,
588 S_GET_SEGMENT(ptr),
589 S_GET_VALUE(ptr),
590 S_GET_NAME(ptr));
591
592 on_page++;
593 listing_page(0);
594 }
595 }
596
597 }
598 printf("\n");
599 on_page++;
600 listing_page(0);
601 printf("UNDEFINED SYMBOLS\n");
602 on_page++;
603 listing_page(0);
604
605 for (ptr = symbol_rootP; ptr != (symbolS*)NULL; ptr = symbol_next(ptr))
606 {
607 if (ptr && strlen(S_GET_NAME(ptr)) != 0)
608 {
609 if (ptr->sy_frag->line == 0)
610 {
611 printf("%s\n", S_GET_NAME(ptr));
612 on_page++;
613 listing_page(0);
614 }
615 }
616 }
617 }
618
619 void
620 DEFUN(print_source,(current_file, list, buffer, width),
621 file_info_type *current_file AND
622 list_info_type *list AND
623 char *buffer AND
624 unsigned int width)
625 {
626 if (current_file->file) {
627 while (current_file->linenum < list->hll_line)
628 {
629 char* p = buffer_line(current_file, buffer, width);
630 printf("%4d:%-13s **** %s\n", current_file->linenum, current_file->filename, p);
631 on_page++;
632 listing_page(list);
633 }
634 }
635 }
636
637 void
638 DEFUN(listing_listing,(name),
639 char *name)
640 {
641 list_info_type *list = head;
642 file_info_type *current_hll_file = (file_info_type *)NULL;
643
644 unsigned int page= 1;
645 unsigned int prev = 0;
646 char *message;
647 char *buffer;
648 char *p;
649 unsigned int addr = 0;
650 int on_page = 0;
651 int show_listing = 1;
652 unsigned int width;
653
654 buffer = malloc(LISTING_RHS_WIDTH);
655 eject = 1;
656 list = head;
657
658 while (list != (list_info_type *)NULL && 0)
659 {
660 if (list->next)
661 list->frag = list->next->frag;
662 list = list->next;
663
664 }
665
666 list = head->next;
667
668
669 while ( list)
670 {
671 width = LISTING_RHS_WIDTH > paper_width ? paper_width :
672 LISTING_RHS_WIDTH;
673
674 switch (list->edict) {
675 case EDICT_LIST:
676 show_listing++;
677 break;
678 case EDICT_NOLIST:
679 show_listing--;
680 break;
681 case EDICT_EJECT:
682 break;
683 case EDICT_NONE:
684 break;
685 case EDICT_TITLE:
686 title = list->edict_arg;
687 break;
688 case EDICT_SBTTL:
689 subtitle = list->edict_arg;
690 break;
691 default:
692 abort();
693 }
694
695 if (show_listing > 0)
696 {
697 /* Scan down the list and print all the stuff which can be done
698 with this line (or lines) */
699 message = 0;
700
701 if (list->hll_file)
702 {
703 current_hll_file = list->hll_file;
704 }
705
706 if (current_hll_file && list->hll_line && listing & LISTING_HLL)
707 {
708 print_source(current_hll_file, list, buffer, width);
709 }
710
711 p = buffer_line(list->file, buffer, width);
712
713 print_lines(list, p, calc_hex(list));
714
715 if (list->edict == EDICT_EJECT)
716 {
717 eject = 1;
718 }
719 }
720 else
721 {
722
723 p = buffer_line(list->file, buffer, width);
724 }
725
726 list = list->next;
727 }
728 free(buffer);
729 }
730
731 void
732 DEFUN(listing_print,(name),
733 char *name)
734 {
735 title = "";
736 subtitle = "";
737
738 if (listing & LISTING_NOFORM)
739 {
740 paper_height = 0;
741 }
742
743 if (listing & LISTING_LISTING)
744 {
745 listing_listing(name);
746
747 }
748 if (listing & LISTING_SYMBOLS)
749 {
750 list_symbol_table();
751 }
752 }
753
754
755 void
756 DEFUN(listing_file,(name),
757 char *name)
758 {
759 fn = name;
760 }
761
762 void
763 DEFUN_VOID(listing_eject)
764 {
765 listing_tail->edict = EDICT_EJECT;
766 }
767
768 void
769 DEFUN_VOID(listing_flags)
770 {
771
772 }
773 void
774 DEFUN(listing_list,(on),
775 unsigned int on)
776 {
777 listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
778 }
779
780
781 void
782 DEFUN_VOID(listing_psize)
783 {
784 paper_height = get_absolute_expression();
785
786 if (paper_height < 0 || paper_height > 1000)
787 {
788 paper_height = 0;
789 as_warn("strantge paper height, set to no form");
790 }
791 if (*input_line_pointer == ',')
792 {
793 input_line_pointer++;
794 paper_width = get_absolute_expression();
795 }
796 }
797
798
799 void
800 DEFUN(listing_title,(depth),
801 unsigned int depth)
802 {
803 char *start;
804 char *title;
805 unsigned int length;
806
807 SKIP_WHITESPACE();
808 if (*input_line_pointer=='\"') {
809 input_line_pointer++;
810 start = input_line_pointer;
811
812 while (*input_line_pointer)
813 {
814 if (*input_line_pointer == '\"')
815 {
816 length = input_line_pointer - start;
817 title = malloc(length + 1);
818 memcpy(title, start, length);
819 title[length] = 0;
820 listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
821 listing_tail->edict_arg = title;
822 input_line_pointer++;
823 demand_empty_rest_of_line();
824 return;
825 }
826 else if (*input_line_pointer == '\n')
827 {
828 as_bad("New line in title");
829 demand_empty_rest_of_line();
830 return;
831 }
832 else
833 {
834 input_line_pointer++;
835 }
836 }
837 }
838 else
839 {
840 as_bad("expecting title in quotes");
841 }
842 }
843
844
845
846 void
847 DEFUN(listing_source_line,(line),
848 unsigned int line)
849 {
850 new_frag();
851 listing_tail->hll_line = line;
852 new_frag();
853
854 }
855
856 void
857 DEFUN(listing_source_file,(file),
858 char *file)
859 {
860 listing_tail->hll_file = file_info(file);
861 }
862
863
864
865 #else
866
867
868 /* Dummy functions for when compiled without listing enabled */
869
870 void
871 DEFUN_VOID(listing_flags)
872 {
873 s_ignore();
874 }
875
876 void DEFUN_VOID(listing_list)
877 {
878 s_ignore();
879 }
880
881 void DEFUN_VOID(listing_eject)
882 {
883 s_ignore();
884 }
885 void DEFUN(listing_psize)
886 {
887 s_ignore();
888 }
889
890 void DEFUN(listing_title, (depth),
891 unsigned int depth)
892 {
893 s_ignore();
894 }
895 void
896 DEFUN(listing_file,(name),
897 char *name)
898 {
899
900 }
901
902 void DEFUN(listing_newline,(name),
903 char *name)
904 {
905
906 }
907
908 void DEFUN(listing_source_line,(n),
909 unsigned int n)
910 {
911
912 }
913 void DEFUN(listing_source_file, (n),
914 char *n)
915 {
916
917 }
918
919
920
921 #endif
922
This page took 0.049829 seconds and 4 git commands to generate.