PageRenderTime 88ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/usr.bin/make/var.c

http://github.com/davshao/dflygsocdrm
C | 2532 lines | 1486 code | 281 blank | 765 comment | 475 complexity | db2f7dd72d9c0a605667e98bbbe2ace6 MD5 | raw file
Possible License(s): AGPL-1.0, CC-BY-SA-3.0, LGPL-2.0, GPL-3.0, LGPL-2.1, LGPL-3.0, MPL-2.0-no-copyleft-exception, 0BSD, BSD-3-Clause, GPL-2.0

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

  1. /*-
  2. * Copyright (c) 2002 Juli Mallett.
  3. * Copyright (c) 1988, 1989, 1990, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. * Copyright (c) 1989 by Berkeley Softworks
  6. * All rights reserved.
  7. *
  8. * This code is derived from software contributed to Berkeley by
  9. * Adam de Boor.
  10. *
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions
  13. * are met:
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. * 3. All advertising materials mentioning features or use of this software
  20. * must display the following acknowledgement:
  21. * This product includes software developed by the University of
  22. * California, Berkeley and its contributors.
  23. * 4. Neither the name of the University nor the names of its contributors
  24. * may be used to endorse or promote products derived from this software
  25. * without specific prior written permission.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  28. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  31. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  32. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  33. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  34. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  35. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  36. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  37. * SUCH DAMAGE.
  38. *
  39. * @(#)var.c 8.3 (Berkeley) 3/19/94
  40. * $FreeBSD: src/usr.bin/make/var.c,v 1.83 2005/02/11 10:49:01 harti Exp $
  41. * $DragonFly: src/usr.bin/make/var.c,v 1.224 2005/09/24 07:37:38 okumoto Exp $
  42. */
  43. /**
  44. * var.c --
  45. * Variable-handling functions
  46. *
  47. * Interface:
  48. * Var_Set Set the value of a variable in the given
  49. * context. The variable is created if it doesn't
  50. * yet exist. The value and variable name need not
  51. * be preserved.
  52. *
  53. * Var_Append Append more characters to an existing variable
  54. * in the given context. The variable needn't
  55. * exist already -- it will be created if it doesn't.
  56. * A space is placed between the old value and the
  57. * new one.
  58. *
  59. * Var_Value Return the value of a variable in a context or
  60. * NULL if the variable is undefined.
  61. *
  62. * Var_Subst Substitute named variable, or all variables if
  63. * NULL in a string using
  64. * the given context as the top-most one. If the
  65. * third argument is non-zero, Parse_Error is
  66. * called if any variables are undefined.
  67. *
  68. * Var_Parse Parse a variable expansion from a string and
  69. * return the result and the number of characters
  70. * consumed.
  71. *
  72. * Var_Delete Delete a variable in a context.
  73. *
  74. * Var_Init Initialize this module.
  75. *
  76. * Debugging:
  77. * Var_Dump Print out all variables defined in the given
  78. * context.
  79. *
  80. * XXX: There's a lot of duplication in these functions.
  81. */
  82. #include <assert.h>
  83. #include <ctype.h>
  84. #include <stdlib.h>
  85. #include <string.h>
  86. #include <sys/types.h>
  87. #include <regex.h>
  88. #include "buf.h"
  89. #include "config.h"
  90. #include "globals.h"
  91. #include "GNode.h"
  92. #include "job.h"
  93. #include "lst.h"
  94. #include "make.h"
  95. #include "parse.h"
  96. #include "str.h"
  97. #include "targ.h"
  98. #include "util.h"
  99. #include "var.h"
  100. /**
  101. *
  102. */
  103. typedef struct VarParser {
  104. const char *const input; /* pointer to input string */
  105. const char *ptr; /* current parser pos in input str */
  106. GNode *ctxt;
  107. bool err;
  108. bool execute;
  109. } VarParser;
  110. typedef struct Var {
  111. char *name; /* the variable's name */
  112. struct Buffer *val; /* its value */
  113. int flags; /* miscellaneous status flags */
  114. #define VAR_IN_USE 1 /* Variable's value currently being used.
  115. * Used to avoid recursion */
  116. #define VAR_JUNK 4 /* Variable is a junk variable that
  117. * should be destroyed when done with
  118. * it. Used by Var_Parse for undefined,
  119. * modified variables */
  120. #define VAR_TO_ENV 8 /* Place variable in environment */
  121. } Var;
  122. typedef struct {
  123. struct Buffer *lhs; /* String to match */
  124. struct Buffer *rhs; /* Replacement string (w/ &'s removed) */
  125. regex_t re;
  126. int nsub;
  127. regmatch_t *matches;
  128. int flags;
  129. #define VAR_SUB_GLOBAL 0x01 /* Apply substitution globally */
  130. #define VAR_SUB_ONE 0x02 /* Apply substitution to one word */
  131. #define VAR_SUB_MATCHED 0x04 /* There was a match */
  132. #define VAR_MATCH_START 0x08 /* Match at start of word */
  133. #define VAR_MATCH_END 0x10 /* Match at end of word */
  134. } VarPattern;
  135. typedef bool VarModifyProc(const char [], bool, struct Buffer *, void *);
  136. static char *VarParse(VarParser *, bool *);
  137. /*
  138. * This is a harmless return value for Var_Parse that can be used by Var_Subst
  139. * to determine if there was an error in parsing -- easier than returning
  140. * a flag, as things outside this module don't give a hoot.
  141. */
  142. char var_Error[] = "";
  143. /*
  144. * Similar to var_Error, but returned when the 'err' flag for Var_Parse is
  145. * set false. Why not just use a constant? Well, gcc likes to condense
  146. * identical string instances...
  147. */
  148. static char varNoError[] = "";
  149. /*
  150. * Internally, variables are contained in four different contexts.
  151. * 1) the environment. They may not be changed. If an environment
  152. * variable is appended-to, the result is placed in the global
  153. * context.
  154. * 2) the global context. Variables set in the Makefile are located in
  155. * the global context. It is the penultimate context searched when
  156. * substituting.
  157. * 3) the command-line context. All variables set on the command line
  158. * are placed in this context. They are UNALTERABLE once placed here.
  159. * 4) the local context. Each target has associated with it a context
  160. * list. On this list are located the structures describing such
  161. * local variables as $(@) and $(*)
  162. * The four contexts are searched in the reverse order from which they are
  163. * listed.
  164. */
  165. static GNode *VAR_ENV; /* variables from the environment */
  166. GNode *VAR_GLOBAL; /* variables from the makefile */
  167. GNode *VAR_CMD; /* variables defined on the command-line */
  168. bool oldVars; /* variable substitution style */
  169. bool checkEnvFirst; /* -e flag */
  170. /**
  171. * Create a Var object.
  172. *
  173. * @param name Name of variable.
  174. * @param value Value of variable.
  175. * @param flags Flags set on variable.
  176. */
  177. static Var *
  178. VarCreate(const char name[], const char value[], int flags)
  179. {
  180. Var *v;
  181. v = emalloc(sizeof(Var));
  182. v->name = estrdup(name);
  183. v->val = Buf_Init(0);
  184. v->flags = flags;
  185. if (value != NULL) {
  186. Buf_Append(v->val, value);
  187. }
  188. return (v);
  189. }
  190. /**
  191. * Destroy a Var object.
  192. *
  193. * @param v Object to destroy.
  194. * @param f true if internal buffer in Buffer object is to be
  195. * removed.
  196. */
  197. static void
  198. VarDestroy(Var *v, bool f)
  199. {
  200. Buf_Destroy(v->val, f);
  201. free(v->name);
  202. free(v);
  203. }
  204. /**
  205. * Remove the tail of the given word and place the result in the given
  206. * buffer.
  207. *
  208. * Results:
  209. * true if characters were added to the buffer (a space needs to be
  210. * added to the buffer before the next word).
  211. *
  212. * Side Effects:
  213. * The trimmed word is added to the buffer.
  214. */
  215. static bool
  216. VarHead(const char word[], bool addSpace, Buffer *buf, void *dummy __unused)
  217. {
  218. char *slash;
  219. slash = strrchr(word, '/');
  220. if (slash != NULL) {
  221. if (addSpace) {
  222. Buf_AddByte(buf, ' ');
  223. }
  224. Buf_AppendRange(buf, word, slash);
  225. } else {
  226. /*
  227. * If no directory part, give . (q.v. the POSIX standard)
  228. */
  229. if (addSpace) {
  230. Buf_Append(buf, " .");
  231. } else {
  232. Buf_AddByte(buf, '.');
  233. }
  234. }
  235. return (true);
  236. }
  237. /**
  238. * Remove the head of the given word and place the result in the given
  239. * buffer.
  240. *
  241. * Results:
  242. * true if characters were added to the buffer (a space needs to be
  243. * added to the buffer before the next word).
  244. *
  245. * Side Effects:
  246. * The trimmed word is added to the buffer.
  247. */
  248. static bool
  249. VarTail(const char word[], bool addSpace, Buffer *buf, void *dummy __unused)
  250. {
  251. const char *slash;
  252. if (addSpace) {
  253. Buf_AddByte(buf, ' ');
  254. }
  255. slash = strrchr(word, '/');
  256. if (slash != NULL) {
  257. slash++;
  258. Buf_Append(buf, slash);
  259. } else {
  260. Buf_Append(buf, word);
  261. }
  262. return (true);
  263. }
  264. /**
  265. * Place the suffix of the given word in the given buffer.
  266. *
  267. * Results:
  268. * true if characters were added to the buffer (a space needs to be
  269. * added to the buffer before the next word).
  270. *
  271. * Side Effects:
  272. * The suffix from the word is placed in the buffer.
  273. */
  274. static bool
  275. VarSuffix(const char word[], bool addSpace, Buffer *buf, void *dummy __unused)
  276. {
  277. const char *dot;
  278. dot = strrchr(word, '.');
  279. if (dot != NULL) {
  280. if (addSpace) {
  281. Buf_AddByte(buf, ' ');
  282. }
  283. dot++;
  284. Buf_Append(buf, dot);
  285. addSpace = true;
  286. }
  287. return (addSpace);
  288. }
  289. /**
  290. * Remove the suffix of the given word and place the result in the
  291. * buffer.
  292. *
  293. * Results:
  294. * true if characters were added to the buffer (a space needs to be
  295. * added to the buffer before the next word).
  296. *
  297. * Side Effects:
  298. * The trimmed word is added to the buffer.
  299. */
  300. static bool
  301. VarRoot(const char word[], bool addSpace, Buffer *buf, void *dummy __unused)
  302. {
  303. char *dot;
  304. if (addSpace) {
  305. Buf_AddByte(buf, ' ');
  306. }
  307. dot = strrchr(word, '.');
  308. if (dot != NULL) {
  309. Buf_AppendRange(buf, word, dot);
  310. } else {
  311. Buf_Append(buf, word);
  312. }
  313. return (true);
  314. }
  315. /**
  316. * Place the word in the buffer if it matches the given pattern.
  317. * Callback function for VarModify to implement the :M modifier.
  318. * A space will be added if requested. A pattern is supplied
  319. * which the word must match.
  320. *
  321. * Results:
  322. * true if a space should be placed in the buffer before the next
  323. * word.
  324. *
  325. * Side Effects:
  326. * The word may be copied to the buffer.
  327. */
  328. static bool
  329. VarMatch(const char word[], bool addSpace, Buffer *buf, void *pattern)
  330. {
  331. if (Str_Match(word, pattern)) {
  332. if (addSpace) {
  333. Buf_AddByte(buf, ' ');
  334. }
  335. addSpace = true;
  336. Buf_Append(buf, word);
  337. }
  338. return (addSpace);
  339. }
  340. /**
  341. * Place the word in the buffer if it matches the given pattern.
  342. * Callback function for VarModify to implement the System V %
  343. * modifiers. A space is added if requested.
  344. *
  345. * Results:
  346. * true if a space should be placed in the buffer before the next
  347. * word.
  348. *
  349. * Side Effects:
  350. * The word may be copied to the buffer.
  351. */
  352. static bool
  353. VarSYSVMatch(const char word[], bool addSpace, Buffer *buf, void *patp)
  354. {
  355. int len;
  356. const char *ptr;
  357. VarPattern *pat = (VarPattern *)patp;
  358. if (addSpace)
  359. Buf_AddByte(buf, ' ');
  360. addSpace = true;
  361. if ((ptr = Str_SYSVMatch(word, Buf_Data(pat->lhs), &len)) != NULL)
  362. Str_SYSVSubst(buf, Buf_Data(pat->rhs), ptr, len);
  363. else
  364. Buf_Append(buf, word);
  365. return (addSpace);
  366. }
  367. /**
  368. * Place the word in the buffer if it doesn't match the given pattern.
  369. * Callback function for VarModify to implement the :N modifier. A
  370. * space is added if requested.
  371. *
  372. * Results:
  373. * true if a space should be placed in the buffer before the next
  374. * word.
  375. *
  376. * Side Effects:
  377. * The word may be copied to the buffer.
  378. */
  379. static bool
  380. VarNoMatch(const char word[], bool addSpace, Buffer *buf, void *pattern)
  381. {
  382. if (!Str_Match(word, pattern)) {
  383. if (addSpace) {
  384. Buf_AddByte(buf, ' ');
  385. }
  386. addSpace = true;
  387. Buf_Append(buf, word);
  388. }
  389. return (addSpace);
  390. }
  391. /**
  392. * Perform a string-substitution on the given word, placing the
  393. * result in the passed buffer. A space is added if requested.
  394. *
  395. * Results:
  396. * true if a space is needed before more characters are added.
  397. */
  398. static bool
  399. VarSubstitute(const char word[], bool addSpace, Buffer *buf, void *patternp)
  400. {
  401. size_t wordLen; /* Length of word */
  402. const char *cp; /* General pointer */
  403. VarPattern *pattern = patternp;
  404. wordLen = strlen(word);
  405. if (1) { /* substitute in each word of the variable */
  406. /*
  407. * Break substitution down into simple anchored cases
  408. * and if none of them fits, perform the general substitution
  409. * case.
  410. */
  411. if ((pattern->flags & VAR_MATCH_START) &&
  412. (strncmp(word, Buf_Data(pattern->lhs),
  413. Buf_Size(pattern->lhs)) == 0)) {
  414. /*
  415. * Anchored at start and beginning of word matches
  416. * pattern.
  417. */
  418. if ((pattern->flags & VAR_MATCH_END) &&
  419. (wordLen == Buf_Size(pattern->lhs))) {
  420. /*
  421. * Also anchored at end and matches to the end
  422. * (word is same length as pattern) add space
  423. * and rhs only if rhs is non-null.
  424. */
  425. if (Buf_Size(pattern->rhs) != 0) {
  426. if (addSpace) {
  427. Buf_AddByte(buf, ' ');
  428. }
  429. addSpace = true;
  430. Buf_AppendBuf(buf, pattern->rhs);
  431. }
  432. } else if (pattern->flags & VAR_MATCH_END) {
  433. /*
  434. * Doesn't match to end -- copy word wholesale
  435. */
  436. goto nosub;
  437. } else {
  438. /*
  439. * Matches at start but need to copy in
  440. * trailing characters.
  441. */
  442. if ((Buf_Size(pattern->rhs) + wordLen -
  443. Buf_Size(pattern->lhs)) != 0) {
  444. if (addSpace) {
  445. Buf_AddByte(buf, ' ');
  446. }
  447. addSpace = true;
  448. }
  449. Buf_AppendBuf(buf, pattern->rhs);
  450. Buf_AddBytes(buf, wordLen -
  451. Buf_Size(pattern->lhs),
  452. (word + Buf_Size(pattern->lhs)));
  453. }
  454. } else if (pattern->flags & VAR_MATCH_START) {
  455. /*
  456. * Had to match at start of word and didn't -- copy
  457. * whole word.
  458. */
  459. goto nosub;
  460. } else if (pattern->flags & VAR_MATCH_END) {
  461. /*
  462. * Anchored at end, Find only place match could occur
  463. * (leftLen characters from the end of the word) and
  464. * see if it does. Note that because the $ will be
  465. * left at the end of the lhs, we have to use strncmp.
  466. */
  467. cp = word + (wordLen - Buf_Size(pattern->lhs));
  468. if ((cp >= word) && (strncmp(cp, Buf_Data(pattern->lhs),
  469. Buf_Size(pattern->lhs)) == 0)) {
  470. /*
  471. * Match found. If we will place characters in
  472. * the buffer, add a space before hand as
  473. * indicated by addSpace, then stuff in the
  474. * initial, unmatched part of the word followed
  475. * by the right-hand-side.
  476. */
  477. if ((cp - word) + Buf_Size(pattern->rhs) != 0) {
  478. if (addSpace) {
  479. Buf_AddByte(buf, ' ');
  480. }
  481. addSpace = true;
  482. }
  483. Buf_AppendRange(buf, word, cp);
  484. Buf_AppendBuf(buf, pattern->rhs);
  485. } else {
  486. /*
  487. * Had to match at end and didn't. Copy entire
  488. * word.
  489. */
  490. goto nosub;
  491. }
  492. } else {
  493. /*
  494. * Pattern is unanchored: search for the pattern in the
  495. * word using strstr(3), copying unmatched portions and
  496. * the right-hand-side for each match found, handling
  497. * non-global substitutions correctly, etc. When the
  498. * loop is done, any remaining part of the word (word
  499. * and wordLen are adjusted accordingly through the
  500. * loop) is copied straight into the buffer.
  501. * addSpace is set false as soon as a space is added
  502. * to the buffer.
  503. */
  504. bool done;
  505. size_t origSize;
  506. done = false;
  507. origSize = Buf_Size(buf);
  508. while (!done) {
  509. cp = strstr(word, Buf_Data(pattern->lhs));
  510. if (cp != NULL) {
  511. if (addSpace && (((cp - word) +
  512. Buf_Size(pattern->rhs)) != 0)) {
  513. Buf_AddByte(buf, ' ');
  514. addSpace = false;
  515. }
  516. Buf_AppendRange(buf, word, cp);
  517. Buf_AppendBuf(buf, pattern->rhs);
  518. wordLen -= (cp - word) +
  519. Buf_Size(pattern->lhs);
  520. word = cp + Buf_Size(pattern->lhs);
  521. if (wordLen == 0 || (pattern->flags &
  522. VAR_SUB_GLOBAL) == 0) {
  523. done = true;
  524. }
  525. } else {
  526. done = true;
  527. }
  528. }
  529. if (wordLen != 0) {
  530. if (addSpace) {
  531. Buf_AddByte(buf, ' ');
  532. }
  533. Buf_AddBytes(buf, wordLen, word);
  534. }
  535. /*
  536. * If added characters to the buffer, need to add a
  537. * space before we add any more. If we didn't add any,
  538. * just return the previous value of addSpace.
  539. */
  540. return ((Buf_Size(buf) != origSize) || addSpace);
  541. }
  542. /*
  543. * Common code for anchored substitutions:
  544. * addSpace was set true if characters were added to the buffer.
  545. */
  546. return (addSpace);
  547. }
  548. nosub:
  549. if (addSpace) {
  550. Buf_AddByte(buf, ' ');
  551. }
  552. Buf_AddBytes(buf, wordLen, word);
  553. return (true);
  554. }
  555. /**
  556. * Print the error caused by a regcomp or regexec call.
  557. *
  558. * Side Effects:
  559. * An error gets printed.
  560. */
  561. static void
  562. VarREError(int err, regex_t *pat, const char str[])
  563. {
  564. char *errbuf;
  565. int errlen;
  566. errlen = regerror(err, pat, 0, 0);
  567. errbuf = emalloc(errlen);
  568. regerror(err, pat, errbuf, errlen);
  569. Error("%s: %s", str, errbuf);
  570. free(errbuf);
  571. }
  572. /**
  573. * Perform a regex substitution on the given word, placing the
  574. * result in the passed buffer. A space is added if requested.
  575. *
  576. * Results:
  577. * true if a space is needed before more characters are added.
  578. */
  579. static bool
  580. VarRESubstitute(const char word[], bool addSpace, Buffer *buf, void *patternp)
  581. {
  582. VarPattern *pat;
  583. int xrv;
  584. const char *wp;
  585. char *rp;
  586. int added;
  587. int flags = 0;
  588. #define MAYBE_ADD_SPACE() \
  589. if (addSpace && !added) \
  590. Buf_AddByte(buf, ' '); \
  591. added = 1
  592. added = 0;
  593. wp = word;
  594. pat = patternp;
  595. if ((pat->flags & (VAR_SUB_ONE | VAR_SUB_MATCHED)) ==
  596. (VAR_SUB_ONE | VAR_SUB_MATCHED)) {
  597. xrv = REG_NOMATCH;
  598. } else {
  599. tryagain:
  600. xrv = regexec(&pat->re, wp, pat->nsub, pat->matches, flags);
  601. }
  602. switch (xrv) {
  603. case 0:
  604. pat->flags |= VAR_SUB_MATCHED;
  605. if (pat->matches[0].rm_so > 0) {
  606. MAYBE_ADD_SPACE();
  607. Buf_AddBytes(buf, pat->matches[0].rm_so, wp);
  608. }
  609. for (rp = Buf_Data(pat->rhs); *rp; rp++) {
  610. if ((*rp == '\\') && ((rp[1] == '&') || (rp[1] == '\\'))) {
  611. MAYBE_ADD_SPACE();
  612. Buf_AddByte(buf, rp[1]);
  613. rp++;
  614. } else if ((*rp == '&') ||
  615. ((*rp == '\\') && isdigit((unsigned char)rp[1]))) {
  616. int n;
  617. const char *subbuf;
  618. int sublen;
  619. char errstr[3];
  620. if (*rp == '&') {
  621. n = 0;
  622. errstr[0] = '&';
  623. errstr[1] = '\0';
  624. } else {
  625. n = rp[1] - '0';
  626. errstr[0] = '\\';
  627. errstr[1] = rp[1];
  628. errstr[2] = '\0';
  629. rp++;
  630. }
  631. if (n > pat->nsub) {
  632. Error("No subexpression %s",
  633. &errstr[0]);
  634. subbuf = "";
  635. sublen = 0;
  636. } else if ((pat->matches[n].rm_so == -1) &&
  637. (pat->matches[n].rm_eo == -1)) {
  638. Error("No match for subexpression %s",
  639. &errstr[0]);
  640. subbuf = "";
  641. sublen = 0;
  642. } else {
  643. subbuf = wp + pat->matches[n].rm_so;
  644. sublen = pat->matches[n].rm_eo -
  645. pat->matches[n].rm_so;
  646. }
  647. if (sublen > 0) {
  648. MAYBE_ADD_SPACE();
  649. Buf_AddBytes(buf, sublen, subbuf);
  650. }
  651. } else {
  652. MAYBE_ADD_SPACE();
  653. Buf_AddByte(buf, *rp);
  654. }
  655. }
  656. wp += pat->matches[0].rm_eo;
  657. if (pat->flags & VAR_SUB_GLOBAL) {
  658. flags |= REG_NOTBOL;
  659. if (pat->matches[0].rm_so == 0 &&
  660. pat->matches[0].rm_eo == 0) {
  661. MAYBE_ADD_SPACE();
  662. Buf_AddByte(buf, *wp);
  663. wp++;
  664. }
  665. if (*wp)
  666. goto tryagain;
  667. }
  668. if (*wp) {
  669. MAYBE_ADD_SPACE();
  670. Buf_Append(buf, wp);
  671. }
  672. break;
  673. default:
  674. VarREError(xrv, &pat->re, "Unexpected regex error");
  675. /* fall through */
  676. case REG_NOMATCH:
  677. if (*wp) {
  678. MAYBE_ADD_SPACE();
  679. Buf_Append(buf, wp);
  680. }
  681. break;
  682. }
  683. return (addSpace || added);
  684. }
  685. /**
  686. * Find a variable in a variable list.
  687. */
  688. static Var *
  689. VarLookup(Lst *vlist, const char name[])
  690. {
  691. LstNode *ln;
  692. LST_FOREACH(ln, vlist)
  693. if (strcmp(((const Var *)Lst_Datum(ln))->name, name) == 0)
  694. return (Lst_Datum(ln));
  695. return (NULL);
  696. }
  697. /**
  698. * Expand a variable name's embedded variables in the given context.
  699. *
  700. * Results:
  701. * The contents of name, possibly expanded.
  702. */
  703. static char *
  704. VarPossiblyExpand(const char name[], GNode *ctxt)
  705. {
  706. Buffer *buf;
  707. if (strchr(name, '$') != NULL) {
  708. buf = Var_Subst(name, ctxt, 0);
  709. return (Buf_Peel(buf));
  710. } else {
  711. return estrdup(name);
  712. }
  713. }
  714. /**
  715. * If the variable name begins with a '.', it could very well be
  716. * one of the local ones. We check the name against all the local
  717. * variables and substitute the short version in for 'name' if it
  718. * matches one of them.
  719. */
  720. static const char *
  721. VarLocal(const char name[])
  722. {
  723. if (name[0] == '.') {
  724. switch (name[1]) {
  725. case 'A':
  726. if (!strcmp(name, ".ALLSRC"))
  727. return (ALLSRC);
  728. if (!strcmp(name, ".ARCHIVE"))
  729. return (ARCHIVE);
  730. break;
  731. case 'I':
  732. if (!strcmp(name, ".IMPSRC"))
  733. return (IMPSRC);
  734. break;
  735. case 'M':
  736. if (!strcmp(name, ".MEMBER"))
  737. return (MEMBER);
  738. break;
  739. case 'O':
  740. if (!strcmp(name, ".OODATE"))
  741. return (OODATE);
  742. break;
  743. case 'P':
  744. if (!strcmp(name, ".PREFIX"))
  745. return (PREFIX);
  746. break;
  747. case 'T':
  748. if (!strcmp(name, ".TARGET"))
  749. return (TARGET);
  750. break;
  751. default:
  752. break;
  753. }
  754. }
  755. return (name);
  756. }
  757. /**
  758. * Find the given variable in the given context and the environment.
  759. *
  760. * Results:
  761. * A pointer to the structure describing the desired variable or
  762. * NULL if the variable does not exist.
  763. */
  764. static Var *
  765. VarFindEnv(const char name[], GNode *ctxt)
  766. {
  767. Var *var;
  768. name = VarLocal(name);
  769. if ((var = VarLookup(&ctxt->context, name)) != NULL)
  770. return (var);
  771. if ((var = VarLookup(&VAR_ENV->context, name)) != NULL)
  772. return (var);
  773. return (NULL);
  774. }
  775. /**
  776. * Look for the variable in the given context.
  777. */
  778. static Var *
  779. VarFindOnly(const char name[], GNode *ctxt)
  780. {
  781. return (VarLookup(&ctxt->context, VarLocal(name)));
  782. }
  783. /**
  784. * Look for the variable in all contexts.
  785. */
  786. static Var *
  787. VarFindAny(const char name[], GNode *ctxt)
  788. {
  789. bool localCheckEnvFirst;
  790. LstNode *ln;
  791. Var *var;
  792. name = VarLocal(name);
  793. /*
  794. * Note whether this is one of the specific variables we were told
  795. * through the -E flag to use environment-variable-override for.
  796. */
  797. localCheckEnvFirst = false;
  798. LST_FOREACH(ln, &envFirstVars) {
  799. if (strcmp(Lst_Datum(ln), name) == 0) {
  800. localCheckEnvFirst = true;
  801. break;
  802. }
  803. }
  804. /*
  805. * First look for the variable in the given context. If it's not there,
  806. * look for it in VAR_CMD, VAR_GLOBAL and the environment,
  807. * in that order, depending on the FIND_* flags in 'flags'
  808. */
  809. if ((var = VarLookup(&ctxt->context, name)) != NULL)
  810. return (var);
  811. /* not there - try command line context */
  812. if (ctxt != VAR_CMD) {
  813. if ((var = VarLookup(&VAR_CMD->context, name)) != NULL)
  814. return (var);
  815. }
  816. /* not there - try global context, but only if not -e/-E */
  817. if (ctxt != VAR_GLOBAL && (!checkEnvFirst && !localCheckEnvFirst)) {
  818. if ((var = VarLookup(&VAR_GLOBAL->context, name)) != NULL)
  819. return (var);
  820. }
  821. if ((var = VarLookup(&VAR_ENV->context, name)) != NULL)
  822. return (var);
  823. /* deferred check for the environment (in case of -e/-E) */
  824. if ((ctxt != VAR_GLOBAL) && (checkEnvFirst || localCheckEnvFirst)) {
  825. if ((var = VarLookup(&VAR_GLOBAL->context, name)) != NULL)
  826. return (var);
  827. }
  828. return (NULL);
  829. }
  830. /**
  831. * Add a new variable of name name and value val to the given context.
  832. *
  833. * Side Effects:
  834. * The new variable is placed at the front of the given context
  835. * The name and val arguments are duplicated so they may
  836. * safely be freed.
  837. */
  838. static void
  839. VarAdd(const char name[], const char val[], GNode *ctxt)
  840. {
  841. Lst_AtFront(&ctxt->context, VarCreate(name, val, 0));
  842. DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, name, val));
  843. }
  844. /**
  845. * Remove a variable from a context.
  846. *
  847. * Side Effects:
  848. * The Var structure is removed and freed.
  849. */
  850. void
  851. Var_Delete(const char name[], GNode *ctxt)
  852. {
  853. LstNode *ln;
  854. DEBUGF(VAR, ("%s:delete %s\n", ctxt->name, name));
  855. LST_FOREACH(ln, &ctxt->context) {
  856. if (strcmp(((const Var *)Lst_Datum(ln))->name, name) == 0) {
  857. VarDestroy(Lst_Datum(ln), true);
  858. Lst_Remove(&ctxt->context, ln);
  859. break;
  860. }
  861. }
  862. }
  863. /**
  864. * Set the variable name to the value val in the given context.
  865. *
  866. * Side Effects:
  867. * If the variable doesn't yet exist, a new record is created for it.
  868. * Else the old value is freed and the new one stuck in its place
  869. *
  870. * Notes:
  871. * The variable is searched for only in its context before being
  872. * created in that context. I.e. if the context is VAR_GLOBAL,
  873. * only VAR_GLOBAL->context is searched. Likewise if it is VAR_CMD, only
  874. * VAR_CMD->context is searched. This is done to avoid the literally
  875. * thousands of unnecessary strcmp's that used to be done to
  876. * set, say, $(@) or $(<).
  877. */
  878. void
  879. Var_Set(const char name[], const char val[], GNode *ctxt)
  880. {
  881. Var *v;
  882. char *n;
  883. /*
  884. * We only look for a variable in the given context since anything
  885. * set here will override anything in a lower context, so there's not
  886. * much point in searching them all just to save a bit of memory...
  887. */
  888. n = VarPossiblyExpand(name, ctxt);
  889. v = VarFindOnly(n, ctxt);
  890. if (v == NULL) {
  891. VarAdd(n, val, ctxt);
  892. if (ctxt == VAR_CMD) {
  893. /*
  894. * Any variables given on the command line
  895. * are automatically exported to the
  896. * environment (as per POSIX standard)
  897. */
  898. if (setenv(n, val, 1) == -1)
  899. Punt( "setenv: %s: can't allocate memory", n);
  900. }
  901. } else {
  902. Buf_Clear(v->val);
  903. Buf_Append(v->val, val);
  904. if (ctxt == VAR_CMD || (v->flags & VAR_TO_ENV)) {
  905. /*
  906. * Any variables given on the command line
  907. * are automatically exported to the
  908. * environment (as per POSIX standard)
  909. */
  910. char *exp_value;
  911. exp_value = Buf_Peel(Var_Subst(val, ctxt, false));
  912. if (setenv(n, exp_value, 1) == -1)
  913. Punt( "setenv: %s: can't allocate memory", n);
  914. free(exp_value);
  915. }
  916. }
  917. DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, n, val));
  918. free(n);
  919. }
  920. /**
  921. * Set the a global name variable to the value.
  922. */
  923. void
  924. Var_SetGlobal(const char name[], const char value[])
  925. {
  926. Var_Set(name, value, VAR_GLOBAL);
  927. }
  928. /**
  929. * Set the VAR_TO_ENV flag on a variable
  930. */
  931. void
  932. Var_SetEnv(const char name[], GNode *ctxt)
  933. {
  934. Var *v;
  935. v = VarFindOnly(name, VAR_CMD);
  936. if (v != NULL) {
  937. /*
  938. * Do not allow .EXPORT: to be set on variables
  939. * from the command line or MAKEFLAGS.
  940. */
  941. Error(
  942. "Warning: Did not set .EXPORTVAR: on %s because it "
  943. "is from the command line or MAKEFLAGS", name);
  944. return;
  945. }
  946. v = VarFindAny(name, ctxt);
  947. if (v == NULL) {
  948. Lst_AtFront(&VAR_ENV->context,
  949. VarCreate(name, NULL, VAR_TO_ENV));
  950. if (setenv(name, "", 1) == -1)
  951. Punt( "setenv: %s: can't allocate memory", name);
  952. Error("Warning: .EXPORTVAR: set on undefined variable %s", name);
  953. } else {
  954. if ((v->flags & VAR_TO_ENV) == 0) {
  955. char *value;
  956. value = Buf_Peel(Var_Subst(Buf_Data(v->val), ctxt, false));
  957. v->flags |= VAR_TO_ENV;
  958. if (setenv(v->name, value, 1) == -1)
  959. Punt( "setenv: %s: can't allocate memory", v->name);
  960. free(value);
  961. }
  962. }
  963. }
  964. /**
  965. * The variable of the given name has the given value appended to it in
  966. * the given context.
  967. *
  968. * Side Effects:
  969. * If the variable doesn't exist, it is created. Else the strings
  970. * are concatenated (with a space in between).
  971. *
  972. * Notes:
  973. * Only if the variable is being sought in the global context is the
  974. * environment searched.
  975. * XXX: Knows its calling circumstances in that if called with ctxt
  976. * an actual target, it will only search that context since only
  977. * a local variable could be being appended to. This is actually
  978. * a big win and must be tolerated.
  979. */
  980. void
  981. Var_Append(const char name[], const char val[], GNode *ctxt)
  982. {
  983. Var *v;
  984. char *n;
  985. n = VarPossiblyExpand(name, ctxt);
  986. if (ctxt == VAR_GLOBAL) {
  987. v = VarFindEnv(n, ctxt);
  988. } else {
  989. v = VarFindOnly(n, ctxt);
  990. }
  991. if (v == NULL) {
  992. VarAdd(n, val, ctxt);
  993. } else {
  994. Buf_AddByte(v->val, ' ');
  995. Buf_Append(v->val, val);
  996. DEBUGF(VAR, ("%s:%s = %s\n", ctxt->name, n, Buf_Data(v->val)));
  997. }
  998. free(n);
  999. }
  1000. /**
  1001. * Return the value of the named variable in the given context
  1002. *
  1003. * Results:
  1004. * The value if the variable exists, NULL if it doesn't.
  1005. */
  1006. const char *
  1007. Var_Value(const char name[], GNode *ctxt)
  1008. {
  1009. Var *v;
  1010. char *n;
  1011. n = VarPossiblyExpand(name, ctxt);
  1012. v = VarFindAny(n, ctxt);
  1013. free(n);
  1014. if (v == NULL) {
  1015. return (NULL);
  1016. } else {
  1017. return (Buf_Data(v->val));
  1018. }
  1019. }
  1020. /**
  1021. * Modify each of the words of the passed string using the given
  1022. * function. Used to implement all modifiers.
  1023. *
  1024. * Results:
  1025. * A string of all the words modified appropriately.
  1026. */
  1027. static char *
  1028. VarModify(const char str[], VarModifyProc *modProc, void *datum)
  1029. {
  1030. ArgArray aa;
  1031. Buffer *buf; /* Buffer for the new string */
  1032. int i;
  1033. bool addSpace; /*
  1034. * true if need to add a space to
  1035. * the buffer before adding the
  1036. * trimmed word
  1037. */
  1038. brk_string(&aa, str, false);
  1039. addSpace = false;
  1040. buf = Buf_Init(0);
  1041. for (i = 1; i < aa.argc; i++)
  1042. addSpace = (*modProc)(aa.argv[i], addSpace, buf, datum);
  1043. ArgArray_Done(&aa);
  1044. return (Buf_Peel(buf));
  1045. }
  1046. /**
  1047. * Sort the words in the string.
  1048. *
  1049. * Input:
  1050. * str String whose words should be sorted
  1051. * cmp A comparison function to control the ordering
  1052. *
  1053. * Results:
  1054. * A string containing the words sorted
  1055. */
  1056. static char *
  1057. VarSortWords(const char str[], int (*cmp)(const void *, const void *))
  1058. {
  1059. ArgArray aa;
  1060. Buffer *buf;
  1061. int i;
  1062. brk_string(&aa, str, false);
  1063. qsort(aa.argv + 1, aa.argc - 1, sizeof(char *), cmp);
  1064. buf = Buf_Init(0);
  1065. for (i = 1; i < aa.argc; i++) {
  1066. Buf_Append(buf, aa.argv[i]);
  1067. Buf_AddByte(buf, ((i < aa.argc - 1) ? ' ' : '\0'));
  1068. }
  1069. ArgArray_Done(&aa);
  1070. return (Buf_Peel(buf));
  1071. }
  1072. static int
  1073. SortIncreasing(const void *l, const void *r)
  1074. {
  1075. return (strcmp(*(const char* const*)l, *(const char* const*)r));
  1076. }
  1077. /**
  1078. * Pass through the tstr looking for 1) escaped delimiters,
  1079. * '$'s and backslashes (place the escaped character in
  1080. * uninterpreted) and 2) unescaped $'s that aren't before
  1081. * the delimiter (expand the variable substitution).
  1082. * Return the expanded string or NULL if the delimiter was missing
  1083. * If pattern is specified, handle escaped ampersands, and replace
  1084. * unescaped ampersands with the lhs of the pattern.
  1085. *
  1086. * Results:
  1087. * A string of all the words modified appropriately.
  1088. * If length is specified, return the string length of the buffer
  1089. * If flags is specified and the last character of the pattern is a
  1090. * $ set the VAR_MATCH_END bit of flags.
  1091. */
  1092. static Buffer *
  1093. VarGetPattern(VarParser *vp, int delim, int *flags, VarPattern *patt)
  1094. {
  1095. Buffer *buf;
  1096. buf = Buf_Init(0);
  1097. /*
  1098. * Skim through until the matching delimiter is found; pick up
  1099. * variable substitutions on the way. Also allow backslashes to quote
  1100. * the delimiter, $, and \, but don't touch other backslashes.
  1101. */
  1102. while (*vp->ptr != '\0') {
  1103. if (*vp->ptr == delim) {
  1104. return (buf);
  1105. } else if ((vp->ptr[0] == '\\') &&
  1106. ((vp->ptr[1] == delim) ||
  1107. (vp->ptr[1] == '\\') ||
  1108. (vp->ptr[1] == '$') ||
  1109. (vp->ptr[1] == '&' && patt != NULL))) {
  1110. vp->ptr++; /* consume backslash */
  1111. Buf_AddByte(buf, vp->ptr[0]);
  1112. vp->ptr++;
  1113. } else if (vp->ptr[0] == '$') {
  1114. if (vp->ptr[1] == delim) {
  1115. if (flags == NULL) {
  1116. Buf_AddByte(buf, vp->ptr[0]);
  1117. vp->ptr++;
  1118. } else {
  1119. /*
  1120. * Unescaped $ at end of patt =>
  1121. * anchor patt at end.
  1122. */
  1123. *flags |= VAR_MATCH_END;
  1124. vp->ptr++;
  1125. }
  1126. } else {
  1127. VarParser subvp = {
  1128. vp->ptr,
  1129. vp->ptr,
  1130. vp->ctxt,
  1131. vp->err,
  1132. vp->execute
  1133. };
  1134. char *rval;
  1135. bool rfree;
  1136. /*
  1137. * If unescaped dollar sign not
  1138. * before the delimiter, assume it's
  1139. * a variable substitution and
  1140. * recurse.
  1141. */
  1142. rval = VarParse(&subvp, &rfree);
  1143. Buf_Append(buf, rval);
  1144. if (rfree)
  1145. free(rval);
  1146. vp->ptr = subvp.ptr;
  1147. }
  1148. } else if (vp->ptr[0] == '&' && patt != NULL) {
  1149. Buf_AppendBuf(buf, patt->lhs);
  1150. vp->ptr++;
  1151. } else {
  1152. Buf_AddByte(buf, vp->ptr[0]);
  1153. vp->ptr++;
  1154. }
  1155. }
  1156. Buf_Destroy(buf, true);
  1157. return (NULL);
  1158. }
  1159. /**
  1160. * Make sure this variable is fully expanded.
  1161. */
  1162. static char *
  1163. VarExpand(Var *v, VarParser *vp)
  1164. {
  1165. char *value;
  1166. char *result;
  1167. if (v->flags & VAR_IN_USE) {
  1168. Fatal("Variable %s is recursive.", v->name);
  1169. /* NOTREACHED */
  1170. }
  1171. v->flags |= VAR_IN_USE;
  1172. /*
  1173. * Before doing any modification, we have to make sure the
  1174. * value has been fully expanded. If it looks like recursion
  1175. * might be necessary (there's a dollar sign somewhere in the
  1176. * variable's value) we just call Var_Subst to do any other
  1177. * substitutions that are necessary. Note that the value
  1178. * returned by Var_Subst will have been
  1179. * dynamically-allocated, so it will need freeing when we
  1180. * return.
  1181. */
  1182. value = Buf_Data(v->val);
  1183. if (strchr(value, '$') == NULL) {
  1184. result = strdup(value);
  1185. } else {
  1186. Buffer *buf;
  1187. buf = Var_Subst(value, vp->ctxt, vp->err);
  1188. result = Buf_Peel(buf);
  1189. }
  1190. v->flags &= ~VAR_IN_USE;
  1191. return (result);
  1192. }
  1193. /**
  1194. * Select only those words in value that match the modifier.
  1195. */
  1196. static char *
  1197. modifier_M(VarParser *vp, const char value[], char endc)
  1198. {
  1199. char *patt;
  1200. char *ptr;
  1201. char *newValue;
  1202. char modifier;
  1203. modifier = vp->ptr[0];
  1204. vp->ptr++; /* consume 'M' or 'N' */
  1205. /*
  1206. * Compress the \:'s out of the pattern, so allocate enough
  1207. * room to hold the uncompressed pattern and compress the
  1208. * pattern into that space.
  1209. */
  1210. patt = estrdup(vp->ptr);
  1211. ptr = patt;
  1212. while (vp->ptr[0] != '\0') {
  1213. if (vp->ptr[0] == endc || vp->ptr[0] == ':') {
  1214. break;
  1215. }
  1216. if (vp->ptr[0] == '\\' &&
  1217. (vp->ptr[1] == endc || vp->ptr[1] == ':')) {
  1218. vp->ptr++; /* consume backslash */
  1219. }
  1220. *ptr = vp->ptr[0];
  1221. ptr++;
  1222. vp->ptr++;
  1223. }
  1224. *ptr = '\0';
  1225. if (modifier == 'M') {
  1226. newValue = VarModify(value, VarMatch, patt);
  1227. } else {
  1228. newValue = VarModify(value, VarNoMatch, patt);
  1229. }
  1230. free(patt);
  1231. return (newValue);
  1232. }
  1233. /**
  1234. * Substitute the replacement string for the pattern. The substitution
  1235. * is applied to each word in value.
  1236. */
  1237. static char *
  1238. modifier_S(VarParser *vp, const char value[], Var *v)
  1239. {
  1240. VarPattern patt;
  1241. char delim;
  1242. char *newValue;
  1243. patt.flags = 0;
  1244. vp->ptr++; /* consume 'S' */
  1245. delim = *vp->ptr; /* used to find end of pattern */
  1246. vp->ptr++; /* consume 1st delim */
  1247. /*
  1248. * If pattern begins with '^', it is anchored to the start of the
  1249. * word -- skip over it and flag pattern.
  1250. */
  1251. if (*vp->ptr == '^') {
  1252. patt.flags |= VAR_MATCH_START;
  1253. vp->ptr++;
  1254. }
  1255. patt.lhs = VarGetPattern(vp, delim, &patt.flags, NULL);
  1256. if (patt.lhs == NULL) {
  1257. /*
  1258. * LHS didn't end with the delim, complain and exit.
  1259. */
  1260. Fatal("Unclosed substitution for %s (%c missing)",
  1261. v->name, delim);
  1262. }
  1263. vp->ptr++; /* consume 2nd delim */
  1264. patt.rhs = VarGetPattern(vp, delim, NULL, &patt);
  1265. if (patt.rhs == NULL) {
  1266. /*
  1267. * RHS didn't end with the delim, complain and exit.
  1268. */
  1269. Fatal("Unclosed substitution for %s (%c missing)",
  1270. v->name, delim);
  1271. }
  1272. vp->ptr++; /* consume last delim */
  1273. /*
  1274. * Check for global substitution. If 'g' after the final delimiter,
  1275. * substitution is global and is marked that way.
  1276. */
  1277. if (vp->ptr[0] == 'g') {
  1278. patt.flags |= VAR_SUB_GLOBAL;
  1279. vp->ptr++;
  1280. }
  1281. /*
  1282. * Global substitution of the empty string causes an infinite number
  1283. * of matches, unless anchored by '^' (start of string) or '$' (end
  1284. * of string). Catch the infinite substitution here. Note that flags
  1285. * can only contain the 3 bits we're interested in so we don't have
  1286. * to mask unrelated bits. We can test for equality.
  1287. */
  1288. if (Buf_Size(patt.lhs) == 0 && patt.flags == VAR_SUB_GLOBAL)
  1289. Fatal("Global substitution of the empty string");
  1290. newValue = VarModify(value, VarSubstitute, &patt);
  1291. /*
  1292. * Free the two strings.
  1293. */
  1294. free(patt.lhs);
  1295. free(patt.rhs);
  1296. return (newValue);
  1297. }
  1298. static char *
  1299. modifier_C(VarParser *vp, char value[], Var *v)
  1300. {
  1301. VarPattern patt;
  1302. char delim;
  1303. int error;
  1304. char *newValue;
  1305. patt.flags = 0;
  1306. vp->ptr++; /* consume 'C' */
  1307. delim = *vp->ptr; /* delimiter between sections */
  1308. vp->ptr++; /* consume 1st delim */
  1309. patt.lhs = VarGetPattern(vp, delim, NULL, NULL);
  1310. if (patt.lhs == NULL) {
  1311. Fatal("Unclosed substitution for %s (%c missing)",
  1312. v->name, delim);
  1313. }
  1314. vp->ptr++; /* consume 2st delim */
  1315. patt.rhs = VarGetPattern(vp, delim, NULL, NULL);
  1316. if (patt.rhs == NULL) {
  1317. Fatal("Unclosed substitution for %s (%c missing)",
  1318. v->name, delim);
  1319. }
  1320. vp->ptr++; /* consume last delim */
  1321. switch (*vp->ptr) {
  1322. case 'g':
  1323. patt.flags |= VAR_SUB_GLOBAL;
  1324. vp->ptr++; /* consume 'g' */
  1325. break;
  1326. case '1':
  1327. patt.flags |= VAR_SUB_ONE;
  1328. vp->ptr++; /* consume '1' */
  1329. break;
  1330. default:
  1331. break;
  1332. }
  1333. error = regcomp(&patt.re, Buf_Data(patt.lhs), REG_EXTENDED);
  1334. if (error) {
  1335. VarREError(error, &patt.re, "RE substitution error");
  1336. free(patt.rhs);
  1337. free(patt.lhs);
  1338. return (var_Error);
  1339. }
  1340. patt.nsub = patt.re.re_nsub + 1;
  1341. if (patt.nsub < 1)
  1342. patt.nsub = 1;
  1343. if (patt.nsub > 10)
  1344. patt.nsub = 10;
  1345. patt.matches = emalloc(patt.nsub * sizeof(regmatch_t));
  1346. newValue = VarModify(value, VarRESubstitute, &patt);
  1347. regfree(&patt.re);
  1348. free(patt.matches);
  1349. free(patt.rhs);
  1350. free(patt.lhs);
  1351. return (newValue);
  1352. }
  1353. static char *
  1354. sysVvarsub(VarParser *vp, char startc, Var *v, const char value[])
  1355. {
  1356. /*
  1357. * This can either be a bogus modifier or a System-V substitution
  1358. * command.
  1359. */
  1360. char endc;
  1361. VarPattern patt;
  1362. bool eqFound;
  1363. int cnt;
  1364. char *newStr;
  1365. const char *cp;
  1366. endc = (startc == OPEN_PAREN) ? CLOSE_PAREN : CLOSE_BRACE;
  1367. patt.flags = 0;
  1368. /*
  1369. * First we make a pass through the string trying to verify it is a
  1370. * SYSV-make-style translation: it must be: <string1>=<string2>)
  1371. */
  1372. eqFound = false;
  1373. cp = vp->ptr;
  1374. cnt = 1;
  1375. while (*cp != '\0' && cnt) {
  1376. if (*cp == '=') {
  1377. eqFound = true;
  1378. /* continue looking for endc */
  1379. } else if (*cp == endc)
  1380. cnt--;
  1381. else if (*cp == startc)
  1382. cnt++;
  1383. if (cnt)
  1384. cp++;
  1385. }
  1386. if (*cp == endc && eqFound) {
  1387. /*
  1388. * Now we break this sucker into the lhs and rhs.
  1389. */
  1390. patt.lhs = VarGetPattern(vp, '=', &patt.flags, NULL);
  1391. if (patt.lhs == NULL) {
  1392. Fatal("Unclosed substitution for %s (%c missing)",
  1393. v->name, '=');
  1394. }
  1395. vp->ptr++; /* consume '=' */
  1396. patt.rhs = VarGetPattern(vp, endc, NULL, &patt);
  1397. if (patt.rhs == NULL) {
  1398. Fatal("Unclosed substitution for %s (%c missing)",
  1399. v->name, endc);
  1400. }
  1401. /*
  1402. * SYSV modifications happen through the whole string. Note
  1403. * the pattern is anchored at the end.
  1404. */
  1405. newStr = VarModify(value, VarSYSVMatch, &patt);
  1406. free(patt.lhs);
  1407. free(patt.rhs);
  1408. } else {
  1409. Error("Unknown modifier '%c'\n", *vp->ptr);
  1410. vp->ptr++;
  1411. while (*vp->ptr != '\0') {
  1412. if (*vp->ptr == endc && *vp->ptr == ':') {
  1413. break;
  1414. }
  1415. vp->ptr++;
  1416. }
  1417. newStr = var_Error;
  1418. }
  1419. return (newStr);
  1420. }
  1421. /**
  1422. * Quote shell meta-characters in the string
  1423. *
  1424. * Results:
  1425. * The quoted string
  1426. */
  1427. static char *
  1428. Var_Quote(const char str[])
  1429. {
  1430. Buffer *buf;
  1431. /* This should cover most shells :-( */
  1432. static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
  1433. buf = Buf_Init(MAKE_BSIZE);
  1434. for (; *str; str++) {
  1435. if (strchr(meta, *str) != NULL)
  1436. Buf_AddByte(buf, '\\');
  1437. Buf_AddByte(buf, *str);
  1438. }
  1439. return (Buf_Peel(buf));
  1440. }
  1441. /*
  1442. * Now we need to apply any modifiers the user wants applied.
  1443. * These are:
  1444. * :M<pattern>
  1445. * words which match the given <pattern>.
  1446. * <pattern> is of the standard file
  1447. * wildcarding form.
  1448. * :S<d><pat1><d><pat2><d>[g]
  1449. * Substitute <pat2> for <pat1> in the value
  1450. * :C<d><pat1><d><pat2><d>[g]
  1451. * Substitute <pat2> for regex <pat1> in the value
  1452. * :H Substitute the head of each word
  1453. * :T Substitute the tail of each word
  1454. * :E Substitute the extension (minus '.') of
  1455. * each word
  1456. * :R Substitute the root of each word
  1457. * (pathname minus the suffix).
  1458. * :lhs=rhs
  1459. * Like :S, but the rhs goes to the end of
  1460. * the invocation.
  1461. * :U Converts variable to upper-case.
  1462. * :L Converts variable to lower-case.
  1463. *
  1464. * XXXHB update this comment or remove it and point to the man page.
  1465. */
  1466. static char *
  1467. ParseModifier(VarParser *vp, char startc, Var *v, bool *freeResult)
  1468. {
  1469. char *value;
  1470. char endc;
  1471. value = VarExpand(v, vp);
  1472. *freeResult = true;
  1473. endc = (startc == OPEN_PAREN) ? CLOSE_PAREN : CLOSE_BRACE;
  1474. vp->ptr++; /* consume first colon */
  1475. while (*vp->ptr != '\0') {
  1476. char *newStr; /* New value to return */
  1477. if (*vp->ptr == endc) {
  1478. return (value);
  1479. }
  1480. DEBUGF(VAR, ("Applying :%c to \"%s\"\n", *vp->ptr, value));
  1481. switch (*vp->ptr) {
  1482. case 'N':
  1483. case 'M':
  1484. newStr = modifier_M(vp, value, endc);
  1485. break;
  1486. case 'S':
  1487. newStr = modifier_S(vp, value, v);
  1488. break;
  1489. case 'C':
  1490. newStr = modifier_C(vp, value, v);
  1491. break;
  1492. default:
  1493. if (vp->ptr[1] != endc && vp->ptr[1] != ':') {
  1494. #ifdef SUNSHCMD
  1495. if ((vp->ptr[0] == 's') &&
  1496. (vp->ptr[1] == 'h') &&
  1497. (vp->ptr[2] == endc || vp->ptr[2] == ':')) {
  1498. const char *error;
  1499. if (vp->execute) {
  1500. newStr = Buf_Peel(
  1501. Cmd_Exec(value, &error));
  1502. } else {
  1503. newStr = estrdup("");
  1504. }
  1505. if (error)
  1506. Error(error, value);
  1507. vp->ptr += 2;
  1508. } else
  1509. #endif
  1510. {
  1511. newStr = sysVvarsub(vp, startc, v, value);
  1512. }
  1513. break;
  1514. }
  1515. switch (vp->ptr[0]) {
  1516. case 'L':
  1517. {
  1518. const char *cp;
  1519. Buffer *buf;
  1520. buf = Buf_Init(MAKE_BSIZE);
  1521. for (cp = value; *cp; cp++)
  1522. Buf_AddByte(buf, tolower((unsigned char)*cp));
  1523. newStr = Buf_Peel(buf);
  1524. vp->ptr++;
  1525. break;
  1526. }
  1527. case 'O':
  1528. newStr = VarSortWords(value, SortIncreasing);
  1529. vp->ptr++;
  1530. break;
  1531. case 'Q':
  1532. newStr = Var_Quote(value);
  1533. vp->ptr++;
  1534. break;
  1535. case 'T':
  1536. newStr = VarModify(value, VarTail, NULL);
  1537. vp->ptr++;
  1538. break;
  1539. case 'U':
  1540. {
  1541. const char *cp;
  1542. Buffer *buf;
  1543. buf = Buf_Init(MAKE_BSIZE);
  1544. for (cp = value; *cp; cp++)
  1545. Buf_AddByte(buf, toupper((unsigned char)*cp));
  1546. newStr = Buf_Peel(buf);
  1547. vp->ptr++;
  1548. break;
  1549. }
  1550. case 'H':
  1551. newStr = VarModify(value, VarHead, NULL);
  1552. vp->ptr++;
  1553. break;
  1554. case 'E':
  1555. newStr = VarModify(value, VarSuffix, NULL);
  1556. vp->ptr++;
  1557. break;
  1558. case 'R':
  1559. newStr = VarModify(value, VarRoot, NULL);
  1560. vp->ptr++;
  1561. break;
  1562. default:
  1563. newStr = sysVvarsub(vp, startc, v, value);
  1564. break;
  1565. }
  1566. break;
  1567. }
  1568. DEBUGF(VAR, ("Result is \"%s\"\n", newStr));
  1569. if (*freeResult) {
  1570. free(value);
  1571. }
  1572. value = newStr;
  1573. *freeResult = (value == var_Error) ? false : true;
  1574. if (vp->ptr[0] == ':') {
  1575. vp->ptr++; /* consume colon */
  1576. }
  1577. }
  1578. return (value);
  1579. }
  1580. static char *
  1581. ParseRestModifier(VarParser *vp, char startc, Buffer *buf, bool *freeResult)
  1582. {
  1583. const char *vname;
  1584. size_t vlen;
  1585. Var *v;
  1586. char *value;
  1587. vname = Buf_Data(buf);
  1588. vlen = Buf_Size(buf);
  1589. v = VarFindAny(vname, vp->ctxt);
  1590. if (v != NULL) {
  1591. value = ParseModifier(vp, startc, v, freeResult);
  1592. return (value);
  1593. }
  1594. if ((vp->ctxt == VAR_CMD) || (vp->ctxt == VAR_GLOBAL)) {
  1595. size_t consumed;
  1596. /*
  1597. * Still need to get to the end of the variable
  1598. * specification, so kludge up a Var structure for the
  1599. * modifications
  1600. */
  1601. v = VarCreate(vname, NULL, VAR_JUNK);
  1602. value = ParseModifier(vp, startc, v, freeResult);
  1603. if (*freeResult) {
  1604. free(value);
  1605. }
  1606. VarDestroy(v, true);
  1607. consumed = vp->ptr - vp->input + 1;
  1608. /*
  1609. * If substituting a local variable in a non-local context,
  1610. * assume it's for dynamic source stuff. We have to handle
  1611. * this specially and return the longhand for the variable
  1612. * with the dollar sign escaped so it makes it back to the
  1613. * caller. Only four of the local variables are treated
  1614. * specially as they are the only four that will be set when
  1615. * dynamic sources are expanded.
  1616. */
  1617. if (vlen == 1 ||
  1618. (vlen == 2 && (vname[1] == 'F' || vname[1] == 'D'))) {
  1619. if (strchr("!%*@", vname[0]) != NULL) {
  1620. value = emalloc(consumed + 1);
  1621. strncpy(value, vp->input, consumed);
  1622. value[consumed] = '\0';
  1623. *freeResult = true;
  1624. return (value);
  1625. }
  1626. }
  1627. if (vlen > 2 &&
  1628. vname[0] == '.' &&
  1629. isupper((unsigned char)vname[1])) {
  1630. if ((strncmp(vname, ".TARGET", vlen - 1) == 0) ||
  1631. (strncmp(vname, ".ARCHIVE", vlen - 1) == 0) ||
  1632. (strncmp(vname, ".PREFIX", vlen - 1) == 0) ||
  1633. (strncmp(vname, ".MEMBER", vlen - 1) == 0)) {
  1634. value = emalloc(consumed + 1);
  1635. strncpy(value, vp->input, consumed);
  1636. value[consumed] = '\0';
  1637. *freeResult = true;
  1638. return (value);
  1639. }
  1640. }
  1641. *freeResult = false;
  1642. return (vp->err ? var_Error : varNoError);
  1643. } else {
  1644. /*
  1645. * Check for D and F forms of local variables since we're in
  1646. * a local context and the name is the right length.
  1647. */
  1648. if (vlen == 2 &&
  1649. (vname[1] == 'F' || vname[1] == 'D') &&
  1650. (strchr("!%*<>@", vname[0]) != NULL)) {
  1651. char name[2];
  1652. name[0] = vname[0];
  1653. name[1] = '\0';
  1654. v = VarFindOnly(name, vp->ctxt);
  1655. if (v != NULL) {
  1656. value = ParseModifier(vp, startc, v, freeResult);
  1657. return (value);
  1658. }
  1659. }
  1660. /*
  1661. * Still need to get to the end of the variable
  1662. * specification, so kludge up a Var structure for the
  1663. * modifications
  1664. */
  1665. v = VarCreate(vname, NULL, VAR_JUNK);
  1666. value = ParseModifier(vp, startc, v, freeResult);
  1667. if (*freeResult) {
  1668. free(value);
  1669. }
  1670. VarDestroy(v, true);
  1671. *freeResult = false;
  1672. return (vp->err ? var_Error : varNoError);
  1673. }
  1674. }
  1675. static char *
  1676. ParseRestEnd(VarParser *vp, Buffer *buf, bool *freeResult)
  1677. {
  1678. const char *vname;
  1679. size_t vlen;
  1680. Var *v;
  1681. char *value;
  1682. vname = Buf_Data(buf);
  1683. vlen = Buf_Size(buf);
  1684. v = VarFindAny(vname, vp->ctxt);
  1685. if (v != NULL) {
  1686. value = VarExpand(v, vp);
  1687. *freeResult = true;
  1688. return (value);
  1689. }
  1690. if ((vp->ctxt == VAR_CMD) || (vp->ctxt == VAR_GLOBAL)) {
  1691. size_t consumed = vp->ptr - vp->input + 1;
  1692. /*
  1693. * If substituting a local variable in a non-local context,
  1694. * assume it's for dynamic source stuff. We have to handle
  1695. * this specially and return the longhand for the variable
  1696. * with the dollar sign escaped so it makes it back to the
  1697. * caller. Only four of the local variables are treated
  1698. * specially as they are the only four that will be set when
  1699. * dynamic sources are expanded.
  1700. */
  1701. if (vlen == 1 ||
  1702. (vlen == 2 && (vname[1] == 'F' || vname[1] == 'D'))) {
  1703. if (strchr("!%*@", vname[0]) != NULL) {
  1704. value = emalloc(consumed + 1);
  1705. strncpy(value, vp->input, consumed);
  1706. value[consumed] = '\0';
  1707. *freeResult = true;
  1708. return (value);
  1709. }
  1710. }
  1711. if (vlen > 2 &&
  1712. vname[0] == '.' &&
  1713. isupper((unsigned char)vname[1])) {
  1714. if ((strncmp(vname, ".TARGET", vlen - 1) == 0) ||
  1715. (strncmp(vname, ".ARCHIVE", vlen - 1) == 0) ||
  1716. (strncmp(vname, ".PREFIX", vlen - 1) == 0) ||
  1717. (strncmp(vname, ".MEMBER", vlen - 1) == 0)) {
  1718. value = emalloc(consumed + 1);
  1719. strncpy(value, vp->input, consumed);
  1720. value[consumed] = '\0';
  1721. *freeResult = true;
  1722. return (value);
  1723. }
  1724. }
  1725. } else {
  1726. /*
  1727. * Check for D and F forms of local variables since we're in
  1728. * a local context and the name is the right length.
  1729. */
  1730. if (vlen == 2 &&
  1731. (vname[1] == 'F' || vname[1] == 'D') &&
  1732. (strchr("!%*<>@", vname[0]) != NULL)) {
  1733. char name[2];
  1734. name[0] = vname[0];
  1735. name[1] = '\0';
  1736. v = VarFindOnly(name, vp->ctxt);
  1737. if (v != NULL) {
  1738. char *val;
  1739. /*
  1740. * No need for nested expansion or anything,
  1741. * as we're the only one who sets these
  1742. * things and we sure don't put nested
  1743. * invocations in them...
  1744. */
  1745. val = Buf_Data(v->val);
  1746. if (vname[1] == 'D') {
  1747. val = VarModify(val, VarHead, NULL);
  1748. } else {
  1749. val = VarModify(val, VarTail, NULL);
  1750. }
  1751. *freeResult = true;
  1752. return (val);
  1753. }
  1754. }
  1755. }
  1756. *freeResult = false;
  1757. return (vp->err ? var_Error : varNoError);
  1758. }
  1759. /**
  1760. * Parse a multi letter variable name, and return it's value.
  1761. */
  1762. static char *
  1763. VarParseLong(VarParser *vp, bool *freeResult)
  1764. {
  1765. Buffer *buf;
  1766. char startc;
  1767. char endc;
  1768. char *value;
  1769. buf = Buf_Init(MAKE_BSIZE);
  1770. startc = vp->ptr[0];
  1771. vp->ptr++; /* consume opening paren or brace */
  1772. endc = (startc == OPEN_PAREN) ? CLOSE_PAREN : CLOSE_BRACE;
  1773. /*
  1774. * Process characters until we reach an end character or a colon,
  1775. * replacing embedded variables as we go.
  1776. */
  1777. while (*vp->ptr != '\0') {
  1778. if (*vp->ptr == endc) {
  1779. value = ParseRestEnd(vp, buf, freeResult);
  1780. vp->ptr++; /* consume closing paren or brace */
  1781. Buf_Destroy(buf, true);
  1782. return (value);
  1783. } else if (*vp->ptr == ':') {
  1784. value = ParseRestModifier(vp, startc, buf, freeResult);
  1785. vp->ptr++; /* consume closing paren or brace */
  1786. Buf_Destroy(buf, true);
  1787. return (value);
  1788. } else if (*vp->ptr == '$') {
  1789. VarParser subvp = {
  1790. vp->ptr,
  1791. vp->ptr,
  1792. vp->ctxt,
  1793. vp->err,
  1794. vp->execute
  1795. };
  1796. char *rval;
  1797. bool rfree;
  1798. rval = VarParse(&subvp, &rfree);
  1799. if (rval == var_Error) {
  1800. Fatal("Error expanding embedded variable.");
  1801. }
  1802. Buf_Append(buf, rval);
  1803. if (rfree)
  1804. free(rval);
  1805. vp->ptr = subvp.ptr;
  1806. } else {
  1807. Buf_AddByte(buf, *vp->ptr);
  1808. vp->ptr++;
  1809. }
  1810. }
  1811. /* If we did not find the end character, return var_Error */
  1812. Buf_Destroy(buf, true);
  1813. *freeResult = false;
  1814. return (var_Error);
  1815. }
  1816. /**
  1817. * Parse a single letter variable name, and return it's value.
  1818. */
  1819. static char *
  1820. VarParseShort(VarParser *vp, bool *freeResult)
  1821. {
  1822. char vname[2];
  1823. Var *v;
  1824. char *value;
  1825. vname[0] = vp->ptr[0];
  1826. vname[1] = '\0';
  1827. vp->ptr++; /* consume single letter */
  1828. v = VarFindAny(vname, vp->ctxt);
  1829. if (v != NULL) {
  1830. value = VarExpand(v, vp);
  1831. *freeResult = true;
  1832. return (value);
  1833. }
  1834. /*
  1835. * If substituting a local variable in a non-local context, assume
  1836. * it's for dynamic source stuff. We have to handle this specially
  1837. * and return the longhand for the variable with the dollar sign
  1838. * escaped so it makes it back to the caller. Only four of the local
  1839. * variables are treated specially as they are the only four that
  1840. * will be set when dynamic sources are expanded.
  1841. */
  1842. if ((vp->ctxt == VAR_CMD) || (vp->ctxt == VAR_GLOBAL)) {
  1843. /* XXX: It looks like $% and $! are reversed here */
  1844. switch (vname[0]) {
  1845. case '@':
  1846. *freeResult = true;
  1847. return (estrdup("$(.TARGET)"));
  1848. case '%':
  1849. *freeResult = true;
  1850. return (estrdup("$(.ARCHIVE)"));
  1851. case '*':
  1852. *freeResult = true;
  1853. return (estrdup("$(.PREFIX)"));
  1854. case '!':
  1855. *freeResult = true;
  1856. return (estrdup("$(.MEMBER)"));
  1857. default:
  1858. *freeResult = false;
  1859. return (vp->err ? var_Error : varNoError);
  1860. }
  1861. }
  1862. /* Variable name was not found. */
  1863. *freeResult = false;
  1864. return (vp->err ? var_Error : varNoError);
  1865. }
  1866. static char *
  1867. VarParse(VarParser *vp, bool *freeResult)
  1868. {
  1869. vp->ptr++; /* consume '$' or last letter of …

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