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 __INPUT_FILE_HH_DEFINED__
22 #define __INPUT_FILE_HH_DEFINED__
23 
24 #include <vector>
25 
26 #include "UTF8_string.hh"
27 #include "UCS_string_vector.hh"
28 
29 /** an input file and its properties. The file can be an apl script(.apl) file
30     or a testcase (.tc) file. The file names initially come from the command
31     line, but can be extended by )COPY commands
32  */
33 /// A single input file to be executed by the interpreter
34 struct InputFile
35 {
36    friend class IO_Files;
37 
38    /// empty constructor
InputFileInputFile39    InputFile() {}
40 
41    /// Normal constructor
InputFileInputFile42    InputFile(const UTF8_string & _filename, FILE * _file,
43                      bool _test, bool _echo, bool _is_script, LX_mode LX)
44    : file     (_file),
45      filename (&_filename[0], _filename.size()),
46      test     (_test),
47      echo     (_echo),
48      is_script(_is_script),
49      with_LX  (LX),
50      line_no  (0),
51      in_html  (0),
52      in_function(false),
53      in_variable(false),
54      in_matched(false),
55      from_COPY(false)
56    {}
57 
58    /// set the from_COPY flag
set_COPYInputFile59    void set_COPY()
60       { from_COPY = true; }
61 
62    /// set the current line number
set_line_noInputFile63    void set_line_no(int num)
64       { line_no = num; }
65 
66    /// set the current HTML mode
set_htmlInputFile67    void set_html(int html)
68       { in_html = html; }
69 
70    /// return the current HTML mode
get_htmlInputFile71    int get_html() const
72       { return in_html; }
73 
74    /// the current file
current_fileInputFile75    static InputFile * current_file()
76       { return files_todo.size() ? &files_todo[0] : 0; }
77 
78    /// the name of the currrent file
current_filenameInputFile79    static const char * current_filename()
80       { return files_todo.size() ? files_todo[0].filename.c_str() : "stdin"; }
81 
82    /// the line number of the currrent file
current_line_noInputFile83    static int current_line_no()
84       { return files_todo.size() ? files_todo[0].line_no : stdin_line_no; }
85 
86    /// increment the line number of the current file
increment_current_line_noInputFile87    static void increment_current_line_no()
88       { if (files_todo.size()) ++files_todo[0].line_no; else ++stdin_line_no; }
89 
90    /// return true iff input comes from a script (as opposed to running
91    /// interactively)
running_scriptInputFile92    static bool running_script()
93       { return files_todo.size() > 0 && files_todo[0].is_script; }
94 
95    /// return true iff the current input file exists and is a test file
is_validatingInputFile96    static bool is_validating()
97       { return files_todo.size() > 0 && files_todo[0].test; }
98 
99    /// the number of testcase (.tc) files
testcase_file_countInputFile100    static int testcase_file_count()
101       {
102         int count = 0;
103         loop(f, files_todo.size())
104             {
105               if (files_todo[f].test)   ++count;
106             }
107         return count;
108       }
109 
110    /// add object to object_filter
add_filter_objectInputFile111    void add_filter_object(UCS_string & object)
112       {
113         object_filter.push_back(object);
114       }
115 
116    /// return true if this file as an oject filter (from )COPY file names...)
has_object_filterInputFile117    bool has_object_filter() const
118       { return object_filter.size() > 0; }
119 
120    /// check the current line and return true if the line is permitted by the
121    /// object_filter. This function also updates \b in_function and \b
122    /// in_variable
123    bool check_filter(const UTF8_string & line);
124 
125    /// true if echo (of the input) is on for the current file
126    static bool echo_current_file();
127 
128    /// open current file unless already open
129    static void open_current_file();
130 
131    /// close the current file and perform some cleanup
132    static void close_current_file();
133 
134    /// randomize the order of test_file_names
135    static void randomize_files();
136 
137    /// files that need to be processed
138    static std::vector<InputFile> files_todo;
139 
140    /// the initial set of files provided on the command line
141    static std::vector<InputFile> files_orig;
142 
143    /// FILE * from fopen (or 0 if file is closed)
144    FILE       * file;
145 
146    /// the file name
147    UTF8_string  filename;
148 
149 protected:
150 
151    bool test;         ///< true for -T testfile, false for -f APL file
152    bool echo;         ///< echo stdin
153    bool is_script;    ///< script (override existing functions)
154    LX_mode with_LX;   ///< execute ⎕LX at the end
155    int  line_no;      ///< line number in file
156    int  in_html;      ///< 0: no HTML, 1: in HTML file 2: in HTML header
157 
158    /// functions and vars that shoule be )COPIED
159    UCS_string_vector object_filter;
160 
161    /// true if current line belongs to a function. Cleared at final ∇
162    bool in_function;
163 
164    /// return true if current line belongs to a variable. Cleared by empty line
165    bool in_variable;
166 
167    /// true if current function or variable was mentioned in object_filter
168    bool in_matched;
169 
170    /// true if this file comes from a )COPY XXX.apl (but not XXX.xml
171    bool from_COPY;
172 
173    /// line number in stdin
174    static int stdin_line_no;
175 };
176 
177 #endif // __INPUT_FILE_HH_DEFINED__
178