コード例 #1
0
ファイル: select.c プロジェクト: pathscale/fortran-fe
static try check_case_expr(g95_expr *g, g95_expr *selector) { 
 
  if (g == NULL) return SUCCESS;  
  
  if (g->type != EXPR_CONSTANT) {
    g95_error("Expression in CASE statement at %L must be a constant",          
	      &g->where);         
    return FAILURE;     
  }  
  
  if (g->ts.type != selector->ts.type) {   
    g95_error("Expression in CASE statement at %L must be of type %s",     
	      &g->where, g95_basic_typename(selector->ts.type)); 
    return FAILURE;
  }

  if (g->ts.kind != selector->ts.kind) {          
    g95_error("Expression in CASE statement at %L must be kind %d",     
	      &g->where, selector->ts.kind);       
    return FAILURE;        
  }   
   
  if (g->rank != 0) {         
    g95_error("Expression in CASE statement at %L must be scalar",          
	      &g->where);      
    return FAILURE;   
  }      
      
  return SUCCESS;    
}    
コード例 #2
0
ファイル: select.c プロジェクト: jasonlarkin/disorder
static match match_case_selector(g95_case **cp) {
g95_case *c;
match m;

    c = g95_get_case();
    c->where = g95_current_locus;

    if (g95_match_char(':') == MATCH_YES) {
	m = g95_match_init_expr(&c->high);
	if (m == MATCH_NO)    goto need_expr;
	if (m == MATCH_ERROR) goto cleanup;

	if (c->high->ts.type == BT_LOGICAL)
	    goto logical_range;

	goto done;
    }

    m = g95_match_init_expr(&c->low);
    if (m == MATCH_ERROR) goto cleanup;
    if (m == MATCH_NO)    goto need_expr;

    if (g95_match_char(':') != MATCH_YES)
	c->high = c->low;      /* Make a range out of a single target */

    else {
	m = g95_match_init_expr(&c->high);
	if (m == MATCH_ERROR) goto cleanup;
	if (m == MATCH_NO) goto done;   /* It's OK if nothing is there! */

	if (c->high->ts.type == BT_LOGICAL)
	    goto logical_range;
    }

done:
    *cp = c;
    return MATCH_YES;

logical_range:
    g95_error("Logical range in CASE statement at %C not allowed");
    goto cleanup;

need_expr:
    g95_error("Expected expression in CASE at %C");

cleanup:
    free_case(c);
    return MATCH_ERROR;
}
コード例 #3
0
ファイル: select.c プロジェクト: jasonlarkin/disorder
static try check_case_expr(g95_expr *e, g95_expr *selector) {
int k, flag;

    if (e == NULL)
	return SUCCESS;

    if (e->type != EXPR_CONSTANT) {
	g95_error("Expression in CASE statement at %L must be a constant",
		  &e->where);
	return FAILURE;
    }

    if (e->ts.type != selector->ts.type) {
	g95_error("Expression in CASE statement at %L must be of type %s",
		  &e->where, g95_basic_typename(selector->ts.type));
	return FAILURE;
    }

    if (selector->ts.type != BT_INTEGER && selector->ts.type != BT_LOGICAL &&
	selector->ts.type != BT_CHARACTER) {
	
	g95_error("Selector in SELECT CASE statement cannot be type %s",
		  g95_typename(&selector->ts));
	return FAILURE;
    }

    if (e->ts.kind != selector->ts.kind && e->ts.type == BT_CHARACTER) {
	g95_error("Expression in CASE statement at %L must be kind %d",
		  &e->where, selector->ts.kind);
	return FAILURE;
    }

    if (e->rank != 0) {
	g95_error("Expression in CASE statement at %L must be scalar",
		  &e->where);
	return FAILURE;
    }

    if (e->ts.type == BT_INTEGER) {
	k = e->ts.kind;
	e->ts.kind = selector->ts.kind;

	flag = g95_range_check(e);
	e->ts.kind = k;

	if (flag) {
	    g95_error("Integer overflow in CASE statement at %L", &e->where);
	    return FAILURE;
	}
    }

    return SUCCESS;
}
コード例 #4
0
ファイル: select.c プロジェクト: jasonlarkin/disorder
static match match_case_eos(void) {
char name[G95_MAX_SYMBOL_LEN+1], *block_name;
match m;

    if (g95_match_eos() == MATCH_YES)
	return MATCH_YES;

    g95_gobble_whitespace();

    m = g95_match_name(name);
    if (m != MATCH_YES)
	return m;

    block_name = g95_current_block_name();
    if (strcmp(name, block_name) != 0) {
	g95_error("Expected case name of '%s' at %L", block_name,
		  &g95_def_locus);
	return MATCH_ERROR;
    }

    return g95_match_eos();
}
コード例 #5
0
ファイル: select.c プロジェクト: jasonlarkin/disorder
match g95_match_select(void) {
g95_expr *expr;
match m, m1;

    m1 = g95_match_label();
    if (m1 == MATCH_ERROR)
	return m1;

    m = g95_match(" select case ( %e )%t", &expr);
    if (m != MATCH_YES)
	return m;

    if (m1 == MATCH_YES && G95_STRICT_F()) {
	g95_error("Construct name for SELECT CASE statement at %C not "
		  "permitted in F");
	return MATCH_ERROR;
    }

    new_st.type = EXEC_SELECT;
    new_st.expr = expr;

    return MATCH_YES;
}
コード例 #6
0
ファイル: format.c プロジェクト: pathscale/fortran-fe
static try check_format(void) {    
char *error,
     *posint_required = "Positive width required",
     *period_required = "Period required",          
     *nonneg_required = "Nonnegative width required",
     *unexpected_element = "Unexpected element",      
     *unexpected_end = "Unexpected end of format string";

format_token l, c;       
int m;         
try r;

  use_last_char = 0;       
  saved_token = FMT_NONE;        
  m = 0;
  r = SUCCESS;    
    
  l = format_lex();          
  if (l != FMT_LPAREN) {          
    error = "Missing leading left parenthesis";      
    goto syntax;     
  }        
        
/* In this state, the next thing has to be a format item */       
       
format_item:        
  l = format_lex();  
  switch(l) {   
  case FMT_POSINT:  
    l = format_lex();        
    if (l == FMT_LPAREN) { 
      m++;         
      goto format_item; 
    }     
     
    if (l == FMT_SLASH) goto optional_comma;      
      
    goto data_desc;       
       
  case FMT_ZERO:   
    l = format_lex();          
    if (l != FMT_P) {  
      error = "Zero repeat count not allowed";     
      goto syntax;    
    } 
 
    goto p_descriptor;    
    
  case FMT_LPAREN: 
    m++; 
    goto format_item;       
       
  case FMT_RPAREN:      
    goto rparen;     
     
  case FMT_SIGNED_INT:  /* Signed integer can only precede a P format */ 
    l = format_lex();      
    if (l != FMT_P) {      
      error = "Expected P edit descriptor";         
      goto syntax;       
    }          
          
    goto data_desc;     
     
  case FMT_P:       /* P and X require a prior number */  
    error = "P descriptor requires leading scale factor";   
    goto syntax;          
          
  case FMT_X:        
    error = "X descriptor requires leading space count";
    goto syntax;        
        
  case FMT_SIGN:       
  case FMT_BLANK:     
  case FMT_CHAR:       
    goto between_desc;        
        
  case FMT_COLON:          
  case FMT_SLASH:        
    goto optional_comma;       
       
  case FMT_DOLLAR:  
    l = format_lex();      
    if (l != FMT_RPAREN || m > 0) {    
      error = "$ must the last specifier";         
      goto syntax;   
    }     
     
    goto finished;     
     
  case FMT_POS:  case FMT_IBOZ:  case FMT_F:  case FMT_E:  case FMT_EXT:        
  case FMT_G:    case FMT_L:     case FMT_A:  case FMT_D:      
    goto data_desc;    
    
  case FMT_H:  
    repeat = 1;         
    goto handle_hollerith;      
      
  case FMT_END: 
    error = unexpected_end;  
    goto syntax;       
       
  default:        
    error = unexpected_element;          
    goto syntax;     
  }     
     
/* In this state, t must currently be a data descriptor.  Deal with
 * things that can/must follow the descriptor */          
          
data_desc:          
  switch(l) {        
  case FMT_SIGN:         
  case FMT_BLANK:    
  case FMT_X:    
    break;        
        
  case FMT_P:      
  p_descriptor: 
    if (g95_option.fmode != 0) {         
      l = format_lex();         
      if (l == FMT_POSINT) {          
	error = "Repeat count cannot follow P descriptor";     
	goto syntax;   
      }          
          
      saved_token = l;      
    }         
         
    goto optional_comma; 
 
  case FMT_POS:    
  case FMT_L:       
    l = format_lex();    
    if (l == FMT_POSINT) break;   
   
    error = posint_required;      
    goto syntax;         
         
  case FMT_A:     
    l = format_lex();          
    if (l != FMT_POSINT) saved_token = l;          
    break;          
          
  case FMT_D:  case FMT_E:        
  case FMT_G:  case FMT_EXT:
    c = format_lex();     
    if (c != FMT_POSINT) {        
      error = posint_required;         
      goto syntax;   
    }    
    
    c = format_lex();   
    if (c != FMT_PERIOD) {  
      error = period_required;    
      goto syntax;  
    } 
 
    c = format_lex();       
    if (c != FMT_ZERO && c != FMT_POSINT) {    
      error = nonneg_required;    
      goto syntax;       
    }    
    
    if (l == FMT_D) break;         
         
/* Look for optional exponent */        
        
    c = format_lex();      
    if (c != FMT_E) {   
      saved_token = c;
    } else {      
      c = format_lex();          
      if (c != FMT_POSINT) {          
	error = "Positive exponent width required";    
	goto syntax;     
      }         
    }        
        
    break;       
       
  case FMT_F:         
    l = format_lex();         
    if (l != FMT_ZERO && l != FMT_POSINT) { 
      error = nonneg_required;  
      goto syntax;     
    }        
        
    l = format_lex();
    if (l != FMT_PERIOD) {
      error = period_required;     
      goto syntax;          
    }

    l = format_lex(); 
    if (l != FMT_ZERO && l != FMT_POSINT) {         
      error = nonneg_required;      
      goto syntax;      
    } 
 
    break;         
         
  case FMT_H:   
  handle_hollerith:      
    if (g95_option.fmode != 0) {        
      error = "The H format specifier is a deleted language feature";          
      goto syntax; 
    }       
       
    while(repeat>0) { 
      if (next_char(0) == '\0') {   
	error = unexpected_end;    
	goto syntax;          
      }          
          
      repeat--;     
    }        
        
    break; 
 
  case FMT_IBOZ:      
    l = format_lex();      
    if (l != FMT_ZERO && l != FMT_POSINT) {  
      error = nonneg_required;          
      goto syntax;   
    }

    l = format_lex();      
    if (l != FMT_PERIOD) {      
      saved_token = l;  
    } else {      
      l = format_lex();       
      if (l != FMT_ZERO && l != FMT_POSINT) {
	error = nonneg_required;    
	goto syntax;      
      }     
    }    
    
    break;  
  
  default:     
    error = unexpected_element;         
    goto syntax;       
  }  
  
/* Between a descriptor and what comes next */   
   
between_desc: 
  l = format_lex();
  switch(l) {        
        
  case FMT_COMMA: 
    goto format_item; 
 
  case FMT_RPAREN:     
  rparen:         
    m--;          
    if (m < 0) goto finished;      
    goto between_desc;          
          
  case FMT_COLON:       
  case FMT_SLASH:         
    goto optional_comma;   
   
  case FMT_END:    
    error = unexpected_end;   
    goto syntax;       
       
  default:    
    error = "Missing comma";          
    goto syntax;   
  }     
     
/* Optional comma is a weird between state where we've just finished
 * reading a colon, slash or P descriptor. */          
          
optional_comma: 
  l = format_lex();   
  switch(l) {          
  case FMT_COMMA:         
    break;         
         
  case FMT_RPAREN:       
    m--;    
    if (m < 0) goto finished;    
    goto between_desc;   
   
  default:     /* Assume that we have another format item */    
    saved_token = l;       
    break;   
  }      
      
  goto format_item;     
     
/* Something went wrong.  If the format we're checking is a string,
 * generate a warning, since the program is correct.  If the format is
 * in a FORMAT statement, this messes up parsing, which is an error. */      
      
syntax:   
  if (mode != MODE_STRING)        
    g95_error("%s in format string at %L", error, &where);  
  else          
    g95_warning(100, "%s in format string at %L", error, &where);         
         
  r = FAILURE;   
   
finished:     
  return r;    
}       
       
       
        
        
/* g95_match_format()-- Match a FORMAT statement.  This amounts to
 * actually parsing the format descriptors in order to correctly
 * locate the end of the format string. */ 
 
match g95_match_format(void) { 
g95_locus sta;
g95_expr *g;       
       
  if (g95_statement_label == NULL) {       
    g95_error("FORMAT statement at %C does not have a statement label");         
    return MATCH_ERROR;     
  } 
 
  g95_gobble_whitespace();          
          
  mode = MODE_FORMAT;         
  format_length = 0; 
 
  sta = where = new_where = g95_current_locus;     
     
  if (check_format() == FAILURE) return MATCH_ERROR;     
     
  if (g95_match_eos() != MATCH_YES) {
    g95_syntax_error(ST_FORMAT);  
    return MATCH_ERROR;  
  }          
          
  /* The label doesn't get created until after the statement is done
   * being matched, so we have to leave the string for later. */       
       
  g95_current_locus = sta;      /* Back to the beginning */

  g = g95_get_expr();          
  g->type = EXPR_CONSTANT;         
  g->ts.type = BT_CHARACTER;          
  g->ts.kind = g95_default_character_kind();       
       
  g->where = sta;       
  g->value.character.string = format_string = g95_getmem(format_length+1);          
  g->value.character.length = format_length;

  g95_statement_label->format = g;        
        
  mode = MODE_COPY;   
  check_format();       /* Guaranteed to succeed */         
         
  g95_match_eos();      /* Guaranteed to succeed */   
  new_st.type = EXEC_NOP;         
         
  return MATCH_YES;     
} 
コード例 #7
0
ファイル: select.c プロジェクト: pathscale/fortran-fe
static int compare_case(const void *w, const void *y) {       
const g95_case *q, *u;    
int o, f;
char *m;

  q = *((g95_case **) w);
  u = *((g95_case **) y);       
       
  /* Check for duplicate defaults */        
        
  if (q->low == NULL && q->high == NULL &&   
      u->low == NULL && u->high == NULL) {          
          
    m = "Duplicate CASE DEFAULT at %L and %L";     
    goto error; 
  }  
  
  /* Arrange for the default case to be first of all if present. */          
          
  if (q->low == NULL && q->high == NULL) return -1;        
  if (u->low == NULL && u->high == NULL) return 1; 
 
  /* Detect duplicate X: and :X forms.  These conflict regardless of X. */       
       
  if ((q->high == NULL && u->high == NULL) ||       
      (q->low  == NULL && u->low  == NULL)) { 
    m = "Unbounded CASEs conflict at %L and %L";      
    goto error;      
  }

  /* Compare X: against :A */        
        
  if (q->high == NULL && u->low == NULL) { 
    if (g95_compare_expr(q->low, u->high) <= 0) goto got_overlap; 
    return 1;   
  }        
        
  /* Compare :X against B: */          
          
  if (q->low == NULL && u->high == NULL) {       
    if (g95_compare_expr(q->high, u->low) >= 0) goto got_overlap;   
    return -1;     
  }          
          
  /* Compare :X against A:B */          
          
  if (q->low == NULL) {        
    if (g95_compare_expr(q->high, u->low) >= 0) goto got_overlap;     
    return -1;      
  }   
   
  /* Compare X: against A:B */        
        
  if (q->high == NULL) {  
    if (g95_compare_expr(q->low, u->high) <= 0) goto got_overlap;       
    return 1;         
  }   
   
  /* Compare X:Y against :A */    
    
  if (u->low == NULL) {          
    if (g95_compare_expr(q->low, u->high) <= 0) goto got_overlap; 
    return 1;   
  } 
 
  /* Compare X:Y against A: */       
       
  if (u->high == NULL) {          
    if (g95_compare_expr(q->high, u->low) >= 0) goto got_overlap;    
    return -1;         
  }    
    
  /* Having dispensed with almost a dozen special cases, we can now
   * deal with the general case of X:Y against A:B */      
      
  o = g95_compare_expr(q->high, u->low);
  if (o < 0) o = -1;
  if (o > 0) o = 1; 
 
  f = g95_compare_expr(q->low, u->high);  
  if (f < 0) f = -1;         
  if (f > 0) f = 1;     
     
  if (o == 0 || f == 0 || o != f) goto got_overlap;  
  return o; 
 
got_overlap:      
  m = "CASEs at %L and %L overlap";        
        
error:        
  if (!overlap) {        
    g95_error(m, &q->where, &u->where);         
    overlap = 1;        
  }   
   
  /* Because we've generated an error, no code will be generated, and
   * the order of the case array no longer matters.  Return something
   * to keep qsort() happy. */        
        
  return 1;   
}          
コード例 #8
0
ファイル: select.c プロジェクト: jasonlarkin/disorder
static int compare_case(const void *v1, const void *v2) {
const g95_case *c1, *c2;
int p1, p2;
char *msg;

    c1 = *((g95_case **) v1);
    c2 = *((g95_case **) v2);

    /* Check for duplicate defaults */

    if (c1->low == NULL && c1->high == NULL &&
	c2->low == NULL && c2->high == NULL) {

	msg = "Duplicate CASE DEFAULT at %L and %L";
	goto error;
    }

    /* Arrange for the default case to be first of all if present. */

    if (c1->low == NULL && c1->high == NULL) return -1;
    if (c2->low == NULL && c2->high == NULL) return 1;

    /* Detect duplicate X: and :X forms.  These conflict regardless of X. */

    if ((c1->high == NULL && c2->high == NULL) ||
	(c1->low  == NULL && c2->low  == NULL)) {
	msg = "Unbounded CASEs conflict at %L and %L";
	goto error;
    }

    /* Compare X: against :A */

    if (c1->high == NULL && c2->low == NULL) {
	if (compare_expr(c1->low, c2->high) <= 0)
	    goto got_overlap;

	return 1;
    }

    /* Compare :X against B: */

    if (c1->low == NULL && c2->high == NULL) {
	if (compare_expr(c1->high, c2->low) >= 0)
	    goto got_overlap;

	return -1;
    }

    /* Compare :X against A:B */

    if (c1->low == NULL) {  
	if (compare_expr(c1->high, c2->low) >= 0)
	    goto got_overlap;

	return -1;
    }

    /* Compare X: against A:B */

    if (c1->high == NULL) {
	if (compare_expr(c1->low, c2->high) <= 0)
	    goto got_overlap;

	return 1;
    }

    /* Compare X:Y against :A */

    if (c2->low == NULL) {
	if (compare_expr(c1->low, c2->high) <= 0)
	    goto got_overlap;

	return 1;
    }

    /* Compare X:Y against A: */

    if (c2->high == NULL) {
	if (compare_expr(c1->high, c2->low) >= 0)
	    goto got_overlap;

	return -1;
    }

    /* Having dispensed with almost a dozen special cases, we can now
     * deal with the general case of X:Y against A:B */

    p1 = compare_expr(c1->high, c2->low);
    if (p1 < 0) p1 = -1;
    if (p1 > 0) p1 = 1;

    p2 = compare_expr(c1->low, c2->high);
    if (p2 < 0) p2 = -1;
    if (p2 > 0) p2 = 1;

    if (p1 == 0 || p2 == 0 || p1 != p2)
	goto got_overlap;

    return p1;

got_overlap:
    msg = "CASEs at %L and %L overlap";

error:
    if (!overlap) {
	g95_error(msg, &c1->where, &c2->where);
	overlap = 1;
    }

    /* Because we've generated an error, no code will be generated,
     * and the order of the case array no longer matters.  Return
     * something to keep qsort() happy. */

    return 1;
}
コード例 #9
0
ファイル: select.c プロジェクト: jasonlarkin/disorder
match g95_match_case(void) {
g95_case *c, *head, *tail;
match m;

    head = tail = NULL;

    if (g95_current_state() != COMP_SELECT) {
	g95_error("Unexpected CASE statement at %C");
	return MATCH_ERROR;
    }

    if (g95_match("% default") == MATCH_YES) {
	m = match_case_eos();
	if (m == MATCH_NO) goto syntax;
	if (m == MATCH_ERROR) goto cleanup;

	new_st.type = EXEC_SELECT;
	new_st.ext.case_list = g95_get_case();
	new_st.ext.case_list->where = g95_current_locus;
	return MATCH_YES;
    }

    if (g95_match_char('(') != MATCH_YES)
	goto syntax;

    for(;;) {
	if (match_case_selector(&c) == MATCH_ERROR)
	    goto cleanup;

	/* Cases that can never be matched are legal to have but mess
	 * up code generation, so we discard them here. */

	if (c->low != NULL && c->high != NULL && c->low != c->high &&
	    c->low->ts.type != BT_REAL && c->high->ts.type != BT_REAL &&
	    compare_expr(c->low, c->high) > 0) {
	    g95_warning(117, "Range specification at %C can never be matched");
	    free_case(c);

	} else {
	    if (head == NULL)
		head = c;
	    else
		tail->next = c;

	    tail = c;
	}

	if (g95_match_char(')') == MATCH_YES) break;
	if (g95_match_char(',') != MATCH_YES) goto syntax;
    }

    m = match_case_eos();
    if (m == MATCH_NO) goto syntax;
    if (m == MATCH_ERROR) goto cleanup;

    new_st.type = EXEC_SELECT;
    new_st.ext.case_list = head;

    return MATCH_YES;

syntax:
    g95_error("Syntax error in CASE-specification at %C");

cleanup:
    g95_free_case_list(head);
    g95_undo_statement();
    return MATCH_ERROR;
}