⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scanner.c

📁 gcc-fortran,linux使用fortran的编译软件。很好用的。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Character scanner.   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005   Free Software Foundation, Inc.   Contributed by Andy VaughtThis file is part of GCC.GCC is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.GCC is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public Licensealong with GCC; see the file COPYING.  If not, write to the FreeSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA02110-1301, USA.  *//* Set of subroutines to (ultimately) return the next character to the   various matching subroutines.  This file's job is to read files and   build up lines that are parsed by the parser.  This means that we   handle continuation lines and "include" lines.   The first thing the scanner does is to load an entire file into   memory.  We load the entire file into memory for a couple reasons.   The first is that we want to be able to deal with nonseekable input   (pipes, stdin) and there is a lot of backing up involved during   parsing.   The second is that we want to be able to print the locus of errors,   and an error on line 999999 could conflict with something on line   one.  Given nonseekable input, we've got to store the whole thing.   One thing that helps are the column truncation limits that give us   an upper bound on the size of individual lines.  We don't store the   truncated stuff.   From the scanner's viewpoint, the higher level subroutines ask for   new characters and do a lot of jumping backwards.  */#include "config.h"#include "system.h"#include "gfortran.h"#include "toplev.h"/* Structure for holding module and include file search path.  */typedef struct gfc_directorylist{  char *path;  struct gfc_directorylist *next;}gfc_directorylist;/* List of include file search directories.  */static gfc_directorylist *include_dirs;static gfc_file *file_head, *current_file;static int continue_flag, end_flag;gfc_source_form gfc_current_form;static gfc_linebuf *line_head, *line_tail;       locus gfc_current_locus;const char *gfc_source_file;static FILE *gfc_src_file;static char *gfc_src_preprocessor_lines[2];/* Main scanner initialization.  */voidgfc_scanner_init_1 (void){  file_head = NULL;  line_head = NULL;  line_tail = NULL;  end_flag = 0;}/* Main scanner destructor.  */voidgfc_scanner_done_1 (void){  gfc_linebuf *lb;  gfc_file *f;  while(line_head != NULL)     {      lb = line_head->next;      gfc_free(line_head);      line_head = lb;    }       while(file_head != NULL)     {      f = file_head->next;      gfc_free(file_head->filename);      gfc_free(file_head);      file_head = f;        }}/* Adds path to the list pointed to by list.  */voidgfc_add_include_path (const char *path){  gfc_directorylist *dir;  const char *p;  p = path;  while (*p == ' ' || *p == '\t')  /* someone might do 'gfortran "-I include"' */    if (*p++ == '\0')      return;  dir = include_dirs;  if (!dir)    {      dir = include_dirs = gfc_getmem (sizeof (gfc_directorylist));    }  else    {      while (dir->next)	dir = dir->next;      dir->next = gfc_getmem (sizeof (gfc_directorylist));      dir = dir->next;    }  dir->next = NULL;  dir->path = gfc_getmem (strlen (p) + 2);  strcpy (dir->path, p);  strcat (dir->path, "/");	/* make '/' last character */}/* Release resources allocated for options.  */voidgfc_release_include_path (void){  gfc_directorylist *p;  gfc_free (gfc_option.module_dir);  while (include_dirs != NULL)    {      p = include_dirs;      include_dirs = include_dirs->next;      gfc_free (p->path);      gfc_free (p);    }}/* Opens file for reading, searching through the include directories   given if necessary.  If the include_cwd argument is true, we try   to open the file in the current directory first.  */FILE *gfc_open_included_file (const char *name, const bool include_cwd){  char *fullname;  gfc_directorylist *p;  FILE *f;  if (include_cwd)    {      f = gfc_open_file (name);      if (f != NULL)	return f;    }  for (p = include_dirs; p; p = p->next)    {      fullname = (char *) alloca(strlen (p->path) + strlen (name) + 1);      strcpy (fullname, p->path);      strcat (fullname, name);      f = gfc_open_file (fullname);      if (f != NULL)	return f;    }  return NULL;}/* Test to see if we're at the end of the main source file.  */intgfc_at_end (void){  return end_flag;}/* Test to see if we're at the end of the current file.  */intgfc_at_eof (void){  if (gfc_at_end ())    return 1;  if (line_head == NULL)    return 1;			/* Null file */  if (gfc_current_locus.lb == NULL)    return 1;  return 0;}/* Test to see if we're at the beginning of a new line.  */intgfc_at_bol (void){  if (gfc_at_eof ())    return 1;  return (gfc_current_locus.nextc == gfc_current_locus.lb->line);}/* Test to see if we're at the end of a line.  */intgfc_at_eol (void){  if (gfc_at_eof ())    return 1;  return (*gfc_current_locus.nextc == '\0');}/* Advance the current line pointer to the next line.  */voidgfc_advance_line (void){  if (gfc_at_end ())    return;  if (gfc_current_locus.lb == NULL)     {      end_flag = 1;      return;    }   gfc_current_locus.lb = gfc_current_locus.lb->next;  if (gfc_current_locus.lb != NULL)             gfc_current_locus.nextc = gfc_current_locus.lb->line;  else     {      gfc_current_locus.nextc = NULL;      end_flag = 1;    }       }/* Get the next character from the input, advancing gfc_current_file's   locus.  When we hit the end of the line or the end of the file, we   start returning a '\n' in order to complete the current statement.   No Fortran line conventions are implemented here.   Requiring explicit advances to the next line prevents the parse   pointer from being on the wrong line if the current statement ends   prematurely.  */static intnext_char (void){  int c;    if (gfc_current_locus.nextc == NULL)    return '\n';  c = *gfc_current_locus.nextc++;  if (c == '\0')    {      gfc_current_locus.nextc--; /* Remain on this line.  */      c = '\n';    }  return c;}/* Skip a comment.  When we come here the parse pointer is positioned   immediately after the comment character.  If we ever implement   compiler directives withing comments, here is where we parse the   directive.  */static voidskip_comment_line (void){  char c;  do    {      c = next_char ();    }  while (c != '\n');  gfc_advance_line ();}/* Comment lines are null lines, lines containing only blanks or lines   on which the first nonblank line is a '!'.  */static voidskip_free_comments (void){  locus start;  char c;  for (;;)    {      start = gfc_current_locus;      if (gfc_at_eof ())	break;      do	{	  c = next_char ();	}      while (gfc_is_whitespace (c));      if (c == '\n')	{	  gfc_advance_line ();	  continue;	}      if (c == '!')	{	  skip_comment_line ();	  continue;	}      break;    }  gfc_current_locus = start;}/* Skip comment lines in fixed source mode.  We have the same rules as   in skip_free_comment(), except that we can have a 'c', 'C' or '*'   in column 1, and a '!' cannot be in column 6.  Also, we deal with   lines with 'd' or 'D' in column 1, if the user requested this.  */static voidskip_fixed_comments (void){  locus start;  int col;  char c;  for (;;)    {      start = gfc_current_locus;      if (gfc_at_eof ())	break;      c = next_char ();      if (c == '\n')	{	  gfc_advance_line ();	  continue;	}      if (c == '!' || c == 'c' || c == 'C' || c == '*')	{	  skip_comment_line ();	  continue;	}      if (gfc_option.flag_d_lines != -1 && (c == 'd' || c == 'D'))	{	  if (gfc_option.flag_d_lines == 0)	    {	      skip_comment_line ();	      continue;	    }	  else	    *start.nextc = c = ' ';	}      col = 1;      while (gfc_is_whitespace (c))	{	  c = next_char ();	  col++;	}      if (c == '\n')	{	  gfc_advance_line ();	  continue;	}      if (col != 6 && c == '!')	{	  skip_comment_line ();	  continue;	}      break;    }  gfc_current_locus = start;}/* Skips the current line if it is a comment.  Assumes that we are at   the start of the current line.  */voidgfc_skip_comments (void){  if (!gfc_at_bol () || gfc_current_form == FORM_FREE)    skip_free_comments ();  else    skip_fixed_comments ();}/* Get the next character from the input, taking continuation lines   and end-of-line comments into account.  This implies that comment   lines between continued lines must be eaten here.  For higher-level   subroutines, this flattens continued lines into a single logical   line.  The in_string flag denotes whether we're inside a character   context or not.  */intgfc_next_char_literal (int in_string){  locus old_loc;  int i, c;  continue_flag = 0;restart:  c = next_char ();  if (gfc_at_end ())    return c;  if (gfc_current_form == FORM_FREE)    {      if (!in_string && c == '!')	{	  /* This line can't be continued */	  do	    {	      c = next_char ();	    }	  while (c != '\n');	  /* Avoid truncation warnings for comment ending lines.  */	  gfc_current_locus.lb->truncated = 0;	  goto done;	}      if (c != '&')	goto done;      /* If the next nonblank character is a ! or \n, we've got a         continuation line.  */      old_loc = gfc_current_locus;      c = next_char ();      while (gfc_is_whitespace (c))	c = next_char ();      /* Character constants to be continued cannot have commentary         after the '&'.  */      if (in_string && c != '\n')	{	  gfc_current_locus = old_loc;	  c = '&';	  goto done;	}      if (c != '!' && c != '\n')	{	  gfc_current_locus = old_loc;	  c = '&';	  goto done;	}      continue_flag = 1;      if (c == '!')	skip_comment_line ();      else	gfc_advance_line ();      /* We've got a continuation line and need to find where it continues.         First eat any comment lines.  */      gfc_skip_comments ();      /* Now that we have a non-comment line, probe ahead for the         first non-whitespace character.  If it is another '&', then         reading starts at the next character, otherwise we must back         up to where the whitespace started and resume from there.  */      old_loc = gfc_current_locus;      c = next_char ();      while (gfc_is_whitespace (c))	c = next_char ();      if (c != '&')	gfc_current_locus = old_loc;    }  else    {      /* Fixed form continuation.  */      if (!in_string && c == '!')	{	  /* Skip comment at end of line.  */	  do	    {	      c = next_char ();	    }	  while (c != '\n');	  /* Avoid truncation warnings for comment ending lines.  */	  gfc_current_locus.lb->truncated = 0;	}      if (c != '\n')	goto done;      continue_flag = 1;      old_loc = gfc_current_locus;      gfc_advance_line ();      gfc_skip_comments ();      /* See if this line is a continuation line.  */      for (i = 0; i < 5; i++)	{	  c = next_char ();	  if (c != ' ')	    goto not_continuation;	}      c = next_char ();      if (c == '0' || c == ' ')	goto not_continuation;    }  /* Ready to read first character of continuation line, which might     be another continuation line!  */  goto restart;not_continuation:  c = '\n';  gfc_current_locus = old_loc;done:  continue_flag = 0;  return c;}/* Get the next character of input, folded to lowercase.  In fixed   form mode, we also ignore spaces.  When matcher subroutines are   parsing character literals, they have to call   gfc_next_char_literal().  */intgfc_next_char (void){  int c;  do    {      c = gfc_next_char_literal (0);    }  while (gfc_current_form == FORM_FIXED && gfc_is_whitespace (c));  return TOLOWER (c);}intgfc_peek_char (void){  locus old_loc;  int c;  old_loc = gfc_current_locus;  c = gfc_next_char ();  gfc_current_locus = old_loc;  return c;}/* Recover from an error.  We try to get past the current statement   and get lined up for the next.  The next statement follows a '\n'   or a ';'.  We also assume that we are not within a character   constant, and deal with finding a '\'' or '"'.  */voidgfc_error_recovery (void){  char c, delim;  if (gfc_at_eof ())    return;  for (;;)    {      c = gfc_next_char ();      if (c == '\n' || c == ';')	break;      if (c != '\'' && c != '"')	{	  if (gfc_at_eof ())	    break;	  continue;	}      delim = c;      for (;;)	{	  c = next_char ();	  if (c == delim)	    break;	  if (c == '\n')	    return;	  if (c == '\\')	    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -