mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
Release calc version 2.11.1
This commit is contained in:
222
codegen.c
222
codegen.c
@@ -1,11 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 1997 David I. Bell
|
||||
* Permission is granted to use, distribute, or modify this source,
|
||||
* provided that this copyright notice remains intact.
|
||||
* codegen - module to generate opcodes from the input tokens
|
||||
*
|
||||
* Module to generate opcodes from the input tokens.
|
||||
* Copyright (C) 1999 David I. Bell and Ernest Bowen
|
||||
*
|
||||
* Primary author: David I. Bell
|
||||
*
|
||||
* Calc is open software; you can redistribute it and/or modify it under
|
||||
* the terms of the version 2.1 of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* Calc is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
||||
* Public License for more details.
|
||||
*
|
||||
* A copy of version 2.1 of the GNU Lesser General Public License is
|
||||
* distributed with calc under the filename COPYING-LGPL. You should have
|
||||
* received a copy with calc; if not, write to Free Software Foundation, Inc.
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* @(#) $Revision: 29.1 $
|
||||
* @(#) $Id: codegen.c,v 29.1 1999/12/14 09:15:35 chongo Exp $
|
||||
* @(#) $Source: /usr/local/src/cmd/calc/RCS/codegen.c,v $
|
||||
*
|
||||
* Under source code control: 1990/02/15 01:48:13
|
||||
* File existed as early as: before 1990
|
||||
*
|
||||
* Share and enjoy! :-) http://reality.sgi.com/chongo/tech/comp/calc/
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "have_unistd.h"
|
||||
#if defined(HAVE_UNISTD_H)
|
||||
@@ -132,7 +156,8 @@ getcommands(BOOL toplevel)
|
||||
/* previously read and -once was given */
|
||||
break;
|
||||
case -2:
|
||||
scanerror(T_NULL, "Maximum input depth reached");
|
||||
scanerror(T_NULL,
|
||||
"Maximum input depth reached");
|
||||
break;
|
||||
default:
|
||||
scanerror(T_NULL, "Cannot open \"%s\"\n", name);
|
||||
@@ -149,7 +174,8 @@ getcommands(BOOL toplevel)
|
||||
break;
|
||||
}
|
||||
if (writeglobals(name))
|
||||
scanerror(T_NULL, "Error writing \"%s\"\n", name);
|
||||
scanerror(T_NULL,
|
||||
"Error writing \"%s\"\n", name);
|
||||
break;
|
||||
|
||||
case T_CD:
|
||||
@@ -157,6 +183,8 @@ getcommands(BOOL toplevel)
|
||||
break;
|
||||
case T_NEWLINE:
|
||||
case T_SEMICOLON:
|
||||
case T_POUNDBANG:
|
||||
case T_POUNDCOMMENT:
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -318,7 +346,9 @@ getfunction(void)
|
||||
index = addparam(name);
|
||||
break;
|
||||
default:
|
||||
scanerror(T_NULL, "Parameter \"%s\" is already defined", name);
|
||||
scanerror(T_NULL,
|
||||
"Parameter \"%s\" is already defined",
|
||||
name);
|
||||
}
|
||||
type = gettoken();
|
||||
if (type == T_ASSIGN) {
|
||||
@@ -348,7 +378,8 @@ getfunction(void)
|
||||
break;
|
||||
default:
|
||||
scanerror(T_NULL,
|
||||
"Left brace or equals sign expected for function");
|
||||
"Left brace or equals sign "
|
||||
"expected for function");
|
||||
return;
|
||||
}
|
||||
endfunc();
|
||||
@@ -393,7 +424,8 @@ getbody(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *defaul
|
||||
|
||||
default:
|
||||
rescantoken();
|
||||
getstatement(contlabel, breaklabel, nextcaselabel, defaultlabel);
|
||||
getstatement(contlabel, breaklabel,
|
||||
nextcaselabel, defaultlabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -442,7 +474,8 @@ getdeclarations(int symtype)
|
||||
break;
|
||||
|
||||
default:
|
||||
scanerror(T_SEMICOLON, "Bad syntax in declaration statement");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Bad syntax in declaration statement");
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -574,7 +607,8 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
|
||||
|
||||
case T_CONTINUE:
|
||||
if (contlabel == NULL_LABEL) {
|
||||
scanerror(T_SEMICOLON, "CONTINUE not within FOR, WHILE, or DO");
|
||||
scanerror(T_SEMICOLON,
|
||||
"CONTINUE not within FOR, WHILE, or DO");
|
||||
return;
|
||||
}
|
||||
addoplabel(OP_JUMP, contlabel);
|
||||
@@ -582,7 +616,8 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
|
||||
|
||||
case T_BREAK:
|
||||
if (breaklabel == NULL_LABEL) {
|
||||
scanerror(T_SEMICOLON, "BREAK not within FOR, WHILE, or DO");
|
||||
scanerror(T_SEMICOLON,
|
||||
"BREAK not within FOR, WHILE, or DO");
|
||||
return;
|
||||
}
|
||||
addoplabel(OP_JUMP, breaklabel);
|
||||
@@ -624,21 +659,26 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
|
||||
switch(gettoken()) {
|
||||
case T_CONTINUE:
|
||||
if (contlabel == NULL_LABEL) {
|
||||
scanerror(T_SEMICOLON, "CONTINUE not within FOR, WHILE, or DO");
|
||||
scanerror(T_SEMICOLON,
|
||||
"CONTINUE not within FOR, "
|
||||
"WHILE, or DO");
|
||||
return;
|
||||
}
|
||||
addoplabel(OP_JUMPNZ, contlabel);
|
||||
break;
|
||||
case T_BREAK:
|
||||
if (breaklabel == NULL_LABEL) {
|
||||
scanerror(T_SEMICOLON, "BREAK not within FOR, WHILE, or DO");
|
||||
scanerror(T_SEMICOLON,
|
||||
"BREAK not within FOR, "
|
||||
"WHILE, or DO");
|
||||
return;
|
||||
}
|
||||
addoplabel(OP_JUMPNZ, breaklabel);
|
||||
break;
|
||||
case T_GOTO:
|
||||
if (gettoken() != T_SYMBOL) {
|
||||
scanerror(T_SEMICOLON, "Missing label in goto");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Missing label in goto");
|
||||
return;
|
||||
}
|
||||
addop(OP_JUMPNZ);
|
||||
@@ -647,7 +687,8 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
|
||||
default:
|
||||
addoplabel(OP_JUMPZ, &label1);
|
||||
rescantoken();
|
||||
getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL);
|
||||
getstatement(contlabel, breaklabel,
|
||||
NULL_LABEL, NULL_LABEL);
|
||||
if (gettoken() != T_ELSE) {
|
||||
setlabel(&label1);
|
||||
rescantoken();
|
||||
@@ -655,7 +696,8 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
|
||||
}
|
||||
addoplabel(OP_JUMP, &label2);
|
||||
setlabel(&label1);
|
||||
getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL);
|
||||
getstatement(contlabel, breaklabel,
|
||||
NULL_LABEL, NULL_LABEL);
|
||||
setlabel(&label2);
|
||||
return;
|
||||
}
|
||||
@@ -716,7 +758,8 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
|
||||
addoplabel(OP_JUMP, &label1);
|
||||
if (gettoken() != T_RIGHTPAREN) {
|
||||
(void) tokenmode(oldmode);
|
||||
scanerror(T_SEMICOLON, "Right parenthesis expected");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Right parenthesis expected");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -761,7 +804,8 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
|
||||
getstatement(contlabel, breaklabel, NULL_LABEL, NULL_LABEL);
|
||||
if (gettoken() != T_WHILE) {
|
||||
(void) tokenmode(oldmode);
|
||||
scanerror(T_SEMICOLON, "WHILE keyword expected for DO statement");
|
||||
scanerror(T_SEMICOLON,
|
||||
"WHILE keyword expected for DO statement");
|
||||
return;
|
||||
}
|
||||
setlabel(contlabel);
|
||||
@@ -782,12 +826,14 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
|
||||
getcondition();
|
||||
if (gettoken() != T_LEFTBRACE) {
|
||||
(void) tokenmode(oldmode);
|
||||
scanerror(T_SEMICOLON, "Missing left brace for switch statement");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Missing left brace for switch statement");
|
||||
return;
|
||||
}
|
||||
addoplabel(OP_JUMP, nextcaselabel);
|
||||
rescantoken();
|
||||
getstatement(contlabel, breaklabel, nextcaselabel, defaultlabel);
|
||||
getstatement(contlabel, breaklabel,
|
||||
nextcaselabel, defaultlabel);
|
||||
addoplabel(OP_JUMP, breaklabel);
|
||||
setlabel(nextcaselabel);
|
||||
if (defaultlabel->l_offset > 0)
|
||||
@@ -800,7 +846,8 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
|
||||
|
||||
case T_CASE:
|
||||
if (nextcaselabel == NULL_LABEL) {
|
||||
scanerror(T_SEMICOLON, "CASE not within SWITCH statement");
|
||||
scanerror(T_SEMICOLON,
|
||||
"CASE not within SWITCH statement");
|
||||
return;
|
||||
}
|
||||
clearlabel(&label1);
|
||||
@@ -809,25 +856,30 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
|
||||
clearlabel(nextcaselabel);
|
||||
(void) getexprlist();
|
||||
if (gettoken() != T_COLON) {
|
||||
scanerror(T_SEMICOLON, "Colon expected after CASE expression");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Colon expected after CASE expression");
|
||||
return;
|
||||
}
|
||||
addoplabel(OP_CASEJUMP, nextcaselabel);
|
||||
setlabel(&label1);
|
||||
getstatement(contlabel, breaklabel, nextcaselabel, defaultlabel);
|
||||
getstatement(contlabel, breaklabel,
|
||||
nextcaselabel, defaultlabel);
|
||||
return;
|
||||
|
||||
case T_DEFAULT:
|
||||
if (gettoken() != T_COLON) {
|
||||
scanerror(T_SEMICOLON, "Colon expected after DEFAULT keyword");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Colon expected after DEFAULT keyword");
|
||||
return;
|
||||
}
|
||||
if (defaultlabel == NULL_LABEL) {
|
||||
scanerror(T_SEMICOLON, "DEFAULT not within SWITCH statement");
|
||||
scanerror(T_SEMICOLON,
|
||||
"DEFAULT not within SWITCH statement");
|
||||
return;
|
||||
}
|
||||
if (defaultlabel->l_offset > 0) {
|
||||
scanerror(T_SEMICOLON, "Multiple DEFAULT clauses in SWITCH");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Multiple DEFAULT clauses in SWITCH");
|
||||
return;
|
||||
}
|
||||
clearlabel(&label1);
|
||||
@@ -835,7 +887,8 @@ getstatement(LABEL *contlabel, LABEL *breaklabel, LABEL *nextcaselabel, LABEL *d
|
||||
setlabel(defaultlabel);
|
||||
addop(OP_POP);
|
||||
setlabel(&label1);
|
||||
getstatement(contlabel, breaklabel, nextcaselabel, defaultlabel);
|
||||
getstatement(contlabel, breaklabel,
|
||||
nextcaselabel, defaultlabel);
|
||||
return;
|
||||
|
||||
case T_ELSE:
|
||||
@@ -990,14 +1043,18 @@ getobjdeclaration(int symtype)
|
||||
switch (gettoken()) {
|
||||
case T_SYMBOL:
|
||||
if (count == MAXINDICES) {
|
||||
scanerror(T_SEMICOLON, "Too many elements in OBJ statement");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Too many elements in OBJ "
|
||||
"statement");
|
||||
(void) tokenmode(oldmode);
|
||||
return;
|
||||
}
|
||||
index = addelement(tokensymbol());
|
||||
for (i = 0; i < count; i++) {
|
||||
if (indices[i] == index) {
|
||||
scanerror(T_SEMICOLON, "Duplicate element name \"%s\"", tokensymbol());
|
||||
scanerror(T_SEMICOLON,
|
||||
"Duplicate element name "
|
||||
"\"%s\"", tokensymbol());
|
||||
(void) tokenmode(oldmode);
|
||||
return;
|
||||
}
|
||||
@@ -1007,7 +1064,8 @@ getobjdeclaration(int symtype)
|
||||
continue;
|
||||
rescantoken();
|
||||
if (gettoken() != T_RIGHTBRACE) {
|
||||
scanerror(T_SEMICOLON, "Bad object type definition");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Bad object type definition");
|
||||
(void) tokenmode(oldmode);
|
||||
return;
|
||||
}
|
||||
@@ -1024,7 +1082,8 @@ getobjdeclaration(int symtype)
|
||||
case T_NEWLINE:
|
||||
continue;
|
||||
default:
|
||||
scanerror(T_SEMICOLON, "Bad object type definition");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Bad object type definition");
|
||||
(void) tokenmode(oldmode);
|
||||
return;
|
||||
}
|
||||
@@ -1073,7 +1132,8 @@ getobjvars(char *name, int symtype)
|
||||
|
||||
index = checkobject(name);
|
||||
if (index < 0) {
|
||||
scanerror(T_SEMICOLON, "Object %s has not been defined yet", name);
|
||||
scanerror(T_SEMICOLON,
|
||||
"Object %s has not been defined yet", name);
|
||||
return;
|
||||
}
|
||||
for (;;) {
|
||||
@@ -1226,7 +1286,8 @@ creatematrix(void)
|
||||
}
|
||||
rescantoken();
|
||||
if (++dim > MAXDIM) {
|
||||
scanerror(T_SEMICOLON, "Only %ld dimensions allowed", MAXDIM);
|
||||
scanerror(T_SEMICOLON,
|
||||
"Only %ld dimensions allowed", MAXDIM);
|
||||
return;
|
||||
}
|
||||
(void) getopassignment();
|
||||
@@ -1249,7 +1310,8 @@ creatematrix(void)
|
||||
/*FALLTHRU*/
|
||||
default:
|
||||
rescantoken();
|
||||
scanerror(T_SEMICOLON, "Illegal matrix definition");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Illegal matrix definition");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1304,7 +1366,8 @@ getinitlist(void)
|
||||
return index;
|
||||
|
||||
default:
|
||||
scanerror(T_SEMICOLON, "Bad initialization list");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Bad initialization list");
|
||||
(void) tokenmode(oldmode);
|
||||
return -1;
|
||||
}
|
||||
@@ -1320,12 +1383,14 @@ static void
|
||||
getcondition(void)
|
||||
{
|
||||
if (gettoken() != T_LEFTPAREN) {
|
||||
scanerror(T_SEMICOLON, "Missing left parenthesis for condition");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Missing left parenthesis for condition");
|
||||
return;
|
||||
}
|
||||
(void) getexprlist();
|
||||
if (gettoken() != T_RIGHTPAREN) {
|
||||
scanerror(T_SEMICOLON, "Missing right parenthesis for condition");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Missing right parenthesis for condition");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1534,7 +1599,8 @@ getaltcond(void)
|
||||
addoplabel(OP_JUMPZ, &altlab);
|
||||
type = getaltcond();
|
||||
if (gettoken() != T_COLON) {
|
||||
scanerror(T_SEMICOLON, "Missing colon for conditional expression");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Missing colon for conditional expression");
|
||||
return EXPR_RVALUE;
|
||||
}
|
||||
addoplabel(OP_JUMP, &donelab);
|
||||
@@ -1945,7 +2011,8 @@ getterm(void)
|
||||
oldmode = tokenmode(TM_DEFAULT);
|
||||
type = getexprlist();
|
||||
if (gettoken() != T_RIGHTPAREN)
|
||||
scanerror(T_SEMICOLON, "Missing right parenthesis");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Missing right parenthesis");
|
||||
(void) tokenmode(oldmode);
|
||||
break;
|
||||
|
||||
@@ -1974,7 +2041,8 @@ getterm(void)
|
||||
|
||||
default:
|
||||
if (iskeyword(type)) {
|
||||
scanerror(T_NULL, "Expression contains reserved keyword");
|
||||
scanerror(T_NULL,
|
||||
"Expression contains reserved keyword");
|
||||
break;
|
||||
}
|
||||
rescantoken();
|
||||
@@ -1993,7 +2061,9 @@ getterm(void)
|
||||
type = 0;
|
||||
break;
|
||||
case T_LEFTPAREN:
|
||||
scanerror(T_NULL, "Function calls not allowed as expressions");
|
||||
scanerror(T_NULL,
|
||||
"Function calls not allowed "
|
||||
"as expressions");
|
||||
default:
|
||||
rescantoken();
|
||||
return type;
|
||||
@@ -2055,7 +2125,9 @@ getidexpr(BOOL okmat, BOOL autodef)
|
||||
type = 0;
|
||||
break;
|
||||
case T_LEFTPAREN:
|
||||
scanerror(T_NULL, "Function calls not allowed as expressions");
|
||||
scanerror(T_NULL,
|
||||
"Function calls not allowed "
|
||||
"as expressions");
|
||||
default:
|
||||
rescantoken();
|
||||
return type;
|
||||
@@ -2153,11 +2225,31 @@ getshowstatement(void)
|
||||
case T_SYMBOL:
|
||||
strncpy(name, tokensymbol(), 4);
|
||||
name[4] = '\0';
|
||||
arg = stringindex("buil\000real\000func\000objf\000conf\000objt\000file\000size\000erro\000cust\000bloc\000cons\000glob\000stat\000numb\000redc\000stri\000lite\000opco\000", name);
|
||||
/* Yuck! */
|
||||
arg = stringindex("buil\000"
|
||||
"real\000"
|
||||
"func\000"
|
||||
"objf\000"
|
||||
"conf\000"
|
||||
"objt\000"
|
||||
"file\000"
|
||||
"size\000"
|
||||
"erro\000"
|
||||
"cust\000"
|
||||
"bloc\000"
|
||||
"cons\000"
|
||||
"glob\000"
|
||||
"stat\000"
|
||||
"numb\000"
|
||||
"redc\000"
|
||||
"stri\000"
|
||||
"lite\000"
|
||||
"opco\000", name);
|
||||
if (arg == 19) {
|
||||
if (gettoken() != T_SYMBOL) {
|
||||
rescantoken();
|
||||
scanerror(T_SEMICOLON, "Function name expected");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Function name expected");
|
||||
return;
|
||||
}
|
||||
index = adduserfunc(tokensymbol());
|
||||
@@ -2174,9 +2266,11 @@ getshowstatement(void)
|
||||
printf("four letters of one of:\n");
|
||||
printf("\tblocks, builtin, config, constants, ");
|
||||
printf("custom, errors, files, functions,\n");
|
||||
printf("\tglobaltypes, objfunctions, objtypes, opcodes, sizes, ");
|
||||
printf("\tglobaltypes, objfunctions, objtypes, "
|
||||
"opcodes, sizes, ");
|
||||
printf("realglobals,\n");
|
||||
printf("\tstatics, numbers, redcdata, strings, literals\n");
|
||||
printf("\tstatics, numbers, redcdata, "
|
||||
"strings, literals\n");
|
||||
rescantoken();
|
||||
return;
|
||||
|
||||
@@ -2237,7 +2331,9 @@ getmatargs(void)
|
||||
break;
|
||||
default:
|
||||
rescantoken();
|
||||
scanerror(T_NULL, "Missing right bracket in array reference");
|
||||
scanerror(T_NULL,
|
||||
"Missing right bracket in "
|
||||
"array reference");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2321,7 +2417,8 @@ definesymbol(char *name, int symtype)
|
||||
return;
|
||||
/*FALLTHRU*/
|
||||
case SYM_PARAM:
|
||||
scanerror(T_COMMA, "Variable \"%s\" is already defined", name);
|
||||
scanerror(T_COMMA,
|
||||
"Variable \"%s\" is already defined", name);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2431,7 +2528,9 @@ getcallargs(char *name)
|
||||
case T_COMMA:
|
||||
break;
|
||||
default:
|
||||
scanerror(T_SEMICOLON, "Missing right parenthesis in function call");
|
||||
scanerror(T_SEMICOLON,
|
||||
"Missing right parenthesis "
|
||||
"in function call");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2475,4 +2574,25 @@ do_changedir(void)
|
||||
}
|
||||
|
||||
|
||||
/* END CODE */
|
||||
/*
|
||||
* getshellfile - process the contents of a shellfile
|
||||
*/
|
||||
void
|
||||
getshellfile(char *shellfile)
|
||||
{
|
||||
/*
|
||||
* treat the calc shell script as if we were reading it
|
||||
*/
|
||||
if (!allow_read) {
|
||||
scanerror(T_NULL,
|
||||
"reading of calc shell script \"%s\" "
|
||||
"dislloaed by -m mode\n", shellfile);
|
||||
} else if (opensearchfile(shellfile, NULL, NULL, FALSE) == 0) {
|
||||
getcommands(FALSE);
|
||||
closeinput();
|
||||
} else {
|
||||
scanerror(T_NULL,
|
||||
"Cannot open calc shell script \"%s\"\n", shellfile);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user