- updated Makefiles
[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
27 #endif // def OBSCURE_CINT_HACK
28
29 typedef list<char *> cplist;
30
31 cplist filenames;
32
33 void cleanup(void)
34 {
35     for (cplist::iterator it=filenames.begin(); it!=filenames.end(); ++it) {
36         cout << "removing file " << *it << endl;
37         remove(*it);
38         free(*it);
39     }
40 }
41
42 void sigterm_handler(int n)
43 {
44     exit(1);
45 }
46
47 bool is_whitespace_char(char c)
48 {
49     return ((c==' ')||(c=='\t')||(c=='\n')||(c=='\r')); 
50 }
51
52 char first_non_whitespace_char(char const * s)
53 {
54     int l=strlen(s);
55     int pos=0;
56     while ((pos<l)&&is_whitespace_char(s[pos])) pos++;
57     return s[pos];
58 }    
59
60 char last_non_whitespace_char(char const * s)
61 {
62     int pos=strlen(s)-1;
63     while ((pos>=0)&&is_whitespace_char(s[pos])) pos--;
64     return s[pos];
65 }    
66
67 string strip_whitespace(string const & s)
68 {
69     string s2;
70     int l=s.length();
71     for (int pos=0; pos<l; ++pos) {
72         if (!is_whitespace_char(s[pos])) s2 += s[pos];
73     }
74     return s2;
75 }
76
77 G__value exec_tempfile(string const & command)
78 {
79     G__value retval;
80     char *tmpfilename=tempnam(NULL,"ginac");
81     ofstream fout;
82     fout.open(tmpfilename);
83     fout << "{" << endl << command << endl << "}" << endl;
84     fout.close();
85     G__store_undo_position();
86     retval=G__exec_tempfile(tmpfilename);
87     G__security_recover(stdout);
88     remove(tmpfilename);
89     free(tmpfilename);
90     return retval;
91 }
92
93 char * process_permanentfile(string const & command)
94 {
95     char *tmpfilename=tempnam(NULL,"ginac");
96     cout << "creating file " << tmpfilename << endl;
97     ofstream fout;
98     fout.open(tmpfilename);
99     fout << command << endl;
100     fout.close();
101     G__store_undo_position();
102     G__loadfile(tmpfilename);
103     G__security_recover(stdout);
104     return tmpfilename;
105 }
106
107 void process_tempfile(string const & command)
108 {
109 #ifdef OBSCURE_CINT_HACK
110     static G__value ref_symbol=exec_tempfile("symbol ginac_cint_internal_symbol; ginac_cint_internal_symbol;");
111     static G__value ref_ex=exec_tempfile("ex ginac_cint_internal_ex; ginac_cint_internal_ex;");
112     static G__value ref_function=exec_tempfile("sin(ginac_cint_internal_symbol);");
113     static G__value ref_power=exec_tempfile("power(ginac_cint_internal_symbol,ginac_cint_internal_symbol);");
114 #endif // def OBSCURE_CINT_HACK
115
116     G__value retval=exec_tempfile(command);
117
118 #ifdef OBSCURE_CINT_HACK
119
120     #define TYPES_EQUAL(A,B) (((A).type==(B).type)&&((A).tagnum==(B).tagnum))
121     
122     static unsigned out_count=0;
123     if (TYPES_EQUAL(retval,ref_ex)) {
124         if (ex::last_created_or_assigned_bp_can_be_converted_to_ex()) {
125             string varname="out"+ToString(++out_count);
126             exec_tempfile("ex "+varname+"(*ex::last_created_or_assigned_bp);\n"
127                           +"LLLAST=LLAST;\n"
128                           +"LLAST=LAST;\n"
129                           +"LAST="+varname+";\n"
130                           +"cout << \""+varname+"   \" << "+varname+" << endl << endl;"); 
131         } else {
132             cout << "warning: last_created_or_assigned_bp modified 0 or not evaluated or not dynallocated" << endl;
133         }
134     }
135 #endif // def OBSCURE_CINT_HACK
136 }
137
138 void greeting(void)
139 {
140     cout << "Welcome to GiNaC-cint V" << VERSION << endl;
141     cout << "This software is provided \"as is\" without any warranty.  Copyright of Cint is" << endl
142          << "owned by Agilent Technologies Japan and Masaharu Goto.  Registration is" << endl
143          << "  __,  _______  requested, at this moment, for commercial use.  Send e-mail to" << endl
144          << " (__) *       | <MXJ02154@niftyserve.or.jp>.  The registration is free." << endl
145          << "  ._) i N a C | The GiNaC framework is Copyright by Johannes Gutenberg Univ." << endl
146          << "<-------------' Germany and licensed under the terms and conditions of the GPL." << endl << endl;
147     cout << "To quit, type 'quit;', 'exit;', 'bye;', '.q', '.quit', '.exit' or '.bye'" << endl;
148 }
149
150 int main(void) 
151 {
152     char *line;
153     char prompt[G__ONELINE];
154
155     greeting();
156
157     atexit(cleanup);
158     signal(SIGTERM,sigterm_handler);
159     
160     G__init_cint("cint");    /* initialize cint */
161
162     exec_tempfile("#include <string>\n");
163     exec_tempfile("ex LAST,LLAST,LLLAST;\n");
164     
165     bool quit=false;
166     bool next_command_is_function=false;    
167     while (!quit) {
168         strcpy(prompt,"GiNaC> ");
169         int open_braces=0;
170         bool end_of_command=false;
171         string command;
172         while (!end_of_command) {
173             line=G__input(prompt);
174         
175             int pos = 0;
176             bool double_quote=false;
177             bool single_quote=false;
178             while(line[pos]!='\0') {
179                 switch(line[pos]) {
180                 case '"':
181                     if (!single_quote) double_quote = !double_quote;
182                     break;
183                 case '\'':
184                     if (!double_quote) single_quote = !single_quote;
185                     break;
186                 case '{':
187                     if ((!single_quote)&&(!double_quote)) open_braces++;
188                     break;
189                 case '}':
190                     if ((!single_quote)&&(!double_quote)) open_braces--;
191                     break;
192                 }
193                 pos++;
194             }
195             command += line;
196             command += '\n';
197             if (open_braces==0) {
198                 if ((first_non_whitespace_char(command.c_str())=='#')||
199                     (first_non_whitespace_char(command.c_str())=='.')||
200                     (last_non_whitespace_char(command.c_str())==';')||
201                     (last_non_whitespace_char(command.c_str())=='}')) {
202                     end_of_command=true;
203                 }
204             }
205             strcpy(prompt,"     > ");
206         }
207         string stripped_command=strip_whitespace(command);
208         if ((stripped_command=="quit;")||
209             (stripped_command=="exit;")||
210             (stripped_command=="bye;")||
211             (stripped_command==".q")||
212             (stripped_command==".quit")||
213             (stripped_command==".exit")||
214             (stripped_command==".bye")) {
215             quit=true;
216         } else if (stripped_command==".function") {
217             cout << "next expression can be a function definition" << endl;
218             next_command_is_function=true;
219         } else if (stripped_command==".cint") {
220             cout << endl << "switching to cint interactive mode" << endl;
221             cout << "'h' for help, 'q' to quit, '{ statements }' or 'p [expression]' to evaluate" << endl;
222             G__pause();
223             cout << "back from cint" << endl;
224         } else if (command[0]=='.') {
225             cout << "special command (TBD): " << command << endl;
226         } else {
227             // cout << "now processing: " << command << endl;
228             if (next_command_is_function) {
229                 next_command_is_function=false;
230                 filenames.push_back(process_permanentfile(command));
231             } else {
232                 process_tempfile(command);
233             }
234         }
235     }
236
237     return 0;
238 }
239
240
241
242
243
244
245