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