ppScope.cxx 104 KB

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