1 /*
2 This file is part of GNU APL, a free implementation of the
3 ISO/IEC Standard 13751, "Programming Language APL, Extended"
4
5 Copyright (C) 2008-2016 Dr. Jürgen Sauermann
6
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 of the License, or
10 (at your option) any later version.
11
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.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #ifndef __COMMAND_HH_DEFINED__
22 #define __COMMAND_HH_DEFINED__
23
24 #include <dirent.h>
25
26 #include "Common.hh"
27 #include "LibPaths.hh"
28 #include "Value.hh"
29 #include "UCS_string.hh"
30 #include "UTF8_string.hh"
31
32 class Workspace;
33
34 //-----------------------------------------------------------------------------
35 /*!
36 Some command related functions, including the main input loop
37 of the APL interpreter.
38 */
39 /// The class implementing all APL commands
40 class Command
41 {
42 public:
43 /// process a single line entered by the user (in immediate execution mode)
44 static void process_line();
45
46 /// process \b line which contains a command or statements
47 static void process_line(UCS_string & line);
48
49 /// process \b line which contains an APL command. Return true iff the
50 /// command was user-defined (and then the function for that command is
51 /// stored in \b line and shall be executed)).
52 static bool do_APL_command(ostream & out, UCS_string & line);
53
54 /// process \b line which contains APL statements
55 static void do_APL_expression(UCS_string & line);
56
57 /// finish the current SI->top() and pop it when done
58 static void finish_context();
59
60 /// parse user-suplied argument (of )VARS, )OPS, or )NMS commands)
61 /// into strings from and to
62 static bool parse_from_to(UCS_string & from, UCS_string & to,
63 const UCS_string & user_input);
64
65 /// return true if \b lib looks like a library reference (a 1-digit number
66 /// or a path containing . or / chars
67 static bool is_lib_ref(const UCS_string & lib);
68
69 /// clean-up and exit from APL interpreter
70 static void cmd_OFF(int exit_val);
71
72 /// return the current boxing format
get_boxing_format()73 static int get_boxing_format()
74 { return boxing_format; }
75
76 /// return the number of APL expressions entered in immediate execution mode
get_APL_expression_count()77 static ShapeItem get_APL_expression_count()
78 { return APL_expression_count; }
79
80 /// one user defined command
81 struct user_command
82 {
83 UCS_string prefix; ///< the first characters of the command
84 UCS_string apl_function; ///< APL function implementing the command
85 int mode; ///< how left arg of apl_function is computed
86 };
87
88 /// check workspace integrity (stale Value and IndexExpr objects, etc)
89 static void cmd_CHECK(ostream & out);
90
91 /// a helper for finding sub-values with two parents
92 struct val_val
93 {
94 /// the parent (0 unless child is a sub-value
95 const Value * parent;
96
97 /// the value (always valid)
98 const Value * child;
99
100 /// compare function for Heapsort::sort()
101 static bool compare_val_val(const val_val & A, const val_val & B,
102 const void *);
103
104 /// compare function for bsearch()
105 static int compare_val_val1(const void * key, const void * B);
106 };
107
108 /// return true if entry is a directory
109 static bool is_directory(dirent * entry, const UTF8_string & path);
110
111 /// format for ]BOXING
112 static int boxing_format;
113
114 protected:
115 /// )BOXING command
116 static void cmd_BOXING(ostream & out, const UCS_string & arg);
117
118 /// )SAVE active WS as CONTINUE and )OFF
119 static void cmd_CONTINUE(ostream & out);
120
121 /// )COPY: copy a workspace file
122 static void cmd_COPY(ostream & out, UCS_string_vector & args,
123 bool protection);
124
125 /// ]DOXY: create doxygen-like documentation of the current workspace
126 static void cmd_DOXY(ostream & out, UCS_string_vector & args);
127
128 /// )DROP: delete a workspace file
129 static void cmd_DROP(ostream & out, const UCS_string_vector & args);
130
131 /// )DUMP: dump a workspace file (.apl)
132 static void cmd_DUMP(ostream & out, const UCS_string_vector & args,
133 bool html, bool silent);
134
135 /// )ERASE: erase symbols
136 static void cmd_ERASE(ostream & out, UCS_string_vector & args);
137
138 /// show list of commands
139 static void cmd_HELP(ostream & out, const UCS_string & arg);
140
141 /// show help for APL primitives
142 static void primitive_help(ostream & out, const char * arg, int arity,
143 const char * prim, const char * name,
144 const char * title, const char * descr);
145
146 /// show or clear input history
147 static void cmd_HISTORY(ostream & out, const UCS_string & arg);
148
149 /// )HOST: execute OS command
150 static void cmd_HOST(ostream & out, const UCS_string & arg);
151
152 /// )IN: import a workspace file
153 static void cmd_IN(ostream & out, UCS_string_vector & args, bool protect);
154
155 /// show US keyboard layout
156 static void cmd_KEYB(ostream & out);
157
158 /// )LOAD: load a workspace file
159 static void cmd_LOAD(ostream & out, UCS_string_vector & args,
160 UCS_string & quad_lx, bool silent);
161
162 /// show performance counters
163 static void cmd_PSTAT(ostream & out, const UCS_string & arg);
164
165 /// open directory arg and follow symlinks
166 static DIR * open_LIB_dir(UTF8_string & path, ostream & out,
167 const UCS_string_vector & args);
168
169 /// list library: common helper
170 static void lib_common(ostream & out, const UCS_string_vector & args,
171 int variant);
172
173 /// list content of workspace and wslib directories: )LIB [N]
174 static void cmd_LIB1(ostream & out, const UCS_string_vector & args);
175
176 /// list content of workspace and wslib directories: ]LIB [N]
177 static void cmd_LIB2(ostream & out, const UCS_string_vector & args);
178
179 /// control logging facilities
180 static void cmd_LOG(ostream & out, const UCS_string & arg);
181
182 /// list paths of workspace and wslib directories
183 static void cmd_LIBS(ostream & out, const UCS_string_vector & lib_ref);
184
185 /// print more error info
186 static void cmd_MORE(ostream & out);
187
188 /// )OUT: export a workspace file
189 static void cmd_OUT(ostream & out, UCS_string_vector & args);
190
191 /// )SAVE: save a workspace file (.xml)
192 static void cmd_SAVE(ostream & out, const UCS_string_vector & args);
193
194 /// create a user defined command
195 static void cmd_USERCMD(ostream & out, const UCS_string & arg,
196 UCS_string_vector & args);
197
198 /// enable and disable colors
199 static void cmd_XTERM(ostream & out, const UCS_string & args);
200
201 /// split whitespace separated arguments into individual arguments
202 static UCS_string_vector split_arg(const UCS_string & arg);
203
204 /// execute a user defined command
205 static void do_USERCMD(ostream & out, UCS_string & line,
206 const UCS_string & line1, const UCS_string & cmd,
207 UCS_string_vector & args, int uidx);
208
209 /// check if a command name conflicts with an existing command
210 static bool check_name_conflict(ostream & out, const UCS_string & cnew,
211 const UCS_string cold);
212
213 /// check if a command is being redefined
214 static bool check_redefinition(ostream & out, const UCS_string & cnew,
215 const UCS_string fnew, const int mnew);
216
217 /// check the number of parameters in a command
218 static bool check_params(ostream & out, const char * command, int argc,
219 const char * args);
220
221 /// resolve an optional lib followed by a WS name
222 static bool resolve_lib_wsname(ostream & out, const UCS_string_vector & args,
223 LibRef &lib, UCS_string & wsname);
224
225 /// a helper struct for the )IN command
226 struct transfer_context
227 {
228 /// constructor
transfer_contextCommand::transfer_context229 transfer_context(bool prot)
230 : new_record(true),
231 recnum(0),
232 timestamp(0),
233 protection(prot)
234 {}
235
236 /// process one record of a workspace file
237 void process_record(const UTF8 * record,
238 const UCS_string_vector & objects);
239
240 /// get the name, rank, and shape of a 1 ⎕TF record
241 uint32_t get_nrs(UCS_string & name, Shape & shape) const;
242
243 /// process a 'A' (array in 2 ⎕TF format) item.
244 void array_2TF(const UCS_string_vector & objects) const;
245
246 /// process a 'C' (character, in 1 ⎕TF format) item.
247 void chars_1TF(const UCS_string_vector & objects) const;
248
249 /// process an 'F' (function in 2 ⎕TF format) item.
250 void function_2TF(const UCS_string_vector & objects) const;
251
252 /// process an 'N' (numeric in 1 ⎕TF format) item.
253 void numeric_1TF(const UCS_string_vector & objects) const;
254
255 /// add \b len UTF8 bytes to \b this transfer_context
256 void add(const UTF8 * str, int len);
257
258 /// true if a new record has started
259 bool new_record;
260
261 /// true if record is EBCDIC (not yet supported)
262 bool is_ebcdic;
263
264 /// the record number
265 int recnum;
266
267 /// the record type ('A', 'C', 'N', or 'F')
268 int item_type;
269
270 /// the last timestamp (if any)
271 APL_time_us timestamp;
272
273 /// true if )IN shall not iverride existing objects
274 bool protection; // protect existing objects
275
276 /// accumulator for data of different records
277 UCS_string data;
278 };
279
280 /// parse the argument of the ]LOG command and set logging accordingly
281 static void log_control(const UCS_string & args);
282
283 /// the number of APL expressions entered in immediate execution mode
284 static ShapeItem APL_expression_count;
285 };
286 //-----------------------------------------------------------------------------
Hswap(Command::val_val & vp1,Command::val_val & vp2)287 inline void Hswap(Command::val_val & vp1, Command::val_val & vp2)
288 {
289 const Command::val_val tmp = vp1; vp1 = vp2; vp2 = tmp;
290 }
291 //-----------------------------------------------------------------------------
292 #endif // __COMMAND_HH_DEFINED__
293