2 * codegen - module to generate opcodes from the input tokens
4 * Copyright (C) 1999-2007 David I. Bell and Ernest Bowen
6 * Primary author: David I. Bell
8 * Calc is open software; you can redistribute it and/or modify it under
9 * the terms of the version 2.1 of the GNU Lesser General Public License
10 * as published by the Free Software Foundation.
12 * Calc is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
15 * Public License for more details.
17 * A copy of version 2.1 of the GNU Lesser General Public License is
18 * distributed with calc under the filename COPYING-LGPL. You should have
19 * received a copy with calc; if not, write to Free Software Foundation, Inc.
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 * @(#) $Revision: 30.4 $
23 * @(#) $Id: codegen.c,v 30.4 2013/08/11 08:41:38 chongo Exp $
24 * @(#) $Source: /usr/local/src/bin/calc/RCS/codegen.c,v $
26 * Under source code control: 1990/02/15 01:48:13
27 * File existed as early as: before 1990
29 * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
34 #include "have_unistd.h"
35 #if defined(HAVE_UNISTD_H)
49 #if defined(_WIN32) && !defined(__CYGWIN__)
53 STATIC BOOL rdonce
; /* TRUE => do not reread this file */
57 S_FUNC
int getsymvalue(char *name
, VALUE
*v_p
);
58 S_FUNC
int getfilename(char *name
, size_t namelen
, BOOL
*once
);
59 S_FUNC BOOL
getid(char *buf
);
60 S_FUNC
void getshowstatement(void);
61 S_FUNC
void getfunction(void);
62 S_FUNC
void ungetfunction(void);
63 S_FUNC
void getbody(LABEL
*contlabel
, LABEL
*breaklabel
,
64 LABEL
*nextcaselabel
, LABEL
*defaultlabel
);
65 S_FUNC
int getdeclarations(int symtype
);
66 S_FUNC
int getsimpledeclaration (int symtype
);
67 S_FUNC
int getonevariable (int symtype
);
68 S_FUNC
void getstatement(LABEL
*contlabel
, LABEL
*breaklabel
,
69 LABEL
*nextcaselabel
, LABEL
*defaultlabel
);
70 S_FUNC
void getobjdeclaration(int symtype
);
71 S_FUNC
void getoneobj(long index
, int symtype
);
72 S_FUNC
void getobjvars(char *name
, int symtype
);
73 S_FUNC
void getmatdeclaration(int symtype
);
74 S_FUNC
void getonematrix(int symtype
);
75 S_FUNC
void creatematrix(void);
76 S_FUNC
void getsimplebody(void);
77 S_FUNC
void getcondition(void);
78 S_FUNC
void getmatargs(void);
79 S_FUNC
void getelement(void);
80 S_FUNC
void usesymbol(char *name
, int autodef
);
81 S_FUNC
void definesymbol(char *name
, int symtype
);
82 S_FUNC
void getcallargs(char *name
);
83 S_FUNC
void do_changedir(void);
84 S_FUNC
int getexprlist(void);
85 S_FUNC
int getopassignment(void);
86 S_FUNC
int getassignment(void);
87 S_FUNC
int getaltcond(void);
88 S_FUNC
int getorcond(void);
89 S_FUNC
int getandcond(void);
90 S_FUNC
int getrelation(void);
91 S_FUNC
int getsum(void);
92 S_FUNC
int getproduct(void);
93 S_FUNC
int getorexpr(void);
94 S_FUNC
int getandexpr(void);
95 S_FUNC
int getshiftexpr(void);
96 S_FUNC
int getreference(void);
97 S_FUNC
int getincdecexpr(void);
98 S_FUNC
int getterm(void);
99 S_FUNC
int getidexpr(BOOL okmat
, int autodef
);
100 S_FUNC
long getinitlist(void);
104 STATIC
int quickindices
[INDICALLOC
];
105 STATIC
int * newindices
;
106 STATIC
int * indices
;
107 STATIC
int maxindices
;
111 * Read all the commands from an input file.
112 * These are either declarations, or else are commands to execute now.
113 * In general, commands are terminated by newlines or semicolons.
114 * Exceptions are function definitions and escaped newlines.
115 * Commands are read and executed until the end of file.
116 * The toplevel flag indicates whether we are at the top interactive level.
119 getcommands(BOOL toplevel
)
121 char name
[MAXCMD
+1+1]; /* program name */
125 name
[MAXCMD
+1] = '\0';
133 (void) tokenmode(TM_NEWLINES
);
134 switch (gettoken()) {
147 switch(getfilename(name
, MAXCMD
+1, NULL
)) {
151 strcpy(name
, DEFAULTCALCHELP
);
168 "read command disallowed by -m mode\n");
174 if (getfilename(name
, MAXCMD
+1, &rdonce
))
176 open_ret
= opensearchfile(name
,calcpath
,
184 /* prev read and -once was given */
188 "Maximum input depth reached");
192 "Cannot open \"%s\"", name
);
202 "write command disallowed by -m mode\n");
205 if (getfilename(name
, MAXCMD
+1, NULL
))
207 if (writeglobals(name
)) {
209 "Error writing \"%s\"\n", name
);
224 updateoldvalue(curfunc
);
228 run_state
= RUN_EXIT
;
229 else if (run_state
< RUN_PRE_TOP_LEVEL
)
230 run_state
= RUN_PRE_TOP_LEVEL
;
231 if (calc_use_scanerr_jmpbuf
!= 0) {
232 longjmp(calc_scanerr_jmpbuf
, 30);
235 "calc_scanerr_jmpbuf not setup, exiting code 30\n");
236 libcalc_call_me_last();
246 * Evaluate a line of statements.
247 * This is done by treating the current line as a function body,
248 * compiling it, and then executing it. Returns TRUE if the line
249 * successfully compiled and executed. The last expression result
250 * is saved in the f_savedvalue element of the current function.
251 * The nestflag variable should be FALSE for the outermost evaluation
252 * level, and TRUE for all other calls (such as the 'eval' function).
253 * The function name begins with an asterisk to indicate specialness.
256 * nestflag TRUE if this is a nested evaluation
259 evaluate(BOOL nestflag
)
262 int loop
= 1; /* 0 => end the main while loop */
264 funcname
= (nestflag
? "**" : "*");
265 beginfunc(funcname
, nestflag
);
266 if (gettoken() == T_LEFTBRACE
) {
267 getbody(NULL_LABEL
, NULL_LABEL
, NULL_LABEL
, NULL_LABEL
);
270 (void) tokenmode(TM_DEFAULT
);
273 switch (gettoken()) {
283 getstatement(NULL_LABEL
, NULL_LABEL
,
284 NULL_LABEL
, NULL_LABEL
);
293 calculate(curfunc
, 0);
298 * Undefine one or more functions
307 switch (gettoken()) {
311 name
= tokensymbol();
312 type
= getbuiltinfunc(name
);
315 "Cannot undefine builtin function \"%s\"", name
);
324 if (gettoken() != T_SYMBOL
) {
325 scanerror(T_SEMICOLON
,
326 "Non-identifier following \"undefine static\"");
329 name
= tokensymbol();
330 endscope(name
, FALSE
);
339 scanerror(T_SEMICOLON
, "Non-name arg for undefine");
347 * Get a function declaration.
348 * func = name '(' '' | name [ ',' name] ... ')' simplebody
349 * | name '(' '' | name [ ',' name] ... ')' body.
354 char *name
; /* parameter name */
355 int type
; /* type of token read */
359 (void) tokenmode(TM_DEFAULT
);
360 if (gettoken() != T_SYMBOL
) {
361 scanerror(T_NULL
, "Function name was expected");
364 name
= tokensymbol();
365 type
= getbuiltinfunc(name
);
367 scanerror(T_SEMICOLON
, "Using builtin function name");
370 beginfunc(name
, FALSE
);
372 if (gettoken() != T_LEFTPAREN
) {
373 scanerror(T_SEMICOLON
,
374 "Left parenthesis expected for function");
380 if (type
== T_RIGHTPAREN
)
382 if (type
!= T_SYMBOL
) {
384 "Using non-identifier as function parameter");
387 name
= tokensymbol();
388 switch (symboltype(name
)) {
392 index
= addparam(name
);
396 "Parameter \"%s\" is already defined",
400 if (type
== T_ASSIGN
) {
402 addopone(OP_PARAMADDR
, index
);
403 addoplabel(OP_JUMPNN
, &label
);
410 if (type
== T_RIGHTPAREN
)
412 if (type
!= T_COMMA
) {
414 "Using other than comma to separate parameters");
418 switch (gettoken()) {
423 getbody(NULL_LABEL
, NULL_LABEL
, NULL_LABEL
,
428 "Left brace or equals sign expected for function");
437 * Get a simple assignment style body for a function declaration.
438 * simplebody = '=' assignment '\n'.
443 (void) tokenmode(TM_NEWLINES
);
444 (void) getexprlist();
450 * Get the body of a function, or a subbody of a function.
451 * body = '{' [ declarations ] ... [ statement ] ... '}'
452 * | [ declarations ] ... [statement ] ... '\n'
456 getbody(LABEL
*contlabel
, LABEL
*breaklabel
, LABEL
*nextcaselabel
,
461 oldmode
= tokenmode(TM_DEFAULT
);
463 switch (gettoken()) {
465 (void) tokenmode(oldmode
);
469 scanerror(T_NULL
, "End-of-file in function body");
474 getstatement(contlabel
, breaklabel
,
475 nextcaselabel
, defaultlabel
);
482 * Get a line of possible local, global, or static variable declarations.
483 * declarations = { LOCAL | GLOBAL | STATIC } onedeclaration
484 * [ ',' onedeclaration ] ... ';'.
487 getdeclarations(int symtype
)
492 switch (gettoken()) {
504 addopone(OP_DEBUG
, linenumber());
506 if (getsimpledeclaration(symtype
))
511 addopone(OP_DEBUG
, linenumber());
512 getmatdeclaration(symtype
);
517 addopone(OP_DEBUG
, linenumber());
518 getobjdeclaration(symtype
);
524 scanerror(T_SEMICOLON
,
525 "Bad syntax in declaration statement");
533 * Get declaration of a sequence of simple identifiers, as in
534 * global a, b = 1, c d = 2, d;
535 * Subsequences end with "," or at end of line; spaces indicate
536 * repeated assignment, e.g. "c d = 2" has the effect of "c = 2, d = 2".
539 getsimpledeclaration(int symtype
)
544 switch (gettoken()) {
547 if (getonevariable(symtype
)) {
563 * Get one variable in a sequence of simple identifiers.
564 * Returns 1 if the subsequence in which the variable occurs ends with
565 * an assignment, e.g. for the variables b, c, d, in
566 * S_FUNC a, b = 1, c d = 2, d;
569 getonevariable(int symtype
)
576 name
= addliteral(tokensymbol());
577 res
= getonevariable(symtype
);
578 definesymbol(name
, symtype
);
581 addop(OP_ASSIGNBACK
);
596 * statement = IF condition statement [ELSE statement]
597 * | FOR '(' [assignment] ';' [assignment] ';' [assignment] ')' statement
598 * | WHILE condition statement
599 * | DO statement WHILE condition ';'
600 * | SWITCH condition '{' [caseclause] ... '}'
603 * | RETURN assignment ';'
605 * | PRINT assignment [, assignment ] ... ';'
606 * | QUIT [ string ] ';'
607 * | ABORT [ string ] ';'
611 * | label ':' statement
615 * contlabel label for continue statement
616 * breaklabel label for break statement
617 * nextcaselabel label for next case statement
618 * defaultlabel label for default case
621 getstatement(LABEL
*contlabel
, LABEL
*breaklabel
,
622 LABEL
*nextcaselabel
, LABEL
*defaultlabel
)
625 LABEL label1
, label2
, label3
, label4
; /* locations for jumps */
630 addopone(OP_DEBUG
, linenumber());
631 switch (gettoken()) {
637 (void) getdeclarations(SYM_GLOBAL
);
642 addoplabel(OP_INITSTATIC
, &label
);
643 if (getdeclarations(SYM_STATIC
))
646 curfunc
->f_opcodecount
-= 2;
650 (void) getdeclarations(SYM_LOCAL
);
658 scanerror(T_NULL
, "Extraneous right brace");
662 if (contlabel
== NULL_LABEL
) {
663 scanerror(T_SEMICOLON
,
664 "CONTINUE not within FOR, WHILE, or DO");
667 addoplabel(OP_JUMP
, contlabel
);
671 if (breaklabel
== NULL_LABEL
) {
672 scanerror(T_SEMICOLON
,
673 "BREAK not within FOR, WHILE, or DO");
676 addoplabel(OP_JUMP
, breaklabel
);
680 if (gettoken() != T_SYMBOL
) {
681 scanerror(T_SEMICOLON
, "Missing label in goto");
685 addlabel(tokensymbol());
689 switch (gettoken()) {
697 (void) getexprlist();
698 if (curfunc
->f_name
[0] == '*')
705 getbody(contlabel
, breaklabel
, nextcaselabel
, defaultlabel
);
714 if (contlabel
== NULL_LABEL
) {
715 scanerror(T_SEMICOLON
,
716 "CONTINUE not within FOR, "
720 addoplabel(OP_JUMPNZ
, contlabel
);
723 if (breaklabel
== NULL_LABEL
) {
724 scanerror(T_SEMICOLON
,
725 "BREAK not within FOR, "
729 addoplabel(OP_JUMPNZ
, breaklabel
);
732 if (gettoken() != T_SYMBOL
) {
733 scanerror(T_SEMICOLON
,
734 "Missing label in goto");
738 addlabel(tokensymbol());
741 addoplabel(OP_JUMPZ
, &label1
);
743 getstatement(contlabel
, breaklabel
,
744 NULL_LABEL
, NULL_LABEL
);
745 if (gettoken() != T_ELSE
) {
750 addoplabel(OP_JUMP
, &label2
);
752 getstatement(contlabel
, breaklabel
,
753 NULL_LABEL
, NULL_LABEL
);
757 if (gettoken() != T_SEMICOLON
) /* This makes ';' optional */
759 if (gettoken() != T_ELSE
) {
763 getstatement(contlabel
, breaklabel
, NULL_LABEL
, NULL_LABEL
);
766 case T_FOR
: /* for (a; b; c) x */
767 oldmode
= tokenmode(TM_DEFAULT
);
772 contlabel
= NULL_LABEL
;
773 breaklabel
= &label4
;
774 if (gettoken() != T_LEFTPAREN
) {
775 (void) tokenmode(oldmode
);
776 scanerror(T_SEMICOLON
, "Left parenthesis expected");
779 if (gettoken() != T_SEMICOLON
) { /* have 'a' part */
781 (void) getexprlist();
783 if (gettoken() != T_SEMICOLON
) {
784 (void) tokenmode(oldmode
);
785 scanerror(T_SEMICOLON
, "Missing semicolon");
789 if (gettoken() != T_SEMICOLON
) { /* have 'b' part */
793 (void) getexprlist();
794 addoplabel(OP_JUMPNZ
, &label3
);
795 addoplabel(OP_JUMP
, breaklabel
);
796 if (gettoken() != T_SEMICOLON
) {
797 (void) tokenmode(oldmode
);
798 scanerror(T_SEMICOLON
, "Missing semicolon");
802 if (gettoken() != T_RIGHTPAREN
) { /* have 'c' part */
803 if (label1
.l_offset
< 0)
804 addoplabel(OP_JUMP
, &label3
);
808 (void) getexprlist();
810 if (label1
.l_offset
>= 0)
811 addoplabel(OP_JUMP
, &label1
);
812 if (gettoken() != T_RIGHTPAREN
) {
813 (void) tokenmode(oldmode
);
814 scanerror(T_SEMICOLON
,
815 "Right parenthesis expected");
820 if (contlabel
== NULL_LABEL
)
822 (void) tokenmode(oldmode
);
823 getstatement(contlabel
, breaklabel
, NULL_LABEL
, NULL_LABEL
);
824 addoplabel(OP_JUMP
, contlabel
);
825 setlabel(breaklabel
);
829 oldmode
= tokenmode(TM_DEFAULT
);
831 clearlabel(contlabel
);
834 (void) tokenmode(oldmode
);
835 if (gettoken() != T_SEMICOLON
) {
836 breaklabel
= &label2
;
837 clearlabel(breaklabel
);
838 addoplabel(OP_JUMPZ
, breaklabel
);
840 getstatement(contlabel
, breaklabel
,
841 NULL_LABEL
, NULL_LABEL
);
842 addoplabel(OP_JUMP
, contlabel
);
843 setlabel(breaklabel
);
845 addoplabel(OP_JUMPNZ
, contlabel
);
850 oldmode
= tokenmode(TM_DEFAULT
);
852 breaklabel
= &label2
;
853 clearlabel(contlabel
);
854 clearlabel(breaklabel
);
857 getstatement(contlabel
, breaklabel
, NULL_LABEL
, NULL_LABEL
);
858 if (gettoken() != T_WHILE
) {
859 (void) tokenmode(oldmode
);
860 scanerror(T_SEMICOLON
,
861 "WHILE keyword expected for DO statement");
866 addoplabel(OP_JUMPNZ
, &label3
);
867 setlabel(breaklabel
);
868 (void) tokenmode(oldmode
);
872 oldmode
= tokenmode(TM_DEFAULT
);
873 breaklabel
= &label1
;
874 nextcaselabel
= &label2
;
875 defaultlabel
= &label3
;
876 clearlabel(breaklabel
);
877 clearlabel(nextcaselabel
);
878 clearlabel(defaultlabel
);
880 if (gettoken() != T_LEFTBRACE
) {
881 (void) tokenmode(oldmode
);
882 scanerror(T_SEMICOLON
,
883 "Missing left brace for switch statement");
886 addoplabel(OP_JUMP
, nextcaselabel
);
888 getstatement(contlabel
, breaklabel
,
889 nextcaselabel
, defaultlabel
);
890 addoplabel(OP_JUMP
, breaklabel
);
891 setlabel(nextcaselabel
);
892 if (defaultlabel
->l_offset
> 0)
893 addoplabel(OP_JUMP
, defaultlabel
);
896 setlabel(breaklabel
);
897 (void) tokenmode(oldmode
);
901 if (nextcaselabel
== NULL_LABEL
) {
902 scanerror(T_SEMICOLON
,
903 "CASE not within SWITCH statement");
907 addoplabel(OP_JUMP
, &label1
);
908 setlabel(nextcaselabel
);
909 clearlabel(nextcaselabel
);
910 (void) getexprlist();
911 if (gettoken() != T_COLON
) {
912 scanerror(T_SEMICOLON
,
913 "Colon expected after CASE expression");
916 addoplabel(OP_CASEJUMP
, nextcaselabel
);
918 getstatement(contlabel
, breaklabel
,
919 nextcaselabel
, defaultlabel
);
923 if (gettoken() != T_COLON
) {
924 scanerror(T_SEMICOLON
,
925 "Colon expected after DEFAULT keyword");
928 if (defaultlabel
== NULL_LABEL
) {
929 scanerror(T_SEMICOLON
,
930 "DEFAULT not within SWITCH statement");
933 if (defaultlabel
->l_offset
> 0) {
934 scanerror(T_SEMICOLON
,
935 "Multiple DEFAULT clauses in SWITCH");
939 addoplabel(OP_JUMP
, &label1
);
940 setlabel(defaultlabel
);
943 getstatement(contlabel
, breaklabel
,
944 nextcaselabel
, defaultlabel
);
948 scanerror(T_SEMICOLON
, "ELSE without preceding IF");
958 switch (gettoken()) {
972 addop(OP_PRINTSPACE
);
979 addopone(OP_PRINTSTRING
, tokenstring());
984 (void) getopassignment();
985 addopone(OP_PRINT
, (long) PRINT_NORMAL
);
990 switch (gettoken()) {
992 addopone(OP_QUIT
, tokenstring());
995 addopone(OP_QUIT
, -1);
1001 switch (gettoken()) {
1003 addopone(OP_ABORT
, tokenstring());
1006 addopone(OP_ABORT
, -1);
1012 if (nextchar() == ':') { /****HACK HACK****/
1013 definelabel(tokensymbol());
1014 if (gettoken() == T_RIGHTBRACE
) {
1019 getstatement(contlabel
, breaklabel
,
1020 NULL_LABEL
, NULL_LABEL
);
1024 /* fall into default case */
1028 type
= getexprlist();
1029 if (contlabel
|| breaklabel
|| (curfunc
->f_name
[0] != '*')) {
1034 if (isassign(type
) || (curfunc
->f_name
[1] != '\0')) {
1038 addop(OP_PRINTRESULT
);
1042 switch (gettoken()) {
1053 addopone(OP_NUMBER
, tokennumber());
1054 scanerror(T_NULL
, "Unexpected number");
1057 scanerror(T_NULL
, "Semicolon expected");
1065 * Read in an object declaration.
1066 * This is of the following form:
1067 * OBJ type [ '{' id [ ',' id ] ... '}' ] [ objlist ].
1068 * The OBJ keyword has already been read. Symtype is SYM_UNDEFINED if this
1069 * is an OBJ statement, otherwise this is part of a declaration which will
1070 * define new symbols with the specified type.
1073 getobjdeclaration(int symtype
)
1075 char *name
; /* name of object type */
1076 int count
; /* number of elements */
1077 int index
; /* current index */
1078 int i
; /* loop counter */
1081 if (gettoken() != T_SYMBOL
) {
1082 scanerror(T_SEMICOLON
, "Object type name missing");
1085 name
= addliteral(tokensymbol());
1086 if (gettoken() != T_LEFTBRACE
) {
1088 getobjvars(name
, symtype
);
1092 * Read in the definition of the elements of the object.
1095 indices
= quickindices
;
1096 maxindices
= INDICALLOC
;
1098 oldmode
= tokenmode(TM_DEFAULT
);
1101 switch (gettoken()) {
1103 if (count
== maxindices
) {
1104 if (maxindices
== INDICALLOC
) {
1105 maxindices
+= INDICALLOC
;
1106 newindices
= (int *) malloc(maxindices
*
1108 if (newindices
== NULL
) {
1109 scanerror(T_SEMICOLON
,
1110 "Out of memory for indices malloc");
1111 (void) tokenmode(oldmode
);
1114 memcpy(newindices
, quickindices
,
1115 INDICALLOC
* sizeof(int));
1116 indices
= newindices
;
1118 maxindices
+= INDICALLOC
;
1119 newindices
= (int *) realloc(indices
,
1120 maxindices
* sizeof(int));
1121 if (newindices
== NULL
) {
1123 scanerror(T_SEMICOLON
,
1124 "Out of memory for indices realloc");
1125 (void) tokenmode(oldmode
);
1128 indices
= newindices
;
1131 index
= addelement(tokensymbol());
1132 for (i
= 0; i
< count
; i
++) {
1133 if (indices
[i
] == index
) {
1134 if (indices
!= quickindices
)
1136 scanerror(T_SEMICOLON
,
1137 "Duplicate element name \"%s\"",
1139 (void) tokenmode(oldmode
);
1143 indices
[count
++] = index
;
1144 if (gettoken() == T_COMMA
)
1147 if (gettoken() != T_RIGHTBRACE
) {
1148 if (indices
!= quickindices
)
1150 scanerror(T_SEMICOLON
,
1151 "Bad object type definition");
1152 (void) tokenmode(oldmode
);
1157 (void) tokenmode(oldmode
);
1158 if (defineobject(name
, indices
, count
)) {
1159 if (indices
!= quickindices
)
1162 "Object type \"%s\" is already defined", name
);
1165 if (indices
!= quickindices
)
1167 getobjvars(name
, symtype
);
1172 if (indices
!= quickindices
)
1174 scanerror(T_SEMICOLON
, "Bad object type definition");
1175 (void) tokenmode(oldmode
);
1184 getoneobj(long index
, int symtype
)
1188 if (gettoken() == T_SYMBOL
) {
1189 if (symtype
== SYM_UNDEFINED
) {
1191 (void) getidexpr(TRUE
, 1);
1193 symname
= tokensymbol();
1194 definesymbol(symname
, symtype
);
1195 usesymbol(symname
, 0);
1197 getoneobj(index
, symtype
);
1202 addopone(OP_OBJCREATE
, index
);
1203 while (gettoken() == T_ASSIGN
)
1204 (void) getinitlist();
1209 * Routine to assign a specified object-type value to each of a set of
1210 * variables in a "global", "local" or "S_FUNC" declaration, or, if
1211 * symtype is SYM_UNDEFINED, to create one object value of the specified
1216 * symtype declaration type
1219 getobjvars(char *name
, int symtype
)
1221 long index
; /* index for object */
1223 index
= checkobject(name
);
1225 scanerror(T_SEMICOLON
,
1226 "Object %s has not been defined yet", name
);
1230 getoneobj(index
, symtype
);
1231 if (symtype
== SYM_UNDEFINED
)
1233 if (gettoken() != T_COMMA
) {
1243 getmatdeclaration(int symtype
)
1246 switch (gettoken()) {
1249 getonematrix(symtype
);
1263 getonematrix(int symtype
)
1268 unsigned long patchpc
;
1271 if (gettoken() == T_SYMBOL
) {
1272 if (symtype
== SYM_UNDEFINED
) {
1274 (void) getidexpr(FALSE
, 1);
1276 name
= tokensymbol();
1277 definesymbol(name
, symtype
);
1280 while (gettoken() == T_COMMA
);
1282 getonematrix(symtype
);
1288 if (gettoken() == T_LEFTPAREN
) {
1289 if (isrvalue(getexprlist())) {
1290 scanerror(T_SEMICOLON
, "Lvalue expected");
1293 if (gettoken() != T_RIGHTPAREN
) {
1294 scanerror(T_SEMICOLON
, "Missing right parenthesis");
1297 getonematrix(symtype
);
1303 if (gettoken() != T_LEFTBRACKET
) {
1305 scanerror(T_SEMICOLON
, "Left-bracket expected");
1311 * If there are no bounds given for the matrix, then they must be
1312 * implicitly defined by a list of initialization values. Put in
1313 * a dummy number in the opcode stream for the bounds and remember
1314 * its location. After we know how many values are in the list, we
1315 * will patch the correct value back into the opcode.
1317 if (gettoken() == T_RIGHTBRACKET
) {
1318 if (gettoken() == T_ASSIGN
) {
1320 patchpc
= curfunc
->f_opcodecount
+ 1;
1321 addopone(OP_NUMBER
, (long) -1);
1324 addopone(OP_MATCREATE
, dim
);
1328 count
= getinitlist();
1329 index
= addqconstant(itoq(count
));
1331 math_error("Cannot allocate constant");
1332 curfunc
->f_opcodes
[patchpc
] = index
;
1336 addopone(OP_MATCREATE
, 0);
1337 if (gettoken() == T_LEFTBRACKET
) {
1348 * This isn't implicit, so we expect expressions for the bounds.
1352 while (gettoken() == T_ASSIGN
)
1353 (void) getinitlist();
1366 if (gettoken() == T_RIGHTBRACKET
) {
1367 addopone(OP_MATCREATE
, dim
);
1368 if (gettoken() == T_LEFTBRACKET
) {
1378 if (++dim
> MAXDIM
) {
1379 scanerror(T_SEMICOLON
,
1380 "Only %d dimensions allowed", MAXDIM
);
1383 (void) getopassignment();
1384 switch (gettoken()) {
1385 case T_RIGHTBRACKET
:
1393 (void) getopassignment();
1394 switch(gettoken()) {
1395 case T_RIGHTBRACKET
:
1403 scanerror(T_SEMICOLON
,
1404 "Illegal matrix definition");
1412 * Get an optional initialization list for a matrix or object definition.
1413 * Returns the number of elements that are in the list, or -1 on parse error.
1414 * initlist = { assignment [ , assignment ] ... }.
1422 oldmode
= tokenmode(TM_DEFAULT
);
1424 if (gettoken() != T_LEFTBRACE
) {
1425 scanerror(T_SEMICOLON
,
1426 "Missing left brace for initialization list");
1427 (void) tokenmode(oldmode
);
1431 for (index
= 0; ; index
++) {
1432 switch(gettoken()) {
1437 (void) tokenmode(oldmode
);
1441 addop(OP_DUPLICATE
);
1442 addopone(OP_ELEMADDR
, index
);
1443 (void) getinitlist();
1449 addopone(OP_ELEMINIT
, index
);
1450 switch (gettoken()) {
1456 (void) tokenmode(oldmode
);
1460 scanerror(T_SEMICOLON
,
1461 "Missing right brace for initialization list");
1462 (void) tokenmode(oldmode
);
1471 * condition = '(' assignment ')'.
1476 if (gettoken() != T_LEFTPAREN
) {
1477 scanerror(T_SEMICOLON
,
1478 "Missing left parenthesis for condition");
1481 (void) getexprlist();
1482 if (gettoken() != T_RIGHTPAREN
) {
1483 scanerror(T_SEMICOLON
,
1484 "Missing right parenthesis for condition");
1491 * Get an expression list consisting of one or more expressions,
1492 * separated by commas. The value of the list is that of the final expression.
1493 * This is the top level routine for parsing expressions.
1494 * Returns flags describing the type of the last assignment or expression found.
1495 * exprlist = assignment [ ',' assignment ] ...
1502 type
= getopassignment();
1503 while (gettoken() == T_COMMA
) {
1505 type
= getopassignment();
1513 * Get an opassignment or possibly just an assignment or expression.
1514 * Returns flags describing the type of assignment or expression found.
1515 * assignment = lvalue '=' assignment
1516 * | lvalue '+=' assignment
1517 * | lvalue '-=' assignment
1518 * | lvalue '*=' assignment
1519 * | lvalue '/=' assignment
1520 * | lvalue '%=' assignment
1521 * | lvalue '//=' assignment
1522 * | lvalue '&=' assignment
1523 * | lvalue '|=' assignment
1524 * | lvalue '<<=' assignment
1525 * | lvalue '>>=' assignment
1526 * | lvalue '^=' assignment
1527 * | lvalue '**=' assignment
1531 getopassignment(void)
1533 int type
; /* type of expression */
1534 long op
; /* opcode to generate */
1536 type
= getassignment();
1537 switch (gettoken()) {
1538 case T_PLUSEQUALS
: op
= OP_ADD
; break;
1539 case T_MINUSEQUALS
: op
= OP_SUB
; break;
1540 case T_MULTEQUALS
: op
= OP_MUL
; break;
1541 case T_DIVEQUALS
: op
= OP_DIV
; break;
1542 case T_SLASHSLASHEQUALS
: op
= OP_QUO
; break;
1543 case T_MODEQUALS
: op
= OP_MOD
; break;
1544 case T_ANDEQUALS
: op
= OP_AND
; break;
1545 case T_OREQUALS
: op
= OP_OR
; break;
1546 case T_LSHIFTEQUALS
: op
= OP_LEFTSHIFT
; break;
1547 case T_RSHIFTEQUALS
: op
= OP_RIGHTSHIFT
; break;
1548 case T_POWEREQUALS
: op
= OP_POWER
; break;
1549 case T_HASHEQUALS
: op
= OP_HASHOP
; break;
1550 case T_TILDEEQUALS
: op
= OP_XOR
; break;
1551 case T_BACKSLASHEQUALS
: op
= OP_SETMINUS
; break;
1557 if (isrvalue(type
)) {
1558 scanerror(T_NULL
, "Illegal assignment");
1559 (void) getopassignment();
1560 return (EXPR_RVALUE
| EXPR_ASSIGN
);
1564 addop(OP_DUPLICATE
);
1565 if (gettoken() == T_LEFTBRACE
) {
1569 while (gettoken() == T_ASSIGN
)
1574 (void) getassignment();
1578 switch (gettoken()) {
1579 case T_PLUSEQUALS
: op
= OP_ADD
; break;
1580 case T_MINUSEQUALS
: op
= OP_SUB
; break;
1581 case T_MULTEQUALS
: op
= OP_MUL
; break;
1582 case T_DIVEQUALS
: op
= OP_DIV
; break;
1583 case T_SLASHSLASHEQUALS
: op
= OP_QUO
; break;
1584 case T_MODEQUALS
: op
= OP_MOD
; break;
1585 case T_ANDEQUALS
: op
= OP_AND
; break;
1586 case T_OREQUALS
: op
= OP_OR
; break;
1587 case T_LSHIFTEQUALS
: op
= OP_LEFTSHIFT
; break;
1588 case T_RSHIFTEQUALS
: op
= OP_RIGHTSHIFT
; break;
1589 case T_POWEREQUALS
: op
= OP_POWER
; break;
1590 case T_HASHEQUALS
: op
= OP_HASHOP
; break;
1591 case T_TILDEEQUALS
: op
= OP_XOR
; break;
1592 case T_BACKSLASHEQUALS
: op
= OP_SETMINUS
; break;
1603 * Get an assignment (lvalue = ...) or possibly just an expression
1607 getassignment (void)
1609 int type
; /* type of expression */
1611 switch(gettoken()) {
1616 case T_RIGHTBRACKET
:
1626 type
= getaltcond();
1628 switch (gettoken()) {
1631 addopone(OP_NUMBER
, tokennumber());
1632 type
= (EXPR_RVALUE
| EXPR_CONST
);
1641 scanerror(T_NULL
, "Missing operator");
1650 if (isrvalue(type
)) {
1651 scanerror(T_SEMICOLON
, "Illegal assignment");
1652 (void) getassignment();
1653 return (EXPR_RVALUE
| EXPR_ASSIGN
);
1656 if (gettoken() == T_LEFTBRACE
) {
1659 while (gettoken() == T_ASSIGN
)
1665 (void) getassignment();
1672 * Get a possible conditional result expression (question mark).
1673 * Flags are returned indicating the type of expression found.
1674 * altcond = orcond [ '?' orcond ':' altcond ].
1679 int type
; /* type of expression */
1680 LABEL donelab
; /* label for done */
1681 LABEL altlab
; /* label for alternate expression */
1684 if (gettoken() != T_QUESTIONMARK
) {
1688 clearlabel(&donelab
);
1689 clearlabel(&altlab
);
1690 addoplabel(OP_JUMPZ
, &altlab
);
1691 type
= getaltcond();
1692 if (gettoken() != T_COLON
) {
1693 scanerror(T_SEMICOLON
,
1694 "Missing colon for conditional expression");
1697 addoplabel(OP_JUMP
, &donelab
);
1699 type
|= getaltcond();
1706 * Get a possible conditional or expression.
1707 * Flags are returned indicating the type of expression found.
1708 * orcond = andcond [ '||' andcond ] ...
1713 int type
; /* type of expression */
1714 LABEL donelab
; /* label for done */
1716 clearlabel(&donelab
);
1717 type
= getandcond();
1718 while (gettoken() == T_OROR
) {
1719 addoplabel(OP_CONDORJUMP
, &donelab
);
1720 type
|= getandcond();
1723 if (donelab
.l_chain
>= 0)
1730 * Get a possible conditional and expression.
1731 * Flags are returned indicating the type of expression found.
1732 * andcond = relation [ '&&' relation ] ...
1737 int type
; /* type of expression */
1738 LABEL donelab
; /* label for done */
1740 clearlabel(&donelab
);
1741 type
= getrelation();
1742 while (gettoken() == T_ANDAND
) {
1743 addoplabel(OP_CONDANDJUMP
, &donelab
);
1744 type
|= getrelation();
1747 if (donelab
.l_chain
>= 0)
1754 * Get a possible relation (equality or inequality), or just an expression.
1755 * Flags are returned indicating the type of relation found.
1756 * relation = sum '==' sum
1767 int type
; /* type of expression */
1768 long op
; /* opcode to generate */
1771 switch (gettoken()) {
1772 case T_EQ
: op
= OP_EQ
; break;
1773 case T_NE
: op
= OP_NE
; break;
1774 case T_LT
: op
= OP_LT
; break;
1775 case T_GT
: op
= OP_GT
; break;
1776 case T_LE
: op
= OP_LE
; break;
1777 case T_GE
: op
= OP_GE
; break;
1791 * Get an expression made up of sums of products.
1792 * Flags indicating the type of expression found are returned.
1793 * sum = product [ {'+' | '-'} product ] ...
1798 int type
; /* type of expression found */
1799 long op
; /* opcode to generate */
1802 switch(gettoken()) {
1804 (void) getproduct();
1808 (void) getproduct();
1813 type
= getproduct();
1816 switch (gettoken()) {
1817 case T_PLUS
: op
= OP_ADD
; break;
1818 case T_MINUS
: op
= OP_SUB
; break;
1819 case T_HASH
: op
= OP_HASHOP
; break;
1826 (void) getproduct();
1834 * Get the product of arithmetic or expressions.
1835 * Flags indicating the type of expression found are returned.
1836 * product = orexpr [ {'*' | '/' | '//' | '%'} orexpr ] ...
1841 int type
; /* type of value found */
1842 long op
; /* opcode to generate */
1846 switch (gettoken()) {
1847 case T_MULT
: op
= OP_MUL
; break;
1848 case T_DIV
: op
= OP_DIV
; break;
1849 case T_MOD
: op
= OP_MOD
; break;
1850 case T_SLASHSLASH
: op
= OP_QUO
; break;
1865 * Get an expression made up of arithmetic or operators.
1866 * Flags indicating the type of expression found are returned.
1867 * orexpr = andexpr [ '|' andexpr ] ...
1872 int type
; /* type of value found */
1874 type
= getandexpr();
1875 while (gettoken() == T_OR
) {
1878 (void) getandexpr();
1888 * Get an expression made up of arithmetic and operators.
1889 * Flags indicating the type of expression found are returned.
1890 * andexpr = shiftexpr [ '&' shiftexpr ] ...
1895 int type
; /* type of value found */
1898 type
= getshiftexpr();
1900 switch (gettoken()) {
1901 case T_AND
: op
= OP_AND
; break;
1902 case T_TILDE
: op
= OP_XOR
; break;
1903 case T_BACKSLASH
: op
= OP_SETMINUS
; break;
1910 (void) getshiftexpr();
1918 * Get a shift or power expression.
1919 * Flags indicating the type of expression found are returned.
1926 * | reference '^' shiftexpr
1927 * | reference '<<' shiftexpr
1928 * | reference '>>' shiftexpr
1934 int type
; /* type of value found */
1935 long op
; /* opcode to generate */
1938 switch (gettoken()) {
1939 case T_PLUS
: op
= OP_PLUS
; break;
1940 case T_MINUS
: op
= OP_NEGATE
; break;
1941 case T_NOT
: op
= OP_NOT
; break;
1942 case T_DIV
: op
= OP_INVERT
; break;
1943 case T_BACKSLASH
: op
= OP_BACKSLASH
; break;
1944 case T_TILDE
: op
= OP_COMP
; break;
1945 case T_HASH
: op
= OP_CONTENT
; break;
1948 (void) getshiftexpr();
1953 type
= getreference();
1954 switch (gettoken()) {
1955 case T_POWER
: op
= OP_POWER
; break;
1956 case T_LEFTSHIFT
: op
= OP_LEFTSHIFT
; break;
1957 case T_RIGHTSHIFT
: op
= OP_RIGHTSHIFT
; break;
1964 (void) getshiftexpr();
1971 * set an address or dereference indicator
1972 * address = '&' term
1973 * dereference = '*' term
1980 switch(gettoken()) {
1982 scanerror(T_NULL
, "&& used as prefix operator");
1985 type
= getreference();
1990 (void) getreference();
1994 case T_POWER
: /* '**' or '^' */
1995 (void) getreference();
2002 type
= getincdecexpr();
2009 * get an increment or decrement expression
2010 * ++expr, --expr, expr++, expr--
2020 if (tok
== T_PLUSPLUS
|| tok
== T_MINUSMINUS
) {
2022 scanerror(T_NULL
, "Bad ++ usage");
2024 if (tok
== T_PLUSPLUS
)
2043 type
= EXPR_RVALUE
| EXPR_ASSIGN
;
2046 addopfunction(OP_CALL
, getbuiltinfunc("fact"), 1);
2056 * Get a single term.
2057 * Flags indicating the type of value found are returned.
2059 * | lvalue '[' assignment ']'
2063 * | imaginary_number
2066 * | '(' assignment ')'
2067 * | function [ '(' [assignment [',' assignment] ] ')' ]
2073 int type
; /* type of term found */
2077 switch (gettoken()) {
2079 addopone(OP_NUMBER
, tokennumber());
2080 type
= (EXPR_RVALUE
| EXPR_CONST
);
2084 addopone(OP_IMAGINARY
, tokennumber());
2085 type
= (EXPR_RVALUE
| EXPR_CONST
);
2094 addopone(OP_STRING
, tokenstring());
2099 if (isrvalue(getterm()))
2100 scanerror(T_NULL
, "Bad ++ usage");
2107 if (isrvalue(getterm()))
2108 scanerror(T_NULL
, "Bad -- usage");
2115 oldmode
= tokenmode(TM_DEFAULT
);
2116 type
= getexprlist();
2117 if (gettoken() != T_RIGHTPAREN
)
2118 scanerror(T_SEMICOLON
,
2119 "Missing right parenthesis");
2120 (void) tokenmode(oldmode
);
2124 getonematrix(SYM_UNDEFINED
);
2129 getobjdeclaration(SYM_UNDEFINED
);
2135 type
= getidexpr(TRUE
, 0);
2144 case T_POWER
: /* '**' or '^' */
2152 if (gettoken() != T_SYMBOL
) {
2154 "No identifier after global specifier");
2158 type
= getidexpr(TRUE
, T_GLOBAL
);
2162 if (gettoken() != T_SYMBOL
) {
2164 "No identifier after local specifier");
2168 type
= getidexpr(TRUE
, T_LOCAL
);
2172 if (gettoken() != T_SYMBOL
) {
2174 "No identifier after static specifier");
2178 type
= getidexpr(TRUE
, T_STATIC
);
2182 scanerror(T_NULL
, "Left bracket with no preceding lvalue");
2186 scanerror(T_NULL
, "Period with no preceding lvalue");
2190 if (iskeyword(type
)) {
2192 "Expression contains reserved keyword");
2196 scanerror(T_COMMA
, "Missing expression");
2200 switch (gettoken()) {
2212 "Function calls not allowed "
2225 * Read in an identifier expressions.
2226 * This is a symbol name followed by parenthesis, or by square brackets or
2227 * element references. The symbol can be a global or a local variable name.
2228 * Returns the type of expression found.
2231 getidexpr(BOOL okmat
, int autodef
)
2234 char name
[SYMBOLSIZE
+1]; /* symbol name */
2240 switch (gettoken()) {
2242 oldmode
= tokenmode(TM_DEFAULT
);
2244 (void) tokenmode(oldmode
);
2248 if (autodef
!= T_GLOBAL
&& autodef
!= T_LOCAL
&&
2249 autodef
!= T_STATIC
)
2251 /* fall into default case */
2254 usesymbol(name
, autodef
);
2257 * Now collect as many element references and matrix index operations
2258 * as there are following the id.
2261 switch (gettoken()) {
2278 "Function calls not allowed "
2289 * getsymvalue - return the VALUE of a symbol
2293 * v_p pointer to value return
2296 * symbol type found:
2298 * SYM_UNDEFINED no such symbol
2299 * SYM_GLOBAL global symbol found
2301 * NOTE: This is a special hack to allow some special code in getfilename()
2302 * to get the value of a symbol. It should NOT be used in the
2303 * general op code generation / calc code parsing case.
2306 getsymvalue(char *name
, VALUE
*v_p
)
2308 GLOBAL
*g_ret
; /* global return from findglobal() */
2311 if (name
== NULL
|| v_p
== NULL
) {
2312 return SYM_UNDEFINED
;
2315 /* look for a global */
2316 g_ret
= findglobal(name
);
2317 if (g_ret
!= NULL
) {
2318 *v_p
= g_ret
->g_value
;
2322 /* no such symbol */
2323 return SYM_UNDEFINED
;
2328 * Read in a filename for a read or write command.
2329 * Both quoted and unquoted filenames are handled here.
2330 * The name must be terminated by an end of line or semicolon.
2331 * Returns TRUE if the filename was successfully parsed.
2334 * name filename to read
2335 * namelen length of filename buffer including NUL byte
2336 * once non-NULL => set to TRUE of -once read
2339 getfilename(char *name
, size_t namelen
, BOOL
*once
)
2342 char *symstr
; /* symbol string */
2343 VALUE val
; /* value of the symbol */
2346 (void) tokenmode(TM_NEWLINES
| TM_ALLSYMS
);
2347 for (i
= 2; i
> 0; i
--) {
2348 switch (gettoken()) {
2351 /* use the value of the literal string */
2352 s
= findstring(tokenstring());
2353 strncpy(name
, s
->s_str
, namelen
-1);
2354 name
[namelen
-1] = '\0';
2360 /* get the symbol name */
2361 symstr
= tokensymbol();
2364 * special hack - symbols starting with $ are
2365 * treated as a global variable
2366 * instead of a literal string.
2368 if (symstr
[0] == '$') {
2370 if (getsymvalue(symstr
, &val
)) {
2371 if (val
.v_type
== V_STR
) {
2372 /* use symbol VALUE string */
2373 symstr
= val
.v_str
->s_str
;
2374 if (symstr
== NULL
) {
2376 "string value pointer is NULL!!");
2381 "a filename variable must be a string");
2385 math_error("no such global variable");
2390 /* return symbol name or value of global var string */
2391 strncpy(name
, symstr
, namelen
-1);
2392 name
[namelen
-1] = '\0';
2403 /* found something unexpected */
2408 /* deal with -once */
2409 if (i
== 2 && once
!= NULL
) {
2410 if ((*once
= !strcmp(name
, "-once")))
2420 * Read the show command to display useful information
2423 getshowstatement(void)
2428 switch (gettoken()) {
2430 strncpy(name
, tokensymbol(), 4);
2433 arg
= stringindex("buil\000"
2458 printf("SHOW command to be followed by at least ");
2459 printf("four letters of one of:\n");
2460 printf("\tblocks, builtin, config, constants, ");
2461 printf("custom, errors, files, functions,\n");
2462 printf("\tglobaltypes, objfunctions, objtypes, "
2463 "opcodes, sizes, ");
2464 printf("realglobals,\n");
2465 printf("\tstatics, numbers, redcdata, "
2466 "strings, literals\n");
2472 if (gettoken() != T_SYMBOL
) {
2474 scanerror(T_SEMICOLON
,
2475 "Function name expected for show statement");
2478 index
= adduserfunc(tokensymbol());
2479 addopone(OP_SHOW
, index
+ 19);
2483 addopone(OP_SHOW
, arg
);
2485 warning("Unknown parameter for show statement");
2490 * Read in a set of matrix index arguments, surrounded with square brackets.
2491 * This also handles double square brackets for 'fast indexing'.
2498 if (gettoken() != T_LEFTBRACKET
) {
2499 scanerror(T_NULL
, "Matrix indexing expected");
2503 * Parse all levels of the array reference
2504 * Look for the 'fast index' first.
2506 if (gettoken() == T_LEFTBRACKET
) {
2507 (void) getopassignment();
2508 if ((gettoken() != T_RIGHTBRACKET
) ||
2509 (gettoken() != T_RIGHTBRACKET
)) {
2510 scanerror(T_NULL
, "Bad fast index usage");
2518 * Normal indexing with the indexes separated by commas.
2519 * Initialize the flag in the opcode to assume that the array
2520 * element will only be referenced for reading. If the parser
2521 * finds that the element will be referenced for writing, then
2522 * it will call writeindexop to change the flag in the opcode.
2525 if (gettoken() == T_RIGHTBRACKET
) {
2526 addoptwo(OP_INDEXADDR
, (long) dim
, (long) FALSE
);
2532 (void) getopassignment();
2533 switch (gettoken()) {
2534 case T_RIGHTBRACKET
:
2535 addoptwo(OP_INDEXADDR
, (long) dim
,
2543 "Missing right bracket in "
2552 * Get an element of an object reference.
2553 * The leading period which introduces the element has already been read.
2559 char name
[SYMBOLSIZE
+1];
2563 index
= findelement(name
);
2565 scanerror(T_NULL
, "Element \"%s\" is undefined", name
);
2568 addopone(OP_ELEMADDR
, index
);
2573 * Read in a single symbol name and copy its value into the given buffer.
2574 * Returns TRUE if a valid symbol id was found.
2582 if (iskeyword(type
)) {
2583 scanerror(T_NULL
, "Reserved keyword used as symbol name");
2588 if (type
!= T_SYMBOL
) {
2590 scanerror(T_NULL
, "Symbol name expected");
2594 strncpy(buf
, tokensymbol(), SYMBOLSIZE
);
2595 buf
[SYMBOLSIZE
] = '\0';
2601 * Define a symbol name to be of the specified symbol type. The scope
2602 * of a static variable with the same name is terminated if symtype is
2603 * global or if symtype is static and the old variable is at the same
2604 * level. Warnings are issued when a global or local variable is
2605 * redeclared and when in the same body the variable will be accessible only
2606 ^ with the appropriate specfier.
2609 definesymbol(char *name
, int symtype
)
2611 switch (symboltype(name
)) {
2613 if (symtype
== SYM_GLOBAL
|| symtype
== SYM_STATIC
)
2614 endscope(name
, symtype
== SYM_GLOBAL
);
2617 if (symtype
== SYM_GLOBAL
&& conf
->redecl_warn
) {
2618 warning("redeclaration of global \"%s\"",
2625 if (symtype
== SYM_LOCAL
&& conf
->redecl_warn
) {
2626 warning("redeclaration of local \"%s\"",
2630 if (symtype
== SYM_GLOBAL
&& conf
->dupvar_warn
) {
2631 warning("both local and global \"%s\" defined", name
);
2634 if (conf
->dupvar_warn
) {
2635 warning("both local and static \"%s\" defined", name
);
2639 if (symtype
== SYM_LOCAL
&& conf
->dupvar_warn
) {
2640 warning("both local and parameter \"%s\" defined",
2644 if (symtype
== SYM_GLOBAL
&& conf
->dupvar_warn
) {
2645 warning("both global and parameter \"%s\" defined",
2649 if (conf
->dupvar_warn
) {
2650 warning("both static and parameter \"%s\" defined",
2654 if (symtype
== SYM_LOCAL
)
2655 (void) addlocal(name
);
2657 (void) addglobal(name
, (symtype
== SYM_STATIC
));
2662 * Check a symbol name to see if it is known and generate code to reference it.
2663 * The symbol can be either a parameter name, a local name, or a global name.
2664 * If autodef is true, we automatically define the name as a global symbol
2665 * if it is not yet known.
2668 * name symbol name to be checked
2669 * autodef 1 => define if symbol is not known
2670 * T_GLOBAL => get global, define if necessary
2673 usesymbol(char *name
, int autodef
)
2677 type
= symboltype(name
);
2678 if (autodef
== T_GLOBAL
) {
2679 if (type
== SYM_GLOBAL
) {
2680 warning("Unnecessary global specifier");
2682 addopptr(OP_GLOBALADDR
, (char *) addglobal(name
, FALSE
));
2685 if (autodef
== T_STATIC
) {
2686 addopptr(OP_GLOBALADDR
, (char *) addglobal(name
, TRUE
));
2689 if (autodef
== T_LOCAL
) {
2690 if (type
== SYM_LOCAL
) {
2691 warning("Unnecessary local specifier");
2693 addopone(OP_LOCALADDR
, addlocal(name
));
2698 addopone(OP_LOCALADDR
, (long) findlocal(name
));
2701 addopone(OP_PARAMADDR
, (long) findparam(name
));
2705 addopptr(OP_GLOBALADDR
, (char *) findglobal(name
));
2709 * The symbol is not yet defined.
2710 * If we are at the top level and we are allowed to, then define it.
2712 if ((curfunc
->f_name
[0] != '*') || !autodef
) {
2713 scanerror(T_NULL
, "\"%s\" is undefined", name
);
2716 (void) addglobal(name
, FALSE
);
2717 addopptr(OP_GLOBALADDR
, (char *) findglobal(name
));
2722 * Get arguments for a function call.
2723 * The name and beginning parenthesis has already been seen.
2724 * callargs = [ [ '&' ] assignment [',' [ '&' ] assignment] ] ')'.
2727 * name name of function
2730 getcallargs(char *name
)
2732 long index
; /* function index */
2733 long op
; /* opcode to add */
2734 int argcount
; /* number of arguments */
2738 index
= getbuiltinfunc(name
);
2741 index
= adduserfunc(name
);
2743 if (gettoken() == T_RIGHTPAREN
) {
2745 builtincheck(index
, 0);
2746 addopfunction(op
, index
, 0);
2753 if (gettoken() == T_RIGHTPAREN
) {
2756 builtincheck(index
, argcount
);
2757 addopfunction(op
, index
, argcount
);
2761 if (gettoken() == T_COMMA
) {
2766 addrflag
= (gettoken() == T_BACKQUOTE
);
2769 (void) getopassignment();
2773 if (!addrflag
&& (op
!= OP_CALL
))
2775 if (!strcmp(name
, "quomod") && argcount
> 2)
2777 switch (gettoken()) {
2780 builtincheck(index
, argcount
);
2781 addopfunction(op
, index
, argcount
);
2786 scanerror(T_SEMICOLON
,
2787 "Missing right parenthesis "
2788 "in function call");
2796 * Change the current directory. If no directory is given, assume home.
2804 /* look at the next token */
2805 (void) tokenmode(TM_NEWLINES
| TM_ALLSYMS
);
2807 /* determine the new directory */
2809 switch (gettoken()) {
2811 s
= findstring(tokenstring());
2822 fprintf(stderr
, "Cannot determine HOME directory\n");
2825 /* change to that directory */