299 lines
		
	
	
	
		
			7.4 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			299 lines
		
	
	
	
		
			7.4 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| /****************************************************************
 | |
| Copyright 1990 by AT&T Bell Laboratories, Bellcore.
 | |
| 
 | |
| Permission to use, copy, modify, and distribute this software
 | |
| and its documentation for any purpose and without fee is hereby
 | |
| granted, provided that the above copyright notice appear in all
 | |
| copies and that both that the copyright notice and this
 | |
| permission notice and warranty disclaimer appear in supporting
 | |
| documentation, and that the names of AT&T Bell Laboratories or
 | |
| Bellcore or any of their entities not be used in advertising or
 | |
| publicity pertaining to distribution of the software without
 | |
| specific, written prior permission.
 | |
| 
 | |
| AT&T and Bellcore disclaim all warranties with regard to this
 | |
| software, including all implied warranties of merchantability
 | |
| and fitness.  In no event shall AT&T or Bellcore be liable for
 | |
| any special, indirect or consequential damages or any damages
 | |
| whatsoever resulting from loss of use, data or profits, whether
 | |
| in an action of contract, negligence or other tortious action,
 | |
| arising out of or in connection with the use or performance of
 | |
| this software.
 | |
| ****************************************************************/
 | |
| 
 | |
| %{
 | |
| #	include "defs.h"
 | |
| #	include "p1defs.h"
 | |
| 
 | |
| static int nstars;			/* Number of labels in an
 | |
| 					   alternate return CALL */
 | |
| static int datagripe;
 | |
| static int ndim;
 | |
| static int vartype;
 | |
| int new_dcl;
 | |
| static ftnint varleng;
 | |
| static struct Dims dims[MAXDIM+1];
 | |
| static struct Labelblock *labarray[MAXLABLIST];	/* Labels in an alternate
 | |
| 						   return CALL */
 | |
| 
 | |
| /* The next two variables are used to verify that each statement might be reached
 | |
|    during runtime.   lastwasbranch   is tested only in the defintion of the
 | |
|    stat:   nonterminal. */
 | |
| 
 | |
| int lastwasbranch = NO;
 | |
| static int thiswasbranch = NO;
 | |
| extern ftnint yystno;
 | |
| extern flag intonly;
 | |
| static chainp datastack;
 | |
| extern long laststfcn, thisstno;
 | |
| extern int can_include;	/* for netlib */
 | |
| 
 | |
| ftnint convci();
 | |
| Addrp nextdata();
 | |
| expptr mklogcon(), mkaddcon(), mkrealcon(), mkstrcon(), mkbitcon();
 | |
| expptr mkcxcon();
 | |
| struct Listblock *mklist();
 | |
| struct Listblock *mklist();
 | |
| struct Impldoblock *mkiodo();
 | |
| Extsym *comblock();
 | |
| #define ESNULL (Extsym *)0
 | |
| #define NPNULL (Namep)0
 | |
| #define LBNULL (struct Listblock *)0
 | |
| extern void freetemps(), make_param();
 | |
| 
 | |
|  static void
 | |
| pop_datastack() {
 | |
| 	chainp d0 = datastack;
 | |
| 	if (d0->datap)
 | |
| 		curdtp = (chainp)d0->datap;
 | |
| 	datastack = d0->nextp;
 | |
| 	d0->nextp = 0;
 | |
| 	frchain(&d0);
 | |
| 	}
 | |
| 
 | |
| %}
 | |
| 
 | |
| /* Specify precedences and associativities. */
 | |
| 
 | |
| %union	{
 | |
| 	int ival;
 | |
| 	ftnint lval;
 | |
| 	char *charpval;
 | |
| 	chainp chval;
 | |
| 	tagptr tagval;
 | |
| 	expptr expval;
 | |
| 	struct Labelblock *labval;
 | |
| 	struct Nameblock *namval;
 | |
| 	struct Eqvchain *eqvval;
 | |
| 	Extsym *extval;
 | |
| 	}
 | |
| 
 | |
| %left SCOMMA
 | |
| %nonassoc SCOLON
 | |
| %right SEQUALS
 | |
| %left SEQV SNEQV
 | |
| %left SOR
 | |
| %left SAND
 | |
| %left SNOT
 | |
| %nonassoc SLT SGT SLE SGE SEQ SNE
 | |
| %left SCONCAT
 | |
| %left SPLUS SMINUS
 | |
| %left SSTAR SSLASH
 | |
| %right SPOWER
 | |
| 
 | |
| %start program
 | |
| %type <labval> thislabel label assignlabel
 | |
| %type <tagval> other inelt
 | |
| %type <ival> type typespec typename dcl letter addop relop stop nameeq
 | |
| %type <lval> lengspec
 | |
| %type <charpval> filename
 | |
| %type <chval> datavar datavarlist namelistlist funarglist funargs
 | |
| %type <chval> dospec dospecw
 | |
| %type <chval> callarglist arglist args exprlist inlist outlist out2 substring
 | |
| %type <namval> name arg call var
 | |
| %type <expval> lhs expr uexpr opt_expr fexpr unpar_fexpr
 | |
| %type <expval> ubound simple value callarg complex_const simple_const bit_const
 | |
| %type <extval> common comblock entryname progname
 | |
| %type <eqvval> equivlist
 | |
| 
 | |
| %%
 | |
| 
 | |
| program:
 | |
| 	| program stat SEOS
 | |
| 	;
 | |
| 
 | |
| stat:	  thislabel  entry
 | |
| 		{
 | |
| /* stat:   is the nonterminal for Fortran statements */
 | |
| 
 | |
| 		  lastwasbranch = NO; }
 | |
| 	| thislabel  spec
 | |
| 	| thislabel  exec
 | |
| 		{ /* forbid further statement function definitions... */
 | |
| 		  if (parstate == INDATA && laststfcn != thisstno)
 | |
| 			parstate = INEXEC;
 | |
| 		  thisstno++;
 | |
| 		  if($1 && ($1->labelno==dorange))
 | |
| 			enddo($1->labelno);
 | |
| 		  if(lastwasbranch && thislabel==NULL)
 | |
| 			warn("statement cannot be reached");
 | |
| 		  lastwasbranch = thiswasbranch;
 | |
| 		  thiswasbranch = NO;
 | |
| 		  if($1)
 | |
| 			{
 | |
| 			if($1->labtype == LABFORMAT)
 | |
| 				err("label already that of a format");
 | |
| 			else
 | |
| 				$1->labtype = LABEXEC;
 | |
| 			}
 | |
| 		  freetemps();
 | |
| 		}
 | |
| 	| thislabel SINCLUDE filename
 | |
| 		{ if (can_include)
 | |
| 			doinclude( $3 );
 | |
| 		  else {
 | |
| 			fprintf(diagfile, "Cannot open file %s\n", $3);
 | |
| 			done(1);
 | |
| 			}
 | |
| 		}
 | |
| 	| thislabel  SEND  end_spec
 | |
| 		{ if ($1)
 | |
| 			lastwasbranch = NO;
 | |
| 		  endproc(); /* lastwasbranch = NO; -- set in endproc() */
 | |
| 		}
 | |
| 	| thislabel SUNKNOWN
 | |
| 		{ extern void unclassifiable();
 | |
| 		  unclassifiable();
 | |
| 
 | |
| /* flline flushes the current line, ignoring the rest of the text there */
 | |
| 
 | |
| 		  flline(); };
 | |
| 	| error
 | |
| 		{ flline();  needkwd = NO;  inioctl = NO;
 | |
| 		  yyerrok; yyclearin; }
 | |
| 	;
 | |
| 
 | |
| thislabel:  SLABEL
 | |
| 		{
 | |
| 		if(yystno != 0)
 | |
| 			{
 | |
| 			$$ = thislabel =  mklabel(yystno);
 | |
| 			if( ! headerdone ) {
 | |
| 				if (procclass == CLUNKNOWN)
 | |
| 					procclass = CLMAIN;
 | |
| 				puthead(CNULL, procclass);
 | |
| 				}
 | |
| 			if(thislabel->labdefined)
 | |
| 				execerr("label %s already defined",
 | |
| 					convic(thislabel->stateno) );
 | |
| 			else	{
 | |
| 				if(thislabel->blklevel!=0 && thislabel->blklevel<blklevel
 | |
| 				    && thislabel->labtype!=LABFORMAT)
 | |
| 					warn1("there is a branch to label %s from outside block",
 | |
| 					      convic( (ftnint) (thislabel->stateno) ) );
 | |
| 				thislabel->blklevel = blklevel;
 | |
| 				thislabel->labdefined = YES;
 | |
| 				if(thislabel->labtype != LABFORMAT)
 | |
| 					p1_label((long)(thislabel - labeltab));
 | |
| 				}
 | |
| 			}
 | |
| 		else    $$ = thislabel = NULL;
 | |
| 		}
 | |
| 	;
 | |
| 
 | |
| entry:	  SPROGRAM new_proc progname
 | |
| 		   {startproc($3, CLMAIN); }
 | |
| 	| SPROGRAM new_proc progname progarglist
 | |
| 		   {	warn("ignoring arguments to main program");
 | |
| 			/* hashclear(); */
 | |
| 			startproc($3, CLMAIN); }
 | |
| 	| SBLOCK new_proc progname
 | |
| 		{ if($3) NO66("named BLOCKDATA");
 | |
| 		  startproc($3, CLBLOCK); }
 | |
| 	| SSUBROUTINE new_proc entryname arglist
 | |
| 		{ entrypt(CLPROC, TYSUBR, (ftnint) 0,  $3, $4); }
 | |
| 	| SFUNCTION new_proc entryname arglist
 | |
| 		{ entrypt(CLPROC, TYUNKNOWN, (ftnint) 0, $3, $4); }
 | |
| 	| type SFUNCTION new_proc entryname arglist
 | |
| 		{ entrypt(CLPROC, $1, varleng, $4, $5); }
 | |
| 	| SENTRY entryname arglist
 | |
| 		 { if(parstate==OUTSIDE || procclass==CLMAIN
 | |
| 			|| procclass==CLBLOCK)
 | |
| 				execerr("misplaced entry statement", CNULL);
 | |
| 		  entrypt(CLENTRY, 0, (ftnint) 0, $2, $3);
 | |
| 		}
 | |
| 	;
 | |
| 
 | |
| new_proc:
 | |
| 		{ newproc(); }
 | |
| 	;
 | |
| 
 | |
| entryname:  name
 | |
| 		{ $$ = newentry($1, 1); }
 | |
| 	;
 | |
| 
 | |
| name:	  SNAME
 | |
| 		{ $$ = mkname(token); }
 | |
| 	;
 | |
| 
 | |
| progname:		{ $$ = NULL; }
 | |
| 	| entryname
 | |
| 	;
 | |
| 
 | |
| progarglist:
 | |
| 	  SLPAR SRPAR
 | |
| 	| SLPAR progargs SRPAR
 | |
| 	;
 | |
| 
 | |
| progargs: progarg
 | |
| 	| progargs SCOMMA progarg
 | |
| 	;
 | |
| 
 | |
| progarg:  SNAME
 | |
| 	| SNAME SEQUALS SNAME
 | |
| 	;
 | |
| 
 | |
| arglist:
 | |
| 		{ $$ = 0; }
 | |
| 	| SLPAR SRPAR
 | |
| 		{ NO66(" () argument list");
 | |
| 		  $$ = 0; }
 | |
| 	| SLPAR args SRPAR
 | |
| 		{$$ = $2; }
 | |
| 	;
 | |
| 
 | |
| args:	  arg
 | |
| 		{ $$ = ($1 ? mkchain((char *)$1,CHNULL) : CHNULL ); }
 | |
| 	| args SCOMMA arg
 | |
| 		{ if($3) $1 = $$ = mkchain((char *)$3, $1); }
 | |
| 	;
 | |
| 
 | |
| arg:	  name
 | |
| 		{ if($1->vstg!=STGUNKNOWN && $1->vstg!=STGARG)
 | |
| 			dclerr("name declared as argument after use", $1);
 | |
| 		  $1->vstg = STGARG;
 | |
| 		}
 | |
| 	| SSTAR
 | |
| 		{ NO66("altenate return argument");
 | |
| 
 | |
| /* substars   means that '*'ed formal parameters should be replaced.
 | |
|    This is used to specify alternate return labels; in theory, only
 | |
|    parameter slots which have '*' should accept the statement labels.
 | |
|    This compiler chooses to ignore the '*'s in the formal declaration, and
 | |
|    always return the proper value anyway.
 | |
| 
 | |
|    This variable is only referred to in   proc.c   */
 | |
| 
 | |
| 		  $$ = 0;  substars = YES; }
 | |
| 	;
 | |
| 
 | |
| 
 | |
| 
 | |
| filename:   SHOLLERITH
 | |
| 		{
 | |
| 		char *s;
 | |
| 		s = copyn(toklen+1, token);
 | |
| 		s[toklen] = '\0';
 | |
| 		$$ = s;
 | |
| 		}
 | |
| 	;
 |