source: trunk/tools/linguist/shared/proparser.cpp@ 90

Last change on this file since 90 was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 6.2 KB
Line 
1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3**
4** This file is part of Qt Linguist.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
12** licenses may use this file in accordance with the Qt Commercial License
13** Agreement provided with the Software.
14**
15** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17**
18** See http://www.trolltech.com/gpl/ for GPL licensing information.
19** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
20** information about Qt Commercial License Agreements.
21**
22** Contact info@trolltech.com if any conditions of this licensing are
23** not clear to you.
24**
25**********************************************************************/
26
27#include "proparser.h"
28
29#include <qdir.h>
30#include <qfile.h>
31#include <qfileinfo.h>
32#include <qregexp.h>
33#include <qstringlist.h>
34#include <qtextstream.h>
35
36#ifdef Q_OS_UNIX
37#include <unistd.h>
38#endif
39
40#ifdef Q_OS_WIN32
41#define QT_POPEN _popen
42#else
43#define QT_POPEN popen
44#endif
45
46QString loadFile( const QString &fileName )
47{
48 QFile file( fileName );
49 if ( !file.open(IO_ReadOnly) ) {
50 fprintf( stderr, "error: Cannot load '%s': %s\n",
51 file.name().latin1(),
52 file.errorString().latin1() );
53 return QString();
54 }
55
56 QTextStream in( &file );
57 return in.read();
58}
59
60QMap<QString, QString> proFileTagMap( const QString& text )
61{
62 QString t = text;
63 QMap<QString, QString> tagMap;
64 bool stillProcess = true; // If include() has a $$tag then we need to reprocess
65
66 while(stillProcess) {
67
68 /*
69 Strip any commments before we try to include. We
70 still need to do it after we include to make sure the
71 included file does not have comments
72 */
73 t.replace( QRegExp(QString("#[^\n]*\n")), QString(" ") );
74
75 /*
76 Process include() commands.
77 $$PWD is a special case so we have to change it while
78 we know where the included file is.
79 */
80 QRegExp callToInclude("include\\s*\\(\\s*([^()\\s]+)\\s*\\)");
81 int i = 0;
82 while ( (i = callToInclude.search(t, i)) != -1 ) {
83 bool doneWithVar = false;
84 QString fileName = callToInclude.cap(1);
85 QString after = fileName.replace("$$PWD", QDir::currentDirPath());
86 if (!tagMap.isEmpty() && after.contains("$$")) {
87 QRegExp var( "\\$\\$[({]?([a-zA-Z0-9_]+)[)}]?" );
88 int ii = 0;
89 while ((ii = after.find(var, ii)) != -1) {
90 if (tagMap.contains(var.cap(1))) {
91 after.replace(ii, var.cap(0).length(), tagMap[var.cap(1)]);
92 } else { // Couldn't find it
93 doneWithVar = true;
94 break;
95 }
96 }
97
98 }
99 if (doneWithVar || !after.contains("$$")) {
100 after = loadFile(after);
101 QFileInfo fi(callToInclude.cap(1));
102 after.replace("$$PWD", fi.dirPath());
103 t.replace( i, callToInclude.matchedLength(), after );
104 }
105 i += after.length();
106 }
107
108 /*
109 Strip comments, merge lines ending with backslash, add
110 spaces around '=' and '+=', replace '\n' with ';', and
111 simplify white spaces.
112 */
113 t.replace( QRegExp(QString("#[^\n]*\n")), QString(" ") );
114 t.replace( QRegExp(QString("\\\\[^\n\\S]*\n")), QString(" ") );
115 t.replace( "=", QString(" = ") );
116 t.replace( "+ =", QString(" += ") );
117 t.replace( "\n", QString(";") );
118 t = t.simplifyWhiteSpace();
119
120 /*
121 Populate tagMap with 'key = value' entries.
122 */
123 QStringList lines = QStringList::split( QChar(';'), t );
124 QStringList::Iterator line;
125 for ( line = lines.begin(); line != lines.end(); ++line ) {
126 QStringList toks = QStringList::split( QChar(' '), *line );
127
128 if ( toks.count() >= 3 &&
129 (toks[1] == QString("=") || toks[1] == QString("+=")) ) {
130 QString tag = toks.first();
131 int k = tag.findRev( QChar(':') ); // as in 'unix:'
132 if ( k != -1 )
133 tag = tag.mid( k + 1 );
134 toks.remove( toks.begin() );
135
136 QString action = toks.first();
137 toks.remove( toks.begin() );
138
139 if ( tagMap.contains(tag) ) {
140 if ( action == QString("=") )
141 tagMap.replace( tag, toks.join(QChar(' ')) );
142 else
143 tagMap[tag] += QChar( ' ' ) + toks.join( QChar(' ') );
144 } else {
145 tagMap[tag] = toks.join( QChar(' ') );
146 }
147 }
148 }
149
150 /*
151 Expand $$variables within the 'value' part of a 'key = value'
152 pair.
153 */
154 QRegExp var( "\\$\\$[({]?([a-zA-Z0-9_]+)[)}]?" );
155 QMap<QString, QString>::Iterator it;
156 for ( it = tagMap.begin(); it != tagMap.end(); ++it ) {
157 int i = 0;
158 while ( (i = var.search((*it), i)) != -1 ) {
159 int len = var.matchedLength();
160 QString invocation = var.cap(1);
161 QString after;
162
163 if ( invocation == "system" ) {
164 // skip system(); it will be handled in the next pass
165 ++i;
166 } else {
167 if ( tagMap.contains(invocation) )
168 after = tagMap[invocation];
169 else if (invocation.lower() == "pwd")
170 after = QDir::currentDirPath();
171 (*it).replace( i, len, after );
172 }
173 }
174 }
175
176 /*
177 Execute system() calls.
178 */
179 QRegExp callToSystem( "\\$\\$system\\s*\\(([^()]*)\\)" );
180 for ( it = tagMap.begin(); it != tagMap.end(); ++it ) {
181 int i = 0;
182 while ( (i = callToSystem.search((*it), i)) != -1 ) {
183 /*
184 This code is stolen from qmake's project.cpp file.
185 Ideally we would use the same parser, so we wouldn't
186 have this code duplication.
187 */
188 QString after;
189 char buff[256];
190 FILE *proc = QT_POPEN( callToSystem.cap(1).latin1(), "r" );
191 while ( proc && !feof(proc) ) {
192 int read_in = fread( buff, 1, 255, proc );
193 if ( !read_in )
194 break;
195 for ( int i = 0; i < read_in; i++ ) {
196 if ( buff[i] == '\n' || buff[i] == '\t' )
197 buff[i] = ' ';
198 }
199 buff[read_in] = '\0';
200 after += buff;
201 }
202 (*it).replace( i, callToSystem.matchedLength(), after );
203 i += after.length();
204 }
205 }
206 stillProcess = callToInclude.search(t) != -1;
207 }
208 return tagMap;
209}
Note: See TracBrowser for help on using the repository browser.