27c643f715a5558e12ffe524fac1d1ae3579425e
[ginac.git] / cint / ginaccint.cpp
1 #include "G__ci.h"   /* G__atpause is defined in G__ci.h */
2 #include <iostream>
3 #include <fstream>
4 #include <string>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <ginac/ginac.h>
8 #include <list>
9
10 extern "C" G__value G__exec_tempfile G__P((char *file));
11 extern "C" void G__store_undo_position(void);
12
13 #ifdef OBSCURE_CINT_HACK
14
15 #include <strstream>
16
17 template<class T>
18 string ToString(T const & t)
19 {
20     char buf[256];
21     ostrstream(buf,sizeof(buf)) << t << ends;
22     return buf;
23 }
24
25 basic * ex::last_created_or_assigned_bp=0;
26 bool ex::last_created_or_assigned_bp_modified=false;
27
28 #endif // def OBSCURE_CINT_HACK
29
30 typedef list<char *> cplist;
31
32 cplist filenames;
33
34 void cleanup(void)
35 {
36     for (cplist::iterator it=filenames.begin(); it!=filenames.end(); ++it) {
37         cout << "removing file " << *it << endl;
38         remove(*it);
39         free(*it);
40     }
41 }
42
43 void sigterm_handler(int n)
44 {
45     exit(1);
46 }
47
48 bool is_whitespace_char(char c)
49 {
50     return ((c==' ')||(c=='\t')||(c=='\n')||(c=='\r')); 
51 }
52
53 char first_non_whitespace_char(char const * s)
54 {
55     int l=strlen(s);
56     int pos=0;
57     while ((pos<l)&&is_whitespace_char(s[pos])) pos++;
58     return s[pos];
59 }    
60
61 char last_non_whitespace_char(char const * s)
62 {
63     int pos=strlen(s)-1;
64     while ((pos>=0)&&is_whitespace_char(s[pos])) pos--;
65     return s[pos];
66 }    
67
68 string strip_whitespace(string const & s)
69 {
70     string s2;
71     int l=s.length();
72     for (int pos=0; pos<l; ++pos) {
73         if (!is_whitespace_char(s[pos])) s2 += s[pos];
74     }
75     return s2;
76 }
77
78 G__value exec_tempfile(string const & command)
79 {
80     G__value retval;
81     char *tmpfilename=tempnam(NULL,"ginac");
82     ofstream fout;
83     fout.open(tmpfilename);
84     fout << "{" << endl << command << endl << "}" << endl;
85     fout.close();
86     G__store_undo_position();
87     retval=G__exec_tempfile(tmpfilename);
88     G__security_recover(stdout);
89     remove(tmpfilename);
90     free(tmpfilename);
91     return retval;
92 }
93
94 char * process_permanentfile(string const & command)
95 {
96     char *tmpfilename=tempnam(NULL,"ginac");
97     cout << "creating file " << tmpfilename << endl;
98     ofstream fout;
99     fout.open(tmpfilename);
100     fout << command << endl;
101     fout.close();
102     G__store_undo_position();
103     G__loadfile(tmpfilename);
104     G__security_recover(stdout);
105     return tmpfilename;
106 }
107
108 void process_tempfile(string const & command)
109 {
110 #ifdef OBSCURE_CINT_HACK
111     static G__value ref_ex=exec_tempfile("ex ginac_cint_internal; ginac_cint_internal;");
112     ex dummy_ex;
113     ex::last_created_or_assigned_bp_modified=false;
114 #endif // def OBSCURE_CINT_HACK
115
116     G__value retval=exec_tempfile(command);
117
118 #ifdef OBSCURE_CINT_HACK
119     static unsigned out_count=0;
120     if (!ex::last_created_or_assigned_bp_modified) {
121         if ((ref_ex.type==retval.type)&&(ref_ex.tagnum==retval.tagnum)) {
122             ex * ep=(ex *)(retval.obj.i);
123             dummy_ex=*ep;
124         }
125     }
126     if (ex::last_created_or_assigned_bp_modified) {
127         if (ex::last_created_or_assigned_bp_can_be_converted_to_ex()) {
128             string varname="Out"+ToString(++out_count);
129             exec_tempfile("ex "+varname+"(*ex::last_created_or_assigned_bp);\n"
130                          +"LLLAST=LLAST;\n"
131                          +"LLAST=LAST;\n"
132                          +"LAST="+varname+";\n"
133                          +"cout << \""+varname+" = \" << "+varname+" << endl << endl;"); 
134         } else {
135             cout << "warning: last_created_or_assigned_bp modified but 0 or not evaluated or not dynallocated" << endl;
136         }
137     }
138 #endif // def OBSCURE_CINT_HACK
139 }
140
141 void greeting(void)
142 {
143     cout << "Welcome to GiNaCcint V0.2" << endl << endl;
144     cout << "To quit, type 'quit;', 'exit;', 'bye;', '.q', '.quit', '.exit' or '.bye'" << endl;
145 }
146
147 int main(void) 
148 {
149     char *line;
150     char prompt[G__ONELINE];
151
152     greeting();
153
154     atexit(cleanup);
155     signal(SIGTERM,sigterm_handler);
156     
157     G__init_cint("cint");    /* initialize cint */
158
159     exec_tempfile("#include <string>\n");
160     exec_tempfile("ex LAST,LLAST,LLLAST;\n");
161     
162     bool quit=false;
163     bool next_command_is_function=false;    
164     while (!quit) {
165         strcpy(prompt,"GiNaCcint> ");
166         int open_braces=0;
167         bool end_of_command=false;
168         string command;
169         while (!end_of_command) {
170             line=G__input(prompt);
171         
172             int pos = 0;
173             bool double_quote=false;
174             bool single_quote=false;
175             while(line[pos]!='\0') {
176                 switch(line[pos]) {
177                 case '"':
178                     if (!single_quote) double_quote = !double_quote;
179                     break;
180                 case '\'':
181                     if (!double_quote) single_quote = !single_quote;
182                     break;
183                 case '{':
184                     if ((!single_quote)&&(!double_quote)) open_braces++;
185                     break;
186                 case '}':
187                     if ((!single_quote)&&(!double_quote)) open_braces--;
188                     break;
189                 }
190                 pos++;
191             }
192             command += line;
193             command += '\n';
194             if (open_braces==0) {
195                 if ((first_non_whitespace_char(command.c_str())=='#')||
196                     (first_non_whitespace_char(command.c_str())=='.')||
197                     (last_non_whitespace_char(command.c_str())==';')||
198                     (last_non_whitespace_char(command.c_str())=='}')) {
199                     end_of_command=true;
200                 }
201             }
202             strcpy(prompt,"  (more) > ");
203         }
204         string stripped_command=strip_whitespace(command);
205         if ((stripped_command=="quit;")||
206             (stripped_command=="exit;")||
207             (stripped_command=="bye;")||
208             (stripped_command==".q")||
209             (stripped_command==".quit")||
210             (stripped_command==".exit")||
211             (stripped_command==".bye")) {
212             quit=true;
213         } else if (stripped_command==".function") {
214             cout << "next expression can be a function definition" << endl;
215             next_command_is_function=true;
216         } else if (stripped_command==".cint") {
217             cout << endl << "switching to cint interactive mode" << endl;
218             cout << "'h' for help, 'q' to quit, '{ statements }' or 'p [expression]' to evaluate" << endl;
219             G__pause();
220             cout << "back from cint" << endl;
221         } else if (command[0]=='.') {
222             cout << "special command (TBD): " << command << endl;
223         } else {
224             // cout << "now processing: " << command << endl;
225             if (next_command_is_function) {
226                 next_command_is_function=false;
227                 filenames.push_back(process_permanentfile(command));
228             } else {
229                 process_tempfile(command);
230             }
231         }
232     }
233
234     return 0;
235 }
236
237
238
239
240
241
242