home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 4.2J (Developer) / os42jdev.iso / NextDeveloper / Source / GNU / cctools / as / input-scrub.c < prev    next >
C/C++ Source or Header  |  1994-06-03  |  12KB  |  445 lines

  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 */
  445.