1 /*
2  *  The Regina Rexx Interpreter
3  *  Copyright (C) 1992-1994  Anders Christensen <anders@pvv.unit.no>
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Library General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Library General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Library General Public
16  *  License along with this library; if not, write to the Free
17  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 #ifndef REGINA_TYPES_H_INCLUDED
20 #define REGINA_TYPES_H_INCLUDED
21 
22 typedef struct varbox *variableptr ;
23 typedef const struct varbox *cvariableptr ;
24 
25 /*
26  * var_hashtable is a table with size entries. The entries are added according
27  * to their hash value.
28  * r is the number of read accesses.
29  * w is the number of write accesses.
30  * c is the number of collisions on access or while creating/copying the table.
31  * e is the number of true elements in the tbl, hashed to size buckets.
32  * Note that tbl contains one more hidden element used for variable
33  * maintenance if size > 0.
34  */
35 typedef struct {
36    variableptr    *tbl;
37    unsigned        reads;
38    unsigned        writes;
39    unsigned        collisions;
40    unsigned        elements;
41    unsigned        size;
42 } var_hashtable;
43 
44 typedef struct varbox {
45    var_hashtable *index;
46    variableptr next, prev, realbox ;
47    struct strengtype *name, *value ;
48    int guard ;
49    num_descr *num ;
50    int flag ;
51    unsigned hash ;
52    long hwired, valid ; /* FGC: at least valid may be too small for many
53                                 recursions with short instead of long.
54                                 27.09.98 (09/27/98). */
55    variableptr stem ;
56 } variable ;
57 
58 /* typedef int bool ; */
59 
60 typedef struct {
61    unsigned int lnum:1 ;    /* left side of comparison is a number or string constant */
62    unsigned int rnum:1 ;    /* right side of comparison is a number or string constant */
63    unsigned int lsvar:1 ;   /* left side of comparison is a simple variable */
64    unsigned int rsvar:1 ;   /* right side of comparison is a simple variable */
65    unsigned int lcvar:1 ;   /* left side of comparison is a compound variable */
66    unsigned int rcvar:1 ;   /* right side of comparison is a compound variable */
67 } compflags ;
68 
69 typedef enum {
70    awtUNKNOWN = 0,
71    awtSTREAM = 1,
72    awtSTEM = 2,
73    awtLIFO = 3,
74    awtFIFO = 4
75 } AddressWithType;
76 
77 typedef enum {
78    antUNKNOWN = 0,
79    antSTRING = 1,
80    antSIMSYMBOL = 2
81 } AddressNameType;
82 
83 typedef enum {
84    fpdRETAIN = 0,
85    fpdCLEAR = 1
86 } FilePtrDisposition;
87 
88 typedef struct {
89    unsigned int append:1;
90    unsigned int isinput:1;
91    unsigned int iserror:1;
92    unsigned int awt:3; /* overlay with AddressWithType */
93    unsigned int ant:2; /* overlay with AddressNameType */
94    unsigned int noeol:1; /* for INPUT NOEOL */
95 } outputflags; /* used by ADDRESS WITH resourceo */
96 
97 typedef enum {
98    PROTECTED_DelayedScriptExit,
99    PROTECTED_DelayedInterpreterExit,
100    PROTECTED_DelayedRexxSignal
101 } delayed_error_type_t;
102 
103 typedef enum {
104    QisUnused,
105    QisSESSION,
106    QisInternal,
107    QisExternal,
108    QisTemp
109 } queue_type_t ;
110 
111 typedef struct  {
112    time_t sec ;
113    time_t usec ;
114 } rexx_time;
115 
116 struct _tsd_t; /* If this won't work change "struct _tsd_t *" to "void *"
117                 * below. This will require more changes. Let your compiler
118                 * choose the places.
119                 */
120 
121 typedef struct pparambox *paramboxptr ;
122 typedef const struct pparambox *cparamboxptr ;
123 typedef struct pparambox {
124    paramboxptr next ;
125    int dealloc ;
126    struct strengtype *value ;
127 } parambox ;
128 
129 typedef struct tnode {
130    unsigned int type ;
131    int charnr, lineno ;
132    union {                 /* saves memory which is really needed          */
133       int called;          /* used during execution *and* don't need init  */
134       struct tnode *last;  /* used during parsing                          */
135    } o ;
136    struct strengtype *name ;
137    rexx_time *now ;
138    struct tnode *p[4] ;
139    union {
140       /*
141        * WARNING: When changing check whether to modify dumptree and the
142        *          whole instore stuff. Seek for X_CEXPRLIST.
143        */
144       streng *(*func)(struct _tsd_t *,cparamboxptr) ;
145       streng *strng ;
146       struct tnode *node ;
147       num_descr *number ;
148       compflags flags ;
149       variable *varbx ;
150       outputflags of ;
151       int parseflags ;
152       int nonansi ;
153       int trace_only ; /* For labels */
154    } u ;
155    struct tnode *next ;
156    unsigned long nodeindex ; /* for an effectiv relocation, never change! */
157 } treenode ;
158 typedef struct tnode *nodeptr ;
159 typedef const struct tnode *cnodeptr ;
160 
161 typedef struct lineboxx *lineboxptr ;
162 typedef const struct lineboxx *clineboxptr ;
163 typedef struct lineboxx {
164    lineboxptr next, prev ;
165    struct strengtype *line ;
166    int lineno ;
167 } linebox ;
168 
169 typedef struct labelboxx *labelboxptr ;
170 typedef const struct labelboxx *clabelboxptr ;
171 typedef struct labelboxx {
172    labelboxptr next ;
173    unsigned long hash ;
174    nodeptr entry ;
175 } labelbox ;
176 
177 typedef struct trap_type  /* index is type of signal */
178 {
179    unsigned int on_off:1 ;     /* true if trap is active/on */
180 /* unsigned int trapped:1 ; */ /* true if condition has been raised */
181    unsigned int def_act:1 ;    /* true if default action is to ignore */
182    unsigned int delayed:1 ;    /* true if trap is in delay mode */
183    unsigned int ignored:1 ;    /* true if ignored when in delayed mode */
184    unsigned int invoked:1 ;    /* true if invoked by SIGNAL */
185    streng *name ;          /* label to transfer control to */
186 } trap ;
187 
188 typedef struct sig_type
189 {
190    int type ;
191    streng *info ;
192    streng *descr ;
193    int invoke ;     /* is true if invoked with SIGNAL */
194    int rc, subrc, lineno ;
195 } sigtype ;
196 
197 typedef void (*signal_handler)(int);
198 
199 typedef struct __regina_option
200 {
201    char *name ;
202    int offset ;
203    char *contains ;
204 } option_type ;
205 
206 typedef struct _StackLine {
207    /* A stack line is a double linked list element of a streng. The streng
208     * never contains a line end and is never NULL.
209     * A read operations will happen at the top end, as well as a LIFO
210     * operation.
211     * A FIFO operation will happen at the bottom end.
212     */
213    struct _StackLine *higher ;
214    struct _StackLine *lower ;
215    streng *contents ;
216 } StackLine ;
217 
218 typedef struct _Buffer {
219    /* A buffer is a double linked list of stack line bundles.
220     * MAKEBUF() adds a new buffer at the newest end.
221     */
222    struct _Buffer *higher ;
223    struct _Buffer *lower ;
224 
225    /* The "content" of the buffer. See StackLine for a description.
226     * For a faster response of QUEUED(), we count the elements of lines.
227     */
228    StackLine *top ;
229    StackLine *bottom ;
230    unsigned elements ;
231 } Buffer ;
232 
233 typedef struct {
234    /* A queue is one of different implementations of queue types.
235     * See the picture and the description at the beginning of stack.c.
236     */
237    queue_type_t type;
238    union {
239       struct { /* internal or SESSION: i */
240          /* name is the uppercased name of the queue. In rare cases this
241           * may be NULL for QisSESSION after initialisation.
242           */
243          streng *name ;
244          /*
245           * Indicates if the queue is a "real" queue
246           * or a false queue as a result of a rxqueue('set', 'qname')
247           * on a queue that doesn't exist. This is crap behaviour!
248           * but that's how Object Rexx works :-(
249           */
250          int isReal ;
251          /*
252           * Content: We have a double linked list of buffers. See Buffer
253           * for a description.
254           */
255          Buffer *top ;
256          Buffer *bottom ;
257 
258          /* This is the count of buffers including the zeroth buffer */
259          unsigned buffers ;
260 
261          /* This is the overall count of elements in all buffers */
262          unsigned elements ;
263       } i ;
264       struct { /* external: e */
265          /*
266           * The port number for the current connection to an external rxstack
267           * Valid values: 1..0xFFFF, unused: 0
268           */
269          int portno;
270          /*
271           * The socket fd for the current connection to an external rxstack
272           * Valid values: not -1, unused/error: -1
273           */
274          int socket;
275          /*
276           * The server address of the current connection. Used to determine if
277           * we need to disconnect from one rxstack server and connect to
278           * another.
279           * The true data type is a 32 bit system depending type.
280           * Valid values: not 0, unused: 0
281           */
282          int address;
283          /*
284           * A boolean value which indicates if the external queue has had a timeout
285           * set on it via RXQUEUE( 'Timeout' )
286           * Valid values: 0 or 1
287           */
288          int timeoutSet;
289          streng *name;
290       } e ;
291       Buffer t ; /* temp: t */
292    } u ;
293 } Queue ;
294 
295 typedef struct { /* one for each redirection in environment */
296    streng      *name;     /* name if any, but not expanded      */
297    outputflags  flags;
298    streng      *base;     /* "number" if name is a stem         */
299    streng      *currname; /* expanded name + ".number" if name  */
300                           /* is a stem                          */
301    int          currnamelen;  /* len(currname) without ".number"*/
302    int          currnum;  /* current number for a stem position */
303                           /* or -1 if unknown                   */
304    int          maxnum;   /* maximum number for a stem position */
305                           /* or -1 if unknown                   */
306    void        *file;     /* fileboxptr of the file with the    */
307                           /* above name or NULL.                */
308    Queue       *queue;    /* queue with the above name or NULL. */
309    Queue       *tmp_queue;/* temporary queue for the redirection*/
310                           /* or NULL without this helper.       */
311    unsigned int SameAsOutput:2;   /* locally used in shell.c    */
312    unsigned int FileRedirected:1; /* locally used in shell.c    */
313    char        *tempname; /* locally used filename in shell.c   */
314    int          type;     /* locally used source in shell.c     */
315    int          hdls[3];  /* locally used connection in shell.c */
316 } environpart;
317 
318 typedef struct {
319    struct strengtype *name; /* stemname or streamname if any */
320    int subtype;             /* SUBENVIR_... */
321    int subcomed;            /* has this environment been redirected to an API program via RexxRegistreSubcom???() */
322    environpart input;
323    environpart output;
324    environpart error;
325 } environment;
326 
327 typedef struct proclevelbox *proclevel ;
328 typedef const struct proclevelbox *cproclevel ;
329 typedef struct proclevelbox {
330    int numfuzz, currnumsize, numform ;
331    int mathtype ;
332    rexx_time rx_time ;
333    proclevel prev, next ;
334    var_hashtable *vars ;
335    paramboxptr args ;
336    struct strengtype *environment, *prev_env ;
337    char tracestat, traceint, varflag ; /* MDW 30012002 */
338    sigtype *sig ;
339    trap *traps ;
340    jmp_buf *signal_continue; /* see jump_rexx_signal() */
341    unsigned long options;
342    int pool;
343 } proclevbox ;
344 
345 typedef struct _ttree { /* bucket list of treenodes which allows ultra fast
346                          * loading of instore macros.
347                          */
348    struct _ttree *next;
349    unsigned long  max; /* maximum number of elements in the bucket */
350    unsigned long  num; /* current number of elements in the bucket */
351    unsigned long  sum; /* sum of indices until element 0 */
352    treenode *     elems;
353 } ttree; /* treenode type */
354 
355 typedef struct { /* offsrcline: offset based source lines */
356    unsigned long length;
357    unsigned long offset;
358    /* That's all. You need the source string of the incore macro to create
359     * a real sourceline using this information.
360     */
361 } offsrcline;
362 
363 typedef struct _otree { /* bucket list of offscrlines which allows ultra fast
364                          * loading of instore macros.
365                          */
366    struct _otree *next;
367    unsigned long  max; /* maximum number of elements in the bucket */
368    unsigned long  num; /* current number of elements in the bucket */
369    unsigned long  sum; /* sum of indices until element 0 */
370    offsrcline *   elems;
371 } otree; /* offsrcline type */
372 
373 typedef struct { /* internal_parser_type is a structure containing data from a
374                   * parsing operation.
375                   */
376    lineboxptr     first_source_line; /* Either this two values  */
377    lineboxptr     last_source_line ; /* exist or srclines below */
378    int            tline;             /* line number where error occured */
379    int            tstart;            /* column number where error occured */
380    int            if_linenr;         /* line number of last IF keyword */
381    int            when_linenr;       /* line number of last WHEN keyword */
382    int            select_linenr;     /* line number of last SELECT keyword */
383    labelboxptr    first_label;
384    labelboxptr    last_label;
385    unsigned long  numlabels;
386    labelboxptr    sort_labels ;
387    int            result;
388    nodeptr        root;
389    ttree *        nodes;
390    otree *        srclines;          /* Either this two values exist */
391    const char *   incore_source;     /* or the two values above      */
392    streng *       kill; /* Probably the true source of incore_source in case
393                          * of an "INTERPRET" instruction or other not user
394                          * generated but interpreted strings; else NULL.
395                          */
396    struct _tsd_t *TSD; /* needed during the parsing step */
397 } internal_parser_type;
398 
399 typedef struct { /* extstring: external (instore) string */
400    unsigned long length;
401    /* and directly following the string's content */
402 } extstring;
403 
404 typedef struct { /* external_parser_type: the instore macro in user space */
405    /* Never change from here until source including since it allows the
406     * reconstruction of the source if the machine type or Regina version
407     * doesn't match.
408     */
409    char     Magic[32]; /* "Regina's Internal Format\r\n" filled with 0 */
410 #define MAGIC "Regina's Internal Format\r\n"
411    char     ReginaVersion[64]; /* PARSE_VERSION_STRING */
412 
413    /* The following structure allows the detection of different
414     * architectures. We don't want to try to decode something from
415     * a 64 bit big endian encoded parsing tree on an i586 for
416     * example.
417     */
418    union {
419       char ignore[4 * 256/8]; /* Allow 256 bit machines */
420       struct {
421          unsigned long one; /* value one */
422          unsigned long two; /* value two */
423          void *   ptr3; /* value (void*)3, size may be different to unsigned */
424          void *   ptr4; /* value (void*)4 */
425       } s;
426    } arch_detector;
427 
428    unsigned long OverallSize; /* in byte of this structure and all dependencies */
429 
430    unsigned long version; /* INSTORE_VERSION */
431 
432    /* We describe the sourcelines first */
433    unsigned long NumberOfSourceLines;
434    unsigned long source;
435    /* Offset to table of source lines. Imagine a value of 1000 and
436     * 5 source lines (previous value). This structure has an address
437     * of 500 in the memory (what you get from malloc or something else).
438     * Then: The table has 5 entries at position 1500 in memory.
439     * Each table entry is an offsrcline structure. The source string is the
440     * instore[0] string of RexxStart or another source string.
441     */
442 
443    unsigned long NumberOfTreeElements;
444    unsigned long TreeStart; /* Within 0 .. (NumberOfTreeElements-1) */
445    unsigned long tree;
446    /* Offset to table of nodes. Imagine a value of 2000 and
447     * 6 elements (NumberIfTreeElements). This structure has an address
448     * of 500 in the memory (what you get from malloc or something else).
449     * Then: The table has 6 treenodes at position 2500 in memory.
450     * Each table entry (treenode) must be relocated. Every nodeptr within a
451     * element is just an index within this table. If node->p[2] of one picked
452     * table entry is ((nodeptr) 4) then the address is calculated as follows:
453     * 500 + tree + (4*sizeof(treenode))
454     * This value should be assigned to node->p[2] to use the value in its
455     * normal manner.
456     * A NULL value is represented by (nodeptr) (unsigned) -1.
457     * Every string within a treenode is relocated by adding 500. Imagine a
458     * value of 3000 for node->name. Then an extstring structure is located
459     * at 3500 in memory which represents the string's content.
460     */
461 } external_parser_type;
462 
463 typedef struct systeminfobox *sysinfo ;
464 typedef const struct systeminfobox *csysinfo ;
465 typedef struct systeminfobox {
466    struct strengtype *input_file ; /* must be 0-terminated without counting of the '\0' */
467    streng *environment ;
468    FILE *input_fp;
469    int tracing ;
470    int interactive ;
471    jmp_buf *script_exit;     /* see jump_script_exit() */
472    streng *result ;
473    proclevbox *currlevel0 ;
474    struct systeminfobox *previous ;
475    nodeptr *callstack ;
476    int cstackcnt, cstackmax ;
477    int hooks ;
478    int invoked ;
479    int trace_override;
480    internal_parser_type tree;
481    int ctrlcounter;
482 } sysinfobox ;
483 
484 #ifndef DONT_TYPEDEF_PFN
485 typedef unsigned long (*PFN)() ;
486 #endif
487 
488 
489 struct library {
490    streng *name;
491    void *handle;
492    unsigned long used;
493 
494    struct library *next, *prev;
495 };
496 
497 
498 struct entry_point {
499    streng *name;
500    PFN addr;
501    union {
502       void *gci_info;             /* for function handlers */
503       unsigned char user_area[8]; /* for suncommand and exit handlers */
504    } special;
505 
506    unsigned long hash;
507    struct library *lib;
508    struct entry_point *next, *prev;
509 };
510 
511 /*
512  * Every major OS has some functionality that isn't shared with others.
513  * Most functions relate to the command execution/redirection stuff.
514  * The global function collection *OS_Dep will point to this structure.
515  * Some systems, Win9x and OS/2-EMX, even use the DOS entry table because
516  * they can't take advantage of the performance functions the system
517  * usually provides.
518  * init() may map some "stupid" function on advanced function, as for
519  * instance Win9x doesn't support redirection correctly.
520  */
521 struct _tsd_t;
522 struct regina_utsname;
523 typedef struct _OS_Dep_funcs {
524    void   (*init)                       (void);
525    int    (*setenv)                     (const char *name, const char *value);
526    int    (*fork_exec)                  (struct _tsd_t *TSD, environment *env, const char *cmdline, int *rc);
527    int    (*wait)                       (int process);
528    int    (*open_subprocess_connection) (const struct _tsd_t *TSD, environpart *ep);
529    void   (*unblock_handle)             (int *handle, void *async_info);
530    void   (*restart_file)               (int hdl);
531    int    (*close)                      (int handle, void *async_info);
532    void   (*close_special)              (int handle);
533    int    (*read)                       (int hdl, void *buf, unsigned size, void *async_info) ;
534    int    (*write)                      (int hdl, const void *buf, unsigned size, void *async_info);
535    void*  (*create_async_info)          (const struct _tsd_t *TSD);
536    void   (*delete_async_info)          (void *async_info);
537    void   (*reset_async_info)           (void *async_info);
538    void   (*add_async_waiter)           (void *async_info, int handle, int add_as_read_handle);
539    void   (*wait_async_info)            (void *async_info);
540    int    (*uname)                      (struct regina_utsname *name);
541 } OS_Dep_funcs;
542 
543 #include "regina64.h"
544 
545 
546 #endif /* REGINA_TYPES_H_INCLUDED */
547