52f3ef4881dbd4ed7110fc5c9e1080ea12f56287
[ginac.git] / cint / ginaccint.bin.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 "config.h"
9 #include <list>
10
11 extern "C" G__value G__exec_tempfile G__P((char *file));
12 extern "C" void G__store_undo_position(void);
13
14 #ifdef OBSCURE_CINT_HACK
15
16 #include <strstream>
17
18 template<class T>
19 string ToString(const T & t)
20 {
21     char buf[256];
22     ostrstream(buf,sizeof(buf)) << t << ends;
23     return buf;
24 }
25
26 basic * ex::last_created_or_assigned_bp=0;
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_symbol = exec_tempfile("symbol ginac_cint_internal_symbol; ginac_cint_internal_symbol;");
112     static G__value ref_ex = exec_tempfile("ex ginac_cint_internal_ex; ginac_cint_internal_ex;");
113     static G__value ref_function = exec_tempfile("sin(ginac_cint_internal_symbol);");
114     static G__value ref_power = exec_tempfile("power(ginac_cint_internal_symbol,ginac_cint_internal_symbol);");
115 #endif // def OBSCURE_CINT_HACK
116
117     G__value retval = exec_tempfile(command);
118
119 #ifdef OBSCURE_CINT_HACK
120
121     #define TYPES_EQUAL(A,B) (((A).type==(B).type) && ((A).tagnum==(B).tagnum))
122     
123     static unsigned out_count = 0;
124     if (TYPES_EQUAL(retval,ref_ex)) {
125         if (ex::last_created_or_assigned_bp_can_be_converted_to_ex()) {
126             string varname = "Out"+ToString(++out_count);
127             //string varfill;
128             //for (int i=4-int(log10(out_count)); i>0; --i)
129             //    varfill += ' ';
130             exec_tempfile("ex "+varname+"(*ex::last_created_or_assigned_bp);\n"
131                           +"LLLAST=LLAST;\n"
132                           +"LLAST=LAST;\n"
133                           +"LAST="+varname+";\n"
134                           +"cout << \""+varname+" = \" << "+varname+" << endl << endl;");
135         } else {
136             cout << "warning: last_created_or_assigned_bp modified 0 or not evaluated or not dynallocated" << endl;
137         }
138     }
139 #endif // def OBSCURE_CINT_HACK
140 }
141
142 void greeting(void)
143 {
144     cout << "Welcome to GiNaC-cint (" << PACKAGE << " V" << VERSION << ")" << endl;
145     cout << "This software is provided \"as is\" without any warranty.  Copyright of Cint is" << endl
146          << "owned by Agilent Technologies Japan and Masaharu Goto.  Registration is" << endl
147          << "  __,  _______  requested, at this moment, for commercial use.  Send e-mail to" << endl
148          << " (__) *       | <MXJ02154@niftyserve.or.jp>.  The registration is free." << endl
149          << "  ._) i N a C | The GiNaC framework is Copyright by Johannes Gutenberg Univ.," << endl
150          << "<-------------' Germany and licensed under the terms and conditions of the GPL." << endl << endl;
151 }
152
153 int main(void) 
154 {
155     char *line;
156     char prompt[G__ONELINE];
157
158     greeting();
159
160     atexit(cleanup);
161     signal(SIGTERM,sigterm_handler);
162     
163     G__init_cint("cint");    /* initialize cint */
164
165     exec_tempfile("#include <string>\n");
166     exec_tempfile("ex LAST,LLAST,LLLAST;\n");
167     
168     bool quit = false;
169     bool next_command_is_function=false;    
170     while (!quit) {
171         strcpy(prompt,"GiNaC> ");
172         int open_braces = 0;
173         bool end_of_command=false;
174         string command;
175         while (!end_of_command) {
176             line = G__input(prompt);
177         
178             int pos = 0;
179             bool double_quote=false;
180             bool single_quote=false;
181             while(line[pos]!='\0') {
182                 switch(line[pos]) {
183                 case '"':
184                     if (!single_quote) double_quote = !double_quote;
185                     break;
186                 case '\'':
187                     if (!double_quote) single_quote = !single_quote;
188                     break;
189                 case '{':
190                     if ((!single_quote) && (!double_quote)) open_braces++;
191                     break;
192                 case '}':
193                     if ((!single_quote) && (!double_quote)) open_braces--;
194                     break;
195                 }
196                 pos++;
197             }
198             command += line;
199             command += '\n';
200             if (open_braces==0) {
201                 if ((first_non_whitespace_char(command.c_str())=='#')||
202                     (first_non_whitespace_char(command.c_str())=='.')||
203                     (last_non_whitespace_char(command.c_str())==';')||
204                     (last_non_whitespace_char(command.c_str())=='}')) {
205                     end_of_command=true;
206                 }
207             }
208             strcpy(prompt,"     > ");
209         }
210         string stripped_command=strip_whitespace(command);
211         if ((stripped_command=="quit;")||
212             (stripped_command=="exit;")||
213             (stripped_command=="bye;")||
214             (stripped_command==".q")||
215             (stripped_command==".quit")||
216             (stripped_command==".exit")||
217             (stripped_command==".bye")) {
218             quit = true;
219         } else if (stripped_command==".function") {
220             cout << "next expression can be a function definition" << endl;
221             next_command_is_function=true;
222         } else if (stripped_command==".cint") {
223             cout << endl << "switching to cint interactive mode" << endl;
224             cout << "'h' for help, 'q' to quit, '{ statements }' or 'p [expression]' to evaluate" << endl;
225             G__pause();
226             cout << "back from cint" << endl;
227         } else if (command[0]=='.') {
228             cout << "special command (TBD): " << command << endl;
229         } else {
230             // cout << "now processing: " << command << endl;
231             if (next_command_is_function) {
232                 next_command_is_function = false;
233                 filenames.push_back(process_permanentfile(command));
234             } else {
235                 process_tempfile(command);
236             }
237         }
238     }
239
240     return 0;
241 }
242
243
244
245
246
247
248