2 * Copyright (C) 2001 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 *------------------------------------------------------------------
22 * construction, copy, etc.
37 # include <boost/algorithm/string.hpp>
38 # include <boost/algorithm/string/split.hpp>
42 #ifdef HAVE_LIBREADLINE
43 #include <readline/readline.h>
44 #include <readline/history.h>
46 /*--------------------------------------------------------------------------*/
47 // static std::string getlines(FILE*);
48 OMSTREAM mout
; // > file bitmap //BUG//encapsulation
49 OMSTREAM mlog
; // log file bitmap
50 /*--------------------------------------------------------------------------*/
63 #ifdef HAVE_LIBREADLINE
64 std::string gh
= std::string(getenv("HOME")) + "/.gnucap_history";
67 file
.open(gh
.c_str());
69 while(file
.getline(str
, BUFLEN
)) {
84 if (is_file()) {fclose(_file
);}
87 /*--------------------------------------------------------------------------
88 bool search_file( std::string &name ){
89 const char* h ="HOME";
90 const char* home= getenv(h);
92 if (name[0] == '/') return true; // fixme
94 std::string pathlist[4] = { OPT::libpath , "./", LIBDIR,
95 std::string(home) + std::string("/.gnucap/lib/") };
99 for(int i=1; i<4 ; i++) {
100 if ( FILE* tmp = fopen( (pathlist[i] + "/" + name).c_str(), "r" ) ) {
102 name = pathlist[i]+"/"+name;
105 trace0( (" not found " + pathlist[i] + "/" + name).c_str());
110 --------------------------------------------------------------------------*/
111 CS::CS(CS::INC_FILE
, const std::string
& name
)
123 if(name
[0]=='/' || name
[0]=='~')
128 trace0(("CS::CS(inc, absulute " + name
).c_str());
129 _file
= fopen(name
.c_str(), "r");
132 std::vector
< std::string
> pathlist
;
133 std::string includepath
= OPT::includepath
;
135 boost::algorithm::split(pathlist
, includepath
, boost::is_any_of(":"));
136 for(std::vector
< std::string
>::iterator i
=pathlist
.begin(); i
!=pathlist
.end() ; ++i
) {
137 std::string fn
= (*i
+ "/" + name
);
138 trace1("CS::CS inc, trying ", fn
.c_str());
139 if (( _file
= fopen( fn
.c_str(), "r" ) ) ) {
148 if (!_file
) {itested();
149 throw Exception_File_Open(name
+ ':' + strerror(errno
));
153 /*--------------------------------------------------------------------------*/
154 CS::CS(CS::WHOLE_FILE
, const std::string
& name
)
165 int f
= open(name
.c_str(), O_RDONLY
);
166 if (f
== EOF
) {itested();
167 throw Exception_File_Open(name
+ ':' + strerror(errno
));
170 _length
= static_cast<unsigned>(lseek(f
, off_t(0), SEEK_END
));
171 lseek(f
, off_t(0), SEEK_SET
);
173 char* cmd
= new char[_length
+2];
174 read(f
, cmd
, _length
);
175 cmd
[_length
++] = '\0';
180 /*--------------------------------------------------------------------------*/
181 CS::CS(CS::STRING
, const std::string
& s
)
186 _length(static_cast<unsigned>(s
.length())),
193 /*--------------------------------------------------------------------------*/
209 /*--------------------------------------------------------------------------*/
210 CS
& CS::operator=(const std::string
& s
)
216 _length
= static_cast<unsigned>(s
.length());
219 /*--------------------------------------------------------------------------*/
221 CS
& CS::operator=(const CS
& p
)
233 /*--------------------------------------------------------------------------*/
240 while(_file
&& !tailsize()){
250 /*--------------------------------------------------------------------------*/
251 CS
& CS::get_line(const std::string
& prompt
)
254 if (!_file
) { // assume string or something
257 throw Exception_End_Of_Input("EOF on string/whatever");
258 }else if (is_file() ) {
259 assert(OPT::language
);
261 // CS must know its language.
262 _cmd
= OPT::language
->getlines(_file
);
263 trace2("getlines got", _cmd
, OPT::language
->name());
265 _length
= static_cast<unsigned>(_cmd
.length());
269 assert(_file
== stdin
);
271 // trace0("CS::get_line " + std::string(cmdbuf));
272 getcmd(prompt
.c_str(), cmdbuf
, BUFLEN
);
275 _length
= static_cast<unsigned>(_cmd
.length());
280 IO::mstdout
<< "\"" << fullstring() << "\"\n";
285 /*--------------------------------------------------------------------------*/
286 /* getcmd: get a command.
287 * if "fin" is stdin, display a prompt first.
288 * Also, actually do logging, echo, etc.
290 char *getcmd(const char *prompt
, char *buffer
, int buflen
)
294 if (isatty(fileno(stdin
))) {
296 #ifdef HAVE_LIBREADLINE
298 char* line_read
= readline(prompt
);
299 if (!line_read
) {itested();
300 throw Exception_End_Of_Input("EOF on stdin");
303 // readline gets a new buffer every time, so copy it to where we want it
304 char* end_of_line
= (char*)memccpy(buffer
, line_read
, 0, static_cast<size_t>(buflen
-1));
306 buffer
[buflen
-1] = '\0';
313 trace1("adding history", std::string(buffer
));
316 std::string gh
= std::string(getenv("HOME")) + "/.gnucap_history";
318 file
.open(gh
.c_str(),std::ios_base::app
);
320 file
<< buffer
<< "\n";
328 IO::mstdout
<< prompt
; /* prompt & flush buffer */
329 if (!fgets(buffer
, buflen
, stdin
)) {untested(); /* read line */
330 throw Exception_End_Of_Input("EOF on stdin");
334 (IO::mstdout
- mout
) << '\r'; /* reset col counter */
336 (mlog
+ mout
) << buffer
<< '\n';
340 if (!fgets(buffer
, buflen
, stdin
)) {itested(); /* read line */
341 throw Exception_End_Of_Input("EOF on stdin");
345 (mlog
+ mout
) << buffer
<< '\n';
349 /*--------------------------------------------------------------------------*/
350 static std::string
getlines(FILE *fileptr
)
353 const int buffer_size
= BIGBUFLEN
;
356 bool need_to_get_more
= true; // get another line (extend)
357 while (need_to_get_more
) {
358 char buffer
[buffer_size
+1];
359 char* got_something
= fgets(buffer
, buffer_size
, fileptr
);
360 if (!got_something
) { // probably end of file
361 need_to_get_more
= false;
363 throw Exception_End_Of_Input("");
368 size_t count
= strlen(buffer
);
369 if (buffer
[count
-1] == '\\') {
370 buffer
[count
-1] = '\0';
372 // look ahead at next line
373 //int c = fgetc(fileptr);
375 while (isspace(c
= fgetc(fileptr
))) {
379 need_to_get_more
= true;
380 }else if (c
== '\n') {unreachable();
381 need_to_get_more
= true;
384 need_to_get_more
= false;
394 /*--------------------------------------------------------------------------*/
395 /*--------------------------------------------------------------------------*/