/*
 * $Id: stub.c,v 1.5 2000/07/22 06:13:16 danny Exp $
 *
 * Copyright © 1993, 2000 Free Software Foundation, Inc.
 *
 * 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, 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 software; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 */

static char *rcsid = "$Id: stub.c,v 1.5 2000/07/22 06:13:16 danny Exp $";

/*
 * This is a collection of stubs that are used to call interactive functions.
 *
 * Their responsability is to extract arguments from a command_frame as
 * constructed by the function COMMAND_LOOP.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef	WITH_DMALLOC
#include <dstdlib.h>
#endif

#include "global.h"
#include "cmd.h"
#include "stub.h"

static void
find_args (struct command_arg ** argv_out, int argc, struct command_frame * frame)
{
  int found = 0;
  int pos = 0;
  while (found < argc)
    {
      if (frame->argv[pos].style->representation != cmd_none)
	argv_out[found++] = &frame->argv[pos];
      ++pos;
    }
}

/* These macros are invoked in stubs.h and are used to define
 * the stub functions.  Later, these macros will be redifined 
 * an used to build a table of stub functions.
 */

#define STUB1(STR,NAME, PRE, VAL, TYPE) \
static void \
NAME (frame) \
     struct command_frame * frame; \
{ \
  struct command_arg * argv; \
  find_args (&argv, 1, frame); \
  ((void (*) (TYPE)) frame->cmd->func_func) (PRE argv->val.VAL); \
}

#define STUB2(STR,NAME,PRE1,VAL1,TYPE1,PRE2,VAL2,TYPE2) \
static void \
NAME (frame) \
     struct command_frame * frame; \
{ \
  struct command_arg * argv[2]; \
  find_args (argv, 2, frame); \
  ((void (*) (TYPE1, TYPE2)) frame->cmd->func_func) \
    (PRE1 argv[0]->val.VAL1,  \
     PRE2 argv[1]->val.VAL2); \
}


#define STUB3(STR,NAME,PRE1,VAL1,TYPE1,PRE2,VAL2,TYPE2,PRE3,VAL3,TYPE3) \
static void \
NAME (frame) \
     struct command_frame * frame; \
{ \
  struct command_arg * argv[3]; \
  find_args (argv, 3, frame); \
  frame->cmd->func_func \
    (PRE1 argv[0]->val.VAL1, \
     PRE2 argv[1]->val.VAL2, \
     PRE3 argv[2]->val.VAL3); \
}

#define STUB4(STR,NAME,PRE1,VAL1,TYPE1,PRE2,VAL2,TYPE2,PRE3,VAL3,TYPE3,PRE4,VAL4,TYPE4) \
static void \
NAME (frame) \
     struct command_frame * frame; \
{ \
  struct command_arg * argv[4]; \
  find_args (argv, 4, frame); \
  frame->cmd->func_func \
    (PRE1 argv[0]->val.VAL1, \
     PRE2 argv[1]->val.VAL2, \
     PRE3 argv[2]->val.VAL3, \
     PRE4 argv[3]->val.VAL4); \
}

#define STUB5(STR,NAME,PRE1,VAL1,TYPE1,PRE2,VAL2,TYPE2,PRE3,VAL3,TYPE3,PRE4,VAL4,TYPE4,PRE5,VAL5,TYPE5) \
static void \
NAME (frame) \
     struct command_frame * frame; \
{ \
  struct command_arg * argv[5]; \
  find_args (argv, 5, frame); \
  frame->cmd->func_func \
    (PRE1 argv[0]->val.VAL1, \
     PRE2 argv[1]->val.VAL2, \
     PRE3 argv[2]->val.VAL3, \
     PRE4 argv[3]->val.VAL4, \
     PRE5 argv[4]->val.VAL5); \
}

/* This contains the list of stub functions. */

#include "stubs.h"

/* There is only one `STUB0' so we needn't bother with a macro. */

static void
stub_void (struct command_frame * frame)
{
  frame->cmd->func_func ();
}

/* For define_usr_fmt */
static void
stub_isssssssss (frame)
     struct command_frame * frame;
{
  struct command_arg * argv[10];
  find_args (argv, 10, frame);
  frame->cmd->func_func (argv[0]->val.integer,
			 argv[1]->val.string,
			 argv[2]->val.string,
			 argv[3]->val.string,
			 argv[4]->val.string,
			 argv[5]->val.string,
			 argv[6]->val.string,
			 argv[7]->val.string,
			 argv[8]->val.string,
			 argv[9]->val.string);
}

/* Single character type-codes denote the types of arguments.  A string
 * of type-codes maps to a stub function (hopefully).
 */
struct cmd_stub
{
  char * type;
  cmd_invoker stub;
};

#undef STUB1
#undef STUB2
#undef STUB3
#undef STUB4
#undef STUB5

#define STUB1(STR,NAME,PRE1,VAL1,TYPE1) { STR, NAME },
#define STUB2(STR,NAME,PRE1,VAL1,TYPE1,PRE2,VAL2,TYPE2)  { STR, NAME },
#define STUB3(STR,NAME,PRE1,VAL1,TYPE1,PRE2,VAL2,TYPE2,PRE3,VAL3,TYPE3) \
	{ STR, NAME },
#define STUB4(STR,NAME,PRE1,VAL1,TYPE1,PRE2,VAL2,TYPE2,PRE3,VAL3,TYPE3,PRE4,VAL4,TYPE4) \
	{ STR, NAME },
#define STUB5(STR,NAME,PRE1,VAL1,TYPE1,PRE2,VAL2,TYPE2,PRE3,VAL3,TYPE3,PRE4,VAL4,TYPE4,PRE5,VAL5,TYPE5) \
	{ STR, NAME },

static struct cmd_stub the_stubs[] =
{
  { "", stub_void },
#include "stubs.h"
  { "isssssssss", stub_isssssssss },
  { 0, 0 }
};

/*
 * This looks at the arguments built for the current command and 
 * finds the right stub.
 */
cmd_invoker
find_stub (void)
{
	char	type_buf[100];
	int	x, bufpos;

	/* Figure out a name for the stub we want. */
	for (x = 0, bufpos = 0; x < cmd_argc; ++x)
		if (the_cmd_frame->argv[x].style->representation != cmd_none)
			type_buf[bufpos++] = the_cmd_frame->argv[x].style->representation;
	type_buf[bufpos] = '\0';

	/* Look for the stub. */
	for (x = 0; the_stubs[x].type; ++x)
		if (!stricmp (the_stubs[x].type, type_buf))
			break;

#if 0
	/* This causes an infinite loop */
	if (! the_stubs[x].stub) {
		io_error_msg("internal error: find_stub(%s) no match", type_buf);
	}
#endif

	return the_stubs[x].stub;
}


syntax highlighted by Code2HTML, v. 0.9.1