// expandArg writes NULL-terminated expansions of `arg', a NULL-terminated // string, to stdout. If arg does not begin with `@' or does not refer to a // file, it is written as is. Otherwise the contents of the file are // recursively expanded. On unexpected EOF in malformed response files an // incomplete final argument is written, even if it is empty, to parse like GCC. void expandArg(String *arg) { FILE *f; if (arg->data[0] != '@' || !(f = fopen(&arg->data[1], "r"))) { fwrite(arg->data, 1, arg->len, stdout); return; } resize(arg, 0); State cur = outside; int c; do { c = fgetc(f); State next = transitions[cur][charClass(c)]; if ((cur == unq && next == outside) || (cur != outside && c == EOF)) { append(arg, "", 1); expandArg(arg); resize(arg, 0); } else if (cur == unq_esc || cur == sq_esc || cur == dq_esc || (cur == outside ? next == unq : cur == next)) { char s = c; append(arg, &s, 1); } cur = next; } while (c != EOF); fclose(f); }
// new Function([args, ...], body); CJValueP CJFunctionFunction:: exec(CJavaScript *js, const Values &values) { assert(values.size() >= 1); std::string name; // no name (anonymous function) // values[0] is prototype // args are values[1]->values[values.size() - 2] CJFunction::Args args; if (values.size() > 2) { for (uint i = 1; i < values.size() - 1; ++i) { std::string arg = values[i]->toString(); std::vector<std::string> args1; if (! expandArg(arg, args1)) { js->throwSyntaxError(this, "Invalid function arguments"); return CJValueP(); } for (const auto &arg1 : args1) args.push_back(arg1); } } // create function this global scope and return CJFunctionP userFn = js->createFunction(name, args); userFn->init(userFn); userFn->setScope(js, js->currentUserFunctionScope()); userFn->addFunctionMethods(js, userFn, CJObjTypeP()); // body is values[values.size() - 1] CJExecBlockP block; if (values.size() > 1) { std::string body = values[values.size() - 1]->toString(); js->pushUserFunction(userFn); //js->startScope(userFn->scope()); block = js->interpFunctionBlock(body); //js->endScope(); userFn->setBlock(block); js->popUserFunction(); } return userFn; }
int main(int argc, char **argv) { String arg = { 0 }; while (*++argv) { resize(&arg, 0); append(&arg, *argv, strlen(*argv) + 1); expandArg(&arg); } free(arg.data); return EXIT_SUCCESS; }