📄 project.cpp
字号:
scope_blocks.top().iterate->parser.append(IteratorBlock::Parse(append));
if(iterate_finished) {
scope_blocks.top().iterate = 0;
bool ret = it->exec(this, place);
delete it;
if(!ret)
return false;
s = QString(d);
} else {
return true;
}
}
QString scope, var, op;
QStringList val;
#define SKIP_WS(d) while(*d && (*d == ' ' || *d == '\t')) d++
QByteArray dd = s.toLatin1();
const char *d = dd;
SKIP_WS(d);
IteratorBlock *iterator = 0;
bool scope_failed = false, else_line = false, or_op=false;
char quote = 0;
int parens = 0, scope_count=0, start_block = 0;
while(*d) {
if(!parens) {
if(*d == '=')
break;
if(*d == '+' || *d == '-' || *d == '*' || *d == '~') {
if(*(d+1) == '=') {
break;
} else if(*(d+1) == ' ') {
const char *k = d + 1;
SKIP_WS(k);
if(*k == '=') {
QString msg;
qmake_error_msg(*d + "must be followed immediately by =");
return false;
}
}
}
}
if(quote) {
if(*d == quote)
quote = 0;
} else if(*d == '(') {
++parens;
} else if(*d == ')') {
--parens;
} else if(*d == '"' /*|| *d == '\''*/) {
quote = *d;
}
if(!parens && !quote && (*d == ':' || *d == '{' || *d == ')' || *d == '|')) {
scope_count++;
scope = var.trimmed();
if(*d == ')')
scope += *d; // need this
var = "";
bool test = scope_failed;
if(scope.toLower() == "else") { //else is a builtin scope here as it modifies state
if(scope_count != 1 || scope_blocks.top().else_status == ScopeBlock::TestNone) {
qmake_error_msg(("Unexpected " + scope + " ('" + s + "')").toLatin1());
return false;
}
else_line = true;
test = (scope_blocks.top().else_status == ScopeBlock::TestSeek);
debug_msg(1, "Project Parser: %s:%d : Else%s %s.", parser.file.toLatin1().constData(), parser.line_no,
scope == "else" ? "" : QString(" (" + scope + ")").toLatin1().constData(),
test ? "considered" : "excluded");
} else {
QString comp_scope = scope;
bool invert_test = (comp_scope.left(1) == "!");
if(invert_test)
comp_scope = comp_scope.right(comp_scope.length()-1);
int lparen = comp_scope.indexOf('(');
if(or_op == scope_failed) {
if(lparen != -1) { // if there is an lparen in the scope, it IS a function
int rparen = comp_scope.lastIndexOf(')');
if(rparen == -1) {
QByteArray error;
error.reserve(256);
#if defined(_MSC_VER) && _MSC_VER >= 1400
sprintf_s(error.data(), 256, "Function missing right paren: %s ('%s')",
comp_scope.toLatin1().constData(), s.toLatin1().constData());
#else
sprintf(error.data(), "Function missing right paren: %s ('%s')",
comp_scope.toLatin1().constData(), s.toLatin1().constData());
#endif
qmake_error_msg(error);
return false;
}
QString func = comp_scope.left(lparen);
QStringList args = split_arg_list(comp_scope.mid(lparen+1, rparen - lparen - 1));
for(int i = 0; i < args.size(); ++i)
args[i] = remove_quotes(args[i].trimmed());
if(function) {
fprintf(stderr, "%s:%d: No tests can come after a function definition!\n",
parser.file.toLatin1().constData(), parser.line_no);
return false;
} else if(func == "for") { //for is a builtin function here, as it modifies state
if(args.count() > 2 || args.count() < 1) {
fprintf(stderr, "%s:%d: for(iterate, list) requires two arguments.\n",
parser.file.toLatin1().constData(), parser.line_no);
return false;
} else if(iterator) {
fprintf(stderr, "%s:%d unexpected nested for()\n",
parser.file.toLatin1().constData(), parser.line_no);
return false;
}
iterator = new IteratorBlock;
QString it_list;
if(args.count() == 1) {
doVariableReplace(args[0], place);
it_list = args[0];
if(args[0] != "ever") {
delete iterator;
iterator = 0;
fprintf(stderr, "%s:%d: for(iterate, list) requires two arguments.\n",
parser.file.toLatin1().constData(), parser.line_no);
return false;
}
it_list = "forever";
} else if(args.count() == 2) {
iterator->variable = args[0];
doVariableReplace(args[1], place);
it_list = args[1];
}
QStringList list = place[it_list];
if(list.isEmpty()) {
if(it_list == "forever") {
iterator->loop_forever = true;
} else {
int dotdot = it_list.indexOf("..");
if(dotdot != -1) {
bool ok;
int start = it_list.left(dotdot).toInt(&ok);
if(ok) {
int end = it_list.mid(dotdot+2).toInt(&ok);
if(ok) {
if(start < end) {
for(int i = start; i <= end; i++)
list << QString::number(i);
} else {
for(int i = start; i >= end; i--)
list << QString::number(i);
}
}
}
}
}
}
iterator->list = list;
test = !invert_test;
} else if(iterator) {
iterator->test.append(IteratorBlock::Test(func, args, invert_test));
test = !invert_test;
} else if(func == "defineTest" || func == "defineReplace") {
if(!function_blocks.isEmpty()) {
fprintf(stderr,
"%s:%d: cannot define a function within another definition.\n",
parser.file.toLatin1().constData(), parser.line_no);
return false;
}
if(args.count() != 1) {
fprintf(stderr, "%s:%d: %s(function_name) requires one argument.\n",
parser.file.toLatin1().constData(), parser.line_no, func.toLatin1().constData());
return false;
}
QMap<QString, FunctionBlock*> *map = 0;
if(func == "defineTest")
map = &testFunctions;
else
map = &replaceFunctions;
if(!map || map->contains(args[0])) {
fprintf(stderr, "%s:%d: Function[%s] multiply defined.\n",
parser.file.toLatin1().constData(), parser.line_no, args[0].toLatin1().constData());
return false;
}
function = new FunctionBlock;
map->insert(args[0], function);
test = true;
} else {
test = doProjectTest(func, args, place);
if(*d == ')' && !*(d+1)) {
if(invert_test)
test = !test;
scope_blocks.top().else_status =
(test ? ScopeBlock::TestFound : ScopeBlock::TestSeek);
return true; // assume we are done
}
}
} else {
QString cscope = comp_scope.trimmed();
doVariableReplace(cscope, place);
test = isActiveConfig(cscope.trimmed(), true, &place);
}
if(invert_test)
test = !test;
}
}
if(!test && !scope_failed)
debug_msg(1, "Project Parser: %s:%d : Test (%s) failed.", parser.file.toLatin1().constData(),
parser.line_no, scope.toLatin1().constData());
if(test == or_op)
scope_failed = !test;
or_op = (*d == '|');
if(*d == '{') { // scoping block
start_block++;
if(iterator) {
for(int off = 0, braces = 0; true; ++off) {
if(*(d+off) == '{')
++braces;
else if(*(d+off) == '}' && braces)
--braces;
if(!braces || !*(d+off)) {
iterator->parser.append(QString(QByteArray(d+1, off-1)));
if(braces > 1)
iterator->scope_level += braces-1;
d += off-1;
break;
}
}
}
}
} else if(!parens && *d == '}') {
if(start_block) {
--start_block;
} else if(!scope_blocks.count()) {
warn_msg(WarnParser, "Possible braces mismatch %s:%d", parser.file.toLatin1().constData(), parser.line_no);
} else {
if(scope_blocks.count() == 1) {
fprintf(stderr, "Braces mismatch %s:%d\n", parser.file.toLatin1().constData(), parser.line_no);
return false;
}
debug_msg(1, "Project Parser: %s:%d : Leaving block %d", parser.file.toLatin1().constData(),
parser.line_no, scope_blocks.count());
ScopeBlock sb = scope_blocks.pop();
if(sb.iterate)
sb.iterate->exec(this, place);
}
} else {
var += *d;
}
d++;
}
var = var.trimmed();
if(!else_line || (else_line && !scope_failed))
scope_blocks.top().else_status = (!scope_failed ? ScopeBlock::TestFound : ScopeBlock::TestSeek);
if(start_block) {
ScopeBlock next_block(scope_failed);
next_block.iterate = iterator;
if(iterator)
next_block.else_status = ScopeBlock::TestNone;
else if(scope_failed)
next_block.else_status = ScopeBlock::TestSeek;
else
next_block.else_status = ScopeBlock::TestFound;
scope_blocks.push(next_block);
debug_msg(1, "Project Parser: %s:%d : Entering block %d (%d). [%s]", parser.file.toLatin1().constData(),
parser.line_no, scope_blocks.count(), scope_failed, s.toLatin1().constData());
} else if(iterator) {
iterator->parser.append(var+QString(d));
bool ret = iterator->exec(this, place);
delete iterator;
return ret;
}
if((!scope_count && !var.isEmpty()) || (scope_count == 1 && else_line))
scope_blocks.top().else_status = ScopeBlock::TestNone;
if(!*d) {
if(!var.trimmed().isEmpty())
qmake_error_msg(("Parse Error ('" + s + "')").toLatin1());
return var.isEmpty(); // allow just a scope
}
SKIP_WS(d);
for(; *d && op.indexOf('=') == -1; op += *(d++))
;
op.replace(QRegExp("\\s"), "");
SKIP_WS(d);
QString vals(d); // vals now contains the space separated list of values
int rbraces = vals.count('}'), lbraces = vals.count('{');
if(scope_blocks.count() > 1 && rbraces - lbraces == 1) {
debug_msg(1, "Project Parser: %s:%d : Leaving block %d", parser.file.toLatin1().constData(),
parser.line_no, scope_blocks.count());
ScopeBlock sb = scope_blocks.pop();
if(sb.iterate)
sb.iterate->exec(this, place);
vals.truncate(vals.length()-1);
} else if(rbraces != lbraces) {
warn_msg(WarnParser, "Possible braces mismatch {%s} %s:%d",
vals.toLatin1().constData(), parser.file.toLatin1().constData(), parser.line_no);
}
if(scope_failed)
return true; // oh well
#undef SKIP_WS
doVariableReplace(vals, place);
doVariableReplace(var, place);
var = varMap(var); //backwards compatability
if(!var.isEmpty() && Option::mkfile::do_preprocess) {
static QString last_file("*none*");
if(parser.file != last_file) {
fprintf(stdout, "#file %s:%d\n", parser.file.toLatin1().constData(), parser.line_no);
last_file = parser.file;
}
fprintf(stdout, "%s %s %s\n", var.toLatin1().constData(), op.toLatin1().constData(), vals.toLatin1().constData());
}
// vallist is the broken up list of values
QStringList vallist = split_value_list(vals, (var == "DEPENDPATH" || var == "INCLUDEPATH"));
if(!vallist.filter("=").isEmpty())
warn_msg(WarnParser, "Detected possible line continuation: {%s} %s:%d",
var.toLatin1().constData(), parser.file.toLatin1().constData(), parser.line_no);
QStringList &varlist = place[var]; // varlist is the list in the symbol table
debug_msg(1, "Project Parser: %s:%d :%s: :%s: (%s)", parser.file.toLatin1().constData(), parser.line_no,
var.toLatin1().constData(), op.toLatin1().constData(), vallist.isEmpty() ? "" : vallist.join(" :: ").toLatin1().constData());
// now do the operation
if(op == "~=") {
if(vals.length() < 4 || vals.at(0) != 's') {
qmake_error_msg(("~= operator only can handle s/// function ('" +
s + "')").toLatin1());
return false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -