/* $Id: rtobjref.c,v 1.13 2009/02/08 16:43:03 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 library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library 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
  Lesser 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.
*/

/*
 *  Functions to handle object reference counts.  The arguments to 
 *  the function calls should use the OBJREF() macro, which is defined
 *  in object.h.
 */

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

/*
 *  OBJREF_T is defined in object.h.
 */

void __refObj (OBJREF_T ref1, OBJREF_T ref2) {
  OBJECT *var;
  if (*ref1 && IS_OBJECT (*ref1)) {
    --(*ref1) -> nrefs;
    for (var = (*ref1) -> instancevars; var; var = var -> next)
      __objRefCntDec (OBJREF (var));
  }
  *ref1 = *ref2;
  ++(*ref2) -> nrefs;
  for (var = (*ref2) -> instancevars; var; var = var -> next)
    __objRefCntInc (OBJREF (var));
}

void __objRefCntInc (OBJREF_T obj_p) {
  OBJECT *vars;
  if (! *obj_p || !IS_OBJECT (*obj_p)) {
#ifdef DEBUG_INVALID_OBJ_REFS
    _warning ("__objRefCntInc: Not an object.\n");
#endif
  } else {
    (*obj_p) -> nrefs++;
    for (vars = (*obj_p) -> instancevars; vars; vars = vars -> next)
      __objRefCntInc (OBJREF (vars));
  }
}

void __objRefCntDec (OBJREF_T obj_p) {
  OBJECT *vars;
  if (! *obj_p || !IS_OBJECT (*obj_p)) {
#ifdef DEBUG_INVALID_OBJ_REFS
    _warning ("__objRefCntDec: Not an object.\n");
#endif
  } else {
    (*obj_p) -> nrefs--;
    for (vars = (*obj_p) -> instancevars; 
	 vars && IS_OBJECT(vars); 
	 vars = vars -> next)
      __objRefCntDec (OBJREF (vars));
  }
}

void __objRefCntSet (OBJREF_T obj_p, int nrefs) {
  OBJECT *vars;
  if (! *obj_p || !IS_OBJECT (*obj_p)) {
#ifdef DEBUG_INVALID_OBJ_REFS
    _warning ("__objRefCntSet: Not an object.\n");
#endif
  } else {
    (*obj_p) -> nrefs = nrefs;
    for (vars = (*obj_p) -> instancevars; vars; vars = vars -> next)
      __objRefCntSet (OBJREF (vars), nrefs);
  }
}

OBJECT *obj_ref_str (char *__s) {
  OBJECT *__r;
  if ((__s[0] && (__s[0] == '0')) && 
      (__s[1] && (__s[1] == 'x')) && 
      (__s[2] && isxdigit((int)__s[2])) && 
      (__s[3] && isxdigit((int)__s[3])) && 
      (__s[4] && isxdigit((int)__s[4])) && 
      (__s[5] && isxdigit((int)__s[5])) && 
      (__s[6] && isxdigit((int)__s[6])) && 
      (__s[7] && isxdigit((int)__s[7])) && 
      (__s[8] && isxdigit((int)__s[8]))) {
    if ((__r = (OBJECT *)__ctalkStrToPtr (__s)) != NULL) {
      if (IS_OBJECT(__r)) {
	return __r;
      }
    }
  }
  return NULL;
}

void *generic_ptr_str (char *__s) {
  void *__r;
  int i;
  if ((__s[0] && (__s[0] == '0')) && 
      (__s[1] && (__s[1] == 'x'))) {
    for (i = 2; __s[i]; ++i) {
      if (!isxdigit ((int)__s[i])) {
	return NULL;
      }
    }
  } else {
    return NULL;
  }
  if ((__r = __ctalkStrToPtr (__s)) != NULL) {
    return __r;
  }
  return NULL;
}
