CVS resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / cmCommandArgumentParserHelper.cxx
blob7143f31c8e4ee4da9097ca2e19f840d775660dc6
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCommandArgumentParserHelper.cxx,v $
5 Language: C++
6 Date: $Date: 2007/06/06 20:20:02 $
7 Version: $Revision: 1.20 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmCommandArgumentParserHelper.h"
19 #include "cmSystemTools.h"
20 #include "cmCommandArgumentLexer.h"
22 #include "cmMakefile.h"
24 int cmCommandArgument_yyparse( yyscan_t yyscanner );
26 cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
28 this->FileLine = -1;
29 this->FileName = 0;
30 this->RemoveEmpty = true;
31 this->EmptyVariable[0] = 0;
32 strcpy(this->DCURLYVariable, "${");
33 strcpy(this->RCURLYVariable, "}");
34 strcpy(this->ATVariable, "@");
35 strcpy(this->DOLLARVariable, "$");
36 strcpy(this->LCURLYVariable, "{");
37 strcpy(this->BSLASHVariable, "\\");
39 this->NoEscapeMode = false;
40 this->ReplaceAtSyntax = false;
44 cmCommandArgumentParserHelper::~cmCommandArgumentParserHelper()
46 this->CleanupParser();
49 void cmCommandArgumentParserHelper::SetLineFile(long line, const char* file)
51 this->FileLine = line;
52 this->FileName = file;
55 char* cmCommandArgumentParserHelper::AddString(const char* str)
57 if ( !str || !*str )
59 return this->EmptyVariable;
61 char* stVal = new char[strlen(str)+1];
62 strcpy(stVal, str);
63 this->Variables.push_back(stVal);
64 return stVal;
67 char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key,
68 const char* var)
70 if ( !key )
72 return this->ExpandVariable(var);
74 if ( strcmp(key, "ENV") == 0 )
76 char *ptr = getenv(var);
77 if (ptr)
79 if (this->EscapeQuotes)
81 return this->AddString(cmSystemTools::EscapeQuotes(ptr).c_str());
83 else
85 return ptr;
88 return this->EmptyVariable;
90 cmSystemTools::Error("Key ", key,
91 " is not used yet. For now only $ENV{..} is allowed");
92 return 0;
95 char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
97 if(!var)
99 return 0;
101 if(this->FileName && strcmp(var, "CMAKE_CURRENT_LIST_FILE") == 0)
103 return this->AddString(this->FileName);
105 else if(this->FileLine >= 0 && strcmp(var, "CMAKE_CURRENT_LIST_LINE") == 0)
107 cmOStringStream ostr;
108 ostr << this->FileLine;
109 return this->AddString(ostr.str().c_str());
111 const char* value = this->Makefile->GetDefinition(var);
112 if(!value && !this->RemoveEmpty)
114 return 0;
116 if (this->EscapeQuotes && value)
118 return this->AddString(cmSystemTools::EscapeQuotes(value).c_str());
120 return this->AddString(value);
123 char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
125 if(this->ReplaceAtSyntax)
127 // try to expand the variable
128 char* ret = this->ExpandVariable(var);
129 // if the return was 0 and we want to replace empty strings
130 // then return an empty string
131 if(!ret && this->RemoveEmpty)
133 return this->AddString(ret);
135 // if the ret was not 0, then return it
136 if(ret)
138 return ret;
141 // at this point we want to put it back because of one of these cases:
142 // - this->ReplaceAtSyntax is false
143 // - this->ReplaceAtSyntax is true, but this->RemoveEmpty is false,
144 // and the variable was not defined
145 std::string ref = "@";
146 ref += var;
147 ref += "@";
148 return this->AddString(ref.c_str());
151 char* cmCommandArgumentParserHelper::CombineUnions(char* in1, char* in2)
153 if ( !in1 )
155 return in2;
157 else if ( !in2 )
159 return in1;
161 size_t len = strlen(in1) + strlen(in2) + 1;
162 char* out = new char [ len ];
163 strcpy(out, in1);
164 strcat(out, in2);
165 this->Variables.push_back(out);
166 return out;
169 void cmCommandArgumentParserHelper::AllocateParserType
170 (cmCommandArgumentParserHelper::ParserType* pt,const char* str, int len)
172 pt->str = 0;
173 if ( len == 0 )
175 len = static_cast<int>(strlen(str));
177 if ( len == 0 )
179 return;
181 pt->str = new char[ len + 1 ];
182 strncpy(pt->str, str, len);
183 pt->str[len] = 0;
184 this->Variables.push_back(pt->str);
187 bool cmCommandArgumentParserHelper::HandleEscapeSymbol
188 (cmCommandArgumentParserHelper::ParserType* pt, char symbol)
190 switch ( symbol )
192 case '\\':
193 case '"':
194 case ' ':
195 case '#':
196 case '(':
197 case ')':
198 case '$':
199 case '@':
200 case '^':
201 this->AllocateParserType(pt, &symbol, 1);
202 break;
203 case ';':
204 this->AllocateParserType(pt, "\\;", 2);
205 break;
206 case 't':
207 this->AllocateParserType(pt, "\t", 1);
208 break;
209 case 'n':
210 this->AllocateParserType(pt, "\n", 1);
211 break;
212 case 'r':
213 this->AllocateParserType(pt, "\r", 1);
214 break;
215 case '0':
216 this->AllocateParserType(pt, "\0", 1);
217 break;
218 default:
219 char buffer[2];
220 buffer[0] = symbol;
221 buffer[1] = 0;
222 cmSystemTools::Error("Invalid escape sequence \\", buffer);
223 return false;
225 return true;
228 void cmCommandArgument_SetupEscapes(yyscan_t yyscanner, bool noEscapes);
230 int cmCommandArgumentParserHelper::ParseString(const char* str, int verb)
232 if ( !str)
234 return 0;
236 this->Verbose = verb;
237 this->InputBuffer = str;
238 this->InputBufferPos = 0;
239 this->CurrentLine = 0;
241 this->Result = "";
243 yyscan_t yyscanner;
244 cmCommandArgument_yylex_init(&yyscanner);
245 cmCommandArgument_yyset_extra(this, yyscanner);
246 cmCommandArgument_SetupEscapes(yyscanner, this->NoEscapeMode);
247 int res = cmCommandArgument_yyparse(yyscanner);
248 cmCommandArgument_yylex_destroy(yyscanner);
249 if ( res != 0 )
251 return 0;
254 this->CleanupParser();
256 if ( Verbose )
258 std::cerr << "Expanding [" << str << "] produced: ["
259 << this->Result.c_str() << "]" << std::endl;
261 return 1;
264 void cmCommandArgumentParserHelper::CleanupParser()
266 std::vector<char*>::iterator sit;
267 for ( sit = this->Variables.begin();
268 sit != this->Variables.end();
269 ++ sit )
271 delete [] *sit;
273 this->Variables.erase(this->Variables.begin(), this->Variables.end());
276 int cmCommandArgumentParserHelper::LexInput(char* buf, int maxlen)
278 if ( maxlen < 1 )
280 return 0;
282 if ( this->InputBufferPos < this->InputBuffer.size() )
284 buf[0] = this->InputBuffer[ this->InputBufferPos++ ];
285 if ( buf[0] == '\n' )
287 this->CurrentLine ++;
289 return(1);
291 else
293 buf[0] = '\n';
294 return( 0 );
298 void cmCommandArgumentParserHelper::Error(const char* str)
300 unsigned long pos = static_cast<unsigned long>(this->InputBufferPos);
301 cmOStringStream ostr;
302 ostr << str << " (" << pos << ")";
303 this->ErrorString = ostr.str();
306 void cmCommandArgumentParserHelper::SetMakefile(const cmMakefile* mf)
308 this->Makefile = mf;
311 void cmCommandArgumentParserHelper::SetResult(const char* value)
313 if ( !value )
315 this->Result = "";
316 return;
318 this->Result = value;