1 /*-
2  * Copyright (c) 2005-2019 Michael Scholz <mi-scholz@users.sourceforge.net>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * @(#)utils.h	2.2 11/18/19
27  */
28 
29 #if !defined(_UTILS_H_)
30 #define _UTILS_H_
31 
32 #define PROPERTY_HASH_SIZE	101
33 
34 /*
35  * Shell environment variables and default values:
36  *
37  * $FTH_INIT_FILE		~/.fthrc
38  * $FTH_HISTORY			~/.fth-history
39  * $FTH_HISTORY_LENGTH		100
40  * $FTH_FTHPATH			""
41  * $FTH_LIBPATH			""
42  *
43  * $FTH_DICTIONARY_SIZE		1024 * 1024
44  * $FTH_STACK_SIZE		1024 * 8
45  * $FTH_RETURN_SIZE		1024
46  * $FTH_LOCALS_SIZE		2048
47  */
48 
49 #define FTH_ENV_INIT_FILE	"FTH_INIT_FILE"
50 #define FTH_ENV_HIST		"FTH_HISTORY"
51 #define FTH_ENV_HIST_LEN	"FTH_HISTORY_LENGTH"
52 #define FTH_ENV_FTHPATH		"FTH_FTHPATH"
53 #define FTH_ENV_LIBPATH		"FTH_LIBPATH"
54 
55 #define FTH_ENV_DICTIONARY_SIZE	"FTH_DICTIONARY_SIZE"
56 #define FTH_ENV_STACK_SIZE	"FTH_STACK_SIZE"
57 #define FTH_ENV_RETURN_SIZE	"FTH_RETURN_SIZE"
58 #define FTH_ENV_LOCALS_SIZE	"FTH_LOCALS_SIZE"
59 
60 #define _FTH_String(X)		#X
61 #define FTH_XString(X)		_FTH_String(X)
62 
63 /* proc.c */
64 #define fth_make_proc_from_vfunc(Name, Func, Req, Opt, Rest)		\
65 	fth_make_proc_from_func(Name, (FTH (*)())Func, 1, Req, Opt, Rest)
66 
67 #define FTH_SET_CONSTANT(Name)						\
68 	fth_define_constant(#Name, (FTH)(Name), NULL)
69 
70 /*-
71  * MAKE_MEMBER(Object, Name, Type, Member)
72  *
73  * Object = object type, e.g. FArray, FHash etc.
74  * Name   = prefix string, e.g. ary, str
75  * Type   = what ficl/stack.c provides, e.g. Integer, Float etc.
76  * Member = struct member name, e.g. length
77  *
78  *   MAKE_MEMBER(FArray, ary, Integer, length)
79  *
80  * creates two static C functions:
81  *
82  *   cb_ary_length()
83  *   init_ary_length()
84  *
85  * The latter can be called e.g. in init_array() to create the Ficl
86  * word:
87  *
88  *   ary->length
89  *
90  */
91 #define MAKE_MEMBER(Object, Name, Type, Member)				\
92 static void								\
93 cb_ ## Name ## _ ## Member(ficlVm *vm)					\
94 {									\
95 	FTH		obj;						\
96 									\
97 	FTH_STACK_CHECK(vm, 1, 1);					\
98 	obj = fth_pop_ficl_cell(vm);					\
99 									\
100 	if (fth_instance_p(obj))					\
101 		ficlStackPush ## Type(vm->dataStack,			\
102 		    FTH_INSTANCE_REF_GEN(obj, Object)->Member);		\
103 	else								\
104 		ficlStackPushBoolean(vm->dataStack, 0);			\
105 }									\
106 static void								\
107 init_ ## Name ## _ ## Member(void)					\
108 {									\
109 	ficlDictionaryAppendPrimitive(FTH_FICL_DICT(),			\
110 	    #Name "->" #Member, cb_ ## Name ## _ ## Member,		\
111 	    FICL_WORD_DEFAULT);						\
112 }
113 
114 /* Simple Array */
115 typedef struct {
116 	void          **data;
117 	unsigned	length;
118 	unsigned	incr;
119 } simple_array;
120 
121 /* === IO === */
122 
123 #if defined(HAVE_SYS_SOCKET_H)
124 #include <sys/socket.h>
125 #endif
126 #if defined(HAVE_SYS_UN_H)
127 #include <sys/un.h>
128 #endif
129 #if defined(HAVE_NETINET_IN_H)
130 #include <netinet/in.h>
131 #endif
132 #if defined(HAVE_NETDB_H)
133 #include <netdb.h>
134 #endif
135 #if defined(HAVE_SYS_UIO_H)
136 #include <sys/uio.h>
137 #endif
138 
139 #if !defined(HAVE_STRUCT_SOCKADDR_UN) || defined(_WIN32)
140 #define HAVE_SOCKET		0
141 #define FTH_DEFAULT_ADDRFAM	0
142 #else				/* !_WIN32 */
143 #define HAVE_SOCKET		1
144 #if defined(AF_INET)
145 #define FTH_DEFAULT_ADDRFAM	AF_INET
146 #else
147 #define FTH_DEFAULT_ADDRFAM	2
148 #endif
149 #endif				/* _WIN32 */
150 
151 #define FTH_DEFAULT_PORT	1024
152 
153 /* Keywords for xxx_open(:if-exists). */
154 #define FTH_KEYWORD_ERROR	fth_keyword("error")
155 #define FTH_KEYWORD_RENAME	fth_keyword("rename")
156 #define FTH_KEYWORD_OVERWRITE	fth_keyword("overwrite")
157 
158 typedef enum {
159 	FTH_IO_UNDEF,
160 	FTH_IO_FILE,
161 	FTH_IO_PIPE,
162 	FTH_IO_SOCKET,
163 	FTH_IO_STRING,
164 	FTH_IO_PORT
165 } io_t;
166 
167 typedef struct {
168 	io_t 		type;
169 	FTH 		name;
170 	FTH 		filename;
171 	FTH 		buffer;
172 	int 		fam;
173 	void           *data;
174 	ficl2Integer 	length;
175 	int 		input_p;
176 	int 		output_p;
177 	int 		closed_p;
178 	int             (*read_char) (void *);
179 	void            (*write_char) (void *, int);
180 	char           *(*read_line) (void *);
181 	void            (*write_line) (void *, const char *);
182 	int             (*eof_p) (void *);
183 	ficl2Integer    (*tell) (void *);
184 	ficl2Integer    (*seek) (void *, ficl2Integer, int);
185 	void            (*flush) (void *);
186 	void            (*rewind) (void *);
187 	void            (*close) (void *);
188 } FIO;
189 
190 #define FTH_IO_OBJECT(Obj)	FTH_INSTANCE_REF_GEN(Obj, FIO)
191 
192 #define FTH_IO_TYPE(Obj)	FTH_IO_OBJECT(Obj)->type
193 #define FTH_IO_NAME(Obj)	FTH_IO_OBJECT(Obj)->name
194 #define FTH_IO_FILENAME(Obj)	FTH_IO_OBJECT(Obj)->filename
195 #define FTH_IO_FAM(Obj)		FTH_IO_OBJECT(Obj)->fam
196 #define FTH_IO_DATA(Obj)	FTH_IO_OBJECT(Obj)->data
197 #define FTH_IO_LENGTH(Obj)	FTH_IO_OBJECT(Obj)->length
198 #define FTH_IO_BUFFER(Obj)	FTH_IO_OBJECT(Obj)->buffer
199 #define FTH_IO_INPUT_P(Obj)	FTH_IO_OBJECT(Obj)->input_p
200 #define FTH_IO_OUTPUT_P(Obj)	FTH_IO_OBJECT(Obj)->output_p
201 #define FTH_IO_CLOSED_P(Obj)	FTH_IO_OBJECT(Obj)->closed_p
202 
203 #define FTH_IO_READ_CHAR(Obj)						\
204 	(*FTH_IO_OBJECT(Obj)->read_char)(FTH_IO_DATA(Obj))
205 #define FTH_IO_WRITE_CHAR(Obj, val)					\
206 	(*FTH_IO_OBJECT(Obj)->write_char)(FTH_IO_DATA(Obj), val)
207 #define FTH_IO_READ_LINE(Obj)						\
208 	(*FTH_IO_OBJECT(Obj)->read_line)(FTH_IO_DATA(Obj))
209 #define FTH_IO_WRITE_LINE(Obj, val)					\
210 	(*FTH_IO_OBJECT(Obj)->write_line)(FTH_IO_DATA(Obj), val)
211 #define FTH_IO_EOF_P(Obj)						\
212 	(*FTH_IO_OBJECT(Obj)->eof_p)(FTH_IO_DATA(Obj))
213 #define FTH_IO_TELL(Obj)						\
214 	(*FTH_IO_OBJECT(Obj)->tell)(FTH_IO_DATA(Obj))
215 #define FTH_IO_SEEK(Obj, pos, w)					\
216 	(*FTH_IO_OBJECT(Obj)->seek)(FTH_IO_DATA(Obj), pos, w)
217 #define FTH_IO_FLUSH(Obj)						\
218 	(*FTH_IO_OBJECT(Obj)->flush)(FTH_IO_DATA(Obj))
219 #define FTH_IO_REWIND(Obj)						\
220 	(*FTH_IO_OBJECT(Obj)->rewind)(FTH_IO_DATA(Obj))
221 #define FTH_IO_CLOSE(Obj)						\
222 	(*FTH_IO_OBJECT(Obj)->close)(FTH_IO_DATA(Obj))
223 
224 #define keyword_args_string "\
225 The following keyword arguments exist:\n\
226 :filename    file name (string)                     => file IO\n\
227    :fam          default r/o\n\
228 :command     cmd       (string or array-of-strings) => pipe IO\n\
229    :fam          default r/o\n\
230 :string      string    (string)                     => string IO\n\
231    :fam          default r/o\n\
232 :socket      host      (string)                     => socket IO\n\
233    :domain       default AF_INET\n\
234    :port         default 1024\n\
235 :soft-port   port name (string)                     => soft-port IO\n\
236    :fam          default r/o\n\
237    :port-name    default \"soft-port-name\"\n\
238    :read-char    proc ( -- c )\n\
239    :write-char   proc ( c -- )\n\
240    :read-line    proc ( -- line )\n\
241    :write-line   proc ( line -- )\n\
242    :flush        proc ( -- )\n\
243    :close        proc ( -- )\n\
244 See also io-open-file, io-open-input-file, io-open-output-file, \
245 with-input-port, with-output-port, with-input-from-port, \
246 with-output-to-port, with-error-to-port."
247 
248 __BEGIN_DECLS
249 
250 void		init_gc(void);
251 void		init_array_type(void);
252 void		init_hash_type(void);
253 void		init_io_type(void);
254 void		init_hook_type(void);
255 void		init_string_type(void);
256 void		init_regexp_type(void);
257 void		init_number_types(void);
258 void		init_array(void);
259 void		init_hash (void);
260 void		init_io   (void);
261 void		init_port (void);
262 void		init_file (void);
263 void		init_number(void);
264 void		init_object(void);
265 void		init_proc (void);
266 void		init_hook (void);
267 void		init_string(void);
268 void		init_regexp(void);
269 void		init_symbol(void);
270 void		init_utils(void);
271 
272 /* array.c */
273 /* Next two have no bound checks! */
274 FTH		fth_array_fast_set(FTH, ficlInteger, FTH);
275 FTH		fth_array_fast_ref(FTH, ficlInteger);
276 
277 /* io.c */
278 FTH		make_io_base(int);
279 
280 /* misc.c */
281 void		forth_init(void);
282 void		forth_init_before_load(void);
283 extern int	fth_signal_caught_p;
284 #if !defined(_WIN32)
285 extern sigjmp_buf fth_sig_toplevel;
286 void		signal_check(int);
287 #endif
288 void		fth_reset_loop_and_depth(void);
289 
290 /* numbers.c */
291 int		ficl_parse_number(ficlVm *, ficlString);
292 #if HAVE_COMPLEX
293 int		ficl_parse_complex(ficlVm *, ficlString);
294 #endif
295 int		ficl_parse_bignum(ficlVm *, ficlString);
296 int		ficl_parse_ratio(ficlVm *, ficlString);
297 
298 /* object.c */
299 FTH		make_object_type(const char *, fobj_t);
300 FTH		make_object_type_from(const char *, fobj_t, FTH);
301 
302 void 		gc_free_all(void);
303 void 		gc_push(ficlWord *);
304 void 		gc_pop(void);
305 void 		gc_loop_reset(void);
306 void 		fth_set_backtrace(FTH);
307 void 		fth_show_backtrace(int);
308 
309 /* port.c */
310 FTH		io_keyword_args_ref(int);
311 
312 /* proc.c */
313 FTH		fth_word_dump(FTH);
314 FTH		fth_word_inspect(FTH);
315 FTH		fth_word_to_source(ficlWord *);
316 FTH		fth_word_to_string(FTH);
317 void		ficl_init_locals(ficlVm *, ficlDictionary *);
318 
319 /* string.c */
320 /* Next two have no bound checks! */
321 char		fth_string_c_char_fast_ref(FTH, ficlInteger);
322 char		fth_string_c_char_fast_set(FTH, ficlInteger, char);
323 /* Doesn't remove sep_str. */
324 FTH		fth_string_split_2(FTH, FTH);
325 
326 /* symbol.c */
327 FTH		ficl_ans_real_exc(int);
328 
329 /* utils.c */
330 simple_array   *make_simple_array(int);
331 simple_array   *make_simple_array_var(int,...);
332 int		simple_array_length(simple_array *);
333 int		simple_array_equal_p(simple_array *, simple_array *);
334 void           *simple_array_ref(simple_array *, int);
335 void		simple_array_set(simple_array *, int, void *);
336 void		simple_array_push(simple_array *, void *);
337 void           *simple_array_pop(simple_array *);
338 int		simple_array_index(simple_array *, void *);
339 int		simple_array_rindex(simple_array *, void *);
340 int		simple_array_member_p(simple_array *, void *);
341 void           *simple_array_delete(simple_array *, void *);
342 void           *simple_array_rdelete(simple_array *, void *);
343 simple_array   *simple_array_reverse(simple_array *);
344 simple_array   *simple_array_clear(simple_array *);
345 void		simple_array_free(simple_array *);
346 FTH		simple_array_to_array(simple_array *);
347 
348 void		push_forth_string(ficlVm *, char *);
349 
350 char           *parse_input_buffer(ficlVm *, char *);
351 char           *parse_tib_with_restart(ficlVm *, char *, int,
352 		    ficlString (*) (ficlVm *, int));
353 
354 __END_DECLS
355 
356 #endif				/* _UTILS_H_ */
357 
358 /*
359  * utils.h ends here
360  */
361