[BACK]Return to oxserv.c CVS log [TXT][DIR] Up to [local] / OpenXM / src / ox_ntl

File: [local] / OpenXM / src / ox_ntl / oxserv.c (download)

Revision 1.1, Mon Nov 3 03:11:21 2003 UTC (20 years, 6 months ago) by iwane
Branch: MAIN

added ox_ntl

install `NTL'
   % make install-ntl

install ox_ntl
   % make install

EX.
  [1028] load("ntl.rr")$
  [1040] F=ntl.ex_data(4);
  x^16-136*x^14+6476*x^12-141912*x^10+1513334*x^8-7453176*x^6+13950764*x^4-5596840*x^2+46225
  [1041] F=F*subst(F,x,x+1)$
  [1042] ntl.factor(PID,F);
  [[1,1],[x^16+16*x^15-16*x^14-1344*x^13-4080*x^12+32576*x^11+157376*x^10-255232*x^9-2062624*x^8-249088*x^7+10702080*x^6+9126912*x^5-18643712*x^4-24167424*x^3+2712576*x^2+10653696*x+2324736,1],[x^16-136*x^14+6476*x^12-141912*x^10+1513334*x^8-7453176*x^6+13950764*x^4-5596840*x^2+46225,1]]

/* $OpenXM: OpenXM/src/ox_ntl/oxserv.c,v 1.1 2003/11/03 03:11:21 iwane Exp $ */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include "oxserv.h"


#define DPRINTF(x)	printf x; fflush(stdout)

#define delete_cmo(m)

#define OXSERV_INIT_STACK_SIZE 2048
#define OXSERV_EXT_STACK_SIZE  2048

#if 0
/*===========================================================================*
 * for DEBUG
 *===========================================================================*/
#include <stdarg.h>
void
dprintf(const char *fmt, ...)
{
	FILE *fp;
	va_list ap;
	va_start(ap, fmt);
	
	fp = fopen("error.txt", "a");

	vfprintf(fp, fmt, ap);

	fflush(fp);
	fclose(fp);

	va_end(ap);
}
#endif

/*===========================================================================*
 * Global Variables.
 *===========================================================================*/
/* cmo stack */
static int G_ox_stack_size = 0;
static int G_ox_stack_pointer = 0;
static cmo **G_ox_stack = NULL;

/* ox */
static cmo_mathcap *G_oxserv_mathcap = NULL;

/* User Function */
static cmo *(*G_userExecuteFunction)(const char *, cmo **, int) = NULL;
static cmo *(*G_userExecuteStringParser)(const char *) = NULL;

static cmo *(*G_convertCmo)(cmo *) = NULL; /* convert user object ==> cmo */

/*===========================================================================*
 * CMO STACK FUNCTIONs
 *===========================================================================*/
/*****************************************************************************
 * return the number of cmo in the stack.
 * PARAM   : NONE
 * RETURN  : the number of cmo in the stack.
 *****************************************************************************/
#define oxserv_get_stack_pointer()  G_ox_stack_pointer


/*****************************************************************************
 * initialize stack.
 * PARAM   : NONE
 * RETURN  : if success return OXSERV_SUCCESS, else OXSERV_FAILURE.
 *****************************************************************************/
static int
oxserv_init_stack(void)
{
	free(G_ox_stack);

	G_ox_stack_pointer = 0;
	G_ox_stack_size = OXSERV_INIT_STACK_SIZE;
	G_ox_stack = (cmo **)malloc(G_ox_stack_size * sizeof(cmo *));
	if (G_ox_stack == NULL) {
		DPRINTF(("server: %d: %s\n", errno, strerror(errno)));
		return (OXSERV_FAILURE);
	}
	return (OXSERV_SUCCESS);
}

/*****************************************************************************
 * 
 * PARAM   : NONE
 * RETURN  : if success return OXSERV_SUCCESS, else OXSERV_FAILURE.
 *****************************************************************************/
static int
oxserv_extend_stack(void)
{
	int size2 = G_ox_stack_size + OXSERV_EXT_STACK_SIZE;
	cmo **stack2 = (cmo **)malloc(size2 * sizeof(cmo *));
	if (stack2 == NULL) {
		DPRINTF(("server: %d: %s\n", errno, strerror(errno)));
		return (OXSERV_FAILURE);
	}

	memcpy(stack2, G_ox_stack, G_ox_stack_size * sizeof(cmo *));
	free(G_ox_stack);

	G_ox_stack = stack2;
	G_ox_stack_size = size2;

	return (OXSERV_SUCCESS);
}

/*****************************************************************************
 * push a cmo onto the topof the stack.
 * PARAM   : m  : the cmo to be pushed on the stack.
 * RETURN  : if success return OXSERV_SUCCESS, else OXSERV_FAILURE.
 *****************************************************************************/
static int
oxserv_push(cmo *m)
{
	int ret;

	if (G_ox_stack_pointer >= G_ox_stack_size) {
		ret = oxserv_extend_stack();
		if (ret != OXSERV_SUCCESS)
			return (ret);
	}

	G_ox_stack[G_ox_stack_pointer] = m;
	G_ox_stack_pointer++;

	return (OXSERV_SUCCESS);
}

/*****************************************************************************
 * remove thd CMO at the top of this stack and
 * returns that cmo as the value of this function.
 * PARAM   : NONE
 * RETURN  : CMO at the top of the stack.
 *****************************************************************************/
static cmo *
oxserv_pop(void)
{
	cmo *c;
	if (G_ox_stack_pointer > 0) {
		G_ox_stack_pointer--;
		c = G_ox_stack[G_ox_stack_pointer];
		G_ox_stack[G_ox_stack_pointer] = NULL;
		return (c);
	}
	return (NULL);
}

/*****************************************************************************
 * return the cmo at the specified position in the stack without removing it from the stack.
 * PARAM : NONE
 * RETURN: thd cmo at the specified position in the stack.
 *****************************************************************************/
static cmo *
oxserv_get(int i)
{
	if (i < G_ox_stack_pointer && i >= 0) {
		return (G_ox_stack[i]);
	}
	return (NULL);
}


/*****************************************************************************
 * return the cmo at the top of the stack without removing it from the stack.
 * PARAM : NONE
 * RETURN: the cmo at the top of the stack.
 *****************************************************************************/
static cmo *
oxserv_peek(void)
{
	return (oxserv_get(G_ox_stack_pointer - 1));
}

/*****************************************************************************
 *
 * defined for SM_pops
 * 
 * PARAM : n : remove count
 * RETURN: NONE
 *****************************************************************************/
static void
oxserv_remove(int n)
{
	int i;
	cmo *m;

	if (n > G_ox_stack_size)
		n = G_ox_stack_size;

	for (i = 0; i < n; i++) {
		--G_ox_stack_pointer;
		m = G_ox_stack[G_ox_stack_pointer];
		G_ox_stack[G_ox_stack_pointer] = NULL;
		delete_cmo(m);
	}
}


/*===========================================================================*
 * OX_SERVER
 *===========================================================================*/

/*****************************************************************************
 * pop n and to discard element from the stack
 * PARAM : fd : OXFILE
 * RETURN: NONE
 *****************************************************************************/
static void
oxserv_sm_popCMO(OXFILE *fd)
{
	cmo *m = oxserv_pop();
	if (m == NULL) {
		m = new_cmo_null();
	} else if (G_convertCmo) {
		m = G_convertCmo(m);
	}

	send_ox_cmo(fd, m);

	delete_cmo(m);
}

/*****************************************************************************
 * pop an cmo from stack, convert it into a string according to the
 * output format of the local system, and send the string.
 * PARAM : fd : OXFILE
 * RETURN: NONE
 *****************************************************************************/
static void
oxserv_sm_popString(OXFILE *fd)
{
	char *str;
	cmo *m = oxserv_pop();
	cmo_string *m_str;

	if (m == NULL)
		m = new_cmo_null();

	str = new_string_set_cmo(m);

	m_str = new_cmo_string(str);

	send_ox_cmo(fd, (cmo *)m_str);

	delete_cmo(m);
	delete_cmo(m_str);

/* free(str); */
}

/*****************************************************************************
 * pop n and to discard element from the stack
 * PARAM : fd : OXFILE
 * RETURN: NONE
 *****************************************************************************/
static void
oxserv_sm_pops()
{
	cmo_int32 *c;

	c = (cmo_int32 *)oxserv_pop(); /* suppose */

	oxserv_remove(c->i)

	delete_cmo(c);
}

/*****************************************************************************
 * for SM_getsp
 *
 * PARAM : fd : OXFILE
 * RETURN: NONE
 *****************************************************************************/
static void
oxserv_sm_getsp()
{
	cmo_int32 *m = new_cmo_int32(oxserv_get_stack_pointer());
	oxserv_push((cmo *)m);
}

/*****************************************************************************
 * 
 * PARAM : ver    : 
 *       : vstr   : 
 *       : sysname:
 *       : cmos   :
 *       : sms    :
 * RETURN: NONE
 * SEE   : oxserv_set();
 *****************************************************************************/
static void
oxserv_mathcap_init(int ver, char *vstr, char *sysname, int *cmos, int *sms)
{
	int i;

	int local_sms[] = {
		SM_popCMO,
		SM_mathcap,
		SM_setMathCap,
		SM_pops,
		SM_getsp,
		SM_popString,
		SM_pushCMOtag,
		0,
		SM_executeFunction,
		SM_dupErrors,
		SM_executeStringByLocalParser,
		SM_executeStringByLocalParserInBatchMode,
		SM_shutdown,
		0,
	};

	/* depend on ox_toolkit */
	int local_cmos[] = {
		CMO_ERROR2,
		CMO_NULL,
		CMO_INT32,
		CMO_STRING,
		CMO_MATHCAP,
		CMO_LIST,
		CMO_MONOMIAL32,
		CMO_ZZ,
		CMO_ZERO,
		CMO_RECURSIVE_POLYNOMIAL,
		CMO_DISTRIBUTED_POLYNOMIAL,
		CMO_POLYNOMIAL_IN_ONE_VARIABLE,
		CMO_DMS_GENERIC,
		CMO_RING_BY_NAME,
		CMO_INDETERMINATE,
		CMO_TREE,
		CMO_LAMBDA,
		0,
		CMO_QQ,
		CMO_ATTRIBUTE_LIST,
		CMO_DMS,
		CMO_DMS_OF_N_VARIABLES,
		CMO_LIST_R,
		CMO_INT32COEFF,
		CMO_RATIONAL,
		CMO_DATUM,
		0,
	};

	if (sms == NULL) {
		sms = local_sms;

		for (i = 0; sms[i] != 0; i++)
			;
		if (G_userExecuteFunction != NULL)
			sms[i++] = SM_executeFunction;

		if (G_userExecuteStringParser != NULL) {
			sms[i++] = SM_executeStringByLocalParser;
			sms[i++] = SM_executeStringByLocalParserInBatchMode;
		}

		sms[i] = 0;
	}
	if (cmos == NULL)
		cmos = local_cmos;

	mathcap_init(ver, vstr, sysname, cmos, sms);

	delete_cmo(G_oxserv_mathcap);

	G_oxserv_mathcap = mathcap_get(new_mathcap());
}

static void
oxserv_sm_mathcap()
{
	if (G_oxserv_mathcap == NULL) {
		oxserv_mathcap_init(0, "", "oxserv", NULL, NULL);
	}

	oxserv_push((cmo *)G_oxserv_mathcap);
}

static void
oxserv_sm_executeStringByLocalParserInBatchMode(void)
{
	cmo_string *str = (cmo_string *)oxserv_peek();
	cmo *c;
	c = G_userExecuteStringParser(str->s);
	oxserv_push(c);
}

static void
oxserv_sm_executeStringByLocalParser(void)
{
	cmo_string *str = (cmo_string *)oxserv_pop();
	cmo *c;
	c = G_userExecuteStringParser(str->s);
	oxserv_push(c);
}



static void
oxserv_sm_executeFunction(void)
{
	int i;
	cmo_string *name = (cmo_string *)oxserv_pop();
	cmo_int32 *cnt = (cmo_int32 *)oxserv_pop();
	cmo **arg = (cmo **)malloc(cnt->i * sizeof(cmo *));
	cmo *ret;

	for (i = 0; i < cnt->i; i++) {
		arg[i] = oxserv_pop();
	}

	/* user function */
	ret = G_userExecuteFunction(name->s, arg, cnt->i);

	oxserv_push(ret);

	for (i = 0; i < cnt->i; i++) {
		delete_cmo(arg[i]);
	}

	delete_cmo(name);
	delete_cmo(cnt);

	free(arg);
}

static void
oxserv_sm_pushCMOtag()
{
	cmo *c = oxserv_peek();
	cmo_int32 *tag = new_cmo_int32(c->tag);

	oxserv_push((cmo *)tag);
}


static void
oxserv_sm_dupErrors()
{
	cmo_list *list;
	cmo *c;
	int i;

	list = new_cmo_list();

	for (i = 0; i < oxserv_get_stack_pointer(); i++) {
		c = oxserv_get(i);
		if (c->tag == CMO_ERROR2) {
			list_append(list, c);
		}
	}

	oxserv_push((cmo *)list);
}


static int
oxserv_receive_and_execute_sm_command(OXFILE *fd)
{
	int code = receive_int32(fd);

	DPRINTF(("SM_CODE=%d=0x%x\n", code, code));

	switch (code) {
	case SM_popCMO:
		oxserv_sm_popCMO(fd);
		break;
	case SM_executeStringByLocalParser:
		if (G_userExecuteStringParser)
			oxserv_sm_executeStringByLocalParser();
		break;
	case SM_executeStringByLocalParserInBatchMode:
		if (G_userExecuteStringParser)
			oxserv_sm_executeStringByLocalParserInBatchMode();
		break;
	case SM_pops:
		oxserv_sm_pops();
		break;
	case SM_popString:
		oxserv_sm_popString(fd);
		break;
	case SM_getsp:
		oxserv_sm_getsp();
		break;
	case SM_mathcap:
		oxserv_sm_mathcap();
		break;
	case SM_setMathCap:
		/* dont support */
		oxserv_pop();
		break;
	case SM_executeFunction:
		if (G_userExecuteFunction)
			oxserv_sm_executeFunction();
		break;
	case SM_pushCMOtag:
		oxserv_sm_pushCMOtag();
		break;
	case SM_dupErrors:
		oxserv_sm_dupErrors();
		break;
	default:
		break;
	}
	return (OXSERV_SUCCESS);
}


/*****************************************************************************
 * reveice ox_data
 * PARAM : fd : OXFILE
 * RETURN: NONE
 *****************************************************************************/
int
oxserv_receive(OXFILE *fd)
{
	int tag;
	cmo *c;
	int ret = OXSERV_SUCCESS;

	tag = receive_ox_tag(fd);

	DPRINTF(("oxserv_TAG=%d=0x%x\n", tag, tag));
	switch (tag) {
	case OX_DATA:
		c = receive_cmo(fd);
		DPRINTF(("CMO_TAG=%d=0x%x\n", c->tag, c->tag));
		oxserv_push(c);
		break;

	case OX_COMMAND:
		ret = oxserv_receive_and_execute_sm_command(fd);
		break;

	default:
		DPRINTF(("receive unknown ox_tag: %d=0x%x\n", tag, tag));
		return (OXSERV_FAILURE);
	}

	return (ret);
}


/*****************************************************************************
 * initialize oxserver
 *
 * PARAM : see oxserv_mathcap_init()
 * RETURN: NONE
 * SEE   : oxserv_mathcap_init()
 *       : oxserv_set();
 *****************************************************************************/
int
oxserv_init(OXFILE *oxfp, int ver, char *vstr, char *sysname, int *cmos, int *sms)
{
	int ret;

	ret = oxserv_init_stack();
	if (ret != OXSERV_SUCCESS)
		return (ret);

	oxserv_mathcap_init(ver, vstr, sysname, cmos, sms);

	oxf_determine_byteorder_server(oxfp);

	return (OXSERV_SUCCESS);
}


/*****************************************************************************
 * set oxserver
 * PARAM : mode : mode
 *              :
 *       : ptr  :
 *       : rsv  : reserve space.
 * RETURN: NONE
 * SEE   : 
 *****************************************************************************/
int
oxserv_set(int mode, void *ptr, void *rsv)
{
	switch (mode) {
	case OXSERV_SET_EXECUTE_FUNCTION:
		G_userExecuteFunction = (cmo *(*)(const char *, cmo **, int))ptr;
		break;
	case OXSERV_SET_EXECUTE_STRING_PARSER:
		G_userExecuteStringParser = (cmo *(*)(const char *))ptr;
		break;
	case OXSERV_SET_CONVERT_CMO:
		G_convertCmo = (cmo *(*)(cmo *))ptr;
		break;
	default:
		return (OXSERV_FAILURE);
	}


	return (OXSERV_SUCCESS);
}


/*****************************************************************************
 * destroy
 * PARAM : mode : mode
 *              :
 *       : ptr  :
 *       : rsv  : reserve space.
 * RETURN: NONE
 * SEE   : 
 *****************************************************************************/
void
oxserv_dest()
{
	free(G_ox_stack);
}
	

#if 0

cmo *
oxserv_executeFunction(const char *func, cmo **arg, int argc)
{
	int i;

	printf("%s()\n", func);

	for (i = 0; i < argc; i++) {
		printf("\t%2d: %s\n", i, new_string_set_cmo(arg[i]));
	}

	return ((cmo *)new_cmo_int32(0));
}

int
main(int argc, char *argv[])
{
	int fd = 3;
	int i;
	int ret;

	OXFILE *oxfp = oxf_open(fd);

	ox_stderr_init(stderr);

	oxserv_init(0, "$Date: 2003/11/02 16:39:16 $", "oxserv", NULL, NULL);

	DPRINTF(("main - start\n"));
	for (i = 0;; i++) {
		DPRINTF(("@"));
		ret = oxserv_receive(oxfp);
		if (ret != OXSERV_SUCCESS)
			break;
	}

	oxf_close(fd);
	delete_cmo(G_oxserv_mathcap);

	return (0);
}

#endif