File: aisc.h

package info (click to toggle)
arb 6.0.6-8
  • links: PTS, VCS
  • area: non-free
  • in suites: sid, trixie
  • size: 66,204 kB
  • sloc: ansic: 394,911; cpp: 250,290; makefile: 19,644; sh: 15,879; perl: 10,473; fortran: 6,019; ruby: 683; xml: 503; python: 53; awk: 32
file content (380 lines) | stat: -rw-r--r-- 9,812 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
// ================================================================ //
//                                                                  //
//   File      : aisc.h                                             //
//   Purpose   :                                                    //
//                                                                  //
//   Institute of Microbiology (Technical University Munich)        //
//   http://www.arb-home.de/                                        //
//                                                                  //
// ================================================================ //

#ifndef AISC_H
#define AISC_H

#ifndef ARB_SIMPLE_ASSERT_H
#include <arb_simple_assert.h>
#endif
#ifndef DUPSTR_H
#include <dupstr.h>
#endif
#ifndef _UNISTD_H
#include <unistd.h>
#endif
#ifndef ATTRIBUTES_H
#include <attributes.h>
#endif


#define aisc_assert(cond) arb_assert(cond)

// ------------------------------------------------------------

#define OPENFILES 16
#define HASHSIZE  1024
#define STACKSIZE 20

enum aisc_commands {
    no_command,
    IF,
    ENDIF,
    ELSE,
    FOR,
    NEXT,
    ENDFOR,
    ELSEIF,
    FUNCTION,
    LABEL,
    MAX_COM
};

struct hash_entry {
    char       *key;
    char       *val;
    hash_entry *next;
};
struct hash {
    int          size;
    hash_entry **entries;
};

// ------------------------------------------------------------

inline char *copy_string_part(const char *first, const char *last) {
    int   size = last-first+1;
    char *mem  = (char*)malloc(size+1);

    memcpy(mem, first, size);
    mem[size] = 0;

    return mem;
}

// ------------------------------------------------------------
// structures holding data read from *.aisc files

class TokenList;
class TokenListBlock;

// --------------
//      Token

class Token {
    Token     *next;                                // (owned)
    TokenList *parent;

    bool  isBlock;
    char *key;
    union {
        TokenListBlock *sub;                        // (owned), NULL = empty block
        char           *val;                        // NULL means ""
    } content;

public:
    Token(const char *key_, const char *val_)
        : next(NULL)
        , parent(NULL)
        , isBlock(false)
        , key(strdup(key_))
    {
        content.val = val_ ? strdup(val_) : NULL;
    }
    Token(const char *key_, TokenListBlock *block_); // takes ownage of block_
    ~Token();

    void append(Token *tok) { next = tok; }
    void set_parent(TokenList *list) { aisc_assert(!parent); parent = list; }

    const char *get_key() const { return key; }

    bool is_block() const { return isBlock; }
    const TokenListBlock *get_content() const { aisc_assert(isBlock); return content.sub; }

    bool has_value() const { return !is_block() && content.val; }
    const char *get_value() const { aisc_assert(has_value()); return content.val; }

    const Token *next_token() const { return next; }
    const TokenList *parent_list() const { return parent; }
    const Token *parent_block_token() const;
};

// ------------------
//      TokenList

class TokenList {
    Token          *head;                           // list of tokens (owned)
    Token          *tail;
    TokenList      *next;                           // owned
    TokenListBlock *parent;

public:
    TokenList() {
        head   = NULL;
        tail   = NULL;
        next   = NULL;
        parent = NULL;
    }
    ~TokenList() {
        delete head;
        delete next;
    }

    void append(Token *tok) {
        if (!head) head = tok;
        else tail->append(tok);

        tail = tok;
        tok->set_parent(this);
    }
    void append(TokenList *cmd) { next = cmd; }
    void set_parent(TokenListBlock *block) { parent = block; }

    bool empty() const { return !head; }
    const Token *first_token() const { return head; }
    const TokenList *next_list() const { return next; }
    const TokenListBlock *parent_block() const { return parent; }
};

// -----------------------
//      TokenListBlock

class TokenListBlock {
    TokenList   *head;                              // list of TokenLists (owned)
    TokenList   *tail;
    const Token *parent;

public:
    TokenListBlock() {
        head   = NULL;
        tail   = NULL;
        parent = NULL;
    }
    ~TokenListBlock() { delete head; }

    bool empty() const { return !head; }
    void append(TokenList *cmd) {
        if (!head) head = cmd;
        else tail->append(cmd);

        tail = cmd;
        cmd->set_parent(this);
    }
    void set_block_token(Token *tok) { aisc_assert(!parent); parent = tok; }

    const TokenList *first_list() const { return head; }
    const Token *first_token() const { return head->first_token(); }
    const Token *block_token() const { return parent; }
};

// ------------------------------------------------------------

inline Token::Token(const char *key_, TokenListBlock *block_)
    : next(NULL)
    , parent(NULL)
    , isBlock(true)
    , key(strdup(key_))
{
    aisc_assert(block_);
    content.sub = block_;
    if (content.sub) {
        content.sub->set_block_token(this);
    }
}
inline Token::~Token() {
    free(key);
    if (isBlock) delete content.sub;
    else free(content.val);
    delete next;
}
inline const Token *Token::parent_block_token() const {
    return parent_list()->parent_block()->block_token();
}

// ------------------------------------------------------------

struct for_data {
    char        *forstr;
    const Token *forcursor;
    long         forval;
    long         forend;
    for_data    *next;
};



typedef struct command_lines {
    command_lines *next;
    char          *str;
    int            linenr;
    char          *path;
    aisc_commands  command;
    for_data      *fd;
    command_lines *IF;
    command_lines *ELSE;
    command_lines *ENDIF;
    command_lines *FOR;
    command_lines *NEXT;
    command_lines *ENDFOR;
} CL;

struct stack {
    const Token *cursor;
    CL          *pc;
    hash        *hs;
    stack       *next;
};

class Output {
    FILE *fp;
    char *id;   // internal name used in AISC
    char *name; // file-system name

    bool wasOpened() const { return fp && !name; }

    void close_file() {
        if (wasOpened()) fclose(fp);
        fp = NULL;
    }
    
    void setup() { fp = NULL; id = NULL; name = NULL; }
    void cleanup() { close_file(); free(id); free(name); }
    void reuse() { cleanup(); setup(); }

public:

    Output() { setup(); }
    ~Output() { cleanup(); }

    bool inUse() const { return fp; }

    void assign(FILE *fp_, const char *id_, const char *name_) {
        aisc_assert(!inUse());
        fp   = fp_;
        id   = strdup(id_);
        name = strdup(name_);
    }
    void assign_stdout(const char *id_) {
        aisc_assert(!inUse());
        fp   = stdout;
        id   = strdup(id_);
        name = NULL;
    }

    void close_and_unlink() {
        close_file();
        if (name) {
            fprintf(stderr, "Unlinking %s\n", name);
            unlink(name);
        }
        reuse();
    }
    void close() { reuse(); }

    bool hasID(const char *Name) const { return id && strcmp(id, Name) == 0; }

    void putchar(char c) {
        putc(c, fp);
    }
};

struct global {
    int             error_flag;
    char            outtab[256];
    const Token    *cursor;
    TokenListBlock *root;
    CL             *prg;
    CL             *pc;
    CL             *nextpc;
    stack          *st;
    int             sp;
    int             line_cnt;
    const char     *last_line_start;
    char           *line_path;
    int             lastchar;
    char           *linebuf;
    int             bufsize;
    int             s_pos;

    Output  output[OPENFILES];
    Output *current_output; // pointer to one element of 'output'


    int   tabstop;
    int   tabs[10];
    hash *fns;
    int   tabpos;

};

extern global *gl;
extern char    string_buf[256];

#define EOSTR    0
#define BEG_STR1 '('
#define BEG_STR2 '~'
#define END_STR1 '~'
#define END_STR2 ')'

inline bool is_SPACE(char c) { return c == ' ' || c == '\t'; }
inline bool is_SEP(char c)   { return c == ',' || c == ';'; }
inline bool is_LF(char c)    { return c == '\n'; }
inline bool is_EOS(char c)   { return c == EOSTR; }

inline bool is_SPACE_LF(char c)         { return is_SPACE(c) || is_LF(c); }
inline bool is_SPACE_LF_EOS(char c)     { return is_SPACE_LF(c) || is_EOS(c); }
inline bool is_SPACE_SEP_LF_EOS(char c) { return is_SPACE_LF_EOS(c) || is_SEP(c); }
inline bool is_LF_EOS(char c)           { return is_LF(c) || is_EOS(c); }
inline bool is_SEP_LF_EOS(char c)       { return is_SEP(c) || is_LF_EOS(c); }

inline void SKIP_SPACE_LF         (const char *& var) { while (is_SPACE_LF(*var)) ++var; }
inline void SKIP_SPACE_LF         (char *& var)       { while (is_SPACE_LF(*var)) ++var; }
inline void SKIP_SPACE_LF_BACKWARD(const char *& var) { while (is_SPACE_LF(*var)) --var; }
inline void SKIP_SPACE_LF_BACKWARD(char *& var)       { while (is_SPACE_LF(*var)) --var; }

enum LookupScope {
    LOOKUP_LIST,
    LOOKUP_BLOCK,
    LOOKUP_BLOCK_REST,
    LOOKUP_LIST_OR_PARENT_LIST,
};

#include "aisc_proto.h"

// #define SHOW_CALLER // show where error was raised

#ifdef SHOW_CALLER

#define print_error(err)          print_error_internal(err, __FILE__, __LINE__)
#define print_warning(err)        print_warning_internal(err, __FILE__, __LINE__)
#define printf_error(format, arg) print_error_internal(formatted(format, arg), __FILE__, __LINE__)

#else

#define print_error(err)          print_error_internal(err, NULL, 0)
#define print_warning(err)        print_warning_internal(err, NULL, 0)
#define printf_error(format, arg) print_error_internal(formatted(format, arg), NULL, 0)

#endif

#else
#error aisc.h included twice
#endif // AISC_H