source: tags/svn.1.5.4/AISC/aisc.c

Last change on this file was 8309, checked in by westram, 12 years ago
  • moved much code into static scope

(partly reverted by [8310])

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.8 KB
Line 
1// ================================================================
2/*                                                                  */
3//   File      : aisc.c
4//   Purpose   : ARB integrated source compiler
5/*                                                                  */
6//   Institute of Microbiology (Technical University Munich)
7//   http://www.arb-home.de
8/*                                                                  */
9// ================================================================
10
11#include "aisc_interpreter.h"
12#include <cctype>
13#include <list>
14#include <string>
15
16using namespace std;
17
18// AISC_MKPT_PROMOTE:#ifndef AISC_DEF_H
19// AISC_MKPT_PROMOTE:#include "aisc_def.h"
20// AISC_MKPT_PROMOTE:#endif
21
22
23static char string_buf[256];
24
25char *read_aisc_file(const char *path, const Location *loc) {
26    char *buffer = 0;
27    FILE *input  = fopen(path, "rt");
28
29    if (!input) {
30        printf_error(loc, "file '%s' not found", path);
31    }
32    else {
33        if (fseek(input, 0, 2)==-1) {
34            printf_error(loc, "file '%s' not seekable", path);
35        }
36        else {
37            int data_size = (int)ftell(input);
38
39            if (data_size == 0) {
40                Location fileLoc(0, path);
41                print_error(&fileLoc, "file is empty");
42            }
43            else {
44                data_size++;
45                rewind(input);
46                buffer =  (char *)malloc(data_size+1);
47                data_size = fread(buffer, 1, data_size, input);
48                buffer[data_size] = 0;
49            }
50        }
51        fclose(input);
52    }
53    return buffer;
54}
55
56inline int max(int i, int j) { return i<j ? j : i; }
57
58void LineQueue::alignInto(LineQueue& dest) {
59    int offset = 0;
60    int len[count];
61
62    for (int i = 0; i<count; ++i) len[i] = strlen(queue[i]);
63
64    while (1) {
65        int max_mark_pos = -1;
66        int mark_pos[count];
67        for (int i = 0; i<count; ++i) {
68            char *line   = queue[i];
69            char *mark   = len[i]>offset ? strchr(line+offset, ALIGN_MARKER) : NULL;
70            mark_pos[i]  = mark ? mark-line : -1;
71            max_mark_pos = max(max_mark_pos, mark_pos[i]);
72        }
73        if (max_mark_pos == -1) break;
74
75        for (int i = 0; i<count; ++i) {
76            if (mark_pos[i] >= 0) {
77                int insert = max_mark_pos-mark_pos[i];
78                aisc_assert(insert >= 0);
79                if (insert >= 0) {
80                    int   new_len  = len[i]+insert;
81                    char *new_line = (char*)malloc(new_len+1);
82
83                    memcpy(new_line, queue[i], mark_pos[i]);
84                    memset(new_line+mark_pos[i], ' ', insert);
85                    strcpy(new_line+max_mark_pos, queue[i]+mark_pos[i]+1);
86
87                    len[i] = new_len;
88                    freeset(queue[i], new_line);
89                }
90            }
91        }
92
93        offset = max_mark_pos;
94    }
95
96    for (int i = 0; i<count; ++i) {
97        dest.add(queue[i]);
98        queue[i] = NULL;
99    }
100    count = 0;
101}
102
103struct queued_line {
104    string line;
105    int    indentation;
106    queued_line(const char *line_, int indent) : line(line_), indentation(indent) { }
107};
108
109typedef list<queued_line> PrintQueue;
110
111class PrintMaybe : virtual Noncopyable {
112    Output&          out;
113    const Location&  started_at;
114    bool             printed_sth;
115    PrintMaybe      *next;
116    PrintQueue       queue;
117
118public:
119    PrintMaybe(PrintMaybe *head, Output& out_, const Location& loc)
120        : out(out_),
121          started_at(loc), 
122          printed_sth(false),
123          next(head)
124    {
125    }
126    ~PrintMaybe() {
127    }
128
129    void add(const char *line) {
130        if (printed_sth) {
131            out.write(line);
132        }
133        else {
134            queue.push_back(queued_line(line, out.get_formatter().get_indent()));
135        }
136    }
137    void spool() {
138        aisc_assert(!printed_sth);
139        printed_sth = true;
140        if (!queue.empty()) {
141            Formatter& formatter  = out.get_formatter();
142            int        old_indent = formatter.get_indent();
143            for (PrintQueue::iterator i = queue.begin(); i != queue.end(); ++i) {
144                queued_line& ql = *i;
145                formatter.set_indent(ql.indentation);
146                out.write(ql.line.c_str());
147            }
148            formatter.set_indent(old_indent);
149            queue.clear();
150        }
151    }
152
153    void will_print() {
154        if (next) next->will_print();
155        if (!printed_sth) {
156            spool();
157        }
158    }
159
160    void not_destroyed_error() {
161        print_error(&started_at, "PMSTART without matching PMEND");
162        if (next) next->not_destroyed_error();
163    }
164
165    static void pop(PrintMaybe*& head) {
166        PrintMaybe *next = head->next;
167        head->next       = NULL;
168        delete head;
169        head             = next;
170    }
171};
172
173void Output::setup() {
174    fp    = NULL;
175    id    = NULL;
176    name  = NULL;
177    maybe = NULL;
178
179    have_open_loc = false;
180}
181void Output::cleanup() {
182    close_file();
183    free(id);
184    free(name);
185    if (maybe) {
186        maybe->not_destroyed_error();
187        delete maybe;
188    }
189}
190
191void Output::maybe_start() {
192    maybe = new PrintMaybe(maybe, *this, Interpreter::instance->at()->source);
193}
194int Output::maybe_write(const char *line) {
195    if (!maybe) {
196        print_error(Interpreter::instance->at(), "no PMSTART before PM");
197        return -1;
198    }
199    maybe->add(line);
200    return 0;
201}
202int Output::maybe_end() {
203    if (!maybe) {
204        print_error(Interpreter::instance->at(), "no PMSTART before PMEND");
205        return -1;
206    }
207    PrintMaybe::pop(maybe);
208    return 0;
209}
210
211int Output::write(const char *line) {
212    if (!inUse()) {
213        print_error(Interpreter::instance->at(), "Fatal: attempt to write to unused file");
214        return -1;
215    }
216
217    if (maybe) maybe->will_print();
218
219    int res = formatter.write(line);
220    formatter.flush(fp);
221    return res;
222}
223
224Formatter::Formatter()
225    : tabstop(4),
226      column(0),
227      indent(0),
228      printed_sth(false)
229{
230    set_tabstop(4);
231
232    for (int i = 0; i < 256; i++) {
233        outtab[i] = i;
234    }
235
236    outtab[(unsigned char)'n']  = '\n';
237    outtab[(unsigned char)'t']  = '\t';
238    outtab[(unsigned char)'|']  = ALIGN_MARKER;
239    outtab[(unsigned char)'0']  = 0;
240    outtab[(unsigned char)'1']  = 0;
241    outtab[(unsigned char)'2']  = 0;
242    outtab[(unsigned char)'3']  = 0;
243    outtab[(unsigned char)'4']  = 0;
244    outtab[(unsigned char)'5']  = 0;
245    outtab[(unsigned char)'6']  = 0;
246    outtab[(unsigned char)'7']  = 0;
247    outtab[(unsigned char)'8']  = 0;
248    outtab[(unsigned char)'9']  = 0;
249    outtab[(unsigned char)'\\'] = 0;
250}
251
252int Formatter::write(const char *str) {
253    int         no_nl = 0;
254    const char *p     = str;
255    char        c;
256
257    while ((c = *(p++))) {
258        if (c == '$') {
259            c = *(p++);
260            if (!c)
261                break;
262
263            if (!outtab[(unsigned)(c)]) {
264                if (c == '\\') {
265                    no_nl = 1;
266                }
267                else if (isdigit(c)) {
268                    int pos = tabs[c - '0'];
269                    tab_to_pos(pos);
270                }
271                continue;
272            }
273            else {
274                c = outtab[(unsigned)(c)];
275            }
276        }
277        if (c == '\t') {
278            int pos = ((column/tabstop)+1)*tabstop;
279            tab_to_pos(pos);
280        }
281        else if (c == '\n') {
282            if (no_nl) {
283                no_nl = 0;
284            }
285            else {
286                finish_line();
287            }
288        }
289        else if (c == '@') {
290            if (strncmp(p, "SETSOURCE", 9) == 0) { // skip '@SETSOURCE file, line@'
291                p = strchr(p, '@');
292                if (!p) {
293                    print_error(Interpreter::instance->at(), "expected '@' after '@SETSOURCE' (injected code)");
294                    return 1;
295                }
296                p++;
297            }
298            else {
299                print_char(c);
300            }
301        }
302        else {
303            print_char(c);
304        }
305    }
306    if (!no_nl) {
307        finish_line();
308    }
309    return 0;
310}
311
312bool Interpreter::set_data(const char *dataBlock, int offset_in_line) {
313    parser.set_line_start(dataBlock, offset_in_line);
314    parser.set_source(at()->source); // remove ?
315    data.set_tokens(parser.parseTokenListBlock(dataBlock));
316    return data.get_tokens();
317}
318
319
320int Interpreter::launch(int argc, char ** argv) {
321    int exitcode = EXIT_FAILURE;
322
323    // save CL-arguments as variables (with names like 'argv[0]' ..)
324    {
325        for (int i=0; i<argc; i++) {
326            write_var(formatted("argv[%i]", i), argv[i]);
327        }
328        write_var("argc", formatted("%i", argc));
329    }
330
331    {
332        char *buf = read_aisc_file(argv[1], NULL);
333        if (buf) {
334            prg = parser.parse_program(buf, argv[1]);
335            free(buf);
336        }
337    }
338   
339    if (!prg) {
340        fputs("Nothing to execute\n", stderr);
341    }
342    else {
343        if (compile_program()) {
344            fprintf(stderr, "Compilation of '%s' failed\n", argv[1]);
345        }
346        else {
347            if (run_program()) {
348                if (!Location::get_error_count()) {
349                    print_error(at(), "AISC compiler bailed out w/o error");
350                }
351                fputs("AISC reports errors\n", stderr);
352                for (int i = 0; i < OPENFILES; i++) output[i].close_and_unlink();
353                fflush(stdout);
354            }
355            else {
356                aisc_assert(!Location::get_error_count());
357                exitcode = EXIT_SUCCESS;
358            }
359        }
360    }
361
362    return exitcode;
363}
364
365int main(int argc, char ** argv) {
366    int exitcode = EXIT_FAILURE;
367
368    if (argc < 2) {
369        fprintf(stderr, "AISC - ARB integrated source compiler\n");
370        fprintf(stderr, "Usage: aisc [fileToCompile]+\n");
371        fprintf(stderr, "Error: missing file name\n");
372    }
373    else {
374        exitcode = Interpreter().launch(argc, argv);
375    }
376    return exitcode;
377}
378
379
Note: See TracBrowser for help on using the repository browser.