/* $Id: ctoobj.c,v 1.2 2009/01/04 15:42:13 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 C function calls to objects, run-time functions.
 */

#include <stdio.h>
#include <string.h>
#include "object.h"
#include "message.h"
#include "ctalk.h"

/*
 *  Create an Integer object returned by a C function call.
 *  If within a function, the scope is LOCAL_VAR, else
 *  GLOBAL_VAR.
 */

OBJECT *__ctalkCIntToObj (int i) {

  char buf[MAXMSG];
  int scope;

  sprintf (buf, "%d", i);
  scope = ((get_fn () == NULL) ? GLOBAL_VAR : LOCAL_VAR);
  return __ctalkCreateObjectInit (buf, "Integer", "Magnitude", 
			      scope, buf);
}

OBJECT *__ctalkCLongLongToObj (long long int l) {

  char buf[MAXMSG];
  int scope;

  sprintf (buf, "%lld", l);
  scope = ((get_fn () == NULL) ? GLOBAL_VAR : LOCAL_VAR);
  return __ctalkCreateObjectInit (buf, "LongInteger", "Magnitude", 
			      scope, buf);
}

OBJECT *__ctalkCDoubleToObj (double d) {

  char buf[MAXMSG];

  sprintf (buf, "%f", d);
  return __ctalkCreateObjectInit (buf, "Float", "Magnitude", 
			     ((get_fn () == NULL) ? GLOBAL_VAR : LOCAL_VAR),
				     buf);
}

OBJECT *__ctalkCCharPtrToObj (char *s) {

  return __ctalkCreateObjectInit (s, "String", "Character", 
			     ((get_fn () == NULL) ? GLOBAL_VAR : LOCAL_VAR),
				     s);
}

int __ctalkIsObject (void *v) {
  return IS_OBJECT(v);
}

char *__ctalkCVARReturnClass (CVAR *fn_cvar, char buf[]) {

  CVAR *typedef_cvar;

  if (!strcmp (fn_cvar -> type, "char")) {
    switch (fn_cvar -> n_derefs)
      {
      case 2:
	strcpy (buf, "Array");
	break;
      case 1:
	strcpy (buf, "String");
	break;
      case 0:
	strcpy (buf, "Character");
	break;
      default:
	break;
      }
  } else {
    if (!strcmp (fn_cvar -> type, "int") ||
 	!strcmp (fn_cvar -> type, "short") ||
 	!strcmp (fn_cvar -> type, "long")) {
      if ((!strcmp (fn_cvar -> type, "long") && 
 	   !strcmp (fn_cvar -> qualifier, "long")) ||
 	  (!strcmp (fn_cvar -> qualifier, "long") &&
 	   !strcmp (fn_cvar -> qualifier2, "long")))
 	strcpy (buf, "LongInteger");
      else
 	strcpy (buf, "Integer");
    } else {
      if (!strcmp (fn_cvar -> type, "float") ||
 	  !strcmp (fn_cvar -> type, "double")) {
 	strcpy (buf, "Float");
      } else {
	if ((typedef_cvar = __ctalkGetTypedef (fn_cvar -> type)) != NULL) {
	  __ctalkCVARReturnClass (typedef_cvar, buf); 
	} else {
	  _warning ("Unimplemented type %s in cvar_return_class (). Return class defaulting to %s.\n",
		    fn_cvar -> type, DEFAULT_CLIB_RETURNCLASS);
	  strcpy (buf, DEFAULT_CLIB_RETURNCLASS);
	}
      }
    }
  }
  return buf;
}

char *__ctalkCFUNCReturnClass (CFUNC *fn_cfunc, char buf[]) {

  if (!strcmp (fn_cfunc -> return_type, "char")) {
    switch (fn_cfunc -> return_derefs)
      {
      case 2:
	strcpy (buf, "Array");
	break;
      case 1:
	strcpy (buf, "String");
	break;
      case 0:
	strcpy (buf, "Character");
	break;
      default:
	break;
      }
  } else {
    if (!strcmp (fn_cfunc -> return_type, "int") ||
 	!strcmp (fn_cfunc -> return_type, "short") ||
 	!strcmp (fn_cfunc -> return_type, "long")) {
      if ((!strcmp (fn_cfunc -> return_type, "long") && 
 	   !strcmp (fn_cfunc -> qualifier_type, "long")) ||
 	  (!strcmp (fn_cfunc -> qualifier_type, "long") &&
 	   !strcmp (fn_cfunc -> qualifier2_type, "long")))
 	strcpy (buf, "LongInteger");
      else
 	strcpy (buf, "Integer");
    } else {
      if (!strcmp (fn_cfunc -> return_type, "float") ||
 	  !strcmp (fn_cfunc -> return_type, "double")) {
 	strcpy (buf, "Float");
      }
    }
  }
  return buf;
}

