PageRenderTime 58ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/opensource.apple.com/source/bsdmake/bsdmake-24/var.c?txt

#
Unknown | 2612 lines | 2324 code | 288 blank | 0 comment | 0 complexity | 2be3238cab40c827e8df704bd1f17d55 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, GPL-2.0, BSD-3-Clause, GPL-3.0, MPL-2.0, LGPL-2.0, LGPL-2.1, CC-BY-SA-3.0, IPL-1.0, ISC, AGPL-1.0, AGPL-3.0, JSON, Apache-2.0, 0BSD

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

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