/* C_file.c
C code for Sather 1.0 library external class C_DIRENT */

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <dirent.h>
#include <sys/param.h>
#include <sys/stat.h>
#include "header.h"

EXT_OB error_message(void) {

  return strerror(errno);

}

BOOL c_textfile_feof(FILE *fp) {
  int c;

  /* Find out if there's nothing more to read */
  clearerr(fp);
  c=fgetc(fp);
  if (c==-1) return TRUE;

#ifdef __EMX__

  if (c=='\032')
    {
      int c2;
      
      /* Find out if Ctrl-Z was at the end of the file */
      c2=fgetc(fp);
      if (c2==-1) return TRUE;
      
      ungetc(c2,fp);
    }
#endif
  
  ungetc(c,fp);
  return FALSE;
}

BOOL c_binaryfile_feof(FILE *fp) {
  int c;

  /* Find out if there's nothing more to read */
  clearerr(fp);
  c=fgetc(fp);
  if (c==-1) return TRUE;
  ungetc(c,fp);
  return FALSE;
}

INT c_textfile_fread(char *fs,INT items,FILE *fp) {
  int i;
  clearerr(fp);
  i=fread(fs,1,items,fp);
#ifdef __EMX__
  /* Remove trailing Ctrl-Z */
  if (feof(fp) && fs[i-1]=='\032' ) i--;
#endif
  return i;
}

INT c_textfile_fgetc(FILE *fp) {
  int c;
  
  c=fgetc(fp);

#ifdef __EMX__
  if (c=='\032')
    {
      int c2;

      /* Find out if Ctrl-Z was at the end of the file */
      c2=fgetc(fp);
      if (c2==-1) return c2;

      ungetc(c2,fp);
    }
#endif

  return c;
}

int list_length(char *list) {
  /* Counts the length of what resolve_path returns. */

  int ind=0;

  if (list[0]=='\0')
    return 1;

  while ( (list[ind]!='\0') || (list[ind+1]!='\0') )
    ind++;

  return ind+2;

}

EXT_OB resolve_drive(char *workdir, char *fname) {
#ifdef __EMX__
  static char drive[3];

  if (isalpha(fname[0]) && fname[1]==':' &&
      (fname[2]=='/' || fname[2]=='\\')) {
    drive[0]=fname[0];
    drive[1]=':';
    drive[2]='\0';
    return drive;
  };

  if (isalpha(workdir[0]) && workdir[1]==':' &&
      (workdir[2]=='/' || workdir[2]=='\\')) {
    drive[0]=workdir[0];
    drive[1]=':';
    drive[2]='\0';
    return drive;
  };

  drive[0]=tolower(_getdrive());
  drive[1]=':';
  drive[2]='\0';
  return drive;

#else

  return NULL;

#endif
}

EXT_OB resolve_path(char *original_workdir, char *original_fname) {

  /***********************/
  /* Example run:        */
  /* fname=="../bin/gcc" */
  /* workdir=="/usr/lib" */
  /***********************/

         char workdir[MAXPATHLEN];  /* Current working directory */
  int         workdir_ind=0;          
  static char res[MAXPATHLEN+2];    /* Result                    */
  int         res_ind=0;          
         char fname[MAXPATHLEN];    /* Filename to be resolved   */
  int         fname_ind=0;        
  char *token;

  /* Define the directory separators */
#ifdef __EMX__
  char *separators="/\\";
#else
  char *separators="/";
#endif

  /* Make a copy of fname because strtok() would destroy it */
  strcpy(fname,original_fname);

  /* Make a copy of workdir because strtok() would destroy it */
  strcpy(workdir,original_workdir);
  
  /*****************/
  /* ""            */
  /*  ^res         */
  /*  ^res+res_ind */
  /*****************/

#ifdef __EMX__
  /* Skip over the drive designations */

  if (isalpha(fname[0]) && fname[1]==':' &&
      (fname[2]=='/' || fname[2]=='\\'))
    fname_ind=2;

  if (isalpha(workdir[0]) && workdir[1]==':' &&
      (workdir[2]=='/' || workdir[2]=='\\'))
    workdir_ind=2;
#endif

  /* Parse the current working directory if necessary */
#ifdef __EMX__
  if ((fname[fname_ind]!='/') && (fname[fname_ind]!='\\')) {
#else
  if (fname[fname_ind]!='/') {
#endif
    token=strtok(workdir+workdir_ind,separators);
    while (token!=NULL) {
      if (strlen(token)==0) 
	continue;
      strcpy(res+res_ind,token);
      res_ind += strlen(token)+1;
      token=strtok(NULL,separators);
    }
  }
  
  /***************************/
  /* "usr\0lib\0"            */
  /*  ^res      ^res+res_ind */
  /***************************/

  /* Parse the argument filename */
  token=strtok(fname+fname_ind,separators);
  while (token!=NULL) {
    if (strlen(token)==0) {
      token=strtok(NULL,separators);
      continue;
    }
    if (strcmp(token,".")==0) {
      token=strtok(NULL,separators);
      continue;
    }
    if (strcmp(token,"..")==0) {
      if (res_ind>0) {
	/* Remove last component of res, if any exists */
	res_ind -= 2;
	while (res_ind>=0 && res[res_ind]!='\0')
	  res_ind--;
	res_ind++;
      }
      token=strtok(NULL,separators);
      continue;
    }
    strcpy(res+res_ind,token);
    res_ind += strlen(token)+1;
    token=strtok(NULL,separators);
  }

  /* Terminate list with an empty string */
  res[res_ind]='\0';
  
  /*********************************/
  /* "usr\0bin\0gcc\0\0"           */
  /*  ^res            ^res+res_ind */
  /*********************************/

  return res;

}

#if defined(DOS_FILENAMES) && defined(__EMX__)

const char *output_separator = "\\";

#else

const char *output_separator = "/";

#endif

EXT_OB unresolve_filename(char *drive, char *path) {
  static char buffer[MAXPATHLEN];

  if (drive!=NULL)
    strcpy(buffer,drive);
  else
    strcpy(buffer,"");

  strcat(buffer,output_separator);

  if (strlen(path)>0) {
    strcat(buffer,path);
    path += strlen(path)+1;
  }

  while(strlen(path)>0) {
    strcat(buffer,output_separator);
    strcat(buffer,path);
    path += strlen(path)+1;
  }
    
  return buffer;
}

EXT_OB rel_child(char *path, char *s) {

  static char res[MAXPATHLEN];

  if (path==NULL)
    strcpy(res,s);
  else {
    strcpy(res,path);
    strcat(res,output_separator);
    strcat(res,s);
  }

  return res;

}

EXT_OB rel_parent(char *path) {

  static char res[MAXPATHLEN];

  if (path==NULL)
    strcpy(res,"..");
  else {
    strcpy(res,path);
    strcat(res,output_separator);
    strcat(res,"..");
  }

  return res;

}

BOOL test_file(char* fname) {
  /* Return true if 'fname' is a regular file or a link to file. */
  struct stat status;
  if (stat(fname,&status)) return 0;
  if ((status.st_mode & S_IFMT) == S_IFREG)
    return 1;
  else
    return 0;
}

BOOL test_dir(char* fname) {
  /* Return true if 'fname' is a directory or a link to directory. */
  struct stat status;
  if (stat(fname,&status)) return 0;
  if ((status.st_mode & S_IFMT) == S_IFDIR)
    return 1;
  else
    return 0;
}

BOOL test_link(char* fname) {
  /* Return true if 'fname' is a symbolic link. */

#ifdef __EMX__

  return 0;

#else

  struct stat status;
  if (lstat(fname,&status)) return 0;
  if ((status.st_mode & S_IFMT) == S_IFLNK)
    return 1;
  else
    return 0;

#endif

}

BOOL create_file(char* fname) {
  int i=creat(fname,0777); /* all permissions given */
  if (i==-1) 
    return 0;
  else {
    close(i);
    return 1;
  }
}

BOOL create_dir(char* fname) {
  if (mkdir(fname,0777)==-1) /* all permissions given */
    return 0;
  else
    return 1;
}

BOOL remove_file(char* fname) {
  if (remove(fname)==-1)
    return 0;
  else
    return 1;
}

BOOL remove_dir(char* fname) {
  if (rmdir(fname)==-1)
    return 0;
  else
    return 1;
}

BOOL remove_link(char* fname) {
  if (remove(fname)==-1)
    return 0;
  else
    return 1;
}

EXT_OB open_dir(char* path) {

  return opendir(path);

}

char* read_dir(EXT_OB dirp) {
  struct dirent *entry;

  while (1) {

    entry=readdir(dirp);

    if (entry==NULL) {
      closedir(dirp);
      return NULL;
    }

    if (strcmp(entry->d_name,".")==0 || strcmp(entry->d_name,"..")==0) 
      continue;

    return entry->d_name;

  }

}

EXT_OB current_work() {

#ifdef __EMX__

  static char buffer[MAXPATHLEN+2];
  getcwd(buffer+2,MAXPATHLEN);
  buffer[0]=tolower(_getdrive());
  buffer[1]=':';
  return buffer;

#else

  static char buffer[MAXPATHLEN];
  getcwd(buffer,MAXPATHLEN);
  return buffer;

#endif

}

EXT_OB current_root() {

#ifdef __EMX__

  static char root[4];

  root[0]=tolower(_getdrive());
  root[1]=':';
  root[2]='/';
  root[2]='\0';

  return &root;

#else

  static char *root = "/";
  return root;

#endif

}

