ppScope.cxx 107 KB

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