-rw-r--r-- | qmake/project.cpp | 524 |
1 files changed, 419 insertions, 105 deletions
diff --git a/qmake/project.cpp b/qmake/project.cpp index 834823d..8aa6ff7 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -1,11 +1,9 @@ /**************************************************************************** -** $Id$ ** -** Definition of ________ class. ** -** Created : 970521 +** Implementation of QMakeProject class. ** -** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. +** Copyright (C) 1992-2003 Trolltech AS. All rights reserved. ** -** This file is part of the network module of the Qt GUI Toolkit. +** This file is part of qmake. ** @@ -38,2 +36,3 @@ #include "project.h" +#include "property.h" #include "option.h" @@ -60,2 +59,3 @@ struct parser_info { } parser; + static void qmake_error_msg(const char *msg) @@ -65,2 +65,42 @@ static void qmake_error_msg(const char *msg) +QStringList qmake_mkspec_paths() +{ + QStringList ret; + const QString concat = QDir::separator() + QString("mkspecs"); + if(const char *qmakepath = getenv("QMAKEPATH")) { +#ifdef Q_OS_WIN + QStringList lst = QStringList::split(';', qmakepath); + for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it) { + QStringList lst2 = QStringList::split(':', (*it)); + for(QStringList::Iterator it2 = lst2.begin(); it2 != lst2.end(); ++it2) + ret << ((*it2) + concat); + } +#else + QStringList lst = QStringList::split(':', qmakepath); + for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it) + ret << ((*it) + concat); +#endif + } + if(const char *qtdir = getenv("QTDIR")) + ret << (QString(qtdir) + concat); +#ifdef QT_INSTALL_PREFIX + ret << (QT_INSTALL_PREFIX + concat); +#endif +#if defined(HAVE_QCONFIG_CPP) + ret << (qInstallPath() + concat); +#endif +#ifdef QT_INSTALL_DATA + ret << (QT_INSTALL_DATA + concat); +#endif +#if defined(HAVE_QCONFIG_CPP) + ret << (qInstallPathData() + concat); +#endif + + /* prefer $QTDIR if it is set */ + if (getenv("QTDIR")) + ret << getenv("QTDIR"); + ret << qInstallPathData(); + return ret; +} + static QString varMap(const QString &x) @@ -70,8 +110,22 @@ static QString varMap(const QString &x) ret = "QMAKE" + ret.mid(5); - if(ret == "INTERFACES") + else if(ret == "INTERFACES") ret = "FORMS"; - if(ret == "QMAKE_POST_BUILD") + else if(ret == "QMAKE_POST_BUILD") ret = "QMAKE_POST_LINK"; - if(ret == "TARGETDEPS") + else if(ret == "TARGETDEPS") ret = "POST_TARGETDEPS"; + else if(ret == "LIBPATH") + ret = "QMAKE_LIBDIR"; + else if(ret == "QMAKE_EXT_MOC") + ret = "QMAKE_EXT_CPP_MOC"; + else if(ret == "QMAKE_MOD_MOC") + ret = "QMAKE_H_MOD_MOC"; + else if(ret == "QMAKE_LFLAGS_SHAPP") + ret = "QMAKE_LFLAGS_APP"; + else if(ret == "PRECOMPH") + ret = "PRECOMPILED_HEADER"; + else if(ret == "PRECOMPCPP") + ret = "PRECOMPILED_SOURCE"; + else if(ret == "INCPATH") + ret = "INCLUDEPATH"; return ret; @@ -81,7 +135,11 @@ static QStringList split_arg_list(const QString ¶ms) { - QStringList args; - int last = 0, parens = 0; QChar quote = 0; - for(int x = 0; x < (int)params.length(); x++) { - if(params[x] == ')') { + QStringList args; + for(int x = 0, last = 0, parens = 0; x <= (int)params.length(); x++) { + if(x == (int)params.length()) { + QString mid = params.mid(last, x - last).stripWhiteSpace(); + if(mid[(int)mid.length()-1] == quote) + mid.truncate(1); + args << mid; + } else if(params[x] == ')') { parens--; @@ -94,3 +152,3 @@ static QStringList split_arg_list(const QString ¶ms) } else if(!parens && !quote && params[x] == ',') { - args << params.mid(last, x - last); + args << params.mid(last, x - last).stripWhiteSpace(); last = x+1; @@ -98,4 +156,2 @@ static QStringList split_arg_list(const QString ¶ms) } - if(last != (int)params.length()) - args << params.mid(last); return args; @@ -105,3 +161,3 @@ static QStringList split_value_list(const QString &vals, bool do_semicolon=FALSE { - int last = 0; + QString build; QStringList ret; @@ -109,14 +165,18 @@ static QStringList split_value_list(const QString &vals, bool do_semicolon=FALSE for(int x = 0; x < (int)vals.length(); x++) { - if(!quote.isEmpty() && vals[x] == quote.top()) { + if(x != (int)vals.length()-1 && vals[x] == '\\' && (vals[x+1] == '\'' || vals[x+1] == '"')) + build += vals[x++]; //get that 'escape' + else if(!quote.isEmpty() && vals[x] == quote.top()) quote.pop(); - } else if(vals[x] == '\'' || vals[x] == '"') { + else if(vals[x] == '\'' || vals[x] == '"') quote.push(vals[x]); - } else if(quote.isEmpty() && - ((do_semicolon && vals[x] == ';') || vals[x] == ' ')) { - ret << vals.mid(last, x - last); - last = x+1; + + if(quote.isEmpty() && ((do_semicolon && vals[x] == ';') || vals[x] == ' ')) { + ret << build; + build = ""; + } else { + build += vals[x]; } } - if(last != (int)vals.length()) - ret << vals.mid(last); + if(!build.isEmpty()) + ret << build; return ret; @@ -126,2 +186,17 @@ QMakeProject::QMakeProject() { + prop = NULL; +} + +QMakeProject::QMakeProject(QMakeProperty *p) +{ + prop = p; +} + +void +QMakeProject::reset() +{ + /* scope blocks start at true */ + test_status = TestNone; + scope_flag = 0x01; + scope_block = 0; } @@ -132,3 +207,3 @@ QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place) QString s = t.simplifyWhiteSpace(); - int hash_mark = s.find('#'); + int hash_mark = s.find("#"); if(hash_mark != -1) //good bye comments @@ -149,3 +224,3 @@ QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place) /* adjust scope for each block which appears on a single line */ - for(int i = (s.contains('{')-s.contains('}')); i; i--) + for(int i = (s.contains('{')-s.contains('}')); i>0; i--) scope_flag &= ~(0x01 << (++scope_block)); @@ -230,3 +305,3 @@ QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place) } else { - test = isActiveConfig(comp_scope.stripWhiteSpace(), TRUE); + test = isActiveConfig(comp_scope.stripWhiteSpace(), TRUE, &place); } @@ -250,2 +325,10 @@ QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place) } + } else if(!parens && *d == '}') { + if(!scope_block) { + warn_msg(WarnParser, "Possible braces mismatch %s:%d", parser.file.latin1(), parser.line_no); + } else { + debug_msg(1, "Project Parser: %s:%d : Leaving block %d", parser.file.latin1(), + parser.line_no, scope_block); + --scope_block; + } } else { @@ -255,2 +338,3 @@ QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place) } + var = var.stripWhiteSpace(); if(!scope_count || (scope_count == 1 && else_line)) @@ -262,3 +346,3 @@ QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place) if(!*d) { - if(!var.isEmpty()) + if(!var.stripWhiteSpace().isEmpty()) qmake_error_msg("Parse Error ('" + s + "')"); @@ -268,3 +352,4 @@ QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place) SKIP_WS(d); - for( ; *d && op.find('=') == -1; op += *(d++)); + for( ; *d && op.find('=') == -1; op += *(d++)) + ; op.replace(QRegExp("\\s"), ""); @@ -286,3 +371,2 @@ QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place) - var = var.stripWhiteSpace(); #undef SKIP_WS @@ -292,6 +376,6 @@ QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place) if(parser.file != last_file) { - fprintf(stderr, "#file %s:%d\n", parser.file.latin1(), parser.line_no); + fprintf(stdout, "#file %s:%d\n", parser.file.latin1(), parser.line_no); last_file = parser.file; } - fprintf(stderr, "%s %s %s\n", var.latin1(), op.latin1(), vals.latin1()); + fprintf(stdout, "%s %s %s\n", var.latin1(), op.latin1(), vals.latin1()); } @@ -307,3 +391,3 @@ QMakeProject::parse(const QString &t, QMap<QString, QStringList> &place) debug_msg(1, "Project Parser: %s:%d :%s: :%s: (%s)", parser.file.latin1(), parser.line_no, - var.latin1(), op.latin1(), vallist.join(" :: ").latin1()); + var.latin1(), op.latin1(), vallist.isEmpty() ? "" : vallist.join(" :: ").latin1()); @@ -371,6 +455,3 @@ QMakeProject::read(const QString &file, QMap<QString, QStringList> &place) parser_info pi = parser; - /* scope blocks start at true */ - test_status = TestNone; - scope_flag = 0x01; - scope_block = 0; + reset(); @@ -397,10 +478,11 @@ QMakeProject::read(const QString &file, QMap<QString, QStringList> &place) int prelen = line.length(); - { - int hash_mark = line.find('#'); - if(hash_mark != -1) //bye comments + + int hash_mark = line.find("#"); + if(hash_mark != -1) //good bye comments line = line.left(hash_mark); - } if(!line.isEmpty() && line.right(1) == "\\") { + if (!line.startsWith("#")) { line.truncate(line.length() - 1); s += line + " "; + } } else if(!line.isEmpty() || (line.isEmpty() && !prelen)) { @@ -421,2 +503,5 @@ QMakeProject::read(const QString &file, QMap<QString, QStringList> &place) parser = pi; + if(scope_block != 0) + warn_msg(WarnParser, "%s: Unterminated conditional at end of file.", + file.latin1()); return ret; @@ -425,11 +510,11 @@ QMakeProject::read(const QString &file, QMap<QString, QStringList> &place) bool -QMakeProject::read(const QString &project, const QString &, bool just_project) +QMakeProject::read(const QString &project, const QString &, uchar cmd) { - if(just_project) { //nothing more, nothing less pfile = project; - if(pfile != "-" && !QFile::exists(pfile) && pfile.right(4) != ".pro") - pfile += ".pro"; - return read(pfile, vars); + return read(cmd); } +bool +QMakeProject::read(uchar cmd) +{ if(cfile.isEmpty()) { @@ -441,4 +526,3 @@ QMakeProject::read(const QString &project, const QString &, bool just_project) - /* parse the cache */ - if(Option::mkfile::do_cache) { + if(cmd & ReadCache && Option::mkfile::do_cache) { /* parse the cache */ if(Option::mkfile::cachefile.isEmpty()) { //find it as it has not been specified @@ -464,12 +548,7 @@ QMakeProject::read(const QString &project, const QString &, bool just_project) } - /* parse mkspec */ - QStringList mkspec_roots; - /* prefer $QTDIR if it is set */ - if (getenv("QTDIR")) - mkspec_roots << getenv("QTDIR"); - mkspec_roots << qInstallPathData(); + if(cmd & ReadConf) { /* parse mkspec */ + QStringList mkspec_roots = qmake_mkspec_paths(); if(Option::mkfile::qmakespec.isEmpty()) { for(QStringList::Iterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { - QString mkspec = (*it) + QDir::separator() + QString("mkspecs") + - QDir::separator() + "default"; + QString mkspec = (*it) + QDir::separator() + "default"; if(QFile::exists(mkspec)) { @@ -488,4 +567,3 @@ QMakeProject::read(const QString &project, const QString &, bool just_project) for(QStringList::Iterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { - QString mkspec = (*it) + QDir::separator() + QString("mkspecs") + - QDir::separator() + Option::mkfile::qmakespec; + QString mkspec = (*it) + QDir::separator() + Option::mkfile::qmakespec; if(QFile::exists(mkspec)) { @@ -504,3 +582,8 @@ QMakeProject::read(const QString &project, const QString &, bool just_project) /* parse qmake configuration */ + while(Option::mkfile::qmakespec.endsWith(QString(QChar(QDir::separator())))) + Option::mkfile::qmakespec.truncate(Option::mkfile::qmakespec.length()-1); QString spec = Option::mkfile::qmakespec + QDir::separator() + "qmake.conf"; + if(!QFile::exists(spec) && + QFile::exists(Option::mkfile::qmakespec + QDir::separator() + "tmake.conf")) + spec = Option::mkfile::qmakespec + QDir::separator() + "tmake.conf"; debug_msg(1, "QMAKESPEC conf: reading %s", spec.latin1()); @@ -514,7 +597,9 @@ QMakeProject::read(const QString &project, const QString &, bool just_project) } - + } + if(cmd & ReadCmdLine) { /* commandline */ - cfile = project; + cfile = pfile; parser.line_no = 1; //really arg count now.. duh parser.file = "(internal)"; + reset(); for(QStringList::Iterator it = Option::before_user_vars.begin(); @@ -528,16 +613,24 @@ QMakeProject::read(const QString &project, const QString &, bool just_project) } + } - /* parse project file */ - debug_msg(1, "Project file: reading %s", project.latin1()); vars = base_vars; /* start with the base */ - pfile = project; - if(pfile != "-" && !QFile::exists(pfile) && pfile.right(4) != ".pro") + if(cmd & ReadProFile) { /* parse project file */ + debug_msg(1, "Project file: reading %s", pfile.latin1()); + if(pfile != "-" && !QFile::exists(pfile) && !pfile.endsWith(".pro")) pfile += ".pro"; - if(!read(pfile, vars)) return FALSE; + } + if(cmd & ReadPostFiles) { /* parse post files */ + const QStringList l = vars["QMAKE_POST_INCLUDE_FILES"]; + for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) + read((*it), vars); + } + + if(cmd & ReadCmdLine) { parser.line_no = 1; //really arg count now.. duh parser.file = "(internal)"; + reset(); for(QStringList::Iterator it = Option::after_user_vars.begin(); @@ -550,2 +643,3 @@ QMakeProject::read(const QString &project, const QString &, bool just_project) } + } @@ -553,3 +647,4 @@ QMakeProject::read(const QString &project, const QString &, bool just_project) if(!Option::user_template.isEmpty()) { - debug_msg(1, "Overriding TEMPLATE (%s) with: %s", vars["TEMPLATE"].first().latin1(), Option::user_template.latin1()); + debug_msg(1, "Overriding TEMPLATE (%s) with: %s", vars["TEMPLATE"].first().latin1(), + Option::user_template.latin1()); vars["TEMPLATE"].clear(); @@ -563,5 +658,4 @@ QMakeProject::read(const QString &project, const QString &, bool just_project) templ = QStringList(templ.first().left(templ.first().length() - 2)); - if ( !Option::user_template_prefix.isEmpty() ) { + if ( !Option::user_template_prefix.isEmpty() ) templ.first().prepend(Option::user_template_prefix); - } @@ -595,3 +689,3 @@ QMakeProject::read(const QString &project, const QString &, bool just_project) bool -QMakeProject::isActiveConfig(const QString &x, bool regex) +QMakeProject::isActiveConfig(const QString &x, bool regex, QMap<QString, QStringList> *place) { @@ -639,3 +733,3 @@ QMakeProject::isActiveConfig(const QString &x, bool regex) - QStringList &configs = vars["CONFIG"]; + QStringList &configs = (place ? (*place)["CONFIG"] : vars["CONFIG"]); for(QStringList::Iterator it = configs.begin(); it != configs.end(); ++it) { @@ -779,3 +873,6 @@ QMakeProject::doProjectTest(const QString& func, QStringList args, QMap<QString, } else if(func == "include" || func == "load") { - if(args.count() != 1) { + QString seek_var; + if(args.count() == 2 && func == "include") { + seek_var = args[1]; + } else if(args.count() != 1) { QString func_desc = "include(file)"; @@ -796,18 +893,46 @@ QMakeProject::doProjectTest(const QString& func, QStringList args, QMap<QString, if(file.find(Option::dir_sep) == -1 || !QFile::exists(file)) { - if(QFile::exists(Option::mkfile::qmakespec + QDir::separator() + file)) { - file.prepend(Option::mkfile::qmakespec + QDir::separator()); - } else { bool found = FALSE; + const QString concat = QDir::separator() + QString("mkspecs") + + QDir::separator() + QString("features"); QStringList feature_roots; - if(getenv("QTDIR")) - feature_roots << getenv("QTDIR"); + if(const char *mkspec_path = getenv("QMAKEFEATURES")) { +#ifdef Q_OS_WIN + QStringList lst = QStringList::split(';', mkspec_path); + for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it) + feature_roots += QStringList::split(':', (*it)); +#else + feature_roots += QStringList::split(':', mkspec_path); +#endif + } + if(const char *qmakepath = getenv("QMAKEPATH")) { +#ifdef Q_OS_WIN + QStringList lst = QStringList::split(';', qmakepath); + for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it) { + QStringList lst2 = QStringList::split(':', (*it)); + for(QStringList::Iterator it2 = lst2.begin(); it2 != lst2.end(); ++it2) + feature_roots << ((*it2) + concat); + } +#else + QStringList lst = QStringList::split(':', qmakepath); + for(QStringList::Iterator it = lst.begin(); it != lst.end(); ++it) + feature_roots << ((*it) + concat); +#endif + } + feature_roots << Option::mkfile::qmakespec; + if(const char *qtdir = getenv("QTDIR")) + feature_roots << (qtdir + concat); #ifdef QT_INSTALL_PREFIX - feature_roots << QT_INSTALL_PREFIX; + feature_roots << (QT_INSTALL_PREFIX + concat); +#endif +#if defined(HAVE_QCONFIG_CPP) + feature_roots << (qInstallPath() + concat); #endif #ifdef QT_INSTALL_DATA - feature_roots << QT_INSTALL_DATA; + feature_roots << (QT_INSTALL_DATA + concat); +#endif +#if defined(HAVE_QCONFIG_CPP) + feature_roots << (qInstallPathData() + concat); #endif for(QStringList::Iterator it = feature_roots.begin(); it != feature_roots.end(); ++it) { - QString prf = (*it) + QDir::separator() + QString("mkspecs") + - QDir::separator() + QString("features") + QDir::separator() + file; + QString prf = (*it) + QDir::separator() + file; if(QFile::exists(prf)) { @@ -824,5 +949,33 @@ QMakeProject::doProjectTest(const QString& func, QStringList args, QMap<QString, } + if(QDir::isRelativePath(file)) { + QStringList include_roots; + include_roots << Option::output_dir; + QString pfilewd = QFileInfo(parser.file).dirPath(); + if(pfilewd.isEmpty()) + include_roots << pfilewd; + if(Option::output_dir != QDir::currentDirPath()) + include_roots << QDir::currentDirPath(); + for(QStringList::Iterator it = include_roots.begin(); it != include_roots.end(); ++it) { + if(QFile::exists((*it) + QDir::separator() + file)) { + file = (*it) + QDir::separator() + file; + break; + } + } } + if(Option::mkfile::do_preprocess) //nice to see this first.. + fprintf(stderr, "#switching file %s(%s) - %s:%d\n", func.latin1(), file.latin1(), + parser.file.latin1(), parser.line_no); debug_msg(1, "Project Parser: %s'ing file %s.", func.latin1(), file.latin1()); + QString orig_file = file; + int di = file.findRev(Option::dir_sep); + QDir sunworkshop42workaround = QDir::current(); + QString oldpwd = sunworkshop42workaround.currentDirPath(); + if(di != -1) { + if(!QDir::setCurrent(file.left(file.findRev(Option::dir_sep)))) { + fprintf(stderr, "Cannot find directory: %s\n", file.left(di).latin1()); + return FALSE; + } + file = file.right(file.length() - di - 1); + } parser_info pi = parser; @@ -831,8 +984,15 @@ QMakeProject::doProjectTest(const QString& func, QStringList args, QMap<QString, TestStatus sc = test_status; - bool r = read(file.latin1(), place); + bool r = FALSE; + if(!seek_var.isNull()) { + QMap<QString, QStringList> tmp; + if((r = read(file.latin1(), tmp))) + place[seek_var] += tmp[seek_var]; + } else { + r = read(file.latin1(), place); + } if(r) - vars["QMAKE_INTERNAL_INCLUDED_FILES"].append(file); + vars["QMAKE_INTERNAL_INCLUDED_FILES"].append(orig_file); else warn_msg(WarnParser, "%s:%d: Failure to include file %s.", - pi.file.latin1(), pi.line_no, file.latin1()); + pi.file.latin1(), pi.line_no, orig_file.latin1()); parser = pi; @@ -841,2 +1001,3 @@ QMakeProject::doProjectTest(const QString& func, QStringList args, QMap<QString, scope_block = sb; + QDir::setCurrent(oldpwd); return r; @@ -856,3 +1017,3 @@ QMakeProject::doProjectTest(const QString& func, QStringList args, QMap<QString, fixEnvVariables(msg); - printf("Project %s: %s\n", func.upper().latin1(), msg.latin1()); + fprintf(stderr, "Project %s: %s\n", func.upper().latin1(), msg.latin1()); if(func == "message") @@ -892,3 +1053,3 @@ QMakeProject::doProjectCheckReqs(const QStringList &deps, QMap<QString, QStringL } else { - test = isActiveConfig(chk, TRUE); + test = isActiveConfig(chk, TRUE, &place); } @@ -913,3 +1074,3 @@ QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> & for(int var_begin, var_last=0; (var_begin = str.find("$$", var_last)) != -1; var_last = var_begin) { - if(var_begin >= int( str.length() + 2 ) ) { + if(var_begin >= (int)str.length() + 2) { break; @@ -922,3 +1083,3 @@ QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> & int var_incr = var_begin + 2; - bool in_braces = FALSE, as_env = FALSE; + bool in_braces = FALSE, as_env = FALSE, as_prop = FALSE; if(str[var_incr] == '{') { @@ -926,3 +1087,3 @@ QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> & var_incr++; - while(var_incr < int( str.length() ) && + while(var_incr < (int)str.length() && (str[var_incr] == ' ' || str[var_incr] == '\t' || str[var_incr] == '\n')) @@ -933,5 +1094,8 @@ QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> & var_incr++; + } else if(str[var_incr] == '[') { + as_prop = TRUE; + var_incr++; } QString val, args; - while(var_incr < int( str.length() ) && + while(var_incr < (int)str.length() && (str[var_incr].isLetter() || str[var_incr].isNumber() || str[var_incr] == '.' || str[var_incr] == '_')) @@ -943,2 +1107,13 @@ QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> & parser.file.latin1(), parser.line_no, + str.mid(var_begin, QMAX(var_incr - var_begin, + (int)str.length())).latin1(), str.latin1()); + var_begin += var_incr; + continue; + } + var_incr++; + } else if(as_prop) { + if(str[var_incr] != ']') { + var_incr++; + warn_msg(WarnParser, "%s:%d: Unterminated prop-variable replacement '%s' (%s)", + parser.file.latin1(), parser.line_no, str.mid(var_begin, QMAX(var_incr - var_begin, int(str.length()))).latin1(), str.latin1()); @@ -949,3 +1124,3 @@ QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> & } else if(str[var_incr] == '(') { //args - for(int parens = 0; var_incr < int( str.length() ); var_incr++) { + for(int parens = 0; var_incr < (int)str.length(); var_incr++) { if(str[var_incr] == '(') { @@ -964,3 +1139,3 @@ QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> & } - if(var_incr > int( str.length() ) || (in_braces && str[var_incr] != '}')) { + if(var_incr > (int)str.length() || (in_braces && str[var_incr] != '}')) { var_incr++; @@ -968,3 +1143,4 @@ QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> & parser.file.latin1(), parser.line_no, - str.mid(var_begin, QMAX(var_incr - var_begin, int( str.length() ))).latin1(), str.latin1()); + str.mid(var_begin, QMAX(var_incr - var_begin, + (int)str.length())).latin1(), str.latin1()); var_begin += var_incr; @@ -978,2 +1154,5 @@ QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> & replacement = getenv(val); + } else if(as_prop) { + if(prop) + replacement = prop->value(val); } else if(args.isEmpty()) { @@ -983,2 +1162,10 @@ QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> & replacement = "\t"; + else if(val == "LITERAL_DOLLAR") + replacement = "$"; + else if(val == "LITERAL_HASH") + replacement = "#"; + else if(val == "PWD") + replacement = QDir::currentDirPath(); + else if(val == "DIR_SEPARATOR") + replacement = Option::dir_sep; else @@ -986,19 +1173,83 @@ QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> & } else { - QStringList arg_list = split_arg_list(args); - for(QStringList::Iterator arit = arg_list.begin(); arit != arg_list.end(); ++arit) { - (*arit) = (*arit).stripWhiteSpace(); // blah, get rid of space - doVariableReplace((*arit), place); - } + QStringList arg_list = split_arg_list(doVariableReplace(args, place)); debug_msg(1, "Running function: %s( %s )", val.latin1(), arg_list.join("::").latin1()); if(val.lower() == "member") { - if(arg_list.count() < 1 || arg_list.count() > 2) { - fprintf(stderr, "%s:%d: member(var, place) requires two arguments.\n", + if(arg_list.count() < 1 || arg_list.count() > 3) { + fprintf(stderr, "%s:%d: member(var, start, end) requires three arguments.\n", parser.file.latin1(), parser.line_no); } else { - uint pos = 0; - if(arg_list.count() == 2) - pos = arg_list[1].toInt(); const QStringList &var = place[varMap(arg_list.first())]; - if(var.count() >= pos) - replacement = var[pos]; + int start = 0; + if(arg_list.count() >= 2) + start = arg_list[1].toInt(); + if(start < 0) + start += int(var.count()); + int end = start; + if(arg_list.count() == 3) + end = arg_list[2].toInt(); + if(end < 0) + end += int(var.count()); + if(end < start) + end = start; + for(int i = start; i <= end && (int)var.count() >= i; i++) { + if(!replacement.isEmpty()) + replacement += " "; + replacement += var[i]; + } + } + } else if(val.lower() == "fromfile") { + if(arg_list.count() != 2) { + fprintf(stderr, "%s:%d: fromfile(file, variable) requires two arguments.\n", + parser.file.latin1(), parser.line_no); + } else { + QString file = arg_list[0]; + file = Option::fixPathToLocalOS(file); + file.replace("\"", ""); + + if(QDir::isRelativePath(file)) { + QStringList include_roots; + include_roots << Option::output_dir; + QString pfilewd = QFileInfo(parser.file).dirPath(); + if(pfilewd.isEmpty()) + include_roots << pfilewd; + if(Option::output_dir != QDir::currentDirPath()) + include_roots << QDir::currentDirPath(); + for(QStringList::Iterator it = include_roots.begin(); it != include_roots.end(); ++it) { + if(QFile::exists((*it) + QDir::separator() + file)) { + file = (*it) + QDir::separator() + file; + break; + } + } + } + QString orig_file = file; + int di = file.findRev(Option::dir_sep); + QDir sunworkshop42workaround = QDir::current(); + QString oldpwd = sunworkshop42workaround.currentDirPath(); + if(di != -1 && QDir::setCurrent(file.left(file.findRev(Option::dir_sep)))) + file = file.right(file.length() - di - 1); + parser_info pi = parser; + int sb = scope_block; + int sf = scope_flag; + TestStatus sc = test_status; + QMap<QString, QStringList> tmp; + bool r = read(file.latin1(), tmp); + if(r) { + replacement = tmp[arg_list[1]].join(" "); + vars["QMAKE_INTERNAL_INCLUDED_FILES"].append(orig_file); + } else { + warn_msg(WarnParser, "%s:%d: Failure to include file %s.", + pi.file.latin1(), pi.line_no, orig_file.latin1()); + } + parser = pi; + test_status = sc; + scope_flag = sf; + scope_block = sb; + QDir::setCurrent(oldpwd); + } + } else if(val.lower() == "eval") { + for(QStringList::ConstIterator arg_it = arg_list.begin(); + arg_it != arg_list.end(); ++arg_it) { + if(!replacement.isEmpty()) + replacement += " "; + replacement += place[(*arg_it)].join(" "); } @@ -1028,2 +1279,20 @@ QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> & } + } else if(val.lower() == "split") { + if(arg_list.count() < 2 || arg_list.count() > 3) { + fprintf(stderr, "%s:%d split(var, sep, join) requires three arguments\n", + parser.file.latin1(), parser.line_no); + } else { + QString sep = arg_list[1], join = " "; + if(arg_list.count() == 3) + join = arg_list[2]; + QStringList var = place[varMap(arg_list.first())]; + for(QStringList::Iterator vit = var.begin(); vit != var.end(); ++vit) { + QStringList lst = QStringList::split(sep, (*vit)); + for(QStringList::Iterator spltit = lst.begin(); spltit != lst.end(); ++spltit) { + if(!replacement.isEmpty()) + replacement += join; + replacement += (*spltit); + } + } + } } else if(val.lower() == "find") { @@ -1052,3 +1321,3 @@ QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> & while(proc && !feof(proc)) { - int read_in = fread(buff, 1, 255, proc); + int read_in = int(fread(buff, 1, 255, proc)); if(!read_in) @@ -1063,2 +1332,47 @@ QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> & } + } else if(val.lower() == "files") { + if(arg_list.count() != 1) { + fprintf(stderr, "%s:%d files(pattern) requires one argument\n", + parser.file.latin1(), parser.line_no); + } else { + QString dir, regex = arg_list[0]; + regex = Option::fixPathToLocalOS(regex); + regex.replace("\"", ""); + if(regex.findRev(QDir::separator()) != -1) { + dir = regex.left(regex.findRev(QDir::separator()) + 1); + regex = regex.right(regex.length() - dir.length()); + } + QDir d(dir, regex); + for(int i = 0; i < (int)d.count(); i++) { + if(!replacement.isEmpty()) + replacement += " "; + replacement += dir + d[i]; + } + } + } else if(val.lower() == "prompt") { + if(arg_list.count() != 1) { + fprintf(stderr, "%s:%d prompt(question) requires one argument\n", + parser.file.latin1(), parser.line_no); + } else if(projectFile() == "-") { + fprintf(stderr, "%s:%d prompt(question) cannot be used when '-o -' is used.\n", + parser.file.latin1(), parser.line_no); + } else { + QString msg = arg_list.first(); + if((msg.startsWith("\"") || msg.startsWith("'")) && msg.endsWith(msg.left(1))) + msg = msg.mid(1, msg.length()-2); + msg.replace(QString("${QMAKE_FILE}"), parser.file.latin1()); + msg.replace(QString("${QMAKE_LINE_NUMBER}"), QString::number(parser.line_no)); + msg.replace(QString("${QMAKE_DATE}"), QDateTime::currentDateTime().toString()); + doVariableReplace(msg, place); + fixEnvVariables(msg); + if(!msg.endsWith("?")) + msg += "?"; + fprintf(stderr, "Project %s: %s ", val.upper().latin1(), msg.latin1()); + + QFile qfile; + if(qfile.open(IO_ReadOnly, stdin)) { + QTextStream t(&qfile); + replacement = t.readLine(); + } + } } else { |