/***************************************************************************
*   Copyright (C) 2001-2002 by Bernd Gehrmann                             *
*   bernd@kdevelop.org                                                    *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
***************************************************************************/

#include <tqdir.h>
#include <tqfile.h>
#include <tqregexp.h>
#include <tqtextstream.h>
#include <tqdict.h>

#include <kdebug.h>
#include <tdeparts/componentfactory.h>
#include <kservice.h>

#include "misc.h"

#include "kdevcompileroptions.h"


static KDevCompilerOptions *createCompilerOptions( const TQString &name, TQObject *parent )
{
	KService::Ptr service = KService::serviceByDesktopName( name );
	if ( !service )
	{
		kdDebug( 9020 ) << "Can't find service " << name << endl;
		return 0;
	}


    KLibFactory *factory = KLibLoader::self()->factory(TQFile::encodeName(service->library()));
    if (!factory) {
        TQString errorMessage = KLibLoader::self()->lastErrorMessage();
        kdDebug(9020) << "There was an error loading the module " << service->name() << endl <<
	    "The diagnostics is:" << endl << errorMessage << endl;
        exit(1);
    }

    TQStringList args;
    TQVariant prop = service->property("X-TDevelop-Args");
    if (prop.isValid())
        args = TQStringList::split(" ", prop.toString());

    TQObject *obj = factory->create(parent, service->name().latin1(),
                                   "KDevCompilerOptions", args);

    if (!obj->inherits("KDevCompilerOptions")) {
        kdDebug(9020) << "Component does not inherit KDevCompilerOptions" << endl;
        return 0;
    }
    KDevCompilerOptions *dlg = (KDevCompilerOptions*) obj;

    return dlg;

/*
	TQStringList args;
	TQVariant prop = service->property( "X-TDevelop-Args" );
	if ( prop.isValid() )
		args = TQStringList::split( " ", prop.toString() );

	return KParts::ComponentFactory
	       ::createInstanceFromService<KDevCompilerOptions>( service, parent,
	                                                         service->name().latin1(), args );*/
}


TQString AutoProjectTool::execFlagsDialog( const TQString &compiler, const TQString &flags, TQWidget *parent )
{
	KDevCompilerOptions * plugin = createCompilerOptions( compiler, parent );

	if ( plugin )
	{
		TQString newflags = plugin->exec( parent, flags );
		delete plugin;
		return newflags;
	}
	return TQString();
}


TQString AutoProjectTool::canonicalize( const TQString &str )
{
	TQString res;
	for ( uint i = 0; i < str.length(); ++i )
		res += ( str[ i ].isLetterOrNumber() || str[ i ] == '@' ) ? str[ i ] : TQChar( '_' );

	kdDebug(9020) << k_funcinfo << "normalized '" << str << "' to '" << res << "'" << endl;
	return res;
}


/**
 * Read the Makefile.am and return a map of all the variables.
 * Will take notice of backslash and += constructs.
 * @param fileName
 * @param variables
 */
void AutoProjectTool::parseMakefileam(const TQString &fileName, TQMap<TQString, TQString> *variables)
{
	TQFile f(fileName);
	if (!f.open(IO_ReadOnly))
	{
		return ;
	}
	TQTextStream stream(&f);

	TQRegExp re("^(#tdevelop:[ \t]*)?([A-Za-z][@A-Za-z0-9_]*)[ \t]*([:\\+]?=)[ \t]*(.*)$");

	TQString last;
	bool multiLine = false;
	while (!stream.atEnd())
	{
		TQString s = stream.readLine().stripWhiteSpace();
		if (re.exactMatch(s))
		{
			TQString lhs = re.cap(2);
			TQString rhs = re.cap(4);
			if (rhs[ rhs.length() - 1 ] == '\\')
			{
				multiLine = true;
				last = lhs;
				rhs[rhs.length() - 1] = ' ';
			}

			// The need for stripWhiteSpace seems to be a TQt bug.
			// make our list nice and neat.
			TQStringList bits = TQStringList::split(" ", rhs);
			rhs = bits.join(" ");
			if (re.cap(3) == "+=")
			{
				((*variables)[lhs] += ' ') += rhs;
			}
			else
			{
				variables->insert(lhs, rhs);
			}
		}
		else if (multiLine)
		{
			if (s[s.length()-1] == '\\')
			{
				s[s.length()-1] = ' ';
			}
			else
			{
				multiLine = false;
			}
			TQStringList bits = TQStringList::split(" ", s);
			((*variables)[last] += ' ') += bits.join(" ");
		}
	}
	f.close();

	TQMap<TQString, TQString> list;

	for (TQMap<TQString, TQString>::iterator iter = variables->begin();iter != variables->end();iter++)
	{
		TQStringList items = TQStringList::split(" ", iter.data());
		TQMap<TQString, TQString> unique;
		for (uint i = 0;i < items.size();i++)
		{
			unique.insert(items[i], "");
		}
		TQString line;
		for (TQMap<TQString, TQString>::iterator it = unique.begin();it != unique.end();it++)
		{
			line += it.key() + ' ';
		}
		if (line.length() > 1)
		{
			line.setLength(line.length() - 1);
		}

		list.insert(iter.key(), line);
	}
	*variables = list;
}

/**
 * Add entries to a variable. Will just add the variables to the existing line, removing duplicates
 * Will preserve += constructs and make sure that the variable only has one copy of the value across
 * all += constructs
 * @param fileName
 * @param variables key=value string of entries to add
 */
void AutoProjectTool::addToMakefileam(const TQString &fileName, TQMap<TQString, TQString> variables)
{
	AutoProjectTool::addRemoveMakefileam(fileName,  variables,  true);
}

/**
 * Set entries to a variable. Will set the variables to the existing line, removing duplicates
 * Will preserve += constructs and make sure that the variable only has one copy of the value across
 * all += constructs
 * Adds line if it does not exist.
 * @param fileName
 * @param variables key=value string of entries to add
 */
void AutoProjectTool::setMakefileam ( const TQString &fileName, TQMap<TQString, TQString> variables )
{
	for ( TQMap<TQString, TQString>::Iterator it0 = variables.begin(); it0 != variables.end(); ++it0 )
	{
		kdDebug ( 9020 ) << "key (set): " << it0.key() << "=" << it0.data() << endl;
	}

	// input file reading
	TQFile fin ( fileName );
	if ( !fin.open ( IO_ReadOnly ) )
	{
		return ;
	}
	TQTextStream ins ( &fin );

	// output file writing.
	TQFile fout ( fileName + "#" );
	if ( !fout.open ( IO_WriteOnly ) )
	{
		fin.close();
		return ;
	}
	TQTextStream outs ( &fout );

	// variables
	TQRegExp re ( "^(#tdevelop:[ \t]*)?([A-Za-z][@A-Za-z0-9_]*)[ \t]*([:\\+]?=)[ \t]*(.*)$" );

	bool multiLine = false;
	TQString lastLhs;
	TQMap<TQString, TQString> seenLhs;
	while ( !fin.atEnd() )
	{
		TQString s = ins.readLine();
		if ( re.exactMatch ( s ) )
		{
			TQString lhs = re.cap ( 2 );
			bool notFound = ( variables.find ( lhs ) == variables.end() );

			if ( notFound )
			{
				if ( seenLhs.find ( lhs ) == seenLhs.end() )
				{
					// not interested in this line at all
					// write it out as is..
					outs << s << endl;
				}
				// we have seen this variable, but since we are setting the
				// whole line - we skip this as it will be a += line.
			}
			else
			{
				// we are interested in this line..
				TQString rhs = re.cap ( 4 ).stripWhiteSpace();
				if ( rhs[ rhs.length() - 1 ] == '\\' )
				{
					// save it for when we have the whole line..
					multiLine = true;
					lastLhs = lhs;
				}
				else
				{
					// deal with it now - a single line
					// we are adding our interested values to this line and writing it
					// now write the line out if it is not going to be empty.
					TQString newLine ( lhs );
					newLine += " = ";
					bool added = false;
					int len = newLine.length();
					TQStringList variableList = TQStringList::split ( ' ', variables[lhs] );
					for ( uint count = 0; count < variableList.size(); count++ )
					{
						len += variableList[count].length() + 1;
						if ( len > 80 )
						{
							newLine += "\\\n\t";
							len = 8;
						}
						newLine += variableList[count];
						newLine += ' ';
						added = true;

					}
					// only print it out if there was a value to add..
					if ( added )
					{
						newLine.setLength ( newLine.length() - 1 );
						outs << newLine << endl;
					}
					seenLhs[lhs] = "done";
					variables.erase ( lhs );
				}
			}
		}
		else if ( multiLine )
		{
			s = s.stripWhiteSpace();
			// we are only here if were interested in this line..
			if ( s[s.length()-1] == '\\' )
			{
				s.setLength ( s.length() - 1 );
				// still more multi line we wait for..
			}
			else
			{
				// end of the multi line..
				multiLine = false;
			}

			if ( !multiLine )
			{
				// we are adding our interested values to this line and writing it
				// now write the line out if it is not going to be empty.
				TQString newLine ( lastLhs );
				newLine += " = ";
				bool added = false;
				int len = newLine.length();
				TQStringList variableList = TQStringList::split ( ' ', variables[lastLhs] );
				for ( uint count = 0; count < variableList.size(); count++ )
				{
					len += variableList[count].length() + 1;
					if ( len > 80 )
					{
						newLine += "\\\n\t";
						len = 8;
					}
					newLine += variableList[count];
					newLine += ' ';
					added = true;
				}
				// only print it out if there was a value to add..
				if ( added )
				{
					newLine.setLength ( newLine.length() - 1 );
					outs << newLine << endl;
				}
				seenLhs[lastLhs] = "done";
				variables.erase ( lastLhs );
				lastLhs.setLength ( 0 );
			}
		}
		else
		{
			// can write this line out..
			// not a match, not a multi line,
			outs << s << endl;
		}
	}

	for ( TQMap<TQString, TQString>::Iterator it0 = variables.begin(); it0 != variables.end(); ++it0 )
	{
		TQString newLine ( it0.key() );
		newLine += " = ";
		bool added = false;
		int len = newLine.length();
		TQStringList variableList = TQStringList::split ( ' ', it0.data() );
		for ( uint count = 0; count < variableList.size(); count++ )
		{
			len += variableList[count].length() + 1;
			if ( len > 80 )
			{
				newLine += "\\\n\t";
				len = 8;
			}
			newLine += variableList[count];
			newLine += ' ';
			added = true;

		}
		// only print it out if there was a value to add..
		if ( added )
		{
			newLine.setLength ( newLine.length() - 1 );
			outs << newLine << endl;
		}
	}

	fin.close();
	fout.close();

	TQDir().rename ( fileName + "#", fileName );
}


/**
 * Add entries to a variable. Will just add the variables to the existing line, removing duplicates
 * Will preserve += constructs and make sure that the variable only has one copy of the value across
 * all += constructs
 * @param fileName
 * @param variables key=value string of entries to add
 * @param add true= add these key,value pairs, false = remove. You can have empty values for an add - the whole line is
 * removed. For adding, we will not add an empty line.
 */
void AutoProjectTool::addRemoveMakefileam(const TQString &fileName, TQMap<TQString, TQString> variables,  bool add)
{
	// input file reading
	TQFile fin(fileName);
	if (!fin.open(IO_ReadOnly))
	{
		return ;
	}
	TQTextStream ins(&fin);

	// output file writing.
	TQFile fout(fileName + "#");
	if (!fout.open(IO_WriteOnly))
	{
		fin.close();
		return ;
	}
	TQTextStream outs(&fout);

	// variables
	TQRegExp re("^(#tdevelop:[ \t]*)?([A-Za-z][@A-Za-z0-9_]*)[ \t]*([:\\+]?=)[ \t]*(.*)$");

	// build key=map of values to add
	// map can be empty.we never add an empty key, but do remove empty keys from the file..
	TQDict< TQMap<TQString, bool> > interest;
	for (TQMap<TQString, TQString>::Iterator it0 = variables.begin(); it0 != variables.end(); ++it0)
	{
		kdDebug(9020) << "key (" << add<<"): " << it0.key() << "="<< it0.data() << endl;

		TQMap<TQString, bool>* set = new TQMap<TQString, bool>();
		if (!it0.data().stripWhiteSpace().isEmpty())
		{
			TQStringList variableList = TQStringList::split(' ', it0.data());

			for (uint i = 0; i < variableList.count(); i++)
			{
				set->insert(variableList[i], true);
			}
		}
		interest.insert(it0.key(), set);
	}

	bool multiLine = false;
	TQString lastLhs;
	TQStringList lastRhs;
	TQMap<TQString, TQString> seenLhs;
	while (!fin.atEnd())
	{
		TQString s = ins.readLine();
		if (re.exactMatch(s))
		{
			TQString lhs = re.cap(2);
			TQMap<TQString, bool>* ourRhs = interest.find(lhs);

			if (!ourRhs)
			{
				// not interested in this line at all
				// write it out as is..
				outs << s << endl;
			}
			else
			{
				// we are interested in this line..
				TQString rhs = re.cap(4).stripWhiteSpace();
				if (rhs[ rhs.length() - 1 ] == '\\')
				{
					// save it for when we have the whole line..
					multiLine = true;
					lastLhs = lhs;
					rhs.setLength(rhs.length() - 1);
					lastRhs += TQStringList::split(" ", rhs);
				}
				else
				{
					// deal with it now.

					TQStringList bits = TQStringList::split(" ", rhs);
					if (add)
					{
						// we are adding our interested values to this line and writing it

						// add this line to we we want to add to remove duplicates.
						for (uint index = 0; index < bits.size(); index++)
						{
							TQMap<TQString, bool>::iterator findEntry = ourRhs->find(bits[index]);
							if (findEntry == ourRhs->end())
							{
								// we haven't seen it, so add it, so we don't add it again later..
								ourRhs->insert(bits[index], true);
							}
							// else we have this value in our 'to add list' , it is either already been
							// added, so we don't want to add it again, or it hasn't been added, in which
							// case we will do so soon. so we can ignore this now..
						}
						// now write the line out if it is not going to be empty.
						TQString newLine(lhs);
						if (seenLhs.find(lhs) == seenLhs.end())
						{
							newLine += " = ";
							seenLhs[lhs] = "";
						}
						else
						{
							newLine += " += ";
						}

						int len = newLine.length();
						bool added = false;
						TQValueList<TQString> keys = ourRhs->keys();
						for (uint count = 0; count < keys.size(); count++)
						{
							// if out entry is true, add it..
							if ((*ourRhs)[keys[count]])
							{
								added = true;
								len += keys[count].length() + 1;
								if (len > 80)
								{
									newLine += "\\\n\t";
									len = 8;
								}
								newLine += keys[count];
								newLine += ' ';
								// set our value so we don't add it again.
								(*ourRhs)[keys[count]] = false;
							}
						}
						// only print it out if there was a value to add..
						if (added)
						{
							newLine.setLength(newLine.length() - 1);
							outs << newLine << endl;
						}
					}
					else
					{
						// we are removing our interested values from this line

						// special case - no values, remove the line..
						if (!ourRhs->empty())
						{
							// check if any of these values are down to remove.
							TQString newLine(lhs);
							if (seenLhs.find(lhs) == seenLhs.end())
							{
								newLine += " = ";
								seenLhs[lhs] = "";
							}
							else
							{
								newLine += " += ";
							}

							int len = newLine.length();
							bool added = false;
							for (TQStringList::Iterator posIter = bits.begin(); posIter != bits.end();posIter++)
							{
								TQMap<TQString, bool>::iterator findEntry = ourRhs->find(*posIter);
								if (findEntry == ourRhs->end())
								{
									// we do not want to remove it..
									added = true;
									len += (*posIter).length() + 1;
									if (len > 80)
									{
										newLine += "\\\n\t";
										len = 8;
									}
									newLine += (*posIter);
									newLine += ' ';
								}
								// else we have this value in our 'to remove list', so don't add it.
							}
							// only print it out if there was a value on it..
							if (added)
							{
								newLine.setLength(newLine.length() - 1);
								outs << newLine << endl;
							}
						}
					}//if (add)
				}//if ( rhs[ rhs.length() - 1 ] == '\\'  )
			}//if ( found == interest.end())
		}
		else if (multiLine)
		{
			s = s.stripWhiteSpace();
			// we are only here if were interested in this line..
			if (s[s.length()-1] == '\\')
			{
				s.setLength(s.length() - 1);
				// still more multi line we wait for..
			}
			else
			{
				// end of the multi line..
				multiLine = false;
			}
			lastRhs += TQStringList::split(" ", s);

			if (!multiLine)
			{
				// now we have to deal with this multiLine value..
				// ourRhs will always be a value, as we only get multiLine if we're interested in it..
				TQMap<TQString, bool>* ourRhs = interest.find(lastLhs);

				if (add)
				{
					// we are adding our interested values to this line and writing it

					// add this line to we we want to add to remove duplicates.
					for (uint index = 0; index < lastRhs.size(); index++)
					{
						TQMap<TQString, bool>::iterator findEntry = ourRhs->find(lastRhs[index]);
						if (findEntry == ourRhs->end())
						{
							// we haven't seen it, so add it, so we don't add it again later..
							ourRhs->insert(lastRhs[index], true);
						}
						// else we have this value in our 'to add list' , it is either already been
						// added, so we don't want to add it again, or it hasn't been added, in which
						// case we will do so soon. so we can ignore this now..
					}
					// now write the line out if it is not going to be empty.
					TQString newLine(lastLhs);
					if (seenLhs.find(lastLhs) == seenLhs.end())
					{
						newLine += " = ";
						seenLhs[lastLhs] = "";
					}
					else
					{
						newLine += " += ";
					}

					int len = newLine.length();
					bool added = false;
					TQValueList<TQString> keys = ourRhs->keys();
					for (uint count = 0; count < keys.size(); count++)
					{
						// if out entry is true, add it..
						if ((*ourRhs)[keys[count]])
						{
							added = true;
							len += keys[count].length() + 1;
							if (len > 80)
							{
								newLine += "\\\n\t";
								len = 8;
							}
							newLine += keys[count];
							newLine += ' ';
							// set our value so we don't add it again.
							(*ourRhs)[keys[count]] = false;
						}
					}
					// only print it out if there was a value to add..
					if (added)
					{
						newLine.setLength(newLine.length() - 1);
						outs << newLine << endl;
					}
				}
				else
				{
					// we are removing our interested values from this line
					// special case - no values, remove the line..
					if (!ourRhs->empty())
					{
						// check if any of these values are down to remove.
						TQString newLine(lastLhs);
						if (seenLhs.find(lastLhs) == seenLhs.end())
						{
							newLine += " = ";
							seenLhs[lastLhs] = "";
						}
						else
						{
							newLine += " += ";
						}
						int len = newLine.length();
						bool added = false;
						for (TQStringList::Iterator posIter = lastRhs.begin(); posIter != lastRhs.end();posIter++)
						{
							TQMap<TQString, bool>::iterator findEntry = ourRhs->find(*posIter);
							if (findEntry == ourRhs->end())
							{
								// we do not want to remove it..
								added = true;
								len += (*posIter).length() + 1;
								if (len > 80)
								{
									newLine += "\\\n\t";
									len = 8;
								}
								newLine += (*posIter);
								newLine += ' ';
							}
							// else we have this value in our 'to remove list', so don't add it.
						}
						// only print it out if there was a value on it..
						if (added)
						{
							newLine.setLength(newLine.length() - 1);
							outs << newLine << endl;
						}
					}
				}

				lastLhs.setLength(0);
				lastRhs.clear();
			}
		}
		else
		{
			// can write this line out..
			// not a match, not a multi line,
			outs << s << endl;
		}
	}

	if (add)
	{
		TQDictIterator<TQMap<TQString, bool> > it(interest);
		for (; it.current(); ++it)
		{
			TQString lhs = it.currentKey();
			TQMap<TQString, bool>* ourRhs = it.current();

			TQString newLine(lhs);
			if (seenLhs.find(lhs) == seenLhs.end())
			{
				newLine += " = ";
				seenLhs[lastLhs] = "";
			}
			else
			{
				newLine += " += ";
			}
			int len = newLine.length();
			bool added = false;
			TQValueList<TQString> keys = ourRhs->keys();
			for (uint count = 0; count < keys.size(); count++)
			{
				if ((*ourRhs)[keys[count]])
				{
					added = true;
					len += keys[count].length() + 1;
					if (len > 80)
					{
						newLine += "\\\n\t";
						len = 8;
					}
					newLine += keys[count];
					newLine += ' ';
					// set our value so we don't add it again.
					(*ourRhs)[keys[count]] = false;
				}
			}
			// only print it out if there was a value to add..
			if (added)
			{
				newLine.setLength(newLine.length() - 1);
				outs << newLine << endl;
			}
		}
	}
	interest.setAutoDelete(true);
	interest.clear();

	fin.close();
	fout.close();

	TQDir().rename(fileName + "#", fileName);
}

/**
 * Any items in the map will be removed from the Makefile.am
 * Empty lines are removed. eg. foo_LDDADD if empty is removed.
 * @param fileName full path to Makefile.am
 * @param variables lines to remove items from.
 */
void AutoProjectTool::removeFromMakefileam(const TQString &fileName, TQMap <TQString, TQString> variables)
{
	AutoProjectTool::addRemoveMakefileam(fileName, variables,  false);
}


/**
 * Open the file and parse out the AC_OUTPUT line. following backslash continue lines..
 * @param configureinpath
 * @return list of all the values
 */
TQStringList AutoProjectTool::configureinLoadMakefiles(TQString configureinpath)
{
	TQFile configurein(configureinpath);

	if (!configurein.open(IO_ReadOnly))
	{
		kdDebug(9020) << k_funcinfo << " - couldn't open file: " << configureinpath << endl;
		return TQStringList();
	}

	TQTextStream stream(&configurein);
	TQStringList list;

	TQString ac_match("^AC_OUTPUT");

	TQRegExp ac_regex(ac_match);
	bool multiLine = false;
	TQChar cont('\\');
	TQRegExp close("\\)");
	TQRegExp open("\\(");
	while (!stream.eof())
	{
		TQString line = stream.readLine().stripWhiteSpace();
		if (multiLine)
		{
			if (close.search(line) >= 0)
			{
				line = line.replace(close.search(line), 1, "");
				list += TQStringList::split(" ", line);
				break;
			}
			else
			{
				if (line.endsWith(cont))
				{
					line.setLength(line.length() - 1);
				}
				list += TQStringList::split(" ", line);
			}
		}
		else if (ac_regex.search(line) >= 0)
		{
			line = line.replace(ac_regex.search(line), ac_match.length() - 1, "");

			if (open.search(line) >= 0)
			{
				line = line.replace(open.search(line), 1, "");
			}

			if (line.endsWith(cont))
			{
				line.setLength(line.length() - 1);
				multiLine = true;
			}
			else
			{
				if (close.search(line) >= 0)
				{
					line = line.replace(close.search(line), 1, "");
				}
			}

			list = TQStringList::split(" ", line);

			if (!multiLine)
			{
				break;
			}
		}
	}

	configurein.close();

	// make a new object on the heap
	return list;

}

/**
 * Write the items to the AC_OUTPUT line. This replaces the exiting line.
 * @param configureinpath
 * @param makefiles
 */
void AutoProjectTool::configureinSaveMakefiles(TQString fileName, TQStringList makefiles)
{
	// input file reading
	TQFile fin(fileName);
	if (!fin.open(IO_ReadOnly))
	{
		return ;
	}
	TQTextStream ins(&fin);

	// output file writing.
	TQFile fout(fileName + "#");
	if (!fout.open(IO_WriteOnly))
	{
		fin.close();
		return ;
	}
	TQTextStream outs(&fout);

	// remove duplicates if any..
	TQMap<TQString, TQString> toAdd;
	for (uint i = 0; i < makefiles.size();i++)
	{
		toAdd.insert(makefiles[i].stripWhiteSpace(), "");
	}

	TQString ac_match("^AC_OUTPUT");
	TQRegExp ac_regex(ac_match);
	bool multiLine = false;
	TQChar cont('\\');
	TQRegExp close("\\)");
	TQRegExp open("\\(");
	bool done = false;
	while (!fin.atEnd())
	{
		TQString line = ins.readLine();
		if (done)
		{
			outs << line << endl;
		}
		else
		{
			if (multiLine)
			{
				line = line.stripWhiteSpace();
				if (close.search(line) >= 0)
				{
					int len = 10;
					TQString acline("AC_OUTPUT(");
					for (TQMap<TQString, TQString>::iterator iter = toAdd.begin();iter != toAdd.end();iter++)
					{
						len += iter.key().length();
						if (len > 80)
						{
							acline += "\\\n\t";
							len = 8;
						}
						acline += iter.key();
						acline += ' ';
					}
					acline.setLength(acline.length() - 1);
					acline = acline.append(")");
					outs  << acline << endl;
					done = true;
				}
				else
				{
					if (line.endsWith(cont))
					{
						line.setLength(line.length() - 1);
					}
				}
			}
			else if (ac_regex.search(line) >= 0)
			{
				line = line.stripWhiteSpace();
				line = line.replace(ac_regex.search(line), ac_match.length() - 1, "");
				if (line.endsWith(cont))
				{
					line.setLength(line.length() - 1);
					multiLine = true;
				}
				if (open.search(line) >= 0)
				{
					line = line.replace(open.search(line), 1, "");
				}
				if (close.search(line) >= 0)
				{
					line = line.replace(close.search(line), 1, "");
				}

				if (!multiLine)
				{
					int len = 10;
					TQString acline("AC_OUTPUT(");
					for (TQMap<TQString, TQString>::iterator iter = toAdd.begin();iter != toAdd.end();iter++)
					{
						len += iter.key().length();
						if (len > 80)
						{
							acline += "\\\n\t";
							len = 8;
						}
						acline += iter.key();
						acline += ' ';
					}
					acline.setLength(acline.length() - 1);
					acline = acline.append(")");
					outs << acline << endl;
					done = true;
				}
			}
			else
			{
				outs << line << endl;
			}
		}
	}

	fin.close();
	fout.close();

	TQDir().rename(fileName + "#", fileName);

}
