/************************************************************************
 *                  files.c                                             *
 ************************************************************************
 *   Code Generation (Routines for File Operations)                     *
 ************************************************************************
 *   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 "basic.h"
extern unsigned int lincount, linestart, forcount;
extern FILE *fin, *fout, *ftmp, *ffun;
extern char word[], exprstr[], indent[];
int fileopcount = 0;
int dircount = 0;
int processcount = 0; 
int killprc(void)
/* Translates the statement : KILL   path    */
{
        int nxtoken;
        EmitSource();
        nxtoken = expr();
        if(nxtoken < 0) { /* it was a null expression */
                error(252); return -1;
        }
        switch(nxtoken) {
                case NUMBER : 
                case NUMVAR : error(13);  return -1;
                case STRVAR : break;
        }
        fprintf(ftmp, "\n%sif(remove(_tmp_) != 0)",indent);
        fprintf(ftmp, "\n%s    ERR = 1;",indent);
        fprintf(ftmp, "\n%sstrcpy(_tmp_,\"\");",indent);
        fflush(ftmp);
        nxtoken = word[0]; /* what is next token */
        if(nxtoken != '\n' && nxtoken == ':' && nxtoken == '\'' && nxtoken == 0){
                error(251);
                return -1;
        }
        ungetc(nxtoken, fin);
        return 0;
}   /* End - killprc() */
int nameprc(void)
/* Translates the statement : NAME <filename-old> AS <filename-new> */
{
        int nxtoken;
        EmitSource();
        nxtoken = expr();
        if(nxtoken < 0) { /* it was a null expression */
                error(252); return -1;
        }
        switch(nxtoken) {
                case NUMBER : 
                case NUMVAR : error(13);  return -1;
                case STRVAR : break;
        }
        fprintf(ftmp, "\n%s{",indent);
        fprintf(ftmp, "\n%s    char oldname[MAXSTRLEN];",indent);
        fprintf(ftmp, "\n%s    strcpy(oldname,_tmp_);",indent);
        fprintf(ftmp, "\n%s    strcpy(_tmp_,\"\");",indent);
        fflush(ftmp);
        if(strcmp(word , "AS") != 0) {
                error(240); return -1;
        }
        nxtoken = expr();
        if(nxtoken < 0) { /* it was a null expression */
                error(252); return -1;
        }
        switch(nxtoken) {
                case NUMBER : 
                case NUMVAR : error(13);  return -1;
                case STRVAR : break;
        }
        fprintf(ftmp, "\n%s  if(rename(oldname,_tmp_) != 0)",indent);
        fprintf(ftmp, "\n%s    ERR = 3;",indent);
        fprintf(ftmp, "\n%s  strcpy(_tmp_,\"\");",indent);
        fprintf(ftmp, "\n%s}",indent);
        fflush(ftmp);
        nxtoken = word[0]; /* what is next token */
        if(nxtoken != '\n' && nxtoken == ':' && nxtoken == '\'' && nxtoken == 0){
                error(251);
                return -1;
        }
        ungetc(nxtoken, fin);
        return 0;
}  /* End - nameprc() */
int shellprc(void)
/* Translates the statement : SHELL  <O.S.command-string>  */
{
        int nxtoken;
        EmitSource();
        nxtoken = expr();
        if(nxtoken < 0) { /* it was a null expression */
                error(252); return -1;
        }
        switch(nxtoken) {
                case NUMBER : 
                case NUMVAR : error(13);  return -1;
                case STRVAR : break;
        }
        fprintf(ftmp, "\n%sif(system(_tmp_) != 0)",indent);
        fprintf(ftmp, "\n%s    ERR = 2;",indent);
        fprintf(ftmp, "\n%sstrcpy(_tmp_,\"\");",indent);
        fflush(ftmp);
        nxtoken = word[0]; /* what is next token */
        if(nxtoken != '\n' && nxtoken == ':' && nxtoken == '\'' && nxtoken == 0){
                error(251);
                return -1;
        }
        ungetc(nxtoken, fin);
        return 0;
}  /* End - shellprc() */

int closeprc(void)
/* Translates the statement CLOSE [[#]filenum[,[#]filenum]...] */
{
   int nxtoken;
   char c;
   EmitSource();
   IncludeFilInit();
   nxtoken = lex();
   if (nxtoken == '\n' || nxtoken == '\'' || nxtoken == ':' || nxtoken == 0){
      /* Plain CLOSE statement */
      fprintf(ftmp,"\n%sfcloseall();",indent);
      fprintf(ftmp,"\n%sInitFiles();",indent);
      ungetc(nxtoken, fin);
      return 0;
   }
   while(1 == 1) {
      if(nxtoken < 0) return -1;
      if(nxtoken == STRING || nxtoken == STRVAR) {
         error(13); return -1;
      }
      if(nxtoken != '#')
         ungetw(word,fin);
      if(getFileNum() < 0) return -1; /* Obtain no.'n' of file to be closed */
      fprintf(ftmp,"\n%s    fclose(fdList[n-1]);",indent);
      fprintf(ftmp,"\n%s    fdList[n-1] = 0;",indent);
      fprintf(ftmp,"\n%s  }",indent);
      fflush(ftmp);
      c = word[0];
      if(c == '\n' || c == ':' || c == '\'' || c == 0)
         break;
      if(c != ','){
         error(2); return -1;
      }
      nxtoken = lex();
   } /* end - while */
   ungetc(c, fin);
   return 0;
} /* End - closeprc() */

int getFileNum(void)
/* Translates the expression following '#' of File Operation Statements */
{
      int exprtyp;
      exprtyp = expr();
      if(exprtyp == -100) { /* There is no expression after '#' */
         strcpy(word,"# or , or file-list start");
         error(252); return -1;
      }
      if(exprtyp < 0) return -1;
      if(exprtyp == STRING || exprtyp == STRVAR){
        strcpy(word,exprstr);
        error(13); return -1;
      }
      fprintf(ftmp,"\n%s  {",indent);
      fprintf(ftmp,"\n%s    int n;",indent);
      fprintf(ftmp,"\n%s    n = (int)(0.5+%s);",indent, exprstr);
      fprintf(ftmp,"\n%s    if(n < 1 || n > %d){",indent, (int)MAXFILENUM);
      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);
      return 0;
} /* End of getFileNum */

int openprc(void)
/* Translates the statement OPEN <mode-string>,[#] <file-number>, <filespec> */
{
   int exprtype, nxtoken;
   EmitSource();
   fprintf(ftmp,"\n%s{",indent);
   fprintf(ftmp,"\n%s   char c;",indent);
   fprintf(ftmp,"\n%s   int  f;",indent);
   fprintf(ftmp,"\n%s   char altmode[2];",indent);
   fprintf(ftmp,"\n%s   altmode[1] = '\\0';",indent);
   fflush(ftmp);
   IncludeFilInit();
   exprtype = expr();
   /* Obtain the File Mode required */
   if(exprtype == -100) {
      strcpy(word, "OPEN");
      error(252); return -1;
   }
   if(exprtype < 0) return -1;
   if(exprtype == NUMBER || exprtype == NUMVAR) {
       strcpy(word, "OPEN");
       error(13); return -1;
   }
   else { /* It should be STRVAR */
       fprintf(ftmp,"\n%s   c = *(_tmp_);",indent);
       fprintf(ftmp,"\n%s   c = (c == 'I' || c == 'i') ? 'r' : c ;",indent);
       fprintf(ftmp,"\n%s   c = (c == 'O' || c == 'o') ? 'w' : c ;",indent);
       fprintf(ftmp,"\n%s   c = (c == 'A' || c == 'a') ? 'a' : c ;",indent);
       fprintf(ftmp,"\n%s   if(!(c == 'r' || c == 'w' || c == 'a')) {",indent);
       fprintf(ftmp,"\n%s     fprintf(stderr,\"\\nBad File Mode in Line-%d\");",indent,lincount);
       fprintf(ftmp,"\n%s     exit(1);}",indent);
       fprintf(ftmp,"\n%s   altmode[0] = c;",indent);
       fprintf(ftmp,"\n%s   strcpy(_tmp_,\"\");",indent);
       fflush(ftmp);
   }
   /* Next to file mode there should be comma(,) */
   if(word[0] != ','){
      error(236); return -1;
   }
   /* Next to the comma there may be an optional '#' */
   nxtoken = lex();
   if(nxtoken < 0) return -1;
   if(nxtoken == STRING || nxtoken == STRVAR){
      error(13); return -1;
   }
   if(nxtoken != '#')
      ungetw(word,fin);
   /* Obtain the File number/ channel number for the file */
   if(getFileNum() < 0) return -1; /* Obtain no.'n' of file to be opened */
   fprintf(ftmp,"\n%s   f = n-1;",indent);
   fprintf(ftmp,"\n%s   if(fdList[f] != 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);
   /* Next to file number there should be comma(,) */
   if(word[0] != ','){
      error(236); return -1;
   }
   /* What is the name of file/file-spec */
   exprtype = expr();
   if(exprtype == -100) { /* There is no expression after the ',' */
      strcpy(word,"# or , or file-list start");
      error(252); return -1;
   }
   if(exprtype < 0) return -1;
   if(exprtype == NUMBER || exprtype == NUMVAR){
      strcpy(word, exprstr);
      error(13); return -1;
   }
   /* '_tmp_' now contains the filespec */
   fprintf(ftmp,"\n%s   fdList[f] = fopen(_tmp_,altmode);",indent);
   fprintf(ftmp,"\n%s   if(fdList[f] == NULL){",indent);
   fprintf(ftmp,"\n%s     fprintf(stderr,\"\\nCan't open-%%s\",_tmp_);",indent);
   fprintf(ftmp,"\n%s     exit(1);}",indent);
   fprintf(ftmp,"\n%s   strcpy(_tmp_,\"\");",indent);
   fprintf(ftmp,"\n%s  }",indent);
   fprintf(ftmp,"\n%s}",indent);
   fflush(ftmp);
   nxtoken = word[0];
   if(nxtoken != '\n' && nxtoken != '\'' && nxtoken != ':' && nxtoken != 0){
       error(2); return -1;
   }
   ungetc(word[0], fin);
   return 0;
} /* End - openprc() */

void IncludeFilInit(void)
/* Checks for first file operation statement.
 * If first file operation statement is seen, the line
 * 'InitFiles();' is added in the .tmp file */
{
   if(fileopcount == 0){
      fprintf(ftmp,"\n%sInitFiles();",indent);
      fflush(ftmp);
   }
   fileopcount++;
}

int RmChDirprc(char *s)
/* Translates the statement -  CHDIR  path-string or RMDIR path-string
 * depending on the content of 's'.
 * if s = 'chdir' it handles the CHDIR,
 * IF s = 'rmdir' it handles the RMDIR statement */
{
   int exprtype, nxtoken;
   exprtype = expr();
   nxtoken = word[0];
   if(exprtype == -100){
      strcpy(word, s);
      error(252); return -1;
   }
   if(exprtype < 0) return -1;
   if(exprtype == NUMBER || exprtype == NUMVAR) {
       strcpy(word, s);
       error(13); return -1;
   }
   if(!StatEnd(nxtoken)){
      error(251); return -1;
   }
   /* Now '_tmp_' contains the path-string */
   EmitSource();
   fprintf(ftmp, "\n%sif(%s(_tmp_) == -1) {",indent, s);
   fprintf(ftmp, "\n%s   fprintf(stderr, \"\\nUnable to %s in Line-%d\");",indent,s,lincount);
   fprintf(ftmp, "\n%s   exit(1);}",indent);
   fprintf(ftmp, "\n%sstrcpy(_tmp_,\"\");",indent);
   fflush(ftmp);
   dircount++;
   ungetc(word[0], fin);
   return 0;
} /* End of RmChDirprc */

int chainprc(void)
/* Translates the statement - CHAIN filespec [, <parameter-string>] */
{
   int exprtype, nxtoken;
#ifdef  __TURBOC__
   processcount++; /* Requires the header - process.h */
#else
   dircount++;   /* Requires - unistd.h */
#endif
   exprtype = expr(); /* Get filespec */
   nxtoken = word[0];
   if(exprtype == -100) {
      strcpy(word, "CHAIN");
      error(252); return -1;
   }
   if(exprtype < 0) return -1;
   if(exprtype == NUMBER || exprtype == NUMVAR) {
      error(13); return -1;
   }
   /* Now '_tmp_' contains the filespec (i.e. Program to which control
    * should be passed).
    * Store filespec in '_tmp1_'   */
   EmitSource();
   fprintf(ftmp, "\n%s{",indent);
   fprintf(ftmp, "\n%s  char *arg[2];",indent);
   fprintf(ftmp, "\n%s  strcpy(_tmp1_, _tmp_);",indent);
   fprintf(ftmp, "\n%s  strcpy(_tmp_,\"\");",indent);
   fflush(ftmp);
   if(nxtoken == ',') { /* There is parameter-string */
      exprtype = expr(); /* Get parameter-string */
      nxtoken = word[0];
      if(exprtype == -100){
        error(252); return -1;
      }
      if(exprtype < 0) return -1;
      /* '_tmp_' now contains the parameter-string to be used with
       *  filespec */
      if(exprtype == NUMBER || exprtype == NUMVAR) {
         error(13); return -1;
      }
   }
   if(!StatEnd(nxtoken)){
     error(251); return -1;
   }
   fprintf(ftmp, "\n%s  arg[1] = strdup(_tmp_);",indent);
   fprintf(ftmp, "\n%s  if(execv(_tmp1_, arg) < 0){",indent);
   fprintf(ftmp, "\n%s    fprintf(stderr,\"\\nCHAIN failed in Line-%d\");",indent,lincount);
   fprintf(ftmp, "\n%s    exit(1);}",indent);
   fprintf(ftmp, "\n%s  strcpy(_tmp_,\"\");",indent);
   fprintf(ftmp, "\n%s  strcpy(_tmp1_,\"\");",indent);
   fprintf(ftmp, "\n%s}",indent);
   fflush(ftmp);
   ungetc(word[0], fin);
   return 0;
} /* End of chainprc */

