1
/***************************************************************************
2
* Copyright (C) 2001-2002 by Bernd Gehrmann *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 2 of the License, or *
8
* (at your option) any later version. *
10
***************************************************************************/
15
#include <qtextstream.h>
19
#include <kparts/componentfactory.h>
24
#include "kdevcompileroptions.h"
27
static KDevCompilerOptions *createCompilerOptions( const QString &name, QObject *parent )
29
KService::Ptr service = KService::serviceByDesktopName( name );
32
kdDebug( 9020 ) << "Can't find service " << name << endl;
37
KLibFactory *factory = KLibLoader::self()->factory(QFile::encodeName(service->library()));
39
QString errorMessage = KLibLoader::self()->lastErrorMessage();
40
kdDebug(9020) << "There was an error loading the module " << service->name() << endl <<
41
"The diagnostics is:" << endl << errorMessage << endl;
46
QVariant prop = service->property("X-KDevelop-Args");
48
args = QStringList::split(" ", prop.toString());
50
QObject *obj = factory->create(parent, service->name().latin1(),
51
"KDevCompilerOptions", args);
53
if (!obj->inherits("KDevCompilerOptions")) {
54
kdDebug(9020) << "Component does not inherit KDevCompilerOptions" << endl;
57
KDevCompilerOptions *dlg = (KDevCompilerOptions*) obj;
63
QVariant prop = service->property( "X-KDevelop-Args" );
65
args = QStringList::split( " ", prop.toString() );
67
return KParts::ComponentFactory
68
::createInstanceFromService<KDevCompilerOptions>( service, parent,
69
service->name().latin1(), args );*/
73
QString AutoProjectTool::execFlagsDialog( const QString &compiler, const QString &flags, QWidget *parent )
75
KDevCompilerOptions * plugin = createCompilerOptions( compiler, parent );
79
QString newflags = plugin->exec( parent, flags );
87
QString AutoProjectTool::canonicalize( const QString &str )
90
for ( uint i = 0; i < str.length(); ++i )
91
res += ( str[ i ].isLetterOrNumber() || str[ i ] == '@' ) ? str[ i ] : QChar( '_' );
93
kdDebug(9020) << k_funcinfo << "normalized '" << str << "' to '" << res << "'" << endl;
99
* Read the Makefile.am and return a map of all the variables.
100
* Will take notice of backslash and += constructs.
104
void AutoProjectTool::parseMakefileam(const QString &fileName, QMap<QString, QString> *variables)
107
if (!f.open(IO_ReadOnly))
111
QTextStream stream(&f);
113
QRegExp re("^(#kdevelop:[ \t]*)?([A-Za-z][@A-Za-z0-9_]*)[ \t]*([:\\+]?=)[ \t]*(.*)$");
116
bool multiLine = false;
117
while (!stream.atEnd())
119
QString s = stream.readLine().stripWhiteSpace();
120
if (re.exactMatch(s))
122
QString lhs = re.cap(2);
123
QString rhs = re.cap(4);
124
if (rhs[ rhs.length() - 1 ] == '\\')
128
rhs[rhs.length() - 1] = ' ';
131
// The need for stripWhiteSpace seems to be a Qt bug.
132
// make our list nice and neat.
133
QStringList bits = QStringList::split(" ", rhs);
134
rhs = bits.join(" ");
135
if (re.cap(3) == "+=")
137
((*variables)[lhs] += ' ') += rhs;
141
variables->insert(lhs, rhs);
146
if (s[s.length()-1] == '\\')
148
s[s.length()-1] = ' ';
154
QStringList bits = QStringList::split(" ", s);
155
((*variables)[last] += ' ') += bits.join(" ");
160
QMap<QString, QString> list;
162
for (QMap<QString, QString>::iterator iter = variables->begin();iter != variables->end();iter++)
164
QStringList items = QStringList::split(" ", iter.data());
165
QMap<QString, QString> unique;
166
for (uint i = 0;i < items.size();i++)
168
unique.insert(items[i], "");
171
for (QMap<QString, QString>::iterator it = unique.begin();it != unique.end();it++)
173
line += it.key() + ' ';
175
if (line.length() > 1)
177
line.setLength(line.length() - 1);
180
list.insert(iter.key(), line);
186
* Add entries to a variable. Will just add the variables to the existing line, removing duplicates
187
* Will preserve += constructs and make sure that the variable only has one copy of the value across
190
* @param variables key=value string of entries to add
192
void AutoProjectTool::addToMakefileam(const QString &fileName, QMap<QString, QString> variables)
194
AutoProjectTool::addRemoveMakefileam(fileName, variables, true);
198
* Set entries to a variable. Will set the variables to the existing line, removing duplicates
199
* Will preserve += constructs and make sure that the variable only has one copy of the value across
201
* Adds line if it does not exist.
203
* @param variables key=value string of entries to add
205
void AutoProjectTool::setMakefileam ( const QString &fileName, QMap<QString, QString> variables )
207
for ( QMap<QString, QString>::Iterator it0 = variables.begin(); it0 != variables.end(); ++it0 )
209
kdDebug ( 9020 ) << "key (set): " << it0.key() << "=" << it0.data() << endl;
212
// input file reading
213
QFile fin ( fileName );
214
if ( !fin.open ( IO_ReadOnly ) )
218
QTextStream ins ( &fin );
220
// output file writing.
221
QFile fout ( fileName + "#" );
222
if ( !fout.open ( IO_WriteOnly ) )
227
QTextStream outs ( &fout );
230
QRegExp re ( "^(#kdevelop:[ \t]*)?([A-Za-z][@A-Za-z0-9_]*)[ \t]*([:\\+]?=)[ \t]*(.*)$" );
232
bool multiLine = false;
234
QMap<QString, QString> seenLhs;
235
while ( !fin.atEnd() )
237
QString s = ins.readLine();
238
if ( re.exactMatch ( s ) )
240
QString lhs = re.cap ( 2 );
241
bool notFound = ( variables.find ( lhs ) == variables.end() );
245
if ( seenLhs.find ( lhs ) == seenLhs.end() )
247
// not interested in this line at all
248
// write it out as is..
251
// we have seen this variable, but since we are setting the
252
// whole line - we skip this as it will be a += line.
256
// we are interested in this line..
257
QString rhs = re.cap ( 4 ).stripWhiteSpace();
258
if ( rhs[ rhs.length() - 1 ] == '\\' )
260
// save it for when we have the whole line..
266
// deal with it now - a single line
267
// we are adding our interested values to this line and writing it
268
// now write the line out if it is not going to be empty.
269
QString newLine ( lhs );
272
int len = newLine.length();
273
QStringList variableList = QStringList::split ( ' ', variables[lhs] );
274
for ( uint count = 0; count < variableList.size(); count++ )
276
len += variableList[count].length() + 1;
282
newLine += variableList[count];
287
// only print it out if there was a value to add..
290
newLine.setLength ( newLine.length() - 1 );
291
outs << newLine << endl;
293
seenLhs[lhs] = "done";
294
variables.erase ( lhs );
298
else if ( multiLine )
300
s = s.stripWhiteSpace();
301
// we are only here if were interested in this line..
302
if ( s[s.length()-1] == '\\' )
304
s.setLength ( s.length() - 1 );
305
// still more multi line we wait for..
309
// end of the multi line..
315
// we are adding our interested values to this line and writing it
316
// now write the line out if it is not going to be empty.
317
QString newLine ( lastLhs );
320
int len = newLine.length();
321
QStringList variableList = QStringList::split ( ' ', variables[lastLhs] );
322
for ( uint count = 0; count < variableList.size(); count++ )
324
len += variableList[count].length() + 1;
330
newLine += variableList[count];
334
// only print it out if there was a value to add..
337
newLine.setLength ( newLine.length() - 1 );
338
outs << newLine << endl;
340
seenLhs[lastLhs] = "done";
341
variables.erase ( lastLhs );
342
lastLhs.setLength ( 0 );
347
// can write this line out..
348
// not a match, not a multi line,
353
for ( QMap<QString, QString>::Iterator it0 = variables.begin(); it0 != variables.end(); ++it0 )
355
QString newLine ( it0.key() );
358
int len = newLine.length();
359
QStringList variableList = QStringList::split ( ' ', it0.data() );
360
for ( uint count = 0; count < variableList.size(); count++ )
362
len += variableList[count].length() + 1;
368
newLine += variableList[count];
373
// only print it out if there was a value to add..
376
newLine.setLength ( newLine.length() - 1 );
377
outs << newLine << endl;
384
QDir().rename ( fileName + "#", fileName );
389
* Add entries to a variable. Will just add the variables to the existing line, removing duplicates
390
* Will preserve += constructs and make sure that the variable only has one copy of the value across
393
* @param variables key=value string of entries to add
394
* @param add true= add these key,value pairs, false = remove. You can have empty values for an add - the whole line is
395
* removed. For adding, we will not add an empty line.
397
void AutoProjectTool::addRemoveMakefileam(const QString &fileName, QMap<QString, QString> variables, bool add)
399
// input file reading
401
if (!fin.open(IO_ReadOnly))
405
QTextStream ins(&fin);
407
// output file writing.
408
QFile fout(fileName + "#");
409
if (!fout.open(IO_WriteOnly))
414
QTextStream outs(&fout);
417
QRegExp re("^(#kdevelop:[ \t]*)?([A-Za-z][@A-Za-z0-9_]*)[ \t]*([:\\+]?=)[ \t]*(.*)$");
419
// build key=map of values to add
420
// map can be empty.we never add an empty key, but do remove empty keys from the file..
421
QDict< QMap<QString, bool> > interest;
422
for (QMap<QString, QString>::Iterator it0 = variables.begin(); it0 != variables.end(); ++it0)
424
kdDebug(9020) << "key (" << add<<"): " << it0.key() << "="<< it0.data() << endl;
426
QMap<QString, bool>* set = new QMap<QString, bool>();
427
if (!it0.data().stripWhiteSpace().isEmpty())
429
QStringList variableList = QStringList::split(' ', it0.data());
431
for (uint i = 0; i < variableList.count(); i++)
433
set->insert(variableList[i], true);
436
interest.insert(it0.key(), set);
439
bool multiLine = false;
442
QMap<QString, QString> seenLhs;
445
QString s = ins.readLine();
446
if (re.exactMatch(s))
448
QString lhs = re.cap(2);
449
QMap<QString, bool>* ourRhs = interest.find(lhs);
453
// not interested in this line at all
454
// write it out as is..
459
// we are interested in this line..
460
QString rhs = re.cap(4).stripWhiteSpace();
461
if (rhs[ rhs.length() - 1 ] == '\\')
463
// save it for when we have the whole line..
466
rhs.setLength(rhs.length() - 1);
467
lastRhs += QStringList::split(" ", rhs);
473
QStringList bits = QStringList::split(" ", rhs);
476
// we are adding our interested values to this line and writing it
478
// add this line to we we want to add to remove duplicates.
479
for (uint index = 0; index < bits.size(); index++)
481
QMap<QString, bool>::iterator findEntry = ourRhs->find(bits[index]);
482
if (findEntry == ourRhs->end())
484
// we haven't seen it, so add it, so we don't add it again later..
485
ourRhs->insert(bits[index], true);
487
// else we have this value in our 'to add list' , it is either already been
488
// added, so we don't want to add it again, or it hasn't been added, in which
489
// case we will do so soon. so we can ignore this now..
491
// now write the line out if it is not going to be empty.
492
QString newLine(lhs);
493
if (seenLhs.find(lhs) == seenLhs.end())
503
int len = newLine.length();
505
QValueList<QString> keys = ourRhs->keys();
506
for (uint count = 0; count < keys.size(); count++)
508
// if out entry is true, add it..
509
if ((*ourRhs)[keys[count]])
512
len += keys[count].length() + 1;
518
newLine += keys[count];
520
// set our value so we don't add it again.
521
(*ourRhs)[keys[count]] = false;
524
// only print it out if there was a value to add..
527
newLine.setLength(newLine.length() - 1);
528
outs << newLine << endl;
533
// we are removing our interested values from this line
535
// special case - no values, remove the line..
536
if (!ourRhs->empty())
538
// check if any of these values are down to remove.
539
QString newLine(lhs);
540
if (seenLhs.find(lhs) == seenLhs.end())
550
int len = newLine.length();
552
for (QStringList::Iterator posIter = bits.begin(); posIter != bits.end();posIter++)
554
QMap<QString, bool>::iterator findEntry = ourRhs->find(*posIter);
555
if (findEntry == ourRhs->end())
557
// we do not want to remove it..
559
len += (*posIter).length() + 1;
565
newLine += (*posIter);
568
// else we have this value in our 'to remove list', so don't add it.
570
// only print it out if there was a value on it..
573
newLine.setLength(newLine.length() - 1);
574
outs << newLine << endl;
578
}//if ( rhs[ rhs.length() - 1 ] == '\\' )
579
}//if ( found == interest.end())
583
s = s.stripWhiteSpace();
584
// we are only here if were interested in this line..
585
if (s[s.length()-1] == '\\')
587
s.setLength(s.length() - 1);
588
// still more multi line we wait for..
592
// end of the multi line..
595
lastRhs += QStringList::split(" ", s);
599
// now we have to deal with this multiLine value..
600
// ourRhs will always be a value, as we only get multiLine if we're interested in it..
601
QMap<QString, bool>* ourRhs = interest.find(lastLhs);
605
// we are adding our interested values to this line and writing it
607
// add this line to we we want to add to remove duplicates.
608
for (uint index = 0; index < lastRhs.size(); index++)
610
QMap<QString, bool>::iterator findEntry = ourRhs->find(lastRhs[index]);
611
if (findEntry == ourRhs->end())
613
// we haven't seen it, so add it, so we don't add it again later..
614
ourRhs->insert(lastRhs[index], true);
616
// else we have this value in our 'to add list' , it is either already been
617
// added, so we don't want to add it again, or it hasn't been added, in which
618
// case we will do so soon. so we can ignore this now..
620
// now write the line out if it is not going to be empty.
621
QString newLine(lastLhs);
622
if (seenLhs.find(lastLhs) == seenLhs.end())
625
seenLhs[lastLhs] = "";
632
int len = newLine.length();
634
QValueList<QString> keys = ourRhs->keys();
635
for (uint count = 0; count < keys.size(); count++)
637
// if out entry is true, add it..
638
if ((*ourRhs)[keys[count]])
641
len += keys[count].length() + 1;
647
newLine += keys[count];
649
// set our value so we don't add it again.
650
(*ourRhs)[keys[count]] = false;
653
// only print it out if there was a value to add..
656
newLine.setLength(newLine.length() - 1);
657
outs << newLine << endl;
662
// we are removing our interested values from this line
663
// special case - no values, remove the line..
664
if (!ourRhs->empty())
666
// check if any of these values are down to remove.
667
QString newLine(lastLhs);
668
if (seenLhs.find(lastLhs) == seenLhs.end())
671
seenLhs[lastLhs] = "";
677
int len = newLine.length();
679
for (QStringList::Iterator posIter = lastRhs.begin(); posIter != lastRhs.end();posIter++)
681
QMap<QString, bool>::iterator findEntry = ourRhs->find(*posIter);
682
if (findEntry == ourRhs->end())
684
// we do not want to remove it..
686
len += (*posIter).length() + 1;
692
newLine += (*posIter);
695
// else we have this value in our 'to remove list', so don't add it.
697
// only print it out if there was a value on it..
700
newLine.setLength(newLine.length() - 1);
701
outs << newLine << endl;
706
lastLhs.setLength(0);
712
// can write this line out..
713
// not a match, not a multi line,
720
QDictIterator<QMap<QString, bool> > it(interest);
721
for (; it.current(); ++it)
723
QString lhs = it.currentKey();
724
QMap<QString, bool>* ourRhs = it.current();
726
QString newLine(lhs);
727
if (seenLhs.find(lhs) == seenLhs.end())
730
seenLhs[lastLhs] = "";
736
int len = newLine.length();
738
QValueList<QString> keys = ourRhs->keys();
739
for (uint count = 0; count < keys.size(); count++)
741
if ((*ourRhs)[keys[count]])
744
len += keys[count].length() + 1;
750
newLine += keys[count];
752
// set our value so we don't add it again.
753
(*ourRhs)[keys[count]] = false;
756
// only print it out if there was a value to add..
759
newLine.setLength(newLine.length() - 1);
760
outs << newLine << endl;
764
interest.setAutoDelete(true);
770
QDir().rename(fileName + "#", fileName);
774
* Any items in the map will be removed from the Makefile.am
775
* Empty lines are removed. eg. foo_LDDADD if empty is removed.
776
* @param fileName full path to Makefile.am
777
* @param variables lines to remove items from.
779
void AutoProjectTool::removeFromMakefileam(const QString &fileName, QMap <QString, QString> variables)
781
AutoProjectTool::addRemoveMakefileam(fileName, variables, false);
786
* Open the file and parse out the AC_OUTPUT line. following backslash continue lines..
787
* @param configureinpath
788
* @return list of all the values
790
QStringList AutoProjectTool::configureinLoadMakefiles(QString configureinpath)
792
QFile configurein(configureinpath);
794
if (!configurein.open(IO_ReadOnly))
796
kdDebug(9020) << k_funcinfo << " - couldn't open file: " << configureinpath << endl;
797
return QStringList();
800
QTextStream stream(&configurein);
803
QString ac_match("^AC_OUTPUT");
805
QRegExp ac_regex(ac_match);
806
bool multiLine = false;
808
QRegExp close("\\)");
810
while (!stream.eof())
812
QString line = stream.readLine().stripWhiteSpace();
815
if (close.search(line) >= 0)
817
line = line.replace(close.search(line), 1, "");
818
list += QStringList::split(" ", line);
823
if (line.endsWith(cont))
825
line.setLength(line.length() - 1);
827
list += QStringList::split(" ", line);
830
else if (ac_regex.search(line) >= 0)
832
line = line.replace(ac_regex.search(line), ac_match.length() - 1, "");
834
if (open.search(line) >= 0)
836
line = line.replace(open.search(line), 1, "");
839
if (line.endsWith(cont))
841
line.setLength(line.length() - 1);
846
if (close.search(line) >= 0)
848
line = line.replace(close.search(line), 1, "");
852
list = QStringList::split(" ", line);
863
// make a new object on the heap
869
* Write the items to the AC_OUTPUT line. This replaces the exiting line.
870
* @param configureinpath
873
void AutoProjectTool::configureinSaveMakefiles(QString fileName, QStringList makefiles)
875
// input file reading
877
if (!fin.open(IO_ReadOnly))
881
QTextStream ins(&fin);
883
// output file writing.
884
QFile fout(fileName + "#");
885
if (!fout.open(IO_WriteOnly))
890
QTextStream outs(&fout);
892
// remove duplicates if any..
893
QMap<QString, QString> toAdd;
894
for (uint i = 0; i < makefiles.size();i++)
896
toAdd.insert(makefiles[i].stripWhiteSpace(), "");
899
QString ac_match("^AC_OUTPUT");
900
QRegExp ac_regex(ac_match);
901
bool multiLine = false;
903
QRegExp close("\\)");
908
QString line = ins.readLine();
911
outs << line << endl;
917
line = line.stripWhiteSpace();
918
if (close.search(line) >= 0)
921
QString acline("AC_OUTPUT(");
922
for (QMap<QString, QString>::iterator iter = toAdd.begin();iter != toAdd.end();iter++)
924
len += iter.key().length();
930
acline += iter.key();
933
acline.setLength(acline.length() - 1);
934
acline = acline.append(")");
935
outs << acline << endl;
940
if (line.endsWith(cont))
942
line.setLength(line.length() - 1);
946
else if (ac_regex.search(line) >= 0)
948
line = line.stripWhiteSpace();
949
line = line.replace(ac_regex.search(line), ac_match.length() - 1, "");
950
if (line.endsWith(cont))
952
line.setLength(line.length() - 1);
955
if (open.search(line) >= 0)
957
line = line.replace(open.search(line), 1, "");
959
if (close.search(line) >= 0)
961
line = line.replace(close.search(line), 1, "");
967
QString acline("AC_OUTPUT(");
968
for (QMap<QString, QString>::iterator iter = toAdd.begin();iter != toAdd.end();iter++)
970
len += iter.key().length();
976
acline += iter.key();
979
acline.setLength(acline.length() - 1);
980
acline = acline.append(")");
981
outs << acline << endl;
987
outs << line << endl;
995
QDir().rename(fileName + "#", fileName);
999
//kate: indent-mode csands; space-indent off; tab-width 4;