1 
2 /******************************************************************************
3 * MODULE     : tm_mathematica.c
4 * DESCRIPTION: Interface with Mathematica
5 * COPYRIGHT  : (C) 2005  Andrey Grozin
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include "mathlink.h"
16 
17 #define CLOSED 11L
18 #define PRE_NAME  "/plugins/mathematica/ps/pre"
19 #define POST_NAME "/plugins/mathematica/ps/post"
20 /* #define LOG "/tmp/log.mma"   */
21 /* #define LOG_PS "/tmp/log.ps" */
22 
23 #ifdef LOG
24 static FILE *log;
25 #endif
26 #ifdef LOG_PS
27 static FILE *psfile;
28 #endif
29 
30 MLENV env =(MLENV)0;
31 MLINK link=(MLINK)0;
32 static size_t size=128;
33 static char *input,*pre_name,*post_name;
34 static int protect_hat=0;
35 
texput(char * s)36 static void texput(char *s) {
37   char c; int n,nl;
38   nl=0;
39   while (c=*(s++)) {
40     if (c=='\\') {
41       c=*(s++);
42       if ((c>='0')&&(c<='9')) {
43 	n=c-'0';
44 	while (1) {
45 	  c=*(s++);
46 	  if ((c<'0')||(c>'9')) {
47 	    if (n==0x0a) { putchar(' '); nl=1; }
48 	    else putchar(n);
49 	    if (c)
50 	      if (nl)
51 		if (c=='>') nl=0;
52 		else if (c>' ') { putchar(c); nl=1; }
53 	      else if (protect_hat&&(c=='^')) putchar(' ');
54 	      else putchar(c);
55 	    break;
56 	  } else n=8*n+(c-'0');
57 	}
58 	if (c=='\0') break;
59       } else if (protect_hat&&(c=='^')) putchar(' ');
60       else putchar(c);
61     } else if (nl) {
62       if (c=='>') nl=0;
63       else if (c>' ') {
64 	if (protect_hat&&(c=='^')) putchar(' ');
65 	else putchar(c);
66 	nl=1;
67       }
68     } else if (protect_hat&&(c=='^')) putchar(' ');
69     else putchar(c);
70   }
71 }
72 
psput(char * s)73 static void psput(char *s) {
74   char c; int n,l;
75   while (c=*(s++)) {
76     if (c=='\\') {
77       c=*(s++);
78       if ((c>='0')&&(c<='7')) {
79 	l=0; n=c-'0';
80 	while (1) {
81 	  l++; c=*(s++);
82 	  if ((l>=3)||(c<'0')||(c>'7')) {
83 	    putchar(n);
84 #ifdef LOG_PS
85 	    fputc(n,psfile);
86 #endif
87 	    if (c) {
88 	      putchar(c);
89 #ifdef LOG_PS
90 	      fputc(c,psfile);
91 #endif
92 	    }
93 	    break;
94 	  } else n=8*n+(c-'0');
95 	}
96 	if (c=='\0') break;
97       } else {
98 	putchar(c);
99 #ifdef LOG_PS
100 	fputc(c,psfile);
101 #endif
102       }
103     } else {
104       putchar(c);
105 #ifdef LOG_PS
106       fputc(c,psfile);
107 #endif
108     }
109   }
110 }
111 
prelude(char * name)112 static void prelude(char *name) {
113   FILE *ps=fopen(name,"r");
114   char(c);
115   while (1) {
116     c=getc(ps);
117     if (c==EOF) break;
118     putchar(c);
119 #ifdef LOG_PS
120     fputc(c,psfile);
121 #endif
122   }
123   fclose(ps);
124 }
125 
command(char * s)126 static void command(char *s) {
127   int pkt,more,non_ps,msg; long err;
128   char *result,*symbol;
129   fputs("\2latex:",stdout);
130   MLPutFunction(link,"EvaluatePacket",1L);
131   MLPutFunction(link,"Print",1L);
132   MLPutFunction(link,"TeXForm",1L);
133   MLPutFunction(link,"ToExpression",1L);
134   MLPutString(link,s);
135   MLEndPacket(link);
136   more=1; non_ps=1; msg=0;
137   do {
138     switch (pkt=MLNextPacket(link)) {
139     case RETURNPKT:
140 #ifdef LOG
141       fputs("RETURNPKT\n",log); fflush(log);
142 #endif
143       more=0;
144       break;
145     case RETURNTEXTPKT:
146       MLGetString(link,&result);
147 #ifdef LOG
148       fprintf(log,"RETURNTEXTPKT: \"%s\"\n",result); fflush(log);
149 #endif
150       MLDisownString(link,result);
151       more=0;
152       break;
153     case INPUTNAMEPKT:
154       MLGetString(link,&result);
155 #ifdef LOG
156       fprintf(log,"INPUTNAMEPKT: \"%s\"\n",result); fflush(log);
157 #endif
158       MLDisownString(link,result);
159       break;
160     case OUTPUTNAMEPKT:
161       MLGetString(link,&result);
162 #ifdef LOG
163       fprintf(log,"OUTPUTNAMEPKT: \"%s\"\n",result); fflush(log);
164 #endif
165       MLDisownString(link,result);
166       break;
167     case TEXTPKT:
168       MLGetString(link,&result);
169 #ifdef LOG
170       fprintf(log,"TEXTPKT: \"%s\"\n",result); fflush(log);
171 #endif
172       if (msg) {
173 	fputs("{\\magenta ",stdout);
174 	protect_hat=1; texput(result);
175 	fputs("}\n\n",stdout);
176 	protect_hat=0; msg=0;
177       } else {
178 	fputs("$\\displaystyle ",stdout);
179 	texput(result);
180 	fputs("$",stdout);
181       }
182       MLDisownString(link,result);
183       break;
184     case MESSAGEPKT:
185       MLGetSymbol(link,&symbol);
186       MLGetString(link,&result);
187 #ifdef LOG
188       fprintf(log,"MESSAGEPKT: \"%s\"  \"%s\"\n",symbol,result); fflush(log);
189 #endif
190       MLDisownSymbol(link,symbol);
191       MLDisownString(link,result);
192       msg=1;
193       break;
194     case DISPLAYPKT:
195       MLGetString(link,&result);
196 #ifdef LOG
197       fprintf(log,"DISPLAYPK: \"%s\"\n",result); fflush(log);
198 #endif
199       if (non_ps) {
200 	fputs("\2ps:",stdout);
201 #ifdef LOG_PS
202 	psfile=fopen(LOG_PS,"w");
203 #endif
204 	prelude(pre_name); non_ps=0;
205       }
206       psput(result);
207       MLDisownString(link,result);
208       break;
209     case DISPLAYENDPKT:
210       MLGetString(link,&result);
211 #ifdef LOG
212       fprintf(log,"DISPLAYENDPKT: \"%s\"\n",result); fflush(log);
213 #endif
214       psput(result);
215       prelude(post_name);
216       fputs("\5{}{}\n\n",stdout);
217 #ifdef LOG_PS
218       fclose(psfile);
219 #endif
220       non_ps=1;
221       MLDisownString(link,result);
222       break;
223     case INPUTPKT:
224       MLGetString(link,&result);
225 #ifdef LOG
226       fprintf(log,"INPUTPKT: \"%s\"\n",result); fflush(log);
227 #endif
228       printf("\2prompt#\\red %s{}\5\5",result);
229       fflush(stdout);
230       MLDisownString(link,result);
231       if (getline(&input,&size,stdin)>=0) command(input);
232       break;
233     case CALLPKT:
234 #ifdef LOG
235       fputs("CALLPKT\n",log); fflush(log);
236 #endif
237       break;
238     default:
239 #ifdef LOG
240       fprintf(log,"UNKNOWN PACKET: %1d\n",pkt); fflush(log);
241 #endif
242       break;
243     }
244     MLNewPacket(link);
245     err=MLError(link);
246     if (err==CLOSED) {
247       fputs("\\red The end\5",stdout);
248       MLClose(link);
249       MLDeinitialize(env);
250       exit(0);
251     } else if (err) {
252       printf("\\red Error %1d: %s\5",err,MLErrorMessage(link));
253       exit(1);
254     }
255   } while (more);
256 }
257 
main(int argc,char * argv[])258 int main(int argc, char *argv[]) {
259   long err;
260   size_t InNum=1,l;
261   char *tm_path;
262 #ifdef LOG
263   log=fopen(LOG,"w");
264 #endif
265 
266   tm_path=getenv("TEXMACS_PATH");
267   if (tm_path==NULL) exit(1);
268   l=strlen(tm_path);
269   pre_name=malloc(l+strlen(PRE_NAME)+1);
270   post_name=malloc(l+strlen(POST_NAME)+1);
271   strcpy(pre_name,tm_path);  strcpy(pre_name+l,PRE_NAME);
272   strcpy(post_name,tm_path); strcpy(post_name+l,POST_NAME);
273 
274   input=(char*)malloc(size);
275 
276   env=MLInitialize((MLParametersPointer)0);
277   if (env==(MLENV)0) {
278     fputs("\2latex:\\red Initialization of MathLink failed\5",stdout);
279     exit(1);
280   }
281 
282   link=MLOpenString(env,"-linkname \"math -mathlink\"",&err);
283   if (link==(MLINK)0) {
284     fputs("\2latex:\\red Link with Mathematica failed",stdout);
285     MLDeinitialize(env);
286     exit(1);
287   }
288 
289   fputs("\2latex:\\red Mathematica",stdout);
290 
291   while (1) {
292     /* Prompt */
293     printf("\2prompt#\\red In[%1d]:= {}\5\5",InNum++);
294     fflush(stdout);
295     if (getline(&input,&size,stdin)>=0) command(input);
296   }
297 
298   return 0;
299 }
300