summaryrefslogtreecommitdiff
path: root/qmake/project.cpp
authorkergoth <kergoth>2002-11-05 16:40:27 (UTC)
committer kergoth <kergoth>2002-11-05 16:40:27 (UTC)
commitcf2ae9bf818d7cdddc56a3d6eea21ded4e815b68 (patch) (unidiff)
treed350f2f3138707f3f701444a0e72218b744c5df2 /qmake/project.cpp
parentd590a056fde3eb4ad37ecd202ea024a9ad110106 (diff)
downloadopie-cf2ae9bf818d7cdddc56a3d6eea21ded4e815b68.zip
opie-cf2ae9bf818d7cdddc56a3d6eea21ded4e815b68.tar.gz
opie-cf2ae9bf818d7cdddc56a3d6eea21ded4e815b68.tar.bz2
er, it was prioritizing QMAKESPECSDIR above QMAKESPEC.. fixed
Diffstat (limited to 'qmake/project.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--qmake/project.cpp2
1 files changed, 1 insertions, 1 deletions
diff --git a/qmake/project.cpp b/qmake/project.cpp
index 96cdad8..44eb503 100644
--- a/qmake/project.cpp
+++ b/qmake/project.cpp
@@ -1,994 +1,994 @@
1/**************************************************************************** 1/****************************************************************************
2** $Id$ 2** $Id$
3** 3**
4** Definition of ________ class. 4** Definition of ________ class.
5** 5**
6** Created : 970521 6** Created : 970521
7** 7**
8** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. 8** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
9** 9**
10** This file is part of the network module of the Qt GUI Toolkit. 10** This file is part of the network module of the Qt GUI Toolkit.
11** 11**
12** This file may be distributed under the terms of the Q Public License 12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file 13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file. 14** LICENSE.QPL included in the packaging of this file.
15** 15**
16** This file may be distributed and/or modified under the terms of the 16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software 17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the 18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file. 19** packaging of this file.
20** 20**
21** Licensees holding valid Qt Enterprise Edition licenses may use this 21** Licensees holding valid Qt Enterprise Edition licenses may use this
22** file in accordance with the Qt Commercial License Agreement provided 22** file in accordance with the Qt Commercial License Agreement provided
23** with the Software. 23** with the Software.
24** 24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27** 27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for 28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements. 29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information. 30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information. 31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32** 32**
33** Contact info@trolltech.com if any conditions of this licensing are 33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you. 34** not clear to you.
35** 35**
36**********************************************************************/ 36**********************************************************************/
37 37
38#include "project.h" 38#include "project.h"
39#include "option.h" 39#include "option.h"
40#include <qfile.h> 40#include <qfile.h>
41#include <qdir.h> 41#include <qdir.h>
42#include <qregexp.h> 42#include <qregexp.h>
43#include <qtextstream.h> 43#include <qtextstream.h>
44#include <qvaluestack.h> 44#include <qvaluestack.h>
45#ifdef Q_OS_UNIX 45#ifdef Q_OS_UNIX
46# include <unistd.h> 46# include <unistd.h>
47#endif 47#endif
48#include <stdio.h> 48#include <stdio.h>
49#include <stdlib.h> 49#include <stdlib.h>
50 50
51#ifdef Q_OS_WIN32 51#ifdef Q_OS_WIN32
52#define QT_POPEN _popen 52#define QT_POPEN _popen
53#else 53#else
54#define QT_POPEN popen 54#define QT_POPEN popen
55#endif 55#endif
56 56
57struct parser_info { 57struct parser_info {
58 QString file; 58 QString file;
59 int line_no; 59 int line_no;
60} parser; 60} parser;
61static void qmake_error_msg(const char *msg) 61static void qmake_error_msg(const char *msg)
62{ 62{
63 fprintf(stderr, "%s:%d: %s\n", parser.file.latin1(), parser.line_no, msg); 63 fprintf(stderr, "%s:%d: %s\n", parser.file.latin1(), parser.line_no, msg);
64} 64}
65 65
66static QString varMap(const QString &x) 66static QString varMap(const QString &x)
67{ 67{
68 QString ret(x); 68 QString ret(x);
69 ret.replace(QRegExp("^TMAKE"), "QMAKE"); 69 ret.replace(QRegExp("^TMAKE"), "QMAKE");
70 if(ret == "INTERFACES") 70 if(ret == "INTERFACES")
71 ret = "FORMS"; 71 ret = "FORMS";
72 return ret; 72 return ret;
73} 73}
74 74
75static QStringList split_arg_list(const QString &params) 75static QStringList split_arg_list(const QString &params)
76{ 76{
77 QStringList args; 77 QStringList args;
78 int last = 0, parens = 0; 78 int last = 0, parens = 0;
79 QChar quote = 0; 79 QChar quote = 0;
80 for(int x = 0; x < (int)params.length(); x++) { 80 for(int x = 0; x < (int)params.length(); x++) {
81 if(params[x] == ')') { 81 if(params[x] == ')') {
82 parens--; 82 parens--;
83 } else if(params[x] == '(') { 83 } else if(params[x] == '(') {
84 parens++; 84 parens++;
85 } else if(params[x] == quote) { 85 } else if(params[x] == quote) {
86 quote = 0; 86 quote = 0;
87 } else if(params[x] == '\'' || params[x] == '"') { 87 } else if(params[x] == '\'' || params[x] == '"') {
88 quote = params[x]; 88 quote = params[x];
89 } else if(!parens && !quote && params[x] == ',') { 89 } else if(!parens && !quote && params[x] == ',') {
90 args << params.mid(last, x - last); 90 args << params.mid(last, x - last);
91 last = x+1; 91 last = x+1;
92 } 92 }
93 } 93 }
94 if(last != (int)params.length()) 94 if(last != (int)params.length())
95 args << params.mid(last); 95 args << params.mid(last);
96 return args; 96 return args;
97} 97}
98 98
99static QStringList split_value_list(const QString &vals, bool do_semicolon=FALSE) 99static QStringList split_value_list(const QString &vals, bool do_semicolon=FALSE)
100{ 100{
101 int last = 0; 101 int last = 0;
102 QStringList ret; 102 QStringList ret;
103 QValueStack<QChar> quote; 103 QValueStack<QChar> quote;
104 for(int x = 0; x < (int)vals.length(); x++) { 104 for(int x = 0; x < (int)vals.length(); x++) {
105 if(!quote.isEmpty() && vals[x] == quote.top()) { 105 if(!quote.isEmpty() && vals[x] == quote.top()) {
106 quote.pop(); 106 quote.pop();
107 } else if(vals[x] == '\'' || vals[x] == '"') { 107 } else if(vals[x] == '\'' || vals[x] == '"') {
108 quote.push(vals[x]); 108 quote.push(vals[x]);
109 } else if(quote.isEmpty() && 109 } else if(quote.isEmpty() &&
110 ((do_semicolon && vals[x] == ';') || vals[x] == ' ')) { 110 ((do_semicolon && vals[x] == ';') || vals[x] == ' ')) {
111 ret << vals.mid(last, x - last); 111 ret << vals.mid(last, x - last);
112 last = x+1; 112 last = x+1;
113 } 113 }
114 } 114 }
115 if(last != (int)vals.length()) 115 if(last != (int)vals.length())
116 ret << vals.mid(last); 116 ret << vals.mid(last);
117 return ret; 117 return ret;
118} 118}
119 119
120QMakeProject::QMakeProject() 120QMakeProject::QMakeProject()
121{ 121{
122} 122}
123 123
124bool 124bool
125QMakeProject::parse(QString t, QMap<QString, QStringList> &place) 125QMakeProject::parse(QString t, QMap<QString, QStringList> &place)
126{ 126{
127 QString s = t.simplifyWhiteSpace(); 127 QString s = t.simplifyWhiteSpace();
128 s.replace(QRegExp("#.*$"), ""); /* bye comments */ 128 s.replace(QRegExp("#.*$"), ""); /* bye comments */
129 if(s.isEmpty()) /* blank_line */ 129 if(s.isEmpty()) /* blank_line */
130 return TRUE; 130 return TRUE;
131 131
132 if(s.stripWhiteSpace().left(1) == "}") { 132 if(s.stripWhiteSpace().left(1) == "}") {
133 debug_msg(1, "Project Parser: %s:%d : Leaving block %d", parser.file.latin1(), 133 debug_msg(1, "Project Parser: %s:%d : Leaving block %d", parser.file.latin1(),
134 parser.line_no, scope_block); 134 parser.line_no, scope_block);
135 test_status = ((scope_flag & (0x01 << scope_block)) ? TestFound : TestSeek); 135 test_status = ((scope_flag & (0x01 << scope_block)) ? TestFound : TestSeek);
136 scope_block--; 136 scope_block--;
137 s = s.mid(1).stripWhiteSpace(); 137 s = s.mid(1).stripWhiteSpace();
138 if(s.isEmpty()) 138 if(s.isEmpty())
139 return TRUE; 139 return TRUE;
140 } 140 }
141 if(!(scope_flag & (0x01 << scope_block))) { 141 if(!(scope_flag & (0x01 << scope_block))) {
142 /* adjust scope for each block which appears on a single line */ 142 /* adjust scope for each block which appears on a single line */
143 for(int i = (s.contains('{')-s.contains('}')); i; i--) 143 for(int i = (s.contains('{')-s.contains('}')); i; i--)
144 scope_flag &= ~(0x01 << (++scope_block)); 144 scope_flag &= ~(0x01 << (++scope_block));
145 debug_msg(1, "Project Parser: %s:%d : Ignored due to block being false.", 145 debug_msg(1, "Project Parser: %s:%d : Ignored due to block being false.",
146 parser.file.latin1(), parser.line_no); 146 parser.file.latin1(), parser.line_no);
147 return TRUE; 147 return TRUE;
148 } 148 }
149 149
150 QString scope, var, op; 150 QString scope, var, op;
151 QStringList val; 151 QStringList val;
152#define SKIP_WS(d) while(*d && (*d == ' ' || *d == '\t')) d++ 152#define SKIP_WS(d) while(*d && (*d == ' ' || *d == '\t')) d++
153 const char *d = s.latin1(); 153 const char *d = s.latin1();
154 SKIP_WS(d); 154 SKIP_WS(d);
155 bool scope_failed = FALSE, else_line = FALSE, or_op=FALSE; 155 bool scope_failed = FALSE, else_line = FALSE, or_op=FALSE;
156 int parens = 0, scope_count=0; 156 int parens = 0, scope_count=0;
157 while(*d && *d != '=') { 157 while(*d && *d != '=') {
158 if((*d == '+' || *d == '-' || *d == '*' || *d == '~')) { 158 if((*d == '+' || *d == '-' || *d == '*' || *d == '~')) {
159 if(*(d+1) == '=') { 159 if(*(d+1) == '=') {
160 break; 160 break;
161 } else if(*(d+1) == ' ') { 161 } else if(*(d+1) == ' ') {
162 const char *k = d + 1; 162 const char *k = d + 1;
163 SKIP_WS(k); 163 SKIP_WS(k);
164 if(*k == '=') { 164 if(*k == '=') {
165 QString msg; 165 QString msg;
166 qmake_error_msg(*d + "must be followed immediatly by ="); 166 qmake_error_msg(*d + "must be followed immediatly by =");
167 return FALSE; 167 return FALSE;
168 } 168 }
169 } 169 }
170 } 170 }
171 171
172 if ( *d == '(' ) 172 if ( *d == '(' )
173 ++parens; 173 ++parens;
174 else if ( *d == ')' ) 174 else if ( *d == ')' )
175 --parens; 175 --parens;
176 176
177 if(!parens && (*d == ':' || *d == '{' || *d == ')' || *d == '|')) { 177 if(!parens && (*d == ':' || *d == '{' || *d == ')' || *d == '|')) {
178 scope_count++; 178 scope_count++;
179 scope = var.stripWhiteSpace(); 179 scope = var.stripWhiteSpace();
180 if ( *d == ')' ) 180 if ( *d == ')' )
181 scope += *d; /* need this */ 181 scope += *d; /* need this */
182 var = ""; 182 var = "";
183 183
184 bool test = scope_failed; 184 bool test = scope_failed;
185 if(scope.lower() == "else") { 185 if(scope.lower() == "else") {
186 if(scope_count != 1 || test_status == TestNone) { 186 if(scope_count != 1 || test_status == TestNone) {
187 qmake_error_msg("Unexpected " + scope + " ('" + s + "')"); 187 qmake_error_msg("Unexpected " + scope + " ('" + s + "')");
188 return FALSE; 188 return FALSE;
189 } 189 }
190 else_line = TRUE; 190 else_line = TRUE;
191 test = (test_status == TestSeek); 191 test = (test_status == TestSeek);
192 debug_msg(1, "Project Parser: %s:%d : Else%s %s.", parser.file.latin1(), parser.line_no, 192 debug_msg(1, "Project Parser: %s:%d : Else%s %s.", parser.file.latin1(), parser.line_no,
193 scope == "else" ? "" : QString(" (" + scope + ")").latin1(), 193 scope == "else" ? "" : QString(" (" + scope + ")").latin1(),
194 test ? "considered" : "excluded"); 194 test ? "considered" : "excluded");
195 } else { 195 } else {
196 QString comp_scope = scope; 196 QString comp_scope = scope;
197 bool invert_test = (comp_scope.left(1) == "!"); 197 bool invert_test = (comp_scope.left(1) == "!");
198 if(invert_test) 198 if(invert_test)
199 comp_scope = comp_scope.right(comp_scope.length()-1); 199 comp_scope = comp_scope.right(comp_scope.length()-1);
200 int lparen = comp_scope.find('('); 200 int lparen = comp_scope.find('(');
201 if(or_op || !scope_failed) { 201 if(or_op || !scope_failed) {
202 if(lparen != -1) { /* if there is an lparen in the scope, it IS a function */ 202 if(lparen != -1) { /* if there is an lparen in the scope, it IS a function */
203 int rparen = comp_scope.findRev(')'); 203 int rparen = comp_scope.findRev(')');
204 if(rparen == -1) { 204 if(rparen == -1) {
205 QCString error; 205 QCString error;
206 error.sprintf("Function missing right paren: %s ('%s')", 206 error.sprintf("Function missing right paren: %s ('%s')",
207 comp_scope.latin1(), s.latin1()); 207 comp_scope.latin1(), s.latin1());
208 qmake_error_msg(error); 208 qmake_error_msg(error);
209 return FALSE; 209 return FALSE;
210 } 210 }
211 QString func = comp_scope.left(lparen); 211 QString func = comp_scope.left(lparen);
212 test = doProjectTest(func, comp_scope.mid(lparen+1, rparen - lparen - 1), place); 212 test = doProjectTest(func, comp_scope.mid(lparen+1, rparen - lparen - 1), place);
213 if ( *d == ')' && !*(d+1) ) { 213 if ( *d == ')' && !*(d+1) ) {
214 if(invert_test) 214 if(invert_test)
215 test = !test; 215 test = !test;
216 test_status = (test ? TestFound : TestSeek); 216 test_status = (test ? TestFound : TestSeek);
217 return TRUE; /* assume we are done */ 217 return TRUE; /* assume we are done */
218 } 218 }
219 } else { 219 } else {
220 test = isActiveConfig(comp_scope.stripWhiteSpace()); 220 test = isActiveConfig(comp_scope.stripWhiteSpace());
221 } 221 }
222 if(invert_test) 222 if(invert_test)
223 test = !test; 223 test = !test;
224 } 224 }
225 } 225 }
226 if(!test && !scope_failed) 226 if(!test && !scope_failed)
227 debug_msg(1, "Project Parser: %s:%d : Test (%s) failed.", parser.file.latin1(), 227 debug_msg(1, "Project Parser: %s:%d : Test (%s) failed.", parser.file.latin1(),
228 parser.line_no, scope.latin1()); 228 parser.line_no, scope.latin1());
229 if(test == or_op) 229 if(test == or_op)
230 scope_failed = !test; 230 scope_failed = !test;
231 or_op = (*d == '|'); 231 or_op = (*d == '|');
232 if(*d == '{') { /* scoping block */ 232 if(*d == '{') { /* scoping block */
233 if(!scope_failed) 233 if(!scope_failed)
234 scope_flag |= (0x01 << (++scope_block)); 234 scope_flag |= (0x01 << (++scope_block));
235 else 235 else
236 scope_flag &= ~(0x01 << (++scope_block)); 236 scope_flag &= ~(0x01 << (++scope_block));
237 debug_msg(1, "Project Parser: %s:%d : Entering block %d (%d).", parser.file.latin1(), 237 debug_msg(1, "Project Parser: %s:%d : Entering block %d (%d).", parser.file.latin1(),
238 parser.line_no, scope_block, !scope_failed); 238 parser.line_no, scope_block, !scope_failed);
239 } 239 }
240 } else { 240 } else {
241 var += *d; 241 var += *d;
242 } 242 }
243 d++; 243 d++;
244 } 244 }
245 if(!scope_count || (scope_count == 1 && else_line)) 245 if(!scope_count || (scope_count == 1 && else_line))
246 test_status = TestNone; 246 test_status = TestNone;
247 else if(!else_line || test_status != TestFound) 247 else if(!else_line || test_status != TestFound)
248 test_status = (scope_failed ? TestSeek : TestFound); 248 test_status = (scope_failed ? TestSeek : TestFound);
249 if(scope_failed) 249 if(scope_failed)
250 return TRUE; /* oh well */ 250 return TRUE; /* oh well */
251 if(!*d) { 251 if(!*d) {
252 if(!var.isEmpty()) 252 if(!var.isEmpty())
253 qmake_error_msg("Parse Error ('" + s + "')"); 253 qmake_error_msg("Parse Error ('" + s + "')");
254 return var.isEmpty(); /* allow just a scope */ 254 return var.isEmpty(); /* allow just a scope */
255 } 255 }
256 256
257 SKIP_WS(d); 257 SKIP_WS(d);
258 for( ; *d && op.find('=') == -1; op += *(d++)); 258 for( ; *d && op.find('=') == -1; op += *(d++));
259 op.replace(QRegExp("\\s"), ""); 259 op.replace(QRegExp("\\s"), "");
260 260
261 SKIP_WS(d); 261 SKIP_WS(d);
262 QString vals(d); /* vals now contains the space separated list of values */ 262 QString vals(d); /* vals now contains the space separated list of values */
263 int rbraces = vals.contains('}'), lbraces = vals.contains('{'); 263 int rbraces = vals.contains('}'), lbraces = vals.contains('{');
264 if(scope_block && rbraces - lbraces == 1) { 264 if(scope_block && rbraces - lbraces == 1) {
265 debug_msg(1, "Project Parser: %s:%d : Leaving block %d", parser.file.latin1(), 265 debug_msg(1, "Project Parser: %s:%d : Leaving block %d", parser.file.latin1(),
266 parser.line_no, scope_block); 266 parser.line_no, scope_block);
267 test_status = ((scope_flag & (0x01 << scope_block)) ? TestFound : TestSeek); 267 test_status = ((scope_flag & (0x01 << scope_block)) ? TestFound : TestSeek);
268 scope_block--; 268 scope_block--;
269 vals.truncate(vals.length()-1); 269 vals.truncate(vals.length()-1);
270 } else if(rbraces != lbraces) { 270 } else if(rbraces != lbraces) {
271 warn_msg(WarnParser, "Possible braces mismatch {%s} %s:%d", 271 warn_msg(WarnParser, "Possible braces mismatch {%s} %s:%d",
272 vals.latin1(), parser.file.latin1(), parser.line_no); 272 vals.latin1(), parser.file.latin1(), parser.line_no);
273 } 273 }
274 doVariableReplace(vals, place); 274 doVariableReplace(vals, place);
275 275
276 var = var.stripWhiteSpace(); 276 var = var.stripWhiteSpace();
277#undef SKIP_WS 277#undef SKIP_WS
278 278
279 if(!var.isEmpty() && Option::mkfile::do_preprocess) { 279 if(!var.isEmpty() && Option::mkfile::do_preprocess) {
280 static QString last_file("*none*"); 280 static QString last_file("*none*");
281 if(parser.file != last_file) { 281 if(parser.file != last_file) {
282 fprintf(stderr, "#file %s:%d\n", parser.file.latin1(), parser.line_no); 282 fprintf(stderr, "#file %s:%d\n", parser.file.latin1(), parser.line_no);
283 last_file = parser.file; 283 last_file = parser.file;
284 } 284 }
285 fprintf(stderr, "%s %s %s\n", var.latin1(), op.latin1(), vals.latin1()); 285 fprintf(stderr, "%s %s %s\n", var.latin1(), op.latin1(), vals.latin1());
286 } 286 }
287 var = varMap(var); //backwards compatability 287 var = varMap(var); //backwards compatability
288 288
289 /* vallist is the broken up list of values */ 289 /* vallist is the broken up list of values */
290 QStringList vallist = split_value_list(vals, (var == "DEPENDPATH" || var == "INCLUDEPATH")); 290 QStringList vallist = split_value_list(vals, (var == "DEPENDPATH" || var == "INCLUDEPATH"));
291 if(!vallist.grep("=").isEmpty()) 291 if(!vallist.grep("=").isEmpty())
292 warn_msg(WarnParser, "Detected possible line continuation: {%s} %s:%d", 292 warn_msg(WarnParser, "Detected possible line continuation: {%s} %s:%d",
293 var.latin1(), parser.file.latin1(), parser.line_no); 293 var.latin1(), parser.file.latin1(), parser.line_no);
294 294
295 QStringList &varlist = place[var]; /* varlist is the list in the symbol table */ 295 QStringList &varlist = place[var]; /* varlist is the list in the symbol table */
296 debug_msg(1, "Project Parser: %s:%d :%s: :%s: (%s)", parser.file.latin1(), parser.line_no, 296 debug_msg(1, "Project Parser: %s:%d :%s: :%s: (%s)", parser.file.latin1(), parser.line_no,
297 var.latin1(), op.latin1(), vallist.join(" :: ").latin1()); 297 var.latin1(), op.latin1(), vallist.join(" :: ").latin1());
298 298
299 /* now do the operation */ 299 /* now do the operation */
300 if(op == "~=") { 300 if(op == "~=") {
301 if(vallist.count() != 1) { 301 if(vallist.count() != 1) {
302 qmake_error_msg("~= operator only accepts one right hand paramater ('" + 302 qmake_error_msg("~= operator only accepts one right hand paramater ('" +
303 s + "')"); 303 s + "')");
304 return FALSE; 304 return FALSE;
305 } 305 }
306 QString val(vallist.first()); 306 QString val(vallist.first());
307 if(val.length() < 4 || val.at(0) != 's') { 307 if(val.length() < 4 || val.at(0) != 's') {
308 qmake_error_msg("~= operator only can handle s/// function ('" + 308 qmake_error_msg("~= operator only can handle s/// function ('" +
309 s + "')"); 309 s + "')");
310 return FALSE; 310 return FALSE;
311 } 311 }
312 QChar sep = val.at(1); 312 QChar sep = val.at(1);
313 QStringList func = QStringList::split(sep, val, TRUE); 313 QStringList func = QStringList::split(sep, val, TRUE);
314 if(func.count() < 3 || func.count() > 4) { 314 if(func.count() < 3 || func.count() > 4) {
315 qmake_error_msg("~= operator only can handle s/// function ('" + 315 qmake_error_msg("~= operator only can handle s/// function ('" +
316 s + "')"); 316 s + "')");
317 return FALSE; 317 return FALSE;
318 } 318 }
319 bool global = FALSE, case_sense = TRUE; 319 bool global = FALSE, case_sense = TRUE;
320 if(func.count() == 4) { 320 if(func.count() == 4) {
321 global = func[3].find('g') != -1; 321 global = func[3].find('g') != -1;
322 case_sense = func[3].find('i') == -1; 322 case_sense = func[3].find('i') == -1;
323 } 323 }
324 QRegExp regexp(func[1], case_sense); 324 QRegExp regexp(func[1], case_sense);
325 for(QStringList::Iterator varit = varlist.begin(); 325 for(QStringList::Iterator varit = varlist.begin();
326 varit != varlist.end(); ++varit) { 326 varit != varlist.end(); ++varit) {
327 if((*varit).contains(regexp)) { 327 if((*varit).contains(regexp)) {
328 (*varit) = (*varit).replace(regexp, func[2]); 328 (*varit) = (*varit).replace(regexp, func[2]);
329 if(!global) 329 if(!global)
330 break; 330 break;
331 } 331 }
332 } 332 }
333 } else { 333 } else {
334 if(op == "=") { 334 if(op == "=") {
335 if(!varlist.isEmpty()) 335 if(!varlist.isEmpty())
336 warn_msg(WarnParser, "Operator=(%s) clears variables previously set: %s:%d", 336 warn_msg(WarnParser, "Operator=(%s) clears variables previously set: %s:%d",
337 var.latin1(), parser.file.latin1(), parser.line_no); 337 var.latin1(), parser.file.latin1(), parser.line_no);
338 varlist.clear(); 338 varlist.clear();
339 } 339 }
340 for(QStringList::Iterator valit = vallist.begin(); 340 for(QStringList::Iterator valit = vallist.begin();
341 valit != vallist.end(); ++valit) { 341 valit != vallist.end(); ++valit) {
342 if((*valit).isEmpty()) 342 if((*valit).isEmpty())
343 continue; 343 continue;
344 if((op == "*=" && !(*varlist.find((*valit)))) || 344 if((op == "*=" && !(*varlist.find((*valit)))) ||
345 op == "=" || op == "+=") 345 op == "=" || op == "+=")
346 varlist.append((*valit)); 346 varlist.append((*valit));
347 else if(op == "-=") 347 else if(op == "-=")
348 varlist.remove((*valit)); 348 varlist.remove((*valit));
349 } 349 }
350 } 350 }
351 if(var == "REQUIRES") /* special case to get communicated to backends! */ 351 if(var == "REQUIRES") /* special case to get communicated to backends! */
352 doProjectCheckReqs(vallist, place); 352 doProjectCheckReqs(vallist, place);
353 353
354 return TRUE; 354 return TRUE;
355} 355}
356 356
357bool 357bool
358QMakeProject::read(QString file, QMap<QString, QStringList> &place) 358QMakeProject::read(QString file, QMap<QString, QStringList> &place)
359{ 359{
360 parser_info pi = parser; 360 parser_info pi = parser;
361 /* scope blocks start at true */ 361 /* scope blocks start at true */
362 test_status = TestNone; 362 test_status = TestNone;
363 scope_flag = 0x01; 363 scope_flag = 0x01;
364 scope_block = 0; 364 scope_block = 0;
365 365
366 file = Option::fixPathToLocalOS(file); 366 file = Option::fixPathToLocalOS(file);
367 doVariableReplace(file, place); 367 doVariableReplace(file, place);
368 bool ret = FALSE, using_stdin = FALSE; 368 bool ret = FALSE, using_stdin = FALSE;
369 QFile qfile; 369 QFile qfile;
370 if(!strcmp(file, "-")) { 370 if(!strcmp(file, "-")) {
371 qfile.setName(""); 371 qfile.setName("");
372 ret = qfile.open(IO_ReadOnly, stdin); 372 ret = qfile.open(IO_ReadOnly, stdin);
373 using_stdin = TRUE; 373 using_stdin = TRUE;
374 } else { 374 } else {
375 qfile.setName(file); 375 qfile.setName(file);
376 ret = qfile.open(IO_ReadOnly); 376 ret = qfile.open(IO_ReadOnly);
377 } 377 }
378 if ( ret ) { 378 if ( ret ) {
379 QTextStream t( &qfile ); 379 QTextStream t( &qfile );
380 QString s, line; 380 QString s, line;
381 parser.file = file; 381 parser.file = file;
382 parser.line_no = 0; 382 parser.line_no = 0;
383 while ( !t.eof() ) { 383 while ( !t.eof() ) {
384 parser.line_no++; 384 parser.line_no++;
385 line = t.readLine().stripWhiteSpace(); 385 line = t.readLine().stripWhiteSpace();
386 int prelen = line.length(); 386 int prelen = line.length();
387 line.replace(QRegExp("#.*$"), ""); // bye comments 387 line.replace(QRegExp("#.*$"), ""); // bye comments
388 if(!line.isEmpty() && line.right(1) == "\\") { 388 if(!line.isEmpty() && line.right(1) == "\\") {
389 line.truncate(line.length() - 1); 389 line.truncate(line.length() - 1);
390 s += line + " "; 390 s += line + " ";
391 } else if(!line.isEmpty() || (line.isEmpty() && !prelen)) { 391 } else if(!line.isEmpty() || (line.isEmpty() && !prelen)) {
392 if(s.isEmpty() && line.isEmpty()) 392 if(s.isEmpty() && line.isEmpty())
393 continue; 393 continue;
394 if(!line.isEmpty()) 394 if(!line.isEmpty())
395 s += line; 395 s += line;
396 if(!s.isEmpty()) { 396 if(!s.isEmpty()) {
397 if(!(ret = parse(s, place))) 397 if(!(ret = parse(s, place)))
398 break; 398 break;
399 s = ""; 399 s = "";
400 } 400 }
401 } 401 }
402 } 402 }
403 if(!using_stdin) 403 if(!using_stdin)
404 qfile.close(); 404 qfile.close();
405 } 405 }
406 parser = pi; 406 parser = pi;
407 return ret; 407 return ret;
408} 408}
409 409
410bool 410bool
411QMakeProject::read(QString project, QString) 411QMakeProject::read(QString project, QString)
412{ 412{
413 if(cfile.isEmpty()) { 413 if(cfile.isEmpty()) {
414 // hack to get the Option stuff in there 414 // hack to get the Option stuff in there
415 base_vars["QMAKE_EXT_CPP"] = Option::cpp_ext; 415 base_vars["QMAKE_EXT_CPP"] = Option::cpp_ext;
416 base_vars["QMAKE_EXT_H"] = Option::h_ext; 416 base_vars["QMAKE_EXT_H"] = Option::h_ext;
417 417
418 /* parse the cache */ 418 /* parse the cache */
419 if(Option::mkfile::do_cache) { 419 if(Option::mkfile::do_cache) {
420 if(Option::mkfile::cachefile.isEmpty()) { //find it as it has not been specified 420 if(Option::mkfile::cachefile.isEmpty()) { //find it as it has not been specified
421 QString dir = QDir::convertSeparators(Option::output_dir); 421 QString dir = QDir::convertSeparators(Option::output_dir);
422 while(!QFile::exists((Option::mkfile::cachefile = dir + 422 while(!QFile::exists((Option::mkfile::cachefile = dir +
423 QDir::separator() + ".qmake.cache"))) { 423 QDir::separator() + ".qmake.cache"))) {
424 dir = dir.left(dir.findRev(QDir::separator())); 424 dir = dir.left(dir.findRev(QDir::separator()));
425 if(dir.isEmpty() || dir.find(QDir::separator()) == -1) { 425 if(dir.isEmpty() || dir.find(QDir::separator()) == -1) {
426 Option::mkfile::cachefile = ""; 426 Option::mkfile::cachefile = "";
427 break; 427 break;
428 } 428 }
429 if(Option::mkfile::cachefile_depth == -1) 429 if(Option::mkfile::cachefile_depth == -1)
430 Option::mkfile::cachefile_depth = 1; 430 Option::mkfile::cachefile_depth = 1;
431 else 431 else
432 Option::mkfile::cachefile_depth++; 432 Option::mkfile::cachefile_depth++;
433 } 433 }
434 } 434 }
435 if(!Option::mkfile::cachefile.isEmpty()) { 435 if(!Option::mkfile::cachefile.isEmpty()) {
436 read(Option::mkfile::cachefile, cache); 436 read(Option::mkfile::cachefile, cache);
437 if(Option::mkfile::qmakespec.isEmpty() && !cache["QMAKESPEC"].isEmpty()) 437 if(Option::mkfile::qmakespec.isEmpty() && !cache["QMAKESPEC"].isEmpty())
438 Option::mkfile::qmakespec = cache["QMAKESPEC"].first(); 438 Option::mkfile::qmakespec = cache["QMAKESPEC"].first();
439 } 439 }
440 } 440 }
441 /* parse mkspec */ 441 /* parse mkspec */
442 QStringList mkspec_roots; 442 QStringList mkspec_roots;
443 /* prefer $QTDIR if it is set */ 443 /* prefer $QTDIR if it is set */
444 /* prefer QMAKESPECSDIR -cl */ 444 /* prefer QMAKESPECSDIR -cl */
445 445
446 if (getenv("QTDIR")) { 446 if (getenv("QTDIR")) {
447 mkspec_roots << getenv("QTDIR"); 447 mkspec_roots << getenv("QTDIR");
448 } 448 }
449 mkspec_roots << qInstallPathData(); 449 mkspec_roots << qInstallPathData();
450 450
451 if (getenv("QMAKESPECSDIR")){ 451 if (Option::mkfile::qmakespec.isEmpty() && getenv("QMAKESPECSDIR")){
452 QString mkspec = QString(getenv("QMAKESPECSDIR")) + QDir::separator() + 452 QString mkspec = QString(getenv("QMAKESPECSDIR")) + QDir::separator() +
453 QDir::separator() + "default"; 453 QDir::separator() + "default";
454 if(QFile::exists(mkspec)) 454 if(QFile::exists(mkspec))
455 Option::mkfile::qmakespec = mkspec; 455 Option::mkfile::qmakespec = mkspec;
456 } 456 }
457 457
458 if(Option::mkfile::qmakespec.isEmpty()) { 458 if(Option::mkfile::qmakespec.isEmpty()) {
459 for(QStringList::Iterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { 459 for(QStringList::Iterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) {
460 QString mkspec = (*it) + QDir::separator() + QString("mkspecs") + 460 QString mkspec = (*it) + QDir::separator() + QString("mkspecs") +
461 QDir::separator() + "default"; 461 QDir::separator() + "default";
462 if(QFile::exists(mkspec)) { 462 if(QFile::exists(mkspec)) {
463 Option::mkfile::qmakespec = mkspec; 463 Option::mkfile::qmakespec = mkspec;
464 break; 464 break;
465 } 465 }
466 } 466 }
467 } 467 }
468 468
469 if(Option::mkfile::qmakespec.isEmpty()) { 469 if(Option::mkfile::qmakespec.isEmpty()) {
470 fprintf(stderr, "QMAKESPEC has not been set, so configuration cannot be deduced.\n"); 470 fprintf(stderr, "QMAKESPEC has not been set, so configuration cannot be deduced.\n");
471 return FALSE; 471 return FALSE;
472 } 472 }
473 473
474 if(QDir::isRelativePath(Option::mkfile::qmakespec)) { 474 if(QDir::isRelativePath(Option::mkfile::qmakespec)) {
475 bool found_mkspec = FALSE; 475 bool found_mkspec = FALSE;
476 for(QStringList::Iterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { 476 for(QStringList::Iterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) {
477 QString mkspec = (*it) + QDir::separator() + QString("mkspecs") + 477 QString mkspec = (*it) + QDir::separator() + QString("mkspecs") +
478 QDir::separator() + Option::mkfile::qmakespec; 478 QDir::separator() + Option::mkfile::qmakespec;
479 if(QFile::exists(mkspec)) { 479 if(QFile::exists(mkspec)) {
480 found_mkspec = TRUE; 480 found_mkspec = TRUE;
481 Option::mkfile::qmakespec = mkspec; 481 Option::mkfile::qmakespec = mkspec;
482 break; 482 break;
483 } 483 }
484 } 484 }
485 if(!found_mkspec) { 485 if(!found_mkspec) {
486 fprintf(stderr, "Could not find mkspecs for your QMAKESPEC after trying:\n\t%s\n", 486 fprintf(stderr, "Could not find mkspecs for your QMAKESPEC after trying:\n\t%s\n",
487 mkspec_roots.join("\n\t").latin1()); 487 mkspec_roots.join("\n\t").latin1());
488 return FALSE; 488 return FALSE;
489 } 489 }
490 } 490 }
491 491
492 /* parse qmake configuration */ 492 /* parse qmake configuration */
493 QString spec = Option::mkfile::qmakespec + QDir::separator() + "qmake.conf"; 493 QString spec = Option::mkfile::qmakespec + QDir::separator() + "qmake.conf";
494 debug_msg(1, "QMAKESPEC conf: reading %s", spec.latin1()); 494 debug_msg(1, "QMAKESPEC conf: reading %s", spec.latin1());
495 if(!read(spec, base_vars)) { 495 if(!read(spec, base_vars)) {
496 fprintf(stderr, "Failure to read QMAKESPEC conf file %s.\n", spec.latin1()); 496 fprintf(stderr, "Failure to read QMAKESPEC conf file %s.\n", spec.latin1());
497 return FALSE; 497 return FALSE;
498 } 498 }
499 if(Option::mkfile::do_cache && !Option::mkfile::cachefile.isEmpty()) { 499 if(Option::mkfile::do_cache && !Option::mkfile::cachefile.isEmpty()) {
500 debug_msg(1, "QMAKECACHE file: reading %s", Option::mkfile::cachefile.latin1()); 500 debug_msg(1, "QMAKECACHE file: reading %s", Option::mkfile::cachefile.latin1());
501 read(Option::mkfile::cachefile, base_vars); 501 read(Option::mkfile::cachefile, base_vars);
502 } 502 }
503 503
504 /* commandline */ 504 /* commandline */
505 cfile = project; 505 cfile = project;
506 parser.line_no = 1; //really arg count now.. duh 506 parser.line_no = 1; //really arg count now.. duh
507 parser.file = "(internal)"; 507 parser.file = "(internal)";
508 for(QStringList::Iterator it = Option::before_user_vars.begin(); 508 for(QStringList::Iterator it = Option::before_user_vars.begin();
509 it != Option::before_user_vars.end(); ++it) { 509 it != Option::before_user_vars.end(); ++it) {
510 if(!parse((*it), base_vars)) { 510 if(!parse((*it), base_vars)) {
511 fprintf(stderr, "Argument failed to parse: %s\n", (*it).latin1()); 511 fprintf(stderr, "Argument failed to parse: %s\n", (*it).latin1());
512 return FALSE; 512 return FALSE;
513 } 513 }
514 parser.line_no++; 514 parser.line_no++;
515 } 515 }
516 } 516 }
517 517
518 /* parse project file */ 518 /* parse project file */
519 debug_msg(1, "Project file: reading %s", project.latin1()); 519 debug_msg(1, "Project file: reading %s", project.latin1());
520 vars = base_vars; /* start with the base */ 520 vars = base_vars; /* start with the base */
521 521
522 pfile = project; 522 pfile = project;
523 if(pfile != "-" && !QFile::exists(pfile) && pfile.right(4) != ".pro") 523 if(pfile != "-" && !QFile::exists(pfile) && pfile.right(4) != ".pro")
524 pfile += ".pro"; 524 pfile += ".pro";
525 525
526 if(!read(pfile, vars)) 526 if(!read(pfile, vars))
527 return FALSE; 527 return FALSE;
528 528
529 parser.line_no = 1; //really arg count now.. duh 529 parser.line_no = 1; //really arg count now.. duh
530 parser.file = "(internal)"; 530 parser.file = "(internal)";
531 for(QStringList::Iterator it = Option::after_user_vars.begin(); 531 for(QStringList::Iterator it = Option::after_user_vars.begin();
532 it != Option::after_user_vars.end(); ++it) { 532 it != Option::after_user_vars.end(); ++it) {
533 if(!parse((*it), vars)) { 533 if(!parse((*it), vars)) {
534 fprintf(stderr, "Argument failed to parse: %s\n", (*it).latin1()); 534 fprintf(stderr, "Argument failed to parse: %s\n", (*it).latin1());
535 return FALSE; 535 return FALSE;
536 } 536 }
537 parser.line_no++; 537 parser.line_no++;
538 } 538 }
539 539
540 /* now let the user override the template from an option.. */ 540 /* now let the user override the template from an option.. */
541 if(!Option::user_template.isEmpty()) { 541 if(!Option::user_template.isEmpty()) {
542 debug_msg(1, "Overriding TEMPLATE (%s) with: %s", vars["TEMPLATE"].first().latin1(), Option::user_template.latin1()); 542 debug_msg(1, "Overriding TEMPLATE (%s) with: %s", vars["TEMPLATE"].first().latin1(), Option::user_template.latin1());
543 vars["TEMPLATE"].clear(); 543 vars["TEMPLATE"].clear();
544 vars["TEMPLATE"].append(Option::user_template); 544 vars["TEMPLATE"].append(Option::user_template);
545 } 545 }
546 546
547 if(vars["TEMPLATE"].isEmpty()) 547 if(vars["TEMPLATE"].isEmpty())
548 vars["TEMPLATE"].append(QString("app")); 548 vars["TEMPLATE"].append(QString("app"));
549 else 549 else
550 vars["TEMPLATE"].first().replace(QRegExp("\\.t$"), ""); 550 vars["TEMPLATE"].first().replace(QRegExp("\\.t$"), "");
551 if(!Option::user_template_prefix.isEmpty()) 551 if(!Option::user_template_prefix.isEmpty())
552 vars["TEMPLATE"].first().prepend(Option::user_template_prefix); 552 vars["TEMPLATE"].first().prepend(Option::user_template_prefix);
553 553
554 if(vars["TARGET"].isEmpty()) { 554 if(vars["TARGET"].isEmpty()) {
555 // ### why not simply use: 555 // ### why not simply use:
556 // QFileInfo fi(pfile); 556 // QFileInfo fi(pfile);
557 // fi.baseName(); 557 // fi.baseName();
558 QString tmp = pfile; 558 QString tmp = pfile;
559 if(tmp.findRev('/') != -1) 559 if(tmp.findRev('/') != -1)
560 tmp = tmp.right( tmp.length() - tmp.findRev('/') - 1 ); 560 tmp = tmp.right( tmp.length() - tmp.findRev('/') - 1 );
561 if(tmp.findRev('.') != -1) 561 if(tmp.findRev('.') != -1)
562 tmp = tmp.left(tmp.findRev('.')); 562 tmp = tmp.left(tmp.findRev('.'));
563 vars["TARGET"].append(tmp); 563 vars["TARGET"].append(tmp);
564 } 564 }
565 565
566 QString test_version = getenv("QTESTVERSION"); 566 QString test_version = getenv("QTESTVERSION");
567 if (!test_version.isEmpty()) { 567 if (!test_version.isEmpty()) {
568 QString s = vars["TARGET"].first(); 568 QString s = vars["TARGET"].first();
569 if (s == "qt" || s == "qt-mt" || s == "qte" || s == "qte-mt") { 569 if (s == "qt" || s == "qt-mt" || s == "qte" || s == "qte-mt") {
570 QString &ver = vars["VERSION"].first(); 570 QString &ver = vars["VERSION"].first();
571 // fprintf(stderr,"Current QT version number: " + ver + "\n"); 571 // fprintf(stderr,"Current QT version number: " + ver + "\n");
572 if (ver != "" && ver != test_version) { 572 if (ver != "" && ver != test_version) {
573 ver = test_version; 573 ver = test_version;
574 fprintf(stderr,"Changed QT version number to " + test_version + "!\n"); 574 fprintf(stderr,"Changed QT version number to " + test_version + "!\n");
575 } 575 }
576 } 576 }
577 } 577 }
578 return TRUE; 578 return TRUE;
579} 579}
580 580
581bool 581bool
582QMakeProject::isActiveConfig(const QString &x) 582QMakeProject::isActiveConfig(const QString &x)
583{ 583{
584 if(x.isEmpty()) 584 if(x.isEmpty())
585 return TRUE; 585 return TRUE;
586 586
587 QRegExp re(x, FALSE, TRUE); 587 QRegExp re(x, FALSE, TRUE);
588 if((Option::target_mode == Option::TARG_MACX_MODE || Option::target_mode == Option::TARG_QNX6_MODE || Option::target_mode == Option::TARG_UNIX_MODE) && 588 if((Option::target_mode == Option::TARG_MACX_MODE || Option::target_mode == Option::TARG_QNX6_MODE || Option::target_mode == Option::TARG_UNIX_MODE) &&
589 x == "unix") 589 x == "unix")
590 return TRUE; 590 return TRUE;
591 else if(Option::target_mode == Option::TARG_MACX_MODE && x == "macx") 591 else if(Option::target_mode == Option::TARG_MACX_MODE && x == "macx")
592 return TRUE; 592 return TRUE;
593 else if(Option::target_mode == Option::TARG_QNX6_MODE && x == "qnx6") 593 else if(Option::target_mode == Option::TARG_QNX6_MODE && x == "qnx6")
594 return TRUE; 594 return TRUE;
595 else if(Option::target_mode == Option::TARG_MAC9_MODE && x == "mac9") 595 else if(Option::target_mode == Option::TARG_MAC9_MODE && x == "mac9")
596 return TRUE; 596 return TRUE;
597 else if((Option::target_mode == Option::TARG_MAC9_MODE || Option::target_mode == Option::TARG_MACX_MODE) && 597 else if((Option::target_mode == Option::TARG_MAC9_MODE || Option::target_mode == Option::TARG_MACX_MODE) &&
598 x == "mac") 598 x == "mac")
599 return TRUE; 599 return TRUE;
600 else if(Option::target_mode == Option::TARG_WIN_MODE && x == "win32") 600 else if(Option::target_mode == Option::TARG_WIN_MODE && x == "win32")
601 return TRUE; 601 return TRUE;
602 602
603 603
604 QString spec = Option::mkfile::qmakespec.right(Option::mkfile::qmakespec.length() - 604 QString spec = Option::mkfile::qmakespec.right(Option::mkfile::qmakespec.length() -
605 (Option::mkfile::qmakespec.findRev(QDir::separator())+1)); 605 (Option::mkfile::qmakespec.findRev(QDir::separator())+1));
606 if(re.exactMatch(spec)) 606 if(re.exactMatch(spec))
607 return TRUE; 607 return TRUE;
608#ifdef Q_OS_UNIX 608#ifdef Q_OS_UNIX
609 else if(spec == "default") { 609 else if(spec == "default") {
610 static char *buffer = NULL; 610 static char *buffer = NULL;
611 if(!buffer) 611 if(!buffer)
612 buffer = (char *)malloc(1024); 612 buffer = (char *)malloc(1024);
613 int l = readlink(Option::mkfile::qmakespec, buffer, 1024); 613 int l = readlink(Option::mkfile::qmakespec, buffer, 1024);
614 if(l != -1) { 614 if(l != -1) {
615 buffer[l] = '\0'; 615 buffer[l] = '\0';
616 QString r = buffer; 616 QString r = buffer;
617 if(r.findRev('/') != -1) 617 if(r.findRev('/') != -1)
618 r = r.mid(r.findRev('/') + 1); 618 r = r.mid(r.findRev('/') + 1);
619 if(re.exactMatch(r)) 619 if(re.exactMatch(r))
620 return TRUE; 620 return TRUE;
621 } 621 }
622 } 622 }
623#endif 623#endif
624 624
625 625
626 QStringList &configs = vars["CONFIG"]; 626 QStringList &configs = vars["CONFIG"];
627 for(QStringList::Iterator it = configs.begin(); it != configs.end(); ++it) { 627 for(QStringList::Iterator it = configs.begin(); it != configs.end(); ++it) {
628 if(re.exactMatch((*it))) 628 if(re.exactMatch((*it)))
629 return TRUE; 629 return TRUE;
630 } 630 }
631 return FALSE; 631 return FALSE;
632} 632}
633 633
634bool 634bool
635QMakeProject::doProjectTest(QString func, const QString &params, QMap<QString, QStringList> &place) 635QMakeProject::doProjectTest(QString func, const QString &params, QMap<QString, QStringList> &place)
636{ 636{
637 QStringList args = split_arg_list(params); 637 QStringList args = split_arg_list(params);
638 for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { 638 for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) {
639 QString tmp = (*arit).stripWhiteSpace(); 639 QString tmp = (*arit).stripWhiteSpace();
640 if((tmp[0] == '\'' || tmp[0] == '"') && tmp.right(1) == tmp.left(1)) 640 if((tmp[0] == '\'' || tmp[0] == '"') && tmp.right(1) == tmp.left(1))
641 tmp = tmp.mid(1, tmp.length() - 2); 641 tmp = tmp.mid(1, tmp.length() - 2);
642 } 642 }
643 return doProjectTest(func.stripWhiteSpace(), args, place); 643 return doProjectTest(func.stripWhiteSpace(), args, place);
644} 644}
645 645
646bool 646bool
647QMakeProject::doProjectTest(QString func, QStringList args, QMap<QString, QStringList> &place) 647QMakeProject::doProjectTest(QString func, QStringList args, QMap<QString, QStringList> &place)
648{ 648{
649 for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { 649 for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) {
650 (*arit) = (*arit).stripWhiteSpace(); // blah, get rid of space 650 (*arit) = (*arit).stripWhiteSpace(); // blah, get rid of space
651 doVariableReplace((*arit), place); 651 doVariableReplace((*arit), place);
652 } 652 }
653 debug_msg(1, "Running project test: %s( %s )", func.latin1(), args.join("::").latin1()); 653 debug_msg(1, "Running project test: %s( %s )", func.latin1(), args.join("::").latin1());
654 654
655 if(func == "requires") { 655 if(func == "requires") {
656 return doProjectCheckReqs(args, place); 656 return doProjectCheckReqs(args, place);
657 } else if(func == "exists") { 657 } else if(func == "exists") {
658 if(args.count() != 1) { 658 if(args.count() != 1) {
659 fprintf(stderr, "%s:%d: exists(file) requires one argument.\n", parser.file.latin1(), 659 fprintf(stderr, "%s:%d: exists(file) requires one argument.\n", parser.file.latin1(),
660 parser.line_no); 660 parser.line_no);
661 return FALSE; 661 return FALSE;
662 } 662 }
663 QString file = args.first(); 663 QString file = args.first();
664 file = Option::fixPathToLocalOS(file); 664 file = Option::fixPathToLocalOS(file);
665 doVariableReplace(file, place); 665 doVariableReplace(file, place);
666 666
667 if(QFile::exists(file)) 667 if(QFile::exists(file))
668 return TRUE; 668 return TRUE;
669 //regular expression I guess 669 //regular expression I guess
670 QString dirstr = QDir::currentDirPath(); 670 QString dirstr = QDir::currentDirPath();
671 int slsh = file.findRev(Option::dir_sep); 671 int slsh = file.findRev(Option::dir_sep);
672 if(slsh != -1) { 672 if(slsh != -1) {
673 dirstr = file.left(slsh+1); 673 dirstr = file.left(slsh+1);
674 file = file.right(file.length() - slsh - 1); 674 file = file.right(file.length() - slsh - 1);
675 } 675 }
676 QDir dir(dirstr, file); 676 QDir dir(dirstr, file);
677 return dir.count() != 0; 677 return dir.count() != 0;
678 } else if(func == "system") { 678 } else if(func == "system") {
679 if(args.count() != 1) { 679 if(args.count() != 1) {
680 fprintf(stderr, "%s:%d: system(exec) requires one argument.\n", parser.file.latin1(), 680 fprintf(stderr, "%s:%d: system(exec) requires one argument.\n", parser.file.latin1(),
681 parser.line_no); 681 parser.line_no);
682 return FALSE; 682 return FALSE;
683 } 683 }
684 return system(args.first().latin1()) == 0; 684 return system(args.first().latin1()) == 0;
685 } else if(func == "contains") { 685 } else if(func == "contains") {
686 if(args.count() != 2) { 686 if(args.count() != 2) {
687 fprintf(stderr, "%s:%d: contains(var, val) requires two arguments.\n", parser.file.latin1(), 687 fprintf(stderr, "%s:%d: contains(var, val) requires two arguments.\n", parser.file.latin1(),
688 parser.line_no); 688 parser.line_no);
689 return FALSE; 689 return FALSE;
690 } 690 }
691 QRegExp regx(args[1]); 691 QRegExp regx(args[1]);
692 QStringList &l = place[args[0]]; 692 QStringList &l = place[args[0]];
693 for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { 693 for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
694 if(regx.exactMatch((*it))) 694 if(regx.exactMatch((*it)))
695 return TRUE; 695 return TRUE;
696 } 696 }
697 return FALSE; 697 return FALSE;
698 } else if(func == "infile") { 698 } else if(func == "infile") {
699 if(args.count() < 2 || args.count() > 3) { 699 if(args.count() < 2 || args.count() > 3) {
700 fprintf(stderr, "%s:%d: infile(file, var, val) requires at least 2 arguments.\n", 700 fprintf(stderr, "%s:%d: infile(file, var, val) requires at least 2 arguments.\n",
701 parser.file.latin1(), parser.line_no); 701 parser.file.latin1(), parser.line_no);
702 return FALSE; 702 return FALSE;
703 } 703 }
704 QMakeProject proj; 704 QMakeProject proj;
705 QString file = args[0]; 705 QString file = args[0];
706 doVariableReplace(file, place); 706 doVariableReplace(file, place);
707 fixEnvVariables(file); 707 fixEnvVariables(file);
708 int di = file.findRev(Option::dir_sep); 708 int di = file.findRev(Option::dir_sep);
709 QDir sunworkshop42workaround = QDir::current(); 709 QDir sunworkshop42workaround = QDir::current();
710 QString oldpwd = sunworkshop42workaround.currentDirPath(); 710 QString oldpwd = sunworkshop42workaround.currentDirPath();
711 if(di != -1) { 711 if(di != -1) {
712 if(!QDir::setCurrent(file.left(file.findRev(Option::dir_sep)))) { 712 if(!QDir::setCurrent(file.left(file.findRev(Option::dir_sep)))) {
713 fprintf(stderr, "Cannot find directory: %s\n", file.left(di).latin1()); 713 fprintf(stderr, "Cannot find directory: %s\n", file.left(di).latin1());
714 return FALSE; 714 return FALSE;
715 } 715 }
716 file = file.right(file.length() - di - 1); 716 file = file.right(file.length() - di - 1);
717 } 717 }
718 parser_info pi = parser; 718 parser_info pi = parser;
719 bool ret = !proj.read(file, oldpwd); 719 bool ret = !proj.read(file, oldpwd);
720 parser = pi; 720 parser = pi;
721 if(ret) { 721 if(ret) {
722 fprintf(stderr, "Error processing project file: %s\n", file.latin1()); 722 fprintf(stderr, "Error processing project file: %s\n", file.latin1());
723 QDir::setCurrent(oldpwd); 723 QDir::setCurrent(oldpwd);
724 return FALSE; 724 return FALSE;
725 } 725 }
726 if(args.count() == 2) { 726 if(args.count() == 2) {
727 ret = !proj.isEmpty(args[1]); 727 ret = !proj.isEmpty(args[1]);
728 } else { 728 } else {
729 QRegExp regx(args[2]); 729 QRegExp regx(args[2]);
730 QStringList &l = proj.values(args[1]); 730 QStringList &l = proj.values(args[1]);
731 for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { 731 for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
732 if(regx.exactMatch((*it))) { 732 if(regx.exactMatch((*it))) {
733 ret = TRUE; 733 ret = TRUE;
734 break; 734 break;
735 } 735 }
736 } 736 }
737 } 737 }
738 QDir::setCurrent(oldpwd); 738 QDir::setCurrent(oldpwd);
739 return ret; 739 return ret;
740 } else if(func == "count") { 740 } else if(func == "count") {
741 if(args.count() != 2) { 741 if(args.count() != 2) {
742 fprintf(stderr, "%s:%d: count(var, count) requires two arguments.\n", parser.file.latin1(), 742 fprintf(stderr, "%s:%d: count(var, count) requires two arguments.\n", parser.file.latin1(),
743 parser.line_no); 743 parser.line_no);
744 return FALSE; 744 return FALSE;
745 } 745 }
746 return vars[args[0]].count() == args[1].toUInt(); 746 return vars[args[0]].count() == args[1].toUInt();
747 } else if(func == "isEmpty") { 747 } else if(func == "isEmpty") {
748 if(args.count() != 1) { 748 if(args.count() != 1) {
749 fprintf(stderr, "%s:%d: isEmpty(var) requires one argument.\n", parser.file.latin1(), 749 fprintf(stderr, "%s:%d: isEmpty(var) requires one argument.\n", parser.file.latin1(),
750 parser.line_no); 750 parser.line_no);
751 return FALSE; 751 return FALSE;
752 } 752 }
753 return vars[args[0]].isEmpty(); 753 return vars[args[0]].isEmpty();
754 } else if(func == "include" || func == "load") { 754 } else if(func == "include" || func == "load") {
755 if(args.count() != 1) { 755 if(args.count() != 1) {
756 QString func_desc = "include(file)"; 756 QString func_desc = "include(file)";
757 if(func == "load") 757 if(func == "load")
758 func_desc = "load(feature)"; 758 func_desc = "load(feature)";
759 fprintf(stderr, "%s:%d: %s requires one argument.\n", parser.file.latin1(), 759 fprintf(stderr, "%s:%d: %s requires one argument.\n", parser.file.latin1(),
760 parser.line_no, func_desc.latin1()); 760 parser.line_no, func_desc.latin1());
761 return FALSE; 761 return FALSE;
762 } 762 }
763 763
764 QString file = args.first(); 764 QString file = args.first();
765 file = Option::fixPathToLocalOS(file); 765 file = Option::fixPathToLocalOS(file);
766 file.replace("\"", ""); 766 file.replace("\"", "");
767 doVariableReplace(file, place); 767 doVariableReplace(file, place);
768 if(func == "load") { 768 if(func == "load") {
769 if(!file.endsWith(Option::prf_ext)) 769 if(!file.endsWith(Option::prf_ext))
770 file += Option::prf_ext; 770 file += Option::prf_ext;
771 if(file.find(Option::dir_sep) == -1 || !QFile::exists(file)) { 771 if(file.find(Option::dir_sep) == -1 || !QFile::exists(file)) {
772 if(QFile::exists(Option::mkfile::qmakespec + QDir::separator() + file)) { 772 if(QFile::exists(Option::mkfile::qmakespec + QDir::separator() + file)) {
773 file.prepend(Option::mkfile::qmakespec + QDir::separator()); 773 file.prepend(Option::mkfile::qmakespec + QDir::separator());
774 } else { 774 } else {
775 bool found = FALSE; 775 bool found = FALSE;
776 QStringList feature_roots; 776 QStringList feature_roots;
777 if(getenv("QTDIR")) 777 if(getenv("QTDIR"))
778 feature_roots << getenv("QTDIR"); 778 feature_roots << getenv("QTDIR");
779#ifdef QT_INSTALL_PREFIX 779#ifdef QT_INSTALL_PREFIX
780 feature_roots << QT_INSTALL_PREFIX; 780 feature_roots << QT_INSTALL_PREFIX;
781#endif 781#endif
782#ifdef QT_INSTALL_DATA 782#ifdef QT_INSTALL_DATA
783 feature_roots << QT_INSTALL_DATA; 783 feature_roots << QT_INSTALL_DATA;
784#endif 784#endif
785 for(QStringList::Iterator it = feature_roots.begin(); it != feature_roots.end(); ++it) { 785 for(QStringList::Iterator it = feature_roots.begin(); it != feature_roots.end(); ++it) {
786 QString prf = (*it) + QDir::separator() + QString("mkspecs") + 786 QString prf = (*it) + QDir::separator() + QString("mkspecs") +
787 QDir::separator() + QString("features") + QDir::separator() + file; 787 QDir::separator() + QString("features") + QDir::separator() + file;
788 if(QFile::exists(prf)) { 788 if(QFile::exists(prf)) {
789 found = TRUE; 789 found = TRUE;
790 file = prf; 790 file = prf;
791 break; 791 break;
792 } 792 }
793 } 793 }
794 if(!found) { 794 if(!found) {
795 printf("Project LOAD(): Feature %s cannot be found.\n", args.first().latin1()); 795 printf("Project LOAD(): Feature %s cannot be found.\n", args.first().latin1());
796 exit(3); 796 exit(3);
797 } 797 }
798 } 798 }
799 } 799 }
800 } 800 }
801 801
802 debug_msg(1, "Project Parser: %s'ing file %s.", func.latin1(), file.latin1()); 802 debug_msg(1, "Project Parser: %s'ing file %s.", func.latin1(), file.latin1());
803 parser_info pi = parser; 803 parser_info pi = parser;
804 int sb = scope_block; 804 int sb = scope_block;
805 int sf = scope_flag; 805 int sf = scope_flag;
806 TestStatus sc = test_status; 806 TestStatus sc = test_status;
807 bool r = read(file.latin1(), place); 807 bool r = read(file.latin1(), place);
808 if(r) 808 if(r)
809 vars["QMAKE_INTERNAL_INCLUDED_FILES"].append(file); 809 vars["QMAKE_INTERNAL_INCLUDED_FILES"].append(file);
810 parser = pi; 810 parser = pi;
811 test_status = sc; 811 test_status = sc;
812 scope_flag = sf; 812 scope_flag = sf;
813 scope_block = sb; 813 scope_block = sb;
814 return r; 814 return r;
815 } else if(func == "error" || func == "message") { 815 } else if(func == "error" || func == "message") {
816 if(args.count() != 1) { 816 if(args.count() != 1) {
817 fprintf(stderr, "%s:%d: %s(message) requires one argument.\n", parser.file.latin1(), 817 fprintf(stderr, "%s:%d: %s(message) requires one argument.\n", parser.file.latin1(),
818 parser.line_no, func.latin1()); 818 parser.line_no, func.latin1());
819 return FALSE; 819 return FALSE;
820 } 820 }
821 QString msg = args.first(); 821 QString msg = args.first();
822 doVariableReplace(msg, place); 822 doVariableReplace(msg, place);
823 fixEnvVariables(msg); 823 fixEnvVariables(msg);
824 printf("Project %s: %s\n", func.upper().latin1(), msg.latin1()); 824 printf("Project %s: %s\n", func.upper().latin1(), msg.latin1());
825 if(func == "message") 825 if(func == "message")
826 return TRUE; 826 return TRUE;
827 exit(2); 827 exit(2);
828 } else { 828 } else {
829 fprintf(stderr, "%s:%d: Unknown test function: %s\n", parser.file.latin1(), parser.line_no, 829 fprintf(stderr, "%s:%d: Unknown test function: %s\n", parser.file.latin1(), parser.line_no,
830 func.latin1()); 830 func.latin1());
831 } 831 }
832 return FALSE; 832 return FALSE;
833} 833}
834 834
835bool 835bool
836QMakeProject::doProjectCheckReqs(const QStringList &deps, QMap<QString, QStringList> &place) 836QMakeProject::doProjectCheckReqs(const QStringList &deps, QMap<QString, QStringList> &place)
837{ 837{
838 bool ret = FALSE; 838 bool ret = FALSE;
839 for(QStringList::ConstIterator it = deps.begin(); it != deps.end(); ++it) { 839 for(QStringList::ConstIterator it = deps.begin(); it != deps.end(); ++it) {
840 QString chk = (*it); 840 QString chk = (*it);
841 if(chk.isEmpty()) 841 if(chk.isEmpty())
842 continue; 842 continue;
843 bool invert_test = (chk.left(1) == "!"); 843 bool invert_test = (chk.left(1) == "!");
844 if(invert_test) 844 if(invert_test)
845 chk = chk.right(chk.length() - 1); 845 chk = chk.right(chk.length() - 1);
846 846
847 bool test; 847 bool test;
848 int lparen = chk.find('('); 848 int lparen = chk.find('(');
849 if(lparen != -1) { /* if there is an lparen in the chk, it IS a function */ 849 if(lparen != -1) { /* if there is an lparen in the chk, it IS a function */
850 int rparen = chk.findRev(')'); 850 int rparen = chk.findRev(')');
851 if(rparen == -1) { 851 if(rparen == -1) {
852 QCString error; 852 QCString error;
853 error.sprintf("Function (in REQUIRES) missing right paren: %s", chk.latin1()); 853 error.sprintf("Function (in REQUIRES) missing right paren: %s", chk.latin1());
854 qmake_error_msg(error); 854 qmake_error_msg(error);
855 } else { 855 } else {
856 QString func = chk.left(lparen); 856 QString func = chk.left(lparen);
857 test = doProjectTest(func, chk.mid(lparen+1, rparen - lparen - 1), place); 857 test = doProjectTest(func, chk.mid(lparen+1, rparen - lparen - 1), place);
858 } 858 }
859 } else { 859 } else {
860 test = isActiveConfig(chk); 860 test = isActiveConfig(chk);
861 } 861 }
862 if(invert_test) { 862 if(invert_test) {
863 chk.prepend("!"); 863 chk.prepend("!");
864 test = !test; 864 test = !test;
865 } 865 }
866 if(!test) { 866 if(!test) {
867 debug_msg(1, "Project Parser: %s:%d Failed test: REQUIRES = %s", 867 debug_msg(1, "Project Parser: %s:%d Failed test: REQUIRES = %s",
868 parser.file.latin1(), parser.line_no, chk.latin1()); 868 parser.file.latin1(), parser.line_no, chk.latin1());
869 place["QMAKE_FAILED_REQUIREMENTS"].append(chk); 869 place["QMAKE_FAILED_REQUIREMENTS"].append(chk);
870 ret = FALSE; 870 ret = FALSE;
871 } 871 }
872 } 872 }
873 return ret; 873 return ret;
874} 874}
875 875
876 876
877QString 877QString
878QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> &place) 878QMakeProject::doVariableReplace(QString &str, const QMap<QString, QStringList> &place)
879{ 879{
880 for(int x = 0, rep; x < 5; x++) { 880 for(int x = 0, rep; x < 5; x++) {
881 QRegExp reg_var; 881 QRegExp reg_var;
882 reg_var.setMinimal(TRUE); 882 reg_var.setMinimal(TRUE);
883 if( x == 0 ) //function blocked out by {}'s 883 if( x == 0 ) //function blocked out by {}'s
884 reg_var = QRegExp("\\$\\$\\{([a-zA-Z0-9_]*)\\((\\(.|(.*)\\)*)\\)\\}"); 884 reg_var = QRegExp("\\$\\$\\{([a-zA-Z0-9_]*)\\((\\(.|(.*)\\)*)\\)\\}");
885 else if( x == 1 ) //variables blocked out by {}'s 885 else if( x == 1 ) //variables blocked out by {}'s
886 reg_var = QRegExp("\\$\\$\\{([a-zA-Z0-9_\\.-]*)\\}"); 886 reg_var = QRegExp("\\$\\$\\{([a-zA-Z0-9_\\.-]*)\\}");
887 else if(x == 2) //environment 887 else if(x == 2) //environment
888 reg_var = QRegExp("\\$\\$\\(([a-zA-Z0-9_\\.-]*)\\)"); 888 reg_var = QRegExp("\\$\\$\\(([a-zA-Z0-9_\\.-]*)\\)");
889 else if(x == 3) //function 889 else if(x == 3) //function
890 reg_var = QRegExp("\\$\\$([a-zA-Z0-9_]*)\\((\\(.|(.*)\\)*)\\)"); 890 reg_var = QRegExp("\\$\\$([a-zA-Z0-9_]*)\\((\\(.|(.*)\\)*)\\)");
891 else if(x == 4) //normal variable 891 else if(x == 4) //normal variable
892 reg_var = QRegExp("\\$\\$([a-zA-Z0-9_\\.-]*)"); 892 reg_var = QRegExp("\\$\\$([a-zA-Z0-9_\\.-]*)");
893 while((rep = reg_var.search(str)) != -1) { 893 while((rep = reg_var.search(str)) != -1) {
894 QString replacement; 894 QString replacement;
895 if(x == 2) {//environment 895 if(x == 2) {//environment
896 replacement = getenv(reg_var.cap(1)); 896 replacement = getenv(reg_var.cap(1));
897 } else if(x == 0 || x == 3) { //function 897 } else if(x == 0 || x == 3) { //function
898 QStringList args = split_arg_list(reg_var.cap(2)); 898 QStringList args = split_arg_list(reg_var.cap(2));
899 for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { 899 for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) {
900 (*arit) = (*arit).stripWhiteSpace(); // blah, get rid of space 900 (*arit) = (*arit).stripWhiteSpace(); // blah, get rid of space
901 doVariableReplace((*arit), place); 901 doVariableReplace((*arit), place);
902 } 902 }
903 debug_msg(1, "Running function: %s( %s )", reg_var.cap(1).latin1(), args.join("::").latin1()); 903 debug_msg(1, "Running function: %s( %s )", reg_var.cap(1).latin1(), args.join("::").latin1());
904 if(reg_var.cap(1).lower() == "member") { 904 if(reg_var.cap(1).lower() == "member") {
905 if(args.count() < 1 || args.count() > 2) { 905 if(args.count() < 1 || args.count() > 2) {
906 fprintf(stderr, "%s:%d: member(var, place) requires two arguments.\n", 906 fprintf(stderr, "%s:%d: member(var, place) requires two arguments.\n",
907 parser.file.latin1(), parser.line_no); 907 parser.file.latin1(), parser.line_no);
908 } else { 908 } else {
909 uint pos = 0; 909 uint pos = 0;
910 if(args.count() == 2) 910 if(args.count() == 2)
911 pos = args[1].toInt(); 911 pos = args[1].toInt();
912 const QStringList &var = place[varMap(args.first())]; 912 const QStringList &var = place[varMap(args.first())];
913 if(var.count() >= pos) 913 if(var.count() >= pos)
914 replacement = var[pos]; 914 replacement = var[pos];
915 } 915 }
916 } else if(reg_var.cap(1).lower() == "list") { 916 } else if(reg_var.cap(1).lower() == "list") {
917 if(args.count() != 1) { 917 if(args.count() != 1) {
918 fprintf(stderr, "%s:%d: list(vals) requires one" 918 fprintf(stderr, "%s:%d: list(vals) requires one"
919 "argument.\n", parser.file.latin1(), parser.line_no); 919 "argument.\n", parser.file.latin1(), parser.line_no);
920 } else { 920 } else {
921 static int x = 0; 921 static int x = 0;
922 replacement.sprintf(".QMAKE_INTERNAL_TMP_VAR_%d", x++); 922 replacement.sprintf(".QMAKE_INTERNAL_TMP_VAR_%d", x++);
923 (*((QMap<QString, QStringList>*)&place))[replacement] = split_value_list(args.first()); 923 (*((QMap<QString, QStringList>*)&place))[replacement] = split_value_list(args.first());
924 } 924 }
925 } else if(reg_var.cap(1).lower() == "join") { 925 } else if(reg_var.cap(1).lower() == "join") {
926 if(args.count() < 1 || args.count() > 4) { 926 if(args.count() < 1 || args.count() > 4) {
927 fprintf(stderr, "%s:%d: join(var, glue, before, after) requires four" 927 fprintf(stderr, "%s:%d: join(var, glue, before, after) requires four"
928 "arguments.\n", parser.file.latin1(), parser.line_no); 928 "arguments.\n", parser.file.latin1(), parser.line_no);
929 } else { 929 } else {
930 QString glue, before, after; 930 QString glue, before, after;
931 if(args.count() >= 2) 931 if(args.count() >= 2)
932 glue = args[1].replace("\"", "" ); 932 glue = args[1].replace("\"", "" );
933 if(args.count() >= 3) 933 if(args.count() >= 3)
934 before = args[2].replace("\"", "" ); 934 before = args[2].replace("\"", "" );
935 if(args.count() == 4) 935 if(args.count() == 4)
936 after = args[3].replace("\"", "" ); 936 after = args[3].replace("\"", "" );
937 const QStringList &var = place[varMap(args.first())]; 937 const QStringList &var = place[varMap(args.first())];
938 if(!var.isEmpty()) 938 if(!var.isEmpty())
939 replacement = before + var.join(glue) + after; 939 replacement = before + var.join(glue) + after;
940 } 940 }
941 } else if(reg_var.cap(1).lower() == "find") { 941 } else if(reg_var.cap(1).lower() == "find") {
942 if(args.count() != 2) { 942 if(args.count() != 2) {
943 fprintf(stderr, "%s:%d find(var, str) requires two arguments\n", 943 fprintf(stderr, "%s:%d find(var, str) requires two arguments\n",
944 parser.file.latin1(), parser.line_no); 944 parser.file.latin1(), parser.line_no);
945 } else { 945 } else {
946 QRegExp regx(args[1]); 946 QRegExp regx(args[1]);
947 const QStringList &var = place[varMap(args.first())]; 947 const QStringList &var = place[varMap(args.first())];
948 for(QStringList::ConstIterator vit = var.begin(); 948 for(QStringList::ConstIterator vit = var.begin();
949 vit != var.end(); ++vit) { 949 vit != var.end(); ++vit) {
950 if(regx.search(*vit) != -1) { 950 if(regx.search(*vit) != -1) {
951 if(!replacement.isEmpty()) 951 if(!replacement.isEmpty())
952 replacement += " "; 952 replacement += " ";
953 replacement += (*vit); 953 replacement += (*vit);
954 } 954 }
955 } 955 }
956 } 956 }
957 } else if(reg_var.cap(1).lower() == "system") { 957 } else if(reg_var.cap(1).lower() == "system") {
958 if(args.count() != 1) { 958 if(args.count() != 1) {
959 fprintf(stderr, "%s:%d system(execut) requires one argument\n", 959 fprintf(stderr, "%s:%d system(execut) requires one argument\n",
960 parser.file.latin1(), parser.line_no); 960 parser.file.latin1(), parser.line_no);
961 } else { 961 } else {
962 char buff[256]; 962 char buff[256];
963 FILE *proc = QT_POPEN(args.join(" ").latin1(), "r"); 963 FILE *proc = QT_POPEN(args.join(" ").latin1(), "r");
964 while(proc && !feof(proc)) { 964 while(proc && !feof(proc)) {
965 int read_in = fread(buff, 1, 255, proc); 965 int read_in = fread(buff, 1, 255, proc);
966 if(!read_in) 966 if(!read_in)
967 break; 967 break;
968 for(int i = 0; i < read_in; i++) { 968 for(int i = 0; i < read_in; i++) {
969 if(buff[i] == '\n' || buff[i] == '\t') 969 if(buff[i] == '\n' || buff[i] == '\t')
970 buff[i] = ' '; 970 buff[i] = ' ';
971 } 971 }
972 buff[read_in] = '\0'; 972 buff[read_in] = '\0';
973 replacement += buff; 973 replacement += buff;
974 } 974 }
975 } 975 }
976 } else { 976 } else {
977 fprintf(stderr, "%s:%d: Unknown replace function: %s\n", 977 fprintf(stderr, "%s:%d: Unknown replace function: %s\n",
978 parser.file.latin1(), parser.line_no, reg_var.cap(1).latin1()); 978 parser.file.latin1(), parser.line_no, reg_var.cap(1).latin1());
979 } 979 }
980 } else { //variable 980 } else { //variable
981 if(reg_var.cap(1).left(1) == ".") 981 if(reg_var.cap(1).left(1) == ".")
982 replacement = ""; 982 replacement = "";
983 else if(reg_var.cap(1) == "LITERAL_WHITESPACE") 983 else if(reg_var.cap(1) == "LITERAL_WHITESPACE")
984 replacement = "\t"; 984 replacement = "\t";
985 else 985 else
986 replacement = place[varMap(reg_var.cap(1))].join(" "); 986 replacement = place[varMap(reg_var.cap(1))].join(" ");
987 } 987 }
988 debug_msg(2, "Project parser: %d (%s) :: %s -> %s", x, str.latin1(), 988 debug_msg(2, "Project parser: %d (%s) :: %s -> %s", x, str.latin1(),
989 reg_var.capturedTexts().join("::").latin1(), replacement.latin1()); 989 reg_var.capturedTexts().join("::").latin1(), replacement.latin1());
990 str.replace(rep, reg_var.matchedLength(), replacement); 990 str.replace(rep, reg_var.matchedLength(), replacement);
991 } 991 }
992 } 992 }
993 return str; 993 return str;
994} 994}