1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCommandArgumentParserHelper.cxx,v $
6 Date: $Date: 2009-03-25 14:36:57 $
7 Version: $Revision: 1.23 $
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()
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
)
59 return this->EmptyVariable
;
61 char* stVal
= new char[strlen(str
)+1];
63 this->Variables
.push_back(stVal
);
67 char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key
,
72 return this->ExpandVariable(var
);
74 if ( strcmp(key
, "ENV") == 0 )
76 char *ptr
= getenv(var
);
79 if (this->EscapeQuotes
)
81 return this->AddString(cmSystemTools::EscapeQuotes(ptr
).c_str());
88 return this->EmptyVariable
;
90 if ( strcmp(key
, "CACHE") == 0 )
92 if(const char* c
= this->Makefile
->GetCacheManager()->GetCacheValue(var
))
94 if(this->EscapeQuotes
)
96 return this->AddString(cmSystemTools::EscapeQuotes(c
).c_str());
100 return this->AddString(c
);
103 return this->EmptyVariable
;
106 e
<< "Syntax $" << key
<< "{} is not supported. "
107 << "Only ${}, $ENV{}, and $CACHE{} are allowed.";
108 this->SetError(e
.str());
112 char* cmCommandArgumentParserHelper::ExpandVariable(const char* var
)
118 if(this->FileLine
>= 0 && strcmp(var
, "CMAKE_CURRENT_LIST_LINE") == 0)
120 cmOStringStream ostr
;
121 ostr
<< this->FileLine
;
122 return this->AddString(ostr
.str().c_str());
124 const char* value
= this->Makefile
->GetDefinition(var
);
125 if(!value
&& !this->RemoveEmpty
)
129 if (this->EscapeQuotes
&& value
)
131 return this->AddString(cmSystemTools::EscapeQuotes(value
).c_str());
133 return this->AddString(value
);
136 char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var
)
138 if(this->ReplaceAtSyntax
)
140 // try to expand the variable
141 char* ret
= this->ExpandVariable(var
);
142 // if the return was 0 and we want to replace empty strings
143 // then return an empty string
144 if(!ret
&& this->RemoveEmpty
)
146 return this->AddString(ret
);
148 // if the ret was not 0, then return it
154 // at this point we want to put it back because of one of these cases:
155 // - this->ReplaceAtSyntax is false
156 // - this->ReplaceAtSyntax is true, but this->RemoveEmpty is false,
157 // and the variable was not defined
158 std::string ref
= "@";
161 return this->AddString(ref
.c_str());
164 char* cmCommandArgumentParserHelper::CombineUnions(char* in1
, char* in2
)
174 size_t len
= strlen(in1
) + strlen(in2
) + 1;
175 char* out
= new char [ len
];
178 this->Variables
.push_back(out
);
182 void cmCommandArgumentParserHelper::AllocateParserType
183 (cmCommandArgumentParserHelper::ParserType
* pt
,const char* str
, int len
)
188 len
= static_cast<int>(strlen(str
));
194 pt
->str
= new char[ len
+ 1 ];
195 strncpy(pt
->str
, str
, len
);
197 this->Variables
.push_back(pt
->str
);
200 bool cmCommandArgumentParserHelper::HandleEscapeSymbol
201 (cmCommandArgumentParserHelper::ParserType
* pt
, char symbol
)
214 this->AllocateParserType(pt
, &symbol
, 1);
217 this->AllocateParserType(pt
, "\\;", 2);
220 this->AllocateParserType(pt
, "\t", 1);
223 this->AllocateParserType(pt
, "\n", 1);
226 this->AllocateParserType(pt
, "\r", 1);
229 this->AllocateParserType(pt
, "\0", 1);
234 e
<< "Invalid escape sequence \\" << symbol
;
235 this->SetError(e
.str());
242 void cmCommandArgument_SetupEscapes(yyscan_t yyscanner
, bool noEscapes
);
244 int cmCommandArgumentParserHelper::ParseString(const char* str
, int verb
)
250 this->Verbose
= verb
;
251 this->InputBuffer
= str
;
252 this->InputBufferPos
= 0;
253 this->CurrentLine
= 0;
258 cmCommandArgument_yylex_init(&yyscanner
);
259 cmCommandArgument_yyset_extra(this, yyscanner
);
260 cmCommandArgument_SetupEscapes(yyscanner
, this->NoEscapeMode
);
261 int res
= cmCommandArgument_yyparse(yyscanner
);
262 cmCommandArgument_yylex_destroy(yyscanner
);
268 this->CleanupParser();
272 std::cerr
<< "Expanding [" << str
<< "] produced: ["
273 << this->Result
.c_str() << "]" << std::endl
;
278 void cmCommandArgumentParserHelper::CleanupParser()
280 std::vector
<char*>::iterator sit
;
281 for ( sit
= this->Variables
.begin();
282 sit
!= this->Variables
.end();
287 this->Variables
.erase(this->Variables
.begin(), this->Variables
.end());
290 int cmCommandArgumentParserHelper::LexInput(char* buf
, int maxlen
)
296 if ( this->InputBufferPos
< this->InputBuffer
.size() )
298 buf
[0] = this->InputBuffer
[ this->InputBufferPos
++ ];
299 if ( buf
[0] == '\n' )
301 this->CurrentLine
++;
312 void cmCommandArgumentParserHelper::Error(const char* str
)
314 unsigned long pos
= static_cast<unsigned long>(this->InputBufferPos
);
315 cmOStringStream ostr
;
316 ostr
<< str
<< " (" << pos
<< ")";
317 this->SetError(ostr
.str());
320 void cmCommandArgumentParserHelper::SetMakefile(const cmMakefile
* mf
)
325 void cmCommandArgumentParserHelper::SetResult(const char* value
)
332 this->Result
= value
;
335 void cmCommandArgumentParserHelper::SetError(std::string
const& msg
)
337 // Keep only the first error.
338 if(this->ErrorString
.empty())
340 this->ErrorString
= msg
;