1*47443Sdonn /* @(#)input-scrub.c 6.2 (Berkeley) 03/15/91 2*47443Sdonn 3*47443Sdonn Modified for Berkeley Unix by Donn Seeley, donn@okeeffe.berkeley.edu */ 4*47443Sdonn 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 } 306*47443Sdonn 307*47443Sdonn /* 308*47443Sdonn * linestab() -- generate a line number stab for the current source line. 309*47443Sdonn * If the filename has changed, generate a file stab first. 310*47443Sdonn */ 311*47443Sdonn void 312*47443Sdonn linestab() 313*47443Sdonn { 314*47443Sdonn static char *saved_file; 315*47443Sdonn static int saved_len; 316*47443Sdonn static line_numberT saved_line; 317*47443Sdonn char *file; 318*47443Sdonn line_numberT line; 319*47443Sdonn int len; 32047405Sdonn 321*47443Sdonn if (!flagseen['g'] || 322*47443Sdonn !physical_input_file || 323*47443Sdonn !input_file_is_open() || 324*47443Sdonn now_seg != SEG_TEXT) 325*47443Sdonn return; 32647405Sdonn 327*47443Sdonn file = logical_input_file ? logical_input_file : physical_input_file; 328*47443Sdonn line = logical_input_line ? logical_input_line : physical_input_line; 32947405Sdonn 330*47443Sdonn if (saved_file == 0 || strcmp(file, saved_file) != 0) 331*47443Sdonn { 332*47443Sdonn stabs(file); 333*47443Sdonn len = strlen(file) + 1; 334*47443Sdonn if (len > saved_len) 335*47443Sdonn { 336*47443Sdonn if (saved_file == 0) 337*47443Sdonn saved_file = xmalloc(len); 338*47443Sdonn else 339*47443Sdonn saved_file = xrealloc(saved_file, len); 340*47443Sdonn memcpy(saved_file, file, len); 341*47443Sdonn saved_len = len; 342*47443Sdonn } 343*47443Sdonn else 344*47443Sdonn strcpy(saved_file, file); 345*47443Sdonn saved_line = 0; 346*47443Sdonn } 347*47443Sdonn 348*47443Sdonn if (saved_line == 0 || line != saved_line) 349*47443Sdonn { 350*47443Sdonn stabd(line); 351*47443Sdonn saved_line = line; 352*47443Sdonn } 353*47443Sdonn } 35447405Sdonn 35547405Sdonn /* 35647405Sdonn * a s _ h o w m u c h ( ) 35747405Sdonn * 35847405Sdonn * Output to given stream how much of line we have scanned so far. 35947405Sdonn * Assumes we have scanned up to and including input_line_pointer. 36047405Sdonn * No free '\n' at end of line. 36147405Sdonn */ 36247405Sdonn void 36347405Sdonn as_howmuch (stream) 36447405Sdonn FILE * stream; /* Opened for write please. */ 36547405Sdonn { 36647405Sdonn register char * p; /* Scan input line. */ 36747405Sdonn /* register char c; JF unused */ 36847405Sdonn 36947405Sdonn for (p = input_line_pointer - 1; * p != '\n'; --p) 37047405Sdonn { 37147405Sdonn } 37247405Sdonn ++ p; /* p -> 1st char of line. */ 37347405Sdonn for (; p <= input_line_pointer; p++) 37447405Sdonn { 37547405Sdonn /* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */ 37647405Sdonn /* c = *p & 0xFF; JF unused */ 37747405Sdonn as_1_char (*p, stream); 37847405Sdonn } 37947405Sdonn } 38047405Sdonn 38147405Sdonn static void 38247405Sdonn as_1_char (c,stream) 38347405Sdonn unsigned char c; 38447405Sdonn FILE * stream; 38547405Sdonn { 38647405Sdonn if ( c > 127 ) 38747405Sdonn { 38847405Sdonn (void)putc( '%', stream); 38947405Sdonn c -= 128; 39047405Sdonn } 39147405Sdonn if ( c < 32 ) 39247405Sdonn { 39347405Sdonn (void)putc( '^', stream); 39447405Sdonn c += '@'; 39547405Sdonn } 39647405Sdonn (void)putc( c, stream); 39747405Sdonn } 39847405Sdonn 39947405Sdonn /* end: input_scrub.c */ 400