/****************************************************************************** * MODULE : tm_mathematica.c * DESCRIPTION: Interface with Mathematica * COPYRIGHT : (C) 2005 Andrey Grozin ******************************************************************************* * This software falls under the GNU general public license version 3 or later. * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE * in the root directory or . ******************************************************************************/ #include #include #include #include "mathlink.h" #define CLOSED 11L #define PRE_NAME "/plugins/mathematica/ps/pre" #define POST_NAME "/plugins/mathematica/ps/post" #define LOG "./log.mma" // #define LOG_PS "./log.ps" /* MODIFY THE EXTENSION TO EXPORT DIFFERENT FORMAT*/ #define FIG_NAME "./tmp.eps" #ifdef LOG static FILE *log; #endif #ifdef LOG_PS static FILE *psfile; #endif MLENV env =(MLENV)0; MLINK link=(MLINK)0; static size_t size=128; static char *input,*pre_name,*post_name; static char *mls_buf; static int protect_hat=0; static void texput(char *s, FILE* fid) { char c; int n,nl; char* pc; nl=0; pc=s; while( (c=*(s++)) ) { if (c=='\\') { c=*(s++); if ((c>='0')&&(c<='9')) { n=c-'0'; while (1) { c=*(s++); if ((c<'0')||(c>'9')) { if (n==0x0a) { putc(' ', fid); *(pc++) = ' '; nl=1; } else { putc(n, fid); *(pc++) = n; } if (c) if (nl) { if (c=='>') nl=0; else if (c>' ') { putc(c, fid); *(pc++) = c; nl=1; } else if (protect_hat&&(c=='^')) { putc(' ', fid); *(pc++) = ' '; } else {putc(c, fid); *(pc++) = c;} } break; } else n=8*n+(c-'0'); } if (c=='\0') {*(pc++) = '\0'; break;} } else if (protect_hat&&(c=='^')) {putc(' ', fid); *(pc++) = ' ';} else {putc(c, fid); *(pc++) = c;} } else if (nl) { if (c=='>') nl=0; else if (c>' ') { if (protect_hat&&(c=='^')) { putc(' ', fid); *(pc++) = ' '; } else { putc(c, fid); *(pc++) = c;} nl=1; } } else if (protect_hat&&(c=='^')) { putc(' ', fid); *(pc++) = ' '; } else {putc(c, fid); *(pc++) = c;} } } static void psput(char *s) { char c; int n,l; char* pc; pc = s; while( ( c=*(s++) ) ) { if (c=='\\') { c=*(s++); if ((c>='0')&&(c<='7')) { l=0; n=c-'0'; while (1) { l++; c=*(s++); if ((l>=3)||(c<'0')||(c>'7')) { putchar(n); *(pc++) = n; #ifdef LOG_PS fputc(n,psfile); #endif if (c) { putchar(c); *(pc++) = c; #ifdef LOG_PS fputc(c,psfile); #endif } break; } else n=8*n+(c-'0'); } if (c=='\0') {*(pc++)='\0'; break;} } else { putchar(c); *(pc++) = c; #ifdef LOG_PS fputc(c,psfile); #endif } } else { putchar(c); *(pc++) = c; #ifdef LOG_PS fputc(c,psfile); #endif } } } static void prelude(char *name) { FILE *ps=fopen(name,"r"); char(c); while (1) { c=getc(ps); if (c==EOF) break; putchar(c); #ifdef LOG_PS fputc(c,psfile); #endif } fclose(ps); } static void regularize(char* s) { /* delete '\\\012' and '\012>' */ char c; char* pc; pc=s; while( (c=*(s++)) ) { if(c=='\\') { c=*(s++); if(c=='\\') { s+=5; } else if((c<='9')&&(c>='0')) { while((c=*(s++))) { if(c=='>'||c==' ') break; } } } else *(pc++) = c; } *pc = '\0'; } static void eps_to_string() { FILE* f_ps; int c; fputs("ps:", stdout); fflush(stdout); if( ( f_ps = fopen(FIG_NAME, "r") ) ) { while((c=fgetc(f_ps)) != EOF) { putchar(c); } putchar( '\0' ); putchar( '\n' ); fclose(f_ps); } else { fputs("Cannot open tmp.eps\n", stdout); } } static void evaluate(int type, char* s) { int pkt,more,non_ps,msg; long err; char *result,*symbol; /* FILE* f_log; */ MLPutFunction(link, "EvaluatePacket", 1L); switch(type) { case -1: /* No way! */ exit(1); case 0: /* TeX */ MLPutFunction(link, "Print", 1L); MLPutFunction(link, "TeXForm", 1L); MLPutFunction(link, "ToExpression", 1L); MLPutString(link,s); break; case 1: /* Graphics */ regularize(s); /* remove control characters */ /* f_log = fopen("./fig.log", "w"); fputs(s, f_log); fclose(f_log); */ MLPutFunction(link, "Export", 2L); MLPutString(link, FIG_NAME); MLPutFunction(link, "ToExpression", 1L); MLPutString(link, s); break; } MLEndPacket(link); more=1; non_ps=1; msg=0; do { switch (pkt=MLNextPacket(link)) { case RETURNPKT: #ifdef LOG fputs("RETURNPKT@evaluate\n\n",log); fflush(log); #endif more=0; break; case RETURNTEXTPKT: MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"RETURNTEXTPKT@evaluate: \"%s\"\n\n",result); fflush(log); #endif MLReleaseString(link,result); more=0; break; case INPUTNAMEPKT: MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"INPUTNAMEPKT@evaluate: \"%s\"\n",result); fflush(log); #endif MLReleaseString(link,result); break; case OUTPUTNAMEPKT: MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"OUTPUTNAMEPKT@evaluate: \"%s\"\n",result); fflush(log); #endif MLReleaseString(link,result); break; case TEXTPKT: MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"TEXTPKT@evaluate: \"%s\"\n",result); fflush(log); #endif if (msg) { fputs("{\\magenta ",stdout); protect_hat=1; texput(result, stdout); fputs("}\n\n",stdout); protect_hat=0; msg=0; } else { switch(type) { case 0: /* TeX */ fputs("$\\displaystyle ",stdout); texput(result, stdout); fputs("$",stdout); break; case 1: /* graphics */ break; default: fputs("Oops, nothing happened...\n", stdout); break; } } MLReleaseString(link,result); break; case MESSAGEPKT: MLGetSymbol(link,(const char**)&symbol); MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"MESSAGEPKT@evaluate: \"%s\" \"%s\"\n",symbol,result); fflush(log); #endif MLReleaseSymbol(link,symbol); MLReleaseString(link,result); msg=1; break; case DISPLAYPKT: MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"DISPLAYPK@evaluate: \"%s\"\n",result); fflush(log); #endif if (non_ps) { fputs("\2ps:",stdout); #ifdef LOG_PS psfile=fopen(LOG_PS,"w"); #endif prelude(pre_name); non_ps=0; } psput(result); MLReleaseString(link,result); break; case DISPLAYENDPKT: MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"DISPLAYENDPKT@evaluate: \"%s\"\n",result); fflush(log); #endif psput(result); prelude(post_name); fputs("\5{}{}\n\n",stdout); #ifdef LOG_PS fclose(psfile); #endif non_ps=1; MLReleaseString(link,result); break; case CALLPKT: #ifdef LOG fputs("CALLPKT@evaluate\n",log); fflush(log); #endif break; default: #ifdef LOG fprintf(log,"UNKNOWN PACKET@evaluate: %1d\n",pkt); fflush(log); #endif break; } MLNewPacket(link); err=MLError(link); if (err==CLOSED) { fputs("\\red The end\5",stdout); MLClose(link); MLDeinitialize(env); exit(0); } else if (err) { printf("\\red Error %ld: %s\5",err,MLErrorMessage(link)); exit(1); } } while (more); } static void command(char *s) { int pkt,more,non_ps,msg, type, is_buf; long err; char *result,*symbol; fputs("\2latex:",stdout); MLPutFunction(link,"EvaluatePacket",1L); MLPutFunction(link,"Print",1L); // MLPutFunction(link,"TeXForm",1L); MLPutFunction(link, "ExportString", 2L); MLPutFunction(link,"ToExpression",1L); MLPutString(link,s); MLPutString(link,"Text"); MLEndPacket(link); more=1; non_ps=1; msg=0; type = 0; is_buf = 0; do { switch (pkt=MLNextPacket(link)) { case RETURNPKT: #ifdef LOG fputs("RETURNPKT@command\n\n",log); fflush(log); #endif more=0; break; case RETURNTEXTPKT: MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"RETURNTEXTPKT@command: \"%s\"\n\n",result); fflush(log); #endif MLReleaseString(link,result); more=0; break; case INPUTNAMEPKT: MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"INPUTNAMEPKT@command: \"%s\"\n",result); fflush(log); #endif MLReleaseString(link,result); break; case OUTPUTNAMEPKT: MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"OUTPUTNAMEPKT@command: \"%s\"\n",result); fflush(log); #endif MLReleaseString(link,result); break; case TEXTPKT: MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"TEXTPKT@command: \"%s\"\n",result); fflush(log); #endif if (msg) { fputs("{\\magenta ",stdout); protect_hat=1; texput(result, stdout); fputs("}\n\n",stdout); protect_hat=0; msg=0; } else { if( is_buf ) { fputs("TEXTPKT more than once?\n", stdout); break; } if( ! ( mls_buf = (char*)malloc(strlen(result)+1) ) ) { fputs("Cannot allocate memory for the returning TEXT packet.\n", stdout); break; } is_buf = 1; strcpy(mls_buf, result); // fputs("$\\displaystyle ",stdout); char* pKeyword; if( (pKeyword=strstr(mls_buf, "Graphics")) ) if( (mls_buf - pKeyword) == 0 ) { /* begin with keyword "Graphics" */ type = 1; fputs("Graphics\n", stdout); break; } // texput(result, stdout); // fputs("$",stdout); } MLReleaseString(link,result); break; case MESSAGEPKT: MLGetSymbol(link,(const char**)&symbol); MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"MESSAGEPKT@command: \"%s\" \"%s\"\n",symbol,result); fflush(log); #endif MLReleaseSymbol(link,symbol); MLReleaseString(link,result); msg=1; break; case DISPLAYPKT: MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"DISPLAYPK@command: \"%s\"\n",result); fflush(log); #endif if (non_ps) { fputs("\2ps:",stdout); #ifdef LOG_PS psfile=fopen(LOG_PS,"w"); #endif prelude(pre_name); non_ps=0; } psput(result); MLReleaseString(link,result); break; case DISPLAYENDPKT: MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"DISPLAYENDPKT@command: \"%s\"\n",result); fflush(log); #endif psput(result); prelude(post_name); fputs("\5{}{}\n\n",stdout); #ifdef LOG_PS fclose(psfile); #endif non_ps=1; MLReleaseString(link,result); break; case INPUTPKT: MLGetString(link,(const char**)&result); #ifdef LOG fprintf(log,"INPUTPKT@command: \"%s\"\n",result); fflush(log); #endif printf("\2prompt#\\red %s{}\5\5",result); fflush(stdout); MLReleaseString(link,result); if (getline(&input,&size,stdin)>=0) command(input); break; case CALLPKT: #ifdef LOG fputs("CALLPKT@command\n",log); fflush(log); #endif break; default: #ifdef LOG fprintf(log,"UNKNOWN PACKET@command: %1d\n",pkt); fflush(log); #endif break; } MLNewPacket(link); err=MLError(link); if (err==CLOSED) { fputs("\\red The end\5",stdout); MLClose(link); MLDeinitialize(env); exit(0); } else if (err) { printf("\\red Error %ld: %s\5",err,MLErrorMessage(link)); exit(1); } } while (more); if(is_buf) { evaluate(type, mls_buf); free(mls_buf); is_buf = 0; } /* post-process, e.g., reading a generated figure */ switch(type) { case 0: /* tex */ break; case 1: /* figure */ /* e.g., read the generated EPS file and dump to TeXmacs*/ /* fputs("\2ps:",stdout); */ /* prelude(pre_name); */ /* eps_to_string(); */ /* prelude(post_name); */ /* fputs("\5{}{}\n\n",stdout);*/ fputs("\2ps:", stdout); fflush(stdout); system("cat ~/tmp.eps"); fputs("\5{}{}\n\n", stdout); /* or can use other methods, like loading .png, .svg., whatever */ //fputs("$",stdout); break; default: break; } } int main(int argc, char *argv[]) { int err; size_t InNum=1,l; char *tm_path; #ifdef LOG log=fopen(LOG,"w"); #endif tm_path=getenv("TEXMACS_PATH"); /* tm_path = (char*)"./"; */ if (tm_path==NULL) exit(1); l=strlen(tm_path); pre_name=(char*)malloc(l+strlen(PRE_NAME)+1); post_name=(char*)malloc(l+strlen(POST_NAME)+1); strcpy(pre_name,tm_path); strcpy(pre_name+l,PRE_NAME); strcpy(post_name,tm_path); strcpy(post_name+l,POST_NAME); input=(char*)malloc(size); env=MLInitialize((MLParametersPointer)0); if (env==(MLENV)0) { fputs("\2latex:\\red Initialization of MathLink failed\5",stdout); exit(1); } link=MLOpenString(env,"-linkname \"math -mathlink\"",&err); if (link==(MLINK)0) { fputs("\2latex:\\red Link with Mathematica failed",stdout); MLDeinitialize(env); exit(1); } fputs("\2latex:\\red Mathematica",stdout); while (1) { /* Prompt */ printf("\2prompt#\\red In[%1d]:= {}\5\5",InNum++); fflush(stdout); if (getline(&input,&size,stdin)>=0) command(input); } return 0; }