|
|
1.1 ! root 1: /* input_scrub.c - layer between app and the rest of the world ! 2: Copyright (C) 1987 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 1, 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: #include <stdlib.h> ! 21: #include <string.h> ! 22: #include <errno.h> ! 23: #include <libc.h> ! 24: #ifdef NeXT /* .include feature */ ! 25: #include <sys/file.h> ! 26: #include <sys/param.h> ! 27: #endif /* NeXT .include feature */ ! 28: #include "as.h" ! 29: #include "read.h" ! 30: #include "input-file.h" ! 31: #include "input-scrub.h" ! 32: #include "app.h" ! 33: #include "xmalloc.h" ! 34: #include "messages.h" ! 35: ! 36: /* ! 37: * O/S independent module to supply buffers of sanitised source code ! 38: * to rest of assembler. We get raw input data of some length. ! 39: * Also looks after line numbers, for e.g. error messages. ! 40: * This module used to do the sanitising, but now a pre-processor program ! 41: * (app) does that job so this module is degenerate. ! 42: * Now input is pre-sanitised, so we only worry about finding the ! 43: * last partial line. A buffer of full lines is returned to caller. ! 44: * The last partial line begins the next buffer we build and return to caller. ! 45: * The buffer returned to caller is preceeded by BEFORE_STRING and followed ! 46: * by AFTER_STRING. The last character before AFTER_STRING is a newline. ! 47: */ ! 48: ! 49: /* ! 50: * We expect the following sanitation has already been done. ! 51: * ! 52: * No comments, reduce a comment to a space. ! 53: * Reduce a tab to a space unless it is 1st char of line. ! 54: * All multiple tabs and spaces collapsed into 1 char. Tab only ! 55: * legal if 1st char of line. ! 56: * # line file statements converted to .line x;.file y; statements. ! 57: * Escaped newlines at end of line: remove them but add as many newlines ! 58: * to end of statement as you removed in the middle, to synch line numbers. ! 59: */ ! 60: ! 61: #define BEFORE_STRING ("\n") ! 62: #define AFTER_STRING ("\0") /* memcpy of 0 chars might choke. */ ! 63: #define BEFORE_SIZE (1) ! 64: #define AFTER_SIZE (1) /* includes the \0 */ ! 65: ! 66: static char * buffer_start; /* -> 1st char of full buffer area. */ ! 67: static char * partial_where; /* -> after last full line in buffer. */ ! 68: static int partial_size; /* >=0. Number of chars in partial line in buffer. */ ! 69: static char save_source [AFTER_SIZE]; ! 70: /* Because we need AFTER_STRING just after last */ ! 71: /* full line, it clobbers 1st part of partial */ ! 72: /* line. So we preserve 1st part of partial */ ! 73: /* line here. */ ! 74: static int buffer_length; /* What is the largest size buffer that */ ! 75: /* input_file_give_next_buffer() could */ ! 76: /* return to us? */ ! 77: ! 78: /* ! 79: We never have more than one source file open at once. ! 80: We may, however, read more than 1 source file in an assembly. ! 81: NULL means we have no file open right now. ! 82: */ ! 83: ! 84: ! 85: /* ! 86: We must track the physical file and line number for error messages. ! 87: We also track a "logical" file and line number corresponding to (C?) ! 88: compiler source line numbers. ! 89: Whenever we open a file we must fill in physical_input_file. So if it is NULL ! 90: we have not opened any files yet. ! 91: */ ! 92: ! 93: int doing_include = FALSE; /* TRUE when we are processing a .include */ ! 94: ! 95: char *physical_input_file = NULL; ! 96: char *logical_input_file = NULL; ! 97: ! 98: line_numberT physical_input_line = 0; ! 99: line_numberT logical_input_line = 0; ! 100: ! 101: ! 102: void ! 103: input_scrub_begin( ! 104: void) ! 105: { ! 106: know( strlen(BEFORE_STRING) == BEFORE_SIZE ); ! 107: know( strlen(AFTER_STRING) + 1 == AFTER_SIZE ); ! 108: ! 109: input_file_begin (); ! 110: ! 111: buffer_length = input_file_buffer_size (); ! 112: ! 113: buffer_start = xmalloc ((long)(BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE)); ! 114: memcpy(buffer_start, BEFORE_STRING, (int)BEFORE_SIZE); ! 115: ! 116: /* Line number things. */ ! 117: logical_input_line = 0; ! 118: logical_input_file = (char *)NULL; ! 119: physical_input_file = NULL; /* No file read yet. */ ! 120: do_scrub_begin(); ! 121: } ! 122: ! 123: void ! 124: input_scrub_end( ! 125: void) ! 126: { ! 127: input_file_end (); ! 128: } ! 129: ! 130: char * /* Return start of caller's part of buffer. */ ! 131: input_scrub_new_file( ! 132: char *filename) ! 133: { ! 134: input_file_open (filename, !flagseen['f']); ! 135: physical_input_file = filename[0] ? filename : "{standard input}"; ! 136: physical_input_line = 0; ! 137: ! 138: partial_size = 0; ! 139: return (buffer_start + BEFORE_SIZE); ! 140: } ! 141: ! 142: char * ! 143: input_scrub_next_buffer( ! 144: char **bufp) ! 145: { ! 146: register char * limit; /* -> just after last char of buffer. */ ! 147: ! 148: if (partial_size) ! 149: { ! 150: memcpy(buffer_start + BEFORE_SIZE, partial_where, (int)partial_size); ! 151: memcpy(buffer_start + BEFORE_SIZE, save_source, (int)AFTER_SIZE); ! 152: } ! 153: limit = input_file_give_next_buffer (buffer_start + BEFORE_SIZE + partial_size); ! 154: if (limit) ! 155: { ! 156: register char * p; /* Find last newline. */ ! 157: ! 158: for (p = limit; * -- p != '\n'; ) ! 159: { ! 160: } ! 161: ++ p; ! 162: if (p <= buffer_start + BEFORE_SIZE) ! 163: { ! 164: as_fatal ("Source line too long. Please change file %s then rebuild assembler.", __FILE__); ! 165: } ! 166: partial_where = p; ! 167: partial_size = limit - p; ! 168: memcpy(save_source, partial_where, (int)AFTER_SIZE); ! 169: memcpy(partial_where, AFTER_STRING, (int)AFTER_SIZE); ! 170: } ! 171: else ! 172: { ! 173: partial_where = 0; ! 174: if (partial_size > 0) ! 175: { ! 176: as_warn( "Partial line at end of file ignored" ); ! 177: } ! 178: } ! 179: return (partial_where); ! 180: } ! 181: ! 182: /* ! 183: * The remaining part of this file deals with line numbers, error ! 184: * messages and so on. ! 185: */ ! 186: ! 187: ! 188: /* ! 189: * seen_at_least_1_file() returns TRUE if we opened any file. ! 190: */ ! 191: int ! 192: seen_at_least_1_file( ! 193: void) ! 194: { ! 195: return (physical_input_file != NULL); ! 196: } ! 197: ! 198: void ! 199: bump_line_counters( ! 200: void) ! 201: { ! 202: ++ physical_input_line; ! 203: ++ logical_input_line; ! 204: } ! 205: ! 206: /* ! 207: * new_logical_line() ! 208: * ! 209: * Tells us what the new logical line number and file are. ! 210: * If the line_number is <0, we don't change the current logical line number. ! 211: * If the fname is NULL, we don't change the current logical file name. ! 212: */ ! 213: void ! 214: new_logical_line( ! 215: char *fname, /* DON'T destroy it! We point to it! */ ! 216: int line_number) ! 217: { ! 218: if ( fname ) ! 219: { ! 220: logical_input_file = fname; ! 221: } ! 222: if ( line_number >= 0 ) ! 223: { ! 224: logical_input_line = line_number; ! 225: } ! 226: } ! 227: ! 228: /* ! 229: * a s _ w h e r e ( ) ! 230: * ! 231: * Write a line to stderr locating where we are in reading ! 232: * input source files. ! 233: * As a sop to the debugger of AS, pretty-print the offending line. ! 234: */ ! 235: void ! 236: as_where( ! 237: void) ! 238: { ! 239: char *p; ! 240: line_numberT line; ! 241: ! 242: if (physical_input_file) ! 243: { /* we tried to read SOME source */ ! 244: if (input_file_is_open()) ! 245: { /* we can still read lines from source */ ! 246: p = logical_input_file ? logical_input_file : physical_input_file; ! 247: line = logical_input_line ? logical_input_line : physical_input_line; ! 248: fprintf(stderr,"%s:%u:", p, line); ! 249: } ! 250: else ! 251: { ! 252: p = logical_input_file ? logical_input_file : physical_input_file; ! 253: line = logical_input_line ? logical_input_line : physical_input_line; ! 254: fprintf (stderr,"%s:unknown:", p); ! 255: } ! 256: } ! 257: else ! 258: { ! 259: } ! 260: } ! 261: ! 262: /* ! 263: * as_where_ProjectBuilder() returns the fileName, directory, and line number ! 264: * to be used to tell ProjectBuilder where the error is. Note that the '/' ! 265: * between fileName and directory does not appear in what is returned. ! 266: */ ! 267: void ! 268: as_where_ProjectBuilder( ! 269: char **fileName, ! 270: char **directory, ! 271: int *line) ! 272: { ! 273: char *p, *q; ! 274: static char directory_buf[MAXPATHLEN]; ! 275: ! 276: getwd(directory_buf); ! 277: *fileName = NULL; ! 278: *directory = directory_buf; ! 279: *line = 0; ! 280: ! 281: if(physical_input_file){ ! 282: p = logical_input_file ? ! 283: logical_input_file : physical_input_file; ! 284: if(input_file_is_open()){ ! 285: *line = logical_input_line ? ! 286: logical_input_line : physical_input_line; ! 287: } ! 288: *fileName = p; ! 289: q = strrchr(p, '/'); ! 290: if(q == NULL) ! 291: return; ! 292: *fileName = p + 1; ! 293: strncat(directory_buf, p, q - p); ! 294: } ! 295: } ! 296: ! 297: /* ! 298: * a s _ p e r r o r ! 299: * ! 300: * Like perror(3), but with more info. ! 301: */ ! 302: void ! 303: as_perror( ! 304: char *gripe, /* Unpunctuated error theme. */ ! 305: char *filename) ! 306: { ! 307: fprintf (stderr,"as:file(%s) %s! ", ! 308: filename, gripe ! 309: ); ! 310: if (errno > sys_nerr) ! 311: { ! 312: fprintf (stderr, "Unknown error #%d.", errno); ! 313: } ! 314: else ! 315: { ! 316: fprintf (stderr, "%s.", sys_errlist [errno]); ! 317: } ! 318: (void)putc('\n', stderr); ! 319: errno = 0; /* After reporting, clear it. */ ! 320: if (input_file_is_open()) /* RMS says don't mention line # if not needed. */ ! 321: { ! 322: as_where(); ! 323: } ! 324: } ! 325: ! 326: ! 327: #ifdef NeXT /* .include feature */ ! 328: /* DJA -- added for .include pseudo op support */ ! 329: void ! 330: read_an_include_file( ! 331: char *no_path_name) ! 332: { ! 333: char * buffer; ! 334: char * last_buffer_limit; ! 335: char * last_buffer_start; ! 336: int last_doing_include; ! 337: FILE * last_f_in; ! 338: char * last_file_name; ! 339: char * last_input_line_pointer; ! 340: char * last_logical_input_file; ! 341: line_numberT last_logical_input_line; ! 342: int last_partial_size; ! 343: char * last_partial_where; ! 344: char * last_physical_input_file; ! 345: line_numberT last_physical_input_line; ! 346: char last_save_source [AFTER_SIZE]; ! 347: #if 0 ! 348: char * last_save_buffer; ! 349: #endif ! 350: char name_buffer [MAXPATHLEN]; ! 351: scrub_context_data scrub_context; ! 352: register struct directory_stack * the_path_pointer; ! 353: register char * whole_file_name; ! 354: ! 355: /* ! 356: * figure out what directory the file name is in. ! 357: */ ! 358: whole_file_name = no_path_name; ! 359: if (access(whole_file_name, R_OK)) ! 360: { ! 361: whole_file_name = name_buffer; ! 362: the_path_pointer = include; ! 363: while (the_path_pointer) ! 364: { ! 365: if (strlen (the_path_pointer->fname) + (strlen (no_path_name)) >= MAXPATHLEN) ! 366: as_warn ("include file name too long: \"%s%s\"", the_path_pointer->fname, no_path_name); ! 367: else ! 368: { ! 369: *whole_file_name = '\0'; ! 370: strcpy (whole_file_name, the_path_pointer->fname); ! 371: strcat (whole_file_name, "/"); ! 372: strcat (whole_file_name, no_path_name); ! 373: if (!access(whole_file_name, R_OK)) ! 374: goto found; ! 375: } ! 376: the_path_pointer = the_path_pointer->next; ! 377: } ! 378: the_path_pointer = include_defaults; ! 379: while (the_path_pointer->fname != NULL) ! 380: { ! 381: if (strlen (the_path_pointer->fname) + (strlen (no_path_name)) >= MAXPATHLEN) ! 382: as_warn ("include file name too long: \"%s%s\"", the_path_pointer->fname, no_path_name); ! 383: else ! 384: { ! 385: *whole_file_name = '\0'; ! 386: strcpy (whole_file_name, the_path_pointer->fname); ! 387: strcat (whole_file_name, "/"); ! 388: strcat (whole_file_name, no_path_name); ! 389: if (!access(whole_file_name, R_OK)) ! 390: goto found; ! 391: } ! 392: the_path_pointer++; ! 393: } ! 394: as_fatal ("Couldn't find the include file: \"%s\"", no_path_name); ! 395: return; ! 396: } ! 397: found: ! 398: /* ! 399: * save a copy of the file state for a recursive call to read a file ! 400: */ ! 401: last_buffer_limit = buffer_limit; ! 402: last_buffer_start = buffer_start; ! 403: last_doing_include = doing_include; ! 404: last_f_in = f_in; ! 405: last_file_name = file_name; ! 406: last_input_line_pointer = input_line_pointer; ! 407: last_logical_input_file = logical_input_file; ! 408: last_logical_input_line = logical_input_line; ! 409: last_partial_size = partial_size; ! 410: last_partial_where = partial_where; ! 411: last_physical_input_file = physical_input_file; ! 412: last_physical_input_line = physical_input_line; ! 413: memcpy(last_save_source, save_source, sizeof (save_source)); ! 414: save_scrub_context (&scrub_context); ! 415: /* ! 416: * set up for another file ! 417: */ ! 418: partial_size = 0; ! 419: doing_include = TRUE; ! 420: input_scrub_begin (); ! 421: buffer = input_scrub_new_file (whole_file_name); ! 422: if (f_in != (FILE *)0) ! 423: read_a_source_file(buffer); ! 424: ! 425: xfree (buffer_start); ! 426: /* ! 427: * restore the file state ! 428: */ ! 429: buffer_limit = last_buffer_limit; ! 430: buffer_start = last_buffer_start; ! 431: doing_include = last_doing_include; ! 432: f_in = last_f_in; ! 433: file_name = last_file_name; ! 434: input_line_pointer = last_input_line_pointer; ! 435: logical_input_file = last_logical_input_file; ! 436: logical_input_line = last_logical_input_line; ! 437: partial_size = last_partial_size; ! 438: partial_where = last_partial_where; ! 439: physical_input_file = last_physical_input_file; ! 440: physical_input_line = last_physical_input_line; ! 441: memcpy(save_source, last_save_source, sizeof (save_source)); ! 442: restore_scrub_context (&scrub_context); ! 443: } /* read_an_include_file */ ! 444: #endif /* NeXT .include feature */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.