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