/* $Id: clibtmpl.c,v 1.3 2009/01/08 16:51:40 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.
*/

/*
 *  Translate a macro name to a C99 name.  First check the
 *  name as it is translated by the library, then the C99
 *  name.
 */

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

#define CLIBDIR "libc"
#define CTALKLIBDIR "libctalk"

static struct _c99_names {
  char *lib_name,
    *c99_name;
} c99_names[] = {
#ifdef __GNUC__
  {"_IO_getc", "getc"},
  {"abs",      "abs"},
  {"acos",     "acos"},
  {"acosh",    "acosh"},
  {"asctime",  "asctime"},
  {"asin",     "asin"},
  {"asinh",    "asinh"},
  {"atanh",    "atanh"},
  {"atof",     "atof"},
  {"atoi",     "atoi"},
  {"atol",     "atol"},
  {"atoll",    "atoll"},
  {"cbrt",     "cbrt"},
  {"ceil",     "ceil"},
  {"chdir",    "chdir"},
  {"clearerr", "clearerr"},
  {"clock",    "clock"},
  {"copysign", "copysign"},
  {"cos",      "cos"},
  {"cosh",     "cosh"},
  {"ctime",    "ctime"},
  {"difftime", "difftime"},
  {"erf",      "erf"},
  {"erfc",     "erfc"},
  {"exp",      "exp"},
  {"expm1",    "expm1"},
  {"fabs",     "fabs"},
  {"fabsf",    "fabsf"},
  {"fflush",   "fflush"},
  {"fopen",    "fopen"},
  {"fprintf",  "fprintf"},
  {"fscanf",   "fscanf"},
  {"getchar",  "getchar"},
  {"getcwd",   "getcwd"},
  {"getenv",   "getenv"},
  {"getpid",   "getpid"},
  {"mkdir",    "mkdir"},
  {"printf",   "printf"},
  {"rmdir",    "rmdir"},
  {"scanf",    "scanf"},
  {"sin",      "sin"},
  {"sprintf",  "sprintf"},
  {"sqrt",     "sqrt"},
  {"sscanf",   "sscanf"},
  {"strcat",   "strcat"},
  {"strchr",   "strchr"},
  {"strcasecmp",   "strcasecmp"},
  {"strcmp",   "strcmp"},
  {"strcpy",   "strcpy"},
  {"strerror", "strerror"},
  {"strlen",   "strlen"},
  {"strncat",  "strncat"},
  {"strncasecmp",  "strncasecmp"},
  {"strncmp",  "strncmp"},
  {"strncpy",  "strncpy"},
  {NULL, NULL}
#endif  /* #ifdef __GNUC__ */
};

char *c99_name (char *name, int warn) {
  int i;

  for (i = 0; c99_names[i].lib_name; i++) {
    if (!strcmp (c99_names[i].lib_name, name))
      return c99_names[i].c99_name;
  }

  for (i = 0; c99_names[i].lib_name; i++) {
    if (!strcmp (c99_names[i].c99_name, name))
      return c99_names[i].c99_name;
  }

  if (warn)
    _warning ("c99_name: unknown function %s.\n", name);

  return NULL;
}

char *get_clib_template_file(char *fn_name) {

  char templatedir[FILENAME_MAX],
    templatefile[FILENAME_MAX],
    *filebuf;
  DIR *dir;
  struct dirent *d;
  struct stat statbuf;
  
  if (!fn_name) return NULL;

  strcpy (templatedir, CLASSLIBDIR);
  STRCAT2(templatedir, "/", CLIBDIR);

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

  while ((d = readdir (dir)) != NULL) 
    if (*d -> d_name == *fn_name) break;
  closedir (dir);
    
  if (!d) {
    _warning ("get_clib_template: file for %s not found.\n", fn_name);
    return NULL;
  }

  strcpy (templatefile, templatedir);
  STRCAT2(templatefile, "/", d -> d_name);

  stat (templatefile, &statbuf);

  if ((filebuf = (char *)calloc (statbuf.st_size, sizeof (char))) == NULL)
    _error ("get_clib_template: %s.\n", strerror (errno));

  read_file (filebuf, templatefile);

  return filebuf;
}

char *get_clib_template_fn (char *fn_name) {

  char templatedir[FILENAME_MAX];
  char templatefilename[FILENAME_MAX];
  static char templatefile[FILENAME_MAX];
  DIR *dir;
  struct dirent *d;
  
  if (!fn_name) return NULL;

  strcpy (templatedir, CLASSLIBDIR);
  STRCAT2(templatedir, "/", CLIBDIR);

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

  *templatefilename = 0;
  while ((d = readdir (dir)) != NULL)  {
    if (*d -> d_name == *fn_name) {
      strcpy (templatefilename, d -> d_name);
    }
    if (*templatefilename)
      break;
  }
  closedir (dir);
    
  if (!*templatefilename) {
    _warning ("get_clib_template: file for %s not found.\n", fn_name);
    return NULL;
  }

  strcpy (templatefile, templatedir);
  STRCAT2(templatefile, "/", templatefilename);

  return templatefile;
}


