1*47405Sdonn /* input_scrub.c - layer between app and the rest of the world 2*47405Sdonn Copyright (C) 1987 Free Software Foundation, Inc. 3*47405Sdonn 4*47405Sdonn This file is part of GAS, the GNU Assembler. 5*47405Sdonn 6*47405Sdonn GAS is free software; you can redistribute it and/or modify 7*47405Sdonn it under the terms of the GNU General Public License as published by 8*47405Sdonn the Free Software Foundation; either version 1, or (at your option) 9*47405Sdonn any later version. 10*47405Sdonn 11*47405Sdonn GAS is distributed in the hope that it will be useful, 12*47405Sdonn but WITHOUT ANY WARRANTY; without even the implied warranty of 13*47405Sdonn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*47405Sdonn GNU General Public License for more details. 15*47405Sdonn 16*47405Sdonn You should have received a copy of the GNU General Public License 17*47405Sdonn along with GAS; see the file COPYING. If not, write to 18*47405Sdonn the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 19*47405Sdonn 20*47405Sdonn #include "as.h" 21*47405Sdonn #include "read.h" 22*47405Sdonn #include "input-file.h" 23*47405Sdonn 24*47405Sdonn /* 25*47405Sdonn * O/S independent module to supply buffers of sanitised source code 26*47405Sdonn * to rest of assembler. We get raw input data of some length. 27*47405Sdonn * Also looks after line numbers, for e.g. error messages. 28*47405Sdonn * This module used to do the sanitising, but now a pre-processor program 29*47405Sdonn * (app) does that job so this module is degenerate. 30*47405Sdonn * Now input is pre-sanitised, so we only worry about finding the 31*47405Sdonn * last partial line. A buffer of full lines is returned to caller. 32*47405Sdonn * The last partial line begins the next buffer we build and return to caller. 33*47405Sdonn * The buffer returned to caller is preceeded by BEFORE_STRING and followed 34*47405Sdonn * by AFTER_STRING. The last character before AFTER_STRING is a newline. 35*47405Sdonn */ 36*47405Sdonn 37*47405Sdonn /* 38*47405Sdonn * We expect the following sanitation has already been done. 39*47405Sdonn * 40*47405Sdonn * No comments, reduce a comment to a space. 41*47405Sdonn * Reduce a tab to a space unless it is 1st char of line. 42*47405Sdonn * All multiple tabs and spaces collapsed into 1 char. Tab only 43*47405Sdonn * legal if 1st char of line. 44*47405Sdonn * # line file statements converted to .line x;.file y; statements. 45*47405Sdonn * Escaped newlines at end of line: remove them but add as many newlines 46*47405Sdonn * to end of statement as you removed in the middle, to synch line numbers. 47*47405Sdonn */ 48*47405Sdonn 49*47405Sdonn #define BEFORE_STRING ("\n") 50*47405Sdonn #define AFTER_STRING ("\0") /* bcopy of 0 chars might choke. */ 51*47405Sdonn #define BEFORE_SIZE (1) 52*47405Sdonn #define AFTER_SIZE (1) 53*47405Sdonn 54*47405Sdonn static char * buffer_start; /* -> 1st char of full buffer area. */ 55*47405Sdonn static char * partial_where; /* -> after last full line in buffer. */ 56*47405Sdonn static int partial_size; /* >=0. Number of chars in partial line in buffer. */ 57*47405Sdonn static char save_source [AFTER_SIZE]; 58*47405Sdonn /* Because we need AFTER_STRING just after last */ 59*47405Sdonn /* full line, it clobbers 1st part of partial */ 60*47405Sdonn /* line. So we preserve 1st part of partial */ 61*47405Sdonn /* line here. */ 62*47405Sdonn static int buffer_length; /* What is the largest size buffer that */ 63*47405Sdonn /* input_file_give_next_buffer() could */ 64*47405Sdonn /* return to us? */ 65*47405Sdonn 66*47405Sdonn static void as_1_char (); 67*47405Sdonn 68*47405Sdonn /* 69*47405Sdonn We never have more than one source file open at once. 70*47405Sdonn We may, however, read more than 1 source file in an assembly. 71*47405Sdonn NULL means we have no file open right now. 72*47405Sdonn */ 73*47405Sdonn 74*47405Sdonn 75*47405Sdonn /* 76*47405Sdonn We must track the physical file and line number for error messages. 77*47405Sdonn We also track a "logical" file and line number corresponding to (C?) 78*47405Sdonn compiler source line numbers. 79*47405Sdonn Whenever we open a file we must fill in physical_input_file. So if it is NULL 80*47405Sdonn we have not opened any files yet. 81*47405Sdonn */ 82*47405Sdonn 83*47405Sdonn static 84*47405Sdonn char * physical_input_file, 85*47405Sdonn * logical_input_file; 86*47405Sdonn 87*47405Sdonn 88*47405Sdonn 89*47405Sdonn typedef unsigned int line_numberT; /* 1-origin line number in a source file. */ 90*47405Sdonn /* A line ends in '\n' or eof. */ 91*47405Sdonn 92*47405Sdonn static 93*47405Sdonn line_numberT physical_input_line, 94*47405Sdonn logical_input_line; 95*47405Sdonn 96*47405Sdonn void 97*47405Sdonn input_scrub_begin () 98*47405Sdonn { 99*47405Sdonn know( strlen(BEFORE_STRING) == BEFORE_SIZE ); 100*47405Sdonn know( strlen( AFTER_STRING) == AFTER_SIZE ); 101*47405Sdonn 102*47405Sdonn input_file_begin (); 103*47405Sdonn 104*47405Sdonn buffer_length = input_file_buffer_size (); 105*47405Sdonn 106*47405Sdonn buffer_start = xmalloc ((long)(BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE)); 107*47405Sdonn bcopy (BEFORE_STRING, buffer_start, (int)BEFORE_SIZE); 108*47405Sdonn 109*47405Sdonn /* Line number things. */ 110*47405Sdonn logical_input_line = 0; 111*47405Sdonn logical_input_file = (char *)NULL; 112*47405Sdonn physical_input_file = NULL; /* No file read yet. */ 113*47405Sdonn do_scrub_begin(); 114*47405Sdonn } 115*47405Sdonn 116*47405Sdonn void 117*47405Sdonn input_scrub_end () 118*47405Sdonn { 119*47405Sdonn input_file_end (); 120*47405Sdonn } 121*47405Sdonn 122*47405Sdonn char * /* Return start of caller's part of buffer. */ 123*47405Sdonn input_scrub_new_file (filename) 124*47405Sdonn char * filename; 125*47405Sdonn { 126*47405Sdonn input_file_open (filename, !flagseen['f']); 127*47405Sdonn physical_input_file = filename[0] ? filename : "{standard input}"; 128*47405Sdonn physical_input_line = 0; 129*47405Sdonn 130*47405Sdonn partial_size = 0; 131*47405Sdonn return (buffer_start + BEFORE_SIZE); 132*47405Sdonn } 133*47405Sdonn 134*47405Sdonn char * 135*47405Sdonn input_scrub_next_buffer (bufp) 136*47405Sdonn char **bufp; 137*47405Sdonn { 138*47405Sdonn register char * limit; /* -> just after last char of buffer. */ 139*47405Sdonn 140*47405Sdonn #ifdef DONTDEF 141*47405Sdonn if(preprocess) { 142*47405Sdonn if(save_buffer) { 143*47405Sdonn *bufp = save_buffer; 144*47405Sdonn save_buffer = 0; 145*47405Sdonn } 146*47405Sdonn limit = input_file_give_next_buffer(buffer_start+BEFORE_SIZE); 147*47405Sdonn if (!limit) { 148*47405Sdonn partial_where = 0; 149*47405Sdonn if(partial_size) 150*47405Sdonn as_warn("Partial line at end of file ignored"); 151*47405Sdonn return partial_where; 152*47405Sdonn } 153*47405Sdonn 154*47405Sdonn if(partial_size) 155*47405Sdonn bcopy(save_source, partial_where,(int)AFTER_SIZE); 156*47405Sdonn do_scrub(partial_where,partial_size,buffer_start+BEFORE_SIZE,limit-(buffer_start+BEFORE_SIZE),&out_string,&out_length); 157*47405Sdonn limit=out_string + out_length; 158*47405Sdonn for(p=limit;*--p!='\n';) 159*47405Sdonn ; 160*47405Sdonn p++; 161*47405Sdonn if(p<=buffer_start+BEFORE_SIZE) 162*47405Sdonn as_fatal("Source line too long. Please change file '%s' and re-make the assembler.",__FILE__); 163*47405Sdonn 164*47405Sdonn partial_where = p; 165*47405Sdonn partial_size = limit-p; 166*47405Sdonn bcopy(partial_where, save_source,(int)AFTER_SIZE); 167*47405Sdonn bcopy(AFTER_STRING, partial_where, (int)AFTER_SIZE); 168*47405Sdonn 169*47405Sdonn save_buffer = *bufp; 170*47405Sdonn *bufp = out_string; 171*47405Sdonn 172*47405Sdonn return partial_where; 173*47405Sdonn } 174*47405Sdonn 175*47405Sdonn /* We're not preprocessing. Do the right thing */ 176*47405Sdonn #endif 177*47405Sdonn if (partial_size) 178*47405Sdonn { 179*47405Sdonn bcopy (partial_where, buffer_start + BEFORE_SIZE, (int)partial_size); 180*47405Sdonn bcopy (save_source, buffer_start + BEFORE_SIZE, (int)AFTER_SIZE); 181*47405Sdonn } 182*47405Sdonn limit = input_file_give_next_buffer (buffer_start + BEFORE_SIZE + partial_size); 183*47405Sdonn if (limit) 184*47405Sdonn { 185*47405Sdonn register char * p; /* Find last newline. */ 186*47405Sdonn 187*47405Sdonn for (p = limit; * -- p != '\n'; ) 188*47405Sdonn { 189*47405Sdonn } 190*47405Sdonn ++ p; 191*47405Sdonn if (p <= buffer_start + BEFORE_SIZE) 192*47405Sdonn { 193*47405Sdonn as_fatal ("Source line too long. Please change file %s then rebuild assembler.", __FILE__); 194*47405Sdonn } 195*47405Sdonn partial_where = p; 196*47405Sdonn partial_size = limit - p; 197*47405Sdonn bcopy (partial_where, save_source, (int)AFTER_SIZE); 198*47405Sdonn bcopy (AFTER_STRING, partial_where, (int)AFTER_SIZE); 199*47405Sdonn } 200*47405Sdonn else 201*47405Sdonn { 202*47405Sdonn partial_where = 0; 203*47405Sdonn if (partial_size > 0) 204*47405Sdonn { 205*47405Sdonn as_warn( "Partial line at end of file ignored" ); 206*47405Sdonn } 207*47405Sdonn } 208*47405Sdonn return (partial_where); 209*47405Sdonn } 210*47405Sdonn 211*47405Sdonn /* 212*47405Sdonn * The remaining part of this file deals with line numbers, error 213*47405Sdonn * messages and so on. 214*47405Sdonn */ 215*47405Sdonn 216*47405Sdonn 217*47405Sdonn int 218*47405Sdonn seen_at_least_1_file () /* TRUE if we opened any file. */ 219*47405Sdonn { 220*47405Sdonn return (physical_input_file != NULL); 221*47405Sdonn } 222*47405Sdonn 223*47405Sdonn void 224*47405Sdonn bump_line_counters () 225*47405Sdonn { 226*47405Sdonn ++ physical_input_line; 227*47405Sdonn ++ logical_input_line; 228*47405Sdonn } 229*47405Sdonn 230*47405Sdonn /* 231*47405Sdonn * new_logical_line() 232*47405Sdonn * 233*47405Sdonn * Tells us what the new logical line number and file are. 234*47405Sdonn * If the line_number is <0, we don't change the current logical line number. 235*47405Sdonn * If the fname is NULL, we don't change the current logical file name. 236*47405Sdonn */ 237*47405Sdonn void 238*47405Sdonn new_logical_line (fname, line_number) 239*47405Sdonn char * fname; /* DON'T destroy it! We point to it! */ 240*47405Sdonn int line_number; 241*47405Sdonn { 242*47405Sdonn if ( fname ) 243*47405Sdonn { 244*47405Sdonn logical_input_file = fname; 245*47405Sdonn } 246*47405Sdonn if ( line_number >= 0 ) 247*47405Sdonn { 248*47405Sdonn logical_input_line = line_number; 249*47405Sdonn } 250*47405Sdonn } 251*47405Sdonn 252*47405Sdonn /* 253*47405Sdonn * a s _ w h e r e ( ) 254*47405Sdonn * 255*47405Sdonn * Write a line to stderr locating where we are in reading 256*47405Sdonn * input source files. 257*47405Sdonn * As a sop to the debugger of AS, pretty-print the offending line. 258*47405Sdonn */ 259*47405Sdonn void 260*47405Sdonn as_where() 261*47405Sdonn { 262*47405Sdonn char *p; 263*47405Sdonn line_numberT line; 264*47405Sdonn 265*47405Sdonn if (physical_input_file) 266*47405Sdonn { /* we tried to read SOME source */ 267*47405Sdonn if (input_file_is_open()) 268*47405Sdonn { /* we can still read lines from source */ 269*47405Sdonn #ifdef DONTDEF 270*47405Sdonn fprintf (stderr," @ physical line %ld., file \"%s\"", 271*47405Sdonn (long) physical_input_line, physical_input_file); 272*47405Sdonn fprintf (stderr," @ logical line %ld., file \"%s\"\n", 273*47405Sdonn (long) logical_input_line, logical_input_file); 274*47405Sdonn (void)putc(' ', stderr); 275*47405Sdonn as_howmuch (stderr); 276*47405Sdonn (void)putc('\n', stderr); 277*47405Sdonn #else 278*47405Sdonn p = logical_input_file ? logical_input_file : physical_input_file; 279*47405Sdonn line = logical_input_line ? logical_input_line : physical_input_line; 280*47405Sdonn fprintf(stderr,"%s:%u:", p, line); 281*47405Sdonn #endif 282*47405Sdonn } 283*47405Sdonn else 284*47405Sdonn { 285*47405Sdonn #ifdef DONTDEF 286*47405Sdonn fprintf (stderr," After reading source.\n"); 287*47405Sdonn #else 288*47405Sdonn p = logical_input_file ? logical_input_file : physical_input_file; 289*47405Sdonn line = logical_input_line ? logical_input_line : physical_input_line; 290*47405Sdonn fprintf (stderr,"%s:unknown:", p); 291*47405Sdonn #endif 292*47405Sdonn } 293*47405Sdonn } 294*47405Sdonn else 295*47405Sdonn { 296*47405Sdonn #ifdef DONTDEF 297*47405Sdonn fprintf (stderr," Before reading source.\n"); 298*47405Sdonn #else 299*47405Sdonn #endif 300*47405Sdonn } 301*47405Sdonn } 302*47405Sdonn 303*47405Sdonn 304*47405Sdonn 305*47405Sdonn 306*47405Sdonn /* 307*47405Sdonn * a s _ h o w m u c h ( ) 308*47405Sdonn * 309*47405Sdonn * Output to given stream how much of line we have scanned so far. 310*47405Sdonn * Assumes we have scanned up to and including input_line_pointer. 311*47405Sdonn * No free '\n' at end of line. 312*47405Sdonn */ 313*47405Sdonn void 314*47405Sdonn as_howmuch (stream) 315*47405Sdonn FILE * stream; /* Opened for write please. */ 316*47405Sdonn { 317*47405Sdonn register char * p; /* Scan input line. */ 318*47405Sdonn /* register char c; JF unused */ 319*47405Sdonn 320*47405Sdonn for (p = input_line_pointer - 1; * p != '\n'; --p) 321*47405Sdonn { 322*47405Sdonn } 323*47405Sdonn ++ p; /* p -> 1st char of line. */ 324*47405Sdonn for (; p <= input_line_pointer; p++) 325*47405Sdonn { 326*47405Sdonn /* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */ 327*47405Sdonn /* c = *p & 0xFF; JF unused */ 328*47405Sdonn as_1_char (*p, stream); 329*47405Sdonn } 330*47405Sdonn } 331*47405Sdonn 332*47405Sdonn static void 333*47405Sdonn as_1_char (c,stream) 334*47405Sdonn unsigned char c; 335*47405Sdonn FILE * stream; 336*47405Sdonn { 337*47405Sdonn if ( c > 127 ) 338*47405Sdonn { 339*47405Sdonn (void)putc( '%', stream); 340*47405Sdonn c -= 128; 341*47405Sdonn } 342*47405Sdonn if ( c < 32 ) 343*47405Sdonn { 344*47405Sdonn (void)putc( '^', stream); 345*47405Sdonn c += '@'; 346*47405Sdonn } 347*47405Sdonn (void)putc( c, stream); 348*47405Sdonn } 349*47405Sdonn 350*47405Sdonn /* end: input_scrub.c */ 351