OpenASIP  2.0
EditLineReader.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2009 Tampere University.
3 
4  This file is part of TTA-Based Codesign Environment (TCE).
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23  */
24 /**
25  * @file EditLineReader.cc
26  *
27  * Definition of EditLineReader.cc.
28  *
29  * @author Jussi Nykänen 2004 (nykanen-no.spam-cs.tut.fi)
30  * @author Pekka Jääskeläinen 2005 (pjaaskel-no.spam-cs.tut.fi)
31  * @note reviewed 2 June 2004 by jm, pj, tr, jn
32  * @note rating: yellow
33  */
34 
35 #include <string>
36 #include <cstring>
37 #include <cctype>
38 #include <cstdio>
39 #include <map>
40 
41 #include "EditLineReader.hh"
42 #include "StringTools.hh"
43 #include "MapTools.hh"
44 #include "Application.hh"
45 
46 using std::string;
47 using std::map;
48 
49 map<EditLine*, EditLineReader*> EditLineReader::lineReaders_;
50 
51 /**
52  * Constructor.
53  *
54  * @param program The name of the invocating program.
55  */
57  LineReader(), prompt_(NULL), program_(program), editLine_(NULL),
58  history_(NULL) {
59 }
60 
61 /**
62  * Destructor.
63  */
65 
66  lineReaders_.erase(editLine_);
67 
68  if (history_ != NULL) {
69  history_end(history_);
70  }
71 
72  if (editLine_ != NULL) {
73  el_end(editLine_);
74  }
75 
76  if (prompt_ != NULL) {
77  delete[] prompt_;
78  }
79 }
80 
81 /**
82  * Initializes LineReader.
83  *
84  * Sets the prompt printing function and initializes history.
85  *
86  * @param defPrompt The prompt for the program.
87  * @param in Input file stream.
88  * @param out Output file stream.
89  * @param err Error file stream.
90  */
91 void
93  std::string defPrompt,
94  FILE* in,
95  FILE* out,
96  FILE* err) {
97 
99  // initialize EditLine
100  editLine_ = el_init(program_.c_str(), in, out, err);
101  assert(editLine_!=NULL);
102  // define prompt printing function
103  el_set(editLine_, EL_PROMPT, wrapperToCallPrompt);
104  // bind all keys to the standard GNU emacs-like bindings.
105  //el_set(editLine_, EL_BIND, "-e");
106  el_set(editLine_, EL_EDITOR, "emacs");
107  if (in != stdin) {
108  // when reading from file, editing is set off
109  el_set(editLine_, EL_EDITMODE, 0);
110  }
111  // initialize History
112  HistEvent ev;
113  history_ = history_init();
114  if (history_!=NULL) {
115  // size of the history is set to 100
116  history(history_, &ev, H_SETSIZE, 100);
117  el_set(editLine_, EL_HIST, history, history_);
118  }
119  lineReaders_.insert(ValType(editLine_, this));
120  in_ = in;
121  setInitialized();
122 }
123 
124 /**
125  * Reads line from input stream.
126  *
127  * If prompt is given, it is used as a prompt only for reading this one line.
128  *
129  * @param prompt The prompt.
130  * @return The string that is read.
131  * @exception ObjectNotInitialized If LineReader is not initialized.
132  * @exception EndOfFile When end of file mark (ctrl-d) is received.
133  */
134 string
135 EditLineReader::readLine(std::string prompt) {
136  if (!initialized()) {
137  string message = "LineReader not initialized";
138  throw ObjectNotInitialized(__FILE__, __LINE__, __func__, message);
139  }
140 
141  char* oldPrompt = NULL;
142  if (prompt != "") {
143  oldPrompt = prompt_;
145  }
146 
147  int count;
148  const char* c = el_gets(editLine_, &count);
149 
150  bool endOfFile = (c == NULL || strlen(c) == 0 || feof(in_));
151  if (endOfFile) {
152  string message = "End of file.";
153  throw EndOfFile(__FILE__, __LINE__, __func__, message);
154  }
155 
156  // add command to history
157  updateHistory(c);
158  if (oldPrompt != NULL) {
159  delete[] prompt_;
160  prompt_ = oldPrompt;
161  }
162  return c;
163 }
164 
165 /**
166  * Asks user a question and expects that answer is given as char.
167  *
168  * Prompt is temporarily changed to 'question' during the execution of this
169  * function.
170  *
171  * @param question The asked question.
172  * @param allowedChars The chars that are legal answers.
173  * @param caseSensitive Flag indicating whether answer is read case sensitive
174  * or not.
175  * @param defaultAnswer The default answer.
176  * @return User given answer.
177  * @exception ObjectNotInitialized If LineReader is not initialized.
178  */
179 char
181  std::string question, std::string allowedChars, bool caseSensitive,
182  char defaultAnswer) {
183  if (!initialized()) {
184  string method = "EditLineReader::charQuestion()";
185  string message = "LineReader not initialized";
186  throw ObjectNotInitialized(__FILE__, __LINE__, method, message);
187  }
188 
189  char* oldPrompt = prompt_;
191 
192  if (defaultAnswer == '\0') {
193  const char* answer = nullptr;
194  do {
195  int count;
196  answer = el_gets(editLine_, &count);
197  } while (strlen(answer) != 1 &&
198  !StringTools::
199  containsChar(allowedChars, answer[0], caseSensitive));
200 
201  updateHistory(answer);
202  delete[] prompt_;
203  prompt_ = oldPrompt;
204  return answer[0];
205  } else {
206  const char* answer = nullptr;
207  int count;
208  assert(editLine_ != nullptr);
209  answer = el_gets(editLine_, &count);
210  if (answer == nullptr) {
211  updateHistory("");
212  delete[] prompt_;
213  prompt_ = oldPrompt;
214  return defaultAnswer;
215  }
216  if (strlen(answer) != 1 &&
217  !StringTools::
218  containsChar(allowedChars, answer[0], caseSensitive)) {
219 
220  updateHistory(&defaultAnswer);
221  delete[] prompt_;
222  prompt_ = oldPrompt;
223  return defaultAnswer;
224  } else {
225  updateHistory(answer);
226  delete[] prompt_;
227  prompt_ = oldPrompt;
228  return answer[0];
229  }
230  }
231 }
232 
233 /**
234  * Static wrapper function that calls function that returns the prompt.
235  *
236  * If correct EditLine* instance is not found in the map, an empty string
237  * (null char*) is returned.
238  *
239  * @param edit EditLine which prompt is needed.
240  * @return The prompt.
241  */
242 char*
244 
245  MapIt mi = lineReaders_.find(edit);
246  if (mi == lineReaders_.end()) {
247  return NULL;
248  }
249  EditLineReader* reader = (*mi).second;
250  return reader->prompt();
251 }
252 
253 /**
254  * Returns the used prompt.
255  *
256  * @return The prompt.
257  */
258 char*
260  return prompt_;
261 }
262 
263 /**
264  * Inserts a new entry to history.
265  *
266  * Only non-empty strings are saved to history.
267  *
268  * @param newEntry A new entry to be added.
269  */
270 void
271 EditLineReader::updateHistory(const char* newEntry) {
272  string entry(newEntry);
273  entry = StringTools::trim(entry);
274  if (entry != "") {
275  HistEvent ev;
276  history(history_, &ev, H_ENTER, newEntry);
277  putInInputHistory(newEntry);
278  }
279 }
EditLineReader::program_
std::string program_
The name of the invocating program.
Definition: EditLineReader.hh:86
EditLineReader::initialize
virtual void initialize(std::string defPrompt="", FILE *in=stdin, FILE *out=stdout, FILE *err=stderr)
Definition: EditLineReader.cc:92
MapTools.hh
EditLineReader::history_
History * history_
History instance.
Definition: EditLineReader.hh:90
StringTools::stringToCharPtr
static char * stringToCharPtr(const std::string &source)
Definition: StringTools.cc:83
EditLineReader::prompt
char * prompt()
Definition: EditLineReader.cc:259
EditLineReader::updateHistory
void updateHistory(const char *c)
Definition: EditLineReader.cc:271
LineReader::putInInputHistory
void putInInputHistory(const std::string &inputLine)
Definition: LineReader.cc:184
EditLineReader::editLine_
EditLine * editLine_
EditLine instance.
Definition: EditLineReader.hh:88
LineReader::setInitialized
void setInitialized()
EditLineReader::ValType
std::map< EditLine *, EditLineReader * >::value_type ValType
value_type for map.
Definition: EditLineReader.hh:70
EditLineReader::wrapperToCallPrompt
static char * wrapperToCallPrompt(EditLine *edit)
Definition: EditLineReader.cc:243
StringTools.hh
assert
#define assert(condition)
Definition: Application.hh:86
ObjectNotInitialized
Definition: Exception.hh:640
Application.hh
__func__
#define __func__
Definition: Application.hh:67
EditLineReader::MapIt
std::map< EditLine *, EditLineReader * >::iterator MapIt
Iterator for map.
Definition: EditLineReader.hh:72
EditLineReader::readLine
virtual std::string readLine(std::string prompt="")
Definition: EditLineReader.cc:135
StringTools
Definition: StringTools.hh:44
EditLineReader::in_
FILE * in_
Input stream is saved for end-of-file checking.
Definition: EditLineReader.hh:98
LineReader::initialized
bool initialized() const
StringTools::trim
static std::string trim(const std::string &source)
Definition: StringTools.cc:55
EditLineReader::~EditLineReader
virtual ~EditLineReader()
Definition: EditLineReader.cc:64
LineReader
Definition: LineReader.hh:52
EditLineReader::EditLineReader
EditLineReader(std::string program="")
Definition: EditLineReader.cc:56
EditLineReader::prompt_
char * prompt_
Line reader prompt.
Definition: EditLineReader.hh:84
EditLineReader
Definition: EditLineReader.hh:53
program
find Finds info of the inner loops in the program
Definition: InnerLoopFinder.cc:80
EndOfFile
Definition: Exception.hh:189
EditLineReader::charQuestion
virtual char charQuestion(std::string question, std::string allowedChars, bool caseSensitive=false, char defaultAnswer='\0')
Definition: EditLineReader.cc:180
EditLineReader.hh
EditLineReader::lineReaders_
static std::map< EditLine *, EditLineReader * > lineReaders_
Map containing all (EditLine*, EditLineReader*) pairs to make prompt printing possible....
Definition: EditLineReader.hh:95