1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmCommandArgumentParserHelper.cxx,v $
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()
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 cmSystemTools::Error("Key ", key
,
91 " is not used yet. For now only $ENV{..} is allowed");
95 char* cmCommandArgumentParserHelper::ExpandVariable(const char* var
)
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
)
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
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
= "@";
148 return this->AddString(ref
.c_str());
151 char* cmCommandArgumentParserHelper::CombineUnions(char* in1
, char* in2
)
161 size_t len
= strlen(in1
) + strlen(in2
) + 1;
162 char* out
= new char [ len
];
165 this->Variables
.push_back(out
);
169 void cmCommandArgumentParserHelper::AllocateParserType
170 (cmCommandArgumentParserHelper::ParserType
* pt
,const char* str
, int len
)
175 len
= static_cast<int>(strlen(str
));
181 pt
->str
= new char[ len
+ 1 ];
182 strncpy(pt
->str
, str
, len
);
184 this->Variables
.push_back(pt
->str
);
187 bool cmCommandArgumentParserHelper::HandleEscapeSymbol
188 (cmCommandArgumentParserHelper::ParserType
* pt
, char symbol
)
201 this->AllocateParserType(pt
, &symbol
, 1);
204 this->AllocateParserType(pt
, "\\;", 2);
207 this->AllocateParserType(pt
, "\t", 1);
210 this->AllocateParserType(pt
, "\n", 1);
213 this->AllocateParserType(pt
, "\r", 1);
216 this->AllocateParserType(pt
, "\0", 1);
222 cmSystemTools::Error("Invalid escape sequence \\", buffer
);
228 void cmCommandArgument_SetupEscapes(yyscan_t yyscanner
, bool noEscapes
);
230 int cmCommandArgumentParserHelper::ParseString(const char* str
, int verb
)
236 this->Verbose
= verb
;
237 this->InputBuffer
= str
;
238 this->InputBufferPos
= 0;
239 this->CurrentLine
= 0;
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
);
254 this->CleanupParser();
258 std::cerr
<< "Expanding [" << str
<< "] produced: ["
259 << this->Result
.c_str() << "]" << std::endl
;
264 void cmCommandArgumentParserHelper::CleanupParser()
266 std::vector
<char*>::iterator sit
;
267 for ( sit
= this->Variables
.begin();
268 sit
!= this->Variables
.end();
273 this->Variables
.erase(this->Variables
.begin(), this->Variables
.end());
276 int cmCommandArgumentParserHelper::LexInput(char* buf
, int maxlen
)
282 if ( this->InputBufferPos
< this->InputBuffer
.size() )
284 buf
[0] = this->InputBuffer
[ this->InputBufferPos
++ ];
285 if ( buf
[0] == '\n' )
287 this->CurrentLine
++;
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
)
311 void cmCommandArgumentParserHelper::SetResult(const char* value
)
318 this->Result
= value
;