![]() ![]() | ![]() |
version 1.1, 2000/12/03 21:45:48 | version 1.7, 2003/02/04 14:27:43 | ||
---|---|---|---|
|
|
||
/* -*- mode: C; coding: euc-japan -*- */ | /* -*- mode: C; coding: euc-japan -*- */ | ||
/* $OpenXM$ */ | /* $OpenXM: OpenXM/src/ox_math/sm_ext.c,v 1.6 2003/01/15 10:16:10 ohara Exp $ */ | ||
/* | /* | ||
Copyright (C) Katsuyoshi OHARA, 2000. | Copyright (C) Katsuyoshi OHARA, 2000. | ||
|
|
||
See OpenXM/Copyright/Copyright.mathlink for detail. | See OpenXM/Copyright/Copyright.mathlink for detail. | ||
*/ | */ | ||
/* | |||
Remarks: | |||
file descripter 3 and 4 are already opened by the parent process. | |||
*/ | |||
#include <stdio.h> | #include <stdio.h> | ||
#include <stdlib.h> | #include <stdlib.h> | ||
#include <unistd.h> | #include <unistd.h> | ||
#include <gmp.h> | #include <gmp.h> | ||
#include <mathlink.h> | |||
#include <ox_toolkit.h> | #include <ox_toolkit.h> | ||
#include "sm.h" | #include "sm.h" | ||
extern int flag_mlo_symbol; | static struct { int (*func_ptr)(); int key; } tbl_smcmd[] = { | ||
{sm_executeFunction, SM_executeFunction}, | |||
{sm_executeStringByLocalParser, SM_executeStringByLocalParser}, | |||
{sm_executeStringByLocalParser, SM_executeStringByLocalParserInBatchMode}, | |||
{sm_mathcap, SM_mathcap}, | |||
{sm_set_mathcap, SM_setMathCap}, | |||
{sm_popString, SM_popString}, | |||
{sm_popCMO, SM_popCMO}, | |||
{sm_pops, SM_pops}, | |||
{shutdown, SM_shutdown}, | |||
{NULL, NULL} | |||
}; | |||
/* MathLink independent */ | extern OXFILE *stack_oxfp; | ||
static cmo **stack = NULL; | |||
static int stack_ptr = 0; | |||
static int stack_size = 0; | |||
OXFILE *stack_oxfp = NULL; | |||
#define DIFFERENCE_OF_STACK 1024 | int (*sm_search_f(int code))() | ||
void stack_extend() | |||
{ | { | ||
int newsize = stack_size + DIFFERENCE_OF_STACK; | int i; | ||
cmo **newstack = (cmo **)malloc(sizeof(cmo *)*newsize); | for (i=0; tbl_smcmd[i].key != NULL; i++) { | ||
if (stack != NULL) { | if (code == tbl_smcmd[i].key) { | ||
memcpy(newstack, stack, sizeof(cmo *)*stack_size); | return tbl_smcmd[i].func_ptr; | ||
free(stack); | } | ||
} | } | ||
stack_size = newsize; | return NULL; | ||
stack = newstack; | |||
} | } | ||
void push(cmo* m) | |||
{ | |||
#if DEBUG | |||
symbol_t symp; | |||
if (m->tag == CMO_STRING) { | |||
fprintf(stderr, "ox_math:: a CMO_STRING(%s) was pushed.\n", ((cmo_string *)m)->s); | |||
}else { | |||
symp = lookup_by_tag(m->tag); | |||
fprintf(stderr, "ox_math:: a %s was pushed.\n", symbol_get_key(symp)); | |||
} | |||
#endif | |||
if (stack_ptr >= stack_size) { | |||
stack_extend(); | |||
} | |||
stack[stack_ptr] = m; | |||
stack_ptr++; | |||
} | |||
/* if the stack is empty, then pop() returns (CMO_NULL). */ | |||
cmo *pop() | |||
{ | |||
if (stack_ptr > 0) { | |||
return stack[--stack_ptr]; | |||
} | |||
return new_cmo_null(); | |||
} | |||
void pops(int n) | |||
{ | |||
stack_ptr -= n; | |||
if (stack_ptr < 0) { | |||
stack_ptr = 0; | |||
} | |||
} | |||
void push_error(int errcode, cmo* pushback) | |||
{ | |||
return push((cmo *)make_error_object(errcode, pushback)); | |||
} | |||
/* | |||
If error occurs, then | |||
an sm_*() function returns non-zero and | |||
an error obect is set by a function which calls sm_*(). | |||
*/ | |||
int sm_popCMO(OXFILE* oxfp) | |||
{ | |||
cmo* m = pop(); | |||
#ifdef DEBUG | |||
symbol_t symp = lookup_by_tag(m->tag); | |||
fprintf(stderr, "ox_math:: opecode = SM_popCMO. (%s)\n", symbol_get_key(symp)); | |||
#endif | |||
if (m != NULL) { | |||
send_ox_cmo(oxfp, m); | |||
return 0; | |||
} | |||
return SM_popCMO; | |||
} | |||
int sm_pops(OXFILE* oxfp) | |||
{ | |||
cmo* m = pop(); | |||
if (m != NULL && m->tag == CMO_INT32) { | |||
pops(((cmo_int32 *)m)->i); | |||
return 0; | |||
} | |||
return ERROR_ID_UNKNOWN_SM; | |||
} | |||
/* MathLink dependent */ | /* MathLink dependent */ | ||
int sm_popString(OXFILE* oxfp) | void sm_popString() | ||
{ | { | ||
char *s; | char *s; | ||
cmo *err; | cmo *err; | ||
cmo *m; | cmo *m = pop(); | ||
#ifdef DEBUG | |||
fprintf(stderr, "ox_math:: opecode = SM_popString.\n"); | |||
#endif | |||
m = pop(); | |||
if (m->tag == CMO_STRING) { | if (m->tag == CMO_STRING) { | ||
send_ox_cmo(oxfp, m); | send_ox_cmo(stack_oxfp, m); | ||
}else if ((s = new_string_set_cmo(m)) != NULL) { | }else if ((s = new_string_set_cmo(m)) != NULL) { | ||
send_ox_cmo(oxfp, (cmo *)new_cmo_string(s)); | send_ox_cmo(stack_oxfp, (cmo *)new_cmo_string(s)); | ||
}else { | }else { | ||
err = make_error_object(SM_popString, m); | err = make_error_object(SM_popString, m); | ||
send_ox_cmo(oxfp, err); | send_ox_cmo(stack_oxfp, err); | ||
} | } | ||
return 0; | |||
} | } | ||
int local_execute(char *s) | int local_execute(char *s) | ||
{ | { | ||
extern int flag_mlo_symbol; | |||
if(*s == 'i') { | if(*s == 'i') { | ||
switch(s[1]) { | switch(s[1]) { | ||
case '+': | case '+': | ||
|
|
||
} | } | ||
/* The following function is depend on an implementation of a server. */ | /* The following function is depend on an implementation of a server. */ | ||
int sm_executeStringByLocalParser(OXFILE* oxfp) | void sm_executeStringByLocalParser() | ||
{ | { | ||
symbol_t symp; | |||
cmo* m = pop(); | cmo* m = pop(); | ||
char *s = NULL; | char *s = NULL; | ||
#ifdef DEBUG | |||
fprintf(stderr, "ox_math:: opecode = SM_executeStringByLocalParser.\n"); | |||
#endif | |||
if (m->tag == CMO_STRING | if (m->tag == CMO_STRING | ||
&& strlen(s = ((cmo_string *)m)->s) != 0) { | && strlen(s = ((cmo_string *)m)->s) != 0) { | ||
if (s[0] == ':') { | if (s[0] == ':') { | ||
|
|
||
/* for mathematica */ | /* for mathematica */ | ||
/* Sending the string `s' to mathematica for its evaluation. */ | /* Sending the string `s' to mathematica for its evaluation. */ | ||
ml_evaluateStringByLocalParser(s); | ml_evaluateStringByLocalParser(s); | ||
ml_select(); | m = ml_return(); | ||
push(receive_mlo()); | push(m); | ||
} | } | ||
return 0; | }else { | ||
} | ox_printf(" <%s>", get_symbol_by_tag(m->tag)); | ||
#ifdef DEBUG | push_error(SM_executeStringByLocalParser, m); | ||
symp = lookup_by_tag(m->tag); | } | ||
fprintf(stderr, "ox_math:: error. the top of stack is %s.\n", symbol_get_key(symp)); | |||
#endif | |||
return SM_executeStringByLocalParser; | |||
} | } | ||
int sm_executeFunction(OXFILE* oxfp) | void sm_executeFunction() | ||
{ | { | ||
int i, argc; | int i, argc; | ||
cmo **argv; | cmo **argv; | ||
|
|
||
cmo* m; | cmo* m; | ||
if ((m = pop()) == NULL || m->tag != CMO_STRING) { | if ((m = pop()) == NULL || m->tag != CMO_STRING) { | ||
return SM_executeFunction; | push_error(SM_executeFunction, m); | ||
} | } | ||
func = ((cmo_string *)m)->s; | func = ((cmo_string *)m)->s; | ||
if ((m = pop()) == NULL || m->tag != CMO_INT32) { | if ((m = pop()) == NULL || m->tag != CMO_INT32) { | ||
return SM_executeFunction; | push_error(SM_executeFunction, m); | ||
} | } | ||
argc = ((cmo_int32 *)m)->i; | argc = ((cmo_int32 *)m)->i; | ||
|
|
||
argv[i] = pop(); | argv[i] = pop(); | ||
} | } | ||
ml_executeFunction(func, argc, argv); | ml_executeFunction(func, argc, argv); | ||
ml_select(); | m = ml_return(); | ||
push(receive_mlo()); | push(m); | ||
return 0; | |||
} | } | ||
int sm_mathcap(OXFILE* oxfp) | void sm_mathcap() | ||
{ | { | ||
push((cmo *)oxf_cmo_mathcap(oxfp)); | push((cmo *)oxf_cmo_mathcap(stack_oxfp)); | ||
return 0; | |||
} | } | ||
void sm_set_mathcap(OXFILE *oxfp) | void sm_set_mathcap() | ||
{ | { | ||
cmo_mathcap *m = (cmo_mathcap *)pop(); | cmo_mathcap *m = (cmo_mathcap *)pop(); | ||
if (m->tag == CMO_MATHCAP) { | if (m->tag == CMO_MATHCAP) { | ||
oxf_mathcap_update(oxfp, m); | oxf_mathcap_update(stack_oxfp, m); | ||
}else { | }else { | ||
push_error(-1, m); | push_error(-1, m); | ||
/* an error object must be pushed */ | /* an error object must be pushed */ | ||
} | } | ||
} | |||
int receive_sm_command(OXFILE* oxfp) | |||
{ | |||
return receive_int32(oxfp); | |||
} | |||
int execute_sm_command(OXFILE* oxfp, int code) | |||
{ | |||
int err = 0; | |||
#ifdef DEBUG | |||
symbol_t sp = lookup_by_tag(code); | |||
fprintf(stderr, "ox_math:: %s received.\n", symbol_get_key(sp)); | |||
#endif | |||
switch(code) { | |||
case SM_popCMO: | |||
err = sm_popCMO(oxfp); | |||
break; | |||
case SM_popString: | |||
err = sm_popString(oxfp); | |||
break; | |||
case SM_mathcap: | |||
err = sm_mathcap(oxfp); | |||
break; | |||
case SM_pops: | |||
err = sm_pops(oxfp); | |||
break; | |||
case SM_executeStringByLocalParser: | |||
case SM_executeStringByLocalParserInBatchMode: | |||
err = sm_executeStringByLocalParser(oxfp); | |||
break; | |||
case SM_executeFunction: | |||
err = sm_executeFunction(oxfp); | |||
break; | |||
case SM_shutdown: | |||
shutdown(); | |||
break; | |||
case SM_setMathCap: | |||
pop(); /* ignore */ | |||
break; | |||
default: | |||
fprintf(stderr, "unknown command: %d.\n", code); | |||
err = ERROR_ID_UNKNOWN_SM; | |||
} | |||
if (err != 0) { | |||
push((cmo *)make_error_object(err, new_cmo_null())); | |||
} | |||
} | |||
int sm_run(int code) | |||
{ | |||
return execute_sm_command(stack_oxfp, code); | |||
} | } |