include include "addmasks.h" define YYMAXDEPTH 64 define YYOPLEN 1 define yyparse addparse define MAX_CODE SZ_COMMAND define MAX_TOKEN SZ_FNAME # Characters define DOT '.' define BLANK ' ' define CMTCHAR '#' # Tokens generated by xyacc have been moved to addmasks.h define Y_WRONG 257 define Y_LPAR 258 define Y_RPAR 259 define Y_IDENT 260 define Y_IF 261 define Y_DONE 262 define Y_THEN 263 define Y_ELSE 264 define Y_PUSH 265 define Y_CONST 266 define Y_OR 267 define Y_AND 268 define Y_NOT 269 define Y_EQ 270 define Y_NE 271 define Y_LT 272 define Y_GT 273 define Y_LE 274 define Y_GE 275 define yyclearin yychar = -1 define yyerrok yyerrflag = 0 define YYMOVE call amovi (Memi[$1], Memi[$2], YYOPLEN) define YYERRCODE 256 # line 117 "addcompile.y" # ADDCOMPILE -- Compile an addmasks expression into RPN instructions pointer procedure addcompile (expr) char expr[ARB] # i: Expression to be parsed #-- include "addcompile.com" int ic, fd, len, debug pointer sp, pcode data debug / NO / int open(), stropen(), strlen(), addparse() extern addlexer begin # Create pseudocode array call malloc (pcode, MAX_CODE, TY_INT) # Initialize parsing common block call smark (sp) call salloc (line, SZ_LINE, TY_CHAR) ch = line Memc[line] = EOS ncode = 0 code = pcode # Open the expression as a file for (ic = 1; IS_WHITE(expr[ic]); ic = ic + 1) ; if (expr[ic] == '@') fd = open (expr[ic+1], READ_ONLY, TEXT_FILE) else { len = strlen (expr[ic]) + 1 fd = stropen (expr[ic], len, READ_ONLY) } # Parse expression to produce reverse polish code if (addparse (fd, debug, addlexer) == ERR) { if (Memc[line] != EOS) { call eprintf ("%s\n%*t^\n") call pargstr (Memc[line]) call pargi (ch-line) } call error (1, "Syntax error in expression") } # Clean up and return pseudocode array call close (fd) call sfree (sp) return (pcode) end # ADDLEXER -- Lexical analysis of addmasks expression int procedure addlexer (fd, value) int fd # i: File containing expression to be lexed pointer value # i: Pointer to current token value #-- include "addcompile.com" char token[MAX_TOKEN] int ic, jc, nc, type, ktype int keytype[12] string keytok "or and eq ne lt gt le ge not if then else" data keytype / Y_OR, Y_AND, Y_EQ, Y_NE, Y_LT, Y_GT, Y_LE, Y_GE, Y_NOT, Y_IF, Y_THEN, Y_ELSE / int getline(), ctoi(), word_match() begin # Skip over leading white space and comments while (Memc[ch] <= BLANK || Memc[ch] == CMTCHAR) { # If all characters have been read from the current line # or a comment character was found, get the next line if (Memc[ch] == EOS || Memc[ch] == CMTCHAR) { ch = line if (getline (fd, Memc[line]) == EOF) { Memc[ch] = EOS break } } else { ch = ch + 1 } } # The token type is determined from the first character in the token ic = 1 Memi[value] = NULL # End of expression token if (Memc[ch] == EOS) { type = Y_DONE # Numeric constant } else if (IS_DIGIT(Memc[ch])) { for (ic = 1; ic <= MAX_TOKEN; ic = ic + 1) { if (! IS_DIGIT(Memc[ch])) break token[ic] = Memc[ch] ch = ch + 1 } token[ic] = EOS call malloc (Memi[value], ic, TY_CHAR) call strcpy (token, Memc[Memi[value]], ic) type = Y_CONST # Token is alphanumeric. Keyword or variable. } else if (IS_ALPHA (Memc[ch])) { # Gather characters in token for (ic = 1; ic <= MAX_TOKEN; ic = ic + 1) { if (Memc[ch] != '_' && ! IS_ALNUM(Memc[ch])) break if (IS_UPPER(Memc[ch])) token[ic] = TO_LOWER(Memc[ch]) else token[ic] = Memc[ch] ch = ch + 1 } token[ic] = EOS ktype = word_match (token, keytok) if (ktype > 0) { type = keytype[ktype] } else if (token[1] == 'i' && token[2] == 'm') { jc = 3 type = Y_IDENT nc = ctoi (token, jc, Memi[value]) if (token[jc] != EOS) { type = Y_WRONG call malloc (Memi[value], ic, TY_CHAR) call strcpy (token, Memc[Memi[value]], ic) } } else { type = Y_WRONG call malloc (Memi[value], ic, TY_CHAR) call strcpy (token, Memc[Memi[value]], ic) } # Tokens beginning with a dot are keywords } else if (Memc[ch] == DOT) { # Gather characters in token ch = ch + 1 for (ic = 1; ic < MAX_TOKEN && Memc[ch] != DOT; ic = ic + 1) { if (Memc[ch] == EOS) break if (IS_UPPER(Memc[ch])) token[ic] = TO_LOWER(Memc[ch]) else token[ic] = Memc[ch] ch = ch + 1 } token[ic] = EOS ch = ch + 1 ktype = word_match (token, keytok) if (ktype > 0) { type = keytype[ktype] } else { type = Y_WRONG call malloc (Memi[value], ic, TY_CHAR) call strcpy (token, Memc[Memi[value]], ic) } # Anything else is a symbol } else { switch (Memc[ch]) { case '(': type = Y_LPAR case ')': type = Y_RPAR case '<': if (Memc[ch+1] != '=') { type = Y_LT } else { type = Y_LE ch = ch + 1 } case '>': if (Memc[ch+1] != '=') { type = Y_GT } else { type = Y_GE ch = ch + 1 } case '|': if (Memc[ch+1] != '|') { type = Y_WRONG } else { type = Y_OR ch = ch + 1 } case '&': if (Memc[ch+1] != '&') { type = Y_WRONG } else { type = Y_AND ch = ch + 1 } case '=': if (Memc[ch+1] != '=') { type = Y_WRONG } else { type = Y_EQ ch = ch + 1 } case '!': if (Memc[ch+1] != '=') { type = Y_NOT } else { type = Y_NE ch = ch + 1 } default: type = Y_WRONG } if (type == Y_WRONG) { call malloc (Memi[value], 2, TY_CHAR) call strcpy (Memc[ch], Memc[Memi[value]], 2) } ch = ch + 1 } return (type) end # ADDENCODE -- Add an instruction to the code array procedure addencode (token) int token # i: Instruction token #-- include "addcompile.com" begin if (ncode == MAX_CODE) call error (1, "Expression too complex") else { Memi[code] = token code = code + 1 ncode = ncode + 1 } end # ADDNUMBER -- Add a numeric constant to the code array procedure addnumber (const) pointer const # i: Pointer to constant value #-- include "addcompile.com" pointer chr begin chr = const - 1 repeat { chr = chr + 1 if (ncode == MAX_CODE) call error (1, "Expression too complex") Memi[code] = Memc[chr] code = code + 1 ncode = ncode + 1 } until (Memc[chr] == EOS) call mfree (const, TY_CHAR) end define YYNPROD 19 define YYLAST 109 # Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. # Parser for yacc output, translated to the IRAF SPP language. The contents # of this file form the bulk of the source of the parser produced by Yacc. # Yacc recognizes several macros in the yaccpar input source and replaces # them as follows: # A user suppled "global" definitions and declarations # B parser tables # C user supplied actions (reductions) # The remainder of the yaccpar code is not changed. define yystack_ 10 # statement labels for gotos define yynewstate_ 20 define yydefault_ 30 define yyerrlab_ 40 define yyabort_ 50 define YYFLAG (-1000) # defs used in user actions define YYERROR goto yyerrlab_ define YYACCEPT return (OK) define YYABORT return (ERR) # YYPARSE -- Parse the input stream, returning OK if the source is # syntactically acceptable (i.e., if compilation is successful), # otherwise ERR. The parameters YYMAXDEPTH and YYOPLEN must be # supplied by the caller in the %{ ... %} section of the Yacc source. # The token value stack is a dynamically allocated array of operand # structures, with the length and makeup of the operand structure being # application dependent. int procedure yyparse (fd, yydebug, yylex) int fd # stream to be parsed bool yydebug # print debugging information? int yylex() # user-supplied lexical input function extern yylex() short yys[YYMAXDEPTH] # parser stack -- stacks tokens pointer yyv # pointer to token value stack pointer yyval # value returned by action pointer yylval # value of token int yyps # token stack pointer pointer yypv # value stack pointer int yychar # current input token number int yyerrflag # error recovery flag int yynerrs # number of errors short yyj, yym # internal variables pointer yysp, yypvt short yystate, yyn int yyxi, i errchk salloc, yylex short yyexca[70] data (yyexca(i),i= 1, 8) / -1, 1, 0, -1, -2, 0, -1, 26/ data (yyexca(i),i= 9, 16) / 270, 0, 271, 0, -2, 11, -1, 27/ data (yyexca(i),i= 17, 24) / 270, 0, 271, 0, -2, 12, -1, 28/ data (yyexca(i),i= 25, 32) / 272, 0, 273, 0, 274, 0, 275, 0/ data (yyexca(i),i= 33, 40) / -2, 13, -1, 29, 272, 0, 273, 0/ data (yyexca(i),i= 41, 48) / 274, 0, 275, 0, -2, 14, -1, 30/ data (yyexca(i),i= 49, 56) / 272, 0, 273, 0, 274, 0, 275, 0/ data (yyexca(i),i= 57, 64) / -2, 15, -1, 31, 272, 0, 273, 0/ data (yyexca(i),i= 65, 70) / 274, 0, 275, 0, -2, 16/ short yyact[109] data (yyact(i),i= 1, 8) / 34, 11, 2, 14, 13, 32, 15, 16/ data (yyact(i),i= 9, 16) / 17, 18, 19, 20, 1, 14, 13, 0/ data (yyact(i),i= 17, 24) / 15, 16, 17, 18, 19, 20, 23, 0/ data (yyact(i),i= 25, 32) / 0, 0, 14, 13, 0, 15, 16, 17/ data (yyact(i),i= 33, 40) / 18, 19, 20, 14, 13, 0, 15, 16/ data (yyact(i),i= 41, 48) / 17, 18, 19, 20, 13, 0, 15, 16/ data (yyact(i),i= 49, 56) / 17, 18, 19, 20, 15, 16, 17, 18/ data (yyact(i),i= 57, 64) / 19, 20, 17, 18, 19, 20, 3, 10/ data (yyact(i),i= 65, 72) / 9, 0, 6, 4, 10, 9, 0, 6/ data (yyact(i),i= 73, 80) / 7, 5, 0, 8, 0, 7, 12, 0/ data (yyact(i),i= 81, 88) / 8, 0, 21, 22, 0, 0, 0, 24/ data (yyact(i),i= 89, 96) / 25, 26, 27, 28, 29, 30, 31, 0/ data (yyact(i),i= 97,104) / 0, 33, 0, 0, 0, 0, 0, 0/ data (yyact(i),i=105,109) / 0, 0, 0, 0, 35/ short yypact[36] data (yypact(i),i= 1, 8) /-194,-1000,-261,-1000,-189,-232,-1000,-1000/ data (yypact(i),i= 9, 16) /-189,-189,-1000,-1000,-241,-189,-189,-189/ data (yypact(i),i= 17, 24) /-189,-189,-189,-189,-189,-218,-254,-189/ data (yypact(i),i= 25, 32) /-218,-224,-214,-214,-1000,-1000,-1000,-1000/ data (yypact(i),i= 33, 36) /-1000,-264,-189,-232/ short yypgo[4] data (yypgo(i),i= 1, 4) / 0, 12, 2, 73/ short yyr1[19] data (yyr1(i),i= 1, 8) / 0, 1, 1, 2, 2, 2, 3, 3/ data (yyr1(i),i= 9, 16) / 3, 3, 3, 3, 3, 3, 3, 3/ data (yyr1(i),i= 17, 19) / 3, 3, 3/ short yyr2[19] data (yyr2(i),i= 1, 8) / 0, 2, 1, 6, 4, 1, 1, 1/ data (yyr2(i),i= 9, 16) / 3, 3, 2, 3, 3, 3, 3, 3/ data (yyr2(i),i= 17, 19) / 3, 3, 1/ short yychk[36] data (yychk(i),i= 1, 8) /-1000, -1, -2, 256, 261, -3, 260, 266/ data (yychk(i),i= 9, 16) / 269, 258, 257, 262, -3, 268, 267, 270/ data (yychk(i),i= 17, 24) / 271, 272, 273, 274, 275, -3, -3, 263/ data (yychk(i),i= 25, 32) / -3, -3, -3, -3, -3, -3, -3, -3/ data (yychk(i),i= 33, 36) / 259, -3, 264, -3/ short yydef[36] data (yydef(i),i= 1, 8) / 0, -2, 0, 2, 0, 5, 6, 7/ data (yydef(i),i= 9, 16) / 0, 0, 18, 1, 0, 0, 0, 0/ data (yydef(i),i= 17, 24) / 0, 0, 0, 0, 0, 10, 0, 0/ data (yydef(i),i= 25, 32) / 8, 9, -2, -2, -2, -2, -2, -2/ data (yydef(i),i= 33, 36) / 17, 4, 0, 3/ begin call smark (yysp) call salloc (yyv, (YYMAXDEPTH+2) * YYOPLEN, TY_STRUCT) # Initialization. The first element of the dynamically allocated # token value stack (yyv) is used for yyval, the second for yylval, # and the actual stack starts with the third element. yystate = 0 yychar = -1 yynerrs = 0 yyerrflag = 0 yyps = 0 yyval = yyv yylval = yyv + YYOPLEN yypv = yylval yystack_ # SHIFT -- Put a state and value onto the stack. The token and # value stacks are logically the same stack, implemented as two # separate arrays. if (yydebug) { call printf ("state %d, char 0%o\n") call pargs (yystate) call pargi (yychar) } yyps = yyps + 1 yypv = yypv + YYOPLEN if (yyps > YYMAXDEPTH) { call sfree (yysp) call eprintf ("yacc stack overflow\n") return (ERR) } yys[yyps] = yystate YYMOVE (yyval, yypv) yynewstate_ # Process the new state. yyn = yypact[yystate+1] if (yyn <= YYFLAG) goto yydefault_ # simple state # The variable "yychar" is the lookahead token. if (yychar < 0) { yychar = yylex (fd, yylval) if (yychar < 0) yychar = 0 } yyn = yyn + yychar if (yyn < 0 || yyn >= YYLAST) goto yydefault_ yyn = yyact[yyn+1] if (yychk[yyn+1] == yychar) { # valid shift yychar = -1 YYMOVE (yylval, yyval) yystate = yyn if (yyerrflag > 0) yyerrflag = yyerrflag - 1 goto yystack_ } yydefault_ # Default state action. yyn = yydef[yystate+1] if (yyn == -2) { if (yychar < 0) { yychar = yylex (fd, yylval) if (yychar < 0) yychar = 0 } # Look through exception table. yyxi = 1 while ((yyexca[yyxi] != (-1)) || (yyexca[yyxi+1] != yystate)) yyxi = yyxi + 2 for (yyxi=yyxi+2; yyexca[yyxi] >= 0; yyxi=yyxi+2) { if (yyexca[yyxi] == yychar) break } yyn = yyexca[yyxi+1] if (yyn < 0) { call sfree (yysp) return (OK) # ACCEPT -- all done } } # SYNTAX ERROR -- resume parsing if possible. if (yyn == 0) { switch (yyerrflag) { case 0, 1, 2: if (yyerrflag == 0) { # brand new error call eprintf ("syntax error\n") yyerrlab_ yynerrs = yynerrs + 1 # fall through... } # case 1: # case 2: incompletely recovered error ... try again yyerrflag = 3 # Find a state where "error" is a legal shift action. while (yyps >= 1) { yyn = yypact[yys[yyps]+1] + YYERRCODE if ((yyn >= 0) && (yyn < YYLAST) && (yychk[yyact[yyn+1]+1] == YYERRCODE)) { # Simulate a shift of "error". yystate = yyact[yyn+1] goto yystack_ } yyn = yypact[yys[yyps]+1] # The current yyps has no shift on "error", pop stack. if (yydebug) { call printf ("error recovery pops state %d, ") call pargs (yys[yyps]) call printf ("uncovers %d\n") call pargs (yys[yyps-1]) } yyps = yyps - 1 yypv = yypv - YYOPLEN } # ABORT -- There is no state on the stack with an error shift. yyabort_ call sfree (yysp) return (ERR) case 3: # No shift yet; clobber input char. if (yydebug) { call printf ("error recovery discards char %d\n") call pargi (yychar) } if (yychar == 0) goto yyabort_ # don't discard EOF, quit yychar = -1 goto yynewstate_ # try again in the same state } } # REDUCE -- Reduction by production yyn. if (yydebug) { call printf ("reduce %d\n") call pargs (yyn) } yyps = yyps - yyr2[yyn+1] yypvt = yypv yypv = yypv - yyr2[yyn+1] * YYOPLEN YYMOVE (yypv + YYOPLEN, yyval) yym = yyn # Consult goto table to find next state. yyn = yyr1[yyn+1] yyj = yypgo[yyn+1] + yys[yyps] + 1 if (yyj >= YYLAST) yystate = yyact[yypgo[yyn+1]+1] else { yystate = yyact[yyj+1] if (yychk[yystate+1] != -yyn) yystate = yyact[yypgo[yyn+1]+1] } # Perform action associated with the grammar rule, if any. switch (yym) { case 1: # line 36 "addcompile.y" { # Normal exit. Code a stop instruction call addencode (Y_DONE) return (OK) } case 2: # line 41 "addcompile.y" { # Parser error return (ERR) } case 3: # line 47 "addcompile.y" { # Code an if_then_else instruction call addencode (Y_ELSE) } case 4: # line 51 "addcompile.y" { # Code an if_then instruction call addencode (Y_THEN) } case 5: # line 55 "addcompile.y" { # No action } case 6: # line 59 "addcompile.y" { # Code a push instruction call addencode (Y_PUSH) call addencode (Memi[yypvt]) } case 7: # line 64 "addcompile.y" { # Code a push constant instruction call addencode (Y_CONST) call addnumber (Memi[yypvt]) } case 8: # line 69 "addcompile.y" { # Code a logical and instruction call addencode (Y_AND) } case 9: # line 73 "addcompile.y" { # Code a logical or instruction call addencode (Y_OR) } case 10: # line 77 "addcompile.y" { # Code a logical negation instruction call addencode (Y_NOT) } case 11: # line 81 "addcompile.y" { # Code a equals instruction call addencode (Y_EQ) } case 12: # line 85 "addcompile.y" { # Code a not equals instruction call addencode (Y_NE) } case 13: # line 89 "addcompile.y" { # Code a less than instruction call addencode (Y_LT) } case 14: # line 93 "addcompile.y" { # Code a greater than instruction call addencode (Y_GT) } case 15: # line 97 "addcompile.y" { # Code a less than or equals instruction call addencode (Y_LE) } case 16: # line 101 "addcompile.y" { # Code a greater than or equals instruction call addencode (Y_GE) } case 17: # line 105 "addcompile.y" { # No action } case 18: # line 108 "addcompile.y" { # Lexical error call eprintf ("Unrecognized token (%s)\n") call pargstr (Memc[Memi[yypvt]]) call mfree (Memi[yypvt], TY_CHAR) return (ERR) } } goto yystack_ # stack new state and value end