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