aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs')
-rw-r--r--src/libs/utils/environment.cpp443
-rw-r--r--src/libs/utils/environment.h109
-rw-r--r--src/libs/utils/utils-lib.pri6
3 files changed, 556 insertions, 2 deletions
diff --git a/src/libs/utils/environment.cpp b/src/libs/utils/environment.cpp
new file mode 100644
index 00000000000..03b0084ecc6
--- /dev/null
+++ b/src/libs/utils/environment.cpp
@@ -0,0 +1,443 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation ([email protected])
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "environment.h"
+
+#include <QtCore/QProcess>
+#include <QtCore/QDir>
+#include <QtCore/QString>
+
+using namespace Utils;
+
+QList<EnvironmentItem> EnvironmentItem::fromStringList(QStringList list)
+{
+ QList<EnvironmentItem> result;
+ foreach (const QString &string, list) {
+ int pos = string.indexOf(QLatin1Char('='));
+ if (pos == -1) {
+ EnvironmentItem item(string, QString());
+ item.unset = true;
+ result.append(item);
+ } else {
+ EnvironmentItem item(string.left(pos), string.mid(pos+1));
+ result.append(item);
+ }
+ }
+ return result;
+}
+
+QStringList EnvironmentItem::toStringList(QList<EnvironmentItem> list)
+{
+ QStringList result;
+ foreach (const EnvironmentItem &item, list) {
+ if (item.unset)
+ result << QString(item.name);
+ else
+ result << QString(item.name + '=' + item.value);
+ }
+ return result;
+}
+
+Environment::Environment()
+{
+}
+
+Environment::Environment(QStringList env)
+{
+ foreach (const QString &s, env) {
+ int i = s.indexOf("=");
+ if (i >= 0) {
+#ifdef Q_OS_WIN
+ m_values.insert(s.left(i).toUpper(), s.mid(i+1));
+#else
+ m_values.insert(s.left(i), s.mid(i+1));
+#endif
+ }
+ }
+}
+
+QStringList Environment::toStringList() const
+{
+ QStringList result;
+ const QMap<QString, QString>::const_iterator end = m_values.constEnd();
+ for (QMap<QString, QString>::const_iterator it = m_values.constBegin(); it != end; ++it) {
+ QString entry = it.key();
+ entry += QLatin1Char('=');
+ entry += it.value();
+ result.push_back(entry);
+ }
+ return result;
+}
+
+void Environment::set(const QString &key, const QString &value)
+{
+#ifdef Q_OS_WIN
+ QString _key = key.toUpper();
+#else
+ const QString &_key = key;
+#endif
+ m_values.insert(_key, value);
+}
+
+void Environment::unset(const QString &key)
+{
+#ifdef Q_OS_WIN
+ QString _key = key.toUpper();
+#else
+ const QString &_key = key;
+#endif
+ m_values.remove(_key);
+}
+
+void Environment::appendOrSet(const QString &key, const QString &value, const QString &sep)
+{
+#ifdef Q_OS_WIN
+ QString _key = key.toUpper();
+#else
+ const QString &_key = key;
+#endif
+ QMap<QString, QString>::iterator it = m_values.find(key);
+ if (it == m_values.end()) {
+ m_values.insert(_key, value);
+ } else {
+ // Append unless it is already there
+ const QString toAppend = sep + value;
+ if (!it.value().endsWith(toAppend))
+ it.value().append(toAppend);
+ }
+}
+
+void Environment::prependOrSet(const QString&key, const QString &value, const QString &sep)
+{
+#ifdef Q_OS_WIN
+ QString _key = key.toUpper();
+#else
+ const QString &_key = key;
+#endif
+ QMap<QString, QString>::iterator it = m_values.find(key);
+ if (it == m_values.end()) {
+ m_values.insert(_key, value);
+ } else {
+ // Prepend unless it is already there
+ const QString toPrepend = value + sep;
+ if (!it.value().startsWith(toPrepend))
+ it.value().prepend(toPrepend);
+ }
+}
+
+void Environment::appendOrSetPath(const QString &value)
+{
+#ifdef Q_OS_WIN
+ const QChar sep = QLatin1Char(';');
+#else
+ const QChar sep = QLatin1Char(':');
+#endif
+ appendOrSet(QLatin1String("PATH"), QDir::toNativeSeparators(value), QString(sep));
+}
+
+void Environment::prependOrSetPath(const QString &value)
+{
+#ifdef Q_OS_WIN
+ const QChar sep = QLatin1Char(';');
+#else
+ const QChar sep = QLatin1Char(':');
+#endif
+ prependOrSet(QLatin1String("PATH"), QDir::toNativeSeparators(value), QString(sep));
+}
+
+Environment Environment::systemEnvironment()
+{
+ return Environment(QProcess::systemEnvironment());
+}
+
+void Environment::clear()
+{
+ m_values.clear();
+}
+
+QString Environment::searchInPath(QString executable) const
+{
+// qDebug()<<"looking for "<<executable<< "in PATH: "<<m_values.value("PATH");
+ if (executable.isEmpty())
+ return QString();
+ QFileInfo fi(executable);
+ if (fi.isAbsolute() && fi.exists())
+ return executable;
+#ifdef Q_OS_WIN
+ if (!executable.endsWith(QLatin1String(".exe")))
+ executable.append(QLatin1String(".exe"));
+#endif
+ const QChar slash = QLatin1Char('/');
+ foreach (const QString &p, path()) {
+// qDebug()<<"trying"<<p + '/' + executable;
+ QString fp = p;
+ fp += slash;
+ fp += executable;
+ const QFileInfo fi(fp);
+ if (fi.exists()) {
+// qDebug()<<"returning "<<fi.absoluteFilePath();
+ return fi.absoluteFilePath();
+ }
+ }
+ return QString();
+}
+
+QStringList Environment::path() const
+{
+#ifdef Q_OS_WIN
+ const QChar sep = QLatin1Char(';');
+#else
+ const QChar sep = QLatin1Char(':');
+#endif
+ return m_values.value(QLatin1String("PATH")).split(sep, QString::SkipEmptyParts);
+}
+
+QString Environment::value(const QString &key) const
+{
+ return m_values.value(key);
+}
+
+QString Environment::key(Environment::const_iterator it) const
+{
+ return it.key();
+}
+
+QString Environment::value(Environment::const_iterator it) const
+{
+ return it.value();
+}
+
+Environment::const_iterator Environment::constBegin() const
+{
+ return m_values.constBegin();
+}
+
+Environment::const_iterator Environment::constEnd() const
+{
+ return m_values.constEnd();
+}
+
+Environment::const_iterator Environment::find(const QString &name)
+{
+ QMap<QString, QString>::const_iterator it = m_values.constFind(name);
+ if (it == m_values.constEnd())
+ return constEnd();
+ else
+ return it;
+}
+
+int Environment::size() const
+{
+ return m_values.size();
+}
+
+void Environment::modify(const QList<EnvironmentItem> & list)
+{
+ Environment resultEnvironment = *this;
+ foreach (const EnvironmentItem &item, list) {
+ if (item.unset) {
+ resultEnvironment.unset(item.name);
+ } else {
+ // TODO use variable expansion
+ QString value = item.value;
+ for (int i=0; i < value.size(); ++i) {
+ if (value.at(i) == QLatin1Char('$')) {
+ if ((i + 1) < value.size()) {
+ const QChar &c = value.at(i+1);
+ int end = -1;
+ if (c == '(')
+ end = value.indexOf(')', i);
+ else if (c == '{')
+ end = value.indexOf('}', i);
+ if (end != -1) {
+ const QString &name = value.mid(i+2, end-i-2);
+ Environment::const_iterator it = find(name);
+ if (it != constEnd())
+ value.replace(i, end-i+1, it.value());
+ }
+ }
+ }
+ }
+ resultEnvironment.set(item.name, value);
+ }
+ }
+ *this = resultEnvironment;
+}
+
+bool Environment::hasKey(const QString &key)
+{
+ return m_values.contains(key);
+}
+
+bool Environment::operator!=(const Environment &other) const
+{
+ return !(*this == other);
+}
+
+bool Environment::operator==(const Environment &other) const
+{
+ return m_values == other.m_values;
+}
+
+QStringList Environment::parseCombinedArgString(const QString &program)
+{
+ QStringList args;
+ QString tmp;
+ int quoteCount = 0;
+ bool inQuote = false;
+
+ // handle quoting. tokens can be surrounded by double quotes
+ // "hello world". three consecutive double quotes represent
+ // the quote character itself.
+ for (int i = 0; i < program.size(); ++i) {
+ if (program.at(i) == QLatin1Char('"')) {
+ ++quoteCount;
+ if (quoteCount == 3) {
+ // third consecutive quote
+ quoteCount = 0;
+ tmp += program.at(i);
+ }
+ continue;
+ }
+ if (quoteCount) {
+ if (quoteCount == 1)
+ inQuote = !inQuote;
+ quoteCount = 0;
+ }
+ if (!inQuote && program.at(i).isSpace()) {
+ if (!tmp.isEmpty()) {
+ args += tmp;
+ tmp.clear();
+ }
+ } else {
+ tmp += program.at(i);
+ }
+ }
+ if (!tmp.isEmpty())
+ args += tmp;
+ return args;
+}
+
+QString Environment::joinArgumentList(const QStringList &arguments)
+{
+ QString result;
+ const QChar doubleQuote = QLatin1Char('"');
+ foreach (QString arg, arguments) {
+ if (!result.isEmpty())
+ result += QLatin1Char(' ');
+ arg.replace(QString(doubleQuote), QLatin1String("\"\"\""));
+ if (arg.contains(QLatin1Char(' '))) {
+ arg.insert(0, doubleQuote);
+ arg += doubleQuote;
+ }
+ result += arg;
+ }
+ return result;
+}
+
+enum State { BASE, VARIABLE, OPTIONALVARIABLEBRACE, STRING, STRING_ESCAPE, ESCAPE };
+
+/** Expand environment variables in a string.
+ *
+ * Environment variables are accepted in the following forms:
+ * $SOMEVAR, ${SOMEVAR} and %SOMEVAR%.
+ *
+ * The following escape sequences are supported:
+ * "\$", "\\" and "\"" which will be replaced by '$', '\' and '%'
+ * respectively.
+ *
+ * Strings enclosed in '"' characters do not get varaibles
+ * substituted. Escape codes are processed though.
+ *
+ */
+QString Environment::expandVariables(const QString &input) const
+{
+ QString result;
+ QString variable;
+ QChar endVariable;
+ State state = BASE;
+
+ int length = input.count();
+ for (int i = 0; i < length; ++i) {
+ QChar c = input.at(i);
+ if (state == BASE) {
+ if (c == '\\') {
+ state = ESCAPE;
+ } else if (c == '$') {
+ state = OPTIONALVARIABLEBRACE;
+ variable.clear();
+ endVariable = QChar(0);
+ } else if (c == '%') {
+ state = VARIABLE;
+ variable.clear();
+ endVariable = '%';
+ } else if (c == '\"') {
+ state = STRING;
+ result += c;
+ } else {
+ result += c;
+ }
+ } else if (state == VARIABLE) {
+ if (c == endVariable) {
+ result += value(variable);
+ state = BASE;
+ } else if (c.isLetterOrNumber() || c == '_') {
+ variable += c;
+ } else {
+ result += value(variable);
+ result += c;
+ state = BASE;
+ }
+ } else if (state == OPTIONALVARIABLEBRACE) {
+ if (c == '{')
+ endVariable = '}';
+ else
+ variable = c;
+ state = VARIABLE;
+ } else if (state == STRING) {
+ if (c == '\\') {
+ state = STRING_ESCAPE;
+ } else if (c == '\"') {
+ state = BASE;
+ result += c;
+ } else {
+ result += c;
+ }
+ } else if (state == STRING_ESCAPE) {
+ result += c;
+ state = STRING;
+ } else if (state == ESCAPE){
+ result += c;
+ state = BASE;
+ }
+ }
+ if (state == VARIABLE)
+ result += value(variable);
+ return result;
+}
diff --git a/src/libs/utils/environment.h b/src/libs/utils/environment.h
new file mode 100644
index 00000000000..1177c4dc1c1
--- /dev/null
+++ b/src/libs/utils/environment.h
@@ -0,0 +1,109 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation ([email protected])
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef UTILS_ENVIRONMENT_H
+#define UTILS_ENVIRONMENT_H
+
+#include "utils_global.h"
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QMap>
+#include <QtCore/QList>
+
+namespace Utils {
+
+class QTCREATOR_UTILS_EXPORT EnvironmentItem
+{
+public:
+ EnvironmentItem(QString n, QString v)
+ : name(n), value(v), unset(false)
+ {}
+
+ QString name;
+ QString value;
+ bool unset;
+
+ bool operator==(const EnvironmentItem &other)
+ {
+ return (unset == other.unset) && (name == other.name) && (value == other.value);
+ }
+
+ static QList<EnvironmentItem> fromStringList(QStringList list);
+ static QStringList toStringList(QList<EnvironmentItem> list);
+};
+
+class QTCREATOR_UTILS_EXPORT Environment {
+public:
+ typedef QMap<QString, QString>::const_iterator const_iterator;
+
+ Environment();
+ explicit Environment(QStringList env);
+ static Environment systemEnvironment();
+
+ QStringList toStringList() const;
+ QString value(const QString &key) const;
+ void set(const QString &key, const QString &value);
+ void unset(const QString &key);
+ void modify(const QList<EnvironmentItem> & list);
+ bool hasKey(const QString &key);
+
+ void appendOrSet(const QString &key, const QString &value, const QString &sep = QString());
+ void prependOrSet(const QString &key, const QString &value, const QString &sep = QString());
+
+ void appendOrSetPath(const QString &value);
+ void prependOrSetPath(const QString &value);
+
+ void clear();
+ int size() const;
+
+ Environment::const_iterator find(const QString &name);
+ QString key(Environment::const_iterator it) const;
+ QString value(Environment::const_iterator it) const;
+
+ Environment::const_iterator constBegin() const;
+ Environment::const_iterator constEnd() const;
+
+ QString searchInPath(QString executable) const;
+ QStringList path() const;
+
+ static QStringList parseCombinedArgString(const QString &program);
+ static QString joinArgumentList(const QStringList &arguments);
+
+ QString expandVariables(const QString &) const;
+
+ bool operator!=(const Environment &other) const;
+ bool operator==(const Environment &other) const;
+private:
+ QMap<QString, QString> m_values;
+};
+
+} // namespace Utils
+
+#endif // UTILS_ENVIRONMENT_H
diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri
index d338913edf3..bfae91f6345 100644
--- a/src/libs/utils/utils-lib.pri
+++ b/src/libs/utils/utils-lib.pri
@@ -6,7 +6,8 @@ dll {
INCLUDEPATH += $$PWD
-SOURCES += $$PWD/reloadpromptutils.cpp \
+SOURCES += $$PWD/environment.cpp \
+ $$PWD/reloadpromptutils.cpp \
$$PWD/stringutils.cpp \
$$PWD/filesearch.cpp \
$$PWD/pathchooser.cpp \
@@ -61,7 +62,8 @@ unix:!macx {
HEADERS += $$PWD/unixutils.h
SOURCES += $$PWD/unixutils.cpp
}
-HEADERS += $$PWD/utils_global.h \
+HEADERS += $$PWD/environment.h \
+ $$PWD/utils_global.h \
$$PWD/reloadpromptutils.h \
$$PWD/stringutils.h \
$$PWD/filesearch.h \