21 #include <ucommon/ucommon.h>
22 #include <ucommon/export.h>
31 #define NUM_FORMAT "%lld"
33 #define NUM_FORMAT "%ld"
37 using namespace UCOMMON_NAMESPACE;
39 Script::interp::interp() :
40 memalloc(Script::paging)
44 Script::interp::~interp()
49 void Script::interp::initialize(
void)
51 unsigned tempcount =
sizeof(temps) /
sizeof(
char *);
60 stack = (Script::stack_t *)alloc(
sizeof(Script::stack_t) * Script::stacking);
61 syms = (LinkedObject **)alloc(
sizeof(LinkedObject *) * Script::indexing);
62 memset(syms, 0,
sizeof(Script::symbol *) * Script::indexing);
63 while(pos < tempcount)
64 temps[pos++] = (
char *)alloc(Script::sizing + 1);
67 Script::symbol *err = createSymbol(
"error:64");
72 bool Script::interp::error(
const char *msg)
76 fprintf(stderr,
"*** %s(%d): %s\n", image->filename, stack[frame].line->lnum, msg);
80 String::set(errmsg, 65, msg);
82 if(!eq(stack[frame].scr->name,
"_init_")) {
83 if(scriptEvent(
"error"))
91 char *Script::interp::getTemp(
void)
93 unsigned tempcount =
sizeof(temps) /
sizeof(
char *);
95 char *ptr = temps[tempindex++];
96 if(tempindex >= tempcount)
101 const char *Script::interp::getFormat(Script::symbol *sym,
const char *
id,
char *tp)
109 static char null[1] = {0};
111 unsigned dcount = 0, pos;
117 Script::symbol *index = NULL;
124 if(eq(
id,
"len:", 4))
125 snprintf(tp, Script::sizing + 1,
"%u", (
unsigned)strlen(sym->data));
126 else if(eq(
id,
"key:", 4)) {
127 String::set(tp, Script::sizing + 1, cp);
128 ep = strchr(tp,
'=');
132 String::set(tp, 2,
"-");
134 else if(eq(
id,
"tail:", 5)) {
135 dcount = Script::count(sym->data);
137 String::set(tp, Script::sizing + 1, Script::get(cp, --dcount));
141 else if(eq(
id,
"head:", 5)) {
142 String::set(tp, Script::sizing + 1, sym->data);
143 if(Script::count(tp) > 1) {
144 dcount = Script::offset(tp, 1);
149 else if(eq(
id,
"pull:", 5) || eq(
id,
"<<:", 3)) {
150 String::set(tp, Script::sizing + 1, sym->data);
151 if(Script::count(tp) > 1) {
152 dcount = Script::offset(tp, 1);
154 memcpy(sym->data, sym->data + dcount, strlen(sym->data + dcount) + 1);
159 else if(eq(
id,
"pop:", 4) || eq(
id,
">>:", 3)) {
160 dcount = Script::count(sym->data);
162 String::set(tp, Script::sizing + 1, Script::get(sym->data, --dcount));
164 dcount = Script::offset(sym->data, dcount);
165 sym->data[--dcount] = 0;
173 else if(eq(
id,
"val:", 4) && (*cp ==
'\'' || *cp ==
'\"' || *cp ==
'(')) {
174 String::set(tp, Script::sizing + 1, cp + 1);
176 ep = strrchr(tp,
')');
178 ep = strchr(tp, *cp);
182 else if(eq(
id,
"val:", 4) && strchr(sym->data,
'=')) {
183 cp = strchr(sym->data,
'=') + 1;
184 if(*cp ==
'\"' || *cp ==
'\'') {
185 String::set(tp, Script::sizing + 1, cp + 1);
186 ep = strchr(tp, *cp);
191 String::set(tp, Script::sizing + 1, cp);
192 ep = strchr(tp,
',');
197 else if(eq(
id,
"unquote:", 8) && sym->size) {
203 ep = strrchr(cp,
')');
207 else if(*cp ==
'\"' || *cp ==
'\'') {
208 ep = strchr(cp + 1, *cp);
213 String::set(sym->data, sym->size + 1, cp);
216 else if(eq(
id,
"upper:", 6) && sym->size) {
217 String::upper(sym->data);
220 else if(eq(
id,
"lower:", 6) && sym->size) {
221 String::lower(sym->data);
224 else if((eq(
id,
"inc:", 4) || eq(
id,
"++:", 3)) && sym->size) {
226 snprintf(sym->data, sym->size + 1,
NUM_FORMAT, ++val);
229 else if(eq(
id,
"count:", 6))
230 snprintf(tp, Script::sizing + 1,
"%u", Script::count(sym->data));
231 else if(eq(
id,
"index/", 6)) {
238 if(pos < strlen(sym->data))
239 cp = sym->data + pos;
242 Script::copy(cp, tp, Script::sizing);
244 else if(eq(
id,
"offset/", 7)) {
252 cp = Script::get(sym->data, pos);
253 Script::copy(cp, tp, Script::sizing);
255 else if((eq(
id,
"dec:", 4) || eq(
id,
"--:", 3)) && sym->size) {
257 snprintf(sym->data, sym->size + 1,
NUM_FORMAT, --val);
260 else if(eq(
id,
"size:", 5))
261 snprintf(tp, Script::sizing + 1,
"%d", sym->size);
262 else if(eq(
id,
"val:", 4) || eq(
id,
"int:", 4)) {
264 snprintf(tp, Script::sizing + 1,
NUM_FORMAT, val);
266 else if(eq(
id,
"num:", 4)) {
268 snprintf(tp, Script::sizing + 1,
NUM_FORMAT, val);
270 String::add(tp, Script::sizing + 1,
".");
272 cp = strchr(sym->data,
'.');
277 while(dcount++ < Script::decimals && pos < Script::sizing) {
278 if(*cp && isdigit(*cp))
285 else if(eq(
id,
"map/", 4)) {
287 String::set(idbuf,
sizeof(idbuf),
id + 4);
288 ep = strchr(idbuf,
':');
292 if(!index || !index->data[0])
294 pos = atoi(sym->data);
297 snprintf(idbuf,
sizeof(idbuf),
",%s", sym->data);
301 else if(eq(
id,
"find/", 5)) {
306 while(dcount < 30 && *
id && *
id !=
':')
307 idbuf[dcount++] = *(
id++);
308 idbuf[dcount++] =
'=';
313 if(!strncmp(cp, idbuf + 1, len - 1))
314 cp = sym->data + len - 1;
315 else if(NULL != (cp = strstr(sym->data, idbuf)))
324 else if(*cp ==
'(') {
330 while(dcount < Script::sizing && *cp && *cp != quote) {
331 if(*cp ==
'(' && paren)
333 if(*cp ==
')' && paren) {
337 if(*cp ==
'=' && quote ==
',' && cp[1] ==
'\"') {
338 tp[dcount++] = *(cp++);
342 tp[dcount++] = *(cp++);
346 else if(eq(
id,
"bool:", 5)) {
347 if(atoi(sym->data) > 0 || tolower(sym->data[0]) ==
't' || tolower(sym->data[0] ==
'y'))
348 snprintf(tp, Script::sizing + 1,
"true");
350 snprintf(tp, Script::sizing + 1,
"false");
355 const char *Script::interp::getContent(
const char *cp)
367 id = strchr(cp,
':');
373 return getFormat(sym, ++cp, tp);
386 if(cp[1] && cp[1] !=
'=')
392 const char *Script::interp::getKeyword(
const char *
id)
394 line_t *line = stack[frame].line;
398 while(index < line->argc) {
399 cp = line->argv[index++];
402 return getContent(line->argv[index]);
409 const char *Script::interp::getIndex(
void)
413 unsigned pos = frame;
415 method = stack[--pos].line->method;
416 if(method == (method_t)&Script::methods::scrForeach) {
417 char *temp = getTemp();
418 snprintf(temp, Script::sizing,
"%d", stack[pos].index);
425 Script::method_t Script::interp::getLooping(
void)
428 return (method_t)NULL;
430 return stack[frame - 1].line->method;
433 const char *Script::interp::getContent(
void)
436 line_t *line = stack[frame].line;
437 while(stack[frame].index < line->argc) {
438 cp = line->argv[stack[frame].index++];
441 ++stack[frame].index;
450 const char *Script::interp::getValue(
void)
453 line_t *line = stack[frame].line;
454 while(stack[frame].index < line->argc) {
455 cp = line->argv[stack[frame].index++];
458 ++stack[frame].index;
461 return getContent(cp);
467 bool Script::interp::setConst(
const char *
id,
const char *value)
470 linked_pointer<Script::symbol> sp;
471 Script::symbol *var = NULL;
473 if(*
id ==
'=' || *
id ==
'%')
479 path = NamedObject::keyindex(
id, Script::indexing);
483 if(eq(sp->name,
id) && sp->scope == stack[frame].scope)
488 var = (Script::symbol *)alloc(
sizeof(Script::symbol));
491 var->scope = stack[frame].scope;
493 var->data = dup(value);
494 var->enlist(&syms[path]);
498 Script::symbol *Script::interp::createSymbol(
const char *
id)
501 linked_pointer<Script::symbol> sp;
502 Script::symbol *var = NULL, *local = NULL;
503 unsigned size = Script::sizing;
506 if(*
id ==
'=' || *
id ==
'%')
512 if(strchr(
id,
':')) {
513 char *temp = getTemp();
515 String::set(temp, Script::sizing + 1,
id);
516 cp = strchr(temp,
':');
524 path = NamedObject::keyindex(
id, Script::indexing);
528 size = Script::sizing;
531 if(eq(sp->name,
id) && sp->scope == NULL)
533 if(eq(sp->name,
id) && sp->scope == stack[frame].scope)
542 var = (Script::symbol *)alloc(
sizeof(Script::symbol));
548 var->data = (
char *)alloc(size + 1);
549 var->enlist(&syms[path]);
555 unsigned Script::interp::getTypesize(
const char *type_id)
560 if(eq(type_id,
"int"))
563 if(eq(type_id,
"num"))
566 if(eq(type_id,
"bool"))
572 const char *Script::interp::getTypeinit(
const char *type_id)
577 if(eq(type_id,
"int") || eq(type_id,
"num"))
580 if(eq(type_id,
"bool"))
586 void Script::interp::getParams(Script::header *scope, Script::line_t *line)
595 while(index < line->argc) {
596 cp = line->argv[index++];
599 cp = line->argv[index++];
602 snprintf(pbuf,
sizeof(pbuf),
"%d", ++param);
605 if(eq(cp,
"required") || eq(cp,
"optional"))
606 setRef(scope,
id, const_cast<char *>(
""), 0);
607 else if(*cp ==
'%') {
610 setRef(scope,
id, sym->data, sym->size);
614 setRef(scope,
id, const_cast<char *>(
""), 0);
619 setRef(scope,
id, const_cast<char *>(cp), 0);
624 void Script::interp::setRef(Script::header *scope,
const char *
id,
char *value,
unsigned size)
627 linked_pointer<Script::symbol> sp;
628 Script::symbol *var = NULL;
630 if(*
id ==
'=' || *
id ==
'%')
636 path = NamedObject::keyindex(
id, Script::indexing);
640 if(eq(sp->name,
id) && sp->scope == scope) {
648 var = (Script::symbol *)alloc(
sizeof(Script::symbol));
653 var->enlist(&syms[path]);
660 Script::symbol *Script::interp::getVar(
const char *
id,
const char *value)
663 linked_pointer<Script::symbol> sp;
664 Script::symbol *var = NULL;
665 unsigned size = Script::sizing;
668 if(*
id ==
'=' || *
id ==
'%')
674 if(strchr(
id,
':')) {
675 char *temp = getTemp();
677 String::set(temp, Script::sizing + 1,
id);
678 cp = strchr(temp,
':');
682 size = getTypesize(cp);
684 value = getTypeinit(cp);
690 path = NamedObject::keyindex(
id, Script::indexing);
694 size = Script::sizing;
697 if(eq(sp->name,
id) && sp->scope == stack[frame].scope) {
705 var = (Script::symbol *)alloc(
sizeof(Script::symbol));
709 var->scope = stack[frame].scope;
711 var->data = (
char *)alloc(size + 1);
712 var->enlist(&syms[path]);
722 String::set(var->data, var->size + 1, value);
728 Script::symbol *Script::interp::find(
const char *
id)
730 unsigned path = NamedObject::keyindex(
id, Script::indexing);
731 linked_pointer<Script::symbol> sp = syms[path];
732 Script::symbol *global = NULL, *local = NULL;
735 if(eq(sp->name,
id)) {
736 if(sp->scope == NULL)
738 else if(sp->scope == stack[frame].scope)
750 void Script::interp::detach(
void)
755 void Script::interp::startScript(Script::header *scr)
757 linked_pointer<Script::event> ep = scr->events;
760 if(eq(ep->name,
"init")) {
762 stack[frame].event = *ep;
763 stack[frame].line = ep->first;
770 bool Script::interp::attach(Script *img,
const char *entry)
772 Script::header *
main = NULL;
773 linked_pointer<Script::header> hp;
782 if(entry && *entry ==
'@')
783 main = Script::find(img, entry);
784 else while(entry && main == NULL && path < Script::indexing) {
785 hp = img->scripts[path++];
788 if(*cp ==
'@' && match(cp, entry)) {
797 main = Script::find(img,
"@main");
802 setStack(img->first);
804 while(frame && stack[frame].line)
805 (this->*(stack[frame].line->method))();
807 if(is(img->shared)) {
809 setStack(img->shared->first);
810 while(frame && stack[frame].line)
811 (this->*(stack[frame].line->method))();
822 void Script::interp::skip(
void)
824 stack[frame].line = stack[frame].line->next;
827 bool Script::interp::match(
const char *found,
const char *name)
829 assert(found != NULL);
830 assert(name != NULL);
835 return !stricmp(found, name);
838 bool Script::interp::isInherited(
const char *name)
843 Script::event *Script::interp::scriptMethod(
const char *name)
845 linked_pointer<Script::event> mp = stack[frame].scr->methods;
848 if(match(mp->name, name))
855 bool Script::interp::scriptEvent(
const char *name)
857 linked_pointer<Script::event> ep;
858 bool inherit = isInherited(name);
859 unsigned stackp = frame;
862 ep = stack[stackp].scr->events;
865 if(match(ep->name, name))
871 if(!is(ep) && !inherit)
876 if(stack[stackp].event == *ep)
882 setStack(stack[frame].scr, *ep);
886 while(stackp > stack[stackp].base && stack[stackp].line->loop)
889 if(stackp && stackp >= stack[stackp].base)
896 void Script::interp::setStack(Script::header *scr, Script::event *ev)
898 stack[frame].scr = scr;
899 stack[frame].event = ev;
900 stack[frame].index = 0;
901 stack[frame].resmask = scr->resmask;
904 stack[frame].line = ev->first;
906 stack[frame].line = scr->first;
909 void Script::interp::pullBase(
void)
911 while(frame && stack[frame - 1].base == stack[frame].base)
915 void Script::interp::pullScope(
void)
917 while(frame && stack[frame - 1].scr == stack[frame].scr)
921 void Script::interp::pullLoop(
void)
925 stack[frame - 1].line = stack[frame].line;
926 stack[frame - 1].index = 0;
931 unsigned Script::interp::getResource(
void)
933 if(!stack || !stack[frame].scr || (frame == 0 && !stack[frame].line))
936 if(stack[frame].line)
937 return stack[frame].line->mask | stack[frame].resmask;
939 return stack[frame].resmask;
942 bool Script::interp::pop(
void)
953 void Script::interp::push(
void)
955 if(frame >= Script::stacking) {
956 if(!scriptEvent(
"stack")) {
958 stack[frame].line = NULL;
963 stack[frame + 1] = stack[frame];
967 bool Script::interp::trylabel(
const char *label)
972 Script::header *scr = Script::find(*image, label);
973 if(!scr || !scr->first || stack[stack[frame].base].scr == scr)
976 frame = stack[frame].base;
981 bool Script::interp::tryexit(
void)
983 if(stack[frame].event && eq(
"exit", stack[frame].event->name))
986 if(scriptEvent(
"exit"))
989 Script::header *ex = Script::find(image.get(),
"@exit");
992 if(!ex || stack[frame].scr == ex)
999 bool Script::interp::step(
void)
1001 unsigned scount = Script::stepping;
1002 line_t *line = stack[frame].line;
1005 while(line && rtn && scount--) {
1006 rtn = (this->*(line->method))();
1007 line = stack[frame].line;
1013 while(stack[frame].line == NULL && frame)
1016 if(!stack[frame].line && !tryexit())
1022 bool Script::interp::getCondition(
const char *test,
const char *v)
1024 unsigned points = 0;
1025 Script::symbol *sym;
1027 if(eq(test,
"defined")) {
1042 if(eq(test,
"const")) {
1058 if(eq(test,
"modify")) {
1075 if(eq(test,
"empty")) {
1081 if(eq(test,
"integer")) {
1096 if(eq(test,
"digits")) {
1108 if(eq(test,
"number")) {
1134 bool Script::interp::isConditional(
unsigned index)
1136 Script::line_t *line = stack[frame].line;
1140 while(index < line->argc) {
1141 rtn = getExpression(index);
1142 cp = line->argv[index];
1143 if((*cp ==
'-' || *cp ==
'!') && isalpha(cp[1]))
1148 if(index >= line->argc)
1151 cp = line->argv[index++];
1153 if(eq(cp,
"?&&") || eq(cp,
"and")) {
1159 if(eq(cp,
"?||") || eq(cp,
"or")) {
1170 bool Script::interp::getExpression(
unsigned index)
1172 Script::line_t *line = stack[frame].line;
1173 const char *v1 =
"", *v2 =
"", *op;
1174 const char *d1, *d2;
1176 char dec1[9], dec2[9];
1178 unsigned pos = 0, pcount;
1186 if(index < line->argc) {
1187 v1 = line->argv[index++];
1188 if((*v1 ==
'-' || *v1 ==
'!') && isalpha(v1[1])) {
1189 if(index < line->argc)
1190 v2 = line->argv[index++];
1194 return getCondition(++v1, v2);
1196 return !getCondition(++v1, v2);
1198 v1 = getContent(v1);
1203 if(index <= line->argc) {
1204 op = line->argv[index++];
1213 if(index <= line->argc)
1214 v2 = getContent(line->argv[index++]);
1216 d1 = strchr(v1,
'.');
1217 d2 = strchr(v2,
'.');
1222 snprintf(dec1,
sizeof(dec1),
NUM_FORMAT, dv);
1226 snprintf(dec2,
sizeof(dec2),
NUM_FORMAT, dv);
1229 unsigned c1 = strlen(dec1);
1230 unsigned c2 = strlen(dec2);
1237 dec1[8] = dec2[8] = 0;
1239 return ((atol(v1) == atol(v2)) && !strcmp(dec1, dec2));
1242 return ((atol(v1) != atol(v2)) || strcmp(dec1, dec2));
1245 return (*v1 && *v2);
1248 return (*v1 || *v2);
1251 if(strcmp(v1, v2) > 0)
1257 if(strcmp(v1, v2) < 0)
1263 if(strcmp(v1, v2) >= 0)
1269 if(strcmp(v1, v2) <= 0)
1274 if(eq(op,
"==") || eq(op,
"eq"))
1277 if(eq(op,
"!=") || eq(op,
"ne"))
1287 return (atol(v1) < atol(v2) || (atol(v1) == atol(v2) && dv1 < dv2));
1297 return (atoi(v1) < atoi(v2) || (atol(v1) == atol(v2) && dv1 <= dv2));
1307 return (atol(v1) > atol(v2) || (atol(v1) == atol(v2) && dv1 > dv2));
1317 return (atol(v1) > atol(v2) || (atol(v1) == atol(v2) && dv1 >= dv2));
1320 if(eq(op,
"?") || eq(op,
"in")) {
1321 pcount = Script::count(v2);
1326 while(pos < pcount) {
1327 op = Script::get(v2, pos++);
1328 if(op && eq(v1, op, len) && (op[len] ==
',' || op[len] == 0 || op[len] ==
'='))
1334 if(eq(op,
"!?") || eq(op,
"notin")) {
1335 pcount = Script::count(v2);
1340 while(pos < pcount) {
1341 op = Script::get(v2, pos++);
1342 if(op && eq(v1, op, len) && (op[len] ==
',' || op[len] == 0 || op[len] ==
'='))
1348 if(eq(op,
"!$") || eq(op,
"isnot"))
1349 return !match(v2, v1);
1351 if(eq(op,
"$") || eq(op,
"is"))
1352 return match(v2, v1);
1355 if(eq(op,
"~") || eq(op,
"!~")) {
1357 regex_t *regex =
new regex_t;
1358 memset(regex, 0,
sizeof(regex_t));
1360 if(regcomp(regex, v2, REG_ICASE|REG_NOSUB|REG_NEWLINE)) {
1366 if(regexec(regex, v1, 0, NULL, 0))
#define BAYONNE_NAMESPACE
GNU Bayonne library namespace.
int main(int argc, char **argv)