/************************************************************************
 *                       code.c                                         *
 ************************************************************************
 *   Code Generation Routines (General)                                 *
 ************************************************************************
 *   Part of the project : BASCY  Version 1.0                           *
 *   Copyright (C) 2001 - S. Narasimhan, No.11, Sathya Nagar,           *
 *                        MADURAI-625018. INDIA                         *
 *                       email: narasimhan_s_@hotmail.com               *
 ************************************************************************
 * This program is free software; you can redistribute it and/or modify *
 * it under the terms of the GNU General Public License as published by *
 * the Free Software Foundation; either version 2 of the License, or    *
 * (at your option) any later version.                                  *
 *                                                                      *
 * This program 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 General Public License for more details.                         *
 *                                                                      *
 * You should have received a copy of the GNU General Public License    *
 * along with this program; if not, write to the Free Software          *
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            *
 *                                                                      *
 ************************************************************************/
#include <string.h>
#include "basic.h"
#define  LS_SIZE  40
extern unsigned int lincount, linestart, forcount, whilecount;
extern unsigned int docount, gosubcount, retcount, prvlinestart;
extern int AlreadyDefined;
extern int NeedSource;
extern FILE *fin, *fout, *ftmp, *ffun;
extern char word[];
extern char indent[];
extern struct symbol symtab[];
static struct ndx *ndxlist = 0; /* linked list of loop index variables */
static FUNCTION  *FunList = 0;  /* Linked List of Functions */
static ARRAY  *ArrList = 0;     /* Linked List of Arrays */
int LoopStack[LS_SIZE];
char exprstr[MAXWORDLEN];
int multibranch = FALSE;
int Looptr = 0;
int coniocount = 0;
int remstat(void)
/* Flush rest of the input line */
{
	char  c;
        while ((c = getc(fin)) != '\n' && c != EOF)
		;
	if (c == '\n') {
		linestart = TRUE;
	}
        ungetc(c,fin);
        return 0;
} /* End - remstat */
int ifprc(void)
/* Translates the statement IF <expr> THEN <label> | <statement list>
 * Also translates the      IF <expr> THEN
 * part of BLOCK IF */
{
        int nxtoken ,AftThen;
        static int ifcount = 0;
        nxtoken = expr();
        if(nxtoken < 0) {
                error(252);
                return -1;
        }
        if(strcmp(word, "THEN") != 0) {
                error(240);
                return -1;
        }
        EmitSource();
        switch(nxtoken) {
                case NUMBER :
                case NUMVAR :fprintf(ftmp, "\n%sif(%s) {",indent, exprstr);
                             fflush(ftmp);
                             SetIndent();
                             ifcount++;
                             break;
                case STRVAR : error(13);
                              return -1;
        }
        /* Examine the token following 'THEN' */
        if((AftThen = lex()) < 0) return -1;
        /* Is LF(\n) or comment(\') follows 'THEN' */
        if(AftThen == '\n' || AftThen == '\'') {
           /* If so, it is start of BLOCK IF.
            * But BLOCK IF should be the first statement of the line
            */
           if(!prvlinestart) {
              strcpy(word, "IF");
              error(205); return -1;
           }
           if(pushloop(BLOCKIF) < 0) return -1;
           /* ifcount (counter for single line IF statement)
            * had been incremented already for BLOCK IF also
            * So, adjust it now by decrementing it */
           ifcount--;
           ungetc(word[0], fin); /*Push back the char. to be parsed later */
           return 0;             /* and quit this procedure */
        }
        else { /* it is Single Line IF statement */
           /* Push back the token into the Input Stream */
           if(AftThen == NUMVAR || AftThen == STRVAR){
              /* and Undo the insertion of the VAR. into the
               * Symbol Table */
               int i, uval;
               i = lookup(word);
               uval = symtab[i].u.ival;
               if(uval == 0)
                  symtab[i].name = 0;
           }   
           if(AftThen == STRING)
             ungetc('"', fin);
           ungetw(word, fin);
           if(AftThen == STRING)
             ungetc('"', fin);
           /* and proceed with this procedure */
        }
        do {
          nxtoken = lex() ;
          switch(nxtoken) {
             case STATKEY : if(statement() < 0)
                               return -1;
                            break;
              case NUMARR :
              case STRARR :
              case NUMVAR :
              case STRVAR : asgn1();
                            break;
              case BUILTIN  :
              case OTHERKEY :
              case STRING   : error(246);
                              return -1;
              case NUMBER : /* Stat of form IF <expr> THEN <label> */ 
                           ungetw(word, fin); /*Push back the label into the Input stream */
                           multibranch = FALSE;
                           if(gotoprc() < 0) /* & call GOTO statement module */
                              return -1;
                           break;
              case '\'' : remstat();
                          break;
              case '\n' : lincount++ ; linestart = TRUE ;
                          break;
               case ':'  : 
               case  0   : break;
               default :
                          error(246);
                          return -1;
          } /*switch */
	} while(nxtoken != '\n');
        while(ifcount > 0) {
                DeIndent();
                fprintf(ftmp,"\n%s}",indent);
                fflush(ftmp);
                ifcount--;
        }
        return 0;
} /* ifprc */

int elseprc(void)
/* Translates the ELSE statement of BLOCK IF/THEN/ELSE/ENDIF structure
 */
{
   int iftyp;
   /* Examine the top of stack */
   pushloop(iftyp = poploop());
   /* If it is not BLOCKIF, we have encountered the error
    * ELSE without IF */
   if(iftyp != BLOCKIF) {
     error(206); return -1;
   }
   /* For BLOCK IF, ELSE should be the first token of the line */
   if(!prvlinestart) {
      error(205); return -1;
   }
   /* Code generation */
   EmitSource();
   DeIndent();
   fprintf(ftmp, "\n%s}",indent); /* Terminate the previous block */
   fprintf(ftmp, "\n%selse {",indent); /* & start a block for ELSE */
   SetIndent();
   fflush(ftmp);
   return 0;
} /* elseprc */

int elseifprc(void)
/* Translates the "ELSEIF condition THEN"
 * part of the BLOCK IF/THEN/ELSE/ENDIF structure */
{
   int exprtyp,iftyp;
   /* Examine the top of stack */
   pushloop(iftyp = poploop());
   /* If it is not BLOCKIF, we have encountered the error
    * ELSE without IF */
   if(iftyp != BLOCKIF) {
     error(206); return -1;
   }
   /* ELSEIF should be the first token of the line */
   if(!prvlinestart) {
      error(205); return -1;
   }
   if((exprtyp = expr()) < 0){
       error(252);
       return -1;
   }
   if(strcmp(word, "THEN") != 0) {
       error(240);
       return -1;
   }
   /* Code Generation */
   EmitSource();
   switch(exprtyp) {
       case NUMBER :
       case NUMVAR :DeIndent();
                    fprintf(ftmp, "\n%s}",indent); /* Terminate previous block */
                    fprintf(ftmp, "\n%selse if(%s) {",indent, exprstr);
                    fflush(ftmp);
                    SetIndent();
                    break;
       case STRVAR : error(13);
                     return -1;
   }
   return 0;
} /* elseifprc */

int endifprc(void)
/* Translates the statement "ENDIF" or "END IF" of BLOCK IF/THEN/ELSE/ENDIF
 * structure */
{
   int nxtoken, iftyp;
   /* END IF should occur at the beginning of line */
   if(!prvlinestart){
     strcpy(word, "END IF");
     error(205); return -1;
   }
   /*The top of stack should be BLOCKIF and it should be removed from stack */
   iftyp = poploop();
   if(iftyp != BLOCKIF) {
      error(204); return -1;
   }
   /* <End-of-Statement> should follow ENDIF */
   if((nxtoken = lex()) < 0) return -1;
   if(!StatEnd(nxtoken)) {
      error(251); return -1;
   }
   ungetc(word[0], fin);
   /* Code Generation */
   EmitSource();
   DeIndent();
   fprintf(ftmp,"\n%s}",indent); /* Terminate the block */
   fflush(ftmp);
   return 0;
} /* endifprc() */

int swaprc(void)
/*Translates the statement SWAP <var1>, <var2>   */
{
        int nxtoken, var1type;
        char *var1;
        var1type = nxtoken = lex();
        vardec(word);
        if(var1type == NUMARR || var1type == STRARR){
           if(arr2var() < 0) return -1;
        }
        var1 = strdup(word);
        if(var1 == 0) { error(249); return -1;}
        EmitSource();
        fprintf(ftmp, "\n%s{",indent);
        SetIndent();
        switch(nxtoken) {
                case NUMARR :
                case NUMVAR : fprintf(ftmp, "\n%sdouble tmp;",indent);
                              fprintf(ftmp, "\n%stmp=%s;",indent, word);
                              break;
                case STRARR :
                case STRVAR : fprintf(ftmp, "\n%schar tmp[MAXSTRLEN+1];",indent);
                              fprintf(ftmp, "\n%sstrcpy(tmp, %s);",indent, word);
                              break;
                default  : error(242);
                           return -1;
        }
        fflush(ftmp);
        if(lex() != ',') {
                error(236);
                return -1;
        }
        nxtoken = lex();
        vardec(word);
        if(nxtoken == NUMARR || nxtoken == STRARR){
           if(arr2var() < 0) return -1;
        }
        switch(nxtoken) {
                case NUMARR :
                case NUMVAR : if(var1type == STRVAR || var1type == STRARR){
                                error(13);
                                return -1;
                              }
                              fprintf(ftmp, "\n%s%s = %s;",indent, var1, word);
                              fprintf(ftmp, "\n%s%s = tmp;",indent, word);
                              break;
                case STRARR :
                case STRVAR : if(var1type == NUMVAR || var1type == NUMARR){
                                error(13);
                                return -1;
                              }
                              fprintf(ftmp, "\n%sstrcpy(%s,%s);",indent, var1, word);
                              fprintf(ftmp, "\n%sstrcpy(%s,tmp);",indent, word);
                              break;
                default  : error(242);
                           return -1;
        }
        DeIndent();
        fprintf(ftmp, "\n%s}",indent);
        fflush(ftmp);
	nxtoken = lex(); /* what is the next token */
        if ((nxtoken != '\n') && (nxtoken != 0) && (nxtoken != ':') &&
            (nxtoken != '\'')) {  /* it is not
                                   * end of line, EOF, ':', QUOTE */
             error(251);          /*if so print error*/
             return(-1);
        }
        ungetc(nxtoken, fin);
        free(var1);
        return 0;
}  /*end - swaprc */
int letprc(void)
/* Function to translate the statement LET <var> = <expr>
 * Calls asgn1() */
{
        int nxtoken;
        nxtoken = lex();
        if (nxtoken == -1)
                return -1;
        if ((nxtoken == STRVAR) || (nxtoken == NUMVAR) ||
            (nxtoken == STRARR) || (nxtoken == NUMARR))
                return(asgn1());
        else {
                error(242);
                return -1;
        }
}  /* end - letprc */

int endprc(void)
/* Translates the statements - END  or  END IF  */
{
   int nxtoken;
   if((nxtoken = lex()) < 0) return -1;
   /* whether IF follows END */
   if(strcmp(word,"IF") == 0)
      return(endifprc());
   else{
      if(!StatEnd(nxtoken)){
        error(2); return -1;
      }
      ungetc(word[0], fin);
      return(haltprc());
   }
} /* endprc */

int haltprc(void)
/* Translates the END statement or STOP statement */
{
        EmitSource();
        fprintf(ftmp, "\n%sexit(0);",indent);
        fflush(ftmp);
        return 0;
}   /* end - haltprc */
int cls(void)
/* Function to translate the CLS statement  */
{
	int nxtoken;
	nxtoken = lex(); /* what is the next token */
        if ((nxtoken != '\n') && nxtoken != 0 && nxtoken != ':' && nxtoken != '\'') {  /* it is not
                                          end of line, EOF, ':', QUOTE */
		 	error(251);     /*if so print error*/
		 	return(-1);
        }
        ungetc(nxtoken, fin); 
        EmitSource();
        fprintf(ftmp,"\n%s{int  i;",indent);
        fprintf(ftmp,"\n%s for(i = 25; i > 0; i--)",indent);
        fprintf(ftmp,"\n%s\tputchar('\\n');",indent);
        fprintf(ftmp,"\n%s}",indent);
        fflush(ftmp);
	return(0);
} /* end - cls */
int beep(void)
/* To translate the BEEP statement */
{
	int nxtoken;
	nxtoken = lex(); /* what is the next token */
        if ((nxtoken != '\n') && nxtoken != 0 && nxtoken != ':' && nxtoken != '\'') {  /* it is not
                                          end of line, EOF, ':', QUOTE */
		 	error(251);     /*if so print error*/
		 	return(-1);
        }
        ungetc(nxtoken, fin);
        EmitSource();
        fprintf(ftmp,"\n%sprintf(\"\\007\");\n",indent);
        fflush(ftmp);
        return 0;
}   /* end - beep */
int gotoprc(void)
/* To translate the GOTO <label> statement */
{
        int nxtoken, s, t;
        nxtoken = lex();
        if (nxtoken != NUMBER) {
                error(245); /* label expected */
                return -1;
        }
        if ((t = lookup(word)) < 0) { /* Referred label is not already defined*/
             s = instal(word, LABEL, lincount);
             if (s < 0) {    /*symbol table full */
                error(248);
                return -1;
             }
        }
        else { /* If label is defined, what is its u.ival */
                int val;
                val = symtab[t].u.ival;
                if (val < 0)  /*Label defined earlier now being referred*/
                        symtab[t].u.ival = 0;
        }
        if(!multibranch)
            EmitSource();
        lblconv(word);
        fprintf(ftmp, "%sgoto _%s;",indent, word);
        fflush(ftmp);
        if(!multibranch) {
          nxtoken = lex(); /* what is the next token */
          if ((nxtoken != '\n') && nxtoken != 0 && nxtoken != ':' && nxtoken != '\'') {  /* it is not
                                          end of line, EOF, ':', QUOTE */
		 	error(251);     /*if so print error*/
		 	return(-1);
          }
          ungetc(nxtoken, fin);
        }
        return 0;
}   /* end - gotoprc */
int gosubprc(void)
/* Translates the statement GOSUB  <label>   */
{
        int nxtoken,s, t;
        gosubcount++;
        nxtoken = lex();
        if (nxtoken != NUMBER) {
                error(245); /* label expected */
                return -1;
        }
        if(!multibranch)
            EmitSource();
        if ((t = lookup(word)) < 0) { /* Referred label is not already defined*/
             s = instal(word, PROC, lincount);
             if (s < 0) {    /*symbol table full */
                error(248);
                return -1;
             }
        }
        else { /* If label is defined, what is its u.ival */
                int val, typ;
                val = symtab[t].u.ival;
                typ = symtab[t].type;
                if (val < 0)  { /*Label defined earlier now being referred*/
                        symtab[t].u.ival = 0;
                        symtab[t].type   = PROC;
                }
                else {
                      if (typ != PROC) { /* Label of GOTO referred in GOSUB */
                          error(231);
                          return -1;
                      }
                }
        }
        fprintf(ftmp, "\n%sif(setjmp(rtnstack[pushret()]) == 0)",indent);
        fflush(ftmp);
        SetIndent();
        lblconv(word);
        fprintf(ftmp, "\n%sgoto _%s;",indent, word);
        fflush(ftmp);
        DeIndent();
        if(!multibranch) {
          nxtoken = lex(); /* what is the next token */
          if ((nxtoken != '\n') && nxtoken != 0 && nxtoken != ':' && nxtoken != '\'') {  /* it is not
                                          end of line, EOF, ':', QUOTE */
		 	error(251);     /*if so print error*/
		 	return(-1);
          }
          ungetc(nxtoken, fin);
        }
        return 0;
} /* end of gosubprc() */
int returnprc(void)
/* Translates the statement RETURN of GOSUB ... RETURN construct */
{
        int nxtoken;
        EmitSource();
        retcount++;
        fprintf(ftmp, "\n%slongjmp(rtnstack[popret()],1);",indent);
        fflush(ftmp);
        nxtoken = lex(); /* what is the next token */
        if ((nxtoken != '\n') && nxtoken != 0 && nxtoken != ':' && nxtoken != '\'') {  /* it is not
                                          end of line, EOF, ':', QUOTE */
                      error(251);     /*if so print error*/
                      return(-1);
        }
        ungetc(nxtoken, fin);
        return 0;
} /* end of returnprc() */
void labelprc(void)
/* Translates the statement Label/ Line number */
{
        lblconv(word);
       /* The ; added below to permit labelled null statements
        * Otherwise error will result while compiling the translated
        * C-file */
        fprintf(ftmp, "\n%s_%s:;",indent, word);
        fflush(ftmp);
}  /* End - labelprc() */
int onprc(void)
/* Translates the statements ON <expr> GOTO <lbl1>[,<lbl2>]...
 *                       and ON <expr> GOSUB <lbl1>[,<lbl2>]...  */
{
        int nxtoken, lblptr, gototrack;
        multibranch = TRUE;
        lblptr = 1;
        EmitSource();
        if((nxtoken = expr()) < 0) {
                error(252);  
                return -1;
        }
        if((nxtoken == STRING) || (nxtoken == STRVAR)) {
                error(13);
                return -1;
        }
        if(strcmp(word,"GOTO")  == 0)
                gototrack = TRUE;
        else {
             if(strcmp(word,"GOSUB") == 0)
                gototrack = FALSE;
             else {
                error(240);
                return -1;
             }
        }
        fprintf(ftmp,"\n%sif((%s) < 0) {",indent,exprstr);
        fflush(ftmp);
        SetIndent();
        if(gototrack == TRUE)
           fprintf(ftmp,"\n%sfprintf(stderr, \"\\nOut of bounds in ON ... GOTO statement in line-%d\");",indent,lincount);
        else
           fprintf(ftmp,"\n%sfprintf(stderr, \"\\nOut of bounds in ON ... GOSUB statement in line-%d\");",indent,lincount);
        fprintf(ftmp,"\n%sexit(1);",indent);
        DeIndent();
        fprintf(ftmp,"\n%s}",indent);
        fflush(ftmp);
        fprintf(ftmp, "\n%sswitch((int) %s) {",indent, exprstr);
        fflush(ftmp);
        SetIndent();
        do {
            fprintf(ftmp,"\n%scase %d :",indent, lblptr);
            fflush(ftmp);
            if(gototrack == TRUE) {
                if(gotoprc() < 0)  return -1;
            }
            else {
                if(gosubprc() < 0) return -1;
            }
            if(gototrack == FALSE) { /* ON ... GOSUB track */
                fprintf(ftmp,"\n%s     break;",indent);
                fflush(ftmp);
            }
            lblptr++;
            nxtoken = lex();
            if (nxtoken != ',') 
              if ((nxtoken != '\n') && nxtoken != 0 && nxtoken != ':' && nxtoken != '\'') {  /* it is not
                                          end of line, EOF, ':', QUOTE */
                error(241);
                return -1;
              }
        }while((nxtoken != '\n') && nxtoken != 0 && nxtoken != ':' && nxtoken != '\'');
        ungetc(nxtoken, fin);
        fprintf(ftmp,"\n%sdefault : break;",indent);
        DeIndent();
        fprintf(ftmp,"\n%s}",indent);
        fflush(ftmp);
        multibranch = FALSE;
        return 0;
}  /* End - onprc() */
int asgn1(void)
/* Translates the assignment statement of form - <var> = <expr> */
{
        int nxtoken, i, uval, typ, lhs, rhs;
        char *lhsvar;
        i = lookup(word);
        typ = symtab[i].type;
        if(typ == NUMARR || typ == STRARR) {
          if(arr2var() < 0) return -1;
        }
        uval = symtab[i].u.ival;
        lhs = typ;
        strvarconv(word);
        if (uval == 0) {
                if (typ == STRVAR)
                        fprintf(fout,"\nchar %s[MAXSTRLEN + 1] = \"\";", word);
                else if(typ == NUMVAR)
                        fprintf(fout,"\ndouble %s = 0.0 ;", word);
                fflush(fout);
        }
        EmitSource();
        if (lhs == NUMVAR || lhs == NUMARR)
                fprintf(ftmp,"\n%s%s",indent, word);
        else  {/* if STRVAR || STRARR */
                lhsvar = strdup(word);
                if(lhsvar == 0) { error(249); return -1;}
        }
        fflush(ftmp);
        if((nxtoken = lex()) < 0) return -1;
        if (nxtoken != '=') {
                error(243);
                return -1;
        }
        if (lhs == NUMVAR || lhs == NUMARR) {
                fputs(" = " , ftmp);
                fflush(ftmp);
        }
        if ((rhs = expr()) < 0) {
                error(252);  
         	return -1;
        }
        switch(rhs) {
                case NUMVAR :
                case NUMBER : if (lhs == STRVAR || lhs == STRARR){
                                  error(13);
                                  return -1;
                              }
                              fprintf(ftmp,"%s", exprstr);
                              fputs(";", ftmp);
                              break;
                case STRVAR : if (lhs == NUMVAR || lhs == NUMARR) {
                                error(13);
                                return -1;
                              }
                              fprintf(ftmp, "\n%sstrcpy(%s,_tmp_);",indent, lhsvar);
                              fprintf(ftmp, "\n%sstrcpy(_tmp_,\"\");",indent);
                              free(lhsvar);
                              break;
        }
        fflush(ftmp);
        nxtoken = word[0]; /* what is the next token */
        if ((nxtoken != '\n') && nxtoken != 0 && nxtoken != ':' && nxtoken != '\'') {  /* it is not
                                          end of line, EOF, ':', QUOTE */
		 	error(251);     /*if so print error*/
		 	return(-1);
    }
        ungetc(nxtoken, fin);
        return 0;
} /* End - asgn1() */

int forprc(void)
/* Translates the statement : FOR <var> = <exp1> TO <exp2> [STEP <exp3>] */
/* Nested FORs permitted. But index variables should be different */
{
        int nxtoken;
        char ndxvar[MAXIDLEN];
        char *EndExp, *IncExp;
        struct ndx *np;
        forcount++;
        if(pushloop(FORLOOP) < 0)  return -1;
        nxtoken = lex();
        if(nxtoken != NUMVAR) {
                error(242);
                return -1;
        }
        vardec(word);
	if(!validndx(word)) {  /* If the index var. is in the list,it is error*/
                error(233);
                return -1;
        }
	np = (struct ndx *) emalloc(sizeof(struct ndx));/* Add the index var to list*/
        if(np == 0) return -1; /* If out of memory, return error */
        strcpy(np->name, word);
        np->next = ndxlist;
        ndxlist = np;
        EmitSource();
        fprintf(ftmp, "\n%sfor(%s = ",indent, word);
        fflush(ftmp);
        strcpy(ndxvar, word);
        if(lex() != '=') {
                error(243);
                return -1;
        }
        nxtoken = expr(); /* Get starting value */
        if (nxtoken < 0) {
                error(252);  
         	return -1;
        }
        if(nxtoken == STRVAR) {
                error(13);
                return -1;
        }
        fprintf(ftmp, "%s;", exprstr);
        fflush(ftmp);
        if(strcmp(word, "TO") != 0) {
                error(240); /* keyword missing */
                return -1;
        }
        nxtoken = expr();  /* Get Ending Value */
        if (nxtoken < 0) {
                error(252);  
         	return -1;
        }
        if(nxtoken == STRVAR) {
                error(13);
                return -1;
        }
        EndExp = strdup(exprstr);
        if(EndExp == 0) return -1;
        nxtoken = word[0];
        if ((nxtoken == '\n') || (nxtoken == 0) || (nxtoken == ':') ||
	    (nxtoken == '\'')) {  /* STEP clause is absent */
                fprintf(ftmp,"%s <= %s;", ndxvar, EndExp);
                fprintf(ftmp,"%s++){", ndxvar);  /*If so, increment is 1 */
                SetIndent();
                fflush(ftmp);
        }
        else { /* should be STEP clause */
                if(strcmp(word, "STEP") != 0) {
                        error(240); /* keyword missing */
                        return -1;
                }
                nxtoken = expr(); /* Get Step / Increment Value */
                if (nxtoken < 0) {
                        error(252);  
                        return -1;
                }
                if(nxtoken == STRVAR) {
                        error(13);
                        return -1;
                }
                IncExp = strdup(exprstr);
                if(IncExp == 0) return -1;
                fprintf(ftmp, "/*Loop condition tested inside loop*/;");
                fprintf(ftmp, "%s += (%s)){", ndxvar, exprstr);
                SetIndent();
                fprintf(ftmp, "\n%s/* Loop condition */",indent);
                fprintf(ftmp, "\n%sif((%s) > 0.0 && (%s) > (%s)) break;",indent, IncExp, ndxvar, EndExp);
                fprintf(ftmp, "\n%sif((%s) < 0.0 && (%s) < (%s)) break;",indent, IncExp, ndxvar, EndExp);  
                fflush(ftmp);
                nxtoken = word[0];
                if ((nxtoken != '\n') && (nxtoken != 0) && 
                    (nxtoken != ':') && (nxtoken != '\'')) {  /* it is not
                                        *  end of line, EOF, ':', QUOTE */
                        error(251);     /*if so error*/
                        return(-1);
                }
                free(IncExp);
        }/*end of else part of if*/
        free(EndExp);
        ungetc(nxtoken, fin);
        return 0;
} /* end of forprc() */

int nextprc(void)
/* Translates NEXT statement of FOR loop */
/* Syntax : NEXT [<var>] [,<var>] ...    */
{
        int nxtoken;
        struct ndx *np;
        EmitSource();
        if(poploop() != FORLOOP) { error(234); return -1; }
        if((nxtoken = lex()) < 0) return -1;
        if(StatEnd(nxtoken)){ /* Plain NEXT statement */
           np = ndxlist;
           ndxlist = np->next; /* remove the recent index var from the list */
           free(np);   
           if(forcount > 0) {
                DeIndent();
                fprintf(ftmp, "\n%s} /*End of FOR-%d */",indent, forcount);
                fflush(ftmp);
                forcount--;
           }
           else { /* NEXT statement encountered without FOR statement */
                error(234);
                return -1;
           }
        } /* Plain NEXT */
        else{  /* Form : NEXT <var> [,<var>] ... */
           do {
              if(nxtoken != NUMVAR && nxtoken != STRVAR) {
                 error(242); return -1;
              }
              /* Examine the <var> with recent index var from the list */
              np = ndxlist;
              if(strcmp(word, np->name) != 0) { /* NEXT without FOR */
                 error(234); return -1;
              }
              ndxlist = np->next;
              free(np);
              if(forcount > 0) {
                DeIndent();
                fprintf(ftmp, "\n%s} /*End of FOR-%d */",indent, forcount);
                fflush(ftmp);
                forcount--;
              }
              else { /* NEXT statement encountered without FOR statement */
                error(234);
                return -1;
              }
              if((nxtoken = lex()) < 0) return -1;
              if(StatEnd(nxtoken)) break;
              if(nxtoken != ',') {
                error(2); return -1;
              }
              if((nxtoken = lex()) < 0) return -1;
           }while(1 == 1);
        } /* End of code for NEXT <var> */
        ungetc(word[0], fin);
        return 0;
}  /* End - nextprc() */
int validndx(char *word)
/* look-up if the index var. is already in use
 * If so, return FALSE
 * If not, return TRUE
 */
{
        struct ndx *ndxptr;
	for(ndxptr = ndxlist; ndxptr != (struct ndx *) 0; ndxptr = ndxptr->next)
                if(strcmp(ndxptr->name, word) == 0)
                        return FALSE;
        return TRUE;
}  /* End - validndx() */
int whileprc(void)
/* Translates the statement : WHILE <numeric-expression> */
/* Nested WHILEs permitted.  */
{
    whilecount++;
    if(pushloop(WHILELOOP) < 0) return -1;
    EmitSource();
    {
        int exprtype;
        exprtype = expr();
        if (exprtype < 0) {
                strcpy(word,"WHILE"); 
                error(252);  /* Expression expected after WHILE */
         	return -1;
        }
        if(exprtype == STRVAR) {
                error(13);  /*Type mismatch */
                return -1;
        }
        fprintf(ftmp, "\n%swhile(%s) {",indent, exprstr);
        SetIndent();
        fflush(ftmp);
    }
    {
        int nxtoken = word[0];
        if ((nxtoken != '\n') && (nxtoken != 0) && 
            (nxtoken != ':') && (nxtoken != '\'')) {  /* it is not
                                     *  end of line, EOF, ':', QUOTE */
                    error(251);     /*if so error*/
                    return(-1);
        }
        ungetc(nxtoken, fin);
    }
    return 0;
} /* end - whileprc() */
int wendprc(void)
/* Translates the WEND statement of WHILE loop */
{
        int nxtoken;
        if(poploop() != WHILELOOP) { error(224); return -1; }
        nxtoken = lex();
        if ((nxtoken != '\n') && (nxtoken != 0) && (nxtoken != ':') &&
            (nxtoken != '\'')) {  /* it is not
                                   *  end of line, EOF, ':', QUOTE */
             error(251);     /*if so error*/
             return(-1);
        }
        ungetc(nxtoken, fin);
        EmitSource();
        if(whilecount > 0) {
                DeIndent();
                fprintf(ftmp, "\n%s} /*End of WHILE-%d */",indent, whilecount);
                fflush(ftmp);
                whilecount--;
        }
        else { /* WEND statement encountered without WHILE statement */
                error(224);
                return -1;
        }
        return 0;
} /* end - wendprc() */
void lblconv(char *word)
/* Converts the label - word from BASIC syntax to C syntax as under :
 * _ is inserted as the 1st char of the label
 * Digits of the BASIC label are appended to the _
 *The . of the BASIC label is converted into _
 */
{
        for(; *word != '\0' ;  word++)
                if (*word == '.')
                        *word = '_';
}  /* End - lblconv() */
void strvarconv(char *word)
/* Converts the String Var name - word from BASIC syntax to C Syntax
 * as under : The terminal '$' of BASIC String Var name is replaced
 * by _
 */
{
   int n;
   n = strlen(word) - 1;
   if(word[n] == '$')
      word[n] = '_';
} /* End - strvarconv */

void vardec(char *s)
/* Tests whether the var in s has already been declared
 * If not, it adds the declaration for the variable and
 * sets the u.ival of the symbol table appropriately */
{
        int i, uval, typ;
        i = lookup(s);
        if (i >= 0) {
                typ = symtab[i].type;
                uval = symtab[i].u.ival;
                strvarconv(s);
                if (uval == 0) { /* Means the VAR is not declared so far */
                        if (typ == STRVAR)
                           fprintf(fout,"\nchar %s[MAXSTRLEN + 1] = \"\";", s);
                        else if(typ == NUMVAR)
                           fprintf(fout,"\ndouble %s = 0.0 ;", s);
                        fflush(fout);
                        symtab[i].u.ival = lincount;
                }
        }
} /* End - vardec() */

int randomprc(void)
/* Translates the RANDOMIZE statement
 * Syntax : RANDOMIZE <numeric expr.> | RANDOMIZE TIMER */
{
        int exprtype, nxtoken;
        EmitSource();
        exprtype = expr();
        if (exprtype < 0) {
            strcpy(word,"RANDOMIZE"); 
            error(252);  /* Expression expected after RANDOMIZE */
            return -1;
        }
        if(exprtype == STRVAR || exprtype == STRING) {
           strcpy(word,"RANDOMIZE"); 
           error(13);  /*Type mismatch */
           return -1;
        }
        if(libcode("ABS") < 0) return -1;
        fprintf(ftmp,"\n%ssrand((unsigned int)(ABS(%s)));",indent,exprstr);
        fflush(ftmp);
        nxtoken = word[0];
        if ((nxtoken != '\n') && (nxtoken != 0) && 
            (nxtoken != ':') && (nxtoken != '\'')) {  /* it is not
                                     *  end of line, EOF, ':', QUOTE */
                    error(251);     /*if so error*/
                    return(-1);
        }
        ungetc(nxtoken, fin);
        return 0;
} /* end - randomprc */
int pushloop(int n)
/* Push the loop type on the LoopStack */
{
        if(Looptr < LS_SIZE)
           LoopStack[Looptr++] = n;
        else {
           error(223); return -1;
        }
        return 0;
} /* End - pushloop() */
int poploop(void)
{
        int n;
        if(Looptr > 0)
           n = LoopStack[--Looptr];
        else
           n = -1;
        return(n);
}  /* End - poploop() */
int doprc(void)
/* Translates the statement - DO [{WHILE | UNTIL} condition] */
{
    int nxtoken; 
    docount++;
    EmitSource();
    nxtoken = lex();
    if ((nxtoken != '\n') && (nxtoken != 0) && 
        (nxtoken != ':') && (nxtoken != '\'')) {  
        /* It is conditional DO */                             
      if(pushloop(TOPDOLOOP) < 0) return -1;
      if(strcmp(word, "WHILE") == 0){
         if(whilooprc(1) < 0) return -1;
      }
      else if(strcmp(word, "UNTIL") == 0){
             if(untilooprc(1) < 0) return -1;
      }
      else {
         strcpy(word,"DO");
         error(240);
         return -1;
      }
      nxtoken = word[0];
    }
    else {  /* Plain DO statement without condition */
        if(pushloop(DOLOOP) < 0) return -1;
        fprintf(ftmp, "\n%sdo{ /* DO - %d */",indent, docount);
        SetIndent();
        fflush(ftmp);
    }
    if ((nxtoken != '\n') && (nxtoken != 0) && 
        (nxtoken != ':') && (nxtoken != '\'')) {  /* it is not
                                     *  end of line, EOF, ':', QUOTE */
             error(251);     /*if so error*/
             return(-1);
    }
    ungetc(nxtoken, fin);
    return 0;
} /* end - doprc() */
int whilooprc(int i)
/* Translates the WHILE clause of DO / LOOP statements
 * If i = 1, it is part of DO statement
 * If i = 2, it is part of LOOP statement*/
{
    int exprtype;
    exprtype = expr();
    if (exprtype < 0) {
          strcpy(word,"WHILE"); 
          error(252);  /* Expression expected after WHILE */
          return -1;
    }
    if(exprtype == STRVAR) {
           error(13);  /*Type mismatch */
           return -1;
    }
    if(i == 1) {/* DO WHILE statement */
       fprintf(ftmp, "\n%swhile(%s) {/* DO-%d */",indent, exprstr,docount);
       SetIndent();
    }
    else if(i == 2) {/* LOOP WHILE statement */
       DeIndent();
       fprintf(ftmp, "\n%s} while(%s);/* DO-%d */",indent, exprstr,docount);
    }
    fflush(ftmp);
    return 0;
} /*End - whilooprc */
int untilooprc(int i)
/* Translates the UNTIL clause of DO / LOOP statements
 * If i = 1, it is part of DO statement
 * If i = 2, it is part of LOOP statement*/
{
    int exprtype;
    exprtype = expr();
    if (exprtype < 0) {
          strcpy(word,"UNTIL"); 
          error(252);  /* Expression expected after UNTIL */
          return -1;
    }
    if(exprtype == STRVAR) {
           error(13);  /*Type mismatch */
           return -1;
    }
    if(i == 1) {/* DO UNTIL statement */
       fprintf(ftmp, "\n%swhile(!(%s)) {/* DO-%d */",indent, exprstr,docount);
       SetIndent();
    }
    else if(i == 2) {/* LOOP UNTIL statement */
       DeIndent();
       fprintf(ftmp, "\n%s} while(!(%s));/* DO-%d */",indent, exprstr,docount);
    }
    fflush(ftmp);
    return 0;
} /*End - untilooprc */
int looprc(void)
/* Translates the statement LOOP [{WHILE | UNTIL} condition]  */
{
    int nxtoken, looptyp;
    looptyp = poploop();
    EmitSource();
    nxtoken = lex();
    if ((nxtoken != '\n') && (nxtoken != 0) && 
        (nxtoken != ':') && (nxtoken != '\'')) {  
        /* It is conditional LOOP */                             
        if(looptyp != DOLOOP) { 
          /*Conditional LOOP not matched by Unconditional DO */
          error(221);
          return -1;
        }
        if(strcmp(word, "WHILE") == 0){
           if(whilooprc(2) < 0) return -1;
        }
	else if(strcmp(word, "UNTIL") == 0) {
             if(untilooprc(2) < 0) return -1;
        }
        else {
           strcpy(word,"LOOP");
           error(240);
           return -1;
        }
        docount--;
        nxtoken = word[0];
    }
    else {  /* Plain LOOP statement without condition */
        if(looptyp != DOLOOP && looptyp != TOPDOLOOP) {
          /* LOOP not matched by  DO */
          error(221);
          return -1;
        }
        DeIndent();
        fprintf(ftmp, "\n%s}",indent);
        if(looptyp == DOLOOP) /* Plain LOOP with Plain DO */
           fprintf(ftmp, "while(1 == 1);");
        fprintf(ftmp, " /*End - DO-%d */", docount);
        fflush(ftmp);
        docount--;
    }
    if ((nxtoken != '\n') && (nxtoken != 0) && 
        (nxtoken != ':') && (nxtoken != '\'')) {  
          /* It is not end of line, EOF, ':', QUOTE */
             error(251);  /*if so error*/
             return(-1);
    }
    ungetc(nxtoken, fin);
    return 0;
} /* end - looprc() */
int exitprc(void)
/* Translates the statement EXIT {DO | FOR}  */
{
    int nxtoken, looptyp;
    pushloop(looptyp = poploop());
    EmitSource();
    nxtoken = lex();
    if(strcmp(word, "DO") == 0) { /* EXIT DO statement */
       if(looptyp != DOLOOP && looptyp != TOPDOLOOP) {
         if(docount == 0){
           error(219); return -1;
         }
       }
       fprintf(ftmp, "\n%sbreak;",indent);
       fflush(ftmp);
    }
    else if(strcmp(word,"FOR") == 0) { /* EXIT FOR statement */
       if(looptyp != FORLOOP) {
         if(forcount == 0){
           error(218); return -1;
         }
       }
       fprintf(ftmp, "\n%sbreak;",indent);
       fflush(ftmp);
    }
    else{ 
        strcpy(word, "EXIT");
        error(240); return -1;
    }
    nxtoken = lex();
    if ((nxtoken != '\n') && (nxtoken != 0) && 
        (nxtoken != ':') && (nxtoken != '\'')) {  
          /* It is not end of line, EOF, ':', QUOTE */
             error(251);  /*if so error*/
             return(-1);
    }
    ungetc(nxtoken, fin);
    return 0;
} /* end - exitprc() */
int envirstat(void)
/* Translates the statement ENVIRON <string-expr>
 * It won't look into the string to see whether it conforms to
 * the requirements of the Operating System for an Environment String */
{
   int exprtype;
   EmitSource();
   exprtype = expr();
   if(exprtype < 0) {
      strcpy(word,"ENVIRON");
      error(252); return -1;
   }
   if(exprtype == NUMBER || exprtype == NUMVAR) {
      strcpy(word,"ENVIRON");
      error(13); return -1;
   }
   fprintf(ftmp, "\n%sif(putenv(_tmp_) < 0)",indent);
   fprintf(ftmp, "\n%s   fprintf(stderr,\"\\nENVIRON failed in line-",indent);
   fprintf(ftmp, "%d\");", lincount);
   fflush(ftmp);
   return 0;
} /* End - envirstat */
int sleeprc(void)
/* Translates the statement SLEEP  [<num.expr>]  */
{
   int exprtyp, nxtoken;
#ifdef  __TURBOC__
   coniocount = 1;
#endif
   exprtyp = expr();
   nxtoken = word[0];
   EmitSource();
   if(exprtyp == STRING || exprtyp == STRVAR) {
      strcpy(word,"SLEEP");
      error(13); return -1;
   }
   if(exprtyp != NUMBER && exprtyp != NUMVAR) {
      if(nxtoken == '\n' || nxtoken == ':' ||
         nxtoken == '\'' || nxtoken == 0){ /* Plain SLEEP statement */
#ifdef  __TURBOC__
        fprintf(ftmp,"\n%swhile(!getch()) ;",indent);
        fflush(ftmp);
        ungetc(nxtoken, fin);
        return 0;
#else
        strcpy(exprstr,"(double) 0");
#endif
      }
      else{
        strcpy(word,"SLEEP");
        error(252); return -1;
      }
   }
   if(libcode("TIMER") < 0) return -1;
   fprintf(ftmp,"\n%s{",indent);
   SetIndent();
#ifdef  __TURBOC__
   fprintf(ftmp,"\n%sdouble zero = 0.0;",indent);
   fprintf(ftmp,"\n%sif((%s) <= zero){",indent, exprstr);
   fprintf(ftmp,"\n%s   while(!getch()) ;",indent);
   fprintf(ftmp,"\n%s}",indent);
   fprintf(ftmp,"\n%selse",indent);
   fflush(ftmp);
#endif
   fprintf(ftmp,"\n%s{",indent);
   fprintf(ftmp,"\n%s   double t1;",indent);
   fprintf(ftmp,"\n%s   t1 = TIMER(1);",indent);
   fprintf(ftmp,"\n%s   while(",indent);
#ifdef  __TURBOC__
   fprintf(ftmp,"!kbhit() && ");
#endif
   fprintf(ftmp,"(TIMER(1) - t1) < (double) (%s))  ;", exprstr);
   fprintf(ftmp,"\n%s  }",indent);
   DeIndent();
   fprintf(ftmp,"\n%s}",indent);
   fflush(ftmp);
   nxtoken = word[0];
   if ((nxtoken != '\n') && (nxtoken != 0) && 
       (nxtoken != ':') && (nxtoken != '\'')) {  /* it is not
                                        *  end of line, EOF, ':', QUOTE */
           error(251);     /*if so error*/
           return(-1);
   }
   ungetc(nxtoken, fin);
   return 0;
} /* End - sleeprc() */

int defstat(void)
/* Translates the statement DEF function-name(<Arg>[,<Arg>]...) = <expression>
 * As of now, Strings are not permitted in User Defined Functions */
{
   FUNCTION *fp;
   int  nxtoken,ftype;
   int symndx, rhstype;
   int argnum = 0;
   if((nxtoken = lex()) < 0) return -1;
   if(nxtoken == STRVAR) {
     strcpy(word,"Strings illegal in User Defined Functions");
     error(12);
     return -1;
   }
   if(/*nxtoken == STRVAR ||*/ nxtoken == NUMVAR)
      ftype = nxtoken;
   else {
      error(242); return -1;
   }
   if(AlreadyDefined) {
      error(215); return -1;
   }
   /* lex() stores the Function name in the Symbol table as NUMVAR or STRVAR
    * Change its type as UDF in Symbol Table */
   symndx = lookup(word);
   symtab[symndx].type = UDF;
   fp = (FUNCTION *) emalloc(sizeof(FUNCTION));
   if(fp == 0) return -1;
   /* Store the ptr to Function name in the Functions list */
   fp->name = symtab[symndx].name;
   if((nxtoken = lex()) < 0) return -1;
   if(nxtoken != '(') {
      error(2); return -1;
   }
   while(1 == 1){
      if((nxtoken = lex()) < 0) return -1;
      if(nxtoken == STRVAR) {
         strcpy(word,"Strings illegal in User Defined Functions");
         error(12);
         return -1;
      }
      if(/*nxtoken == STRVAR ||*/ nxtoken == NUMVAR){
         fp->Arg[argnum] = emalloc(strlen(word)+1);
         if(fp->Arg[argnum] == 0) return -1;
         strcpy(fp->Arg[argnum],word);
         fp->ArgType[argnum] = nxtoken;
      }
      else {
         error(242); return -1;
      }
      if((nxtoken = lex()) < 0) return -1;
      if(nxtoken == ',') {
          argnum++;
          if(argnum > MAXARG){
            error(214); return -1;
          }
      }
      else if(nxtoken == ')') break;
      else {
          error(207); return -1;
      }
   } /* end - while */
   fp->ArgCount = argnum+1;
   fp->next = FunList;
   FunList  = fp;
   if((nxtoken = lex()) != '=') {
      error(243); return -1;
   }
   rhstype = expr();
   if(rhstype == -100) {
      strcpy(word, "=");
      error(252); return -1;
   }
   if(rhstype < 0) return -1;
   if(rhstype == STRVAR && ftype == NUMVAR) {
      error(13); return -1;
   }
   if(rhstype == NUMVAR && ftype == STRVAR) {
      strcpy(word, exprstr);
      error(13); return -1;
   }
   nxtoken = word[0];
   if(!StatEnd(nxtoken)) {
       error(251); return -1;
   }
   /* Remove the Arguments from the Symbol Table ,as they are only dummy
    * variables */
   for(argnum = 0; argnum < fp->ArgCount; argnum++) {
      int p;
      p = lookup(fp->Arg[argnum]);
      if(p >= 0)
        symtab[p].name = 0;
   }
   /* Code generation part for DEF statement */
   if(ftype == NUMVAR) {
      fprintf(fout, "\ndouble %s();", fp->name);
      fflush(fout);
      fprintf(ffun, "\ndouble %s(", fp->name);
      fflush(ffun);
   }
   else if(ftype == STRVAR) {
      char *f;
      f = strdup(fp->name);
      if(f == 0) {
         error(249); return -1;
      }
      strvarconv(f);
      fprintf(fout, "\nchar *%s();", f);
      fflush(fout);
      fprintf(ffun, "\nchar *%s(", f);
      fflush(ffun);
      free(f);
   }
   for(argnum = 0; argnum < fp->ArgCount; argnum++) {
      if(fp->ArgType[argnum] == NUMVAR) {
        fprintf(ffun,"double %s",fp->Arg[argnum]);
        fflush(ffun);
      }
      else if(fp->ArgType[argnum] == STRVAR) {
         char *f;
         f = strdup(fp->Arg[argnum]);
         if(f == 0) {
            error(249); return -1;
         }
         strvarconv(f);
         fprintf(ffun,"char *%s", f);
         fflush(ffun);
         free(f);
      }
      if((fp->ArgCount - argnum) > 1) {
        fprintf(ffun,",");
        fflush(ffun);
      }
   } /* End - for */
   fprintf(ffun,")");
   fprintf(ffun,"\n{");
   if(rhstype == NUMVAR)
     fprintf(ffun,"\n  return(%s);", exprstr);
   if(rhstype == STRVAR){
     fprintf(ffun,"\n  char *s;");
     fprintf(ffun,"\n  s = strdup(_tmp_);");
     fprintf(ffun,"\n  strcpy(_tmp_,\"\");");
     fprintf(ffun,"\n  return(s);");
   }
   fprintf(ffun,"\n}");
   fflush(ffun);
   ungetc(word[0], fin);
   return 0;
} /* End - defstat */

FUNCTION *FunSearch(char *s)
/* Search for the Function 's' in the linked list of functions */
{
   FUNCTION  *fp;
   for(fp=FunList; fp != (FUNCTION *) 0; fp = fp->next)
      if(strcmp(fp->name, s) == 0)
          return fp;
   return 0;  /* If not found */
} /* End - FunSearch */

int IsInteger(double x)
/* Test if 'x' is a whole number */
{
   long n;
   n = (long) x;
   return((x == (double) n));
} /* End - IsInteger */

int getsubscript(void)
/* Get the next subscript(array dimension) of the array declaration
 */
{
   int nxtoken;
   double subval; /* Value of the subscript */
   nxtoken = lex();
   if(nxtoken < 0) return -1;
   if(strcmp(word,"+") == 0){ /* Skip unary plus */
       if((nxtoken = lex()) < 0) return -1;
   }
   if(nxtoken == STRING || nxtoken == STRVAR) {
       error(13); return -1;
   }
   if(nxtoken == NUMVAR) {
      error(216); return -1;
   }
   if(nxtoken != NUMBER) {
      error(2); return -1;
   }
   subval = str2num(word);
   if(!IsInteger(subval)){
       error(212); return -1;
   }
   if(subval <= 0.0) {
       error(211); return -1;
   }
   subval = subval+1;
   if(subval < 100000)  /* num2str can handle max. 5 digits */
      num2str(subval,word);
   else
      strcat(word,"+1");
   fprintf(fout,"[%s]", word);
   fflush(fout);
   return 0;
} /* End - getsubscript */

int dimstat(void)
/* Translates the DIM statement
 *  DIM <Var>(<num.constant>[,<num.constant>]), ...
 * This implementation differs from QuickBasic in the following respects:
 *  - In this version, max. 2 dimensional array only is permitted.
 *  - Here, expressions are not permitted as subscripts in DIM.
 *    However, one unary '+' is permitted before the numeric constant
 *  - Here, type specifier is not permitted in DIM statement.
 *  - Here, it is not possible to specify the lower bound of array.It is
 *    always 0.
 */
{
   int nxtoken, arrtype, symndx;
   int dimnum;
   ARRAY *ap;
   if(NeedSource){
      fprintf(fout,"\n/************** Line = %d ************/", lincount);
      fflush(fout);
   }
   while(1 == 1) {
      dimnum = 0; /* Initialize counter for the dimension for this array */
      nxtoken = lex();
      if(nxtoken < 0) return -1;
      if(AlreadyDefined){
        error(215); return -1;
      }
      symndx = lookup(word);
      if(nxtoken == STRVAR){
         arrtype = STRARR;
         strvarconv(word);
         fprintf(fout,"\nchar %s", word);
         fflush(fout);
      }
      else if(nxtoken == NUMVAR){
         arrtype = NUMARR;
         fprintf(fout,"\ndouble %s", word);
         fflush(fout);
      }
      else {
         error(242); return -1;
      }
      ap = (ARRAY *) emalloc(sizeof(ARRAY));
      if(ap == 0) return -1;
      /*Store the pointer to Array Name in the Array list */
      ap->name = symtab[symndx].name;
      nxtoken = lex();
      if(nxtoken < 0) return -1;
      if(nxtoken != '(') {
          error(2); return -1;
      }
      while(1 == 1) { /* If not end of size/subscrip. list */
        if(getsubscript() < 0) return -1; /* Get next dimension for this Array */
        nxtoken = lex();
        if(nxtoken < 0) return -1;
        if(nxtoken == ',') { /* It is multi-dimensional array */
           dimnum++;
           if(dimnum >= MAXDIM){
             error(210); return -1;
           }
        } /* IF - multi dimensional */
        else if(nxtoken == ')') break;
        else {
          error(207); return -1;
        }
      } /* end - while */
      if(arrtype == STRARR)
         fprintf(fout,"[MAXSTRLEN+1]");
      fprintf(fout,";");
      fflush(fout);
      symtab[symndx].type = arrtype;
      ap->DimCount = dimnum+1;
      ap->next = ArrList;
      ArrList  = ap;
      if((nxtoken = lex()) < 0) return -1;
      if(nxtoken == '\n' || nxtoken == '\'' || nxtoken == ':' || nxtoken == 0)
         break;
      if(nxtoken != ',') {
         error(236); return -1;
      }
   } /* End - while */
   if(NeedSource){
      fprintf(fout,"\n/********End of Line = %d ************/", lincount);
      fflush(fout);
   }
   ungetc(word[0],fin);
   return 0;
} /* End - dimstat */

ARRAY *ArrSearch(char *s)
/* Search for the Array 's' in the linked list of arrays */
{
   ARRAY  *ap;
   for(ap=ArrList; ap != (ARRAY *) 0; ap = ap->next)
      if(strcmp(ap->name, s) == 0)
          return ap;
   return 0;  /* If not found */
} /* End - ArrSearch */

int arr2var(void)
/* Convert the Array in  'word'(global var.) into a C - Variable */
{
   int n, nxtoken, kount;
   int dimnum = 0;
   char c, t[MAXWORDLEN], *w;
   ARRAY *ap;
   w = strdup(word);
   if(w == 0) return -1;
   ap = ArrSearch(word);
   if(ap == 0) return -1;
   kount = ap->DimCount;
   n = lookup(word);
   if(symtab[n].type == STRARR)
      strvarconv(word);
   strcpy(t, word);
   nxtoken = lex();
   if(nxtoken < 0) return -1;
   if(nxtoken != '(') {
       error(208); return -1;
   }
   while(1 == 1) {
     if(TranSubVal(t) < 0) return -1;
     if((c = lex()) < 0) return -1;
     /*c = word[0];*/  /* What is the token following the subscript */
     if(c == ',') {/* If',' ,there is more than one subscript */
        dimnum++;
        if(dimnum >= kount) {
           strcpy(word,w);
           error(209); return -1;
        }
     }
     else if(c == ')')  break;
     else {
        error(207); return -1;
     }
   } /* End - while */
   /* Now 't' contains the translated Array Variable
    * Copy it back to the global variable 'word' */
   strcpy(word, t);
   free(w);
   return 0;
} /* End - arr2var */

int TranSubVal(char *s)
/* Translates the next subscript of the array variable
 * and appends the same to the string in 's'. 
 * */
{
   int exprtype,nxtoken;
   char *t;
   t = emalloc(MAXWORDLEN);
   if(t == 0) return -1;
   strcpy(t,s);
   exprtype = lex();
   if(exprtype < 0) return -1;
   if(exprtype == STRING || exprtype == STRVAR) {
       error(13); return -1;
   }
   if(exprtype != NUMBER && exprtype != NUMVAR) {
       error(242); return -1;
   }
   strcat(t,"[(int)(0.5+");
   strcat(t, word); 
   strcat(t,")]");
   if(strlen(t) > MAXWORDLEN-1){
      error(230); return -1;
   }
   strcpy(s,t);
   return 0;
} /* End - TranSubVal */


