packaging: Initial packaging
[platform/upstream/cmake.git] / Source / cmCPluginAPI.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 /*
13    this file contains the implementation of the C API to CMake. Generally
14    these routines just manipulate arguments and then call the associated
15    methods on the CMake classes. */
16
17 #include "cmMakefile.h"
18 #include "cmCPluginAPI.h"
19 #include "cmVersion.h"
20
21 #include "cmSourceFile.h"
22
23 #include <stdlib.h>
24
25 #ifdef __QNX__
26 # include <malloc.h> /* for malloc/free on QNX */
27 #endif
28
29 extern "C"
30 {
31
32 void CCONV *cmGetClientData(void *info)
33 {
34   return ((cmLoadedCommandInfo *)info)->ClientData;
35 }
36
37 void CCONV cmSetClientData(void *info, void *cd)
38 {
39   ((cmLoadedCommandInfo *)info)->ClientData = cd;
40 }
41
42 void CCONV cmSetError(void *info, const char *err)
43 {
44   if (((cmLoadedCommandInfo *)info)->Error)
45     {
46     free(((cmLoadedCommandInfo *)info)->Error);
47     }
48   ((cmLoadedCommandInfo *)info)->Error = strdup(err);
49 }
50
51 unsigned int CCONV  cmGetCacheMajorVersion(void *arg)
52 {
53   cmMakefile *mf = static_cast<cmMakefile *>(arg);
54   return mf->GetCacheMajorVersion();
55 }
56 unsigned int CCONV cmGetCacheMinorVersion(void *arg)
57 {
58   cmMakefile *mf = static_cast<cmMakefile *>(arg);
59   return mf->GetCacheMinorVersion();
60 }
61
62 unsigned int CCONV cmGetMajorVersion(void *)
63 {
64   return cmVersion::GetMajorVersion();
65 }
66
67 unsigned int CCONV cmGetMinorVersion(void *)
68 {
69   return cmVersion::GetMinorVersion();
70 }
71
72 void CCONV cmAddDefinition(void *arg, const char* name, const char* value)
73 {
74   cmMakefile *mf = static_cast<cmMakefile *>(arg);
75   mf->AddDefinition(name,value);
76 }
77
78 /* Add a definition to this makefile and the global cmake cache. */
79 void CCONV cmAddCacheDefinition(void *arg, const char* name,
80   const char* value, const char* doc, int type)
81 {
82   cmMakefile *mf = static_cast<cmMakefile *>(arg);
83
84   switch (type)
85     {
86     case CM_CACHE_BOOL:
87       mf->AddCacheDefinition(name,value,doc,
88                              cmCacheManager::BOOL);
89       break;
90     case CM_CACHE_PATH:
91       mf->AddCacheDefinition(name,value,doc,
92                              cmCacheManager::PATH);
93       break;
94     case CM_CACHE_FILEPATH:
95       mf->AddCacheDefinition(name,value,doc,
96                              cmCacheManager::FILEPATH);
97       break;
98     case CM_CACHE_STRING:
99       mf->AddCacheDefinition(name,value,doc,
100                              cmCacheManager::STRING);
101       break;
102     case CM_CACHE_INTERNAL:
103       mf->AddCacheDefinition(name,value,doc,
104                              cmCacheManager::INTERNAL);
105       break;
106     case CM_CACHE_STATIC:
107       mf->AddCacheDefinition(name,value,doc,
108                              cmCacheManager::STATIC);
109       break;
110     }
111 }
112
113 const char* CCONV cmGetProjectName(void *arg)
114 {
115   cmMakefile *mf = static_cast<cmMakefile *>(arg);
116   return mf->GetProjectName();
117 }
118
119 const char* CCONV cmGetHomeDirectory(void *arg)
120 {
121   cmMakefile *mf = static_cast<cmMakefile *>(arg);
122   return mf->GetHomeDirectory();
123 }
124 const char* CCONV cmGetHomeOutputDirectory(void *arg)
125 {
126   cmMakefile *mf = static_cast<cmMakefile *>(arg);
127   return mf->GetHomeOutputDirectory();
128 }
129 const char* CCONV cmGetStartDirectory(void *arg)
130 {
131   cmMakefile *mf = static_cast<cmMakefile *>(arg);
132   return mf->GetStartDirectory();
133 }
134 const char* CCONV cmGetStartOutputDirectory(void *arg)
135 {
136   cmMakefile *mf = static_cast<cmMakefile *>(arg);
137   return mf->GetStartOutputDirectory();
138 }
139 const char* CCONV cmGetCurrentDirectory(void *arg)
140 {
141   cmMakefile *mf = static_cast<cmMakefile *>(arg);
142   return mf->GetCurrentDirectory();
143 }
144 const char* CCONV cmGetCurrentOutputDirectory(void *arg)
145 {
146   cmMakefile *mf = static_cast<cmMakefile *>(arg);
147   return mf->GetCurrentOutputDirectory();
148 }
149 const char* CCONV cmGetDefinition(void *arg,const char*def)
150 {
151   cmMakefile *mf = static_cast<cmMakefile *>(arg);
152   return mf->GetDefinition(def);
153 }
154
155 int CCONV cmIsOn(void *arg, const char* name)
156 {
157   cmMakefile *mf = static_cast<cmMakefile *>(arg);
158   return static_cast<int>(mf->IsOn(name));
159 }
160
161 /** Check if a command exists. */
162 int CCONV cmCommandExists(void *arg, const char* name)
163 {
164   cmMakefile *mf = static_cast<cmMakefile *>(arg);
165   return static_cast<int>(mf->CommandExists(name));
166 }
167
168 void CCONV cmAddDefineFlag(void *arg, const char* definition)
169 {
170   cmMakefile *mf = static_cast<cmMakefile *>(arg);
171   mf->AddDefineFlag(definition);
172 }
173
174 void CCONV cmAddLinkDirectoryForTarget(void *arg, const char *tgt,
175   const char* d)
176 {
177   cmMakefile *mf = static_cast<cmMakefile *>(arg);
178   mf->AddLinkDirectoryForTarget(tgt,d);
179 }
180
181
182 void CCONV cmAddExecutable(void *arg, const char *exename,
183                      int numSrcs, const char **srcs, int win32)
184 {
185   cmMakefile *mf = static_cast<cmMakefile *>(arg);
186   std::vector<std::string> srcs2;
187   int i;
188   for (i = 0; i < numSrcs; ++i)
189     {
190     srcs2.push_back(srcs[i]);
191     }
192  cmTarget* tg =  mf->AddExecutable(exename, srcs2);
193  if ( win32 )
194    {
195    tg->SetProperty("WIN32_EXECUTABLE", "ON");
196    }
197 }
198
199 void CCONV cmAddUtilityCommand(void *arg, const char* utilityName,
200                          const char* command,
201                          const char* arguments,
202                          int all,
203                          int numDepends,
204                          const char **depends,
205                          int,
206                          const char **)
207 {
208   // Get the makefile instance.  Perform an extra variable expansion
209   // now because the API caller expects it.
210   cmMakefile* mf = static_cast<cmMakefile*>(arg);
211
212   // Construct the command line for the command.
213   cmCustomCommandLine commandLine;
214   std::string expand = command;
215   commandLine.push_back(mf->ExpandVariablesInString(expand));
216   if(arguments && arguments[0])
217     {
218     // TODO: Parse arguments!
219     expand = arguments;
220     commandLine.push_back(mf->ExpandVariablesInString(expand));
221     }
222   cmCustomCommandLines commandLines;
223   commandLines.push_back(commandLine);
224
225   // Accumulate the list of dependencies.
226   std::vector<std::string> depends2;
227   for(int i = 0; i < numDepends; ++i)
228     {
229     expand = depends[i];
230     depends2.push_back(mf->ExpandVariablesInString(expand));
231     }
232
233   // Pass the call to the makefile instance.
234   mf->AddUtilityCommand(utilityName, (all ? false : true),
235                         0, depends2, commandLines);
236 }
237 void CCONV cmAddCustomCommand(void *arg, const char* source,
238                         const char* command,
239                         int numArgs, const char **args,
240                         int numDepends, const char **depends,
241                         int numOutputs, const char **outputs,
242                         const char *target)
243 {
244   // Get the makefile instance.  Perform an extra variable expansion
245   // now because the API caller expects it.
246   cmMakefile* mf = static_cast<cmMakefile*>(arg);
247
248   // Construct the command line for the command.
249   cmCustomCommandLine commandLine;
250   std::string expand = command;
251   commandLine.push_back(mf->ExpandVariablesInString(expand));
252   for(int i=0; i < numArgs; ++i)
253     {
254     expand = args[i];
255     commandLine.push_back(mf->ExpandVariablesInString(expand));
256     }
257   cmCustomCommandLines commandLines;
258   commandLines.push_back(commandLine);
259
260   // Accumulate the list of dependencies.
261   std::vector<std::string> depends2;
262   for(int i = 0; i < numDepends; ++i)
263     {
264     expand = depends[i];
265     depends2.push_back(mf->ExpandVariablesInString(expand));
266     }
267
268   // Accumulate the list of outputs.
269   std::vector<std::string> outputs2;
270   for(int i = 0; i < numOutputs; ++i)
271     {
272     expand = outputs[i];
273     outputs2.push_back(mf->ExpandVariablesInString(expand));
274     }
275
276   // Pass the call to the makefile instance.
277   const char* no_comment = 0;
278   mf->AddCustomCommandOldStyle(target, outputs2, depends2, source,
279                                commandLines, no_comment);
280 }
281
282 void CCONV cmAddCustomCommandToOutput(void *arg, const char* output,
283                                 const char* command,
284                                 int numArgs, const char **args,
285                                 const char* main_dependency,
286                                 int numDepends, const char **depends)
287 {
288   // Get the makefile instance.  Perform an extra variable expansion
289   // now because the API caller expects it.
290   cmMakefile* mf = static_cast<cmMakefile*>(arg);
291
292   // Construct the command line for the command.
293   cmCustomCommandLine commandLine;
294   std::string expand = command;
295   commandLine.push_back(mf->ExpandVariablesInString(expand));
296   for(int i=0; i < numArgs; ++i)
297     {
298     expand = args[i];
299     commandLine.push_back(mf->ExpandVariablesInString(expand));
300     }
301   cmCustomCommandLines commandLines;
302   commandLines.push_back(commandLine);
303
304   // Accumulate the list of dependencies.
305   std::vector<std::string> depends2;
306   for(int i = 0; i < numDepends; ++i)
307     {
308     expand = depends[i];
309     depends2.push_back(mf->ExpandVariablesInString(expand));
310     }
311
312   // Pass the call to the makefile instance.
313   const char* no_comment = 0;
314   const char* no_working_dir = 0;
315   mf->AddCustomCommandToOutput(output, depends2, main_dependency,
316                                commandLines, no_comment, no_working_dir);
317 }
318
319 void CCONV cmAddCustomCommandToTarget(void *arg, const char* target,
320                                 const char* command,
321                                 int numArgs, const char **args,
322                                 int commandType)
323 {
324   // Get the makefile instance.
325   cmMakefile* mf = static_cast<cmMakefile*>(arg);
326
327   // Construct the command line for the command.  Perform an extra
328   // variable expansion now because the API caller expects it.
329   cmCustomCommandLine commandLine;
330   std::string expand = command;
331   commandLine.push_back(mf->ExpandVariablesInString(expand));
332   for(int i=0; i < numArgs; ++i)
333     {
334     expand = args[i];
335     commandLine.push_back(mf->ExpandVariablesInString(expand));
336     }
337   cmCustomCommandLines commandLines;
338   commandLines.push_back(commandLine);
339
340   // Select the command type.
341   cmTarget::CustomCommandType cctype = cmTarget::POST_BUILD;
342   switch (commandType)
343     {
344     case CM_PRE_BUILD:
345       cctype = cmTarget::PRE_BUILD;
346       break;
347     case CM_PRE_LINK:
348       cctype = cmTarget::PRE_LINK;
349       break;
350     case CM_POST_BUILD:
351       cctype = cmTarget::POST_BUILD;
352       break;
353     }
354
355   // Pass the call to the makefile instance.
356   std::vector<std::string> no_depends;
357   const char* no_comment = 0;
358   const char* no_working_dir = 0;
359   mf->AddCustomCommandToTarget(target, no_depends, commandLines,
360                                cctype, no_comment, no_working_dir);
361 }
362
363 void CCONV cmAddLinkLibraryForTarget(void *arg, const char *tgt,
364   const char*value, int libtype)
365 {
366   cmMakefile *mf = static_cast<cmMakefile *>(arg);
367
368   switch (libtype)
369     {
370     case CM_LIBRARY_GENERAL:
371       mf->AddLinkLibraryForTarget(tgt,value, cmTarget::GENERAL);
372       break;
373     case CM_LIBRARY_DEBUG:
374       mf->AddLinkLibraryForTarget(tgt,value, cmTarget::DEBUG);
375       break;
376     case CM_LIBRARY_OPTIMIZED:
377       mf->AddLinkLibraryForTarget(tgt,value, cmTarget::OPTIMIZED);
378       break;
379     }
380 }
381
382 void CCONV cmAddLibrary(void *arg, const char *libname, int shared,
383                   int numSrcs, const char **srcs)
384 {
385   cmMakefile *mf = static_cast<cmMakefile *>(arg);
386   std::vector<std::string> srcs2;
387   int i;
388   for (i = 0; i < numSrcs; ++i)
389     {
390     srcs2.push_back(srcs[i]);
391     }
392   mf->AddLibrary(libname,
393                  (shared? cmTarget::SHARED_LIBRARY : cmTarget::STATIC_LIBRARY),
394                   srcs2);
395 }
396
397 char CCONV *cmExpandVariablesInString(void *arg, const char *source,
398                                 int escapeQuotes, int atOnly)
399 {
400   cmMakefile *mf = static_cast<cmMakefile *>(arg);
401   std::string barf = source;
402   std::string result =
403     mf->ExpandVariablesInString(barf,
404                                 (escapeQuotes ? true : false),
405                                 (atOnly ? true : false));
406   char *res = static_cast<char *>(malloc(result.size() + 1));
407   if (result.size())
408     {
409     strcpy(res,result.c_str());
410     }
411   res[result.size()] = '\0';
412   return res;
413 }
414
415
416 int CCONV cmExecuteCommand(void *arg, const char *name,
417                      int numArgs, const char **args)
418 {
419   cmMakefile *mf = static_cast<cmMakefile *>(arg);
420   cmListFileFunction lff;
421   lff.Name = name;
422   for(int i = 0; i < numArgs; ++i)
423     {
424     // Assume all arguments are quoted.
425     lff.Arguments.push_back(
426       cmListFileArgument(args[i], cmListFileArgument::Quoted,
427                          "[CMake-Plugin]", 0));
428     }
429   cmExecutionStatus status;
430   return mf->ExecuteCommand(lff,status);
431 }
432
433 void CCONV cmExpandSourceListArguments(void *arg,
434                                  int numArgs,
435                                  const char **args,
436                                  int *resArgc,
437                                  char ***resArgv,
438                                  unsigned int startArgumentIndex)
439 {
440   cmMakefile *mf = static_cast<cmMakefile *>(arg);
441   std::vector<std::string> result;
442   std::vector<std::string> args2;
443   int i;
444   for (i = 0; i < numArgs; ++i)
445     {
446     args2.push_back(args[i]);
447     }
448   mf->ExpandSourceListArguments(args2, result, startArgumentIndex);
449   int resargc = static_cast<int>(result.size());
450   char **resargv = 0;
451   if (resargc)
452     {
453     resargv = (char **)malloc(resargc*sizeof(char *));
454     }
455   for (i = 0; i < resargc; ++i)
456     {
457     resargv[i] = strdup(result[i].c_str());
458     }
459   *resArgc = resargc;
460   *resArgv = resargv;
461 }
462
463 void CCONV cmFreeArguments(int argc, char **argv)
464 {
465   int i;
466   for (i = 0; i < argc; ++i)
467     {
468     free(argv[i]);
469     }
470   if (argv)
471     {
472     free(argv);
473     }
474 }
475
476 int CCONV cmGetTotalArgumentSize(int argc, char **argv)
477 {
478   int i;
479   int result = 0;
480   for (i = 0; i < argc; ++i)
481     {
482     if (argv[i])
483       {
484       result = result + static_cast<int>(strlen(argv[i]));
485       }
486     }
487   return result;
488 }
489
490 // Source file proxy object to support the old cmSourceFile/cmMakefile
491 // API for source files.
492 struct cmCPluginAPISourceFile
493 {
494   cmCPluginAPISourceFile(): RealSourceFile(0) {}
495   cmSourceFile* RealSourceFile;
496   std::string SourceName;
497   std::string SourceExtension;
498   std::string FullPath;
499   std::vector<std::string> Depends;
500   cmPropertyMap Properties;
501 };
502
503 // Keep a map from real cmSourceFile instances stored in a makefile to
504 // the CPluginAPI proxy source file.
505 class cmCPluginAPISourceFileMap:
506   public std::map<cmSourceFile*, cmCPluginAPISourceFile*>
507 {
508 public:
509   typedef std::map<cmSourceFile*, cmCPluginAPISourceFile*> derived;
510   typedef derived::iterator iterator;
511   typedef derived::value_type value_type;
512   ~cmCPluginAPISourceFileMap()
513     {
514     for(iterator i=this->begin(); i != this->end(); ++i)
515       {
516       delete i->second;
517       }
518     }
519 };
520 cmCPluginAPISourceFileMap cmCPluginAPISourceFiles;
521
522 void * CCONV cmCreateSourceFile(void)
523 {
524   return (void*)new cmCPluginAPISourceFile;
525 }
526
527 void * CCONV cmCreateNewSourceFile(void *arg)
528 {
529   cmMakefile *mf = static_cast<cmMakefile *>(arg);
530   cmCPluginAPISourceFile *sf = new cmCPluginAPISourceFile;
531   sf->Properties.SetCMakeInstance(mf->GetCMakeInstance());
532   return (void*)sf;
533 }
534
535 void CCONV cmDestroySourceFile(void *arg)
536 {
537   cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
538   // Only delete if it was created by cmCreateSourceFile or
539   // cmCreateNewSourceFile and is therefore not in the map.
540   if(!sf->RealSourceFile)
541     {
542     delete sf;
543     }
544 }
545
546 void CCONV *cmGetSource(void *arg, const char *name)
547 {
548   cmMakefile *mf = static_cast<cmMakefile *>(arg);
549   if(cmSourceFile* rsf = mf->GetSource(name))
550     {
551     // Lookup the proxy source file object for this source.
552     cmCPluginAPISourceFileMap::iterator i = cmCPluginAPISourceFiles.find(rsf);
553     if(i == cmCPluginAPISourceFiles.end())
554       {
555       // Create a proxy source file object for this source.
556       cmCPluginAPISourceFile* sf = new cmCPluginAPISourceFile;
557       sf->RealSourceFile = rsf;
558       sf->FullPath = rsf->GetFullPath();
559       sf->SourceName =
560         cmSystemTools::GetFilenameWithoutLastExtension(sf->FullPath.c_str());
561       sf->SourceExtension =
562         cmSystemTools::GetFilenameLastExtension(sf->FullPath.c_str());
563
564       // Store the proxy in the map so it can be re-used and deleted later.
565       cmCPluginAPISourceFileMap::value_type entry(rsf, sf);
566       i = cmCPluginAPISourceFiles.insert(entry).first;
567       }
568     return (void *)i->second;
569     }
570   else
571     {
572     return 0;
573     }
574 }
575
576 void * CCONV cmAddSource(void *arg, void *arg2)
577 {
578   cmMakefile *mf = static_cast<cmMakefile *>(arg);
579   cmCPluginAPISourceFile* osf = static_cast<cmCPluginAPISourceFile*>(arg2);
580   if(osf->FullPath.empty())
581     {
582     return 0;
583     }
584
585   // Create the real cmSourceFile instance and copy over saved information.
586   cmSourceFile* rsf = mf->GetOrCreateSource(osf->FullPath.c_str());
587   rsf->GetProperties() = osf->Properties;
588   for(std::vector<std::string>::iterator i = osf->Depends.begin();
589       i != osf->Depends.end(); ++i)
590     {
591     rsf->AddDepend(i->c_str());
592     }
593
594   // Create the proxy for the real source file.
595   cmCPluginAPISourceFile* sf = new cmCPluginAPISourceFile;
596   sf->RealSourceFile = rsf;
597   sf->FullPath = osf->FullPath;
598   sf->SourceName = osf->SourceName;
599   sf->SourceExtension = osf->SourceExtension;
600
601   // Store the proxy in the map so it can be re-used and deleted later.
602   cmCPluginAPISourceFiles[rsf] = sf;
603   return (void *)sf;
604 }
605
606 const char * CCONV cmSourceFileGetSourceName(void *arg)
607 {
608   cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
609   return sf->SourceName.c_str();
610 }
611
612 const char * CCONV  cmSourceFileGetFullPath(void *arg)
613 {
614   cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
615   return sf->FullPath.c_str();
616 }
617
618 const char * CCONV  cmSourceFileGetProperty(void *arg,const char *prop)
619 {
620   cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
621   if(cmSourceFile* rsf = sf->RealSourceFile)
622     {
623     return rsf->GetProperty(prop);
624     }
625   else
626     {
627     if(!strcmp(prop,"LOCATION"))
628       {
629       return sf->FullPath.c_str();
630       }
631     bool chain = false;
632     // Ignore chain because old code will not expect it and it is a
633     // pain to implement here anyway.
634     return sf->Properties.GetPropertyValue(prop, cmProperty::SOURCE_FILE,
635                                            chain);
636     }
637 }
638
639 int CCONV cmSourceFileGetPropertyAsBool(void *arg,const char *prop)
640 {
641   cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
642   if(cmSourceFile* rsf = sf->RealSourceFile)
643     {
644     return rsf->GetPropertyAsBool(prop) ? 1:0;
645     }
646   else
647     {
648     return cmSystemTools::IsOn(cmSourceFileGetProperty(arg, prop))? 1:0;
649     }
650 }
651
652 void CCONV cmSourceFileSetProperty(void *arg,const char *prop,
653                                    const char *value)
654 {
655   cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
656   if(cmSourceFile* rsf = sf->RealSourceFile)
657     {
658     rsf->SetProperty(prop, value);
659     }
660   else if(prop)
661     {
662     if(!value) { value = "NOTFOUND"; }
663     sf->Properties.SetProperty(prop, value, cmProperty::SOURCE_FILE);
664     }
665 }
666
667 void CCONV cmSourceFileAddDepend(void *arg, const char *depend)
668 {
669   cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
670   if(cmSourceFile* rsf = sf->RealSourceFile)
671     {
672     rsf->AddDepend(depend);
673     }
674   else
675     {
676     sf->Depends.push_back(depend);
677     }
678 }
679
680 void CCONV cmSourceFileSetName(void *arg, const char* name, const char* dir,
681                                int numSourceExtensions,
682                                const char **sourceExtensions,
683                                int numHeaderExtensions,
684                                const char **headerExtensions)
685 {
686   cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
687   if(sf->RealSourceFile)
688     {
689     // SetName is allowed only on temporary source files created by
690     // the command for building and passing to AddSource.
691     return;
692     }
693   std::vector<std::string> sourceExts;
694   std::vector<std::string> headerExts;
695   int i;
696   for (i = 0; i < numSourceExtensions; ++i)
697     {
698     sourceExts.push_back(sourceExtensions[i]);
699     }
700   for (i = 0; i < numHeaderExtensions; ++i)
701     {
702     headerExts.push_back(headerExtensions[i]);
703     }
704
705   // Save the original name given.
706   sf->SourceName = name;
707
708   // Convert the name to a full path in case the given name is a
709   // relative path.
710   std::string pathname = cmSystemTools::CollapseFullPath(name, dir);
711
712   // First try and see whether the listed file can be found
713   // as is without extensions added on.
714   std::string hname = pathname;
715   if(cmSystemTools::FileExists(hname.c_str()))
716     {
717     sf->SourceName = cmSystemTools::GetFilenamePath(name);
718     if ( sf->SourceName.size() > 0 )
719       {
720       sf->SourceName += "/";
721       }
722     sf->SourceName += cmSystemTools::GetFilenameWithoutLastExtension(name);
723     std::string::size_type pos = hname.rfind('.');
724     if(pos != std::string::npos)
725       {
726       sf->SourceExtension = hname.substr(pos+1, hname.size()-pos);
727       if ( cmSystemTools::FileIsFullPath(name) )
728         {
729         std::string::size_type pos2 = hname.rfind('/');
730         if(pos2 != std::string::npos)
731           {
732           sf->SourceName = hname.substr(pos2+1, pos - pos2-1);
733           }
734         }
735       }
736
737     sf->FullPath = hname;
738     return;
739     }
740
741   // Next, try the various source extensions
742   for( std::vector<std::string>::const_iterator ext = sourceExts.begin();
743        ext != sourceExts.end(); ++ext )
744     {
745     hname = pathname;
746     hname += ".";
747     hname += *ext;
748     if(cmSystemTools::FileExists(hname.c_str()))
749       {
750       sf->SourceExtension = *ext;
751       sf->FullPath = hname;
752       return;
753       }
754     }
755
756   // Finally, try the various header extensions
757   for( std::vector<std::string>::const_iterator ext = headerExts.begin();
758        ext != headerExts.end(); ++ext )
759     {
760     hname = pathname;
761     hname += ".";
762     hname += *ext;
763     if(cmSystemTools::FileExists(hname.c_str()))
764       {
765       sf->SourceExtension = *ext;
766       sf->FullPath = hname;
767       return;
768       }
769     }
770
771   cmOStringStream e;
772   e << "Cannot find source file \"" << pathname << "\"";
773   e << "\n\nTried extensions";
774   for( std::vector<std::string>::const_iterator ext = sourceExts.begin();
775        ext != sourceExts.end(); ++ext )
776     {
777     e << " ." << *ext;
778     }
779   for( std::vector<std::string>::const_iterator ext = headerExts.begin();
780        ext != headerExts.end(); ++ext )
781     {
782     e << " ." << *ext;
783     }
784   cmSystemTools::Error(e.str().c_str());
785   return;
786 }
787
788 void CCONV cmSourceFileSetName2(void *arg, const char* name, const char* dir,
789                                 const char *ext, int headerFileOnly)
790 {
791   cmCPluginAPISourceFile* sf = static_cast<cmCPluginAPISourceFile*>(arg);
792   if(sf->RealSourceFile)
793     {
794     // SetName is allowed only on temporary source files created by
795     // the command for building and passing to AddSource.
796     return;
797     }
798
799   // Implement the old SetName method code here.
800   if(headerFileOnly)
801     {
802     sf->Properties.SetProperty("HEADER_FILE_ONLY", "1",
803                                cmProperty::SOURCE_FILE);
804     }
805   sf->SourceName = name;
806   std::string fname = sf->SourceName;
807   if(ext && strlen(ext))
808     {
809     fname += ".";
810     fname += ext;
811     }
812   sf->FullPath = cmSystemTools::CollapseFullPath(fname.c_str(), dir);
813   cmSystemTools::ConvertToUnixSlashes(sf->FullPath);
814   sf->SourceExtension = ext;
815 }
816
817 char * CCONV cmGetFilenameWithoutExtension(const char *name)
818 {
819   std::string sres = cmSystemTools::GetFilenameWithoutExtension(name);
820   char *result = (char *)malloc(sres.size()+1);
821   strcpy(result,sres.c_str());
822   return result;
823 }
824
825 char * CCONV cmGetFilenamePath(const char *name)
826 {
827   std::string sres = cmSystemTools::GetFilenamePath(name);
828   char *result = (char *)malloc(sres.size()+1);
829   strcpy(result,sres.c_str());
830   return result;
831 }
832
833 char * CCONV cmCapitalized(const char *name)
834 {
835   std::string sres = cmSystemTools::Capitalized(name);
836   char *result = (char *)malloc(sres.size()+1);
837   strcpy(result,sres.c_str());
838   return result;
839 }
840
841 void CCONV cmCopyFileIfDifferent(const char *name1, const char *name2)
842 {
843   cmSystemTools::CopyFileIfDifferent(name1,name2);
844 }
845
846 void CCONV cmRemoveFile(const char *name)
847 {
848   cmSystemTools::RemoveFile(name);
849 }
850
851 void CCONV cmDisplayStatus(void *arg, const char* message)
852 {
853   cmMakefile *mf = static_cast<cmMakefile *>(arg);
854   mf->DisplayStatus(message, -1);
855 }
856
857 void CCONV cmFree(void *data)
858 {
859   free(data);
860 }
861
862 void CCONV DefineSourceFileProperty (void *arg, const char *name,
863   const char *briefDocs,
864   const char *longDocs,
865   int chained)
866 {
867   cmMakefile *mf = static_cast<cmMakefile *>(arg);
868   mf->GetCMakeInstance()->DefineProperty(name,cmProperty::SOURCE_FILE,
869                                          briefDocs, longDocs,
870                                          chained != 0);
871 }
872
873 } // close the extern "C" scope
874
875 cmCAPI cmStaticCAPI =
876 {
877   cmGetClientData,
878   cmGetTotalArgumentSize,
879   cmFreeArguments,
880   cmSetClientData,
881   cmSetError,
882   cmAddCacheDefinition,
883   cmAddCustomCommand,
884   cmAddDefineFlag,
885   cmAddDefinition,
886   cmAddExecutable,
887   cmAddLibrary,
888   cmAddLinkDirectoryForTarget,
889   cmAddLinkLibraryForTarget,
890   cmAddUtilityCommand,
891   cmCommandExists,
892   cmExecuteCommand,
893   cmExpandSourceListArguments,
894   cmExpandVariablesInString,
895   cmGetCacheMajorVersion,
896   cmGetCacheMinorVersion,
897   cmGetCurrentDirectory,
898   cmGetCurrentOutputDirectory,
899   cmGetDefinition,
900   cmGetHomeDirectory,
901   cmGetHomeOutputDirectory,
902   cmGetMajorVersion,
903   cmGetMinorVersion,
904   cmGetProjectName,
905   cmGetStartDirectory,
906   cmGetStartOutputDirectory,
907   cmIsOn,
908
909   cmAddSource,
910   cmCreateSourceFile,
911   cmDestroySourceFile,
912   cmGetSource,
913   cmSourceFileAddDepend,
914   cmSourceFileGetProperty,
915   cmSourceFileGetPropertyAsBool,
916   cmSourceFileGetSourceName,
917   cmSourceFileGetFullPath,
918   cmSourceFileSetName,
919   cmSourceFileSetName2,
920   cmSourceFileSetProperty,
921
922   cmCapitalized,
923   cmCopyFileIfDifferent,
924   cmGetFilenameWithoutExtension,
925   cmGetFilenamePath,
926   cmRemoveFile,
927   cmFree,
928
929   cmAddCustomCommandToOutput,
930   cmAddCustomCommandToTarget,
931   cmDisplayStatus,
932   cmCreateNewSourceFile,
933   DefineSourceFileProperty,
934 };
935