White space and comment changes. #ifdef __STDC__ becomes #if __STDC__
[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
101 #ifndef LISTING_HEADER
102 #define LISTING_HEADER "GAS LISTING"
103 #endif
104 #ifndef LISTING_WORD_SIZE
105 #define LISTING_WORD_SIZE 4
106 #endif
107 #ifndef LISTING_LHS_WIDTH
108 #define LISTING_LHS_WIDTH 1
109 #endif
110 #ifndef LISTING_LHS_WIDTH_SECOND
111 #define LISTING_LHS_WIDTH_SECOND 1
112 #endif
113 #ifndef LISTING_RHS_WIDTH
114 #define LISTING_RHS_WIDTH 100
115 #endif
116 #ifndef LISTING_LHS_CONT_LINES
117 #define LISTING_LHS_CONT_LINES 4
118 #endif
119
120
121 /* This structure remembers which .s were used */
122 typedef struct file_info_struct {
123 char *filename;
124 int linenum;
125 FILE *file;
126 struct file_info_struct *next;
127 int end_pending;
128 } file_info_type ;
129
130
131 /* this structure rememebrs which line from which file goes into which frag */
132 typedef struct list_info_struct {
133 /* Frag which this line of source is nearest to */
134 fragS *frag;
135 /* The actual line in the source file */
136 unsigned int line;
137 /* Pointer to the file info struct for the file which this line
138 belongs to */
139 file_info_type *file;
140
141 /* Next in list */
142 struct list_info_struct *next;
143
144
145 /* Pointer to the file info struct for the high level language
146 source line that belongs here */
147 file_info_type *hll_file;
148
149 /* High level language source line */
150 int hll_line;
151
152
153 /* Pointer to any error message associated with this line */
154 char *message;
155
156 enum {
157 EDICT_NONE,
158 EDICT_SBTTL,
159 EDICT_TITLE,
160 EDICT_NOLIST,
161 EDICT_LIST,
162 EDICT_EJECT,
163 } edict;
164 char *edict_arg;
165 } list_info_type;
166
167 static struct list_info_struct *head;
168 struct list_info_struct *listing_tail;
169 extern int listing;
170 extern unsigned int physical_input_line;
171 extern fragS *frag_now;
172
173 static int paper_width = 200;
174 static int paper_height = 60;
175
176 /* this static array is used to keep the text of data to be printed
177 before the start of the line. It is stored so we can give a bit
178 more info on the next line. To much, and large initialized arrays
179 will use up lots of paper. */
180
181 static char data_buffer[100];
182 static unsigned int data_buffer_size;
183
184 static void
185 listing_message(name, message)
186 char *name;
187 char *message;
188 {
189 unsigned int l = strlen(name) + strlen(message) + 1;
190 char *n = malloc(l);
191 strcpy(n,name);
192 strcat(n,message);
193 if (listing_tail != (list_info_type *)NULL) {
194 listing_tail->message = n;
195 }
196
197 return;
198 } /* lising_message() */
199
200 void
201 listing_warning(message)
202 char *message;
203 {
204 listing_message("Warning:", message);
205 }
206
207 void
208 listing_error(message)
209 char *message;
210 {
211 listing_message("Error:", message);
212 }
213
214 static file_info_type *file_info_head;
215
216 static file_info_type *
217 file_info(file_name)
218 char *file_name;
219 {
220 /* Find an entry with this file name */
221 file_info_type *p = file_info_head;
222
223 while (p != (file_info_type *)NULL) {
224 if (strcmp(p->filename, file_name) == 0)
225 return(p);
226 p = p->next;
227 }
228
229 /* Make new entry */
230
231 p = (file_info_type *) xmalloc(sizeof(file_info_type));
232 p->next = file_info_head;
233 file_info_head = p;
234 p->filename = xmalloc(strlen(file_name)+1);
235 strcpy(p->filename, file_name);
236 p->linenum = 0;
237 p->end_pending = 0;
238
239 p->file = fopen(p->filename,"r");
240 return(p);
241 } /* file_info() */
242
243
244 static void
245 new_frag()
246 {
247 frag_wane(frag_now);
248 frag_new(0);
249 }
250
251 void
252 listing_newline(ps)
253 char *ps;
254 {
255 char *s = ps;
256 extern char *file_name;
257 static unsigned int last_line = 0xffff ;
258
259
260 list_info_type *new;
261 if (physical_input_line != last_line) {
262 last_line = physical_input_line;
263 new_frag();
264
265 new = (list_info_type *) malloc(sizeof(list_info_type));
266 new->frag = frag_now;
267 new->line = physical_input_line ;
268 new->file = file_info(file_name);
269
270 if (listing_tail) {
271 listing_tail->next = new;
272 } else {
273 head = new;
274 }
275
276 listing_tail = new;
277 new->next = (list_info_type *) NULL;
278 new->message = (char *) NULL;
279 new->edict = EDICT_NONE;
280 new->hll_file = (file_info_type*) NULL;
281 new->hll_line = 0;
282 new_frag();
283 }
284
285 return;
286 } /* listing_newline() */
287
288
289 /* This function returns the next source line from the file supplied,
290 truncated to size. It appends a fake line to the end of each input
291 file to make. */
292
293 static char *
294 buffer_line(file, line, size)
295 file_info_type *file;
296 char *line;
297 unsigned int size;
298 {
299 unsigned int count = 0;
300 int c;
301
302 char *p = line;
303
304 /* If we couldn't open the file, return an empty line */
305 if (file->file == (FILE*) NULL) {
306 return("");
307 }
308
309 if (file->end_pending == 10) {
310 *p ++ = '\n';
311 rewind(file->file);
312 file->linenum = 0;
313 file->end_pending = 0;
314 }
315
316 c = fgetc(file->file);
317 size -= 1; /* leave room for null */
318
319 while (c != EOF && c != '\n') {
320 if (count < size)
321 *p++ = c;
322 count++;
323
324 c = fgetc(file->file);
325 }
326
327 if (c == EOF) {
328 file->end_pending ++;
329 *p++ = 'E';
330 *p++ = 'O';
331 *p++ = 'F';
332 }
333
334 file->linenum++;
335 *p++ = 0;
336 return(line);
337 } /* buffer_line() */
338
339 static char *fn;
340
341 static unsigned int eject; /* Eject pending */
342 static unsigned int page; /* Current page number */
343 static char *title; /* current title */
344 static char *subtitle; /* current subtitle */
345 static unsigned int on_page; /* number of lines printed on current page */
346
347 static void
348 listing_page(list)
349 list_info_type *list;
350 {
351 /* Grope around, see if we can see a title or subtitle edict
352 coming up soon (we look down 10 lines of the page and see
353 if it's there). */
354
355 if ((eject || (on_page >= paper_height)) && paper_height != 0) {
356 unsigned int c = 10;
357 int had_title = 0;
358 int had_subtitle = 0;
359
360 page++;
361
362 while (c != 0 && list) {
363 if (list->edict == EDICT_SBTTL && !had_subtitle) {
364 had_subtitle = 1;
365 subtitle = list->edict_arg;
366 }
367
368 if (list->edict == EDICT_TITLE && !had_title) {
369 had_title = 1;
370 title = list->edict_arg;
371 }
372 list = list->next;
373 --c;
374 }
375
376 if (page > 1) {
377 printf("\f");
378 }
379
380 printf("%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
381 printf("%s\n", title);
382 printf("%s\n", subtitle);
383 on_page = 3;
384 eject = 0;
385 }
386
387 return;
388 } /* listing_page() */
389
390
391 static unsigned int
392 calc_hex(list)
393 list_info_type *list;
394 {
395 list_info_type *first = list;
396 list_info_type *last = first;
397 unsigned int address = ~0;
398
399 fragS *frag;
400 fragS *frag_ptr;
401
402 unsigned int byte_in_frag = 0;
403
404 int anything = 0;
405
406 /* Find first frag which says it belongs to this line */
407 frag = list->frag;
408 while (frag && frag->line != list)
409 frag = frag->fr_next;
410
411 frag_ptr = frag;
412
413 data_buffer_size = 0;
414
415 /* Dump all the frags which belong to this line */
416 while (frag_ptr != (fragS *)NULL && frag_ptr->line == first) {
417 /* Print as many bytes from the fixed part as is sensible */
418 while(byte_in_frag < frag_ptr->fr_fix && data_buffer_size < sizeof(data_buffer)-10) {
419 if (address == ~0) {
420 address = frag_ptr->fr_address;
421 }
422
423 sprintf(data_buffer + data_buffer_size, "%02X", (frag_ptr->fr_literal[byte_in_frag]) & 0xff);
424 data_buffer_size += 2;
425 byte_in_frag++;
426 }
427
428 /* Print as many bytes from the variable part as is sensible */
429 while (byte_in_frag < frag_ptr->fr_var * frag_ptr->fr_offset
430 && data_buffer_size < sizeof(data_buffer)-10) {
431 if (address == ~0) {
432 address = frag_ptr->fr_address;
433 }
434 data_buffer[data_buffer_size++] = '*';
435 data_buffer[data_buffer_size++] = '*';
436
437 byte_in_frag++;
438 }
439
440 frag_ptr = frag_ptr->fr_next;
441 }
442
443 data_buffer[data_buffer_size++] = 0;
444 return address;
445 } /* calc_hex() */
446
447 static void
448 print_lines(list, string, address)
449 list_info_type *list;
450 char *string;
451 unsigned int address;
452 {
453 unsigned int idx;
454 unsigned int nchars;
455 unsigned int lines;
456 unsigned int byte_in_word =0;
457 char *src = data_buffer;
458
459 /* Print the stuff on the first line */
460 listing_page(list);
461 nchars = (LISTING_WORD_SIZE * 2 + 1) * LISTING_LHS_WIDTH ;
462
463 /* Print the hex for the first line */
464 if (address == ~0) {
465 printf("% 4d ", list->line);
466 for (idx = 0; idx < nchars; idx++)
467 printf(" ");
468
469 printf("\t%s\n", string ? string : "");
470 on_page++;
471 listing_page(0);
472 } else {
473 if (had_errors()) {
474 printf("% 4d ???? ", list->line);
475 } else {
476 printf("% 4d %04x ", list->line, address);
477 }
478
479 /* And the data to go along with it */
480 idx = 0;
481
482 while (*src && idx < nchars) {
483 printf("%c%c", src[0], src[1]);
484 src += 2;
485 byte_in_word++;
486
487 if (byte_in_word == LISTING_WORD_SIZE) {
488 printf(" ");
489 idx++;
490 byte_in_word = 0;
491 }
492 idx+=2;
493 }
494
495 for (;idx < nchars; idx++)
496 printf(" ");
497
498 printf("\t%s\n", string ? string : "");
499 on_page++;
500 listing_page(list);
501 if (list->message) {
502 printf("**** %s\n",list->message);
503 listing_page(list);
504 on_page++;
505 }
506
507 for (lines = 0; lines < LISTING_LHS_CONT_LINES && *src; lines++) {
508 nchars = ((LISTING_WORD_SIZE*2) +1) * LISTING_LHS_WIDTH_SECOND -1;
509 idx = 0;
510 /* Print any more lines of data, but more compactly */
511 printf("% 4d ", list->line);
512
513 while (*src && idx < nchars) {
514 printf("%c%c", src[0], src[1]);
515 src+=2;
516 idx+=2;
517 byte_in_word++;
518 if (byte_in_word == LISTING_WORD_SIZE) {
519 printf(" ");
520 idx++;
521 byte_in_word = 0;
522 }
523 }
524
525 printf("\n");
526 on_page++;
527 listing_page(list);
528 }
529 }
530 } /* print_lines() */
531
532
533 static void
534 list_symbol_table()
535 {
536 extern symbolS *symbol_rootP;
537 symbolS *ptr;
538
539 eject = 1;
540 listing_page(0);
541 printf("DEFINED SYMBOLS\n");
542 on_page++;
543
544 for (ptr = symbol_rootP; ptr != (symbolS*)NULL; ptr = symbol_next(ptr)) {
545 if (ptr->sy_frag->line) {
546 if (strlen(S_GET_NAME(ptr))) {
547 printf("%20s:%-5d %2d:%08x %s \n",
548 ptr->sy_frag->line->file->filename,
549 ptr->sy_frag->line->line,
550 S_GET_SEGMENT(ptr),
551 S_GET_VALUE(ptr),
552 S_GET_NAME(ptr));
553
554 on_page++;
555 listing_page(0);
556 }
557 }
558
559 }
560
561 printf("\n");
562 on_page++;
563 listing_page(0);
564 printf("UNDEFINED SYMBOLS\n");
565 on_page++;
566 listing_page(0);
567
568 for (ptr = symbol_rootP; ptr != (symbolS*)NULL; ptr = symbol_next(ptr)) {
569 if (ptr && strlen(S_GET_NAME(ptr)) != 0) {
570 if (ptr->sy_frag->line == 0) {
571 printf("%s\n", S_GET_NAME(ptr));
572 on_page++;
573 listing_page(0);
574 }
575 }
576 }
577
578 return;
579 } /* list_symbol_table() */
580
581 void
582 print_source(current_file, list, buffer, width)
583 file_info_type *current_file;
584 list_info_type *list;
585 char *buffer;
586 unsigned int width;
587 {
588 if (current_file->file) {
589 while (current_file->linenum < list->hll_line) {
590 char * p = buffer_line(current_file, buffer, width);
591 printf("%4d:%-13s **** %s\n", current_file->linenum, current_file->filename, p);
592 on_page++;
593 listing_page(list);
594 }
595 }
596
597 return;
598 } /* print_source() */
599
600 /* Sometimes the user doesn't want to be bothered by the debugging
601 records inserted by the compiler, see if the line is suspicioous */
602
603 static int
604 debugging_pseudo(line)
605 char *line;
606 {
607 while (isspace(*line))
608 line++;
609
610 if (*line != '.') return 0;
611
612 line++;
613
614 if (strncmp(line, "def",3) == 0) return 1;
615 if (strncmp(line, "val",3) == 0) return 1;
616 if (strncmp(line, "scl",3) == 0) return 1;
617 if (strncmp(line, "line",4) == 0) return 1;
618 if (strncmp(line, "endef",5) == 0) return 1;
619 if (strncmp(line, "ln",2) ==0) return 1;
620 if (strncmp(line, "type",4) ==0) return 1;
621 if (strncmp(line, "size",4) == 0) return 1;
622 if (strncmp(line, "dim",3) ==0) return 1;
623 if (strncmp(line, "tag",3) == 0) return 1;
624
625 return(0);
626 } /* debugging_pseudo() */
627
628 void
629 listing_listing(name)
630 char *name;
631 {
632 char *buffer;
633 char *message;
634 char *p;
635 file_info_type *current_hll_file = (file_info_type *) NULL;
636 int on_page = 0;
637 int show_listing = 1;
638 list_info_type *list = head;
639 unsigned int addr = 0;
640 unsigned int page = 1;
641 unsigned int prev = 0;
642 unsigned int width;
643
644 buffer = malloc(LISTING_RHS_WIDTH);
645 eject = 1;
646 list = head;
647
648 while (list != (list_info_type *)NULL && 0) {
649 if (list->next)
650 list->frag = list->next->frag;
651 list = list->next;
652 }
653
654 list = head->next;
655
656 while (list) {
657 width = LISTING_RHS_WIDTH > paper_width ? paper_width : LISTING_RHS_WIDTH;
658
659 switch (list->edict) {
660 case EDICT_LIST:
661 show_listing++;
662 break;
663 case EDICT_NOLIST:
664 show_listing--;
665 break;
666 case EDICT_EJECT:
667 break;
668 case EDICT_NONE:
669 break;
670 case EDICT_TITLE:
671 title = list->edict_arg;
672 break;
673 case EDICT_SBTTL:
674 subtitle = list->edict_arg;
675 break;
676 default:
677 abort();
678 }
679
680 if (show_listing > 0) {
681 /* Scan down the list and print all the stuff which can be done
682 with this line (or lines) */
683 message = 0;
684
685 if (list->hll_file) {
686 current_hll_file = list->hll_file;
687 }
688
689 if (current_hll_file && list->hll_line && listing & LISTING_HLL) {
690 print_source(current_hll_file, list, buffer, width);
691 }
692
693 p = buffer_line(list->file, buffer, width);
694
695 if (! ((listing & LISTING_NODEBUG) && debugging_pseudo(p))) {
696 print_lines(list, p, calc_hex(list));
697 }
698
699 if (list->edict == EDICT_EJECT) {
700 eject = 1;
701 }
702 } else {
703
704 p = buffer_line(list->file, buffer, width);
705 }
706
707 list = list->next;
708 }
709 free(buffer);
710 } /* listing_listing() */
711
712 void
713 listing_print(name)
714 char *name;
715 {
716 title = "";
717 subtitle = "";
718
719 if (listing & LISTING_NOFORM)
720 {
721 paper_height = 0;
722 }
723
724 if (listing & LISTING_LISTING)
725 {
726 listing_listing(name);
727
728 }
729 if (listing & LISTING_SYMBOLS)
730 {
731 list_symbol_table();
732 }
733 } /* listing_print() */
734
735
736 void
737 listing_file(name)
738 char *name;
739 {
740 fn = name;
741 }
742
743 void
744 listing_eject()
745 {
746 listing_tail->edict = EDICT_EJECT;
747 return;
748 }
749
750 void
751 listing_flags()
752 {
753
754 }
755
756 void
757 listing_list(on)
758 unsigned int on;
759 {
760 listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
761 }
762
763
764 void
765 listing_psize()
766 {
767 paper_height = get_absolute_expression();
768
769 if (paper_height < 0 || paper_height > 1000) {
770 paper_height = 0;
771 as_warn("strantge paper height, set to no form");
772 }
773
774 if (*input_line_pointer == ',') {
775 input_line_pointer++;
776 paper_width = get_absolute_expression();
777 }
778
779 return;
780 } /* listing_psize() */
781
782
783 void
784 listing_title(depth)
785 unsigned int depth;
786 {
787 char *start;
788 char *title;
789 unsigned int length;
790
791 SKIP_WHITESPACE();
792
793 if (*input_line_pointer=='\"') {
794 input_line_pointer++;
795 start = input_line_pointer;
796
797 while (*input_line_pointer) {
798 if (*input_line_pointer == '\"') {
799 length = input_line_pointer - start;
800 title = malloc(length + 1);
801 memcpy(title, start, length);
802 title[length] = 0;
803 listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
804 listing_tail->edict_arg = title;
805 input_line_pointer++;
806 demand_empty_rest_of_line();
807 return;
808 } else if (*input_line_pointer == '\n') {
809 as_bad("New line in title");
810 demand_empty_rest_of_line();
811 return;
812 } else {
813 input_line_pointer++;
814 }
815 }
816 } else {
817 as_bad("expecting title in quotes");
818 }
819
820 return;
821 } /* listing_title() */
822
823
824
825 void
826 listing_source_line(line)
827 unsigned int line;
828 {
829 new_frag();
830 listing_tail->hll_line = line;
831 new_frag();
832 return;
833 } /* lising_source_line() */
834
835 void
836 listing_source_file(file)
837 char *file;
838 {
839 listing_tail->hll_file = file_info(file);
840 }
841
842 #endif /* not NO_LISTING */
843
844 /* end of listing.c */
This page took 0.046946 seconds and 4 git commands to generate.