version 1.2, 1999/11/02 06:11:58 |
version 1.10, 1999/11/29 12:09:58 |
|
|
/* -*- mode: C; coding: euc-japan -*- */ |
/* -*- mode: C; coding: euc-japan -*- */ |
/* $OpenXM$ */ |
/* $OpenXM: OpenXM/src/ox_math/serv2.c,v 1.9 1999/11/19 20:51:36 ohara Exp $ */ |
/* $Id$ */ |
|
|
|
/* Open Mathematica サーバ */ |
/* Open Mathematica サーバ */ |
/* ファイルディスクリプタ 3, 4 は open されていると仮定して動作する. */ |
/* ファイルディスクリプタ 3, 4 は open されていると仮定して動作する. */ |
|
|
/* MathLink との通信部分 */ |
|
|
|
#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 <mathlink.h> |
#include "ox.h" |
#include "ox.h" |
|
#include "parse.h" |
#include "serv2.h" |
#include "serv2.h" |
|
|
#define UNKNOWN_SM_COMMAND 50000 |
extern int flag_mlo_symbol; |
#define MATH_ERROR 50001 |
|
|
|
|
|
/* MLINK はポインタ型. */ |
|
MLINK lp = NULL; |
|
|
|
/* Mathematica を起動する. */ |
|
int MATH_init() |
|
{ |
|
int argc = 2; |
|
char *argv[] = {"-linkname", "math -mathlink"}; |
|
|
|
if(MLInitialize(NULL) != NULL) { |
|
lp = MLOpen(argc, argv); |
|
if(lp != NULL) { |
|
return 0; |
|
} |
|
} |
|
exit(1); |
|
} |
|
|
|
int MATH_exit() |
|
{ |
|
/* quit Mathematica then close the link */ |
|
MLPutFunction(lp, "Exit", 0); |
|
MLClose(lp); |
|
} |
|
|
|
char *MATH_getObject() |
|
{ |
|
char *s; |
|
|
|
/* skip any packets before the first ReturnPacket */ |
|
while (MLNextPacket(lp) != RETURNPKT) { |
|
usleep(10); |
|
MLNewPacket(lp); |
|
} |
|
/* いまはタイプにかかわらず文字列を取得する. */ |
|
switch(MLGetNext(lp)) { |
|
case MLTKINT: |
|
fprintf(stderr, "type is INTEGER.\n"); |
|
MLGetString(lp, &s); |
|
break; |
|
case MLTKSTR: |
|
fprintf(stderr, "type is STRING.\n"); |
|
MLGetString(lp, &s); |
|
break; |
|
default: |
|
MLGetString(lp, &s); |
|
} |
|
return s; |
|
} |
|
|
|
cmo *MATH_getObject2() |
|
{ |
|
char *s; |
|
cmo *m; |
|
char **sp; |
|
int i,n; |
|
|
|
/* skip any packets before the first ReturnPacket */ |
|
while (MLNextPacket(lp) != RETURNPKT) { |
|
usleep(10); |
|
MLNewPacket(lp); |
|
} |
|
/* いまはタイプにかかわらず文字列を取得する. */ |
|
switch(MLGetNext(lp)) { |
|
case MLTKINT: |
|
fprintf(stderr, "type is INTEGER.\n"); |
|
MLGetString(lp, &s); |
|
m = (cmo *)new_cmo_zz_set_string(s); |
|
break; |
|
case MLTKSTR: |
|
fprintf(stderr, "type is STRING.\n"); |
|
MLGetString(lp, &s); |
|
m = (cmo *)new_cmo_string(s); |
|
break; |
|
case MLTKERR: |
|
fprintf(stderr, "type is ERROR.\n"); |
|
m = (cmo *)gen_error_object(MATH_ERROR); |
|
break; |
|
case MLTKSYM: |
|
fprintf(stderr, "MLTKSYM.\n"); |
|
MLGetString(lp, s); |
|
m = (cmo *)new_cmo_string(s); |
|
break; |
|
case MLTKFUNC: |
|
fprintf(stderr, "MLTKFUNC.\n"); |
|
#if DEBUG |
|
MLGetString(lp, s); |
|
m = (cmo *)new_cmo_string(s); |
|
break; |
|
#endif |
|
MLGetFunction(lp, sp, &n); |
|
fprintf(stderr, "n = %d\n", n); |
|
for (i=0; i<=n; i++) { |
|
fprintf(stderr, "%s "); |
|
} |
|
fprintf(stderr, "\n"); |
|
m = (cmo *)new_cmo_string(s); |
|
break; |
|
case MLTKREAL: |
|
fprintf(stderr, "MLTKREAL is not supported: we use MLTKSTR.\n"); |
|
MLGetString(lp, &s); |
|
m = (cmo *)new_cmo_string(s); |
|
break; |
|
default: |
|
fprintf(stderr, "unknown type: we use STRING.\n"); |
|
MLGetString(lp, &s); |
|
m = (cmo *)new_cmo_string(s); |
|
} |
|
return m; |
|
} |
|
|
|
int MATH_sendObject(cmo *m) |
|
{ |
|
char *s; |
|
switch(m->tag) { |
|
case CMO_INT32: |
|
MLPutInteger(lp, ((cmo_int32 *)m)->i); |
|
break; |
|
case CMO_STRING: |
|
s = ((cmo_string *)m)->s; |
|
MLPutString(lp, s); |
|
fprintf(stderr, "put %s.", s); |
|
break; |
|
default: |
|
MLPutFunction(lp, "ToExpression", 1); |
|
s = convert_cmo_to_cstring(m); |
|
MLPutString(lp, s); |
|
fprintf(stderr, "put %s.", s); |
|
break; |
|
} |
|
} |
|
|
|
int MATH_evaluateStringByLocalParser(char *str) |
|
{ |
|
MLPutFunction(lp, "ToExpression", 1); |
|
MLPutString(lp, str); |
|
MLEndPacket(lp); |
|
} |
|
|
|
int MATH_executeFunction(char *function, int argc, cmo *argv[]) |
|
{ |
|
int i; |
|
MLPutFunction(lp, function, argc); |
|
for (i=0; i<argc; i++) { |
|
MATH_sendObject(argv[i]); |
|
} |
|
MLEndPacket(lp); |
|
} |
|
|
|
/* MathLink 非依存部分 */ |
/* MathLink 非依存部分 */ |
|
|
#define SIZE_OPERAND_STACK 2048 |
#define SIZE_OPERAND_STACK 2048 |
Line 178 static int Stack_Pointer = 0; |
|
Line 25 static int Stack_Pointer = 0; |
|
int initialize_stack() |
int initialize_stack() |
{ |
{ |
Stack_Pointer = 0; |
Stack_Pointer = 0; |
} |
} |
|
|
int push(cmo* m) |
int push(cmo* m) |
{ |
{ |
#if DEBUG |
#if DEBUG |
fprintf(stderr, "server:: a cmo is pushed: tag == %d.\n", m->tag); |
symbol *symp; |
|
|
if (m->tag == CMO_STRING) { |
if (m->tag == CMO_STRING) { |
fprintf(stderr, "server:: %s\n", ((cmo_string *)m)->s); |
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", symp->key); |
} |
} |
#endif |
#endif |
Operand_Stack[Stack_Pointer] = m; |
Operand_Stack[Stack_Pointer] = m; |
Stack_Pointer++; |
Stack_Pointer++; |
if (Stack_Pointer >= SIZE_OPERAND_STACK) { |
if (Stack_Pointer >= SIZE_OPERAND_STACK) { |
fprintf(stderr, "stack over flow.\n"); |
fprintf(stderr, "stack over flow.\n"); |
exit(1); |
Stack_Pointer--; |
} |
} |
} |
} |
|
|
/* エラーのときは NULL を返す */ |
/* スタックが空のときは, (CMO_NULL) をかえす. */ |
/* gen_error_object(SM_popCMO); */ |
|
/* CMO_ERROR2 */ |
|
|
|
cmo* pop() |
cmo* pop() |
{ |
{ |
if (Stack_Pointer > 0) { |
if (Stack_Pointer > 0) { |
Stack_Pointer--; |
Stack_Pointer--; |
return Operand_Stack[Stack_Pointer]; |
return Operand_Stack[Stack_Pointer]; |
} |
} |
return NULL; |
return new_cmo_null(); |
} |
} |
|
|
void pops(int n) |
void pops(int n) |
Line 217 void pops(int n) |
|
|
} |
} |
} |
} |
|
|
|
|
/* sm_XXX 関数群は、エラーのときは 0 以外の値を返し、呼び出し元で |
/* sm_XXX 関数群は、エラーのときは 0 以外の値を返し、呼び出し元で |
エラーオブジェクトをセットする */ |
エラーオブジェクトをセットする */ |
int sm_popCMO(int fd_write) |
int sm_popCMO(int fd_write) |
{ |
{ |
cmo* m = pop(); |
cmo* m = pop(); |
|
#ifdef DEBUG |
|
symbol *symp = lookup_by_tag(m->tag); |
|
fprintf(stderr, "ox_math:: opecode = SM_popCMO. (%s)\n", symp->key); |
|
#endif |
|
|
fprintf(stderr, "code: SM_popCMO.\n"); |
|
if (m != NULL) { |
if (m != NULL) { |
send_ox_cmo(fd_write, m); |
send_ox_cmo(fd_write, m); |
return 0; |
return 0; |
Line 239 int sm_pops(int fd_write) |
|
Line 89 int sm_pops(int fd_write) |
|
pops(((cmo_int32 *)m)->i); |
pops(((cmo_int32 *)m)->i); |
return 0; |
return 0; |
} |
} |
return UNKNOWN_SM_COMMAND; |
return ERROR_ID_UNKNOWN_SM; |
} |
} |
|
|
/* MathLink 依存部分 */ |
/* MathLink 依存部分 */ |
int sm_popString(int fd_write) |
int sm_popString(int fd_write) |
{ |
{ |
char* s; |
char *s; |
cmo* m; |
cmo *err; |
|
cmo *m; |
|
|
#ifdef DEBUG |
#ifdef DEBUG |
fprintf(stderr, "code: SM_popString.\n"); |
fprintf(stderr, "ox_math:: opecode = SM_popString.\n"); |
#endif |
#endif |
|
|
if ((m = pop()) != NULL && (s = convert_cmo_to_cstring(m)) != NULL) { |
m = pop(); |
|
if (m->tag == CMO_STRING) { |
|
send_ox_cmo(fd_write, m); |
|
}else if ((s = convert_cmo_to_string(m)) != NULL) { |
send_ox_cmo(fd_write, (cmo *)new_cmo_string(s)); |
send_ox_cmo(fd_write, (cmo *)new_cmo_string(s)); |
return 0; |
}else { |
|
err = make_error_object(SM_popString, m); |
|
send_ox_cmo(fd_write, err); |
} |
} |
return SM_popString; |
return 0; |
} |
} |
|
|
|
int local_execute(char *s) |
|
{ |
|
if(*s == 'i') { |
|
switch(s[1]) { |
|
case '+': |
|
flag_mlo_symbol = FLAG_MLTKSYM_IS_STRING; |
|
break; |
|
case '-': |
|
case '=': |
|
default: |
|
flag_mlo_symbol = FLAG_MLTKSYM_IS_INDETERMINATE; |
|
} |
|
} |
|
return 0; |
|
} |
|
|
/* この関数はサーバに依存する. */ |
/* この関数はサーバに依存する. */ |
int sm_executeStringByLocalParser(int fd_write) |
int sm_executeStringByLocalParser(int fd_write) |
{ |
{ |
cmo* m = NULL; |
symbol *symp; |
|
cmo* m = pop(); |
|
char *s = NULL; |
#ifdef DEBUG |
#ifdef DEBUG |
fprintf(stderr, "code: SM_executeStringByLocalParser.\n"); |
fprintf(stderr, "ox_math:: opecode = SM_executeStringByLocalParser.\n"); |
#endif |
#endif |
if ((m = pop()) != NULL && m->tag == CMO_STRING) { |
|
/* for mathematica */ |
if (m->tag == CMO_STRING |
/* mathematica に文字列を送って評価させる */ |
&& strlen(s = ((cmo_string *)m)->s) != 0) { |
MATH_evaluateStringByLocalParser(((cmo_string *)m)->s); |
if (s[0] == ':') { |
push(MATH_getObject2()); |
local_execute(++s); |
|
}else { |
|
/* for mathematica */ |
|
/* mathematica に文字列を送って評価させる */ |
|
ml_evaluateStringByLocalParser(s); |
|
push(ml_get_object()); |
|
} |
return 0; |
return 0; |
} |
} |
fprintf(stderr, "cannot execute: top of stack is not string!(%p, %d)\n", m, m->tag); |
#ifdef DEBUG |
|
symp = lookup_by_tag(m->tag); |
|
fprintf(stderr, "ox_math:: error. the top of stack is %s.\n", symp->key); |
|
#endif |
return SM_executeStringByLocalParser; |
return SM_executeStringByLocalParser; |
} |
} |
|
|
Line 292 int sm_executeFunction(int fd_write) |
|
Line 175 int sm_executeFunction(int fd_write) |
|
if ((m = pop()) == NULL || m->tag != CMO_INT32) { |
if ((m = pop()) == NULL || m->tag != CMO_INT32) { |
return SM_executeFunction; |
return SM_executeFunction; |
} |
} |
|
|
argc = ((cmo_int32 *)m)->i; |
argc = ((cmo_int32 *)m)->i; |
argv = malloc(sizeof(cmo *)*argc); |
argv = malloc(argc*sizeof(cmo *)); |
for (i=0; i<argc; i++) { |
for (i=0; i<argc; i++) { |
if ((argv[i] = pop()) == NULL) { |
argv[i] = pop(); |
return SM_executeFunction; |
|
} |
|
} |
} |
MATH_executeFunction(func, argc, argv); |
ml_executeFunction(func, argc, argv); |
push(MATH_getObject2()); |
push(ml_get_object()); |
return 0; |
return 0; |
} |
} |
|
|
Line 310 int sm_executeFunction(int fd_write) |
|
Line 192 int sm_executeFunction(int fd_write) |
|
|
|
int sm_mathcap(int fd_write) |
int sm_mathcap(int fd_write) |
{ |
{ |
cmo* c = make_mathcap_object(VERSION, ID_STRING); |
push(make_mathcap_object(VERSION, ID_STRING)); |
push(c); |
|
return 0; |
return 0; |
} |
} |
|
|
Line 323 int receive_sm_command(int fd_read) |
|
Line 204 int receive_sm_command(int fd_read) |
|
int execute_sm_command(int fd_write, int code) |
int execute_sm_command(int fd_write, int code) |
{ |
{ |
int err = 0; |
int err = 0; |
|
#ifdef DEBUG |
|
symbol *sp = lookup_by_tag(code); |
|
fprintf(stderr, "ox_math:: %s received.\n", sp->key); |
|
#endif |
|
|
switch(code) { |
switch(code) { |
case SM_popCMO: |
case SM_popCMO: |
Line 338 int execute_sm_command(int fd_write, int code) |
|
Line 223 int execute_sm_command(int fd_write, int code) |
|
err = sm_pops(fd_write); |
err = sm_pops(fd_write); |
break; |
break; |
case SM_executeStringByLocalParser: |
case SM_executeStringByLocalParser: |
|
case SM_executeStringByLocalParserInBatchMode: |
err = sm_executeStringByLocalParser(fd_write); |
err = sm_executeStringByLocalParser(fd_write); |
break; |
break; |
case SM_executeFunction: |
case SM_executeFunction: |
err = sm_executeFunction(fd_write); |
err = sm_executeFunction(fd_write); |
break; |
break; |
|
case SM_shutdown: |
|
shutdown(); |
|
break; |
case SM_setMathCap: |
case SM_setMathCap: |
pop(); /* 無視する */ |
pop(); /* 無視する */ |
break; |
break; |
default: |
default: |
fprintf(stderr, "unknown command: %d.\n", code); |
fprintf(stderr, "unknown command: %d.\n", code); |
err = UNKNOWN_SM_COMMAND; |
err = ERROR_ID_UNKNOWN_SM; |
} |
} |
|
|
if (err != 0) { |
if (err != 0) { |
push((cmo *)gen_error_object(err)); |
push((cmo *)make_error_object(err, new_cmo_null())); |
} |
} |
} |
} |