PageRenderTime 26ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/commands/make/var.c

http://github.com/vivekp/minix-nbsd
C | 4032 lines | 2402 code | 275 blank | 1355 comment | 914 complexity | 5f97aa9cba085dd1cec3ef59b48a2dc7 MD5 | raw file
Possible License(s): AGPL-1.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /* $NetBSD: var.c,v 1.159 2010/06/06 01:13:12 sjg Exp $ */
  2. /*
  3. * Copyright (c) 1988, 1989, 1990, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * Adam de Boor.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. /*
  34. * Copyright (c) 1989 by Berkeley Softworks
  35. * All rights reserved.
  36. *
  37. * This code is derived from software contributed to Berkeley by
  38. * Adam de Boor.
  39. *
  40. * Redistribution and use in source and binary forms, with or without
  41. * modification, are permitted provided that the following conditions
  42. * are met:
  43. * 1. Redistributions of source code must retain the above copyright
  44. * notice, this list of conditions and the following disclaimer.
  45. * 2. Redistributions in binary form must reproduce the above copyright
  46. * notice, this list of conditions and the following disclaimer in the
  47. * documentation and/or other materials provided with the distribution.
  48. * 3. All advertising materials mentioning features or use of this software
  49. * must display the following acknowledgement:
  50. * This product includes software developed by the University of
  51. * California, Berkeley and its contributors.
  52. * 4. Neither the name of the University nor the names of its contributors
  53. * may be used to endorse or promote products derived from this software
  54. * without specific prior written permission.
  55. *
  56. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  57. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  58. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  59. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  60. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  61. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  62. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  63. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  64. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  65. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  66. * SUCH DAMAGE.
  67. */
  68. #ifndef MAKE_NATIVE
  69. static char rcsid[] = "$NetBSD: var.c,v 1.159 2010/06/06 01:13:12 sjg Exp $";
  70. #else
  71. #include <sys/cdefs.h>
  72. #ifndef lint
  73. #if 0
  74. static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
  75. #else
  76. __RCSID("$NetBSD: var.c,v 1.159 2010/06/06 01:13:12 sjg Exp $");
  77. #endif
  78. #endif /* not lint */
  79. #endif
  80. /*-
  81. * var.c --
  82. * Variable-handling functions
  83. *
  84. * Interface:
  85. * Var_Set Set the value of a variable in the given
  86. * context. The variable is created if it doesn't
  87. * yet exist. The value and variable name need not
  88. * be preserved.
  89. *
  90. * Var_Append Append more characters to an existing variable
  91. * in the given context. The variable needn't
  92. * exist already -- it will be created if it doesn't.
  93. * A space is placed between the old value and the
  94. * new one.
  95. *
  96. * Var_Exists See if a variable exists.
  97. *
  98. * Var_Value Return the value of a variable in a context or
  99. * NULL if the variable is undefined.
  100. *
  101. * Var_Subst Substitute named variable, or all variables if
  102. * NULL in a string using
  103. * the given context as the top-most one. If the
  104. * third argument is non-zero, Parse_Error is
  105. * called if any variables are undefined.
  106. *
  107. * Var_Parse Parse a variable expansion from a string and
  108. * return the result and the number of characters
  109. * consumed.
  110. *
  111. * Var_Delete Delete a variable in a context.
  112. *
  113. * Var_Init Initialize this module.
  114. *
  115. * Debugging:
  116. * Var_Dump Print out all variables defined in the given
  117. * context.
  118. *
  119. * XXX: There's a lot of duplication in these functions.
  120. */
  121. #include <sys/stat.h>
  122. #ifndef NO_REGEX
  123. #include <sys/types.h>
  124. #include <regex.h>
  125. #endif
  126. #include <ctype.h>
  127. #include <stdlib.h>
  128. #include <limits.h>
  129. #include "make.h"
  130. #include "buf.h"
  131. #include "dir.h"
  132. #include "job.h"
  133. /*
  134. * This is a harmless return value for Var_Parse that can be used by Var_Subst
  135. * to determine if there was an error in parsing -- easier than returning
  136. * a flag, as things outside this module don't give a hoot.
  137. */
  138. char var_Error[] = "";
  139. /*
  140. * Similar to var_Error, but returned when the 'errnum' flag for Var_Parse is
  141. * set false. Why not just use a constant? Well, gcc likes to condense
  142. * identical string instances...
  143. */
  144. static char varNoError[] = "";
  145. /*
  146. * Internally, variables are contained in four different contexts.
  147. * 1) the environment. They may not be changed. If an environment
  148. * variable is appended-to, the result is placed in the global
  149. * context.
  150. * 2) the global context. Variables set in the Makefile are located in
  151. * the global context. It is the penultimate context searched when
  152. * substituting.
  153. * 3) the command-line context. All variables set on the command line
  154. * are placed in this context. They are UNALTERABLE once placed here.
  155. * 4) the local context. Each target has associated with it a context
  156. * list. On this list are located the structures describing such
  157. * local variables as $(@) and $(*)
  158. * The four contexts are searched in the reverse order from which they are
  159. * listed.
  160. */
  161. GNode *VAR_GLOBAL; /* variables from the makefile */
  162. GNode *VAR_CMD; /* variables defined on the command-line */
  163. #define FIND_CMD 0x1 /* look in VAR_CMD when searching */
  164. #define FIND_GLOBAL 0x2 /* look in VAR_GLOBAL as well */
  165. #define FIND_ENV 0x4 /* look in the environment also */
  166. typedef struct Var {
  167. char *name; /* the variable's name */
  168. Buffer val; /* its value */
  169. int flags; /* miscellaneous status flags */
  170. #define VAR_IN_USE 1 /* Variable's value currently being used.
  171. * Used to avoid recursion */
  172. #define VAR_FROM_ENV 2 /* Variable comes from the environment */
  173. #define VAR_JUNK 4 /* Variable is a junk variable that
  174. * should be destroyed when done with
  175. * it. Used by Var_Parse for undefined,
  176. * modified variables */
  177. #define VAR_KEEP 8 /* Variable is VAR_JUNK, but we found
  178. * a use for it in some modifier and
  179. * the value is therefore valid */
  180. #define VAR_EXPORTED 16 /* Variable is exported */
  181. #define VAR_REEXPORT 32 /* Indicate if var needs re-export.
  182. * This would be true if it contains $'s
  183. */
  184. #define VAR_FROM_CMD 64 /* Variable came from command line */
  185. } Var;
  186. /*
  187. * Exporting vars is expensive so skip it if we can
  188. */
  189. #define VAR_EXPORTED_NONE 0
  190. #define VAR_EXPORTED_YES 1
  191. #define VAR_EXPORTED_ALL 2
  192. static int var_exportedVars = VAR_EXPORTED_NONE;
  193. /*
  194. * We pass this to Var_Export when doing the initial export
  195. * or after updating an exported var.
  196. */
  197. #define VAR_EXPORT_PARENT 1
  198. /* Var*Pattern flags */
  199. #define VAR_SUB_GLOBAL 0x01 /* Apply substitution globally */
  200. #define VAR_SUB_ONE 0x02 /* Apply substitution to one word */
  201. #define VAR_SUB_MATCHED 0x04 /* There was a match */
  202. #define VAR_MATCH_START 0x08 /* Match at start of word */
  203. #define VAR_MATCH_END 0x10 /* Match at end of word */
  204. #define VAR_NOSUBST 0x20 /* don't expand vars in VarGetPattern */
  205. /* Var_Set flags */
  206. #define VAR_NO_EXPORT 0x01 /* do not export */
  207. typedef struct {
  208. /*
  209. * The following fields are set by Var_Parse() when it
  210. * encounters modifiers that need to keep state for use by
  211. * subsequent modifiers within the same variable expansion.
  212. */
  213. Byte varSpace; /* Word separator in expansions */
  214. Boolean oneBigWord; /* TRUE if we will treat the variable as a
  215. * single big word, even if it contains
  216. * embedded spaces (as opposed to the
  217. * usual behaviour of treating it as
  218. * several space-separated words). */
  219. } Var_Parse_State;
  220. /* struct passed as 'void *' to VarSubstitute() for ":S/lhs/rhs/",
  221. * to VarSYSVMatch() for ":lhs=rhs". */
  222. typedef struct {
  223. const char *lhs; /* String to match */
  224. int leftLen; /* Length of string */
  225. const char *rhs; /* Replacement string (w/ &'s removed) */
  226. int rightLen; /* Length of replacement */
  227. int flags;
  228. } VarPattern;
  229. /* struct passed as 'void *' to VarLoopExpand() for ":@tvar@str@" */
  230. typedef struct {
  231. GNode *ctxt; /* variable context */
  232. char *tvar; /* name of temp var */
  233. int tvarLen;
  234. char *str; /* string to expand */
  235. int strLen;
  236. int errnum; /* errnum for not defined */
  237. } VarLoop_t;
  238. #ifndef NO_REGEX
  239. /* struct passed as 'void *' to VarRESubstitute() for ":C///" */
  240. typedef struct {
  241. regex_t re;
  242. int nsub;
  243. regmatch_t *matches;
  244. char *replace;
  245. int flags;
  246. } VarREPattern;
  247. #endif
  248. /* struct passed to VarSelectWords() for ":[start..end]" */
  249. typedef struct {
  250. int start; /* first word to select */
  251. int end; /* last word to select */
  252. } VarSelectWords_t;
  253. static Var *VarFind(const char *, GNode *, int);
  254. static void VarAdd(const char *, const char *, GNode *);
  255. static Boolean VarHead(GNode *, Var_Parse_State *,
  256. char *, Boolean, Buffer *, void *);
  257. static Boolean VarTail(GNode *, Var_Parse_State *,
  258. char *, Boolean, Buffer *, void *);
  259. static Boolean VarSuffix(GNode *, Var_Parse_State *,
  260. char *, Boolean, Buffer *, void *);
  261. static Boolean VarRoot(GNode *, Var_Parse_State *,
  262. char *, Boolean, Buffer *, void *);
  263. static Boolean VarMatch(GNode *, Var_Parse_State *,
  264. char *, Boolean, Buffer *, void *);
  265. #ifdef SYSVVARSUB
  266. static Boolean VarSYSVMatch(GNode *, Var_Parse_State *,
  267. char *, Boolean, Buffer *, void *);
  268. #endif
  269. static Boolean VarNoMatch(GNode *, Var_Parse_State *,
  270. char *, Boolean, Buffer *, void *);
  271. #ifndef NO_REGEX
  272. static void VarREError(int, regex_t *, const char *);
  273. static Boolean VarRESubstitute(GNode *, Var_Parse_State *,
  274. char *, Boolean, Buffer *, void *);
  275. #endif
  276. static Boolean VarSubstitute(GNode *, Var_Parse_State *,
  277. char *, Boolean, Buffer *, void *);
  278. static Boolean VarLoopExpand(GNode *, Var_Parse_State *,
  279. char *, Boolean, Buffer *, void *);
  280. static char *VarGetPattern(GNode *, Var_Parse_State *,
  281. int, const char **, int, int *, int *,
  282. VarPattern *);
  283. static char *VarQuote(char *);
  284. static char *VarChangeCase(char *, int);
  285. static char *VarModify(GNode *, Var_Parse_State *,
  286. const char *,
  287. Boolean (*)(GNode *, Var_Parse_State *, char *, Boolean, Buffer *, void *),
  288. void *);
  289. static char *VarOrder(const char *, const char);
  290. static char *VarUniq(const char *);
  291. static int VarWordCompare(const void *, const void *);
  292. static void VarPrintVar(void *);
  293. #define BROPEN '{'
  294. #define BRCLOSE '}'
  295. #define PROPEN '('
  296. #define PRCLOSE ')'
  297. /*-
  298. *-----------------------------------------------------------------------
  299. * VarFind --
  300. * Find the given variable in the given context and any other contexts
  301. * indicated.
  302. *
  303. * Input:
  304. * name name to find
  305. * ctxt context in which to find it
  306. * flags FIND_GLOBAL set means to look in the
  307. * VAR_GLOBAL context as well. FIND_CMD set means
  308. * to look in the VAR_CMD context also. FIND_ENV
  309. * set means to look in the environment
  310. *
  311. * Results:
  312. * A pointer to the structure describing the desired variable or
  313. * NULL if the variable does not exist.
  314. *
  315. * Side Effects:
  316. * None
  317. *-----------------------------------------------------------------------
  318. */
  319. static Var *
  320. VarFind(const char *name, GNode *ctxt, int flags)
  321. {
  322. Hash_Entry *var;
  323. Var *v;
  324. /*
  325. * If the variable name begins with a '.', it could very well be one of
  326. * the local ones. We check the name against all the local variables
  327. * and substitute the short version in for 'name' if it matches one of
  328. * them.
  329. */
  330. if (*name == '.' && isupper((unsigned char) name[1]))
  331. switch (name[1]) {
  332. case 'A':
  333. if (!strcmp(name, ".ALLSRC"))
  334. name = ALLSRC;
  335. if (!strcmp(name, ".ARCHIVE"))
  336. name = ARCHIVE;
  337. break;
  338. case 'I':
  339. if (!strcmp(name, ".IMPSRC"))
  340. name = IMPSRC;
  341. break;
  342. case 'M':
  343. if (!strcmp(name, ".MEMBER"))
  344. name = MEMBER;
  345. break;
  346. case 'O':
  347. if (!strcmp(name, ".OODATE"))
  348. name = OODATE;
  349. break;
  350. case 'P':
  351. if (!strcmp(name, ".PREFIX"))
  352. name = PREFIX;
  353. break;
  354. case 'T':
  355. if (!strcmp(name, ".TARGET"))
  356. name = TARGET;
  357. break;
  358. }
  359. /*
  360. * First look for the variable in the given context. If it's not there,
  361. * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order,
  362. * depending on the FIND_* flags in 'flags'
  363. */
  364. var = Hash_FindEntry(&ctxt->context, name);
  365. if ((var == NULL) && (flags & FIND_CMD) && (ctxt != VAR_CMD)) {
  366. var = Hash_FindEntry(&VAR_CMD->context, name);
  367. }
  368. if (!checkEnvFirst && (var == NULL) && (flags & FIND_GLOBAL) &&
  369. (ctxt != VAR_GLOBAL))
  370. {
  371. var = Hash_FindEntry(&VAR_GLOBAL->context, name);
  372. }
  373. if ((var == NULL) && (flags & FIND_ENV)) {
  374. char *env;
  375. if ((env = getenv(name)) != NULL) {
  376. int len;
  377. v = bmake_malloc(sizeof(Var));
  378. v->name = bmake_strdup(name);
  379. len = strlen(env);
  380. Buf_Init(&v->val, len + 1);
  381. Buf_AddBytes(&v->val, len, env);
  382. v->flags = VAR_FROM_ENV;
  383. return (v);
  384. } else if (checkEnvFirst && (flags & FIND_GLOBAL) &&
  385. (ctxt != VAR_GLOBAL))
  386. {
  387. var = Hash_FindEntry(&VAR_GLOBAL->context, name);
  388. if (var == NULL) {
  389. return NULL;
  390. } else {
  391. return ((Var *)Hash_GetValue(var));
  392. }
  393. } else {
  394. return NULL;
  395. }
  396. } else if (var == NULL) {
  397. return NULL;
  398. } else {
  399. return ((Var *)Hash_GetValue(var));
  400. }
  401. }
  402. /*-
  403. *-----------------------------------------------------------------------
  404. * VarFreeEnv --
  405. * If the variable is an environment variable, free it
  406. *
  407. * Input:
  408. * v the variable
  409. * destroy true if the value buffer should be destroyed.
  410. *
  411. * Results:
  412. * 1 if it is an environment variable 0 ow.
  413. *
  414. * Side Effects:
  415. * The variable is free'ed if it is an environent variable.
  416. *-----------------------------------------------------------------------
  417. */
  418. static Boolean
  419. VarFreeEnv(Var *v, Boolean destroy)
  420. {
  421. if ((v->flags & VAR_FROM_ENV) == 0)
  422. return FALSE;
  423. free(v->name);
  424. Buf_Destroy(&v->val, destroy);
  425. free(v);
  426. return TRUE;
  427. }
  428. /*-
  429. *-----------------------------------------------------------------------
  430. * VarAdd --
  431. * Add a new variable of name name and value val to the given context
  432. *
  433. * Input:
  434. * name name of variable to add
  435. * val value to set it to
  436. * ctxt context in which to set it
  437. *
  438. * Results:
  439. * None
  440. *
  441. * Side Effects:
  442. * The new variable is placed at the front of the given context
  443. * The name and val arguments are duplicated so they may
  444. * safely be freed.
  445. *-----------------------------------------------------------------------
  446. */
  447. static void
  448. VarAdd(const char *name, const char *val, GNode *ctxt)
  449. {
  450. Var *v;
  451. int len;
  452. Hash_Entry *h;
  453. v = bmake_malloc(sizeof(Var));
  454. len = val ? strlen(val) : 0;
  455. Buf_Init(&v->val, len+1);
  456. Buf_AddBytes(&v->val, len, val);
  457. v->flags = 0;
  458. h = Hash_CreateEntry(&ctxt->context, name, NULL);
  459. Hash_SetValue(h, v);
  460. v->name = h->name;
  461. if (DEBUG(VAR)) {
  462. fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val);
  463. }
  464. }
  465. /*-
  466. *-----------------------------------------------------------------------
  467. * Var_Delete --
  468. * Remove a variable from a context.
  469. *
  470. * Results:
  471. * None.
  472. *
  473. * Side Effects:
  474. * The Var structure is removed and freed.
  475. *
  476. *-----------------------------------------------------------------------
  477. */
  478. void
  479. Var_Delete(const char *name, GNode *ctxt)
  480. {
  481. Hash_Entry *ln;
  482. ln = Hash_FindEntry(&ctxt->context, name);
  483. if (DEBUG(VAR)) {
  484. fprintf(debug_file, "%s:delete %s%s\n",
  485. ctxt->name, name, ln ? "" : " (not found)");
  486. }
  487. if (ln != NULL) {
  488. Var *v;
  489. v = (Var *)Hash_GetValue(ln);
  490. if ((v->flags & VAR_EXPORTED)) {
  491. unsetenv(v->name);
  492. }
  493. if (strcmp(MAKE_EXPORTED, v->name) == 0) {
  494. var_exportedVars = VAR_EXPORTED_NONE;
  495. }
  496. if (v->name != ln->name)
  497. free(v->name);
  498. Hash_DeleteEntry(&ctxt->context, ln);
  499. Buf_Destroy(&v->val, TRUE);
  500. free(v);
  501. }
  502. }
  503. /*
  504. * Export a var.
  505. * We ignore make internal variables (those which start with '.')
  506. * Also we jump through some hoops to avoid calling setenv
  507. * more than necessary since it can leak.
  508. * We only manipulate flags of vars if 'parent' is set.
  509. */
  510. static int
  511. Var_Export1(const char *name, int parent)
  512. {
  513. char tmp[BUFSIZ];
  514. Var *v;
  515. char *val = NULL;
  516. int n;
  517. if (*name == '.')
  518. return 0; /* skip internals */
  519. if (!name[1]) {
  520. /*
  521. * A single char.
  522. * If it is one of the vars that should only appear in
  523. * local context, skip it, else we can get Var_Subst
  524. * into a loop.
  525. */
  526. switch (name[0]) {
  527. case '@':
  528. case '%':
  529. case '*':
  530. case '!':
  531. return 0;
  532. }
  533. }
  534. v = VarFind(name, VAR_GLOBAL, 0);
  535. if (v == NULL) {
  536. return 0;
  537. }
  538. if (!parent &&
  539. (v->flags & (VAR_EXPORTED|VAR_REEXPORT)) == VAR_EXPORTED) {
  540. return 0; /* nothing to do */
  541. }
  542. val = Buf_GetAll(&v->val, NULL);
  543. if (strchr(val, '$')) {
  544. if (parent) {
  545. /*
  546. * Flag this as something we need to re-export.
  547. * No point actually exporting it now though,
  548. * the child can do it at the last minute.
  549. */
  550. v->flags |= (VAR_EXPORTED|VAR_REEXPORT);
  551. return 1;
  552. }
  553. if (v->flags & VAR_IN_USE) {
  554. /*
  555. * We recursed while exporting in a child.
  556. * This isn't going to end well, just skip it.
  557. */
  558. return 0;
  559. }
  560. n = snprintf(tmp, sizeof(tmp), "${%s}", name);
  561. if (n < (int)sizeof(tmp)) {
  562. val = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
  563. setenv(name, val, 1);
  564. free(val);
  565. }
  566. } else {
  567. if (parent) {
  568. v->flags &= ~VAR_REEXPORT; /* once will do */
  569. }
  570. if (parent || !(v->flags & VAR_EXPORTED)) {
  571. setenv(name, val, 1);
  572. }
  573. }
  574. /*
  575. * This is so Var_Set knows to call Var_Export again...
  576. */
  577. if (parent) {
  578. v->flags |= VAR_EXPORTED;
  579. }
  580. return 1;
  581. }
  582. /*
  583. * This gets called from our children.
  584. */
  585. void
  586. Var_ExportVars(void)
  587. {
  588. char tmp[BUFSIZ];
  589. Hash_Entry *var;
  590. Hash_Search state;
  591. Var *v;
  592. char *val;
  593. int n;
  594. if (VAR_EXPORTED_NONE == var_exportedVars)
  595. return;
  596. if (VAR_EXPORTED_ALL == var_exportedVars) {
  597. /*
  598. * Ouch! This is crazy...
  599. */
  600. for (var = Hash_EnumFirst(&VAR_GLOBAL->context, &state);
  601. var != NULL;
  602. var = Hash_EnumNext(&state)) {
  603. v = (Var *)Hash_GetValue(var);
  604. Var_Export1(v->name, 0);
  605. }
  606. return;
  607. }
  608. /*
  609. * We have a number of exported vars,
  610. */
  611. n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}");
  612. if (n < (int)sizeof(tmp)) {
  613. char **av;
  614. char *as;
  615. int ac;
  616. int i;
  617. val = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
  618. av = brk_string(val, &ac, FALSE, &as);
  619. for (i = 0; i < ac; i++) {
  620. Var_Export1(av[i], 0);
  621. }
  622. free(val);
  623. free(as);
  624. free(av);
  625. }
  626. }
  627. /*
  628. * This is called when .export is seen or
  629. * .MAKE.EXPORTED is modified.
  630. * It is also called when any exported var is modified.
  631. */
  632. void
  633. Var_Export(char *str, int isExport)
  634. {
  635. char *name;
  636. char *val;
  637. char **av;
  638. char *as;
  639. int track;
  640. int ac;
  641. int i;
  642. if (isExport && (!str || !str[0])) {
  643. var_exportedVars = VAR_EXPORTED_ALL; /* use with caution! */
  644. return;
  645. }
  646. if (strncmp(str, "-env", 4) == 0) {
  647. track = 0;
  648. str += 4;
  649. } else {
  650. track = VAR_EXPORT_PARENT;
  651. }
  652. val = Var_Subst(NULL, str, VAR_GLOBAL, 0);
  653. av = brk_string(val, &ac, FALSE, &as);
  654. for (i = 0; i < ac; i++) {
  655. name = av[i];
  656. if (!name[1]) {
  657. /*
  658. * A single char.
  659. * If it is one of the vars that should only appear in
  660. * local context, skip it, else we can get Var_Subst
  661. * into a loop.
  662. */
  663. switch (name[0]) {
  664. case '@':
  665. case '%':
  666. case '*':
  667. case '!':
  668. continue;
  669. }
  670. }
  671. if (Var_Export1(name, track)) {
  672. if (VAR_EXPORTED_ALL != var_exportedVars)
  673. var_exportedVars = VAR_EXPORTED_YES;
  674. if (isExport && track) {
  675. Var_Append(MAKE_EXPORTED, name, VAR_GLOBAL);
  676. }
  677. }
  678. }
  679. free(val);
  680. free(as);
  681. free(av);
  682. }
  683. /*
  684. * This is called when .unexport[-env] is seen.
  685. */
  686. void
  687. Var_UnExport(char *str)
  688. {
  689. char tmp[BUFSIZ];
  690. char *vlist;
  691. char *cp;
  692. Boolean unexport_env;
  693. int n;
  694. if (!str || !str[0]) {
  695. return; /* assert? */
  696. }
  697. vlist = NULL;
  698. str += 8;
  699. unexport_env = (strncmp(str, "-env", 4) == 0);
  700. if (unexport_env) {
  701. extern char **environ;
  702. static char **savenv;
  703. char **newenv;
  704. cp = getenv(MAKE_LEVEL); /* we should preserve this */
  705. if (environ == savenv) {
  706. /* we have been here before! */
  707. newenv = bmake_realloc(environ, 2 * sizeof(char *));
  708. } else {
  709. if (savenv) {
  710. free(savenv);
  711. savenv = NULL;
  712. }
  713. newenv = bmake_malloc(2 * sizeof(char *));
  714. }
  715. if (!newenv)
  716. return;
  717. /* Note: we cannot safely free() the original environ. */
  718. environ = savenv = newenv;
  719. newenv[0] = NULL;
  720. newenv[1] = NULL;
  721. setenv(MAKE_LEVEL, cp, 1);
  722. } else {
  723. for (; *str != '\n' && isspace((unsigned char) *str); str++)
  724. continue;
  725. if (str[0] && str[0] != '\n') {
  726. vlist = str;
  727. }
  728. }
  729. if (!vlist) {
  730. /* Using .MAKE.EXPORTED */
  731. n = snprintf(tmp, sizeof(tmp), "${" MAKE_EXPORTED ":O:u}");
  732. if (n < (int)sizeof(tmp)) {
  733. vlist = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
  734. }
  735. }
  736. if (vlist) {
  737. Var *v;
  738. char **av;
  739. char *as;
  740. int ac;
  741. int i;
  742. av = brk_string(vlist, &ac, FALSE, &as);
  743. for (i = 0; i < ac; i++) {
  744. v = VarFind(av[i], VAR_GLOBAL, 0);
  745. if (!v)
  746. continue;
  747. if (!unexport_env &&
  748. (v->flags & (VAR_EXPORTED|VAR_REEXPORT)) == VAR_EXPORTED) {
  749. unsetenv(v->name);
  750. }
  751. v->flags &= ~(VAR_EXPORTED|VAR_REEXPORT);
  752. /*
  753. * If we are unexporting a list,
  754. * remove each one from .MAKE.EXPORTED.
  755. * If we are removing them all,
  756. * just delete .MAKE.EXPORTED below.
  757. */
  758. if (vlist == str) {
  759. n = snprintf(tmp, sizeof(tmp),
  760. "${" MAKE_EXPORTED ":N%s}", v->name);
  761. if (n < (int)sizeof(tmp)) {
  762. cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
  763. Var_Set(MAKE_EXPORTED, cp, VAR_GLOBAL, 0);
  764. free(cp);
  765. }
  766. }
  767. }
  768. free(as);
  769. free(av);
  770. if (vlist != str) {
  771. Var_Delete(MAKE_EXPORTED, VAR_GLOBAL);
  772. free(vlist);
  773. }
  774. }
  775. }
  776. /*-
  777. *-----------------------------------------------------------------------
  778. * Var_Set --
  779. * Set the variable name to the value val in the given context.
  780. *
  781. * Input:
  782. * name name of variable to set
  783. * val value to give to the variable
  784. * ctxt context in which to set it
  785. *
  786. * Results:
  787. * None.
  788. *
  789. * Side Effects:
  790. * If the variable doesn't yet exist, a new record is created for it.
  791. * Else the old value is freed and the new one stuck in its place
  792. *
  793. * Notes:
  794. * The variable is searched for only in its context before being
  795. * created in that context. I.e. if the context is VAR_GLOBAL,
  796. * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only
  797. * VAR_CMD->context is searched. This is done to avoid the literally
  798. * thousands of unnecessary strcmp's that used to be done to
  799. * set, say, $(@) or $(<).
  800. * If the context is VAR_GLOBAL though, we check if the variable
  801. * was set in VAR_CMD from the command line and skip it if so.
  802. *-----------------------------------------------------------------------
  803. */
  804. void
  805. Var_Set(const char *name, const char *val, GNode *ctxt, int flags)
  806. {
  807. Var *v;
  808. char *expanded_name = NULL;
  809. /*
  810. * We only look for a variable in the given context since anything set
  811. * here will override anything in a lower context, so there's not much
  812. * point in searching them all just to save a bit of memory...
  813. */
  814. if (strchr(name, '$') != NULL) {
  815. expanded_name = Var_Subst(NULL, name, ctxt, 0);
  816. if (expanded_name[0] == 0) {
  817. if (DEBUG(VAR)) {
  818. fprintf(debug_file, "Var_Set(\"%s\", \"%s\", ...) "
  819. "name expands to empty string - ignored\n",
  820. name, val);
  821. }
  822. free(expanded_name);
  823. return;
  824. }
  825. name = expanded_name;
  826. }
  827. if (ctxt == VAR_GLOBAL) {
  828. v = VarFind(name, VAR_CMD, 0);
  829. if (v != NULL) {
  830. if ((v->flags & VAR_FROM_CMD)) {
  831. if (DEBUG(VAR)) {
  832. fprintf(debug_file, "%s:%s = %s ignored!\n", ctxt->name, name, val);
  833. }
  834. goto out;
  835. }
  836. VarFreeEnv(v, TRUE);
  837. }
  838. }
  839. v = VarFind(name, ctxt, 0);
  840. if (v == NULL) {
  841. VarAdd(name, val, ctxt);
  842. } else {
  843. Buf_Empty(&v->val);
  844. Buf_AddBytes(&v->val, strlen(val), val);
  845. if (DEBUG(VAR)) {
  846. fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val);
  847. }
  848. if ((v->flags & VAR_EXPORTED)) {
  849. Var_Export1(name, VAR_EXPORT_PARENT);
  850. }
  851. }
  852. /*
  853. * Any variables given on the command line are automatically exported
  854. * to the environment (as per POSIX standard)
  855. */
  856. if (ctxt == VAR_CMD && (flags & VAR_NO_EXPORT) == 0) {
  857. if (v == NULL) {
  858. /* we just added it */
  859. v = VarFind(name, ctxt, 0);
  860. }
  861. if (v != NULL)
  862. v->flags |= VAR_FROM_CMD;
  863. /*
  864. * If requested, don't export these in the environment
  865. * individually. We still put them in MAKEOVERRIDES so
  866. * that the command-line settings continue to override
  867. * Makefile settings.
  868. */
  869. if (varNoExportEnv != TRUE)
  870. setenv(name, val, 1);
  871. Var_Append(MAKEOVERRIDES, name, VAR_GLOBAL);
  872. }
  873. /*
  874. * Another special case.
  875. * Several make's support this sort of mechanism for tracking
  876. * recursion - but each uses a different name.
  877. * We allow the makefiles to update .MAKE.LEVEL and ensure
  878. * children see a correctly incremented value.
  879. */
  880. if (ctxt == VAR_GLOBAL && strcmp(MAKE_LEVEL, name) == 0) {
  881. char tmp[64];
  882. int level;
  883. level = atoi(val);
  884. snprintf(tmp, sizeof(tmp), "%u", level + 1);
  885. setenv(MAKE_LEVEL, tmp, 1);
  886. }
  887. out:
  888. if (expanded_name != NULL)
  889. free(expanded_name);
  890. if (v != NULL)
  891. VarFreeEnv(v, TRUE);
  892. }
  893. /*-
  894. *-----------------------------------------------------------------------
  895. * Var_Append --
  896. * The variable of the given name has the given value appended to it in
  897. * the given context.
  898. *
  899. * Input:
  900. * name name of variable to modify
  901. * val String to append to it
  902. * ctxt Context in which this should occur
  903. *
  904. * Results:
  905. * None
  906. *
  907. * Side Effects:
  908. * If the variable doesn't exist, it is created. Else the strings
  909. * are concatenated (with a space in between).
  910. *
  911. * Notes:
  912. * Only if the variable is being sought in the global context is the
  913. * environment searched.
  914. * XXX: Knows its calling circumstances in that if called with ctxt
  915. * an actual target, it will only search that context since only
  916. * a local variable could be being appended to. This is actually
  917. * a big win and must be tolerated.
  918. *-----------------------------------------------------------------------
  919. */
  920. void
  921. Var_Append(const char *name, const char *val, GNode *ctxt)
  922. {
  923. Var *v;
  924. Hash_Entry *h;
  925. char *expanded_name = NULL;
  926. if (strchr(name, '$') != NULL) {
  927. expanded_name = Var_Subst(NULL, name, ctxt, 0);
  928. if (expanded_name[0] == 0) {
  929. if (DEBUG(VAR)) {
  930. fprintf(debug_file, "Var_Append(\"%s\", \"%s\", ...) "
  931. "name expands to empty string - ignored\n",
  932. name, val);
  933. }
  934. free(expanded_name);
  935. return;
  936. }
  937. name = expanded_name;
  938. }
  939. v = VarFind(name, ctxt, (ctxt == VAR_GLOBAL) ? FIND_ENV : 0);
  940. if (v == NULL) {
  941. VarAdd(name, val, ctxt);
  942. } else {
  943. Buf_AddByte(&v->val, ' ');
  944. Buf_AddBytes(&v->val, strlen(val), val);
  945. if (DEBUG(VAR)) {
  946. fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name,
  947. Buf_GetAll(&v->val, NULL));
  948. }
  949. if (v->flags & VAR_FROM_ENV) {
  950. /*
  951. * If the original variable came from the environment, we
  952. * have to install it in the global context (we could place
  953. * it in the environment, but then we should provide a way to
  954. * export other variables...)
  955. */
  956. v->flags &= ~VAR_FROM_ENV;
  957. h = Hash_CreateEntry(&ctxt->context, name, NULL);
  958. Hash_SetValue(h, v);
  959. }
  960. }
  961. if (expanded_name != NULL)
  962. free(expanded_name);
  963. }
  964. /*-
  965. *-----------------------------------------------------------------------
  966. * Var_Exists --
  967. * See if the given variable exists.
  968. *
  969. * Input:
  970. * name Variable to find
  971. * ctxt Context in which to start search
  972. *
  973. * Results:
  974. * TRUE if it does, FALSE if it doesn't
  975. *
  976. * Side Effects:
  977. * None.
  978. *
  979. *-----------------------------------------------------------------------
  980. */
  981. Boolean
  982. Var_Exists(const char *name, GNode *ctxt)
  983. {
  984. Var *v;
  985. char *cp;
  986. if ((cp = strchr(name, '$')) != NULL) {
  987. cp = Var_Subst(NULL, name, ctxt, FALSE);
  988. }
  989. v = VarFind(cp ? cp : name, ctxt, FIND_CMD|FIND_GLOBAL|FIND_ENV);
  990. if (cp != NULL) {
  991. free(cp);
  992. }
  993. if (v == NULL) {
  994. return(FALSE);
  995. } else {
  996. (void)VarFreeEnv(v, TRUE);
  997. }
  998. return(TRUE);
  999. }
  1000. /*-
  1001. *-----------------------------------------------------------------------
  1002. * Var_Value --
  1003. * Return the value of the named variable in the given context
  1004. *
  1005. * Input:
  1006. * name name to find
  1007. * ctxt context in which to search for it
  1008. *
  1009. * Results:
  1010. * The value if the variable exists, NULL if it doesn't
  1011. *
  1012. * Side Effects:
  1013. * None
  1014. *-----------------------------------------------------------------------
  1015. */
  1016. char *
  1017. Var_Value(const char *name, GNode *ctxt, char **frp)
  1018. {
  1019. Var *v;
  1020. v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
  1021. *frp = NULL;
  1022. if (v != NULL) {
  1023. char *p = (Buf_GetAll(&v->val, NULL));
  1024. if (VarFreeEnv(v, FALSE))
  1025. *frp = p;
  1026. return p;
  1027. } else {
  1028. return NULL;
  1029. }
  1030. }
  1031. /*-
  1032. *-----------------------------------------------------------------------
  1033. * VarHead --
  1034. * Remove the tail of the given word and place the result in the given
  1035. * buffer.
  1036. *
  1037. * Input:
  1038. * word Word to trim
  1039. * addSpace True if need to add a space to the buffer
  1040. * before sticking in the head
  1041. * buf Buffer in which to store it
  1042. *
  1043. * Results:
  1044. * TRUE if characters were added to the buffer (a space needs to be
  1045. * added to the buffer before the next word).
  1046. *
  1047. * Side Effects:
  1048. * The trimmed word is added to the buffer.
  1049. *
  1050. *-----------------------------------------------------------------------
  1051. */
  1052. static Boolean
  1053. VarHead(GNode *ctx __unused, Var_Parse_State *vpstate,
  1054. char *word, Boolean addSpace, Buffer *buf,
  1055. void *dummy)
  1056. {
  1057. char *slash;
  1058. slash = strrchr(word, '/');
  1059. if (slash != NULL) {
  1060. if (addSpace && vpstate->varSpace) {
  1061. Buf_AddByte(buf, vpstate->varSpace);
  1062. }
  1063. *slash = '\0';
  1064. Buf_AddBytes(buf, strlen(word), word);
  1065. *slash = '/';
  1066. return (TRUE);
  1067. } else {
  1068. /*
  1069. * If no directory part, give . (q.v. the POSIX standard)
  1070. */
  1071. if (addSpace && vpstate->varSpace)
  1072. Buf_AddByte(buf, vpstate->varSpace);
  1073. Buf_AddByte(buf, '.');
  1074. }
  1075. return(dummy ? TRUE : TRUE);
  1076. }
  1077. /*-
  1078. *-----------------------------------------------------------------------
  1079. * VarTail --
  1080. * Remove the head of the given word and place the result in the given
  1081. * buffer.
  1082. *
  1083. * Input:
  1084. * word Word to trim
  1085. * addSpace True if need to add a space to the buffer
  1086. * before adding the tail
  1087. * buf Buffer in which to store it
  1088. *
  1089. * Results:
  1090. * TRUE if characters were added to the buffer (a space needs to be
  1091. * added to the buffer before the next word).
  1092. *
  1093. * Side Effects:
  1094. * The trimmed word is added to the buffer.
  1095. *
  1096. *-----------------------------------------------------------------------
  1097. */
  1098. static Boolean
  1099. VarTail(GNode *ctx __unused, Var_Parse_State *vpstate,
  1100. char *word, Boolean addSpace, Buffer *buf,
  1101. void *dummy)
  1102. {
  1103. char *slash;
  1104. if (addSpace && vpstate->varSpace) {
  1105. Buf_AddByte(buf, vpstate->varSpace);
  1106. }
  1107. slash = strrchr(word, '/');
  1108. if (slash != NULL) {
  1109. *slash++ = '\0';
  1110. Buf_AddBytes(buf, strlen(slash), slash);
  1111. slash[-1] = '/';
  1112. } else {
  1113. Buf_AddBytes(buf, strlen(word), word);
  1114. }
  1115. return (dummy ? TRUE : TRUE);
  1116. }
  1117. /*-
  1118. *-----------------------------------------------------------------------
  1119. * VarSuffix --
  1120. * Place the suffix of the given word in the given buffer.
  1121. *
  1122. * Input:
  1123. * word Word to trim
  1124. * addSpace TRUE if need to add a space before placing the
  1125. * suffix in the buffer
  1126. * buf Buffer in which to store it
  1127. *
  1128. * Results:
  1129. * TRUE if characters were added to the buffer (a space needs to be
  1130. * added to the buffer before the next word).
  1131. *
  1132. * Side Effects:
  1133. * The suffix from the word is placed in the buffer.
  1134. *
  1135. *-----------------------------------------------------------------------
  1136. */
  1137. static Boolean
  1138. VarSuffix(GNode *ctx __unused, Var_Parse_State *vpstate,
  1139. char *word, Boolean addSpace, Buffer *buf,
  1140. void *dummy)
  1141. {
  1142. char *dot;
  1143. dot = strrchr(word, '.');
  1144. if (dot != NULL) {
  1145. if (addSpace && vpstate->varSpace) {
  1146. Buf_AddByte(buf, vpstate->varSpace);
  1147. }
  1148. *dot++ = '\0';
  1149. Buf_AddBytes(buf, strlen(dot), dot);
  1150. dot[-1] = '.';
  1151. addSpace = TRUE;
  1152. }
  1153. return (dummy ? addSpace : addSpace);
  1154. }
  1155. /*-
  1156. *-----------------------------------------------------------------------
  1157. * VarRoot --
  1158. * Remove the suffix of the given word and place the result in the
  1159. * buffer.
  1160. *
  1161. * Input:
  1162. * word Word to trim
  1163. * addSpace TRUE if need to add a space to the buffer
  1164. * before placing the root in it
  1165. * buf Buffer in which to store it
  1166. *
  1167. * Results:
  1168. * TRUE if characters were added to the buffer (a space needs to be
  1169. * added to the buffer before the next word).
  1170. *
  1171. * Side Effects:
  1172. * The trimmed word is added to the buffer.
  1173. *
  1174. *-----------------------------------------------------------------------
  1175. */
  1176. static Boolean
  1177. VarRoot(GNode *ctx __unused, Var_Parse_State *vpstate,
  1178. char *word, Boolean addSpace, Buffer *buf,
  1179. void *dummy)
  1180. {
  1181. char *dot;
  1182. if (addSpace && vpstate->varSpace) {
  1183. Buf_AddByte(buf, vpstate->varSpace);
  1184. }
  1185. dot = strrchr(word, '.');
  1186. if (dot != NULL) {
  1187. *dot = '\0';
  1188. Buf_AddBytes(buf, strlen(word), word);
  1189. *dot = '.';
  1190. } else {
  1191. Buf_AddBytes(buf, strlen(word), word);
  1192. }
  1193. return (dummy ? TRUE : TRUE);
  1194. }
  1195. /*-
  1196. *-----------------------------------------------------------------------
  1197. * VarMatch --
  1198. * Place the word in the buffer if it matches the given pattern.
  1199. * Callback function for VarModify to implement the :M modifier.
  1200. *
  1201. * Input:
  1202. * word Word to examine
  1203. * addSpace TRUE if need to add a space to the buffer
  1204. * before adding the word, if it matches
  1205. * buf Buffer in which to store it
  1206. * pattern Pattern the word must match
  1207. *
  1208. * Results:
  1209. * TRUE if a space should be placed in the buffer before the next
  1210. * word.
  1211. *
  1212. * Side Effects:
  1213. * The word may be copied to the buffer.
  1214. *
  1215. *-----------------------------------------------------------------------
  1216. */
  1217. static Boolean
  1218. VarMatch(GNode *ctx __unused, Var_Parse_State *vpstate,
  1219. char *word, Boolean addSpace, Buffer *buf,
  1220. void *pattern)
  1221. {
  1222. if (DEBUG(VAR))
  1223. fprintf(debug_file, "VarMatch [%s] [%s]\n", word, (char *)pattern);
  1224. if (Str_Match(word, (char *)pattern)) {
  1225. if (addSpace && vpstate->varSpace) {
  1226. Buf_AddByte(buf, vpstate->varSpace);
  1227. }
  1228. addSpace = TRUE;
  1229. Buf_AddBytes(buf, strlen(word), word);
  1230. }
  1231. return(addSpace);
  1232. }
  1233. #ifdef SYSVVARSUB
  1234. /*-
  1235. *-----------------------------------------------------------------------
  1236. * VarSYSVMatch --
  1237. * Place the word in the buffer if it matches the given pattern.
  1238. * Callback function for VarModify to implement the System V %
  1239. * modifiers.
  1240. *
  1241. * Input:
  1242. * word Word to examine
  1243. * addSpace TRUE if need to add a space to the buffer
  1244. * before adding the word, if it matches
  1245. * buf Buffer in which to store it
  1246. * patp Pattern the word must match
  1247. *
  1248. * Results:
  1249. * TRUE if a space should be placed in the buffer before the next
  1250. * word.
  1251. *
  1252. * Side Effects:
  1253. * The word may be copied to the buffer.
  1254. *
  1255. *-----------------------------------------------------------------------
  1256. */
  1257. static Boolean
  1258. VarSYSVMatch(GNode *ctx, Var_Parse_State *vpstate,
  1259. char *word, Boolean addSpace, Buffer *buf,
  1260. void *patp)
  1261. {
  1262. int len;
  1263. char *ptr;
  1264. VarPattern *pat = (VarPattern *)patp;
  1265. char *varexp;
  1266. if (addSpace && vpstate->varSpace)
  1267. Buf_AddByte(buf, vpstate->varSpace);
  1268. addSpace = TRUE;
  1269. if ((ptr = Str_SYSVMatch(word, pat->lhs, &len)) != NULL) {
  1270. varexp = Var_Subst(NULL, pat->rhs, ctx, 0);
  1271. Str_SYSVSubst(buf, varexp, ptr, len);
  1272. free(varexp);
  1273. } else {
  1274. Buf_AddBytes(buf, strlen(word), word);
  1275. }
  1276. return(addSpace);
  1277. }
  1278. #endif
  1279. /*-
  1280. *-----------------------------------------------------------------------
  1281. * VarNoMatch --
  1282. * Place the word in the buffer if it doesn't match the given pattern.
  1283. * Callback function for VarModify to implement the :N modifier.
  1284. *
  1285. * Input:
  1286. * word Word to examine
  1287. * addSpace TRUE if need to add a space to the buffer
  1288. * before adding the word, if it matches
  1289. * buf Buffer in which to store it
  1290. * pattern Pattern the word must match
  1291. *
  1292. * Results:
  1293. * TRUE if a space should be placed in the buffer before the next
  1294. * word.
  1295. *
  1296. * Side Effects:
  1297. * The word may be copied to the buffer.
  1298. *
  1299. *-----------------------------------------------------------------------
  1300. */
  1301. static Boolean
  1302. VarNoMatch(GNode *ctx __unused, Var_Parse_State *vpstate,
  1303. char *word, Boolean addSpace, Buffer *buf,
  1304. void *pattern)
  1305. {
  1306. if (!Str_Match(word, (char *)pattern)) {
  1307. if (addSpace && vpstate->varSpace) {
  1308. Buf_AddByte(buf, vpstate->varSpace);
  1309. }
  1310. addSpace = TRUE;
  1311. Buf_AddBytes(buf, strlen(word), word);
  1312. }
  1313. return(addSpace);
  1314. }
  1315. /*-
  1316. *-----------------------------------------------------------------------
  1317. * VarSubstitute --
  1318. * Perform a string-substitution on the given word, placing the
  1319. * result in the passed buffer.
  1320. *
  1321. * Input:
  1322. * word Word to modify
  1323. * addSpace True if space should be added before
  1324. * other characters
  1325. * buf Buffer for result
  1326. * patternp Pattern for substitution
  1327. *
  1328. * Results:
  1329. * TRUE if a space is needed before more characters are added.
  1330. *
  1331. * Side Effects:
  1332. * None.
  1333. *
  1334. *-----------------------------------------------------------------------
  1335. */
  1336. static Boolean
  1337. VarSubstitute(GNode *ctx __unused, Var_Parse_State *vpstate,
  1338. char *word, Boolean addSpace, Buffer *buf,
  1339. void *patternp)
  1340. {
  1341. int wordLen; /* Length of word */
  1342. char *cp; /* General pointer */
  1343. VarPattern *pattern = (VarPattern *)patternp;
  1344. wordLen = strlen(word);
  1345. if ((pattern->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) !=
  1346. (VAR_SUB_ONE|VAR_SUB_MATCHED)) {
  1347. /*
  1348. * Still substituting -- break it down into simple anchored cases
  1349. * and if none of them fits, perform the general substitution case.
  1350. */
  1351. if ((pattern->flags & VAR_MATCH_START) &&
  1352. (strncmp(word, pattern->lhs, pattern->leftLen) == 0)) {
  1353. /*
  1354. * Anchored at start and beginning of word matches pattern
  1355. */
  1356. if ((pattern->flags & VAR_MATCH_END) &&
  1357. (wordLen == pattern->leftLen)) {
  1358. /*
  1359. * Also anchored at end and matches to the end (word
  1360. * is same length as pattern) add space and rhs only
  1361. * if rhs is non-null.
  1362. */
  1363. if (pattern->rightLen != 0) {
  1364. if (addSpace && vpstate->varSpace) {
  1365. Buf_AddByte(buf, vpstate->varSpace);
  1366. }
  1367. addSpace = TRUE;
  1368. Buf_AddBytes(buf, pattern->rightLen, pattern->rhs);
  1369. }
  1370. pattern->flags |= VAR_SUB_MATCHED;
  1371. } else if (pattern->flags & VAR_MATCH_END) {
  1372. /*
  1373. * Doesn't match to end -- copy word wholesale
  1374. */
  1375. goto nosub;
  1376. } else {
  1377. /*
  1378. * Matches at start but need to copy in trailing characters
  1379. */
  1380. if ((pattern->rightLen + wordLen - pattern->leftLen) != 0){
  1381. if (addSpace && vpstate->varSpace) {
  1382. Buf_AddByte(buf, vpstate->varSpace);
  1383. }
  1384. addSpace = TRUE;
  1385. }
  1386. Buf_AddBytes(buf, pattern->rightLen, pattern->rhs);
  1387. Buf_AddBytes(buf, wordLen - pattern->leftLen,
  1388. (word + pattern->leftLen));
  1389. pattern->flags |= VAR_SUB_MATCHED;
  1390. }
  1391. } else if (pattern->flags & VAR_MATCH_START) {
  1392. /*
  1393. * Had to match at start of word and didn't -- copy whole word.
  1394. */
  1395. goto nosub;
  1396. } else if (pattern->flags & VAR_MATCH_END) {
  1397. /*
  1398. * Anchored at end, Find only place match could occur (leftLen
  1399. * characters from the end of the word) and see if it does. Note
  1400. * that because the $ will be left at the end of the lhs, we have
  1401. * to use strncmp.
  1402. */
  1403. cp = word + (wordLen - pattern->leftLen);
  1404. if ((cp >= word) &&
  1405. (strncmp(cp, pattern->lhs, pattern->leftLen) == 0)) {
  1406. /*
  1407. * Match found. If we will place characters in the buffer,
  1408. * add a space before hand as indicated by addSpace, then
  1409. * stuff in the initial, unmatched part of the word followed
  1410. * by the right-hand-side.
  1411. */
  1412. if (((cp - word) + pattern->rightLen) != 0) {
  1413. if (addSpace && vpstate->varSpace) {
  1414. Buf_AddByte(buf, vpstate->varSpace);
  1415. }
  1416. addSpace = TRUE;
  1417. }
  1418. Buf_AddBytes(buf, cp - word, word);
  1419. Buf_AddBytes(buf, pattern->rightLen, pattern->rhs);
  1420. pattern->flags |= VAR_SUB_MATCHED;
  1421. } else {
  1422. /*
  1423. * Had to match at end and didn't. Copy entire word.
  1424. */
  1425. goto nosub;
  1426. }
  1427. } else {
  1428. /*
  1429. * Pattern is unanchored: search for the pattern in the word using
  1430. * String_FindSubstring, copying unmatched portions and the
  1431. * right-hand-side for each match found, handling non-global
  1432. * substitutions correctly, etc. When the loop is done, any
  1433. * remaining part of the word (word and wordLen are adjusted
  1434. * accordingly through the loop) is copied straight into the
  1435. * buffer.
  1436. * addSpace is set FALSE as soon as a space is added to the
  1437. * buffer.
  1438. */
  1439. Boolean done;
  1440. int origSize;
  1441. done = FALSE;
  1442. origSize = Buf_Size(buf);
  1443. while (!done) {
  1444. cp = Str_FindSubstring(word, pattern->lhs);
  1445. if (cp != NULL) {
  1446. if (addSpace && (((cp - word) + pattern->rightLen) != 0)){
  1447. Buf_AddByte(buf, vpstate->varSpace);
  1448. addSpace = FALSE;
  1449. }
  1450. Buf_AddBytes(buf, cp-word, word);
  1451. Buf_AddBytes(buf, pattern->rightLen, pattern->rhs);
  1452. wordLen -= (cp - word) + pattern->leftLen;
  1453. word = cp + pattern->leftLen;
  1454. if (wordLen == 0) {
  1455. done = TRUE;
  1456. }
  1457. if ((pattern->flags & VAR_SUB_GLOBAL) == 0) {
  1458. done = TRUE;
  1459. }
  1460. pattern->flags |= VAR_SUB_MATCHED;
  1461. } else {
  1462. done = TRUE;
  1463. }
  1464. }
  1465. if (wordLen != 0) {
  1466. if (addSpace && vpstate->varSpace) {
  1467. Buf_AddByte(buf, vpstate->varSpace);
  1468. }
  1469. Buf_AddBytes(buf, wordLen, word);
  1470. }
  1471. /*
  1472. * If added characters to the buffer, need to add a space
  1473. * before we add any more. If we didn't add any, just return
  1474. * the previous value of addSpace.
  1475. */
  1476. return ((Buf_Size(buf) != origSize) || addSpace);
  1477. }
  1478. return (addSpace);
  1479. }
  1480. nosub:
  1481. if (addSpace && vpstate->varSpace) {
  1482. Buf_AddByte(buf, vpstate->varSpace);
  1483. }
  1484. Buf_AddBytes(buf, wordLen, word);
  1485. return(TRUE);
  1486. }
  1487. #ifndef NO_REGEX
  1488. /*-
  1489. *-----------------------------------------------------------------------
  1490. * VarREError --
  1491. * Print the error caused by a regcomp or regexec call.
  1492. *
  1493. * Results:
  1494. * None.
  1495. *
  1496. * Side Effects:
  1497. * An error gets printed.
  1498. *
  1499. *-----------------------------------------------------------------------
  1500. */
  1501. static void
  1502. VarREError(int errnum, regex_t *pat, const char *str)
  1503. {
  1504. char *errbuf;
  1505. int errlen;
  1506. errlen = regerror(errnum, pat, 0, 0);
  1507. errbuf = bmake_malloc(errlen);
  1508. regerror(errnum, pat, errbuf, errlen);
  1509. Error("%s: %s", str, errbuf);
  1510. free(errbuf);
  1511. }
  1512. /*-
  1513. *-----------------------------------------------------------------------
  1514. * VarRESubstitute --
  1515. * Perform a regex substitution on the given word, placing the
  1516. * result in the passed buffer.
  1517. *
  1518. * Results:
  1519. * TRUE if a space is needed before more characters are added.
  1520. *
  1521. * Side Effects:
  1522. * None.
  1523. *
  1524. *-----------------------------------------------------------------------
  1525. */
  1526. static Boolean
  1527. VarRESubstitute(GNode *ctx __unused, Var_Parse_State *vpstate __unused,
  1528. char *word, Boolean addSpace, Buffer *buf,
  1529. void *patternp)
  1530. {
  1531. VarREPattern *pat;
  1532. int xrv;
  1533. char *wp;
  1534. char *rp;
  1535. int added;
  1536. int flags = 0;
  1537. #define MAYBE_ADD_SPACE() \
  1538. if (addSpace && !added) \
  1539. Buf_AddByte(buf, ' '); \
  1540. added = 1
  1541. added = 0;
  1542. wp = word;
  1543. pat = patternp;
  1544. if ((pat->flags & (VAR_SUB_ONE|VAR_SUB_MATCHED)) ==
  1545. (VAR_SUB_ONE|VAR_SUB_MATCHED))
  1546. xrv = REG_NOMATCH;
  1547. else {
  1548. tryagain:
  1549. xrv = regexec(&pat->re, wp, pat->nsub, pat->matches, flags);
  1550. }
  1551. switch (xrv) {
  1552. case 0:
  1553. pat->flags |= VAR_SUB_MATCHED;
  1554. if (pat->matches[0].rm_so > 0) {
  1555. MAYBE_ADD_SPACE();
  1556. Buf_AddBytes(buf, pat->matches[0].rm_so, wp);
  1557. }
  1558. for (rp = pat->replace; *rp; rp++) {
  1559. if ((*rp == '\\') && ((rp[1] == '&') || (rp[1] == '\\'))) {
  1560. MAYBE_ADD_SPACE();
  1561. Buf_AddByte(buf,rp[1]);
  1562. rp++;
  1563. }
  1564. else if ((*rp == '&') ||
  1565. ((*rp == '\\') && isdigit((unsigned char)rp[1]))) {
  1566. int n;
  1567. const char *subbuf;
  1568. int sublen;
  1569. char errstr[3];
  1570. if (*rp == '&') {
  1571. n = 0;
  1572. errstr[0] = '&';
  1573. errstr[1] = '\0';
  1574. } else {
  1575. n = rp[1] - '0';
  1576. errstr[0] = '\\';
  1577. errstr[1] = rp[1];
  1578. errstr[2] = '\0';
  1579. rp++;
  1580. }
  1581. if (n > pat->nsub) {
  1582. Error("No subexpression %s", &errstr[0]);
  1583. subbuf = "";
  1584. sublen = 0;
  1585. } else if ((pat->matches[n].rm_so == -1) &&
  1586. (pat->matches[n].rm_eo == -1)) {
  1587. Error("No match for subexpression %s", &errstr[0]);
  1588. subbuf = "";
  1589. sublen = 0;
  1590. } else {
  1591. subbuf = wp + pat->matches[n].rm_so;
  1592. sublen = pat->matches[n].rm_eo - pat->matches[n].rm_so;
  1593. }
  1594. if (sublen > 0) {
  1595. MAYBE_ADD_SPACE();
  1596. Buf_AddBytes(buf, sublen, subbuf);
  1597. }
  1598. } else {
  1599. MAYBE_ADD_SPACE();
  1600. Buf_AddByte(buf, *rp);
  1601. }
  1602. }
  1603. wp += pat->matches[0].rm_eo;
  1604. if (pat->flags & VAR_SUB_GLOBAL) {
  1605. flags |= REG_NOTBOL;
  1606. if (pat->matches[0].rm_so == 0 && pat->matches[0].rm_eo == 0) {
  1607. MAYBE_ADD_SPACE();
  1608. Buf_AddByte(buf, *wp);
  1609. wp++;
  1610. }
  1611. if (*wp)
  1612. goto tryagain;
  1613. }
  1614. if (*wp) {
  1615. MAYBE_ADD_SPACE();
  1616. Buf_AddBytes(buf, strlen(wp), wp);
  1617. }
  1618. break;
  1619. default:
  1620. VarREError(xrv, &pat->re, "Unexpected regex error");
  1621. /* fall through */
  1622. case REG_NOMATCH:
  1623. if (*wp) {
  1624. MAYBE_ADD_SPACE();
  1625. Buf_AddBytes(buf,strlen(wp),wp);
  1626. }
  1627. break;
  1628. }
  1629. return(addSpace||added);
  1630. }
  1631. #endif
  1632. /*-
  1633. *-----------------------------------------------------------------------
  1634. * VarLoopExpand --
  1635. * Implements the :@<temp>@<string>@ modifier of ODE make.
  1636. * We set the temp variable named in pattern.lhs to word and expand
  1637. * pattern.rhs storing the result in the passed buffer.
  1638. *
  1639. * Input:
  1640. * word Word to modify
  1641. * addSpace True if space should be added before
  1642. * other characters
  1643. * buf Buffer for result
  1644. * pattern Datafor substitution
  1645. *
  1646. * Results:
  1647. * TRUE if a space is needed before more characters are added.
  1648. *
  1649. * Side Effects:
  1650. * None.
  1651. *
  1652. *-----------------------------------------------------------------------
  1653. */
  1654. static Boolean
  1655. VarLoopExpand(GNode *ctx __unused, Var_Parse_State *vpstate __unused,
  1656. char *word, Boolean addSpace, Buffer *buf,
  1657. void *loopp)
  1658. {
  1659. VarLoop_t *loop = (VarLoop_t *)loopp;
  1660. char *s;
  1661. int slen;
  1662. if (word && *word) {
  1663. Var_Set(loop->tvar, word, loop->ctxt, VAR_NO_EXPORT);
  1664. s = Var_Subst(NULL, loop->str, loop->ctxt, loop->errnum);
  1665. if (s != NULL && *s != '\0') {
  1666. if (addSpace && *s != '\n')
  1667. Buf_AddByte(buf, ' ');
  1668. Buf_AddBytes(buf, (slen = strlen(s)), s);
  1669. addSpace = (slen > 0 && s[slen - 1] != '\n');
  1670. free(s);
  1671. }
  1672. }
  1673. return addSpace;
  1674. }
  1675. /*-
  1676. *-----------------------------------------------------------------------
  1677. * VarSelectWords --
  1678. * Implements the :[start..end] modifier.
  1679. * This is a special case of VarModify since we want to be able
  1680. * to scan the list backwards if start > end.
  1681. *
  1682. * Input:
  1683. * str String whose words should be trimmed
  1684. * seldata words to select
  1685. *
  1686. * Results:
  1687. * A string of all the words selected.
  1688. *
  1689. * Side Effects:
  1690. * None.
  1691. *
  1692. *-----------------------------------------------------------------------
  1693. */
  1694. static char *
  1695. VarSelectWords(GNode *ctx __unused, Var_Parse_State *vpstate,
  1696. const char *str, VarSelectWords_t *seldata)
  1697. {
  1698. Buffer buf; /* Buffer for the new string */
  1699. Boolean addSpace; /* TRUE if need to add a space to the
  1700. * buffer before adding the trimmed
  1701. * word */
  1702. char **av; /* word list */
  1703. char *as; /* word list memory */
  1704. int ac, i;
  1705. int start, end, step;
  1706. Buf_Init(&buf, 0);
  1707. addSpace = FALSE;
  1708. if (vpstate->oneBigWord) {
  1709. /* fake what brk_string() would do if there were only one word */
  1710. ac = 1;
  1711. av = bmake_malloc((ac + 1) * sizeof(char *));
  1712. as = bmake_strdup(str);
  1713. av[0] = as;
  1714. av[1] = NULL;
  1715. } else {
  1716. av = brk_string(str, &ac, FALSE, &as);
  1717. }
  1718. /*
  1719. * Now sanitize sel…

Large files files are truncated, but you can click here to view the full file