ppScope.cxx 110 KB

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