/* $Id: subscr.c,v 1.2 2009/01/04 15:49:32 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.
*/

/*
 *   For arguments that have objects as subscripts, create a 
 *   run time expression.
 *   C (at least GNU C) doesn't allow function calls within
 *   subscripts, so we can't simply use __ctalkEvalExpr () 
 *   if there are objects in the subscripts.
 */

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

static int subscript_ext = 0;

int subscript_object_expr = FALSE;

static char tmpvarname[MAXMSG];
static char exprbuf[MAXMSG];
static char regcvarbuf[MAXMSG];
static char argbuf[MAXMSG];

#define SUBSCRIPT_CVAR_TEMPLATE "\n    { \n\
      int %s; \n\
      %s \n\
      %s \n\
      %s \n\
  }\n\
"

char *subscript_expr (MESSAGE_STACK messages, int start, int end,
		      OBJECT *rcvr_object, METHOD *method,
		      char *array_basename, CVAR *v) {
  static char buf[MAXMSG];
  char array_expr[MAXLABEL];
  int i;

  for (i = start; i >= end; i--)
    strcat (buf, messages[i] -> name);

  sprintf (tmpvarname, SUBSCRIPT_VAR_FMT, subscript_ext++);

  sprintf (exprbuf, TMP_SUBSCRIPT_FMT, tmpvarname, buf);

  sprintf (array_expr, "%s[%s]", array_basename, tmpvarname);

  sprintf (regcvarbuf,
	   "%s (\"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", %d, %d, %d, (void *)%s);\n",
	   REGISTER_C_METHOD_ARG,
	   ((v -> decl) ? v -> decl : NULLSTR),
	   ((v -> type) ? v -> type : NULLSTR),
	   ((v -> qualifier) ? v -> qualifier : NULLSTR),
	   ((v -> qualifier2) ? v -> qualifier2 : NULLSTR),
	   ((v -> storage_class) ? v -> storage_class : NULLSTR),
	   array_expr,
	   v -> is_unsigned,
	   /* Should work for now.  At present, cvar_object () 
	    * (rt_cvar.c) only handles arrays of type char **.
	    */
	   v -> n_derefs - 1,
	   LOCAL_VAR,
	   array_expr);

  sprintf (argbuf, "__ctalk_arg (\"%s\", \"%s\", (void *)\"%s\");", 
	   rcvr_object -> __o_name, method -> name, array_expr);

  sprintf (buf, SUBSCRIPT_CVAR_TEMPLATE, tmpvarname, exprbuf, regcvarbuf,
	   argbuf);

  return buf;
}

