1*47447Sdonn /* @(#)input-scrub.c 6.3 (Berkeley) 03/15/91 247443Sdonn 347443Sdonn Modified for Berkeley Unix by Donn Seeley, donn@okeeffe.berkeley.edu */ 447443Sdonn 547405Sdonn /* input_scrub.c - layer between app and the rest of the world 647405Sdonn Copyright (C) 1987 Free Software Foundation, Inc. 747405Sdonn 847405Sdonn This file is part of GAS, the GNU Assembler. 947405Sdonn 1047405Sdonn GAS is free software; you can redistribute it and/or modify 1147405Sdonn it under the terms of the GNU General Public License as published by 1247405Sdonn the Free Software Foundation; either version 1, or (at your option) 1347405Sdonn any later version. 1447405Sdonn 1547405Sdonn GAS is distributed in the hope that it will be useful, 1647405Sdonn but WITHOUT ANY WARRANTY; without even the implied warranty of 1747405Sdonn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1847405Sdonn GNU General Public License for more details. 1947405Sdonn 2047405Sdonn You should have received a copy of the GNU General Public License 2147405Sdonn along with GAS; see the file COPYING. If not, write to 2247405Sdonn the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 2347405Sdonn 2447405Sdonn #include "as.h" 2547405Sdonn #include "read.h" 2647405Sdonn #include "input-file.h" 2747405Sdonn 2847405Sdonn /* 2947405Sdonn * O/S independent module to supply buffers of sanitised source code 3047405Sdonn * to rest of assembler. We get raw input data of some length. 3147405Sdonn * Also looks after line numbers, for e.g. error messages. 3247405Sdonn * This module used to do the sanitising, but now a pre-processor program 3347405Sdonn * (app) does that job so this module is degenerate. 3447405Sdonn * Now input is pre-sanitised, so we only worry about finding the 3547405Sdonn * last partial line. A buffer of full lines is returned to caller. 3647405Sdonn * The last partial line begins the next buffer we build and return to caller. 3747405Sdonn * The buffer returned to caller is preceeded by BEFORE_STRING and followed 3847405Sdonn * by AFTER_STRING. The last character before AFTER_STRING is a newline. 3947405Sdonn */ 4047405Sdonn 4147405Sdonn /* 4247405Sdonn * We expect the following sanitation has already been done. 4347405Sdonn * 4447405Sdonn * No comments, reduce a comment to a space. 4547405Sdonn * Reduce a tab to a space unless it is 1st char of line. 4647405Sdonn * All multiple tabs and spaces collapsed into 1 char. Tab only 4747405Sdonn * legal if 1st char of line. 4847405Sdonn * # line file statements converted to .line x;.file y; statements. 4947405Sdonn * Escaped newlines at end of line: remove them but add as many newlines 5047405Sdonn * to end of statement as you removed in the middle, to synch line numbers. 5147405Sdonn */ 5247405Sdonn 5347405Sdonn #define BEFORE_STRING ("\n") 5447405Sdonn #define AFTER_STRING ("\0") /* bcopy of 0 chars might choke. */ 5547405Sdonn #define BEFORE_SIZE (1) 5647405Sdonn #define AFTER_SIZE (1) 5747405Sdonn 5847405Sdonn static char * buffer_start; /* -> 1st char of full buffer area. */ 5947405Sdonn static char * partial_where; /* -> after last full line in buffer. */ 6047405Sdonn static int partial_size; /* >=0. Number of chars in partial line in buffer. */ 6147405Sdonn static char save_source [AFTER_SIZE]; 6247405Sdonn /* Because we need AFTER_STRING just after last */ 6347405Sdonn /* full line, it clobbers 1st part of partial */ 6447405Sdonn /* line. So we preserve 1st part of partial */ 6547405Sdonn /* line here. */ 6647405Sdonn static int buffer_length; /* What is the largest size buffer that */ 6747405Sdonn /* input_file_give_next_buffer() could */ 6847405Sdonn /* return to us? */ 6947405Sdonn 7047405Sdonn static void as_1_char (); 7147405Sdonn 7247405Sdonn /* 7347405Sdonn We never have more than one source file open at once. 7447405Sdonn We may, however, read more than 1 source file in an assembly. 7547405Sdonn NULL means we have no file open right now. 7647405Sdonn */ 7747405Sdonn 7847405Sdonn 7947405Sdonn /* 8047405Sdonn We must track the physical file and line number for error messages. 8147405Sdonn We also track a "logical" file and line number corresponding to (C?) 8247405Sdonn compiler source line numbers. 8347405Sdonn Whenever we open a file we must fill in physical_input_file. So if it is NULL 8447405Sdonn we have not opened any files yet. 8547405Sdonn */ 8647405Sdonn 8747405Sdonn static 8847405Sdonn char * physical_input_file, 8947405Sdonn * logical_input_file; 9047405Sdonn 9147405Sdonn 9247405Sdonn 9347405Sdonn typedef unsigned int line_numberT; /* 1-origin line number in a source file. */ 9447405Sdonn /* A line ends in '\n' or eof. */ 9547405Sdonn 9647405Sdonn static 9747405Sdonn line_numberT physical_input_line, 9847405Sdonn logical_input_line; 9947405Sdonn 10047405Sdonn void 10147405Sdonn input_scrub_begin () 10247405Sdonn { 10347405Sdonn know( strlen(BEFORE_STRING) == BEFORE_SIZE ); 10447405Sdonn know( strlen( AFTER_STRING) == AFTER_SIZE ); 10547405Sdonn 10647405Sdonn input_file_begin (); 10747405Sdonn 10847405Sdonn buffer_length = input_file_buffer_size (); 10947405Sdonn 11047405Sdonn buffer_start = xmalloc ((long)(BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE)); 11147405Sdonn bcopy (BEFORE_STRING, buffer_start, (int)BEFORE_SIZE); 11247405Sdonn 11347405Sdonn /* Line number things. */ 11447405Sdonn logical_input_line = 0; 11547405Sdonn logical_input_file = (char *)NULL; 11647405Sdonn physical_input_file = NULL; /* No file read yet. */ 11747405Sdonn do_scrub_begin(); 11847405Sdonn } 11947405Sdonn 12047405Sdonn void 12147405Sdonn input_scrub_end () 12247405Sdonn { 12347405Sdonn input_file_end (); 12447405Sdonn } 12547405Sdonn 12647405Sdonn char * /* Return start of caller's part of buffer. */ 12747405Sdonn input_scrub_new_file (filename) 12847405Sdonn char * filename; 12947405Sdonn { 13047405Sdonn input_file_open (filename, !flagseen['f']); 13147405Sdonn physical_input_file = filename[0] ? filename : "{standard input}"; 13247405Sdonn physical_input_line = 0; 13347405Sdonn 13447405Sdonn partial_size = 0; 13547405Sdonn return (buffer_start + BEFORE_SIZE); 13647405Sdonn } 13747405Sdonn 13847405Sdonn char * 13947405Sdonn input_scrub_next_buffer (bufp) 14047405Sdonn char **bufp; 14147405Sdonn { 14247405Sdonn register char * limit; /* -> just after last char of buffer. */ 14347405Sdonn 14447405Sdonn #ifdef DONTDEF 14547405Sdonn if(preprocess) { 14647405Sdonn if(save_buffer) { 14747405Sdonn *bufp = save_buffer; 14847405Sdonn save_buffer = 0; 14947405Sdonn } 15047405Sdonn limit = input_file_give_next_buffer(buffer_start+BEFORE_SIZE); 15147405Sdonn if (!limit) { 15247405Sdonn partial_where = 0; 15347405Sdonn if(partial_size) 15447405Sdonn as_warn("Partial line at end of file ignored"); 15547405Sdonn return partial_where; 15647405Sdonn } 15747405Sdonn 15847405Sdonn if(partial_size) 15947405Sdonn bcopy(save_source, partial_where,(int)AFTER_SIZE); 16047405Sdonn do_scrub(partial_where,partial_size,buffer_start+BEFORE_SIZE,limit-(buffer_start+BEFORE_SIZE),&out_string,&out_length); 16147405Sdonn limit=out_string + out_length; 16247405Sdonn for(p=limit;*--p!='\n';) 16347405Sdonn ; 16447405Sdonn p++; 16547405Sdonn if(p<=buffer_start+BEFORE_SIZE) 16647405Sdonn as_fatal("Source line too long. Please change file '%s' and re-make the assembler.",__FILE__); 16747405Sdonn 16847405Sdonn partial_where = p; 16947405Sdonn partial_size = limit-p; 17047405Sdonn bcopy(partial_where, save_source,(int)AFTER_SIZE); 17147405Sdonn bcopy(AFTER_STRING, partial_where, (int)AFTER_SIZE); 17247405Sdonn 17347405Sdonn save_buffer = *bufp; 17447405Sdonn *bufp = out_string; 17547405Sdonn 17647405Sdonn return partial_where; 17747405Sdonn } 17847405Sdonn 17947405Sdonn /* We're not preprocessing. Do the right thing */ 18047405Sdonn #endif 18147405Sdonn if (partial_size) 18247405Sdonn { 18347405Sdonn bcopy (partial_where, buffer_start + BEFORE_SIZE, (int)partial_size); 18447405Sdonn bcopy (save_source, buffer_start + BEFORE_SIZE, (int)AFTER_SIZE); 18547405Sdonn } 18647405Sdonn limit = input_file_give_next_buffer (buffer_start + BEFORE_SIZE + partial_size); 18747405Sdonn if (limit) 18847405Sdonn { 18947405Sdonn register char * p; /* Find last newline. */ 19047405Sdonn 19147405Sdonn for (p = limit; * -- p != '\n'; ) 19247405Sdonn { 19347405Sdonn } 19447405Sdonn ++ p; 19547405Sdonn if (p <= buffer_start + BEFORE_SIZE) 19647405Sdonn { 19747405Sdonn as_fatal ("Source line too long. Please change file %s then rebuild assembler.", __FILE__); 19847405Sdonn } 19947405Sdonn partial_where = p; 20047405Sdonn partial_size = limit - p; 20147405Sdonn bcopy (partial_where, save_source, (int)AFTER_SIZE); 20247405Sdonn bcopy (AFTER_STRING, partial_where, (int)AFTER_SIZE); 20347405Sdonn } 20447405Sdonn else 20547405Sdonn { 20647405Sdonn partial_where = 0; 20747405Sdonn if (partial_size > 0) 20847405Sdonn { 20947405Sdonn as_warn( "Partial line at end of file ignored" ); 21047405Sdonn } 21147405Sdonn } 21247405Sdonn return (partial_where); 21347405Sdonn } 21447405Sdonn 21547405Sdonn /* 21647405Sdonn * The remaining part of this file deals with line numbers, error 21747405Sdonn * messages and so on. 21847405Sdonn */ 21947405Sdonn 22047405Sdonn 22147405Sdonn int 22247405Sdonn seen_at_least_1_file () /* TRUE if we opened any file. */ 22347405Sdonn { 22447405Sdonn return (physical_input_file != NULL); 22547405Sdonn } 22647405Sdonn 22747405Sdonn void 22847405Sdonn bump_line_counters () 22947405Sdonn { 23047405Sdonn ++ physical_input_line; 23147405Sdonn ++ logical_input_line; 23247405Sdonn } 23347405Sdonn 23447405Sdonn /* 23547405Sdonn * new_logical_line() 23647405Sdonn * 23747405Sdonn * Tells us what the new logical line number and file are. 23847405Sdonn * If the line_number is <0, we don't change the current logical line number. 23947405Sdonn * If the fname is NULL, we don't change the current logical file name. 24047405Sdonn */ 24147405Sdonn void 24247405Sdonn new_logical_line (fname, line_number) 24347405Sdonn char * fname; /* DON'T destroy it! We point to it! */ 24447405Sdonn int line_number; 24547405Sdonn { 24647405Sdonn if ( fname ) 24747405Sdonn { 24847405Sdonn logical_input_file = fname; 24947405Sdonn } 25047405Sdonn if ( line_number >= 0 ) 25147405Sdonn { 25247405Sdonn logical_input_line = line_number; 25347405Sdonn } 25447405Sdonn } 25547405Sdonn 25647405Sdonn /* 25747405Sdonn * a s _ w h e r e ( ) 25847405Sdonn * 25947405Sdonn * Write a line to stderr locating where we are in reading 26047405Sdonn * input source files. 26147405Sdonn * As a sop to the debugger of AS, pretty-print the offending line. 26247405Sdonn */ 26347405Sdonn void 26447405Sdonn as_where() 26547405Sdonn { 26647405Sdonn char *p; 26747405Sdonn line_numberT line; 26847405Sdonn 26947405Sdonn if (physical_input_file) 27047405Sdonn { /* we tried to read SOME source */ 27147405Sdonn if (input_file_is_open()) 27247405Sdonn { /* we can still read lines from source */ 27347405Sdonn #ifdef DONTDEF 27447405Sdonn fprintf (stderr," @ physical line %ld., file \"%s\"", 27547405Sdonn (long) physical_input_line, physical_input_file); 27647405Sdonn fprintf (stderr," @ logical line %ld., file \"%s\"\n", 27747405Sdonn (long) logical_input_line, logical_input_file); 27847405Sdonn (void)putc(' ', stderr); 27947405Sdonn as_howmuch (stderr); 28047405Sdonn (void)putc('\n', stderr); 28147405Sdonn #else 28247405Sdonn p = logical_input_file ? logical_input_file : physical_input_file; 28347405Sdonn line = logical_input_line ? logical_input_line : physical_input_line; 28447405Sdonn fprintf(stderr,"%s:%u:", p, line); 28547405Sdonn #endif 28647405Sdonn } 28747405Sdonn else 28847405Sdonn { 28947405Sdonn #ifdef DONTDEF 29047405Sdonn fprintf (stderr," After reading source.\n"); 29147405Sdonn #else 29247405Sdonn p = logical_input_file ? logical_input_file : physical_input_file; 29347405Sdonn line = logical_input_line ? logical_input_line : physical_input_line; 29447405Sdonn fprintf (stderr,"%s:unknown:", p); 29547405Sdonn #endif 29647405Sdonn } 29747405Sdonn } 29847405Sdonn else 29947405Sdonn { 30047405Sdonn #ifdef DONTDEF 30147405Sdonn fprintf (stderr," Before reading source.\n"); 30247405Sdonn #else 30347405Sdonn #endif 30447405Sdonn } 30547405Sdonn } 30647443Sdonn 30747443Sdonn /* 308*47447Sdonn * Support for source file debugging. These functions handle 309*47447Sdonn * logical lines and logical files. 31047443Sdonn */ 311*47447Sdonn static char *saved_file; 312*47447Sdonn static int saved_len; 313*47447Sdonn static line_numberT saved_line; 314*47447Sdonn 31547443Sdonn void 316*47447Sdonn filestab() 31747443Sdonn { 31847443Sdonn char *file; 31947443Sdonn int len; 32047405Sdonn 321*47447Sdonn if (!physical_input_file || 322*47447Sdonn !input_file_is_open()) 32347443Sdonn return; 32447405Sdonn 32547443Sdonn file = logical_input_file ? logical_input_file : physical_input_file; 32647405Sdonn 32747443Sdonn if (saved_file == 0 || strcmp(file, saved_file) != 0) 32847443Sdonn { 32947443Sdonn stabs(file); 33047443Sdonn len = strlen(file) + 1; 33147443Sdonn if (len > saved_len) 33247443Sdonn { 33347443Sdonn if (saved_file == 0) 33447443Sdonn saved_file = xmalloc(len); 33547443Sdonn else 33647443Sdonn saved_file = xrealloc(saved_file, len); 33747443Sdonn memcpy(saved_file, file, len); 33847443Sdonn saved_len = len; 33947443Sdonn } 34047443Sdonn else 34147443Sdonn strcpy(saved_file, file); 34247443Sdonn saved_line = 0; 34347443Sdonn } 344*47447Sdonn } 34547443Sdonn 346*47447Sdonn void 347*47447Sdonn funcstab(func) 348*47447Sdonn char *func; 349*47447Sdonn { 350*47447Sdonn if (now_seg != SEG_TEXT) 351*47447Sdonn return; 352*47447Sdonn 353*47447Sdonn filestab(); 354*47447Sdonn stabf(func); 355*47447Sdonn } 356*47447Sdonn 357*47447Sdonn void 358*47447Sdonn linestab() 359*47447Sdonn { 360*47447Sdonn line_numberT line; 361*47447Sdonn 362*47447Sdonn if (now_seg != SEG_TEXT) 363*47447Sdonn return; 364*47447Sdonn 365*47447Sdonn filestab(); 366*47447Sdonn 367*47447Sdonn line = logical_input_line ? logical_input_line : physical_input_line; 368*47447Sdonn 36947443Sdonn if (saved_line == 0 || line != saved_line) 37047443Sdonn { 37147443Sdonn stabd(line); 37247443Sdonn saved_line = line; 37347443Sdonn } 37447443Sdonn } 37547405Sdonn 37647405Sdonn /* 37747405Sdonn * a s _ h o w m u c h ( ) 37847405Sdonn * 37947405Sdonn * Output to given stream how much of line we have scanned so far. 38047405Sdonn * Assumes we have scanned up to and including input_line_pointer. 38147405Sdonn * No free '\n' at end of line. 38247405Sdonn */ 38347405Sdonn void 38447405Sdonn as_howmuch (stream) 38547405Sdonn FILE * stream; /* Opened for write please. */ 38647405Sdonn { 38747405Sdonn register char * p; /* Scan input line. */ 38847405Sdonn /* register char c; JF unused */ 38947405Sdonn 39047405Sdonn for (p = input_line_pointer - 1; * p != '\n'; --p) 39147405Sdonn { 39247405Sdonn } 39347405Sdonn ++ p; /* p -> 1st char of line. */ 39447405Sdonn for (; p <= input_line_pointer; p++) 39547405Sdonn { 39647405Sdonn /* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */ 39747405Sdonn /* c = *p & 0xFF; JF unused */ 39847405Sdonn as_1_char (*p, stream); 39947405Sdonn } 40047405Sdonn } 40147405Sdonn 40247405Sdonn static void 40347405Sdonn as_1_char (c,stream) 40447405Sdonn unsigned char c; 40547405Sdonn FILE * stream; 40647405Sdonn { 40747405Sdonn if ( c > 127 ) 40847405Sdonn { 40947405Sdonn (void)putc( '%', stream); 41047405Sdonn c -= 128; 41147405Sdonn } 41247405Sdonn if ( c < 32 ) 41347405Sdonn { 41447405Sdonn (void)putc( '^', stream); 41547405Sdonn c += '@'; 41647405Sdonn } 41747405Sdonn (void)putc( c, stream); 41847405Sdonn } 41947405Sdonn 42047405Sdonn /* end: input_scrub.c */ 421