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

📄 primary.c

📁 gcc-fortran,linux使用fortran的编译软件。很好用的。
💻 C
📖 第 1 页 / 共 4 页
字号:
     assume we have a complex constant because we've seen the ','.  An     ambiguous case here is the start of an iterator list of some     sort. These sort of lists are matched prior to coming here.  */  if (m == MATCH_ERROR)    {      gfc_free_error (&old_error);      goto cleanup;    }  gfc_pop_error (&old_error);  m = match_complex_part (&imag);  if (m == MATCH_NO)    goto syntax;  if (m == MATCH_ERROR)    goto cleanup;  m = gfc_match_char (')');  if (m == MATCH_NO)    {      /* Give the matcher for implied do-loops a chance to run.  This	 yields a much saner error message for (/ (i, 4=i, 6) /).  */      if (gfc_peek_char () == '=')	{	  m = MATCH_ERROR;	  goto cleanup;	}      else    goto syntax;    }  if (m == MATCH_ERROR)    goto cleanup;  /* Decide on the kind of this complex number.  */  if (real->ts.type == BT_REAL)    {      if (imag->ts.type == BT_REAL)	kind = gfc_kind_max (real, imag);      else	kind = real->ts.kind;    }  else    {      if (imag->ts.type == BT_REAL)	kind = imag->ts.kind;      else	kind = gfc_default_real_kind;    }  target.type = BT_REAL;  target.kind = kind;  if (real->ts.type != BT_REAL || kind != real->ts.kind)    gfc_convert_type (real, &target, 2);  if (imag->ts.type != BT_REAL || kind != imag->ts.kind)    gfc_convert_type (imag, &target, 2);  e = gfc_convert_complex (real, imag, kind);  e->where = gfc_current_locus;  gfc_free_expr (real);  gfc_free_expr (imag);  *result = e;  return MATCH_YES;syntax:  gfc_error ("Syntax error in COMPLEX constant at %C");  m = MATCH_ERROR;cleanup:  gfc_free_expr (e);  gfc_free_expr (real);  gfc_free_expr (imag);  gfc_current_locus = old_loc;  return m;}/* Match constants in any of several forms.  Returns nonzero for a   match, zero for no match.  */matchgfc_match_literal_constant (gfc_expr ** result, int signflag){  match m;  m = match_complex_constant (result);  if (m != MATCH_NO)    return m;  m = match_string_constant (result);  if (m != MATCH_NO)    return m;  m = match_boz_constant (result);  if (m != MATCH_NO)    return m;  m = match_real_constant (result, signflag);  if (m != MATCH_NO)    return m;  m = match_hollerith_constant (result);  if (m != MATCH_NO)    return m;  m = match_integer_constant (result, signflag);  if (m != MATCH_NO)    return m;  m = match_logical_constant (result);  if (m != MATCH_NO)    return m;  return MATCH_NO;}/* Match a single actual argument value.  An actual argument is   usually an expression, but can also be a procedure name.  If the   argument is a single name, it is not always possible to tell   whether the name is a dummy procedure or not.  We treat these cases   by creating an argument that looks like a dummy procedure and   fixing things later during resolution.  */static matchmatch_actual_arg (gfc_expr ** result){  char name[GFC_MAX_SYMBOL_LEN + 1];  gfc_symtree *symtree;  locus where, w;  gfc_expr *e;  int c;  where = gfc_current_locus;  switch (gfc_match_name (name))    {    case MATCH_ERROR:      return MATCH_ERROR;    case MATCH_NO:      break;    case MATCH_YES:      w = gfc_current_locus;      gfc_gobble_whitespace ();      c = gfc_next_char ();      gfc_current_locus = w;      if (c != ',' && c != ')')	break;      if (gfc_find_sym_tree (name, NULL, 1, &symtree))	break;      /* Handle error elsewhere.  */      /* Eliminate a couple of common cases where we know we don't         have a function argument.  */      if (symtree == NULL)        {	  gfc_get_sym_tree (name, NULL, &symtree);          gfc_set_sym_referenced (symtree->n.sym);        }      else	{          gfc_symbol *sym;          sym = symtree->n.sym;          gfc_set_sym_referenced (sym);	  if (sym->attr.flavor != FL_PROCEDURE	      && sym->attr.flavor != FL_UNKNOWN)	    break;	  /* If the symbol is a function with itself as the result and	     is being defined, then we have a variable.  */	  if (sym->attr.function && sym->result == sym)	    {	      if (gfc_current_ns->proc_name == sym		  || (gfc_current_ns->parent != NULL		      && gfc_current_ns->parent->proc_name == sym))		break;	      if (sym->attr.entry		  && (sym->ns == gfc_current_ns		      || sym->ns == gfc_current_ns->parent))		{		  gfc_entry_list *el = NULL;		  for (el = sym->ns->entries; el; el = el->next)		    if (sym == el->sym)		      break;		  if (el)		    break;		}	    }	}      e = gfc_get_expr ();	/* Leave it unknown for now */      e->symtree = symtree;      e->expr_type = EXPR_VARIABLE;      e->ts.type = BT_PROCEDURE;      e->where = where;      *result = e;      return MATCH_YES;    }  gfc_current_locus = where;  return gfc_match_expr (result);}/* Match a keyword argument.  */static matchmatch_keyword_arg (gfc_actual_arglist * actual, gfc_actual_arglist * base){  char name[GFC_MAX_SYMBOL_LEN + 1];  gfc_actual_arglist *a;  locus name_locus;  match m;  name_locus = gfc_current_locus;  m = gfc_match_name (name);  if (m != MATCH_YES)    goto cleanup;  if (gfc_match_char ('=') != MATCH_YES)    {      m = MATCH_NO;      goto cleanup;    }  m = match_actual_arg (&actual->expr);  if (m != MATCH_YES)    goto cleanup;  /* Make sure this name has not appeared yet.  */  if (name[0] != '\0')    {      for (a = base; a; a = a->next)	if (a->name != NULL && strcmp (a->name, name) == 0)	  {	    gfc_error	      ("Keyword '%s' at %C has already appeared in the current "	       "argument list", name);	    return MATCH_ERROR;	  }    }  actual->name = gfc_get_string (name);  return MATCH_YES;cleanup:  gfc_current_locus = name_locus;  return m;}/* Matches an actual argument list of a function or subroutine, from   the opening parenthesis to the closing parenthesis.  The argument   list is assumed to allow keyword arguments because we don't know if   the symbol associated with the procedure has an implicit interface   or not.  We make sure keywords are unique. If SUB_FLAG is set,   we're matching the argument list of a subroutine.  */matchgfc_match_actual_arglist (int sub_flag, gfc_actual_arglist ** argp){  gfc_actual_arglist *head, *tail;  int seen_keyword;  gfc_st_label *label;  locus old_loc;  match m;  *argp = tail = NULL;  old_loc = gfc_current_locus;  seen_keyword = 0;  if (gfc_match_char ('(') == MATCH_NO)    return (sub_flag) ? MATCH_YES : MATCH_NO;  if (gfc_match_char (')') == MATCH_YES)    return MATCH_YES;  head = NULL;  for (;;)    {      if (head == NULL)	head = tail = gfc_get_actual_arglist ();      else	{	  tail->next = gfc_get_actual_arglist ();	  tail = tail->next;	}      if (sub_flag && gfc_match_char ('*') == MATCH_YES)	{	  m = gfc_match_st_label (&label);	  if (m == MATCH_NO)	    gfc_error ("Expected alternate return label at %C");	  if (m != MATCH_YES)	    goto cleanup;	  tail->label = label;	  goto next;	}      /* After the first keyword argument is seen, the following         arguments must also have keywords.  */      if (seen_keyword)	{	  m = match_keyword_arg (tail, head);	  if (m == MATCH_ERROR)	    goto cleanup;	  if (m == MATCH_NO)	    {	      gfc_error		("Missing keyword name in actual argument list at %C");	      goto cleanup;	    }	}      else	{	  /* See if we have the first keyword argument.  */	  m = match_keyword_arg (tail, head);	  if (m == MATCH_YES)	    seen_keyword = 1;	  if (m == MATCH_ERROR)	    goto cleanup;	  if (m == MATCH_NO)	    {	      /* Try for a non-keyword argument.  */	      m = match_actual_arg (&tail->expr);	      if (m == MATCH_ERROR)		goto cleanup;	      if (m == MATCH_NO)		goto syntax;	    }	}    next:      if (gfc_match_char (')') == MATCH_YES)	break;      if (gfc_match_char (',') != MATCH_YES)	goto syntax;    }  *argp = head;  return MATCH_YES;syntax:  gfc_error ("Syntax error in argument list at %C");cleanup:  gfc_free_actual_arglist (head);  gfc_current_locus = old_loc;  return MATCH_ERROR;}/* Used by match_varspec() to extend the reference list by one   element.  */static gfc_ref *extend_ref (gfc_expr * primary, gfc_ref * tail){  if (primary->ref == NULL)    primary->ref = tail = gfc_get_ref ();  else    {      if (tail == NULL)	gfc_internal_error ("extend_ref(): Bad tail");      tail->next = gfc_get_ref ();      tail = tail->next;    }  return tail;}/* Match any additional specifications associated with the current   variable like member references or substrings.  If equiv_flag is   set we only match stuff that is allowed inside an EQUIVALENCE   statement.  */static matchmatch_varspec (gfc_expr * primary, int equiv_flag){  char name[GFC_MAX_SYMBOL_LEN + 1];  gfc_ref *substring, *tail;  gfc_component *component;  gfc_symbol *sym = primary->symtree->n.sym;  match m;  tail = NULL;  if ((equiv_flag && gfc_peek_char () == '(')      || sym->attr.dimension)    {      /* In EQUIVALENCE, we don't know yet whether we are seeing	 an array, character variable or array of character	 variables.  We'll leave the decision till resolve	 time.  */      tail = extend_ref (primary, tail);      tail->type = REF_ARRAY;      m = gfc_match_array_ref (&tail->u.ar, equiv_flag ? NULL : sym->as,			       equiv_flag);      if (m != MATCH_YES)	return m;      if (equiv_flag && gfc_peek_char () == '(')	{	  tail = extend_ref (primary, tail);	  tail->type = REF_ARRAY;	  m = gfc_match_array_ref (&tail->u.ar, NULL, equiv_flag);	  if (m != MATCH_YES)	    return m;	}    }  primary->ts = sym->ts;  if (equiv_flag)    return MATCH_YES;  if (sym->ts.type != BT_DERIVED || gfc_match_char ('%') != MATCH_YES)    goto check_substring;  sym = sym->ts.derived;  for (;;)    {      m = gfc_match_name (name);      if (m == MATCH_NO)	gfc_error ("Expected structure component name at %C");      if (m != MATCH_YES)	return MATCH_ERROR;      component = gfc_find_component (sym, name);      if (component == NULL)	return MATCH_ERROR;      tail = extend_ref (primary, tail);      tail->type = REF_COMPONENT;      tail->u.c.component = component;      tail->u.c.sym = sym;      primary->ts = component->ts;      if (component->as != NULL)	{	  tail = extend_ref (primary, tail);	  tail->type = REF_ARRAY;	  m = gfc_match_array_ref (&tail->u.ar, component->as, equiv_flag);	  if (m != MATCH_YES)	    return m;	}      if (component->ts.type != BT_DERIVED	  || gfc_match_char ('%') != MATCH_YES)	break;      sym = component->ts.derived;    }check_substring:  if (primary->ts.type == BT_UNKNOWN)    {      if (gfc_get_default_type (sym, sym->ns)->type == BT_CHARACTER)       {         gfc_set_default_type (sym, 0, sym->ns);         primary->ts = sym->ts;       }    }  if (primary->ts.type == BT_CHARACTER)    {      switch (match_substring (primary->ts.cl, equiv_flag, &substring))	{	case MATCH_YES:	  if (tail == NULL)	    primary->ref = substring;	  else	    tail->next = substring;	  if (primary->expr_type == EXPR_CONSTANT)	    primary->expr_type = EXPR_SUBSTRING;	  if (substring)	    primary->ts.cl = NULL;	  break;	case MATCH_NO:	  break;	case MATCH_ERROR:	  return MATCH_ERROR;	}    }  return MATCH_YES;}/* Given an expression that is a variable, figure out what the   ultimate variable's type and attribute is, traversing the reference   structures if necessary.   This subroutine is trickier than it looks.  We start at the base   symbol and store the attribute.  Component references load a   completely new attribute.   A couple of rules come into play.  Subobjects of targets are always   targets themselves.  If we see a component that goes through a   pointer, then the expression must also be a target, since the   pointer is associated with something (if it isn't core will soon be   dumped).  If we see a full part or section of an array, the   expression is also an array.   We can have at most one full array reference.  */symbol_attributegfc_variable_attr (gfc_expr * expr, gfc_typespec * ts){  int dimension, pointer, target;  symbol_attribute attr;  gfc_ref *ref;  if (expr->expr_type != EXPR_VARIABLE)    gfc_internal_error ("gfc_variable_attr(): Expression isn't a variable");  ref = expr->ref;  attr = expr->symtree->n.sym->attr;  dimension = attr.dimension;  pointer = attr.pointer;  target = attr.target;  if (pointer)    target = 1;  if (ts != NULL && expr->ts.type == BT_UNKNOWN)    *ts = expr->symtree->n.sym->ts;  for (; ref; ref = ref->next)    switch (ref->type)      {      case REF_ARRAY:	switch (ref->u.ar.type)	  {	  case AR_FULL:	    dimension = 1;	    break;	  case AR_SECTION:	    pointer = 0;	    dimension = 1;	    break;	  case AR_ELEMENT:	    pointer = 0;	    break;	  case AR_UNKNOWN:	    gfc_internal_error ("gfc_variable_attr(): Bad array reference");	  }	break;

⌨️ 快捷键说明

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