/* $Id: include.c,v 1.4 2009/01/04 15:49:31 kiesling Exp $ */

/*
  This file is part of Ctalk.
  Copyright © 2005-2009 Robert Kiesling, ctalk@ctalklang.org.
  Permission is granted to copy this software provided that this copyright 
  notice is included in all source code modules.

  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., 51 Franklin St., Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#ifdef __DJGPP__
#include <dirent.h>
#endif
#include "object.h"
#include "message.h"
#include "ctalk.h"

extern int include_dir_opt;       /* Declared in main.c.       */
extern int n_user_include_dirs;        /* Specified with -I option. */
extern char *user_include_dirs[MAXUSERDIRS];
extern int systeminc_opt;         /* Specified with -s option. */
extern int n_system_inc_dirs;
extern char *systeminc_dirs[MAXUSERDIRS]; 

extern char *classlibdir;         /* Set at compile time.      */
extern char *pkgname;
extern char libcachedir[FILENAME_MAX];
extern char ctalkuserhomedir[FILENAME_MAX];

static char *library_include_paths[MAXUSERDIRS];

#ifdef __DJGPP__
extern int __opendir_flags;
#endif

extern HASHTAB classlibpaths;

static char **last_classlib_path_ptr;

char *find_library_include (char *fname, int find_next) {
  static char pathbuf[FILENAME_MAX];
  if (find_next) {
    ++last_classlib_path_ptr;
    while (*last_classlib_path_ptr) {
      strcpy (pathbuf, *last_classlib_path_ptr);
      STRCAT2(pathbuf, "/", fname);
      if (file_exists(pathbuf)) {
	return pathbuf;
      }
      ++last_classlib_path_ptr;
    }
    /* In case we get another find_next after an unsuccessful find_next. */
    last_classlib_path_ptr = library_include_paths;
   } else {
     last_classlib_path_ptr = library_include_paths;
     while (*last_classlib_path_ptr) {
       strcpy (pathbuf, *last_classlib_path_ptr);
       STRCAT2(pathbuf, "/", fname);
       if (file_exists(pathbuf)) {
	 return pathbuf;
       }
       ++last_classlib_path_ptr;
     }
   }
  return NULL;
}

void init_library_paths (void) {
  int i;
  char libdir[FILENAME_MAX],
    classfilepath[FILENAME_MAX];
  DIR *dir;
  struct dirent *d;
  int n_paths;

  _new_hash (&classlibpaths);

  library_include_paths[0] = strdup (classlibdir);
  n_paths = 1;

  for (i = 0; i < n_user_include_dirs; i++, n_paths++) {
    strcpy (libdir, expand_path(user_include_dirs[i]));
    library_include_paths[i + 1] = strdup (libdir);
    _hash_put (classlibpaths, libdir, libdir);
  }

  sprintf (libdir, "%s/%s", classlibdir, pkgname);
  if (is_dir (libdir)) {
    library_include_paths[n_paths++] = strdup (libdir);
    _hash_put (classlibpaths, libdir, libdir);
  }

  for (i = 0; i < n_paths; i++) {
    strcpy (libdir, expand_path (library_include_paths[i]));

    if ((dir = opendir (libdir)) == NULL)
      _error ("%s: %s.\n", libdir, strerror (errno));

    while ((d = readdir (dir)) != NULL) {
      if (!strncmp (d -> d_name, ".", 1) ||
	  !strncmp (d -> d_name, "..", 2))
	continue;
      sprintf (classfilepath, "%s/%s", libdir, d -> d_name);
      _hash_put (classlibpaths, strdup (classfilepath), d -> d_name);
    }
    closedir (dir);
  }
}

/*
 *  init_user_home_path (), below must be called first.
 */
void init_lib_cache_path (void) {
  char buf[FILENAME_MAX];
#ifdef DJGPP
  strcpy (buf, "/djgpp/include/ctalk/libcache");
  if (file_exists (libcachedir) &&
      !is_dir (libcachedir))
    unlink (libcachedir);
  strcpy (libcachedir, buf);
  if (!file_exists (libcachedir)) {
    mkdir (buf, 0700);
  }
#else
  sprintf (buf, "%s/%s/%s", getenv ("HOME"), ".ctalk", "libcache");
  strcpy (libcachedir, buf);
  if (file_exists (libcachedir) &&
      !is_dir (libcachedir))
    unlink (libcachedir);
  if (!is_dir (libcachedir)) {
    if (mkdir (buf, 0700))
      _error ("%s: %s.\n", buf, strerror (errno));
  }
#endif
}

void init_user_home_path (void) {
  char buf[FILENAME_MAX];
#ifdef DJGPP
  strcpy (buf, "/djgpp/include/ctalk/libcache");
  strcpy (ctalkuserhomedir, buf);
  if (file_exists (ctalkuserhomedir) &&
      !is_dir (ctalkuserhomedir))
    unlink (ctalkuserhomedir);
  if (!file_exists (ctalkuserhomedir)) {
    mkdir (buf, 0700);
  }
#else
  sprintf (buf, "%s/%s", getenv ("HOME"), ".ctalk");
  strcpy (ctalkuserhomedir, buf);
  if (file_exists (ctalkuserhomedir) &&
      !is_dir (ctalkuserhomedir))
    unlink (ctalkuserhomedir);
  if (!is_dir (ctalkuserhomedir)) {
    if (mkdir (buf, 0700))
      _error ("%s: %s.\n", buf, strerror (errno));
  }
#endif
}
