ppScope.cxx 99 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129
  1. // Filename: ppScope.cxx
  2. // Created by: drose (25Sep00)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. #include "ppScope.h"
  6. #include "ppNamedScopes.h"
  7. #include "ppFilenamePattern.h"
  8. #include "ppDirectory.h"
  9. #include "ppSubroutine.h"
  10. #include "ppCommandFile.h"
  11. #include "ppDependableFile.h"
  12. #include "ppMain.h"
  13. #include "tokenize.h"
  14. #include "find_searchpath.h"
  15. #include "filename.h"
  16. #include <stdlib.h>
  17. #include <algorithm>
  18. #include <ctype.h>
  19. #include <glob.h>
  20. #include <sys/stat.h>
  21. #include <unistd.h>
  22. #include <stdio.h> // for perror() and sprintf().
  23. #include <errno.h>
  24. #include <signal.h>
  25. #include <sys/types.h>
  26. #include <sys/wait.h>
  27. #include <assert.h>
  28. static const string variable_patsubst(VARIABLE_PATSUBST);
  29. PPScope::MapVariableDefinition PPScope::_null_map_def;
  30. PPScope::ScopeStack PPScope::_scope_stack;
  31. #ifdef __CYGWIN__
  32. extern "C" void cygwin_conv_to_win32_path(const char *path, char *win32);
  33. extern "C" void cygwin_conv_to_posix_path(const char *path, char *posix);
  34. #endif
  35. ////////////////////////////////////////////////////////////////////
  36. // Function: PPScope::Constructor
  37. // Access: Public
  38. // Description:
  39. ////////////////////////////////////////////////////////////////////
  40. PPScope::
  41. PPScope(PPNamedScopes *named_scopes) :
  42. _named_scopes(named_scopes)
  43. {
  44. _directory = (PPDirectory *)NULL;
  45. _parent_scope = (PPScope *)NULL;
  46. }
  47. ////////////////////////////////////////////////////////////////////
  48. // Function: PPScope::get_named_scopes
  49. // Access: Public
  50. // Description: Returns a pointer to the PPNamedScopes collection
  51. // associated with this scope. This pointer could be
  52. // NULL.
  53. ////////////////////////////////////////////////////////////////////
  54. PPNamedScopes *PPScope::
  55. get_named_scopes() {
  56. return _named_scopes;
  57. }
  58. ////////////////////////////////////////////////////////////////////
  59. // Function: PPScope::set_parent
  60. // Access: Public
  61. // Description: Sets a static parent scope to this scope. When a
  62. // variable reference is undefined in this scope, it
  63. // will search first up the static parent chain before
  64. // it searches the dynamic scope stack.
  65. ////////////////////////////////////////////////////////////////////
  66. void PPScope::
  67. set_parent(PPScope *parent) {
  68. _parent_scope = parent;
  69. }
  70. ////////////////////////////////////////////////////////////////////
  71. // Function: PPScope::get_parent
  72. // Access: Public
  73. // Description: Returns the static parent scope to this scope, if
  74. // any, or NULL if the static parent has not been set.
  75. // See set_parent().
  76. ////////////////////////////////////////////////////////////////////
  77. PPScope *PPScope::
  78. get_parent() {
  79. return _parent_scope;
  80. }
  81. ////////////////////////////////////////////////////////////////////
  82. // Function: PPScope::define_variable
  83. // Access: Public
  84. // Description: Makes a new variable definition. If the variable
  85. // does not already exist in this scope, a new variable
  86. // is created, possibly shadowing a variable declaration
  87. // in some parent scope.
  88. ////////////////////////////////////////////////////////////////////
  89. void PPScope::
  90. define_variable(const string &varname, const string &definition) {
  91. _variables[varname] = definition;
  92. }
  93. ////////////////////////////////////////////////////////////////////
  94. // Function: PPScope::set_variable
  95. // Access: Public
  96. // Description: Changes the definition of an already-existing
  97. // variable. The variable is changed in whichever scope
  98. // it is defined. Returns false if the variable has not
  99. // been defined.
  100. ////////////////////////////////////////////////////////////////////
  101. bool PPScope::
  102. set_variable(const string &varname, const string &definition) {
  103. if (p_set_variable(varname, definition)) {
  104. return true;
  105. }
  106. // Check the scopes on the stack for the variable definition.
  107. ScopeStack::reverse_iterator si;
  108. for (si = _scope_stack.rbegin(); si != _scope_stack.rend(); ++si) {
  109. if ((*si)->p_set_variable(varname, definition)) {
  110. return true;
  111. }
  112. }
  113. // If the variable isn't defined, we check the environment.
  114. const char *env = getenv(varname.c_str());
  115. if (env != (const char *)NULL) {
  116. // It is defined in the environment; thus, it is implicitly
  117. // defined here at the global scope: the bottom of the stack.
  118. PPScope *bottom = this;
  119. if (!_scope_stack.empty()) {
  120. bottom = _scope_stack.front();
  121. }
  122. bottom->define_variable(varname, definition);
  123. return true;
  124. }
  125. // The variable isn't defined anywhere. Too bad.
  126. return false;
  127. }
  128. ////////////////////////////////////////////////////////////////////
  129. // Function: PPScope::define_map_variable
  130. // Access: Public
  131. // Description: Makes a new map variable definition. This defines a
  132. // new variable that can be used as a function to
  133. // retrieve variables from within a named scope, based
  134. // on a particular key variable.
  135. //
  136. // In this variant of define_map_variable(), the
  137. // definition is a string of the form
  138. // key_varname(scope_names).
  139. ////////////////////////////////////////////////////////////////////
  140. void PPScope::
  141. define_map_variable(const string &varname, const string &definition) {
  142. size_t p = definition.find(VARIABLE_OPEN_NESTED);
  143. if (p != string::npos && definition[definition.length() - 1] == VARIABLE_CLOSE_NESTED) {
  144. size_t q = definition.length() - 1;
  145. string scope_names = definition.substr(p + 1, q - (p + 1));
  146. string key_varname = definition.substr(0, p);
  147. define_map_variable(varname, key_varname, scope_names);
  148. } else {
  149. // No scoping; not really a map variable.
  150. define_map_variable(varname, definition, "");
  151. }
  152. }
  153. ////////////////////////////////////////////////////////////////////
  154. // Function: PPScope::define_map_variable
  155. // Access: Public
  156. // Description: Makes a new map variable definition. This defines a
  157. // new variable that can be used as a function to
  158. // retrieve variables from within a named scope, based
  159. // on a particular key variable.
  160. ////////////////////////////////////////////////////////////////////
  161. void PPScope::
  162. define_map_variable(const string &varname, const string &key_varname,
  163. const string &scope_names) {
  164. MapVariableDefinition &def = _map_variables[varname];
  165. def.clear();
  166. define_variable(varname, "");
  167. if (_named_scopes == (PPNamedScopes *)NULL) {
  168. return;
  169. }
  170. if (key_varname.empty()) {
  171. return;
  172. }
  173. vector<string> names;
  174. tokenize_whitespace(scope_names, names);
  175. // Get all of the named scopes.
  176. PPNamedScopes::Scopes scopes;
  177. vector<string>::const_iterator ni;
  178. for (ni = names.begin(); ni != names.end(); ++ni) {
  179. const string &name = (*ni);
  180. _named_scopes->get_scopes(name, scopes);
  181. }
  182. if (scopes.empty()) {
  183. return;
  184. }
  185. // Now go through the scopes and build up the results.
  186. vector<string> results;
  187. PPNamedScopes::Scopes::const_iterator si;
  188. for (si = scopes.begin(); si != scopes.end(); ++si) {
  189. PPScope *scope = (*si);
  190. string key_string = scope->expand_variable(key_varname);
  191. vector<string> keys;
  192. tokenize_whitespace(key_string, keys);
  193. if (!keys.empty()) {
  194. vector<string>::const_iterator ki;
  195. results.insert(results.end(), keys.begin(), keys.end());
  196. for (ki = keys.begin(); ki != keys.end(); ++ki) {
  197. def[*ki] = scope;
  198. }
  199. }
  200. }
  201. // Also define a traditional variable along with the map variable.
  202. define_variable(varname, repaste(results, " "));
  203. }
  204. ////////////////////////////////////////////////////////////////////
  205. // Function: PPScope::add_to_map_variable
  206. // Access: Public
  207. // Description: Adds a new key/scope pair to a previous map variable
  208. // definition.
  209. ////////////////////////////////////////////////////////////////////
  210. void PPScope::
  211. add_to_map_variable(const string &varname, const string &key,
  212. PPScope *scope) {
  213. MapVariableDefinition &def = find_map_variable(varname);
  214. if (&def == &_null_map_def) {
  215. cerr << "Warning: undefined map variable: " << varname << "\n";
  216. return;
  217. }
  218. def[key] = scope;
  219. // We need to do all this work to define the traditional expansion.
  220. // Maybe not a great idea.
  221. vector<string> results;
  222. MapVariableDefinition::const_iterator di;
  223. for (di = def.begin(); di != def.end(); ++di) {
  224. results.push_back((*di).first);
  225. }
  226. set_variable(varname, repaste(results, " "));
  227. }
  228. ////////////////////////////////////////////////////////////////////
  229. // Function: PPScope::define_formals
  230. // Access: Public
  231. // Description: Supplies values to a slew of variables at once,
  232. // typically to define actual values for a list of
  233. // formal parameters to a user-defined subroutine or
  234. // function.
  235. //
  236. // Formals is a vector of variable names to be defined,
  237. // and actuals is a comma-separated list of expressions
  238. // to be substituted in, one-per-one. The
  239. // subroutine_name is used only for error reporting.
  240. ////////////////////////////////////////////////////////////////////
  241. void PPScope::
  242. define_formals(const string &subroutine_name,
  243. const vector<string> &formals, const string &actuals) {
  244. vector<string> actual_words;
  245. tokenize_params(actuals, actual_words, true);
  246. if (actual_words.size() < formals.size()) {
  247. cerr << "Warning: not all parameters defined for " << subroutine_name
  248. << ": " << actuals << "\n";
  249. } else if (actual_words.size() > formals.size()) {
  250. cerr << "Warning: more parameters defined for " << subroutine_name
  251. << " than actually exist: " << actuals << "\n";
  252. }
  253. for (int i = 0; i < (int)formals.size(); i++) {
  254. if (i < (int)actual_words.size()) {
  255. define_variable(formals[i], actual_words[i]);
  256. } else {
  257. define_variable(formals[i], string());
  258. }
  259. }
  260. }
  261. ////////////////////////////////////////////////////////////////////
  262. // Function: PPScope::get_variable
  263. // Access: Public
  264. // Description: Returns the variable definition associated with the
  265. // indicated variable name.
  266. ////////////////////////////////////////////////////////////////////
  267. string PPScope::
  268. get_variable(const string &varname) {
  269. // Is it a user-defined function?
  270. const PPSubroutine *sub = PPSubroutine::get_func(varname);
  271. if (sub != (const PPSubroutine *)NULL) {
  272. return expand_function(varname, sub, string());
  273. }
  274. // cerr << "getvar arg is: '" << varname << "'" << endl;
  275. string result;
  276. if (p_get_variable(varname, result)) {
  277. return result;
  278. }
  279. // Check the scopes on the stack for the variable definition.
  280. ScopeStack::reverse_iterator si;
  281. for (si = _scope_stack.rbegin(); si != _scope_stack.rend(); ++si) {
  282. if ((*si)->p_get_variable(varname, result)) {
  283. return result;
  284. }
  285. }
  286. // If the variable isn't defined, we check the environment.
  287. const char *env = getenv(varname.c_str());
  288. if (env != (const char *)NULL) {
  289. return env;
  290. }
  291. // It's not defined anywhere, so it's implicitly empty.
  292. return string();
  293. }
  294. ////////////////////////////////////////////////////////////////////
  295. // Function: PPScope::expand_defined
  296. // Access: Private
  297. // Description: Expands the "defined" function variable. Code mimics get_variable()
  298. ////////////////////////////////////////////////////////////////////
  299. string PPScope::
  300. expand_defined(const string &params) {
  301. // Split the string up into tokens based on the commas.
  302. vector<string> tokens;
  303. tokenize_params(params, tokens, true);
  304. if (tokens.size() != 1) {
  305. cerr << "error: defined requires one parameter.\n";
  306. return string();
  307. }
  308. string varname = tokens[0];
  309. string falsestr;
  310. string truestr = "1";
  311. cerr << "defined arg is: '" << varname << "'" << endl;
  312. // Is it a user-defined function?
  313. const PPSubroutine *sub = PPSubroutine::get_func(varname);
  314. string nullstr;
  315. if (sub != (const PPSubroutine *)NULL) {
  316. if(nullstr != expand_function(varname, sub, string())) {
  317. return truestr;
  318. }
  319. }
  320. cerr << "zzz 3111\n";
  321. string result;
  322. if (p_get_variable(varname, result)) {
  323. return truestr;
  324. }
  325. // Check the scopes on the stack for the variable definition.
  326. ScopeStack::reverse_iterator si;
  327. for (si = _scope_stack.rbegin(); si != _scope_stack.rend(); ++si) {
  328. if ((*si)->p_get_variable(varname, result)) {
  329. return truestr;
  330. }
  331. }
  332. cerr << "zzz 4111\n";
  333. // If the variable isn't defined, we check the environment.
  334. const char *env = getenv(varname.c_str());
  335. if (env != (const char *)NULL) {
  336. return truestr;
  337. }
  338. cerr << "zzz 5111\n";
  339. // It's not defined anywhere, so it's implicitly empty.
  340. return falsestr;
  341. }
  342. ////////////////////////////////////////////////////////////////////
  343. // Function: PPScope::expand_variable
  344. // Access: Public
  345. // Description: Similar to get_variable(), except the variable
  346. // definition is in turn expanded.
  347. ////////////////////////////////////////////////////////////////////
  348. string PPScope::
  349. expand_variable(const string &varname) {
  350. return expand_string(get_variable(varname));
  351. }
  352. ////////////////////////////////////////////////////////////////////
  353. // Function: PPScope::find_map_variable
  354. // Access: Public
  355. // Description: Looks for the map variable definition in this scope
  356. // or some ancestor scope. Returns the map variable
  357. // definition if it is found, or _null_map_def if it is
  358. // not.
  359. ////////////////////////////////////////////////////////////////////
  360. PPScope::MapVariableDefinition &PPScope::
  361. find_map_variable(const string &varname) {
  362. MapVariableDefinition &def = p_find_map_variable(varname);
  363. if (&def != &_null_map_def) {
  364. return def;
  365. }
  366. // No such map variable. Check the stack.
  367. ScopeStack::reverse_iterator si;
  368. for (si = _scope_stack.rbegin(); si != _scope_stack.rend(); ++si) {
  369. MapVariableDefinition &def = (*si)->p_find_map_variable(varname);
  370. if (&def != &_null_map_def) {
  371. return def;
  372. }
  373. }
  374. // Nada.
  375. return _null_map_def;
  376. }
  377. ////////////////////////////////////////////////////////////////////
  378. // Function: PPScope::get_directory
  379. // Access: Public
  380. // Description: Returns the directory level associated with this
  381. // scope, if any, or with the nearest parent to this
  382. // scope.
  383. ////////////////////////////////////////////////////////////////////
  384. PPDirectory *PPScope::
  385. get_directory() {
  386. if (_directory != (PPDirectory *)NULL) {
  387. return _directory;
  388. }
  389. // Check the stack.
  390. ScopeStack::reverse_iterator si;
  391. for (si = _scope_stack.rbegin(); si != _scope_stack.rend(); ++si) {
  392. if ((*si)->_directory != (PPDirectory *)NULL) {
  393. return (*si)->_directory;
  394. }
  395. }
  396. return (PPDirectory *)NULL;
  397. }
  398. ////////////////////////////////////////////////////////////////////
  399. // Function: PPScope::set_directory
  400. // Access: Public
  401. // Description: Associates this scope with the indicated directory
  402. // level. Typically this is done when definition a
  403. // scope for a particular source file which exists at a
  404. // known directory level.
  405. ////////////////////////////////////////////////////////////////////
  406. void PPScope::
  407. set_directory(PPDirectory *directory) {
  408. _directory = directory;
  409. }
  410. ////////////////////////////////////////////////////////////////////
  411. // Function: PPScope::expand_string
  412. // Access: Public
  413. // Description: Expands out all the variable references in the given
  414. // string. Variables are expanded recursively; that is,
  415. // if a variable expansion includes a reference to
  416. // another variable name, the second variable name is
  417. // expanded. However, cyclical references are not
  418. // expanded.
  419. ////////////////////////////////////////////////////////////////////
  420. string PPScope::
  421. expand_string(const string &str) {
  422. return r_expand_string(str, (ExpandedVariable *)NULL);
  423. }
  424. ////////////////////////////////////////////////////////////////////
  425. // Function: PPScope::expand_self_reference
  426. // Access: Public
  427. // Description: Similar to expand_string(), except that only simple
  428. // references to the named variable are expanded--other
  429. // variable references are left unchanged. This allows
  430. // us to define a variable in terms of its previous
  431. // definition.
  432. ////////////////////////////////////////////////////////////////////
  433. string PPScope::
  434. expand_self_reference(const string &str, const string &varname) {
  435. // Look for a simple reference to the named variable. A more
  436. // complex reference, like a computed variable name or something
  437. // equally loopy, won't work with this simple test. Too bad.
  438. string reference;
  439. reference += VARIABLE_PREFIX;
  440. reference += VARIABLE_OPEN_BRACE;
  441. reference += varname;
  442. reference += VARIABLE_CLOSE_BRACE;
  443. string result;
  444. size_t p = 0;
  445. size_t q = str.find(reference, p);
  446. while (q != string::npos) {
  447. result += str.substr(p, q - p);
  448. p = q;
  449. result += r_expand_variable(str, p, (ExpandedVariable *)NULL);
  450. q = str.find(reference, p);
  451. }
  452. result += str.substr(p);
  453. return result;
  454. }
  455. ////////////////////////////////////////////////////////////////////
  456. // Function: PPScope::push_scope
  457. // Access: Public, Static
  458. // Description: Pushes the indicated scope onto the top of the stack.
  459. // When a variable reference is unresolved in the
  460. // current scope, the scope stack is searched, in LIFO
  461. // order.
  462. ////////////////////////////////////////////////////////////////////
  463. void PPScope::
  464. push_scope(PPScope *scope) {
  465. _scope_stack.push_back(scope);
  466. }
  467. ////////////////////////////////////////////////////////////////////
  468. // Function: PPScope::pop_scope
  469. // Access: Public, Static
  470. // Description: Pops another level off the top of the stack. See
  471. // push_scope().
  472. ////////////////////////////////////////////////////////////////////
  473. PPScope *PPScope::
  474. pop_scope() {
  475. assert(!_scope_stack.empty());
  476. PPScope *back = _scope_stack.back();
  477. _scope_stack.pop_back();
  478. return back;
  479. }
  480. ////////////////////////////////////////////////////////////////////
  481. // Function: PPScope::get_bottom_scope
  482. // Access: Public, Static
  483. // Description: Returns the scope on the bottom of the stack. This
  484. // was the very first scope ever pushed, e.g. the global
  485. // scope.
  486. ////////////////////////////////////////////////////////////////////
  487. PPScope *PPScope::
  488. get_bottom_scope() {
  489. assert(!_scope_stack.empty());
  490. return _scope_stack.front();
  491. }
  492. ////////////////////////////////////////////////////////////////////
  493. // Function: PPScope::tokenize_params
  494. // Access: Public
  495. // Description: Separates a string into tokens based on comma
  496. // delimiters, e.g. for parameters to a function.
  497. // Nested variable references are skipped correctly,
  498. // even if they include commas. Leading and trailing
  499. // whitespace in each token is automatically stripped.
  500. //
  501. // If expand is true, the nested variables are
  502. // automatically expanded as the string is tokenized;
  503. // otherwise, they are left unexpanded.
  504. ////////////////////////////////////////////////////////////////////
  505. void PPScope::
  506. tokenize_params(const string &str, vector<string> &tokens,
  507. bool expand) {
  508. size_t p = 0;
  509. while (p < str.length()) {
  510. // Skip initial whitespace.
  511. while (p < str.length() && isspace(str[p])) {
  512. p++;
  513. }
  514. string token;
  515. while (p < str.length() && str[p] != FUNCTION_PARAMETER_SEPARATOR) {
  516. if (p + 1 < str.length() && str[p] == VARIABLE_PREFIX &&
  517. str[p + 1] == VARIABLE_OPEN_BRACE) {
  518. // Skip a nested variable reference.
  519. if (expand) {
  520. token += r_expand_variable(str, p, (ExpandedVariable *)NULL);
  521. } else {
  522. token += r_scan_variable(str, p);
  523. }
  524. } else {
  525. token += str[p];
  526. p++;
  527. }
  528. }
  529. // Back up past trailing whitespace.
  530. size_t q = token.length();
  531. while (q > 0 && isspace(token[q - 1])) {
  532. q--;
  533. }
  534. tokens.push_back(token.substr(0, q));
  535. p++;
  536. if (p == str.length()) {
  537. // In this case, we have just read past a trailing comma symbol
  538. // at the end of the string, so we have one more empty token.
  539. tokens.push_back(string());
  540. }
  541. }
  542. }
  543. ////////////////////////////////////////////////////////////////////
  544. // Function: PPScope::tokenize_numeric_pair
  545. // Access: Public
  546. // Description: This function is used by all the numeric comparision
  547. // functions, e.g. nne, nlt, etc. It splits the string
  548. // up into two parameters based on commas, and evaluates
  549. // each parameter as a number, into a and b. It returns
  550. // true if successful, or false if there was some user
  551. // error.
  552. ////////////////////////////////////////////////////////////////////
  553. bool PPScope::
  554. tokenize_numeric_pair(const string &str, double &a, double &b) {
  555. vector<string> words;
  556. tokenize_params(str, words, true);
  557. if (words.size() != 2) {
  558. cerr << words.size() << " parameters supplied when two were expected:\n"
  559. << str << "\n";
  560. return false;
  561. }
  562. double results[2];
  563. for (int i = 0; i < 2; i++) {
  564. const char *param = words[i].c_str();
  565. char *n;
  566. results[i] = strtod(param, &n);
  567. if (n == param) {
  568. // strtod failed--not a numeric representation.
  569. cerr << "Warning: " << words[i] << " is not a number.\n";
  570. results[i] = 0.0;
  571. }
  572. }
  573. a = results[0];
  574. b = results[1];
  575. return true;
  576. }
  577. ////////////////////////////////////////////////////////////////////
  578. // Function: PPScope::p_set_variable
  579. // Access: Private
  580. // Description: The private implementation of p_set_variable.
  581. // Returns true if the variable's definition is found
  582. // and set, false otherwise.
  583. ////////////////////////////////////////////////////////////////////
  584. bool PPScope::
  585. p_set_variable(const string &varname, const string &definition) {
  586. Variables::iterator vi;
  587. vi = _variables.find(varname);
  588. if (vi != _variables.end()) {
  589. (*vi).second = definition;
  590. return true;
  591. }
  592. if (_parent_scope != (PPScope *)NULL) {
  593. return _parent_scope->p_set_variable(varname, definition);
  594. }
  595. return false;
  596. }
  597. ////////////////////////////////////////////////////////////////////
  598. // Function: PPScope::p_get_variable
  599. // Access: Private
  600. // Description: The private implementation of get_variable(). This
  601. // checks the local scope only; it does not check the
  602. // stack. It returns true if the variable is defined,
  603. // false otherwise..
  604. ////////////////////////////////////////////////////////////////////
  605. bool PPScope::
  606. p_get_variable(const string &varname, string &result) {
  607. Variables::const_iterator vi;
  608. vi = _variables.find(varname);
  609. if (vi != _variables.end()) {
  610. result = (*vi).second;
  611. return true;
  612. }
  613. if (varname == "RELDIR" &&
  614. _directory != (PPDirectory *)NULL &&
  615. current_output_directory != (PPDirectory *)NULL) {
  616. // $[RELDIR] is a special variable name that evaluates to the
  617. // relative directory of the current scope to the current output
  618. // directory.
  619. result = current_output_directory->get_rel_to(_directory);
  620. return true;
  621. }
  622. if (varname == "DEPENDS_INDEX" &&
  623. _directory != (PPDirectory *)NULL) {
  624. // $[DEPENDS_INDEX] is another special variable name that
  625. // evaluates to the numeric sorting index assigned to this
  626. // directory based on its dependency relationship with other
  627. // directories. It's useful primarily for debugging.
  628. char buffer[32];
  629. sprintf(buffer, "%d", _directory->get_depends_index());
  630. result = buffer;
  631. return true;
  632. }
  633. if (_parent_scope != (PPScope *)NULL) {
  634. return _parent_scope->p_get_variable(varname, result);
  635. }
  636. return false;
  637. }
  638. ////////////////////////////////////////////////////////////////////
  639. // Function: PPScope::r_expand_string
  640. // Access: Private
  641. // Description: The recursive implementation of expand_string().
  642. // This function detects cycles in the variable
  643. // expansion by storing the set of variable names that
  644. // have thus far been expanded in the linked list.
  645. ////////////////////////////////////////////////////////////////////
  646. string PPScope::
  647. r_expand_string(const string &str, PPScope::ExpandedVariable *expanded) {
  648. string result;
  649. // Search for a variable reference.
  650. size_t p = 0;
  651. while (p < str.length()) {
  652. if (p + 1 < str.length() && str[p] == VARIABLE_PREFIX &&
  653. str[p + 1] == VARIABLE_OPEN_BRACE) {
  654. // Here's a nested variable! Expand it fully.
  655. result += r_expand_variable(str, p, expanded);
  656. } else {
  657. result += str[p];
  658. p++;
  659. }
  660. }
  661. return result;
  662. }
  663. ////////////////////////////////////////////////////////////////////
  664. // Function: PPScope::r_scan_variable
  665. // Access: Private
  666. // Description: Scans past a single variable reference without
  667. // expanding it. On input, str is a string containing a
  668. // variable reference (among other stuff), and vp is the
  669. // position within the string of the prefix character at
  670. // the beginning of the variable reference.
  671. //
  672. // On output, vp is set to the position within the
  673. // string of the first character after the variable
  674. // reference's closing bracket. The variable reference
  675. // itself is returned.
  676. ////////////////////////////////////////////////////////////////////
  677. string PPScope::
  678. r_scan_variable(const string &str, size_t &vp) {
  679. // Search for the end of the variable name: an unmatched square
  680. // bracket.
  681. size_t start = vp;
  682. size_t p = vp + 2;
  683. while (p < str.length() && str[p] != VARIABLE_CLOSE_BRACE) {
  684. if (p + 1 < str.length() && str[p] == VARIABLE_PREFIX &&
  685. str[p + 1] == VARIABLE_OPEN_BRACE) {
  686. // Here's a nested variable! Scan past it, matching braces
  687. // properly.
  688. r_scan_variable(str, p);
  689. } else {
  690. p++;
  691. }
  692. }
  693. if (p < str.length()) {
  694. assert(str[p] == VARIABLE_CLOSE_BRACE);
  695. p++;
  696. } else {
  697. cerr << "Warning! Unclosed variable reference:\n"
  698. << str.substr(vp) << "\n";
  699. }
  700. vp = p;
  701. return str.substr(start, vp - start);
  702. }
  703. ////////////////////////////////////////////////////////////////////
  704. // Function: PPScope::r_expand_variable
  705. // Access: Private
  706. // Description: Expands a single variable reference. On input, str
  707. // is a string containing a variable reference (among
  708. // other stuff), and vp is the position within the
  709. // string of the prefix character at the beginning of
  710. // the variable reference.
  711. //
  712. // On output, vp is set to the position within the
  713. // string of the first character after the variable
  714. // reference's closing bracket, and the string expansion
  715. // of the variable reference is returned.
  716. ////////////////////////////////////////////////////////////////////
  717. string PPScope::
  718. r_expand_variable(const string &str, size_t &vp,
  719. PPScope::ExpandedVariable *expanded) {
  720. string varname;
  721. size_t whitespace_at = 0;
  722. size_t open_nested_at = 0;
  723. // Search for the end of the variable name: an unmatched square
  724. // bracket.
  725. size_t p = vp + 2;
  726. while (p < str.length() && str[p] != VARIABLE_CLOSE_BRACE) {
  727. if (p + 1 < str.length() && str[p] == VARIABLE_PREFIX &&
  728. str[p + 1] == VARIABLE_OPEN_BRACE) {
  729. if (whitespace_at != 0) {
  730. // Once we have encountered whitespace, we don't expand
  731. // variables inline anymore. These are now function
  732. // parameters, and might need to be expanded in some other
  733. // scope.
  734. varname += r_scan_variable(str, p);
  735. } else {
  736. varname += r_expand_variable(str, p, expanded);
  737. }
  738. } else {
  739. if (open_nested_at == 0 && str[p] == VARIABLE_OPEN_NESTED) {
  740. open_nested_at = p - (vp + 2);
  741. }
  742. if (open_nested_at == 0 && whitespace_at == 0 && isspace(str[p])) {
  743. whitespace_at = p - (vp + 2);
  744. }
  745. varname += str[p];
  746. p++;
  747. }
  748. }
  749. if (p < str.length()) {
  750. assert(str[p] == VARIABLE_CLOSE_BRACE);
  751. p++;
  752. } else {
  753. cerr << "Warning! Unclosed variable reference:\n"
  754. << str.substr(vp) << "\n";
  755. }
  756. vp = p;
  757. // Check for a function expansion.
  758. if (whitespace_at != 0) {
  759. string funcname = varname.substr(0, whitespace_at);
  760. p = whitespace_at;
  761. while (p < varname.length() && isspace(varname[p])) {
  762. p++;
  763. }
  764. string params = varname.substr(p);
  765. // Is it a user-defined function?
  766. const PPSubroutine *sub = PPSubroutine::get_func(funcname);
  767. if (sub != (const PPSubroutine *)NULL) {
  768. return expand_function(funcname, sub, params);
  769. }
  770. // Is it a built-in function?
  771. if (funcname == "isfullpath") {
  772. return expand_isfullpath(params);
  773. } else if (funcname == "osfilename") {
  774. return expand_osfilename(params);
  775. } else if (funcname == "unixfilename") {
  776. return expand_unixfilename(params);
  777. } else if (funcname == "cygpath_w") {
  778. return expand_cygpath_w(params);
  779. } else if (funcname == "cygpath_p") {
  780. return expand_cygpath_p(params);
  781. } else if (funcname == "wildcard") {
  782. return expand_wildcard(params);
  783. } else if (funcname == "isdir") {
  784. return expand_isdir(params);
  785. } else if (funcname == "isfile") {
  786. return expand_isfile(params);
  787. } else if (funcname == "libtest") {
  788. return expand_libtest(params);
  789. } else if (funcname == "bintest") {
  790. return expand_bintest(params);
  791. } else if (funcname == "shell") {
  792. return expand_shell(params);
  793. } else if (funcname == "standardize") {
  794. return expand_standardize(params);
  795. } else if (funcname == "length") {
  796. return expand_length(params);
  797. } else if (funcname == "substr") {
  798. return expand_substr(params);
  799. } else if (funcname == "findstring") {
  800. return expand_findstring(params);
  801. } else if (funcname == "dir") {
  802. return expand_dir(params);
  803. } else if (funcname == "notdir") {
  804. return expand_notdir(params);
  805. } else if (funcname == "suffix") {
  806. return expand_suffix(params);
  807. } else if (funcname == "basename") {
  808. return expand_basename(params);
  809. } else if (funcname == "word") {
  810. return expand_word(params);
  811. } else if (funcname == "wordlist") {
  812. return expand_wordlist(params);
  813. } else if (funcname == "words") {
  814. return expand_words(params);
  815. } else if (funcname == "firstword") {
  816. return expand_firstword(params);
  817. } else if (funcname == "patsubst") {
  818. return expand_patsubst(params, true);
  819. } else if (funcname == "patsubstw") {
  820. return expand_patsubst(params, false);
  821. } else if (funcname == "subst") {
  822. return expand_subst(params);
  823. } else if (funcname == "wordsubst") {
  824. return expand_wordsubst(params);
  825. } else if (funcname == "filter") {
  826. return expand_filter(params);
  827. } else if (funcname == "filter_out" || funcname == "filter-out") {
  828. return expand_filter_out(params);
  829. } else if (funcname == "sort") {
  830. return expand_sort(params);
  831. } else if (funcname == "unique") {
  832. return expand_unique(params);
  833. } else if (funcname == "matrix") {
  834. return expand_matrix(params);
  835. } else if (funcname == "if") {
  836. return expand_if(params);
  837. } else if (funcname == "eq") {
  838. return expand_eq(params);
  839. } else if (funcname == "defined") {
  840. return expand_defined(params);
  841. } else if (funcname == "ne") {
  842. return expand_ne(params);
  843. } else if (funcname == "=" || funcname == "==") {
  844. return expand_eqn(params);
  845. } else if (funcname == "!=") {
  846. return expand_nen(params);
  847. } else if (funcname == "<") {
  848. return expand_ltn(params);
  849. } else if (funcname == "<=") {
  850. return expand_len(params);
  851. } else if (funcname == ">") {
  852. return expand_gtn(params);
  853. } else if (funcname == ">=") {
  854. return expand_gen(params);
  855. } else if (funcname == "not") {
  856. return expand_not(params);
  857. } else if (funcname == "or") {
  858. return expand_or(params);
  859. } else if (funcname == "and") {
  860. return expand_and(params);
  861. } else if (funcname == "upcase") {
  862. return expand_upcase(params);
  863. } else if (funcname == "downcase") {
  864. return expand_downcase(params);
  865. } else if (funcname == "cdefine") {
  866. return expand_cdefine(params);
  867. } else if (funcname == "closure") {
  868. return expand_closure(params);
  869. } else if (funcname == "unmapped") {
  870. return expand_unmapped(params);
  871. } else if (funcname == "dependencies") {
  872. return expand_dependencies(params);
  873. } else if (funcname == "foreach") {
  874. return expand_foreach(params);
  875. } else if (funcname == "forscopes") {
  876. return expand_forscopes(params);
  877. }
  878. // It must be a map variable.
  879. return expand_map_variable(funcname, params);
  880. }
  881. // Now we have the variable name; was it previously expanded?
  882. ExpandedVariable *ev;
  883. for (ev = expanded; ev != (ExpandedVariable *)NULL; ev = ev->_next) {
  884. if (ev->_varname == varname) {
  885. // Yes, this is a cyclical expansion.
  886. cerr << "Ignoring cyclical expansion of " << varname << "\n";
  887. return string();
  888. }
  889. }
  890. // And now expand the variable.
  891. string expansion;
  892. // Check for a special inline patsubst operation, like GNU make:
  893. // $[varname:%.c=%.o]
  894. string patsubst;
  895. bool got_patsubst = false;
  896. p = varname.find(variable_patsubst);
  897. if (p != string::npos) {
  898. got_patsubst = true;
  899. patsubst = varname.substr(p + variable_patsubst.length());
  900. varname = varname.substr(0, p);
  901. }
  902. // Check for special scoping operators in the variable name.
  903. p = varname.find(VARIABLE_OPEN_NESTED);
  904. if (p != string::npos && varname[varname.length() - 1] == VARIABLE_CLOSE_NESTED) {
  905. size_t q = varname.length() - 1;
  906. string scope_names = varname.substr(p + 1, q - (p + 1));
  907. varname = varname.substr(0, p);
  908. expansion = expand_variable_nested(varname, scope_names);
  909. } else {
  910. // No special scoping; just expand the variable name.
  911. expansion = get_variable(varname);
  912. }
  913. // Finally, recursively expand any variable references in the
  914. // variable's expansion.
  915. ExpandedVariable new_var;
  916. new_var._varname = varname;
  917. new_var._next = expanded;
  918. string result = r_expand_string(expansion, &new_var);
  919. // And *then* apply any inline patsubst.
  920. if (got_patsubst) {
  921. vector<string> tokens;
  922. tokenize(patsubst, tokens, VARIABLE_PATSUBST_DELIM);
  923. if (tokens.size() != 2) {
  924. cerr << "inline patsubst should be of the form "
  925. << VARIABLE_PREFIX << VARIABLE_OPEN_BRACE << "varname"
  926. << VARIABLE_PATSUBST << PATTERN_WILDCARD << ".c"
  927. << VARIABLE_PATSUBST_DELIM << PATTERN_WILDCARD << ".o"
  928. << VARIABLE_CLOSE_BRACE << ".\n";
  929. } else {
  930. PPFilenamePattern from(tokens[0]);
  931. PPFilenamePattern to(tokens[1]);
  932. if (!from.has_wildcard() || !to.has_wildcard()) {
  933. cerr << "The two parameters of inline patsubst must both include "
  934. << PATTERN_WILDCARD << ".\n";
  935. return string();
  936. }
  937. // Split the expansion into tokens based on the spaces.
  938. vector<string> words;
  939. tokenize_whitespace(result, words);
  940. vector<string>::iterator wi;
  941. for (wi = words.begin(); wi != words.end(); ++wi) {
  942. (*wi) = to.transform(*wi, from);
  943. }
  944. result = repaste(words, " ");
  945. }
  946. }
  947. return result;
  948. }
  949. ////////////////////////////////////////////////////////////////////
  950. // Function: PPScope::expand_variable_nested
  951. // Access: Private
  952. // Description: Expands a variable reference of the form
  953. // $[varname(scope scope scope)]. This means to
  954. // concatenate the expansions of the variable in all of
  955. // the named scopes.
  956. ////////////////////////////////////////////////////////////////////
  957. string PPScope::
  958. expand_variable_nested(const string &varname,
  959. const string &scope_names) {
  960. if (_named_scopes == (PPNamedScopes *)NULL) {
  961. return string();
  962. }
  963. vector<string> names;
  964. tokenize_whitespace(scope_names, names);
  965. // Get all of the named scopes.
  966. PPNamedScopes::Scopes scopes;
  967. vector<string>::const_iterator ni;
  968. for (ni = names.begin(); ni != names.end(); ++ni) {
  969. const string &name = (*ni);
  970. _named_scopes->get_scopes(name, scopes);
  971. }
  972. if (scopes.empty()) {
  973. return string();
  974. }
  975. // Now go through the scopes and build up the results.
  976. vector<string> results;
  977. PPNamedScopes::Scopes::const_iterator si;
  978. for (si = scopes.begin(); si != scopes.end(); ++si) {
  979. PPScope *scope = (*si);
  980. string nested = scope->expand_variable(varname);
  981. if (!nested.empty()) {
  982. results.push_back(nested);
  983. }
  984. }
  985. string result = repaste(results, " ");
  986. return result;
  987. }
  988. ////////////////////////////////////////////////////////////////////
  989. // Function: PPScope::expand_isfullpath
  990. // Access: Private
  991. // Description: Expands the "isfullpath" function variable. This
  992. // returns true (actually, the same as its input) if the
  993. // input parameter is a fully-specified path name,
  994. // meaning it begins with a slash for unix_platform, and
  995. // it begins with a slash or backslash, with an optional
  996. // drive leterr, for windows_platform.
  997. ////////////////////////////////////////////////////////////////////
  998. string PPScope::
  999. expand_isfullpath(const string &params) {
  1000. string filename = trim_blanks(expand_string(params));
  1001. string result;
  1002. if (is_fullpath(filename)) {
  1003. result = filename;
  1004. }
  1005. return result;
  1006. }
  1007. ////////////////////////////////////////////////////////////////////
  1008. // Function: PPScope::expand_osfilename
  1009. // Access: Private
  1010. // Description: Expands the "osfilename" function variable. This
  1011. // converts the filename from a Unix-style filename
  1012. // (e.g. with slash separators) to a platform-specific
  1013. // filename. Currently, this only has an effect when
  1014. // generating code for a Windows platform: it simply
  1015. // converts forward slashes to backslashes. On other
  1016. // platforms it has no effect.
  1017. //
  1018. // This is different from cygpath_w in that (a) it works
  1019. // regardless of whether we are actually running under
  1020. // Cygwin, and (b) it does nothing more intelligent than
  1021. // reverse slashes.
  1022. ////////////////////////////////////////////////////////////////////
  1023. string PPScope::
  1024. expand_osfilename(const string &params) {
  1025. // Split the parameter into tokens based on the spaces.
  1026. vector<string> words;
  1027. tokenize_whitespace(expand_string(params), words);
  1028. vector<string>::iterator wi;
  1029. for (wi = words.begin(); wi != words.end(); ++wi) {
  1030. (*wi) = to_os_filename(*wi);
  1031. }
  1032. string result = repaste(words, " ");
  1033. return result;
  1034. }
  1035. ////////////////////////////////////////////////////////////////////
  1036. // Function: PPScope::expand_unixfilename
  1037. // Access: Private
  1038. // Description: Expands the "unixfilename" function variable. This
  1039. // converts the filename from a platform-specific
  1040. // filename to a Unix-style filename (e.g. with slash
  1041. // separators). Currently, this only has an effect when
  1042. // generating code for a Windows platform: it simply
  1043. // converts backslashes to forward slashes. On other
  1044. // platforms it has no effect.
  1045. //
  1046. // This is different from cygpath_p in that (a) it works
  1047. // regardless of whether we are actually running under
  1048. // Cygwin, and (b) it does nothing more intelligent than
  1049. // reverse slashes.
  1050. ////////////////////////////////////////////////////////////////////
  1051. string PPScope::
  1052. expand_unixfilename(const string &params) {
  1053. // Split the parameter into tokens based on the spaces.
  1054. vector<string> words;
  1055. tokenize_whitespace(expand_string(params), words);
  1056. vector<string>::iterator wi;
  1057. for (wi = words.begin(); wi != words.end(); ++wi) {
  1058. (*wi) = to_unix_filename(*wi);
  1059. }
  1060. string result = repaste(words, " ");
  1061. return result;
  1062. }
  1063. ////////////////////////////////////////////////////////////////////
  1064. // Function: PPScope::expand_cygpath_w
  1065. // Access: Private
  1066. // Description: Expands the "cygpath_w" function variable. This is
  1067. // equivalent to $[shell cygpath -w ...] when running
  1068. // under Cygwin, and returns the parameter itself when
  1069. // not running under Cygwin.
  1070. ////////////////////////////////////////////////////////////////////
  1071. string PPScope::
  1072. expand_cygpath_w(const string &params) {
  1073. string filename = trim_blanks(expand_string(params));
  1074. #ifdef __CYGWIN__
  1075. char result[4096];
  1076. cygwin_conv_to_win32_path(filename.c_str(), result);
  1077. filename = result;
  1078. #endif
  1079. return filename;
  1080. }
  1081. ////////////////////////////////////////////////////////////////////
  1082. // Function: PPScope::expand_cygpath_p
  1083. // Access: Private
  1084. // Description: Expands the "cygpath_p" function variable. This is
  1085. // equivalent to $[shell cygpath -p ...] when running
  1086. // under Cygwin, and returns the parameter itself when
  1087. // not running under Cygwin.
  1088. ////////////////////////////////////////////////////////////////////
  1089. string PPScope::
  1090. expand_cygpath_p(const string &params) {
  1091. string filename = trim_blanks(expand_string(params));
  1092. #ifdef __CYGWIN__
  1093. char result[4096];
  1094. cygwin_conv_to_posix_path(filename.c_str(), result);
  1095. filename = result;
  1096. #endif
  1097. return filename;
  1098. }
  1099. ////////////////////////////////////////////////////////////////////
  1100. // Function: PPScope::expand_wildcard
  1101. // Access: Private
  1102. // Description: Expands the "wildcard" function variable. This
  1103. // returns the set of files matched by the parameters
  1104. // with shell matching characters.
  1105. ////////////////////////////////////////////////////////////////////
  1106. string PPScope::
  1107. expand_wildcard(const string &params) {
  1108. vector<string> results;
  1109. glob_string(expand_string(params), results);
  1110. string result = repaste(results, " ");
  1111. return result;
  1112. }
  1113. ////////////////////////////////////////////////////////////////////
  1114. // Function: PPScope::expand_isdir
  1115. // Access: Private
  1116. // Description: Expands the "isdir" function variable. This
  1117. // returns true if the parameter exists and is a
  1118. // directory, or false otherwise. This actually expands
  1119. // the parameter(s) with shell globbing characters,
  1120. // similar to the "wildcard" function, and looks only at
  1121. // the first expansion.
  1122. ////////////////////////////////////////////////////////////////////
  1123. string PPScope::
  1124. expand_isdir(const string &params) {
  1125. vector<string> results;
  1126. glob_string(expand_string(params), results);
  1127. if (results.empty()) {
  1128. // No matching file, too bad.
  1129. return string();
  1130. }
  1131. const string &filename = results[0];
  1132. struct stat stbuf;
  1133. string result;
  1134. if (stat(filename.c_str(), &stbuf) == 0) {
  1135. if (S_ISDIR(stbuf.st_mode)) {
  1136. result = filename;
  1137. }
  1138. }
  1139. return result;
  1140. }
  1141. ////////////////////////////////////////////////////////////////////
  1142. // Function: PPScope::expand_isfile
  1143. // Access: Private
  1144. // Description: Expands the "isfile" function variable. This
  1145. // returns true if the parameter exists and is a
  1146. // regular file, or false otherwise. This actually
  1147. // expands the parameter(s) with shell globbing
  1148. // characters, similar to the "wildcard" function, and
  1149. // looks only at the first expansion.
  1150. ////////////////////////////////////////////////////////////////////
  1151. string PPScope::
  1152. expand_isfile(const string &params) {
  1153. vector<string> results;
  1154. glob_string(expand_string(params), results);
  1155. if (results.empty()) {
  1156. // No matching file, too bad.
  1157. return string();
  1158. }
  1159. const string &filename = results[0];
  1160. struct stat stbuf;
  1161. string result;
  1162. if (stat(filename.c_str(), &stbuf) == 0) {
  1163. if (S_ISREG(stbuf.st_mode)) {
  1164. result = filename;
  1165. }
  1166. }
  1167. return result;
  1168. }
  1169. ////////////////////////////////////////////////////////////////////
  1170. // Function: PPScope::expand_libtest
  1171. // Access: Private
  1172. // Description: Expands the "libtest" function variable. This
  1173. // serves as a poor man's autoconf feature to check to
  1174. // see if a library by the given name exists on the
  1175. // indicated search path, or on the system search path.
  1176. ////////////////////////////////////////////////////////////////////
  1177. string PPScope::
  1178. expand_libtest(const string &params) {
  1179. // Get the parameters out based on commas. The first parameter is a
  1180. // space-separated set of directories to search, the second
  1181. // parameter is a space-separated set of library names.
  1182. vector<string> tokens;
  1183. tokenize_params(params, tokens, true);
  1184. if (tokens.size() != 2) {
  1185. cerr << "libtest requires two parameters.\n";
  1186. return string();
  1187. }
  1188. vector<string> directories;
  1189. tokenize_whitespace(tokens[0], directories);
  1190. // Also add the system directories to the list, whatever we think
  1191. // those should be. Here we have to make a few assumptions.
  1192. #ifdef PLATFORM_WIN32
  1193. const char *windir = getenv("WINDIR");
  1194. if (windir != (const char *)NULL) {
  1195. directories.push_back(string(windir) + "\\System");
  1196. directories.push_back(string(windir) + "\\System32");
  1197. }
  1198. const char *lib = getenv("LIB");
  1199. if (lib != (const char *)NULL) {
  1200. tokenize(lib, directories, ";");
  1201. }
  1202. #endif
  1203. // We'll also check the Unix standard places, even if we're building
  1204. // Windows, since we might be using Cygwin.
  1205. // Check LD_LIBRARY_PATH.
  1206. const char *ld_library_path = getenv("LD_LIBRARY_PATH");
  1207. if (ld_library_path != (const char *)NULL) {
  1208. tokenize(ld_library_path, directories, ":");
  1209. }
  1210. directories.push_back("/lib");
  1211. directories.push_back("/usr/lib");
  1212. vector<string> libnames;
  1213. tokenize_whitespace(tokens[1], libnames);
  1214. if (libnames.empty()) {
  1215. // No libraries is a default "false".
  1216. return string();
  1217. }
  1218. // We only bother to search for the first library name in the list.
  1219. string libname = libnames[0];
  1220. string found;
  1221. #ifdef PLATFORM_WIN32
  1222. if (libname.length() > 4 && libname.substr(libname.length() - 4) == ".lib") {
  1223. found = find_searchpath(directories, libname);
  1224. if (found.empty()) {
  1225. found = find_searchpath(directories, libname.substr(0, libname.length() - 4) + ".dll");
  1226. }
  1227. } else {
  1228. found = find_searchpath(directories, "lib" + libname + ".lib");
  1229. if (found.empty()) {
  1230. found = find_searchpath(directories, "lib" + libname + ".dll");
  1231. }
  1232. }
  1233. #else
  1234. found = find_searchpath(directories, "lib" + libname + ".a");
  1235. if (found.empty()) {
  1236. found = find_searchpath(directories, "lib" + libname + ".so");
  1237. }
  1238. #endif
  1239. return found;
  1240. }
  1241. ////////////////////////////////////////////////////////////////////
  1242. // Function: PPScope::expand_bintest
  1243. // Access: Private
  1244. // Description: Expands the "bintest" function variable. This
  1245. // serves as a poor man's autoconf feature to check to
  1246. // see if an executable program by the given name exists
  1247. // on the indicated search path, or on the system search
  1248. // path.
  1249. ////////////////////////////////////////////////////////////////////
  1250. string PPScope::
  1251. expand_bintest(const string &params) {
  1252. // We only have one parameter: the filename of the executable. We
  1253. // always search for it on the path.
  1254. string binname = expand_string(params);
  1255. if (binname.empty()) {
  1256. // No binary, no exist.
  1257. return string();
  1258. }
  1259. // An explicit path from the root does not require a search.
  1260. #ifdef PLATFORM_WIN32
  1261. if ((binname.length() > 2 && binname[1] == ':') || binname[0] == '/')
  1262. #else
  1263. if (binname[0] == '/')
  1264. #endif
  1265. {
  1266. if (access(binname.c_str(), F_OK) == 0) {
  1267. return binname;
  1268. }
  1269. return string();
  1270. }
  1271. const char *path = getenv("PATH");
  1272. if (path == (const char *)NULL) {
  1273. // If the path is undefined, too bad.
  1274. return string();
  1275. }
  1276. string pathvar(path);
  1277. vector<string> directories;
  1278. #ifdef PLATFORM_WIN32
  1279. if (pathvar.find(';') != string::npos) {
  1280. // If the path contains semicolons, it's a native Windows-style
  1281. // path: split it up based on semicolons.
  1282. tokenize(pathvar, directories, ";");
  1283. } else {
  1284. // Otherwise, assume it's a Cygwin-style path: split it up based
  1285. // on colons.
  1286. tokenize(pathvar, directories, ":");
  1287. }
  1288. #else
  1289. tokenize(pathvar, directories, ":");
  1290. #endif
  1291. string found;
  1292. #ifdef PLATFORM_WIN32
  1293. found = find_searchpath(directories, binname + ".exe");
  1294. if (found.empty()) {
  1295. found = find_searchpath(directories, binname);
  1296. }
  1297. #else
  1298. found = find_searchpath(directories, binname);
  1299. #endif
  1300. return found;
  1301. }
  1302. ////////////////////////////////////////////////////////////////////
  1303. // Function: PPScope::expand_shell
  1304. // Access: Private
  1305. // Description: Expands the "shell" function variable. This executes
  1306. // the given command in a subprocess and returns the
  1307. // standard output.
  1308. ////////////////////////////////////////////////////////////////////
  1309. string PPScope::
  1310. expand_shell(const string &params) {
  1311. // We run $[shell] commands within the directory indicated by
  1312. // $[THISDIRPREFIX]. This way, local filenames will be expanded the
  1313. // way we expect.
  1314. string dirname = trim_blanks(expand_variable("THISDIRPREFIX"));
  1315. string command = expand_string(params);
  1316. int pid, status;
  1317. int pd[2];
  1318. if (pipe(pd) < 0) {
  1319. // pipe() failed.
  1320. perror("pipe");
  1321. return string();
  1322. }
  1323. pid = fork();
  1324. if (pid < 0) {
  1325. // fork() failed.
  1326. perror("fork");
  1327. return string();
  1328. }
  1329. if (pid == 0) {
  1330. // Child.
  1331. if (!dirname.empty()) {
  1332. // We don't have to restore the directory after we're done,
  1333. // because we're doing the chdir() call only within the child
  1334. // process.
  1335. if (chdir(dirname.c_str()) < 0) {
  1336. perror("chdir");
  1337. }
  1338. }
  1339. close(pd[0]);
  1340. dup2(pd[1], STDOUT_FILENO);
  1341. char *argv[4];
  1342. argv[0] = "sh";
  1343. argv[1] = "-c";
  1344. argv[2] = (char *)command.c_str();
  1345. argv[3] = (char *)NULL;
  1346. execv("/bin/sh", argv);
  1347. exit(127);
  1348. }
  1349. // Parent. Wait for the child to terminate, and read from its
  1350. // output while we're waiting.
  1351. close(pd[1]);
  1352. bool child_done = false;
  1353. bool pipe_closed = false;
  1354. string output;
  1355. while (!child_done && !pipe_closed) {
  1356. static const int buffer_size = 1024;
  1357. char buffer[buffer_size];
  1358. int read_bytes = (int)read(pd[0], buffer, buffer_size);
  1359. if (read_bytes < 0) {
  1360. perror("read");
  1361. } else if (read_bytes == 0) {
  1362. pipe_closed = true;
  1363. } else {
  1364. output += string(buffer, read_bytes);
  1365. }
  1366. if (!child_done) {
  1367. int waitresult = waitpid(pid, &status, WNOHANG);
  1368. if (waitresult < 0) {
  1369. if (errno != EINTR) {
  1370. perror("waitpid");
  1371. return string();
  1372. }
  1373. } else if (waitresult > 0) {
  1374. child_done = true;
  1375. }
  1376. }
  1377. }
  1378. close(pd[0]);
  1379. // Now get the output. We split it into words and then reconnect
  1380. // it, to simulate the shell's backpop operator.
  1381. vector<string> results;
  1382. tokenize_whitespace(output, results);
  1383. string result = repaste(results, " ");
  1384. return result;
  1385. }
  1386. ////////////////////////////////////////////////////////////////////
  1387. // Function: PPScope::expand_standardize
  1388. // Access: Private
  1389. // Description: Expands the "standardize" function variable. This
  1390. // converts the filename to standard form by removing
  1391. // consecutive repeated slashes and collapsing /../
  1392. // where possible.
  1393. ////////////////////////////////////////////////////////////////////
  1394. string PPScope::
  1395. expand_standardize(const string &params) {
  1396. string filename = trim_blanks(expand_string(params));
  1397. if (filename.empty()) {
  1398. return string();
  1399. }
  1400. vector<string> components;
  1401. // Pull off the components of the filename one at a time.
  1402. bool global = (filename[0] == '/');
  1403. size_t p = 0;
  1404. while (p < filename.length() && filename[p] == '/') {
  1405. p++;
  1406. }
  1407. while (p < filename.length()) {
  1408. size_t slash = filename.find('/', p);
  1409. string component = filename.substr(p, slash - p);
  1410. if (component == ".") {
  1411. // Ignore /./.
  1412. } else if (component == ".." && !components.empty() &&
  1413. !(components.back() == "..")) {
  1414. // Back up.
  1415. components.pop_back();
  1416. } else {
  1417. components.push_back(component);
  1418. }
  1419. p = slash;
  1420. while (p < filename.length() && filename[p] == '/') {
  1421. p++;
  1422. }
  1423. }
  1424. // Now reassemble the filename.
  1425. string result;
  1426. if (global) {
  1427. result = "/";
  1428. }
  1429. if (!components.empty()) {
  1430. result += components[0];
  1431. for (int i = 1; i < (int)components.size(); i++) {
  1432. result += "/" + components[i];
  1433. }
  1434. }
  1435. return result;
  1436. }
  1437. ////////////////////////////////////////////////////////////////////
  1438. // Function: PPScope::expand_length
  1439. // Access: Private
  1440. // Description: Expands the "length" function variable. This returns
  1441. // the length of the argument in characters.
  1442. ////////////////////////////////////////////////////////////////////
  1443. string PPScope::
  1444. expand_length(const string &params) {
  1445. string word = trim_blanks(expand_string(params));
  1446. char buffer[32];
  1447. sprintf(buffer, "%d", word.length());
  1448. string result = buffer;
  1449. return result;
  1450. }
  1451. ////////////////////////////////////////////////////////////////////
  1452. // Function: PPScope::expand_substr
  1453. // Access: Private
  1454. // Description: Expands the "substr" function variable. $[substr
  1455. // S,E,string] returns the substring of "string"
  1456. // beginning at character S (1-based) and continuing to
  1457. // character E, inclusive.
  1458. ////////////////////////////////////////////////////////////////////
  1459. string PPScope::
  1460. expand_substr(const string &params) {
  1461. // Split the string up into tokens based on the commas.
  1462. vector<string> tokens;
  1463. tokenize_params(params, tokens, true);
  1464. if (tokens.size() != 3) {
  1465. cerr << "substr requires three parameters.\n";
  1466. return string();
  1467. }
  1468. int start = atoi(tokens[0].c_str());
  1469. int end = atoi(tokens[1].c_str());
  1470. if (end < start) {
  1471. // Following GNU make's convention, we swap start and end if
  1472. // they're out of order.
  1473. int t = end;
  1474. end = start;
  1475. start = t;
  1476. }
  1477. const string &word = tokens[2];
  1478. start = max(start, 1);
  1479. end = min(end, (int)word.length());
  1480. if (end < start) {
  1481. return string();
  1482. }
  1483. string result = word.substr(start - 1, end - start + 1);
  1484. return result;
  1485. }
  1486. ////////////////////////////////////////////////////////////////////
  1487. // Function: PPScope::expand_dir
  1488. // Access: Private
  1489. // Description: Expands the "dir" function variable. This returns
  1490. // the directory part of its filename argument(s), or ./
  1491. // if the words contain no slash.
  1492. ////////////////////////////////////////////////////////////////////
  1493. string PPScope::
  1494. expand_dir(const string &params) {
  1495. // Split the parameter into tokens based on the spaces.
  1496. vector<string> words;
  1497. tokenize_whitespace(expand_string(params), words);
  1498. vector<string>::iterator wi;
  1499. for (wi = words.begin(); wi != words.end(); ++wi) {
  1500. string &word = (*wi);
  1501. size_t slash = word.rfind('/');
  1502. if (slash != string::npos) {
  1503. word = word.substr(0, slash + 1);
  1504. } else {
  1505. word = "./";
  1506. }
  1507. }
  1508. string result = repaste(words, " ");
  1509. return result;
  1510. }
  1511. ////////////////////////////////////////////////////////////////////
  1512. // Function: PPScope::expand_notdir
  1513. // Access: Private
  1514. // Description: Expands the "notdir" function variable. This returns
  1515. // everything following the rightmost slash, or the
  1516. // string itself if there is no slash.
  1517. ////////////////////////////////////////////////////////////////////
  1518. string PPScope::
  1519. expand_notdir(const string &params) {
  1520. // Split the parameter into tokens based on the spaces.
  1521. vector<string> words;
  1522. tokenize_whitespace(expand_string(params), words);
  1523. vector<string>::iterator wi;
  1524. for (wi = words.begin(); wi != words.end(); ++wi) {
  1525. string &word = (*wi);
  1526. size_t slash = word.rfind('/');
  1527. if (slash != string::npos) {
  1528. word = word.substr(slash + 1);
  1529. }
  1530. }
  1531. string result = repaste(words, " ");
  1532. return result;
  1533. }
  1534. ////////////////////////////////////////////////////////////////////
  1535. // Function: PPScope::expand_suffix
  1536. // Access: Private
  1537. // Description: Expands the "suffix" function variable. This returns
  1538. // the filename extension, including a dot, if any.
  1539. ////////////////////////////////////////////////////////////////////
  1540. string PPScope::
  1541. expand_suffix(const string &params) {
  1542. // Split the parameter into tokens based on the spaces.
  1543. vector<string> words;
  1544. tokenize_whitespace(expand_string(params), words);
  1545. vector<string>::iterator wi;
  1546. for (wi = words.begin(); wi != words.end(); ++wi) {
  1547. string &word = (*wi);
  1548. size_t dot = word.rfind('.');
  1549. if (dot != string::npos) {
  1550. string ext = word.substr(dot);
  1551. if (ext.find('/') == string::npos) {
  1552. word = ext;
  1553. } else {
  1554. word = string();
  1555. }
  1556. } else {
  1557. word = string();
  1558. }
  1559. }
  1560. string result = repaste(words, " ");
  1561. return result;
  1562. }
  1563. ////////////////////////////////////////////////////////////////////
  1564. // Function: PPScope::expand_basename
  1565. // Access: Private
  1566. // Description: Expands the "basename" function variable. This returns
  1567. // everything but the filename extension (including the
  1568. // directory, if any).
  1569. ////////////////////////////////////////////////////////////////////
  1570. string PPScope::
  1571. expand_basename(const string &params) {
  1572. // Split the parameter into tokens based on the spaces.
  1573. vector<string> words;
  1574. tokenize_whitespace(expand_string(params), words);
  1575. vector<string>::iterator wi;
  1576. for (wi = words.begin(); wi != words.end(); ++wi) {
  1577. string &word = (*wi);
  1578. size_t dot = word.rfind('.');
  1579. if (dot != string::npos) {
  1580. string ext = word.substr(dot);
  1581. if (ext.find('/') == string::npos) {
  1582. word = word.substr(0, dot);
  1583. }
  1584. }
  1585. }
  1586. string result = repaste(words, " ");
  1587. return result;
  1588. }
  1589. ////////////////////////////////////////////////////////////////////
  1590. // Function: PPScope::expand_word
  1591. // Access: Private
  1592. // Description: Expands the "word" function variable. This returns
  1593. // the nth word, 1-based, of the space-separated list of
  1594. // words in the second parameter.
  1595. ////////////////////////////////////////////////////////////////////
  1596. string PPScope::
  1597. expand_word(const string &params) {
  1598. // Split the string up into tokens based on the commas.
  1599. vector<string> tokens;
  1600. tokenize_params(params, tokens, true);
  1601. if (tokens.size() != 2) {
  1602. cerr << "word requires two parameters.\n";
  1603. return string();
  1604. }
  1605. int index = atoi(tokens[0].c_str());
  1606. // Split the second parameter into tokens based on the spaces.
  1607. vector<string> words;
  1608. tokenize_whitespace(expand_string(tokens[1]), words);
  1609. if (index < 1 || index > (int)words.size()) {
  1610. // Out of range.
  1611. return string();
  1612. }
  1613. return words[index - 1];
  1614. }
  1615. ////////////////////////////////////////////////////////////////////
  1616. // Function: PPScope::expand_wordlist
  1617. // Access: Private
  1618. // Description: Expands the "wordlist" function variable. This
  1619. // returns a range of words, 1-based, of the
  1620. // space-separated list of words in the third parameter.
  1621. ////////////////////////////////////////////////////////////////////
  1622. string PPScope::
  1623. expand_wordlist(const string &params) {
  1624. // Split the string up into tokens based on the commas.
  1625. vector<string> tokens;
  1626. tokenize_params(params, tokens, true);
  1627. if (tokens.size() != 3) {
  1628. cerr << "wordlist requires three parameters.\n";
  1629. return string();
  1630. }
  1631. int start = atoi(tokens[0].c_str());
  1632. int end = atoi(tokens[1].c_str());
  1633. if (end < start) {
  1634. // Following GNU make's convention, we swap start and end if
  1635. // they're out of order.
  1636. int t = end;
  1637. end = start;
  1638. start = t;
  1639. }
  1640. // Split the third parameter into tokens based on the spaces.
  1641. vector<string> words;
  1642. tokenize_whitespace(expand_string(tokens[2]), words);
  1643. start = max(start, 1);
  1644. end = min(end, (int)words.size() + 1);
  1645. if (end < start) {
  1646. return string();
  1647. }
  1648. vector<string> results;
  1649. results.insert(results.end(),
  1650. words.begin() + start - 1,
  1651. words.begin() + end - 1);
  1652. string result = repaste(results, " ");
  1653. return result;
  1654. }
  1655. ////////////////////////////////////////////////////////////////////
  1656. // Function: PPScope::expand_words
  1657. // Access: Private
  1658. // Description: Expands the "words" function variable. This
  1659. // returns the number of space-separated words in the
  1660. // list.
  1661. ////////////////////////////////////////////////////////////////////
  1662. string PPScope::
  1663. expand_words(const string &params) {
  1664. // Split the parameter into tokens based on the spaces.
  1665. vector<string> words;
  1666. tokenize_whitespace(expand_string(params), words);
  1667. char buffer[32];
  1668. sprintf(buffer, "%d", words.size());
  1669. string result = buffer;
  1670. return result;
  1671. }
  1672. ////////////////////////////////////////////////////////////////////
  1673. // Function: PPScope::expand_firstword
  1674. // Access: Private
  1675. // Description: Expands the "firstword" function variable. This
  1676. // returns the first of several words separated by
  1677. // whitespace.
  1678. ////////////////////////////////////////////////////////////////////
  1679. string PPScope::
  1680. expand_firstword(const string &params) {
  1681. // Split the parameter into tokens based on the spaces.
  1682. vector<string> words;
  1683. tokenize_whitespace(expand_string(params), words);
  1684. if (!words.empty()) {
  1685. return words[0];
  1686. }
  1687. return string();
  1688. }
  1689. ////////////////////////////////////////////////////////////////////
  1690. // Function: PPScope::expand_patsubst
  1691. // Access: Private
  1692. // Description: Expands the "patsubst" function variable.
  1693. ////////////////////////////////////////////////////////////////////
  1694. string PPScope::
  1695. expand_patsubst(const string &params, bool separate_words) {
  1696. // Split the string up into tokens based on the commas.
  1697. vector<string> tokens;
  1698. tokenize_params(params, tokens, true);
  1699. if (tokens.size() < 3) {
  1700. cerr << "patsubst requires at least three parameters.\n";
  1701. return string();
  1702. }
  1703. if ((tokens.size() % 2) != 1) {
  1704. cerr << "subst requires an odd number of parameters.\n";
  1705. return string();
  1706. }
  1707. // Split the last parameter into tokens based on the spaces--but
  1708. // only if separate_words is true.
  1709. vector<string> words;
  1710. if (separate_words) {
  1711. tokenize_whitespace(tokens.back(), words);
  1712. } else {
  1713. words.push_back(tokens.back());
  1714. }
  1715. // Build up a vector of from/to patterns.
  1716. typedef vector<PPFilenamePattern> Patterns;
  1717. typedef vector<Patterns> FromPatterns;
  1718. FromPatterns from;
  1719. Patterns to;
  1720. size_t i;
  1721. for (i = 0; i < tokens.size() - 1; i += 2) {
  1722. // Each "from" pattern might be a collection of patterns separated
  1723. // by spaces.
  1724. from.push_back(Patterns());
  1725. vector<string> froms;
  1726. tokenize_whitespace(tokens[i], froms);
  1727. vector<string>::const_iterator fi;
  1728. for (fi = froms.begin(); fi != froms.end(); ++fi) {
  1729. PPFilenamePattern pattern(*fi);
  1730. if (!pattern.has_wildcard()) {
  1731. cerr << "All the \"from\" parameters of patsubst must include "
  1732. << PATTERN_WILDCARD << ".\n";
  1733. return string();
  1734. }
  1735. from.back().push_back(pattern);
  1736. }
  1737. // However, the corresponding "to" pattern is just one pattern.
  1738. to.push_back(PPFilenamePattern(tokens[i + 1]));
  1739. }
  1740. size_t num_patterns = from.size();
  1741. assert(num_patterns == to.size());
  1742. vector<string>::iterator wi;
  1743. for (wi = words.begin(); wi != words.end(); ++wi) {
  1744. bool matched = false;
  1745. for (i = 0; i < num_patterns && !matched; i++) {
  1746. Patterns::const_iterator pi;
  1747. for (pi = from[i].begin(); pi != from[i].end() && !matched; ++pi) {
  1748. if ((*pi).matches(*wi)) {
  1749. matched = true;
  1750. (*wi) = to[i].transform(*wi, (*pi));
  1751. }
  1752. }
  1753. }
  1754. }
  1755. string result = repaste(words, " ");
  1756. return result;
  1757. }
  1758. ////////////////////////////////////////////////////////////////////
  1759. // Function: PPScope::expand_filter
  1760. // Access: Private
  1761. // Description: Expands the "filter" function variable.
  1762. ////////////////////////////////////////////////////////////////////
  1763. string PPScope::
  1764. expand_filter(const string &params) {
  1765. // Split the string up into tokens based on the commas.
  1766. vector<string> tokens;
  1767. tokenize_params(params, tokens, true);
  1768. if (tokens.size() != 2) {
  1769. cerr << "filter requires two parameters.\n";
  1770. return string();
  1771. }
  1772. // Split up the first parameter--the list of patterns to filter
  1773. // by--into tokens based on the spaces.
  1774. vector<string> pattern_strings;
  1775. tokenize_whitespace(tokens[0], pattern_strings);
  1776. vector<PPFilenamePattern> patterns;
  1777. vector<string>::const_iterator psi;
  1778. for (psi = pattern_strings.begin(); psi != pattern_strings.end(); ++psi) {
  1779. patterns.push_back(PPFilenamePattern(*psi));
  1780. }
  1781. // Split up the second parameter--the list of words to filter--into
  1782. // tokens based on the spaces.
  1783. vector<string> words;
  1784. tokenize_whitespace(tokens[1], words);
  1785. vector<string>::iterator wi, wnext;
  1786. wnext = words.begin();
  1787. for (wi = words.begin(); wi != words.end(); ++wi) {
  1788. const string &word = (*wi);
  1789. bool matches_pattern = false;
  1790. vector<PPFilenamePattern>::const_iterator pi;
  1791. for (pi = patterns.begin();
  1792. pi != patterns.end() && !matches_pattern;
  1793. ++pi) {
  1794. matches_pattern = (*pi).matches(word);
  1795. }
  1796. if (matches_pattern) {
  1797. *wnext++ = word;
  1798. }
  1799. }
  1800. words.erase(wnext, words.end());
  1801. string result = repaste(words, " ");
  1802. return result;
  1803. }
  1804. ////////////////////////////////////////////////////////////////////
  1805. // Function: PPScope::expand_filter_out
  1806. // Access: Private
  1807. // Description: Expands the "filter_out" function variable.
  1808. ////////////////////////////////////////////////////////////////////
  1809. string PPScope::
  1810. expand_filter_out(const string &params) {
  1811. // Split the string up into tokens based on the commas.
  1812. vector<string> tokens;
  1813. tokenize_params(params, tokens, true);
  1814. if (tokens.size() != 2) {
  1815. cerr << "filter-out requires two parameters.\n";
  1816. return string();
  1817. }
  1818. // Split up the first parameter--the list of patterns to filter
  1819. // by--into tokens based on the spaces.
  1820. vector<string> pattern_strings;
  1821. tokenize_whitespace(tokens[0], pattern_strings);
  1822. vector<PPFilenamePattern> patterns;
  1823. vector<string>::const_iterator psi;
  1824. for (psi = pattern_strings.begin(); psi != pattern_strings.end(); ++psi) {
  1825. patterns.push_back(PPFilenamePattern(*psi));
  1826. }
  1827. // Split up the second parameter--the list of words to filter--into
  1828. // tokens based on the spaces.
  1829. vector<string> words;
  1830. tokenize_whitespace(tokens[1], words);
  1831. vector<string>::iterator wi, wnext;
  1832. wnext = words.begin();
  1833. for (wi = words.begin(); wi != words.end(); ++wi) {
  1834. const string &word = (*wi);
  1835. bool matches_pattern = false;
  1836. vector<PPFilenamePattern>::const_iterator pi;
  1837. for (pi = patterns.begin();
  1838. pi != patterns.end() && !matches_pattern;
  1839. ++pi) {
  1840. matches_pattern = (*pi).matches(word);
  1841. }
  1842. if (!matches_pattern) {
  1843. *wnext++ = word;
  1844. }
  1845. }
  1846. words.erase(wnext, words.end());
  1847. string result = repaste(words, " ");
  1848. return result;
  1849. }
  1850. ////////////////////////////////////////////////////////////////////
  1851. // Function: PPScope::expand_subst
  1852. // Access: Private
  1853. // Description: Expands the "subst" function variable.
  1854. ////////////////////////////////////////////////////////////////////
  1855. string PPScope::
  1856. expand_subst(const string &params) {
  1857. // Split the string up into tokens based on the commas.
  1858. vector<string> tokens;
  1859. tokenize_params(params, tokens, true);
  1860. if (tokens.size() < 3) {
  1861. cerr << "subst requires at least three parameters.\n";
  1862. return string();
  1863. }
  1864. if ((tokens.size() % 2) != 1) {
  1865. cerr << "subst requires an odd number of parameters.\n";
  1866. return string();
  1867. }
  1868. // Now substitute each of the substitute strings out for the
  1869. // replacement strings.
  1870. string str = tokens.back();
  1871. for (size_t i = 0; i < tokens.size() - 1; i += 2) {
  1872. string new_str;
  1873. const string &subst = tokens[i];
  1874. const string &repl = tokens[i + 1];
  1875. size_t q = 0;
  1876. size_t p = str.find(subst, q);
  1877. while (p != string::npos) {
  1878. new_str += str.substr(q, p - q) + repl;
  1879. q = p + subst.length();
  1880. p = str.find(subst, q);
  1881. }
  1882. str = new_str + str.substr(q);
  1883. }
  1884. return str;
  1885. }
  1886. ////////////////////////////////////////////////////////////////////
  1887. // Function: PPScope::expand_findstrnig
  1888. // Access: Private
  1889. // Description: Expands the "findstring" function variable.
  1890. // $[findstring a,b] returns b if and only if it is a
  1891. // substring of a; otherwise, it returns the empty
  1892. // string.
  1893. ////////////////////////////////////////////////////////////////////
  1894. string PPScope::
  1895. expand_findstring(const string &params) {
  1896. // Split the string up into tokens based on the commas.
  1897. vector<string> tokens;
  1898. tokenize_params(params, tokens, true);
  1899. if (tokens.size() != 2) {
  1900. cerr << "findstring requires two parameters.\n";
  1901. return string();
  1902. }
  1903. string str = tokens.back();
  1904. const string &srchstr = tokens[0];
  1905. size_t q = 0;
  1906. size_t p = str.find(srchstr, q);
  1907. if(p == string::npos)
  1908. str = "";
  1909. return str;
  1910. }
  1911. ////////////////////////////////////////////////////////////////////
  1912. // Function: PPScope::expand_wordsubst
  1913. // Access: Private
  1914. // Description: Expands the "wordsubst" function variable. This is
  1915. // like "subst" except it only replaces whole words.
  1916. ////////////////////////////////////////////////////////////////////
  1917. string PPScope::
  1918. expand_wordsubst(const string &params) {
  1919. // Split the string up into tokens based on the commas.
  1920. vector<string> tokens;
  1921. tokenize_params(params, tokens, true);
  1922. if (tokens.size() < 3) {
  1923. cerr << "subst requires at least three parameters.\n";
  1924. return string();
  1925. }
  1926. if ((tokens.size() % 2) != 1) {
  1927. cerr << "subst requires an odd number of parameters.\n";
  1928. return string();
  1929. }
  1930. // Split the last parameter into tokens based on the spaces.
  1931. vector<string> words;
  1932. tokenize_whitespace(tokens.back(), words);
  1933. for (size_t i = 0; i < tokens.size() - 1; i += 2) {
  1934. const string &subst = tokens[i];
  1935. const string &repl = tokens[i + 1];
  1936. vector<string>::iterator wi;
  1937. for (wi = words.begin(); wi != words.end(); ++wi) {
  1938. if ((*wi) == subst) {
  1939. (*wi) = repl;
  1940. }
  1941. }
  1942. }
  1943. string result = repaste(words, " ");
  1944. return result;
  1945. }
  1946. ////////////////////////////////////////////////////////////////////
  1947. // Function: PPScope::expand_sort
  1948. // Access: Private
  1949. // Description: Expands the "sort" function variable: sort the words
  1950. // into alphabetical order, and also remove duplicates.
  1951. ////////////////////////////////////////////////////////////////////
  1952. string PPScope::
  1953. expand_sort(const string &params) {
  1954. // Split the string up into tokens based on the spaces.
  1955. vector<string> words;
  1956. tokenize_whitespace(expand_string(params), words);
  1957. sort(words.begin(), words.end());
  1958. words.erase(unique(words.begin(), words.end()), words.end());
  1959. string result = repaste(words, " ");
  1960. return result;
  1961. }
  1962. ////////////////////////////////////////////////////////////////////
  1963. // Function: PPScope::expand_unique
  1964. // Access: Private
  1965. // Description: Expands the "unique" function variable: remove
  1966. // duplicates from the list of words without changing
  1967. // the order. The first appearance of each word
  1968. // remains.
  1969. ////////////////////////////////////////////////////////////////////
  1970. string PPScope::
  1971. expand_unique(const string &params) {
  1972. // Split the string up into tokens based on the spaces.
  1973. vector<string> words;
  1974. tokenize_whitespace(expand_string(params), words);
  1975. vector<string>::iterator win, wout;
  1976. set<string> included_words;
  1977. win = words.begin();
  1978. wout = words.begin();
  1979. while (win != words.end()) {
  1980. if (included_words.insert(*win).second) {
  1981. // This is a unique word so far.
  1982. *wout++ = *win;
  1983. }
  1984. ++win;
  1985. }
  1986. words.erase(wout, words.end());
  1987. string result = repaste(words, " ");
  1988. return result;
  1989. }
  1990. ////////////////////////////////////////////////////////////////////
  1991. // Function: PPScope::expand_matrix
  1992. // Access: Private
  1993. // Description: Expands the "matrix" function variable. This
  1994. // combines the different words of the n parameters in
  1995. // all possible ways, like the shell {a,b,c} expansion
  1996. // characters. For example, $[matrix a b,c,10 20 30]
  1997. // expands to ac10 ac20 ac30 bc10 bc20 bc30.
  1998. ////////////////////////////////////////////////////////////////////
  1999. string PPScope::
  2000. expand_matrix(const string &params) {
  2001. // Split the string up into tokens based on the commas.
  2002. vector<string> tokens;
  2003. tokenize_params(params, tokens, true);
  2004. // Each token gets split up into words based on the spaces.
  2005. vector<vector<string> > words;
  2006. for (int i = 0; i < (int)tokens.size(); i++) {
  2007. words.push_back(vector<string>());
  2008. tokenize_whitespace(tokens[i], words.back());
  2009. }
  2010. // Now synthesize the results recursively.
  2011. vector<string> results;
  2012. r_expand_matrix(results, words, 0, "");
  2013. string result = repaste(results, " ");
  2014. return result;
  2015. }
  2016. ////////////////////////////////////////////////////////////////////
  2017. // Function: PPScope::expand_if
  2018. // Access: Private
  2019. // Description: Expands the "if" function variable. This evaluates
  2020. // the first parameter and returns the second parameter
  2021. // if the result is true (i.e. nonempty) and the third
  2022. // parameter (if present) if the result is false
  2023. // (i.e. empty).
  2024. ////////////////////////////////////////////////////////////////////
  2025. string PPScope::
  2026. expand_if(const string &params) {
  2027. // Split the string up into tokens based on the commas.
  2028. vector<string> tokens;
  2029. tokenize_params(params, tokens, true);
  2030. if (tokens.size() == 2) {
  2031. if (!tokens[0].empty()) {
  2032. return tokens[1];
  2033. } else {
  2034. return "";
  2035. }
  2036. } else if (tokens.size() == 3) {
  2037. if (!tokens[0].empty()) {
  2038. return tokens[1];
  2039. } else {
  2040. return tokens[2];
  2041. }
  2042. }
  2043. cerr << "if requires two or three parameters.\n";
  2044. return string();
  2045. }
  2046. ////////////////////////////////////////////////////////////////////
  2047. // Function: PPScope::expand_eq
  2048. // Access: Private
  2049. // Description: Expands the "eq" function variable. This tests
  2050. // string equivalence.
  2051. ////////////////////////////////////////////////////////////////////
  2052. string PPScope::
  2053. expand_eq(const string &params) {
  2054. // Split the string up into tokens based on the commas.
  2055. vector<string> tokens;
  2056. tokenize_params(params, tokens, true);
  2057. if (tokens.size() != 2) {
  2058. cerr << "eq requires two parameters.\n";
  2059. return string();
  2060. }
  2061. string result;
  2062. if (tokens[0] == tokens[1]) {
  2063. result = "1";
  2064. }
  2065. return result;
  2066. }
  2067. ////////////////////////////////////////////////////////////////////
  2068. // Function: PPScope::expand_ne
  2069. // Access: Private
  2070. // Description: Expands the "ne" function variable. This tests
  2071. // string equivalence.
  2072. ////////////////////////////////////////////////////////////////////
  2073. string PPScope::
  2074. expand_ne(const string &params) {
  2075. // Split the string up into tokens based on the commas.
  2076. vector<string> tokens;
  2077. tokenize_params(params, tokens, true);
  2078. if (tokens.size() != 2) {
  2079. cerr << "ne requires two parameters.\n";
  2080. return string();
  2081. }
  2082. string result;
  2083. if (!(tokens[0] == tokens[1])) {
  2084. result = "1";
  2085. }
  2086. return result;
  2087. }
  2088. ////////////////////////////////////////////////////////////////////
  2089. // Function: PPScope::expand_eqn
  2090. // Access: Private
  2091. // Description: Expands the "=" function variable. This tests
  2092. // numeric equivalence.
  2093. ////////////////////////////////////////////////////////////////////
  2094. string PPScope::
  2095. expand_eqn(const string &params) {
  2096. double a, b;
  2097. if (!tokenize_numeric_pair(params, a, b)) {
  2098. return string();
  2099. }
  2100. string result;
  2101. if (a == b) {
  2102. result = "1";
  2103. }
  2104. return result;
  2105. }
  2106. ////////////////////////////////////////////////////////////////////
  2107. // Function: PPScope::expand_nen
  2108. // Access: Private
  2109. // Description: Expands the "!=" function variable. This tests
  2110. // numeric equivalence.
  2111. ////////////////////////////////////////////////////////////////////
  2112. string PPScope::
  2113. expand_nen(const string &params) {
  2114. double a, b;
  2115. if (!tokenize_numeric_pair(params, a, b)) {
  2116. return string();
  2117. }
  2118. string result;
  2119. if (a != b) {
  2120. result = "1";
  2121. }
  2122. return result;
  2123. }
  2124. ////////////////////////////////////////////////////////////////////
  2125. // Function: PPScope::expand_ltn
  2126. // Access: Private
  2127. // Description: Expands the "<" function variable. This tests
  2128. // numeric relationships.
  2129. ////////////////////////////////////////////////////////////////////
  2130. string PPScope::
  2131. expand_ltn(const string &params) {
  2132. double a, b;
  2133. if (!tokenize_numeric_pair(params, a, b)) {
  2134. return string();
  2135. }
  2136. string result;
  2137. if (a < b) {
  2138. result = "1";
  2139. }
  2140. return result;
  2141. }
  2142. ////////////////////////////////////////////////////////////////////
  2143. // Function: PPScope::expand_len
  2144. // Access: Private
  2145. // Description: Expands the "<=" function variable. This tests
  2146. // numeric relationships.
  2147. ////////////////////////////////////////////////////////////////////
  2148. string PPScope::
  2149. expand_len(const string &params) {
  2150. double a, b;
  2151. if (!tokenize_numeric_pair(params, a, b)) {
  2152. return string();
  2153. }
  2154. string result;
  2155. if (a <= b) {
  2156. result = "1";
  2157. }
  2158. return result;
  2159. }
  2160. ////////////////////////////////////////////////////////////////////
  2161. // Function: PPScope::expand_gtn
  2162. // Access: Private
  2163. // Description: Expands the ">" function variable. This tests
  2164. // numeric relationships.
  2165. ////////////////////////////////////////////////////////////////////
  2166. string PPScope::
  2167. expand_gtn(const string &params) {
  2168. double a, b;
  2169. if (!tokenize_numeric_pair(params, a, b)) {
  2170. return string();
  2171. }
  2172. string result;
  2173. if (a > b) {
  2174. result = "1";
  2175. }
  2176. return result;
  2177. }
  2178. ////////////////////////////////////////////////////////////////////
  2179. // Function: PPScope::expand_gen
  2180. // Access: Private
  2181. // Description: Expands the ">=" function variable. This tests
  2182. // numeric relationships.
  2183. ////////////////////////////////////////////////////////////////////
  2184. string PPScope::
  2185. expand_gen(const string &params) {
  2186. double a, b;
  2187. if (!tokenize_numeric_pair(params, a, b)) {
  2188. return string();
  2189. }
  2190. string result;
  2191. if (a >= b) {
  2192. result = "1";
  2193. }
  2194. return result;
  2195. }
  2196. ////////////////////////////////////////////////////////////////////
  2197. // Function: PPScope::expand_not
  2198. // Access: Private
  2199. // Description: Expands the "not" function variable. This returns
  2200. // nonempty if its argument is empty, empty if its
  2201. // argument is nonempty.
  2202. ////////////////////////////////////////////////////////////////////
  2203. string PPScope::
  2204. expand_not(const string &params) {
  2205. // Split the string up into tokens based on the commas.
  2206. vector<string> tokens;
  2207. tokenize_params(params, tokens, true);
  2208. if (tokens.size() != 1) {
  2209. cerr << "not requires one parameter.\n";
  2210. return string();
  2211. }
  2212. string result;
  2213. if (tokens[0].empty()) {
  2214. result = "1";
  2215. }
  2216. return result;
  2217. }
  2218. ////////////////////////////////////////////////////////////////////
  2219. // Function: PPScope::expand_or
  2220. // Access: Private
  2221. // Description: Expands the "or" function variable. This returns
  2222. // nonempty if any of its arguments are nonempty.
  2223. // Specifically, it returns the first nonempty argument.
  2224. ////////////////////////////////////////////////////////////////////
  2225. string PPScope::
  2226. expand_or(const string &params) {
  2227. // Split the string up into tokens based on the commas.
  2228. vector<string> tokens;
  2229. tokenize_params(params, tokens, true);
  2230. vector<string>::const_iterator ti;
  2231. for (ti = tokens.begin(); ti != tokens.end(); ++ti) {
  2232. if (!(*ti).empty()) {
  2233. return (*ti);
  2234. }
  2235. }
  2236. return string();
  2237. }
  2238. ////////////////////////////////////////////////////////////////////
  2239. // Function: PPScope::expand_and
  2240. // Access: Private
  2241. // Description: Expands the "and" function variable. This returns
  2242. // nonempty if all of its arguments are nonempty.
  2243. // Specifically, it returns the last argument.
  2244. ////////////////////////////////////////////////////////////////////
  2245. string PPScope::
  2246. expand_and(const string &params) {
  2247. // Split the string up into tokens based on the commas.
  2248. vector<string> tokens;
  2249. tokenize_params(params, tokens, true);
  2250. vector<string>::const_iterator ti;
  2251. for (ti = tokens.begin(); ti != tokens.end(); ++ti) {
  2252. if ((*ti).empty()) {
  2253. return string();
  2254. }
  2255. }
  2256. string result = "1";
  2257. if (!tokens.empty()) {
  2258. result = tokens.back();
  2259. }
  2260. return result;
  2261. }
  2262. ////////////////////////////////////////////////////////////////////
  2263. // Function: PPScope::expand_upcase
  2264. // Access: Private
  2265. // Description: Expands the "upcase" function variable.
  2266. ////////////////////////////////////////////////////////////////////
  2267. string PPScope::
  2268. expand_upcase(const string &params) {
  2269. string result = expand_string(params);
  2270. string::iterator si;
  2271. for (si = result.begin(); si != result.end(); ++si) {
  2272. (*si) = toupper(*si);
  2273. }
  2274. return result;
  2275. }
  2276. ////////////////////////////////////////////////////////////////////
  2277. // Function: PPScope::expand_downcase
  2278. // Access: Private
  2279. // Description: Expands the "downcase" function variable.
  2280. ////////////////////////////////////////////////////////////////////
  2281. string PPScope::
  2282. expand_downcase(const string &params) {
  2283. string result = expand_string(params);
  2284. string::iterator si;
  2285. for (si = result.begin(); si != result.end(); ++si) {
  2286. (*si) = tolower(*si);
  2287. }
  2288. return result;
  2289. }
  2290. ////////////////////////////////////////////////////////////////////
  2291. // Function: PPScope::expand_cdefine
  2292. // Access: Private
  2293. // Description: Expands the "cdefine" function variable. This is a
  2294. // convenience function to output a C-style #define or
  2295. // #undef statement based on the value of the named
  2296. // variable. If the named string is a variable whose
  2297. // definition is nonempty, this returns "#define varname
  2298. // definition". Otherwise, it returns "#undef varname".
  2299. // This is particularly useful for building up a
  2300. // config.h file.
  2301. ////////////////////////////////////////////////////////////////////
  2302. string PPScope::
  2303. expand_cdefine(const string &params) {
  2304. string varname = trim_blanks(params);
  2305. string expansion = trim_blanks(expand_variable(varname));
  2306. string result;
  2307. if (expansion.empty()) {
  2308. result = "#undef " + varname;
  2309. } else {
  2310. result = "#define " + varname + " " + expansion;
  2311. }
  2312. return result;
  2313. }
  2314. ////////////////////////////////////////////////////////////////////
  2315. // Function: PPScope::expand_closure
  2316. // Access: Private
  2317. // Description: Expands the "closure" function variable. This is a
  2318. // special function that recursively expands a map
  2319. // variable with the given parameter string until all
  2320. // definitions have been encountered.
  2321. ////////////////////////////////////////////////////////////////////
  2322. string PPScope::
  2323. expand_closure(const string &params) {
  2324. // Split the string up into tokens based on the commas.
  2325. vector<string> tokens;
  2326. tokenize_params(params, tokens, false);
  2327. if (tokens.size() != 2 && tokens.size() != 3) {
  2328. cerr << "closure requires two or three parameters.\n";
  2329. return string();
  2330. }
  2331. // The first parameter is the map variable name, the second
  2332. // parameter is the expression to evaluate, and the third parameter
  2333. // (if present) is the expression that leads to the recursive
  2334. // evaluation of the map variable.
  2335. string varname = expand_string(tokens[0]);
  2336. string expression = tokens[1];
  2337. string close_on = expression;
  2338. if (tokens.size() > 2) {
  2339. close_on = tokens[2];
  2340. }
  2341. const MapVariableDefinition &def = find_map_variable(varname);
  2342. if (&def == &_null_map_def) {
  2343. cerr << "Warning: undefined map variable: " << varname << "\n";
  2344. return string();
  2345. }
  2346. // Now evaluate the expression within this scope, and then again
  2347. // within each scope indicated by the result, and then within each
  2348. // scope indicated by *that* result, and so on. We need to keep
  2349. // track of the words we have already evaluated (hence the set), and
  2350. // we also need to keep track of all the partial results we have yet
  2351. // to evaluate (hence the vector of strings).
  2352. set<string> closure;
  2353. vector<string> results;
  2354. vector<string> next_pass;
  2355. // Start off with the expression evaluated within the starting
  2356. // scope.
  2357. results.push_back(expand_string(expression));
  2358. next_pass.push_back(expand_string(close_on));
  2359. while (!next_pass.empty()) {
  2360. // Pull off one of the partial results (it doesn't matter which
  2361. // one), and chop it up into its constituent words.
  2362. vector<string> pass;
  2363. tokenize_whitespace(next_pass.back(), pass);
  2364. next_pass.pop_back();
  2365. // And then map each of those words into scopes.
  2366. vector<string>::const_iterator wi;
  2367. for (wi = pass.begin(); wi != pass.end(); ++wi) {
  2368. const string &word = (*wi);
  2369. bool inserted = closure.insert(word).second;
  2370. if (inserted) {
  2371. // This is a new word, which presumably maps to a scope.
  2372. MapVariableDefinition::const_iterator di;
  2373. di = def.find(word);
  2374. if (di != def.end()) {
  2375. PPScope *scope = (*di).second;
  2376. // Evaluate the expression within this scope.
  2377. results.push_back(scope->expand_string(expression));
  2378. // What does close_on evaluate to within this scope? That
  2379. // points us to the next scope(s).
  2380. next_pass.push_back(scope->expand_string(close_on));
  2381. }
  2382. }
  2383. }
  2384. }
  2385. // Now we have the complete transitive closure of $[mapvar close_on].
  2386. string result = repaste(results, " ");
  2387. return result;
  2388. }
  2389. ////////////////////////////////////////////////////////////////////
  2390. // Function: PPScope::expand_unmapped
  2391. // Access: Private
  2392. // Description: Expands the "closure" function variable. This is a
  2393. // special function that returns all the arguments to a
  2394. // map variable, unchanged, that did *not* match any of
  2395. // the keys in the map.
  2396. ////////////////////////////////////////////////////////////////////
  2397. string PPScope::
  2398. expand_unmapped(const string &params) {
  2399. // Split the string up into tokens based on the commas.
  2400. vector<string> tokens;
  2401. tokenize_params(params, tokens, false);
  2402. if (tokens.size() != 2) {
  2403. cerr << "unmapped requires two parameters.\n";
  2404. return string();
  2405. }
  2406. // The first parameter is the map variable name, and the second
  2407. // parameter is the space-separated list of arguments to the map.
  2408. string varname = expand_string(tokens[0]);
  2409. vector<string> keys;
  2410. tokenize_whitespace(expand_string(tokens[1]), keys);
  2411. const MapVariableDefinition &def = find_map_variable(varname);
  2412. if (&def == &_null_map_def) {
  2413. cerr << "Warning: undefined map variable: " << varname << "\n";
  2414. return string();
  2415. }
  2416. vector<string> results;
  2417. vector<string>::const_iterator ki;
  2418. for (ki = keys.begin(); ki != keys.end(); ++ki) {
  2419. MapVariableDefinition::const_iterator di;
  2420. di = def.find(*ki);
  2421. if (di == def.end()) {
  2422. // This key was undefined.
  2423. results.push_back(*ki);
  2424. }
  2425. }
  2426. string result = repaste(results, " ");
  2427. return result;
  2428. }
  2429. ////////////////////////////////////////////////////////////////////
  2430. // Function: PPScope::expand_dependencies
  2431. // Access: Private
  2432. // Description: Expands the "dependencies" function variable. This
  2433. // function returns all of the inter-file dependencies
  2434. // that the named file(s) depend on, as defined by the
  2435. // #include directives appearing within the files.
  2436. ////////////////////////////////////////////////////////////////////
  2437. string PPScope::
  2438. expand_dependencies(const string &params) {
  2439. // Split the string up into filenames based on whitespace.
  2440. vector<string> filenames;
  2441. tokenize_whitespace(expand_string(params), filenames);
  2442. PPDirectory *directory = get_directory();
  2443. assert(directory != (PPDirectory *)NULL);
  2444. vector<string> results;
  2445. vector<string>::const_iterator fi;
  2446. for (fi = filenames.begin(); fi != filenames.end(); ++fi) {
  2447. PPDependableFile *file = directory->get_dependable_file(*fi, false);
  2448. assert(file != (PPDependableFile *)NULL);
  2449. vector<PPDependableFile *> files;
  2450. file->get_complete_dependencies(files);
  2451. vector<PPDependableFile *>::const_iterator dfi;
  2452. for (dfi = files.begin(); dfi != files.end(); ++dfi) {
  2453. PPDependableFile *df = (*dfi);
  2454. string rel_filename =
  2455. current_output_directory->get_rel_to(df->get_directory()) + "/" +
  2456. df->get_filename();
  2457. results.push_back(rel_filename);
  2458. }
  2459. }
  2460. sort(results.begin(), results.end());
  2461. results.erase(unique(results.begin(), results.end()), results.end());
  2462. string result = repaste(results, " ");
  2463. return result;
  2464. }
  2465. ////////////////////////////////////////////////////////////////////
  2466. // Function: PPScope::expand_foreach
  2467. // Access: Private
  2468. // Description: Expands the "foreach" function variable. This
  2469. // evaluates an expression once for each word of a list.
  2470. ////////////////////////////////////////////////////////////////////
  2471. string PPScope::
  2472. expand_foreach(const string &params) {
  2473. // Split the string up into tokens based on the commas.
  2474. vector<string> tokens;
  2475. tokenize_params(params, tokens, false);
  2476. if (tokens.size() != 3) {
  2477. cerr << "foreach requires three parameters.\n";
  2478. return string();
  2479. }
  2480. // The first parameter is the temporary variable name that holds
  2481. // each word as it is expanded; the second parameter is the
  2482. // space-separated list of words. The third parameter is the
  2483. // expression to evaluate.
  2484. string varname = trim_blanks(expand_string(tokens[0]));
  2485. vector<string> words;
  2486. tokenize_whitespace(expand_string(tokens[1]), words);
  2487. vector<string> results;
  2488. vector<string>::const_iterator wi;
  2489. for (wi = words.begin(); wi != words.end(); ++wi) {
  2490. define_variable(varname, *wi);
  2491. results.push_back(expand_string(tokens[2]));
  2492. }
  2493. string result = repaste(results, " ");
  2494. return result;
  2495. }
  2496. ////////////////////////////////////////////////////////////////////
  2497. // Function: PPScope::expand_forscopes
  2498. // Access: Private
  2499. // Description: Expands the "forscopes" function variable. This
  2500. // evaluates an expression once within each of a number
  2501. // of named nested scopes.
  2502. ////////////////////////////////////////////////////////////////////
  2503. string PPScope::
  2504. expand_forscopes(const string &params) {
  2505. // Split the string up into tokens based on the commas.
  2506. vector<string> tokens;
  2507. tokenize_params(params, tokens, false);
  2508. if (tokens.size() != 2) {
  2509. cerr << "forscopes requires two parameters.\n";
  2510. return string();
  2511. }
  2512. // The first parameter is the space-separated list of nested scope
  2513. // names. The second parameter is the expression to evaluate.
  2514. vector<string> scope_names;
  2515. tokenize_whitespace(expand_string(tokens[0]), scope_names);
  2516. if (_named_scopes == (PPNamedScopes *)NULL) {
  2517. return string();
  2518. }
  2519. // Now build up the list of scopes with these names.
  2520. PPNamedScopes::Scopes scopes;
  2521. vector<string>::const_iterator wi;
  2522. for (wi = scope_names.begin(); wi != scope_names.end(); ++wi) {
  2523. _named_scopes->get_scopes(*wi, scopes);
  2524. }
  2525. PPNamedScopes::sort_by_dependency(scopes);
  2526. // Now evaluate the expression within each scope.
  2527. vector<string> results;
  2528. PPNamedScopes::Scopes::const_iterator si;
  2529. for (si = scopes.begin(); si != scopes.end(); ++si) {
  2530. PPScope *scope = *si;
  2531. results.push_back(scope->expand_string(tokens[1]));
  2532. }
  2533. string result = repaste(results, " ");
  2534. return result;
  2535. }
  2536. ////////////////////////////////////////////////////////////////////
  2537. // Function: PPScope::expand_function
  2538. // Access: Private
  2539. // Description: Expands the user-defined function reference. This
  2540. // invokes the nested commands within the function body,
  2541. // and returns all the output text as one line. Quite a
  2542. // job, really.
  2543. ////////////////////////////////////////////////////////////////////
  2544. string PPScope::
  2545. expand_function(const string &funcname,
  2546. const PPSubroutine *sub, const string &params) {
  2547. PPScope::push_scope((PPScope *)this);
  2548. PPScope nested_scope(_named_scopes);
  2549. nested_scope.define_formals(funcname, sub->_formals, params);
  2550. // This won't compile on VC++. It has only ostringstream, which is
  2551. // functionally equivalent but has a slightly different interface.
  2552. ostrstream ostr;
  2553. PPCommandFile command(&nested_scope);
  2554. command.set_output(&ostr);
  2555. command.begin_read();
  2556. bool okflag = true;
  2557. vector<string>::const_iterator li;
  2558. for (li = sub->_lines.begin(); li != sub->_lines.end() && okflag; ++li) {
  2559. okflag = command.read_line(*li);
  2560. }
  2561. if (okflag) {
  2562. okflag = command.end_read();
  2563. }
  2564. // We don't do anything with okflag here. What can we do?
  2565. PPScope::pop_scope();
  2566. // Now get the output. We split it into words and then reconnect
  2567. // it, to replace all whitespace with spaces.
  2568. ostr << ends;
  2569. char *str = ostr.str();
  2570. vector<string> results;
  2571. tokenize_whitespace(str, results);
  2572. string result = repaste(results, " ");
  2573. delete[] str;
  2574. return result;
  2575. }
  2576. ////////////////////////////////////////////////////////////////////
  2577. // Function: PPScope::expand_map_variable
  2578. // Access: Private
  2579. // Description: Expands a map variable function reference. This
  2580. // looks up the given keys in the map and expands the
  2581. // first parameter for each corresponding scope.
  2582. ////////////////////////////////////////////////////////////////////
  2583. string PPScope::
  2584. expand_map_variable(const string &varname, const string &params) {
  2585. // Split the string up into tokens based on the commas, but don't
  2586. // expand the variables yet.
  2587. vector<string> tokens;
  2588. tokenize_params(params, tokens, false);
  2589. if (tokens.size() != 2) {
  2590. cerr << "map variable expansions require two parameters: $["
  2591. << varname << " " << params << "]\n";
  2592. return string();
  2593. }
  2594. // Split the second parameter into tokens based on the spaces. This
  2595. // is the set of keys.
  2596. vector<string> keys;
  2597. tokenize_whitespace(expand_string(tokens[1]), keys);
  2598. return expand_map_variable(varname, tokens[0], keys);
  2599. }
  2600. ////////////////////////////////////////////////////////////////////
  2601. // Function: PPScope::expand_map_variable
  2602. // Access: Private
  2603. // Description: Expands a map variable function reference. This
  2604. // looks up the given keys in the map and expands the
  2605. // expression for each corresponding scope.
  2606. ////////////////////////////////////////////////////////////////////
  2607. string PPScope::
  2608. expand_map_variable(const string &varname, const string &expression,
  2609. const vector<string> &keys) {
  2610. const MapVariableDefinition &def = find_map_variable(varname);
  2611. if (&def == &_null_map_def) {
  2612. cerr << "Warning: undefined map variable: " << varname << "\n";
  2613. return string();
  2614. }
  2615. vector<string> results;
  2616. // Now build up the set of expansions of the expression in the
  2617. // various scopes indicated by the keys.
  2618. vector<string>::const_iterator wi;
  2619. for (wi = keys.begin(); wi != keys.end(); ++wi) {
  2620. MapVariableDefinition::const_iterator di;
  2621. di = def.find(*wi);
  2622. if (di != def.end()) {
  2623. PPScope *scope = (*di).second;
  2624. string expansion = scope->expand_string(expression);
  2625. if (!expansion.empty()) {
  2626. results.push_back(expansion);
  2627. }
  2628. }
  2629. }
  2630. string result = repaste(results, " ");
  2631. return result;
  2632. }
  2633. ////////////////////////////////////////////////////////////////////
  2634. // Function: PPScope::r_expand_matrix
  2635. // Access: Private
  2636. // Description: The recursive implementation of expand_matrix().
  2637. // This generates all of the combinations from the
  2638. // indicated index into the words array, with the given
  2639. // prefix.
  2640. ////////////////////////////////////////////////////////////////////
  2641. void PPScope::
  2642. r_expand_matrix(vector<string> &results, const vector<vector<string> > &words,
  2643. int index, const string &prefix) {
  2644. if (index >= (int)words.size()) {
  2645. // This is the terminal condition.
  2646. results.push_back(prefix);
  2647. } else {
  2648. // Otherwise, tack on the next set of words, and recurse.
  2649. const vector<string> &w = words[index];
  2650. vector<string>::const_iterator wi;
  2651. for (wi = w.begin(); wi != w.end(); ++wi) {
  2652. r_expand_matrix(results, words, index + 1, prefix + (*wi));
  2653. }
  2654. }
  2655. }
  2656. ////////////////////////////////////////////////////////////////////
  2657. // Function: PPScope::p_find_map_variable
  2658. // Access: Private
  2659. // Description: The implementation of find_map_variable() for a
  2660. // particular static scope, without checking the stack.
  2661. ////////////////////////////////////////////////////////////////////
  2662. PPScope::MapVariableDefinition &PPScope::
  2663. p_find_map_variable(const string &varname) {
  2664. MapVariables::const_iterator mvi;
  2665. mvi = _map_variables.find(varname);
  2666. if (mvi != _map_variables.end()) {
  2667. return (MapVariableDefinition &)(*mvi).second;
  2668. }
  2669. if (_parent_scope != (PPScope *)NULL) {
  2670. return _parent_scope->p_find_map_variable(varname);
  2671. }
  2672. return _null_map_def;
  2673. }
  2674. ////////////////////////////////////////////////////////////////////
  2675. // Function: PPScope::glob_string
  2676. // Access: Private
  2677. // Description: Expands the words in the string as if they were a set
  2678. // of filenames using the shell globbing characters.
  2679. // Fills up the results vector (which the user should
  2680. // ensure is empty before calling) with the set of all
  2681. // files that actually match the globbing characters.
  2682. ////////////////////////////////////////////////////////////////////
  2683. void PPScope::
  2684. glob_string(const string &str, vector<string> &results) {
  2685. // We run glob_string() within the directory indicated by
  2686. // $[THISDIRPREFIX]. This way, local filenames will be expanded the
  2687. // way we expect.
  2688. string dirname = trim_blanks(expand_variable("THISDIRPREFIX"));
  2689. bool changed_dir = false;
  2690. if (!dirname.empty()) {
  2691. if (chdir(dirname.c_str()) < 0) {
  2692. perror("chdir");
  2693. } else {
  2694. changed_dir = true;
  2695. }
  2696. }
  2697. vector<string> words;
  2698. tokenize_whitespace(str, words);
  2699. vector<string>::const_iterator wi;
  2700. glob_t pglob;
  2701. memset(&pglob, 0, sizeof(pglob));
  2702. int flags = 0;
  2703. for (wi = words.begin(); wi != words.end(); ++wi) {
  2704. glob((*wi).c_str(), flags, NULL, &pglob);
  2705. flags |= GLOB_APPEND;
  2706. }
  2707. for (int i = 0; i < (int)pglob.gl_pathc; i++) {
  2708. results.push_back(string(pglob.gl_pathv[i]));
  2709. }
  2710. globfree(&pglob);
  2711. // Sort the results into alphabetical order.
  2712. sort(results.begin(), results.end());
  2713. if (changed_dir) {
  2714. // Now restore the current directory back to where it should be.
  2715. PPMain::chdir_root();
  2716. }
  2717. }