1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmListCommand.cxx,v $
6 Date: $Date: 2008-01-23 15:27:59 $
7 Version: $Revision: 1.17 $
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 "cmListCommand.h"
18 #include <cmsys/RegularExpression.hxx>
19 #include <cmsys/SystemTools.hxx>
21 #include <stdlib.h> // required for atoi
23 //----------------------------------------------------------------------------
25 ::InitialPass(std::vector
<std::string
> const& args
, cmExecutionStatus
&)
29 this->SetError("must be called with at least one argument.");
33 const std::string
&subCommand
= args
[0];
34 if(subCommand
== "LENGTH")
36 return this->HandleLengthCommand(args
);
38 if(subCommand
== "GET")
40 return this->HandleGetCommand(args
);
42 if(subCommand
== "APPEND")
44 return this->HandleAppendCommand(args
);
46 if(subCommand
== "FIND")
48 return this->HandleFindCommand(args
);
50 if(subCommand
== "INSERT")
52 return this->HandleInsertCommand(args
);
54 if(subCommand
== "REMOVE_AT")
56 return this->HandleRemoveAtCommand(args
);
58 if(subCommand
== "REMOVE_ITEM")
60 return this->HandleRemoveItemCommand(args
);
62 if(subCommand
== "SORT")
64 return this->HandleSortCommand(args
);
66 if(subCommand
== "REVERSE")
68 return this->HandleReverseCommand(args
);
71 std::string e
= "does not recognize sub-command "+subCommand
;
72 this->SetError(e
.c_str());
76 //----------------------------------------------------------------------------
77 bool cmListCommand::GetListString(std::string
& listString
, const char* var
)
84 const char* cacheValue
85 = this->Makefile
->GetDefinition(var
);
90 listString
= cacheValue
;
94 //----------------------------------------------------------------------------
95 bool cmListCommand::GetList(std::vector
<std::string
>& list
, const char* var
)
97 std::string listString
;
98 if ( !this->GetListString(listString
, var
) )
102 // expand the variable
103 cmSystemTools::ExpandListArgument(listString
, list
);
107 //----------------------------------------------------------------------------
108 bool cmListCommand::HandleLengthCommand(std::vector
<std::string
> const& args
)
112 this->SetError("sub-command LENGTH requires two arguments.");
116 const std::string
& listName
= args
[1];
117 const std::string
& variableName
= args
[args
.size() - 1];
118 std::vector
<std::string
> varArgsExpanded
;
119 // do not check the return value here
120 // if the list var is not found varArgsExpanded will have size 0
121 // and we will return 0
122 this->GetList(varArgsExpanded
, listName
.c_str());
123 size_t length
= varArgsExpanded
.size();
125 sprintf(buffer
, "%d", static_cast<int>(length
));
127 this->Makefile
->AddDefinition(variableName
.c_str(), buffer
);
131 //----------------------------------------------------------------------------
132 bool cmListCommand::HandleGetCommand(std::vector
<std::string
> const& args
)
136 this->SetError("sub-command GET requires at least three arguments.");
140 const std::string
& listName
= args
[1];
141 const std::string
& variableName
= args
[args
.size() - 1];
142 // expand the variable
143 std::vector
<std::string
> varArgsExpanded
;
144 if ( !this->GetList(varArgsExpanded
, listName
.c_str()) )
146 this->Makefile
->AddDefinition(variableName
.c_str(), "NOTFOUND");
152 for ( cc
= 2; cc
< args
.size()-1; cc
++ )
154 int item
= atoi(args
[cc
].c_str());
159 size_t nitem
= varArgsExpanded
.size();
162 item
= (int)nitem
+ item
;
164 if ( item
< 0 || nitem
<= (size_t)item
)
167 str
<< "index: " << item
<< " out of range (-"
168 << varArgsExpanded
.size() << ", "
169 << varArgsExpanded
.size()-1 << ")";
170 this->SetError(str
.str().c_str());
173 value
+= varArgsExpanded
[item
];
176 this->Makefile
->AddDefinition(variableName
.c_str(), value
.c_str());
180 //----------------------------------------------------------------------------
181 bool cmListCommand::HandleAppendCommand(std::vector
<std::string
> const& args
)
185 this->SetError("sub-command APPEND requires at least one argument.");
189 // Skip if nothing to append.
195 const std::string
& listName
= args
[1];
196 // expand the variable
197 std::string listString
;
198 this->GetListString(listString
, listName
.c_str());
200 for ( cc
= 2; cc
< args
.size(); ++ cc
)
202 if ( listString
.size() )
206 listString
+= args
[cc
];
209 this->Makefile
->AddDefinition(listName
.c_str(), listString
.c_str());
213 //----------------------------------------------------------------------------
214 bool cmListCommand::HandleFindCommand(std::vector
<std::string
> const& args
)
218 this->SetError("sub-command FIND requires three arguments.");
222 const std::string
& listName
= args
[1];
223 const std::string
& variableName
= args
[args
.size() - 1];
224 // expand the variable
225 std::vector
<std::string
> varArgsExpanded
;
226 if ( !this->GetList(varArgsExpanded
, listName
.c_str()) )
228 this->Makefile
->AddDefinition(variableName
.c_str(), "-1");
232 std::vector
<std::string
>::iterator it
;
233 unsigned int index
= 0;
234 for ( it
= varArgsExpanded
.begin(); it
!= varArgsExpanded
.end(); ++ it
)
236 if ( *it
== args
[2] )
238 char indexString
[32];
239 sprintf(indexString
, "%d", index
);
240 this->Makefile
->AddDefinition(variableName
.c_str(), indexString
);
246 this->Makefile
->AddDefinition(variableName
.c_str(), "-1");
250 //----------------------------------------------------------------------------
251 bool cmListCommand::HandleInsertCommand(std::vector
<std::string
> const& args
)
255 this->SetError("sub-command INSERT requires at least three arguments.");
259 const std::string
& listName
= args
[1];
261 // expand the variable
262 int item
= atoi(args
[2].c_str());
263 std::vector
<std::string
> varArgsExpanded
;
264 if ( !this->GetList(varArgsExpanded
, listName
.c_str()) && item
!= 0)
267 str
<< "index: " << item
<< " out of range (0, 0)";
268 this->SetError(str
.str().c_str());
272 if ( varArgsExpanded
.size() != 0 )
274 size_t nitem
= varArgsExpanded
.size();
277 item
= (int)nitem
+ item
;
279 if ( item
< 0 || nitem
<= (size_t)item
)
282 str
<< "index: " << item
<< " out of range (-"
283 << varArgsExpanded
.size() << ", "
284 << (varArgsExpanded
.size() == 0?0:(varArgsExpanded
.size()-1)) << ")";
285 this->SetError(str
.str().c_str());
291 for ( cc
= 3; cc
< args
.size(); ++ cc
)
293 varArgsExpanded
.insert(varArgsExpanded
.begin()+item
+cnt
, args
[cc
]);
298 for ( cc
= 0; cc
< varArgsExpanded
.size(); cc
++ )
304 value
+= varArgsExpanded
[cc
];
307 this->Makefile
->AddDefinition(listName
.c_str(), value
.c_str());
311 //----------------------------------------------------------------------------
313 ::HandleRemoveItemCommand(std::vector
<std::string
> const& args
)
317 this->SetError("sub-command REMOVE_ITEM requires two or more arguments.");
321 const std::string
& listName
= args
[1];
322 // expand the variable
323 std::vector
<std::string
> varArgsExpanded
;
324 if ( !this->GetList(varArgsExpanded
, listName
.c_str()) )
326 this->SetError("sub-command REMOVE_ITEM requires list to be present.");
331 for ( cc
= 2; cc
< args
.size(); ++ cc
)
334 while ( kk
< varArgsExpanded
.size() )
336 if ( varArgsExpanded
[kk
] == args
[cc
] )
338 varArgsExpanded
.erase(varArgsExpanded
.begin()+kk
);
348 for ( cc
= 0; cc
< varArgsExpanded
.size(); cc
++ )
354 value
+= varArgsExpanded
[cc
];
357 this->Makefile
->AddDefinition(listName
.c_str(), value
.c_str());
361 //----------------------------------------------------------------------------
363 ::HandleReverseCommand(std::vector
<std::string
> const& args
)
367 this->SetError("sub-command REVERSE requires a list as an argument.");
371 const std::string
& listName
= args
[1];
372 // expand the variable
373 std::vector
<std::string
> varArgsExpanded
;
374 if ( !this->GetList(varArgsExpanded
, listName
.c_str()) )
376 this->SetError("sub-command REVERSE requires list to be present.");
381 std::vector
<std::string
>::reverse_iterator it
;
382 for ( it
= varArgsExpanded
.rbegin(); it
!= varArgsExpanded
.rend(); ++ it
)
388 value
+= it
->c_str();
391 this->Makefile
->AddDefinition(listName
.c_str(), value
.c_str());
395 //----------------------------------------------------------------------------
397 ::HandleSortCommand(std::vector
<std::string
> const& args
)
401 this->SetError("sub-command SORT requires a list as an argument.");
405 const std::string
& listName
= args
[1];
406 // expand the variable
407 std::vector
<std::string
> varArgsExpanded
;
408 if ( !this->GetList(varArgsExpanded
, listName
.c_str()) )
410 this->SetError("sub-command SORT requires list to be present.");
414 std::sort(varArgsExpanded
.begin(), varArgsExpanded
.end());
417 std::vector
<std::string
>::iterator it
;
418 for ( it
= varArgsExpanded
.begin(); it
!= varArgsExpanded
.end(); ++ it
)
424 value
+= it
->c_str();
427 this->Makefile
->AddDefinition(listName
.c_str(), value
.c_str());
431 //----------------------------------------------------------------------------
432 bool cmListCommand::HandleRemoveAtCommand(
433 std::vector
<std::string
> const& args
)
437 this->SetError("sub-command REMOVE_AT requires at least "
442 const std::string
& listName
= args
[1];
443 // expand the variable
444 std::vector
<std::string
> varArgsExpanded
;
445 if ( !this->GetList(varArgsExpanded
, listName
.c_str()) )
447 this->SetError("sub-command REMOVE_AT requires list to be present.");
452 std::vector
<size_t> removed
;
453 for ( cc
= 2; cc
< args
.size(); ++ cc
)
455 int item
= atoi(args
[cc
].c_str());
456 size_t nitem
= varArgsExpanded
.size();
459 item
= (int)nitem
+ item
;
461 if ( item
< 0 || nitem
<= (size_t)item
)
464 str
<< "index: " << item
<< " out of range (-"
465 << varArgsExpanded
.size() << ", "
466 << varArgsExpanded
.size()-1 << ")";
467 this->SetError(str
.str().c_str());
470 removed
.push_back(static_cast<size_t>(item
));
474 for ( cc
= 0; cc
< varArgsExpanded
.size(); ++ cc
)
478 for ( kk
= 0; kk
< removed
.size(); ++ kk
)
480 if ( cc
== removed
[kk
] )
492 value
+= varArgsExpanded
[cc
];
496 this->Makefile
->AddDefinition(listName
.c_str(), value
.c_str());