source: tags/ms_r16q2/AISC/aisc.h

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