root/trunk/AISC/aisc.h

Revision 7413, 9.6 KB (checked in by westram, 14 months ago)

merged from dev [7355] [7369] [7370]

  • Refactored AISC (interpreter)
    • separated 'struct global' into several classes (mostly 'Interpreter').
    • precompile all commands and use a dispatcher
  • changes to behavior
    • new command WARNING
    • detects deadlocks
    • error if referencing data w/o loading it
    • error when files are not closed
    • tweaked/added several errors reported
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : aisc.h                                             //
4//   Purpose   :                                                    //
5//                                                                  //
6//   Institute of Microbiology (Technical University Munich)        //
7//   http://www.arb-home.de/                                        //
8//                                                                  //
9// ================================================================ //
10
11#ifndef AISC_H
12#define AISC_H
13
14#define SIMPLE_ARB_ASSERT
15#ifndef ARB_ASSERT_H
16#include <arb_assert.h>
17#endif
18#ifndef DUPSTR_H
19#include <dupstr.h>
20#endif
21#ifndef _UNISTD_H
22#include <unistd.h>
23#endif
24#ifndef ATTRIBUTES_H
25#include <attributes.h>
26#endif
27
28
29#define aisc_assert(cond) arb_assert(cond)
30
31// ------------------------------------------------------------
32
33#define OPENFILES 16
34#define HASHSIZE  1024
35#define STACKSIZE 20
36
37enum aisc_commands {
38    no_command,
39    IF,
40    ENDIF,
41    ELSE,
42    FOR,
43    NEXT,
44    ENDFOR,
45    ELSEIF,
46    FUNCTION,
47    LABEL,
48    MAX_COM
49};
50
51struct hash_entry {
52    char       *key;
53    char       *val;
54    hash_entry *next;
55};
56struct hash {
57    int          size;
58    hash_entry **entries;
59};
60
61// ------------------------------------------------------------
62
63inline char *copy_string_part(const char *first, const char *last) {
64    int   size = last-first+1;
65    char *mem  = (char*)malloc(size+1);
66
67    memcpy(mem, first, size);
68    mem[size] = 0;
69
70    return mem;
71}
72
73// ------------------------------------------------------------
74// structures holding data read from *.aisc files
75
76class TokenList;
77class TokenListBlock;
78
79// --------------
80//      Token
81
82class Token {
83    Token     *next;                                // (owned)
84    TokenList *parent;
85
86    bool  isBlock;
87    char *key;
88    union {
89        TokenListBlock *sub;                        // (owned), NULL = empty block
90        char           *val;                        // NULL means ""
91    } content;
92
93public:
94    Token(const char *key_, const char *val_)
95        : next(NULL)
96        , parent(NULL)
97        , isBlock(false)
98        , key(strdup(key_))
99    {
100        content.val = val_ ? strdup(val_) : NULL;
101    }
102    Token(const char *key_, TokenListBlock *block_); // takes ownage of block_
103    ~Token();
104
105    void append(Token *tok) { next = tok; }
106    void set_parent(TokenList *list) { aisc_assert(!parent); parent = list; }
107
108    const char *get_key() const { return key; }
109
110    bool is_block() const { return isBlock; }
111    const TokenListBlock *get_content() const { aisc_assert(isBlock); return content.sub; }
112
113    bool has_value() const { return !is_block() && content.val; }
114    const char *get_value() const { aisc_assert(has_value()); return content.val; }
115
116    const Token *next_token() const { return next; }
117    const TokenList *parent_list() const { return parent; }
118    const Token *parent_block_token() const;
119};
120
121// ------------------
122//      TokenList
123
124class TokenList {
125    Token          *head;                           // list of tokens (owned)
126    Token          *tail;
127    TokenList      *next;                           // owned
128    TokenListBlock *parent;
129
130public:
131    TokenList() {
132        head   = NULL;
133        tail   = NULL;
134        next   = NULL;
135        parent = NULL;
136    }
137    ~TokenList() {
138        delete head;
139        delete next;
140    }
141
142    void append(Token *tok) {
143        if (!head) head = tok;
144        else tail->append(tok);
145
146        tail = tok;
147        tok->set_parent(this);
148    }
149    void append(TokenList *cmd) { next = cmd; }
150    void set_parent(TokenListBlock *block) { parent = block; }
151
152    bool empty() const { return !head; }
153    const Token *first_token() const { return head; }
154    const TokenList *next_list() const { return next; }
155    const TokenListBlock *parent_block() const { return parent; }
156};
157
158// -----------------------
159//      TokenListBlock
160
161class TokenListBlock {
162    TokenList   *head;                              // list of TokenLists (owned)
163    TokenList   *tail;
164    const Token *parent;
165
166public:
167    TokenListBlock() {
168        head   = NULL;
169        tail   = NULL;
170        parent = NULL;
171    }
172    ~TokenListBlock() { delete head; }
173
174    bool empty() const { return !head; }
175    void append(TokenList *cmd) {
176        if (!head) head = cmd;
177        else tail->append(cmd);
178
179        tail = cmd;
180        cmd->set_parent(this);
181    }
182    void set_block_token(Token *tok) { aisc_assert(!parent); parent = tok; }
183
184    const TokenList *first_list() const { return head; }
185    const Token *first_token() const { return head->first_token(); }
186    const Token *block_token() const { return parent; }
187};
188
189// ------------------------------------------------------------
190
191inline Token::Token(const char *key_, TokenListBlock *block_)
192    : next(NULL)
193    , parent(NULL)
194    , isBlock(true)
195    , key(strdup(key_))
196{
197    aisc_assert(block_);
198    content.sub = block_;
199    if (content.sub) {
200        content.sub->set_block_token(this);
201    }
202}
203inline Token::~Token() {
204    free(key);
205    if (isBlock) delete content.sub;
206    else free(content.val);
207    delete next;
208}
209inline const Token *Token::parent_block_token() const {
210    return parent_list()->parent_block()->block_token();
211}
212
213// ------------------------------------------------------------
214
215struct for_data {
216    char        *forstr;
217    const Token *forcursor;
218    long         forval;
219    long         forend;
220    for_data    *next;
221};
222
223
224
225typedef struct command_lines {
226    command_lines *next;
227    char          *str;
228    int            linenr;
229    char          *path;
230    aisc_commands  command;
231    for_data      *fd;
232    command_lines *IF;
233    command_lines *ELSE;
234    command_lines *ENDIF;
235    command_lines *FOR;
236    command_lines *NEXT;
237    command_lines *ENDFOR;
238} CL;
239
240struct stack {
241    const Token *cursor;
242    CL          *pc;
243    hash        *hs;
244    stack       *next;
245};
246
247class Output {
248    FILE *fp;
249    char *id;   // internal name used in AISC
250    char *name; // file-system name
251
252    bool wasOpened() const { return fp && !name; }
253
254    void close_file() {
255        if (wasOpened()) fclose(fp);
256        fp = NULL;
257    }
258   
259    void setup() { fp = NULL; id = NULL; name = NULL; }
260    void cleanup() { close_file(); free(id); free(name); }
261    void reuse() { cleanup(); setup(); }
262
263public:
264
265    Output() { setup(); }
266    ~Output() { cleanup(); }
267
268    bool inUse() const { return fp; }
269
270    void assign(FILE *fp_, const char *id_, const char *name_) {
271        aisc_assert(!inUse());
272        fp   = fp_;
273        id   = strdup(id_);
274        name = strdup(name_);
275    }
276    void assign_stdout(const char *id_) {
277        aisc_assert(!inUse());
278        fp   = stdout;
279        id   = strdup(id_);
280        name = NULL;
281    }
282
283    void close_and_unlink() {
284        close_file();
285        if (name) {
286            fprintf(stderr, "Unlinking %s\n", name);
287            unlink(name);
288        }
289        reuse();
290    }
291    void close() { reuse(); }
292
293    bool hasID(const char *Name) const { return id && strcmp(id, Name) == 0; }
294
295    void putchar(char c) {
296        putc(c, fp);
297    }
298};
299
300struct global {
301    int             error_flag;
302    char            outtab[256];
303    const Token    *cursor;
304    TokenListBlock *root;
305    CL             *prg;
306    CL             *pc;
307    CL             *nextpc;
308    stack          *st;
309    int             sp;
310    int             line_cnt;
311    const char     *last_line_start;
312    char           *line_path;
313    int             lastchar;
314    char           *linebuf;
315    int             bufsize;
316    int             s_pos;
317
318    Output  output[OPENFILES];
319    Output *current_output; // pointer to one element of 'output'
320
321
322    int   tabstop;
323    int   tabs[10];
324    hash *fns;
325    int   tabpos;
326
327};
328
329extern global *gl;
330extern char    string_buf[256];
331
332#define EOSTR    0
333#define BEG_STR1 '('
334#define BEG_STR2 '~'
335#define END_STR1 '~'
336#define END_STR2 ')'
337
338inline bool is_SPACE(char c) { return c == ' ' || c == '\t'; }
339inline bool is_SEP(char c)   { return c == ',' || c == ';'; }
340inline bool is_LF(char c)    { return c == '\n'; }
341inline bool is_EOS(char c)   { return c == EOSTR; }
342
343inline bool is_SPACE_LF(char c)         { return is_SPACE(c) || is_LF(c); }
344inline bool is_SPACE_LF_EOS(char c)     { return is_SPACE_LF(c) || is_EOS(c); }
345inline bool is_SPACE_SEP_LF_EOS(char c) { return is_SPACE_LF_EOS(c) || is_SEP(c); }
346inline bool is_LF_EOS(char c)           { return is_LF(c) || is_EOS(c); }
347inline bool is_SEP_LF_EOS(char c)       { return is_SEP(c) || is_LF_EOS(c); }
348
349inline void SKIP_SPACE_LF         (const char *& var) { while (is_SPACE_LF(*var)) ++var; }
350inline void SKIP_SPACE_LF         (char *& var)       { while (is_SPACE_LF(*var)) ++var; }
351inline void SKIP_SPACE_LF_BACKWARD(const char *& var) { while (is_SPACE_LF(*var)) --var; }
352inline void SKIP_SPACE_LF_BACKWARD(char *& var)       { while (is_SPACE_LF(*var)) --var; }
353
354enum LookupScope {
355    LOOKUP_LIST,
356    LOOKUP_BLOCK,
357    LOOKUP_BLOCK_REST,
358    LOOKUP_LIST_OR_PARENT_LIST,
359};
360
361#include "aisc_proto.h"
362
363// #define SHOW_CALLER // show where error was raised
364
365#ifdef SHOW_CALLER
366
367#define print_error(err)          print_error_internal(err, __FILE__, __LINE__)
368#define print_warning(err)        print_warning_internal(err, __FILE__, __LINE__)
369#define printf_error(format, arg) print_error_internal(formatted(format, arg), __FILE__, __LINE__)
370
371#else
372
373#define print_error(err)          print_error_internal(err, NULL, 0)
374#define print_warning(err)        print_warning_internal(err, NULL, 0)
375#define printf_error(format, arg) print_error_internal(formatted(format, arg), NULL, 0)
376
377#endif
378
379#else
380#error aisc.h included twice
381#endif // AISC_H
Note: See TracBrowser for help on using the browser.