Bayonne 3 - API
 All Classes Namespaces Files Functions Variables Typedefs Macros
methods.cpp
Go to the documentation of this file.
1 // Copyright (C) 2008-2011 David Sugar, Tycho Softworks.
2 //
3 // This file is part of GNU Bayonne.
4 //
5 // GNU Bayonne is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // GNU Bayonne is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with GNU Bayonne. If not, see <http://www.gnu.org/licenses/>.
17 
18 #include <config.h>
19 #include <ucommon/ucommon.h>
20 #include <ucommon/export.h>
21 #include <bayonne.h>
22 
23 using namespace BAYONNE_NAMESPACE;
24 using namespace UCOMMON_NAMESPACE;
25 
26 bool Script::methods::scrDo(void)
27 {
28  push();
29  skip();
30  return true;
31 }
32 
33 bool Script::methods::scrPrevious(void)
34 {
35  --frame;
36  if(stack[frame].index < 2) {
37  stack[frame].index = 0;
38  skip();
39  return scrBreak();
40  }
41  stack[frame].index -= 2;
42  return true;
43 }
44 
45 bool Script::methods::scrExpand(void)
46 {
47  unsigned index = 1;
48  Script::line_t *line = stack[frame].line;
49  const char *tuples = getContent(line->argv[0]);
50  unsigned tcount = Script::count(tuples);
51  Script::symbol *sym;
52  const char *cp;
53 
54  while(line->argv[index]) {
55  sym = find(line->argv[index]);
56 
57  if(!sym)
58  sym = getVar(line->argv[index]);
59 
60  if(!sym)
61  return error("symbol not found");
62 
63  if(!sym->size)
64  return error("symbol not writable");
65 
66  if(index > tcount)
67  String::set(sym->data, sym->size + 1, "");
68  else {
69  cp = Script::get(tuples, index - 1);
70  Script::copy(cp, sym->data, sym->size + 1);
71  }
72  ++index;
73  }
74  skip();
75  return true;
76 }
77 
78 bool Script::methods::scrForeach(void)
79 {
80  Script::line_t *line = stack[frame].line;
81  Script::symbol *sym = find(line->argv[0]);
82  const char *cp;
83  unsigned index = stack[frame].index;
84 
85  if(!sym)
86  sym = getVar(line->argv[0]);
87 
88  if(!sym)
89  return error("symbol not found");
90 
91  if(!sym->size)
92  return error("symbol not writable");
93 
94  if(!index) {
95  cp = line->argv[2];
96  if(cp && (*cp == '%' || *cp == '&')) {
97  Script::symbol *skip = find(cp);
98  if(!skip)
99  skip = getVar(cp);
100  if(skip) {
101  index = atoi(skip->data);
102  if(skip->size)
103  String::set(skip->data, 2, "0");
104  }
105  }
106  else if(NULL != (cp = getContent(cp))) {
107  cp = getContent(cp);
108  if(cp)
109  index = atoi(cp);
110  }
111  }
112 
113  cp = Script::get(getContent(line->argv[1]), index);
114  if(cp == NULL) {
115  stack[frame].index = 0;
116  skip();
117  return scrBreak();
118  }
119 
120  Script::copy(cp, sym->data, sym->size + 1);
121  stack[frame].index = ++index;
122  push();
123  skip();
124  return true;
125 }
126 
127 bool Script::methods::scrWhile(void)
128 {
129  if(isConditional(0)) {
130  push();
131  skip();
132  return true;
133  }
134  skip();
135  return scrBreak();
136 }
137 
138 bool Script::methods::scrEndcase(void)
139 {
140  pullLoop();
141  return true;
142 }
143 
144 bool Script::methods::scrCase(void)
145 {
146  Script::method_t method = getLooping();
147  Script::line_t *line = stack[frame].line;
148 
149  if(method == (method_t)&Script::methods::scrCase) {
150  skip();
151  while(stack[frame].line && stack[frame].line->loop > line->loop)
152  skip();
153  return true;
154  }
155 
156  if(isConditional(0)) {
157  push();
158  skip();
159  return true;
160  }
161 
162  return scrOtherwise();
163 
164  if(stack[frame].line->method == (method_t)&Script::methods::scrOtherwise) {
165  push();
166  skip();
167  return false;
168  }
169  return false;
170 }
171 
172 bool Script::methods::scrOtherwise(void)
173 {
174  Script::line_t *line = stack[frame].line;
175 
176  skip();
177  while(stack[frame].line && stack[frame].line->loop > line->loop)
178  skip();
179 
180  return true;
181 }
182 
183 bool Script::methods::scrUntil(void)
184 {
185  if(isConditional(0))
186  pullLoop();
187  else
188  --frame;
189  return true;
190 }
191 
192 bool Script::methods::scrLoop(void)
193 {
194  --frame;
195  return true;
196 }
197 
198 bool Script::methods::scrElif(void)
199 {
200  return scrElse();
201 }
202 
203 bool Script::methods::scrEndif(void)
204 {
205  return scrNop();
206 }
207 
208 bool Script::methods::scrDefine(void)
209 {
210  return scrNop();
211 }
212 
213 bool Script::methods::scrInvoke(void)
214 {
215  Script::line_t *line = stack[frame].line;
216  unsigned mask;
217 
218  getParams(line->sub, line->sub->first);
219  getParams(line->sub, line);
220 
221  skip(); // return to next line
222  push(); // push where we are
223  stack[frame].scope = line->sub;
224  stack[frame].line = line->sub->first->next;
225  startScript(line->sub);
226 
227  mask = stack[frame].resmask |= line->sub->resmask;
228  if(mask != stack[frame].resmask) {
229  stack[frame].resmask = mask;
230  return false;
231  }
232  return true;
233 }
234 
235 bool Script::methods::scrElse(void)
236 {
237  Script::line_t *line = stack[frame].line;
238  unsigned loop = 0;
239 
240  skip();
241  while(NULL != (line = stack[frame].line)) {
242  if(line->method == (method_t)&Script::methods::scrIf)
243  ++loop;
244  else if(line->method == (method_t)&Script::methods::scrEndif) {
245  if(!loop) {
246  skip();
247  return true;
248  }
249  --loop;
250  }
251  skip();
252  }
253  return true;
254 }
255 
256 bool Script::methods::scrIf(void)
257 {
258  Script::line_t *line = stack[frame].line;
259  unsigned loop = 0;
260 
261  if(isConditional(0)) {
262  skip();
263  return true;
264  }
265 
266  skip();
267  while(NULL != (line = stack[frame].line)) {
268  if(line->method == (method_t)&Script::methods::scrIf)
269  ++loop;
270  else if(line->method == (method_t)&Script::methods::scrEndif) {
271  if(!loop) {
272  skip();
273  return true;
274  }
275  --loop;
276  }
277  else if(!loop && line->method == (method_t)&Script::methods::scrElse) {
278  skip();
279  return true;
280  }
281  else if(!loop && line->method == (method_t)&Script::methods::scrElif) {
282  if(isConditional(0)) {
283  skip();
284  return true;
285  }
286  }
287  skip();
288  }
289  return false;
290 }
291 
292 bool Script::methods::scrPause(void)
293 {
294  return false;
295 }
296 
297 bool Script::methods::scrBreak(void)
298 {
299  Script::line_t *line = stack[frame].line;
300  Script::method_t method = getLooping();
301 
302  if(method == (method_t)&Script::methods::scrCase || method == (method_t)&Script::methods::scrOtherwise) {
303  skip();
304  while(stack[frame].line && stack[frame].line->loop >= line->loop)
305  skip();
306  return true;
307  }
308 
309  pullLoop();
310  while(stack[frame].line && stack[frame].line->loop >= line->loop)
311  skip();
312  return true;
313 }
314 
315 bool Script::methods::scrRepeat(void)
316 {
317  --frame;
318  --stack[frame].index;
319  return true;
320 }
321 
322 bool Script::methods::scrContinue(void)
323 {
324  --frame;
325  return true;
326 }
327 
328 bool Script::methods::scrNop(void)
329 {
330  skip();
331  return true;
332 }
333 
334 bool Script::methods::scrWhen(void)
335 {
336  if(!isConditional(0))
337  skip();
338 
339  skip();
340  return true;
341 }
342 
343 bool Script::methods::scrExit(void)
344 {
345  frame = 0;
346  stack[frame].line = NULL;
347  return false;
348 }
349 
350 bool Script::methods::scrRestart(void)
351 {
352  unsigned mask = stack[frame].resmask;
353  pullBase();
354  setStack(stack[frame].scr);
355  if(mask == stack[frame].resmask)
356  return true;
357  return false;
358 }
359 
360 bool Script::methods::scrGoto(void)
361 {
362  Script::line_t *line = stack[frame].line;
363  const char *cp;
364  Script::header *scr = NULL;
365  unsigned index = 0;
366  unsigned mask = stack[frame].resmask;
367 
368  while(!scr && index < line->argc) {
369  cp = line->argv[index++];
370  if(*cp == '^') {
371  if(scriptEvent(++cp))
372  return true;
373  }
374  else
375  scr = Script::find(*image, line->argv[0]);
376  }
377  if(!scr)
378  return error("label not found");
379 
380  pullBase();
381  setStack(scr);
382  startScript(scr);
383  if(mask == stack[frame].resmask)
384  return true;
385  return false;
386 }
387 
388 bool Script::methods::scrGosub(void)
389 {
390  unsigned index = stack[frame].index;
391  Script::line_t *line = stack[frame].line;
392  Script::header *scr = NULL;
393  const char *cp;
394  unsigned mask = stack[frame].resmask;
395  Script::event *ev = NULL;
396 
397  while(ev == NULL && scr == NULL && index < line->argc) {
398  cp = line->argv[index++];
399  if(*cp == '@') {
400  scr = Script::find(*image, cp);
401  if(!scr && image->shared.get())
402  scr = Script::find(image->shared.get(), cp);
403  }
404  else
405  ev = scriptMethod(cp);
406  }
407 
408  if(!scr && !ev) {
409  if(!stack[frame].index)
410  return error("label not found");
411 
412  stack[frame].index = 0;
413  skip();
414  return true;
415  }
416 
417  stack[frame].index = index; // save index for re-call on return...
418  push();
419  if(scr) {
420  setStack(scr);
421  startScript(scr);
422  stack[frame].base = frame; // set base level to new script...
423  if(mask == stack[frame].resmask)
424  return true;
425  }
426  else {
427  stack[frame].line = ev->first;
428  stack[frame].index = 0;
429  return true;
430  }
431  return false;
432 }
433 
434 bool Script::methods::scrReturn(void)
435 {
436  unsigned mask = stack[frame].resmask;
437  if(!pop())
438  return scrExit();
439 
440  if(mask == stack[frame].resmask)
441  return true;
442  return false;
443 }
444 
445 bool Script::methods::scrIndex(void)
446 {
447  const char *op;
448  int result = 0, value;
449 
450  stack[frame].index = 0;
451  result = atoi(getValue());
452 
453  while(NULL != (op = getValue())) {
454  switch(*op) {
455  case '+':
456  result += atoi(getValue());
457  break;
458  case '-':
459  result -= atoi(getValue());
460  break;
461  case '*':
462  result *= atoi(getValue());
463  break;
464  case '/':
465  value = atoi(getValue());
466  if(value == 0)
467  return error("div by zero");
468  result /= value;
469  break;
470  case '#':
471  value = atoi(getValue());
472  if(value == 0)
473  return error("div by zero");
474  result %= value;
475  break;
476  }
477  }
478 
479  --frame;
480  if(!result) {
481  skip();
482  return scrBreak();
483  }
484  else
485  stack[frame].index = --result;
486 
487  return true;
488 }
489 
490 bool Script::methods::scrRef(void)
491 {
492  const char *cp = stack[frame].line->argv[0];
493  cp = getContent(cp);
494  skip();
495  return true;
496 }
497 
498 bool Script::methods::scrExpr(void)
499 {
500  unsigned exdecimals = Script::decimals;
501  const char *id, *cp, *op, *aop;
502  double result, value;
503  long lvalue;
504  char cvt[8];
505  char buf[32];
506 
507  stack[frame].index = 0;
508 
509  cp = getKeyword("decimals");
510  if(cp)
511  exdecimals = atoi(cp);
512 
513  id = getContent();
514  aop = getValue();
515  result = atof(getValue());
516 
517  while(NULL != (op = getValue())) {
518  switch(*op) {
519  case '+':
520  result += atof(getValue());
521  break;
522  case '-':
523  result -= atof(getValue());
524  break;
525  case '*':
526  result *= atof(getValue());
527  break;
528  case '/':
529  value = atof(getValue());
530  if(value == 0.) {
531  return error("div by zero");
532  }
533  result /= value;
534  break;
535  case '#':
536  lvalue = atol(getValue());
537  if(lvalue == 0)
538  return error("div by zero");
539  result = (long)result % lvalue;
540  }
541  }
542  cp = getContent(id);
543  if(cp)
544  value = atof(cp);
545  else
546  value = 0;
547  if(eq(aop, "+="))
548  value += result;
549  else if(eq(aop, "#="))
550  value = (long)value % (long)result;
551  else if(eq(aop, "-="))
552  value -= result;
553  else if(eq(aop, "*="))
554  value *= result;
555  else if(eq(aop, "/=") && result)
556  value /= result;
557  else if(eq(aop, "?=") || eq(aop, ":="))
558  value = result;
559 
560  stack[frame].index = 0;
561  cvt[0] = '%';
562  cvt[1] = '.';
563  cvt[2] = '0' + exdecimals;
564  cvt[3] = 'f';
565  cvt[4] = 0;
566  snprintf(buf, sizeof(buf), cvt, value);
567 
568  if(!getVar(id, buf))
569  return error("invalid symbol");
570 
571  skip();
572  return true;
573 }
574 
575 bool Script::methods::scrVar(void)
576 {
577  unsigned index = 0;
578  Script::line_t *line = stack[frame].line;
579  const char *id;
580 
581  while(index < line->argc) {
582  id = line->argv[index++];
583  if(*id == '=') {
584  if(!getVar(++id, getContent(line->argv[index++])))
585  return error("invalid symbol");
586  }
587  else {
588  if(!getVar(id))
589  return error("invalid symbol");
590  }
591  }
592  skip();
593  return true;
594 }
595 
596 bool Script::methods::scrConst(void)
597 {
598  unsigned index = 0;
599  Script::line_t *line = stack[frame].line;
600  const char *id;
601 
602  while(index < line->argc) {
603  id = line->argv[index++];
604  if(*id == '=') {
605  if(!setConst(++id, getContent(line->argv[index++])))
606  return error("invalid constant");
607  }
608  }
609  skip();
610  return true;
611 }
612 
613 bool Script::methods::scrError(void)
614 {
615  char msg[65];
616  unsigned index = 0;
617  Script::line_t *line = stack[frame].line;
618  bool space = false;
619  const char *cp;
620 
621  msg[0] = 0;
622  while(index < line->argc) {
623  if(space) {
624  String::add(msg, 65, " ");
625  space = false;
626  }
627  cp = line->argv[index++];
628  if(*cp != '&')
629  space = true;
630  String::add(msg, 65, getContent(cp));
631  }
632  return error(msg);
633 }
634 
635 bool Script::methods::scrClear(void)
636 {
637  unsigned index = 0;
638  Script::line_t *line = stack[frame].line;
639  const char *id;
640  Script::symbol *sym;
641 
642  while(index < line->argc) {
643  id = line->argv[index++];
644  sym = find(id);
645 
646  if(!sym || !sym->size)
647  return error("symbol not found");
648 
649  sym->data[0] = 0;
650  }
651  skip();
652  return true;
653 }
654 
655 bool Script::methods::scrAdd(void)
656 {
657  unsigned index = 1;
658  Script::line_t *line = stack[frame].line;
659  Script::symbol *sym = find(line->argv[0]);
660  const char *cp;
661 
662  if(!sym)
663  sym = getVar(line->argv[0]);
664 
665  if(!sym)
666  return error("symbol not found");
667 
668  if(!sym->size)
669  return error("symbol not writable");
670 
671  while(index < line->argc) {
672  cp = getContent(line->argv[index++]);
673  String::add(sym->data, sym->size + 1, cp);
674  }
675  skip();
676  return true;
677 }
678 
679 bool Script::methods::scrPack(void)
680 {
681  unsigned index = 1;
682  Script::line_t *line = stack[frame].line;
683  Script::symbol *sym = find(line->argv[0]);
684  const char *cp;
685  char quote[2] = {0,0};
686 
687  if(!sym)
688  sym = getVar(line->argv[0]);
689 
690  if(!sym)
691  return error("symbol not found");
692 
693  if(!sym->size)
694  return error("symbol not writable");
695 
696  while(index < line->argc) {
697  cp = line->argv[index++];
698  if(*cp == '=') {
699  if(sym->data[0])
700  String::add(sym->data, sym->size + 1, ",");
701 
702  String::add(sym->data, sym->size + 1, ++cp);
703  String::add(sym->data, sym->size + 1, "=");
704  cp = getContent(line->argv[index++]);
705  quote[0] = '\'';
706  goto add;
707  }
708  else {
709  cp = getContent(cp);
710  quote[0] = 0;
711 add:
712  if(sym->data[0])
713  String::add(sym->data, sym->size + 1, ",");
714 
715  if(!quote[0] && strchr(cp, ',')) {
716  if(*cp != '\'' && *cp != '\"')
717  quote[0] = '\'';
718  }
719  // tuple nesting...
720  if(!quote[0] && *cp == '\'')
721  quote[0] = '(';
722  if(quote[0])
723  String::add(sym->data, sym->size + 1, quote);
724  String::add(sym->data, sym->size + 1, cp);
725  if(quote[0] == '(')
726  quote[0] = ')';
727  if(quote[0])
728  String::add(sym->data, sym->size + 1, quote);
729  }
730  }
731  skip();
732  return true;
733 }
734 
735 bool Script::methods::scrPush(void)
736 {
737  Script::line_t *line = stack[frame].line;
738  Script::symbol *sym = createSymbol(line->argv[0]);
739  unsigned size = 0;
740  bool qflag = false;
741  const char *key = NULL, *value;
742 
743  if(!sym)
744  return error("invalid symbol id");
745 
746  if(!sym->size)
747  return error("symbol not writable");
748 
749  if(line->argv[2]) {
750  key = line->argv[1];
751  value = line->argv[2];
752  }
753  else
754  value = line->argv[1];
755 
756  if(key)
757  size = strlen(key) + 1;
758 
759  if(*value != '\"' && *value != '\'') {
760  qflag = true;
761  size += 2;
762  }
763  size += strlen(value);
764 
765  size = strlen(line->argv[1]) + 3;
766  if(line->argv[2])
767  size += strlen(line->argv[2]);
768 
769  if(strlen(sym->data) + size > sym->size)
770  return error("symbol too small");
771 
772  if(sym->data[0])
773  String::add(sym->data, sym->size + 1, ",");
774 
775  size = strlen(sym->data);
776  if(key && qflag)
777  snprintf(sym->data + size, sym->size + 1 - size, "%s='%s'", key, value);
778  else if(key)
779  snprintf(sym->data + size, sym->size + 1 - size, "%s=%s", key, value);
780  else if(qflag)
781  snprintf(sym->data + size, sym->size + 1 - size, "'%s'", value);
782  else
783  String::set(sym->data + size, sym->size + 1, value);
784  skip();
785  return true;
786 }
787 
788 bool Script::methods::scrSet(void)
789 {
790  unsigned index = 1;
791  Script::line_t *line = stack[frame].line;
792  Script::symbol *sym = createSymbol(line->argv[0]);
793  const char *cp;
794 
795  if(!sym)
796  return error("invalid symbol id");
797 
798  if(!sym->size)
799  return error("symbol not writable");
800 
801  sym->data[0] = 0;
802  while(index < line->argc) {
803  cp = getContent(line->argv[index++]);
804  String::add(sym->data, sym->size + 1, cp);
805  }
806  skip();
807  return true;
808 }
809 
#define BAYONNE_NAMESPACE
Definition: bayonne.h:25
GNU Bayonne library namespace.