/************************************************************************
 *                    code1.c                                           *
 ************************************************************************
 *   Code Generation Routines(Input/ Output)                            *
 ************************************************************************
 *   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"
extern unsigned int lincount, linestart, forcount;
extern FILE *fin, *fout, *ftmp, *ffun;
extern char datfil[];
extern char word[];
extern char exprstr[];
extern char indent[];
extern struct symbol symtab[];
extern int NeedSource;
unsigned int datablkount = 0;
int inputprc(void)
/* Translates the statement :
 * Form-1 INPUT [<prompt-string> {;|,}] <var> [,<var>]...
 * Form-2 INPUT # filenumber, <var> [,<var>]... */
{
        char InStream[12] = "stdin" ;  /* Default input from stdin */
        int nxtoken;
        int track = 1; /* Translation Track */
        char promstr[MAXWORDLEN] = "?";
        EmitSource();
        if((nxtoken = lex()) < 0) return -1;
        if(nxtoken == '#'){ /* Form-2. It is FILE Read operation */
           track = 2;
           IncludeFilInit();
           if(getFileNum() < 0) return -1; /* Get number 'n' of file to be read */
           fprintf(ftmp,"\n%s   if(fdList[n-1] == 0){",indent);
           fprintf(ftmp,"\n%s      fprintf(stderr,\"\\nBad File Number(%%d) in Line-%d\",n);",indent,lincount);
           fprintf(ftmp,"\n%s      exit(1);}",indent);
           fflush(ftmp);
           strcpy(InStream,"fdList[n-1]");
           nxtoken = word[0]; /* There should be comma(,) following filenumber */
           if(nxtoken != ',') {
              error(236); return -1;
           }
        }  /* End - nxtoken == '#' */
        else{ /* Form-1. Read stdin */
           fprintf(ftmp, "\n%s{ int ok;",indent);
           fprintf(ftmp, "\n%s  do{",indent);
           fprintf(ftmp, "\n%s     ok = 1;",indent);
           fflush(ftmp);
           switch(nxtoken) {
               int nt;
               case STRING : /* should be prompt string */
                             strcpy(promstr, word);
                             if((nt = lex()) < 0) return -1;
                             if (nt == ';')
                                strcat(promstr, "?");
                             else if (nt != ',') {
                                error(2); return -1;
                             }
                case NUMARR :
                case STRARR :
                case NUMVAR :
                case STRVAR : fprintf(ftmp,"\n%s     printf(\"\\n%%s \",",indent);
                              fprintf(ftmp,"\"%s\");", promstr);
                              fflush(ftmp);
                              if(nxtoken != STRING){
                                ungetw(word, fin);
                                vardec(word);
                              }
                              break;
                default : error(250);
                          return -1;
           } /* End - switch */
        } /* End - Form-1 */
        /* Code common to Form-1 and Form-2 */
        do{
                if((nxtoken = lex()) < 0) return -1;
                if(nxtoken == NUMARR || nxtoken == STRARR) {
                   if(arr2var() < 0) return -1;
                }
                switch(nxtoken) {
                  case NUMARR :
                  case NUMVAR : vardec(word);
                                libcode("getnum");
                                if(track == 1)
                                  fprintf(ftmp, "\n%s     if(ok == 1) {",indent);
                                fprintf(ftmp, "\n%s       %s = getnum(%s);",indent, word,InStream);
                                if(track == 1)
                                  fprintf(ftmp, "\n%s       ok = (_err==1)?0:1;}",indent);
                                fflush(ftmp);
                                break;
                  case STRARR :
                  case STRVAR : libcode("getstr");
                                vardec(word);
                                if(track == 1)
                                  fprintf(ftmp, "\n%s     if(ok == 1) {",indent);
                                fprintf(ftmp, "\n%s       getstr(%s,%s);",indent, InStream,word);
                                if(track == 1)
                                  fprintf(ftmp, "\n%s       ok = (_err==1)?0:1;}",indent );
                                fflush(ftmp);
                                break;
                  default : error(242);
                            return -1;
                } /* switch */
                if((nxtoken = lex()) < 0) return -1;
                switch(nxtoken) {
                  case '\''  :
                  case ':'   :
                  case '\n'  :
                  case  0    :
                  case  ','  :  break;
                  default  : error(241);
                             return -1;
                } /*switch*/
                if(track == 1){
                    if(nxtoken != ',') {
                      fprintf(ftmp, "\n%s     if(ok == 0 || _err == 2) {",indent);
                      fprintf(ftmp, "\n%s       int c;",indent);
                      fprintf(ftmp, "\n%s       printf(\"\\nInvalid entry. Redo from start\\n\");",indent);
                      fprintf(ftmp, "\n%s       while((c=getc(stdin)) != EOF && c!=\'\\n\' && c!=\'\\r\')",indent);
                      fprintf(ftmp, "\n%s        /*Flush rest of input line */;",indent);
                      fprintf(ftmp, "\n%s       ok = 0;",indent);
                      fprintf(ftmp, "\n%s     }",indent);
                      fprintf(ftmp, "\n%s  }while(ok == 0);\n%s}",indent,indent);
                      fflush(ftmp);
                    } /* End - nxtoken != ',' */
                }  /* End - track == 1 */
        }while(nxtoken != '\'' && nxtoken != ':' && nxtoken != '\n' &&
               nxtoken != 0);
        ungetc(nxtoken,fin);
        if(track == 2) {
          fprintf(ftmp,"\n%s  }",indent);
          fflush(ftmp);
        }
        return 0;
} /* end of INPUTPRC() */
int readprc(void)
/* Translates the statement READ <var> [,<var>]...   */
{
        int nxtoken;
        datablkount++;
        if(datablkount == 1) { /* Requisite data structures,functions
                                * are to be installed in target file */
                datadec();
        }
        EmitSource();
        do {
                nxtoken = lex();
                if(nxtoken == NUMARR || nxtoken == STRARR) {
                   if(arr2var() < 0) return -1;
                }
                switch(nxtoken) {
                        case NUMARR :
                        case NUMVAR : vardec(word);
                                      fprintf(ftmp,"\n%s _err = 0;",indent);
                                      fprintf(ftmp,"\n%s if(dbptr == 0) {",indent);
                                      fprintf(ftmp,"\n%s   fprintf(stderr,\"\\nOut of Data near line-%%d\",%d);",indent, lincount);
                                      fprintf(ftmp,"\n%s   exit(1);}",indent);
                                      fprintf(ftmp,"\n%s %s = str2num(dbptr->datastr);",indent, word);
                                      fprintf(ftmp,"\n%s if(_err != 0) {",indent);
                                      fprintf(ftmp,"\n%s    fprintf(stderr, \"\\nType mismatch near line-%%d\",%d);",indent, lincount);
                                      fprintf(ftmp,"\n%s    exit(1);",indent);
                                      fprintf(ftmp,"\n%s }",indent);
                                      fprintf(ftmp,"\n%s dbptr = dbptr->next;",indent);
                                      fflush(ftmp);
                                      break;
                        case STRARR :
                        case STRVAR : /* code for storing the string from datablock */
                                      vardec(word);
                                      fprintf(ftmp,"\n%s if(dbptr == 0) {",indent);
                                      fprintf(ftmp,"\n%s   fprintf(stderr,\"\\nOut of Data near line-%%d\",%d);",indent, lincount);
                                      fprintf(ftmp,"\n%s   exit(1);}",indent);
                                      fprintf(ftmp,"\n%s strcpy(%s,dbptr->datastr);",indent,word);
                                      fprintf(ftmp,"\n%s dbptr = dbptr->next;",indent);
                                      fflush(ftmp);
                                      break;
                        default : error(242);
                                  return -1;
                } /* switch */
                nxtoken = lex();
                switch(nxtoken) {
                  case '\''  :
                  case ':'   :
                  case '\n'  :
                  case  0    :
                  case  ','  :  break;
                  default  : error(241);
                             return -1;
                } /*switch*/
        }while(nxtoken != '\'' && nxtoken != ':' && nxtoken != '\n' &&
               nxtoken != 0);
        ungetc(nxtoken,fin);
        return 0;
} /* end of readprc() */
int dataprc(void)
/* Translates the statement DATA <const> [,<const>]...  */
{
        int  c;
        static int Datacount = 0;
        FILE *fdat;
        datablkount++;
        if(datablkount == 1) { /* Requisite data structures,functions
                                * are to be installed in target file */
                datadec();
        }
        fdat = efopen(datfil,"a");
        if(NeedSource){
          fprintf(fdat,"\n/************** Line = %d ************/", lincount);
          fflush(fdat);
        }
        do {
                Datacount++;
                c = getstring(word);
                fprintf(fdat,"\n  dat = (struct datablock *) (emalloc(sizeof(struct datablock)));");
                fprintf(fdat,"\n  dat->datastr = (char *)(emalloc(%d));",strlen(word)+1);
                fprintf(fdat,"\n  strcpy(dat->datastr, \"%s\");", word);
                fprintf(fdat,"\n  dat->next = 0;");
                fflush(fdat);
                if (Datacount == 1) {
                        fprintf(fdat,"\n  dbFront = dat;");
                        fprintf(fdat,"\n  dbptr = dat;");
                        fflush(fdat);
                }
                else {
                        fprintf(fdat,"\n  dbRear->next = dat;");
                        fflush(fdat);
                }
                fprintf(fdat,"\n  dbRear = dat;");
                fflush(fdat);
                switch(c) {
                  case ':'   :
                  case '\n'  :
                  case  EOF  :
                  case  ','  :  break;
                  default  : error(241);
                             return -1;
                } /* end of switch */
        }while(c != ':' && c != '\n' &&
               c != EOF);
	ungetc(c,fin);
        fclose(fdat);
        return 0;
} /* end of dataprc() */
int restoreprc(void)
/* Translates the statement RESTORE   */
{
	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); 
        datablkount++;
        if(datablkount == 1) { /* Requisite data structures,functions
                                * are to be installed in target file */
                datadec();
        }
        EmitSource();
        fprintf(ftmp, "\n%s dbptr = dbFront;",indent);
        fflush(ftmp);
        return 0;
} /* end of restoreprc() */
int skipwhite(void)
/* Skips white space chars. in the file - fin.
 * On exit, the file pointer points to the non-white char.
 * following the white space char.
 * The non-white char is returned */
{
        int c;
        while ((c=getc(fin)) == ' ' || c == '\t' || c == '\r')
                ;
        return c;
} /* end of skipwhite() */
int getstring(char *s)
/* Get next string into s from the file - fin
 * If the string begins with " then all subsequent chars upto
 * but not including the next " or the newline constitute the string.
 * If the string does not begin with " then all subsequent chars upto
 * but not including comma(,) or newline or colon(:) constitute the string. */
{
        int c, i;
        int quoteseen = NO;
        c = skipwhite();
        if (c == '"') {  /* Quoted string literal */
                quoteseen = YES;
                c = getc(fin);
        }
        for(i = 0 ; ; i++) {
                if (c == '\r' || c == '\n' || c == EOF )
                        break ;
                if(quoteseen == YES && c == '"') {
                        c = skipwhite();
                        break;
                }
                if(quoteseen == NO && (c == ','|| c == ':'))
                        break;
                if ( i >= MAXWORDLEN -1 ) {
                        error(254);
                        return(-1);
                }
                *s++ = c;
                c = getc(fin);
        }
        *s = '\0';
        return c;
}  /* End of getstring() */
int datadec(void)
/* Inserts the requisite data structures and functions for the
 * translation of READ, DATA and RESTORE statements */
{
        fprintf(fout, "\nstruct datablock {");
        fprintf(fout, "\n     char  *datastr;");
        fprintf(fout, "\n     struct datablock *next;");
        fprintf(fout, "\n};");
        fprintf(fout, "\nstruct datablock *datalist = 0;");
        fprintf(fout, "/*Queue of data in DATA statements*/");
        fprintf(fout, "\nstatic struct datablock *dbptr = 0;");
        fprintf(fout, "\nstatic struct datablock *dbFront = 0;");
        fprintf(fout, "\nstatic struct datablock *dbRear = 0;");
        fprintf(fout, "\nstruct datablock *dat;");
        fprintf(fout, "\nchar *emalloc();");
        fflush(fout);
        fprintf(ffun, "\nchar *emalloc(unsigned n)  /*check return from malloc() */");
        fprintf(ffun, "\n{");
        fprintf(ffun, "\n  char *p;");
        fprintf(ffun, "\n  if((p = malloc(n)) == NULL) {");
        fprintf(ffun, "\n    fprintf(stderr,\"\\nOut of memory\");");
        fprintf(ffun, "\n    exit(1);");
        fprintf(ffun, "\n  }");
        fprintf(ffun, "\n  return p;");
        fprintf(ffun, "\n}");
        fflush(ffun); 
        if(libcode("str2num") < 0) return -1;
        return 0;
}   /* End - datadec() */

int printprc(void)
/* Translates the statement
 * PRINT [#filenumber,][USING format-string;][<expr>[,<expr>|;<expr>]...[,|;]]
 */
{
        char *FmtStr_S;  /* Format string of Source code */
        char *FmtStr_O[MAXWORDLEN]; /*Converted Format String */
        char OutStream[12] = "stdout" ; /* Default print to stdout */
        int exptype, nxtoken, FmTyp;
        int ptr = 0;  /* Point to beginning of Format string */
        int prvdelim = ' ';  /* Holds the previous delim */
        int track = 1;      /* Holds the Translation Track */
        int Formatted = FALSE; /* By default unformatted PRINT */
        EmitSource();
        nxtoken = lex();
        if(nxtoken < 0) return -1;
        if(nxtoken == '#'){ /* It is FILE Print operation */
           track = 2;
           IncludeFilInit();
           if(getFileNum() < 0) return -1;
           fprintf(ftmp,"\n%s   if(fdList[n-1] == 0){",indent);
           fprintf(ftmp,"\n%s      fprintf(stderr,\"\\nBad File Number(%%d) in Line-%d\",n);",indent,lincount);
           fprintf(ftmp,"\n%s      exit(1);}",indent);
           fflush(ftmp);
           strcpy(OutStream,"fdList[n-1]");
           nxtoken = word[0];
           if(nxtoken != ',') {
              error(236); return -1;
           }
           if((nxtoken = lex()) < 0) return -1;
        }  /* End - nxtoken == '#' */
        if(strcmp(word,"USING") == 0) {
           if((nxtoken = lex()) < 0) return -1;
           if(nxtoken != STRING){
             strcpy(word,"USING clause-Format String(a Constant) required");
             error(12); return -1;
           }
           Formatted = TRUE;
	   FmtStr_S = strdup(word);
	   if(FmtStr_S == 0) return -1;
           if((nxtoken = lex()) < 0) return -1;
           if(nxtoken != ';'){
              strcpy(word, "USING clause - ; missing");
              error(12); return -1;
           }
        } /* End - 'USING' */
        else /* if(nxtoken != '#')*/ {
           if(nxtoken == STRING)
              ungetc('"',fin);
           ungetw(word,fin);
           if(nxtoken == STRING)
              ungetc('"',fin);
           vardec(word);  /* If it is Var. Declare it */
        }  /* End - else */
	do {
	exptype = expr();
        if(Formatted)
           if(FmtConv(&FmtStr_S[ptr],&FmtStr_O[0], &FmTyp, &ptr) < 0) return -1;
        switch(exptype) {
		case NUMBER :
                case NUMVAR : 
                              prvdelim = ' ';
                              if(Formatted){
                                if(FmTyp == STRVAR){
                                  error(13); return -1;
                                }
                                fprintf(ftmp,"\n%sif(fprintf(%s,\"%s\",",indent,OutStream,FmtStr_O);
                              }
                              else
                                fprintf(ftmp,"\n%sif(fprintf(%s,\" %%f \",",indent,OutStream);
                              fprintf(ftmp, "(double)(%s))==EOF){", exprstr);
                              fprintf(ftmp,"\n%s     fprintf(stderr,\"\\nPRINT failed in Line-%d\");",indent,lincount);
                              fprintf(ftmp,"\n%s     exit(1);}",indent);
                              fflush(ftmp);
                              break;
                case STRVAR : 
                              prvdelim = ' ';
                              if(Formatted){
                                if(FmTyp == NUMVAR){
                                  error(13); return -1;
                                }
                                fprintf(ftmp, "\n%sif(fprintf(%s,\"%s\",",indent,OutStream,FmtStr_O);
                              }
                              else
                                fprintf(ftmp, "\n%sif(fprintf(%s,\" %%s\",",indent,OutStream);
                              fprintf(ftmp, "_tmp_)==EOF){");
                              fprintf(ftmp,"\n%s     fprintf(stderr,\"\\nPRINT failed in Line-%d\");",indent,lincount);
                              fprintf(ftmp,"\n%s     exit(1);}",indent);
                              fprintf(ftmp, "\n%sstrcpy(_tmp_,\"\");",indent);
                              fflush(ftmp);
                              break;
                } /* switch */
		nxtoken = word[0];
                switch(nxtoken) {
                   case  ',' :if(!Formatted){
                                fprintf(ftmp,"\n%sif(fprintf(%s,\"\\t\")==EOF){",indent,OutStream);
                                fprintf(ftmp,"\n%s     fprintf(stderr,\"\\nPRINT failed in Line-%d\");",indent,lincount);
                                fprintf(ftmp,"\n%s     exit(1);}",indent);
                               /* fputs("\nprintf(\"\\t\");", ftmp); */
                                fflush(ftmp);
                              }
                                prvdelim = ',';
                                break;
                   case  ';'  : 
                                prvdelim = ';';
                                break;
                   case  ':'  :
                   case  '\n' :
                   case  '\'' : if(prvdelim != ',' && prvdelim != ';'){
                                   fprintf(ftmp,"\n%sif(fprintf(%s,\"\\n\")==EOF){",indent, OutStream);
                                   fprintf(ftmp,"\n%s     fprintf(stderr,\"\\nPRINT failed in Line-%d\");",indent,lincount);
                                   fprintf(ftmp,"\n%s     exit(1);}",indent);
                                   fflush(ftmp);
                                }
                   case  0    : goto ppover;
                   default    : error(251);
                                return -1;
                }
     } while(TRUE) ;
ppover:  ungetc(word[0] , fin);
     if(track == 2) {
        fprintf(ftmp,"\n%s  }",indent);
        fflush(ftmp);
     }
     return 0;
}  /* End - printprc() */

int FmtConv(char s[], char t[], int *FmTyp, int *ptr)
/* Converts the BASIC language Format String in - 's'
 * into equivalent C - language format String in - 't'
 * FmTyp = Type of the Format string (Numeric / String)
 * ptr   = Pointer to the next position in the Format string - 's'
 */
{
   int i,j,fldlen,prec;
   char c, num[5];
   fldlen = prec = i = j = 0;
   /* Gather all chars. upto but not including the first formatting
    * char. into the Converted format string */
   while((c = s[i++]) != '#' && c != '&' && c != '!'
           && c != '\0') {
       if(c == '_'){ /*Take next char as a literal to be printed*/
          if(s[i] != '\0') c = s[i++];
       } /* if c == '_' */
       else if(c == '.'){/*If next char. is not '#' it is not a format char*/
          if(s[i] == '#') break;
       } /* if c == '.' */
       else if(c == '\\'){
          int tmpos;
          tmpos = i;
          while((c = s[i++]) == ' ')
              ;
          if(c != '\\'){
             c = '\\';
             t[j++] = c;
             i = tmpos;
          }
          else{
             i = tmpos;
             break;
          }
       } /* End - if c == '\\' */
       t[j++] = c;
   } /* End - while */
   switch(c) {
      case '#' : fldlen++;
                 while((c = s[i++]) == '#')
                   fldlen++;
                 if(c == '.') {
                   fldlen++;
                   while((c = s[i++]) == '#'){
                     fldlen++;
                     prec++;
                   }
                 }
                 num2str(fldlen, num);
                 t[j++] = '%';
                 t[j] = '\0';
                 strcat(t, num);
                 strcat(t, ".");
                 num2str(prec,num);
                 strcat(t, num);
                 strcat(t,"f");
                 *FmTyp = NUMVAR; /* It is Numeric type format string */
                 break;
      case '.' : /* Next char. is '#' only as tested previously */
                 fldlen++;
                 prec++;
                 while((c = s[i++]) == '#'){
                   fldlen++;
                   prec++;
                 }
                 num2str(fldlen, num);
                 t[j++] = '%';
                 t[j] = '\0';
                 strcat(t, num);
                 strcat(t, ".");
                 num2str(prec,num);
                 strcat(t, num);
                 strcat(t,"f");
                 *FmTyp = NUMVAR; /* It is Numeric type format string */
                 break;
      case '&' : t[j++] = '%';
                 t[j++] = 's';
                 t[j] = '\0';
                 *FmTyp = STRVAR;  /* It is String type format string */
                 i++;
                 break;
      case '!' : t[j++] = '%';
                 t[j++] = '.';
                 t[j++] = '1';
                 t[j++] = 's';
                 t[j] = '\0';
                 *FmTyp = STRVAR;  /* String Type format string */
                 i++;
                 break;
      case '\\': prec++;
                 while((c = s[i++]) == ' ')
                    prec++;
                 if(c == '\\')
                    prec++;
                 t[j++] = '%';
                 t[j++] = '.';
                 t[j] = '\0';
                 num2str(prec, num);
                 strcat(t, num);
                 strcat(t, "s");
                 *FmTyp = STRVAR;
                 break;
      case '\0' : error(213); return -1;
   } /* End - switch */
   if(c == '\0') { /* End of format string */
       *ptr = 0;   /* Reset pointer to beginning of format string */
       return 0;   /* and return */
   }
   j = strlen(t);
   i--; /* We have gone ahead by 1 char too far. Adjust for this */
   /* Gather remaining chars. preceding the next formatting char(if any)
    * and append to the Converted Format string */

   while((c = s[i++]) != '#' && c != '&' && c != '!'
           && c != '\0') {
       if(c == '_') { /*Take next char as a literal to be printed*/ 
          if(s[i] != '\0') c = s[i++];
       } /* if c == '_' */
       else if(c == '.'){/*If next char. is not '#' it is not a format char*/
          if(s[i] == '#') break;
       }  /* if c == '.' */
       else if(c == '\\'){
          int tmpos;
          tmpos = i;
          while((c = s[i++]) == ' ')
              ;
          if(c != '\\'){
             c = '\\';
             t[j++] = c;
             i = tmpos;
          }
          else{
             i = tmpos;
             break;
          }
       } /* End - if c == '\\' */
       t[j++] = c;
   } /* end - while */
   t[j] = '\0';
   if(c == '\0') *ptr = 0; /* Reset ptr to beginning of format string */
   else *ptr = i - 1;
   return 0;
} /* End - FmtConv */

int writeprc(void)
/* Translates the WRITE [#filenumber,]<expr>[{,|;}<expr>]...*/
{
        char OutStream[12] = "stdout" ; /* Default write to stdout */
        int exptype, nxtoken;
        int prvdelim = ' ';  /* Holds the previous delim */
        int track = 1;      /* Holds the Translation Track */
        EmitSource();
        nxtoken = lex();
        if(nxtoken < 0) return -1;
        if(nxtoken != '#') {
           if(nxtoken == STRING)
              ungetc('"',fin);
           ungetw(word,fin);
           if(nxtoken == STRING)
              ungetc('"',fin);
           vardec(word); /* Declare the variable */
        }
        if(nxtoken == '#'){ /* It is FILE Write operation */
           track = 2;
           IncludeFilInit();
           if(getFileNum() < 0) return -1;
           fprintf(ftmp,"\n%s   if(fdList[n-1] == 0){",indent);
           fprintf(ftmp,"\n%s      fprintf(stderr,\"\\nBad File Number(%%d) in Line-%d\",n);",indent,lincount);
           fprintf(ftmp,"\n%s      exit(1);}",indent);
           fflush(ftmp);
           strcpy(OutStream,"fdList[n-1]");
           nxtoken = word[0];
           if(nxtoken != ',') {
              error(236); return -1;
           }
        }  /* End - nxtoken == '#' */
        do {
	exptype = expr();
        switch(exptype) {
		case NUMBER :
                case NUMVAR : prvdelim = ' ';
                              fprintf(ftmp,"\n%sif(fprintf(%s,\"%%f\",",indent,OutStream);
                              fprintf(ftmp, "(double)(%s))==EOF){", exprstr);
                              fprintf(ftmp,"\n%s     fprintf(stderr,\"\\nWRITE failed in Line-%d\");",indent,lincount);
                              fprintf(ftmp,"\n%s     exit(1);}",indent);
                              fflush(ftmp);
                              break;
                case STRVAR : fprintf(ftmp, "\n%sif(fprintf(%s,\"\\\"\")==EOF){",indent,OutStream);
                              fprintf(ftmp,"\n%s     fprintf(stderr,\"\\nWRITE failed in Line-%d\");",indent,lincount);
                              fprintf(ftmp,"\n%s     exit(1);}",indent);
                              fprintf(ftmp, "\n%sfprintf(%s,\"%%s\",",indent,OutStream);
			      fprintf(ftmp, "_tmp_);");
                              fprintf(ftmp, "\n%sfprintf(%s,\"\\\"\");",indent,OutStream);
                              fprintf(ftmp, "\n%sstrcpy(_tmp_,\"\");",indent);
                              fflush(ftmp);
                              prvdelim = ' ';
                              break;
                default : if(prvdelim != ' ') {
                             error(252); return -1;
                          }
        } /* switch */
        nxtoken = word[0];
        switch(nxtoken) {
             case  ';'  :
             case  ','  : fprintf(ftmp,"\n%sif(fprintf(%s,\",\")==EOF){",indent,OutStream);
                          fprintf(ftmp,"\n%s     fprintf(stderr,\"\\nWRITE failed in Line-%d\");",indent,lincount);
                          fprintf(ftmp,"\n%s     exit(1);}",indent);
                          fflush(ftmp);
                          prvdelim = nxtoken;
                          break;
             case  ':'  :
             case  '\n' :
             case  '\'' : fprintf(ftmp, "\n%sif(fprintf(%s,\"\\n\")==EOF){",indent,OutStream);
                          fprintf(ftmp,"\n%s     fprintf(stderr,\"\\nWRITE failed in Line-%d\");",indent,lincount);
                          fprintf(ftmp,"\n%s     exit(1);}",indent);
                          fflush(ftmp);
             case  0    : goto wpover;
             default    : error(251);
                          return -1;
        }
     } while(TRUE) ;
wpover:  ungetc(word[0] , fin);
     if(track == 2) {
        fprintf(ftmp,"\n%s  }",indent);
        fflush(ftmp);
     }
     return 0;
} /* End - writeprc() */
int lineprc(void)
/* Translates the statements starting with keyword LINE */
{
        EmitSource();
        if(lex() < 0) return -1;
        if(strcmp(word,"INPUT") != 0) {
          strcpy(word,"LINE");
          error(240); return -1;
        }
        /* It is a LINE INPUT statement */
        if(lineinprc() < 0) return -1;
        return 0;
} /* End - lineprc() */
int lineinprc(void)
/* Translates the statement :
 * Form-1 :LINE INPUT [;] [prompt{;|,}] <string var>
 * Form-2 :LINE INPUT # filenumber, <string var>
 * Called by lineprc().
 * On entry, the lexical pointer is next to the keyword INPUT */
{
    char InStream[12] = "stdin" ;  /* Default input from stdin */
    int nxtoken, lfreqd;
    int track = 1; /* Translation Track */
    nxtoken = lex();
    lfreqd = YES;
    if(nxtoken < 0) return -1;
    if(nxtoken == '#'){ /* Form-2. It is FILE Read operation */
        int p;
        track = 2;
        IncludeFilInit();
        if(getFileNum() < 0) return -1; /* Get number 'n' of file to be read */
        fprintf(ftmp,"\n%s   if(fdList[n-1] == 0){",indent);
        fprintf(ftmp,"\n%s      fprintf(stderr,\"\\nBad File Number(%%d) in Line-%d\",n);",indent,lincount);
        fprintf(ftmp,"\n%s      exit(1);}",indent);
        fflush(ftmp);
        strcpy(InStream,"fdList[n-1]");
        nxtoken = word[0]; /* There should be comma(,) following filenumber */
        if(nxtoken != ',') {
            error(236); return -1;
        }
        if((nxtoken = lex()) < 0) return -1;
    }  /* End - nxtoken == '#' */
    else { /* Form-1. Input from stdin */
      if(nxtoken == ';') { 
         lfreqd = NO;
         if((nxtoken = lex()) < 0) return -1;
      }
      if(nxtoken == STRING) { /* It should be prompt string */
         fprintf(ftmp,"\n%sprintf(\"%%s\",",indent);
         fprintf(ftmp,"\"%s\");", word);
         fflush(ftmp);
         if((nxtoken = lex()) < 0) return -1;
         if(nxtoken != ';' && nxtoken != ',') {
            error(241); return -1;
         }
         if((nxtoken = lex()) < 0) return -1;
      }
    } /* End - Form-1 */
    /* Code common to Form-1 and Form-2 */
    if(nxtoken == STRARR){
       if(arr2var() < 0) return -1;
    }
    if(nxtoken == STRVAR || nxtoken == STRARR) {
       /* It should be the var. to hold the line of input */
       libcode("getline");
       vardec(word);
       fprintf(ftmp, "\n%s   getline(%s,%s);",indent, InStream,word);
       fflush(ftmp);
       if((nxtoken = lex()) < 0) return -1;
       if(nxtoken != '\'' && nxtoken != ':' && nxtoken != '\n' &&
          nxtoken != 0){
               error(251); return -1;
       }
       ungetc(nxtoken,fin);
       if(track == 2) {
          fprintf(ftmp,"\n%s  }",indent);
          fflush(ftmp);
       }
       else{
         if(lfreqd){
            fprintf(ftmp,"\n%s   fprintf(stdout,\"\\n\");",indent);
            fflush(ftmp);
         }
       }
       return 0;
   }
   else if(nxtoken == NUMVAR || nxtoken == NUMARR) {
      error(13); return -1;
   }
   else {
      error(242); return -1;
   }
} /* end of lineinprc() */
