X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?a=blobdiff_plain;f=cint%2Fginaccint.bin.cpp;h=065c27c8396b83c96a7d454d940da80e84cbc614;hb=5ced2647e3a2ce07042d0829017d0d12de9883a5;hp=23cb38bd3b502802ad0d1aa69e6dccae2970ff91;hpb=736fa98c85ffb3632e7a910cce34e3e1cc2a3b4b;p=ginac.git diff --git a/cint/ginaccint.bin.cpp b/cint/ginaccint.bin.cpp index 23cb38bd..065c27c8 100644 --- a/cint/ginaccint.bin.cpp +++ b/cint/ginaccint.bin.cpp @@ -1,4 +1,9 @@ #include "G__ci.h" /* G__atpause is defined in G__ci.h */ + +#if (!defined(G__CINTVERSION)) || (G__CINTVERSION < 501438) +#error You need at least cint 5.14.38 to compile GiNaC-cint. Download it via http from root.cern.ch/root/Cint.html or via ftp from ftpthep.physik.uni-mainz.de/pub/cint +#endif // (!defined(G__CINTVERSION)) || (G__CINTVERSION < 501438) + #include #include #include @@ -8,9 +13,16 @@ #include "config.h" #include +#ifndef NO_NAMESPACE_GINAC +using namespace GiNaC; +#endif // ndef NO_NAMESPACE_GINAC + extern "C" G__value G__exec_tempfile G__P((char *file)); extern "C" void G__store_undo_position(void); +#define PROMPT1 "GiNaC> " +#define PROMPT2 " > " + #ifdef OBSCURE_CINT_HACK #include @@ -23,61 +35,33 @@ string ToString(const T & t) return buf; } -basic * ex::last_created_or_assigned_bp=0; -basic * ex::dummy_bp=0; -long ex::last_created_or_assigned_exp=0; +basic * ex::last_created_or_assigned_bp = 0; +basic * ex::dummy_bp = 0; +long ex::last_created_or_assigned_exp = 0; #endif // def OBSCURE_CINT_HACK -typedef list cplist; +G__value exec_tempfile(string const & command); +char * process_permanentfile(string const & command); +void process_tempfile(string const & command); +void greeting(void); +void helpmessage(void); +string preprocess(char const * const line, bool & comment, bool & single_quote, + bool & double_quote, unsigned & open_braces); +void cleanup(void); +void sigterm_handler(int n); +void initialize(void); +void initialize_cint(void); +void restart(void); +bool is_command(string const & command, string & preprocessed, + string const & comparevalue, bool substr=false); +bool readlines(istream * is, string & allcommands); +bool readfile(string const & filename, string & allcommands); +void savefile(string const & filename, string const & allcommands); +typedef list cplist; cplist filenames; - -void cleanup(void) -{ - for (cplist::iterator it=filenames.begin(); it!=filenames.end(); ++it) { - cout << "removing file " << *it << endl; - remove(*it); - free(*it); - } -} - -void sigterm_handler(int n) -{ - exit(1); -} - -bool is_whitespace_char(char c) -{ - return ((c==' ') || (c=='\t') || (c=='\n') || (c=='\r')); -} - -char first_non_whitespace_char(char const * s) -{ - int l = strlen(s); - int pos = 0; - while ((pos=0) && is_whitespace_char(s[pos])) - pos--; - return s[pos]; -} - -string strip_whitespace(string const & s) -{ - string s2; - int l = s.length(); - for (int pos=0; pos. The registration is free." << endl - << " ._) i N a C | The GiNaC framework is Copyright by Johannes Gutenberg Univ.," << endl - << "<-------------' Germany and licensed under the terms and conditions of the GPL." << endl + cout << " __, _______ GiNaC: (C) 1999-2000 Johannes Gutenberg University Mainz," << endl + << " (__) * | Germany. Cint C/C++ interpreter: (C) 1995-2000 Masaharu" << endl + << " ._) i N a C | Goto and Agilent Technologies, Japan. This is free software" << endl + << "<-------------' with ABSOLUTELY NO WARRANTY. For details, type `.warranty'" << endl + << "Type .help for help." << endl << endl; + return; } -int main(void) +void helpmessage(void) { - char *line; - char prompt[G__ONELINE]; + cout << "GiNaC-cint recognizes some special commands which start with a dot:" << endl << endl + << " .cint switch to cint interactive mode (see cint" << endl + << " documentation for further details)" << endl + << " .function define the body of a function (necessary due to a" << endl + << " cint limitation)" << endl + << " .help the text you are currently reading" << endl + << " .q, .quit, .exit, .bye quit GiNaC-cint" << endl + << " .read filename read a file from disk and execute it in GiNaC-cint" << endl + << " (recursive call is possible)" << endl + << " .redirect [filename] redirect 'OutXY = ...' output to a file" << endl + << " (.redirect alone redirects output back to console)" << endl + << " .restart restart GiNaC-cint (does not re-read command line" << endl + << " files)" << endl + << " .save filename save the commands you have entered so far in a file" << endl + << " .silent suppress 'OutXY = ...' output (variables are still" << endl + << " accessible)" << endl + << " .warranty information on redistribution and warranty" << endl + << " .> [filename] same as .redirect [filename]" << endl << endl + << "Instead of '.cmd' you can also write '//GiNaC-cint.cmd' to be compatible with" << endl + << "programs that will be compiled later." << endl + << "Additionally you can exit GiNaC-cint with quit; exit; or bye;" << endl + << endl; + return; +} + +void warrantymessage(void) +{ + cout << "GiNaC is free software; you can redistribute it and/or modify it under the" << endl + << "the terms of the GNU General Public License as published by the Free Software" << endl + << "Foundation; either version 2 of the License, or (at your option) any later" << endl + << "version." << endl + << "This program is distributed in the hope that it will be useful, but WITHOUT" << endl + << "ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS" << endl + << "FOR A PARTICULAR PURPOSE. See the GNU General Public License for more" << endl + << "details." << endl + << "You should have received a copy of the GNU General Public License along with" << endl + << "this program. If not, write to the Free Software Foundation, 675 Mass Ave," << endl + << "Cambridge, MA 02139, USA." << endl << endl; + cout << "Cint and associated tools are copyright by Agilent Technologies Japan Company" << endl + << "and Masaharu Goto ." << endl + << "Source code, binary executable or library of Cint and associated tools can be" << endl + << "used, modified and distributed with no royalty for any purpose provided that" << endl + << "the copyright notice appear in all copies and that both that copyright notice" << endl + << "and this permission notice appear in supporting documentation." << endl + << "Agilent Technologies Japan and the author make no representations about the" << endl + << "suitability of this software for any purpose. It is provided \"AS IS\"" << endl + << "without express or implied warranty." << endl; + return; +} + +string preprocess(char const * const line, bool & comment, bool & single_quote, + bool & double_quote, unsigned & open_braces) +{ + // "preprocess" the line entered to be able to decide if the command shall be + // executed directly or more input is needed or this is a special command + + // ALL whitespace will be removed + // all comments (/* */ and //) will be removed + // open and close braces ( { and } ) outside strings will be counted + + /* + cout << "line=" << line << endl; + cout << "comment=" << comment << ", single_quote=" << single_quote + << ",double_quote=" << double_quote << ", open_braces=" << open_braces + << endl; + */ + + string preprocessed; + int pos = 0; + bool end = false; + bool escape = false; + bool slash = false; + bool asterisk = false; + while ((line[pos]!='\0')&&!end) { + if (escape) { + // last character was a \, ignore this one + escape = false; + } else if (slash) { + // last character was a /, test if * or / + slash = false; + if (line[pos]=='/') { + end = true; + } else if (line[pos]=='*') { + comment = true; + } else { + preprocessed += '/'; + preprocessed += line[pos]; + } + } else if (asterisk) { + // last character was a *, test if / + asterisk = false; + if (line[pos]=='/') { + comment = false; + } else if (line[pos]=='*') { + preprocessed += '*'; + asterisk = true; + } + } else { + switch (line[pos]) { + case ' ': + case '\t': + case '\n': + case '\r': + // whitespace: ignore + break; + case '\\': + // escape character, ignore next + escape=true; + break; + case '"': + if ((!single_quote)&&(!comment)) { + double_quote = !double_quote; + } + break; + case '\'': + if ((!double_quote)&&(!comment)) { + single_quote = !single_quote; + } + break; + case '{': + if ((!single_quote)&&(!double_quote)&&(!comment)) { + open_braces++; + } + break; + case '}': + if ((!single_quote)&&(!double_quote)&&(!comment)&&(open_braces>0)) { + open_braces--; + } + break; + case '/': + slash = true; + break; + case '*': + asterisk = true; + break; + default: + preprocessed += line[pos]; + } + } + pos++; + } + + /* + cout << "preprocessed=" << preprocessed << endl; + cout << "comment=" << comment << ", single_quote=" << single_quote + << ",double_quote=" << double_quote << ", open_braces=" << open_braces + << endl; + */ + + return preprocessed; +} +void cleanup(void) +{ + for (cplist::iterator it=filenames.begin(); it!=filenames.end(); ++it) { + cout << "removing file " << *it << endl; + remove(*it); + free(*it); + } +} + +void sigterm_handler(int n) +{ + exit(1); +} + +void initialize(void) +{ if (isatty(0)) greeting(); atexit(cleanup); signal(SIGTERM,sigterm_handler); - + initialize_cint(); +} + +void initialize_cint(void) +{ G__init_cint("cint"); /* initialize cint */ - exec_tempfile("#include \n"); + // no longer needed as of cint 5.14.31: + // exec_tempfile("#include \n"); + +#ifndef NO_NAMESPACE_GINAC + exec_tempfile("using namespace GiNaC;"); +#endif // ndef NO_NAMESPACE_GINAC + exec_tempfile("ex LAST,LLAST,LLLAST;\n"); + exec_tempfile("bool ginac_cint_internal_redirect_output=false;\n"); + exec_tempfile("ofstream ginac_cint_internal_fout;\n"); +} + +void restart(void) +{ + cout << "Restarting GiNaC-cint." << endl; + G__scratch_all(); + initialize_cint(); +} + +void redirect(string const & filename) +{ + if (filename=="") { + cout << "Redirecting output back to console..." << endl; + exec_tempfile( string() + +"ginac_cint_internal_redirect_output=false;\n" + +"ginac_cint_internal_fout.close();"); + } else { + cout << "Redirecting output to " << filename << "..." << endl; + exec_tempfile( string() + +"ginac_cint_internal_redirect_output=true;\n" + +"ginac_cint_internal_fout.open(\""+filename+"\");\n"); + } +} + +bool is_command(string const & command, string & preprocessed, + string const & comparevalue, bool substr) +{ + bool single_quote = false; + bool double_quote = false; + bool comment = false; + unsigned open_braces = 0; + if ((preprocessed=="."+comparevalue)|| + substr&&(preprocessed.substr(0,comparevalue.length()+1)== + "."+comparevalue)) { + return true; + } + if ((command=="//GiNaC-cint."+comparevalue+"\n")|| + substr&&(command.substr(0,comparevalue.length()+13)== + "//GiNaC-cint."+comparevalue)) { + preprocessed = preprocess(command.substr(12).c_str(),comment, + single_quote,double_quote,open_braces); + return true; + } + return false; +} + +bool readlines(istream * is, string & allcommands) +{ + char const * line; + char prompt[G__ONELINE]; + string linebuffer; bool quit = false; - bool next_command_is_function=false; - while (!quit) { - strcpy(prompt,"GiNaC> "); - int open_braces = 0; + bool eof = false; + bool next_command_is_function = false; + bool single_quote = false; + bool double_quote = false; + bool comment = false; + unsigned open_braces = 0; + + while ((!quit)&&(!eof)) { + strcpy(prompt,PROMPT1); bool end_of_command = false; string command; + string preprocessed; while (!end_of_command) { - line = G__input(prompt); - - int pos = 0; - bool double_quote = false; - bool single_quote = false; - while(line[pos]!='\0') { - switch(line[pos]) { - case '"': - if (!single_quote) double_quote = !double_quote; - break; - case '\'': - if (!double_quote) single_quote = !single_quote; - break; - case '{': - if ((!single_quote) && (!double_quote)) open_braces++; - break; - case '}': - if ((!single_quote) && (!double_quote)) open_braces--; - break; - } - pos++; + if (is==NULL) { + line = G__input(prompt); + } else { + getline(*is,linebuffer); + line = linebuffer.c_str(); } command += line; - command += '\n'; - if (open_braces==0) { - if ((first_non_whitespace_char(command.c_str())=='#')|| - (first_non_whitespace_char(command.c_str())=='.')|| - (last_non_whitespace_char(command.c_str())==';')|| - (last_non_whitespace_char(command.c_str())=='}')) { - end_of_command=true; + command += "\n"; + preprocessed += preprocess(line,comment,single_quote,double_quote,open_braces); + if ((open_braces==0)&&(!single_quote)&&(!double_quote)&&(!comment)) { + unsigned l = preprocessed.length(); + if ((l==0)|| + (preprocessed[0]=='#')|| + (preprocessed[0]=='.')|| + (preprocessed[l-1]==';')|| + (preprocessed[l-1]=='}')) { + end_of_command = true; } } - strcpy(prompt," > "); + strcpy(prompt,PROMPT2); } - string stripped_command=strip_whitespace(command); - if ((stripped_command=="quit;")|| - (stripped_command=="exit;")|| - (stripped_command=="bye;")|| - (stripped_command==".q")|| - (stripped_command==".quit")|| - (stripped_command==".exit")|| - (stripped_command==".bye")) { + if ((preprocessed=="quit;")|| + (preprocessed=="exit;")|| + (preprocessed=="bye;")|| + (is_command(command,preprocessed,"quit"))|| + (is_command(command,preprocessed,"exit"))|| + (is_command(command,preprocessed,"bye"))|| + (is_command(command,preprocessed,"q"))) { quit = true; - } else if (stripped_command==".function") { + } else if (is_command(command,preprocessed,"function")) { cout << "next expression can be a function definition" << endl; next_command_is_function=true; - } else if (stripped_command==".cint") { + } else if (is_command(command,preprocessed,"cint")) { cout << endl << "switching to cint interactive mode" << endl; cout << "'h' for help, 'q' to quit, '{ statements }' or 'p [expression]' to evaluate" << endl; G__pause(); cout << "back from cint" << endl; - } else if (command[0]=='.') { + } else if (is_command(command,preprocessed,"help")) { + helpmessage(); + } else if (is_command(command,preprocessed,"read",true)) { + quit=readfile(preprocessed.substr(5),allcommands); + } else if (is_command(command,preprocessed,"save",true)) { + command = "/* "+command+" */"; // we do not want the .save command itself in saved files + savefile(preprocessed.substr(5),allcommands); + } else if (is_command(command,preprocessed,"restart")) { + restart(); + } else if (is_command(command,preprocessed,"redirect",true)) { + redirect(preprocessed.substr(9)); + } else if (is_command(command,preprocessed,">",true)) { + redirect(preprocessed.substr(2)); + } else if (is_command(command,preprocessed,"silent")) { + redirect("/dev/null"); + } else if (is_command(command,preprocessed,"warranty")) { + warrantymessage(); + /* test for more special commands + } else if (preprocessed==".xyz") { cout << "special command (TBD): " << command << endl; + */ + } else if (command.substr(0,2)=="#!") { + // ignore lines which indicate that this file is executed as a script } else { // cout << "now processing: " << command << endl; if (next_command_is_function) { @@ -248,14 +500,76 @@ int main(void) process_tempfile(command); } } + if (is!=NULL) { + // test for end of file if reading from a stream + eof=is->eof(); + } else { + // save commands only when reading from keyboard + allcommands += command; + } + } + return quit; +} - return 0; +bool readfile(string const & filename, string & allcommands) +{ + cout << "Reading commands from file " << filename << "." << endl; + bool quit = false; + ifstream fin; + fin.open(filename.c_str()); + if (fin.good()) { + quit = readlines(&fin,allcommands); + } else { + cout << "Cannot open " << filename << " for reading." << endl; + } + fin.close(); + return quit; } +void savefile(string const & filename, string const & allcommands) +{ + cout << "Saving commands to file " << filename << "." << endl; + ofstream fout; + fout.open(filename.c_str()); + if (fout.good()) { + fout << allcommands; + if (!fout.good()) { + cout << "Cannot save commands to " << filename << "." << endl; + } + } else { + cout << "Cannot open " << filename << " for writing." << endl; + } + fout.close(); +} +int main(int argc, char ** argv) +{ + string allcommands; + initialize(); + bool quit = false; + bool argsexist = argc>1; + if (argsexist) { + allcommands = "/* Files given as command line arguments:\n"; + } + + argc--; argv++; + while (argc && !quit) { + allcommands += *argv; + allcommands += "\n"; + quit=readfile(*argv,allcommands); + argc--; argv++; + } + if (argsexist) { + allcommands += "*/\n"; + } + if (!quit) { + readlines(NULL,allcommands); + } + return 0; +}