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

📄 match.c

📁 gcc-fortran,linux使用fortran的编译软件。很好用的。
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Matching subroutines in all sizes, shapes and colors.   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006   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.  */#include "config.h"#include "system.h"#include "flags.h"#include "gfortran.h"#include "match.h"#include "parse.h"/* For matching and debugging purposes.  Order matters here!  The   unary operators /must/ precede the binary plus and minus, or   the expression parser breaks.  */mstring intrinsic_operators[] = {    minit ("+", INTRINSIC_UPLUS),    minit ("-", INTRINSIC_UMINUS),    minit ("+", INTRINSIC_PLUS),    minit ("-", INTRINSIC_MINUS),    minit ("**", INTRINSIC_POWER),    minit ("//", INTRINSIC_CONCAT),    minit ("*", INTRINSIC_TIMES),    minit ("/", INTRINSIC_DIVIDE),    minit (".and.", INTRINSIC_AND),    minit (".or.", INTRINSIC_OR),    minit (".eqv.", INTRINSIC_EQV),    minit (".neqv.", INTRINSIC_NEQV),    minit (".eq.", INTRINSIC_EQ),    minit ("==", INTRINSIC_EQ),    minit (".ne.", INTRINSIC_NE),    minit ("/=", INTRINSIC_NE),    minit (".ge.", INTRINSIC_GE),    minit (">=", INTRINSIC_GE),    minit (".le.", INTRINSIC_LE),    minit ("<=", INTRINSIC_LE),    minit (".lt.", INTRINSIC_LT),    minit ("<", INTRINSIC_LT),    minit (".gt.", INTRINSIC_GT),    minit (">", INTRINSIC_GT),    minit (".not.", INTRINSIC_NOT),    minit ("parens", INTRINSIC_PARENTHESES),    minit (NULL, INTRINSIC_NONE)};/******************** Generic matching subroutines ************************//* In free form, match at least one space.  Always matches in fixed   form.  */matchgfc_match_space (void){  locus old_loc;  int c;  if (gfc_current_form == FORM_FIXED)    return MATCH_YES;  old_loc = gfc_current_locus;  c = gfc_next_char ();  if (!gfc_is_whitespace (c))    {      gfc_current_locus = old_loc;      return MATCH_NO;    }  gfc_gobble_whitespace ();  return MATCH_YES;}/* Match an end of statement.  End of statement is optional   whitespace, followed by a ';' or '\n' or comment '!'.  If a   semicolon is found, we continue to eat whitespace and semicolons.  */matchgfc_match_eos (void){  locus old_loc;  int flag, c;  flag = 0;  for (;;)    {      old_loc = gfc_current_locus;      gfc_gobble_whitespace ();      c = gfc_next_char ();      switch (c)	{	case '!':	  do	    {	      c = gfc_next_char ();	    }	  while (c != '\n');	  /* Fall through */	case '\n':	  return MATCH_YES;	case ';':	  flag = 1;	  continue;	}      break;    }  gfc_current_locus = old_loc;  return (flag) ? MATCH_YES : MATCH_NO;}/* Match a literal integer on the input, setting the value on   MATCH_YES.  Literal ints occur in kind-parameters as well as   old-style character length specifications.  */matchgfc_match_small_literal_int (int *value, int *cnt){  locus old_loc;  char c;  int i, j;  old_loc = gfc_current_locus;  gfc_gobble_whitespace ();  c = gfc_next_char ();  *cnt = 0;  if (!ISDIGIT (c))    {      gfc_current_locus = old_loc;      return MATCH_NO;    }  i = c - '0';  j = 1;  for (;;)    {      old_loc = gfc_current_locus;      c = gfc_next_char ();      if (!ISDIGIT (c))	break;      i = 10 * i + c - '0';      j++;      if (i > 99999999)	{	  gfc_error ("Integer too large at %C");	  return MATCH_ERROR;	}    }  gfc_current_locus = old_loc;  *value = i;  *cnt = j;  return MATCH_YES;}/* Match a small, constant integer expression, like in a kind   statement.  On MATCH_YES, 'value' is set.  */matchgfc_match_small_int (int *value){  gfc_expr *expr;  const char *p;  match m;  int i;  m = gfc_match_expr (&expr);  if (m != MATCH_YES)    return m;  p = gfc_extract_int (expr, &i);  gfc_free_expr (expr);  if (p != NULL)    {      gfc_error (p);      m = MATCH_ERROR;    }  *value = i;  return m;}/* Matches a statement label.  Uses gfc_match_small_literal_int() to   do most of the work.  */matchgfc_match_st_label (gfc_st_label ** label){  locus old_loc;  match m;  int i, cnt;  old_loc = gfc_current_locus;  m = gfc_match_small_literal_int (&i, &cnt);  if (m != MATCH_YES)    return m;  if (cnt > 5)    {      gfc_error ("Too many digits in statement label at %C");      goto cleanup;    }  if (i == 0)    {      gfc_error ("Statement label at %C is zero");      goto cleanup;    }  *label = gfc_get_st_label (i);  return MATCH_YES;cleanup:  gfc_current_locus = old_loc;  return MATCH_ERROR;}/* Match and validate a label associated with a named IF, DO or SELECT   statement.  If the symbol does not have the label attribute, we add   it.  We also make sure the symbol does not refer to another   (active) block.  A matched label is pointed to by gfc_new_block.  */matchgfc_match_label (void){  char name[GFC_MAX_SYMBOL_LEN + 1];  match m;  gfc_new_block = NULL;  m = gfc_match (" %n :", name);  if (m != MATCH_YES)    return m;  if (gfc_get_symbol (name, NULL, &gfc_new_block))    {      gfc_error ("Label name '%s' at %C is ambiguous", name);      return MATCH_ERROR;    }  if (gfc_new_block->attr.flavor == FL_LABEL)    {      gfc_error ("Duplicate construct label '%s' at %C", name);      return MATCH_ERROR;    }  if (gfc_add_flavor (&gfc_new_block->attr, FL_LABEL,		      gfc_new_block->name, NULL) == FAILURE)    return MATCH_ERROR;  return MATCH_YES;}/* Try and match the input against an array of possibilities.  If one   potential matching string is a substring of another, the longest   match takes precedence.  Spaces in the target strings are optional   spaces that do not necessarily have to be found in the input   stream.  In fixed mode, spaces never appear.  If whitespace is   matched, it matches unlimited whitespace in the input.  For this   reason, the 'mp' member of the mstring structure is used to track   the progress of each potential match.   If there is no match we return the tag associated with the   terminating NULL mstring structure and leave the locus pointer   where it started.  If there is a match we return the tag member of   the matched mstring and leave the locus pointer after the matched   character.   A '%' character is a mandatory space.  */intgfc_match_strings (mstring * a){  mstring *p, *best_match;  int no_match, c, possibles;  locus match_loc;  possibles = 0;  for (p = a; p->string != NULL; p++)    {      p->mp = p->string;      possibles++;    }  no_match = p->tag;  best_match = NULL;  match_loc = gfc_current_locus;  gfc_gobble_whitespace ();  while (possibles > 0)    {      c = gfc_next_char ();      /* Apply the next character to the current possibilities.  */      for (p = a; p->string != NULL; p++)	{	  if (p->mp == NULL)	    continue;	  if (*p->mp == ' ')	    {	      /* Space matches 1+ whitespace(s).  */	      if ((gfc_current_form == FORM_FREE)		  && gfc_is_whitespace (c))		continue;	      p->mp++;	    }	  if (*p->mp != c)	    {	      /* Match failed.  */	      p->mp = NULL;	      possibles--;	      continue;	    }	  p->mp++;	  if (*p->mp == '\0')	    {	      /* Found a match.  */	      match_loc = gfc_current_locus;	      best_match = p;	      possibles--;	      p->mp = NULL;	    }	}    }  gfc_current_locus = match_loc;  return (best_match == NULL) ? no_match : best_match->tag;}/* See if the current input looks like a name of some sort.  Modifies   the passed buffer which must be GFC_MAX_SYMBOL_LEN+1 bytes long.  */matchgfc_match_name (char *buffer){  locus old_loc;  int i, c;  old_loc = gfc_current_locus;  gfc_gobble_whitespace ();  c = gfc_next_char ();  if (!ISALPHA (c))    {      gfc_current_locus = old_loc;      return MATCH_NO;    }  i = 0;  do    {      buffer[i++] = c;      if (i > gfc_option.max_identifier_length)	{	  gfc_error ("Name at %C is too long");	  return MATCH_ERROR;	}      old_loc = gfc_current_locus;      c = gfc_next_char ();    }  while (ISALNUM (c)	 || c == '_'	 || (gfc_option.flag_dollar_ok && c == '$'));  buffer[i] = '\0';  gfc_current_locus = old_loc;  return MATCH_YES;}/* Match a symbol on the input.  Modifies the pointer to the symbol   pointer if successful.  */matchgfc_match_sym_tree (gfc_symtree ** matched_symbol, int host_assoc){  char buffer[GFC_MAX_SYMBOL_LEN + 1];  match m;  m = gfc_match_name (buffer);  if (m != MATCH_YES)    return m;  if (host_assoc)    return (gfc_get_ha_sym_tree (buffer, matched_symbol))      ? MATCH_ERROR : MATCH_YES;  if (gfc_get_sym_tree (buffer, NULL, matched_symbol))    return MATCH_ERROR;  return MATCH_YES;}matchgfc_match_symbol (gfc_symbol ** matched_symbol, int host_assoc){  gfc_symtree *st;  match m;  m = gfc_match_sym_tree (&st, host_assoc);  if (m == MATCH_YES)    {      if (st)        *matched_symbol = st->n.sym;      else        *matched_symbol = NULL;    }  else    *matched_symbol = NULL;  return m;}/* Match an intrinsic operator.  Returns an INTRINSIC enum. While matching,    we always find INTRINSIC_PLUS before INTRINSIC_UPLUS. We work around this    in matchexp.c.  */matchgfc_match_intrinsic_op (gfc_intrinsic_op * result){  gfc_intrinsic_op op;  op = (gfc_intrinsic_op) gfc_match_strings (intrinsic_operators);  if (op == INTRINSIC_NONE)    return MATCH_NO;  *result = op;  return MATCH_YES;}/* Match a loop control phrase:    <LVALUE> = <EXPR>, <EXPR> [, <EXPR> ]   If the final integer expression is not present, a constant unity   expression is returned.  We don't return MATCH_ERROR until after   the equals sign is seen.  */matchgfc_match_iterator (gfc_iterator * iter, int init_flag){  char name[GFC_MAX_SYMBOL_LEN + 1];  gfc_expr *var, *e1, *e2, *e3;  locus start;  match m;  /* Match the start of an iterator without affecting the symbol     table.  */  start = gfc_current_locus;  m = gfc_match (" %n =", name);  gfc_current_locus = start;  if (m != MATCH_YES)    return MATCH_NO;  m = gfc_match_variable (&var, 0);  if (m != MATCH_YES)    return MATCH_NO;  gfc_match_char ('=');  e1 = e2 = e3 = NULL;  if (var->ref != NULL)    {      gfc_error ("Loop variable at %C cannot be a sub-component");      goto cleanup;    }  if (var->symtree->n.sym->attr.intent == INTENT_IN)    {      gfc_error ("Loop variable '%s' at %C cannot be INTENT(IN)",		 var->symtree->n.sym->name);      goto cleanup;    }  if (var->symtree->n.sym->attr.pointer)    {      gfc_error ("Loop variable at %C cannot have the POINTER attribute");      goto cleanup;    }  m = init_flag ? gfc_match_init_expr (&e1) : gfc_match_expr (&e1);  if (m == MATCH_NO)    goto syntax;  if (m == MATCH_ERROR)    goto cleanup;  if (gfc_match_char (',') != MATCH_YES)    goto syntax;  m = init_flag ? gfc_match_init_expr (&e2) : gfc_match_expr (&e2);  if (m == MATCH_NO)    goto syntax;  if (m == MATCH_ERROR)    goto cleanup;  if (gfc_match_char (',') != MATCH_YES)    {      e3 = gfc_int_expr (1);      goto done;    }  m = init_flag ? gfc_match_init_expr (&e3) : gfc_match_expr (&e3);  if (m == MATCH_ERROR)    goto cleanup;  if (m == MATCH_NO)    {      gfc_error ("Expected a step value in iterator at %C");      goto cleanup;    }done:  iter->var = var;  iter->start = e1;  iter->end = e2;  iter->step = e3;  return MATCH_YES;syntax:  gfc_error ("Syntax error in iterator at %C");cleanup:  gfc_free_expr (e1);  gfc_free_expr (e2);  gfc_free_expr (e3);  return MATCH_ERROR;}/* Tries to match the next non-whitespace character on the input.   This subroutine does not return MATCH_ERROR.  */matchgfc_match_char (char c){  locus where;  where = gfc_current_locus;  gfc_gobble_whitespace ();  if (gfc_next_char () == c)    return MATCH_YES;  gfc_current_locus = where;  return MATCH_NO;}/* General purpose matching subroutine.  The target string is a   scanf-like format string in which spaces correspond to arbitrary   whitespace (including no whitespace), characters correspond to   themselves.  The %-codes are:   %%  Literal percent sign   %e  Expression, pointer to a pointer is set   %s  Symbol, pointer to the symbol is set   %n  Name, character buffer is set to name   %t  Matches end of statement.   %o  Matches an intrinsic operator, returned as an INTRINSIC enum.   %l  Matches a statement label   %v  Matches a variable expression (an lvalue)   %   Matches a required space (in free form) and optional spaces.  */matchgfc_match (const char *target, ...){  gfc_st_label **label;  int matches, *ip;  locus old_loc;  va_list argp;  char c, *np;  match m, n;  void **vp;  const char *p;  old_loc = gfc_current_locus;  va_start (argp, target);  m = MATCH_NO;  matches = 0;  p = target;

⌨️ 快捷键说明

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