Deleted Added
full compact
parse.c (144787) parse.c (144894)
1/*-
2 * Copyright (c) 1988, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1989 by Berkeley Softworks
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor.

--- 25 unchanged lines hidden (view full) ---

34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)parse.c 8.3 (Berkeley) 3/19/94
39 */
40
41#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1988, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1989 by Berkeley Softworks
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor.

--- 25 unchanged lines hidden (view full) ---

34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)parse.c 8.3 (Berkeley) 3/19/94
39 */
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: head/usr.bin/make/parse.c 144787 2005-04-08 09:03:40Z harti $");
42__FBSDID("$FreeBSD: head/usr.bin/make/parse.c 144894 2005-04-11 07:20:10Z harti $");
43
44/*-
45 * parse.c --
46 * Functions to parse a makefile.
47 *
48 * One function, Parse_Init, must be called before any functions
49 * in this module are used. After that, the function Parse_File is the
50 * main entry point and controls most of the other functions in this

--- 186 unchanged lines hidden (view full) ---

237 { ".SHELL", ExShell, 0 },
238 { ".SILENT", Silent, OP_SILENT },
239 { ".SINGLESHELL", SingleShell, 0 },
240 { ".SUFFIXES", Suffixes, 0 },
241 { ".USE", Attribute, OP_USE },
242 { ".WAIT", Wait, 0 },
243};
244
43
44/*-
45 * parse.c --
46 * Functions to parse a makefile.
47 *
48 * One function, Parse_Init, must be called before any functions
49 * in this module are used. After that, the function Parse_File is the
50 * main entry point and controls most of the other functions in this

--- 186 unchanged lines hidden (view full) ---

237 { ".SHELL", ExShell, 0 },
238 { ".SILENT", Silent, OP_SILENT },
239 { ".SINGLESHELL", SingleShell, 0 },
240 { ".SUFFIXES", Suffixes, 0 },
241 { ".USE", Attribute, OP_USE },
242 { ".WAIT", Wait, 0 },
243};
244
245/*
246 * Directive table. We use a hash table. This hash table has been generated
247 * with mph which can be found on the usual GNU mirrors. If you change the
248 * directives (adding, deleting, reordering) you need to create a new table
249 * and hash function (directive_hash). The command line to generate the
250 * table is:
251 *
252 * mph -d2 -m1 <tab | emitc -l -s
253 *
254 * Where tab is a file containing just the directive strings, one per line.
255 *
256 * While inporting the result of this the following changes have been made
257 * to the generated code:
258 *
259 * prefix the names of the g, T0 and T1 arrays with 'directive_'.
260 *
261 * make the type of the tables 'const [un]signed char'.
262 *
263 * make the hash function use the length for termination,
264 * not the trailing '\0'.
265 */
266static void parse_include(char *, int, int);
267static void parse_message(char *, int, int);
268static void parse_undef(char *, int, int);
269static void parse_for(char *, int, int);
270static void parse_endfor(char *, int, int);
271
272static const signed char directive_g[] = {
273 16, 0, -1, 14, 5, 2, 2, -1, 0, 0,
274 -1, -1, 16, 11, -1, 15, -1, 14, 7, -1,
275 8, 6, 1, -1, -1, 0, 4, 6, -1, 0,
276 0, 2, 0, 13, -1, 14, -1, 0,
277};
278
279static const unsigned char directive_T0[] = {
280 11, 25, 14, 30, 14, 26, 23, 15, 9, 37,
281 27, 32, 27, 1, 17, 27, 35, 13, 8, 22,
282 8, 28, 7,
283};
284
285static const unsigned char directive_T1[] = {
286 19, 20, 31, 17, 29, 2, 7, 12, 1, 31,
287 11, 18, 11, 20, 10, 2, 15, 19, 4, 10,
288 13, 36, 3,
289};
290
291static const struct directive {
292 const char *name;
293 int code;
294 Boolean skip_flag; /* execute even when skipped */
295 void (*func)(char *, int, int);
296} directives[] = {
297 { "elif", COND_ELIF, TRUE, Cond_If },
298 { "elifdef", COND_ELIFDEF, TRUE, Cond_If },
299 { "elifmake", COND_ELIFMAKE, TRUE, Cond_If },
300 { "elifndef", COND_ELIFNDEF, TRUE, Cond_If },
301 { "elifnmake", COND_ELIFNMAKE, TRUE, Cond_If },
302 { "else", COND_ELSE, TRUE, Cond_Else },
303 { "endfor", 0, FALSE, parse_endfor },
304 { "endif", COND_ENDIF, TRUE, Cond_Endif },
305 { "error", 1, FALSE, parse_message },
306 { "for", 0, FALSE, parse_for },
307 { "if", COND_IF, TRUE, Cond_If },
308 { "ifdef", COND_IFDEF, TRUE, Cond_If },
309 { "ifmake", COND_IFMAKE, TRUE, Cond_If },
310 { "ifndef", COND_IFNDEF, TRUE, Cond_If },
311 { "ifnmake", COND_IFNMAKE, TRUE, Cond_If },
312 { "include", 0, FALSE, parse_include },
313 { "undef", 0, FALSE, parse_undef },
314 { "warning", 0, FALSE, parse_message },
315};
316#define NDIRECTS (sizeof(directives) / sizeof(directives[0]))
317
245/*-
246 *----------------------------------------------------------------------
247 * ParseFindKeyword --
248 * Look in the table of keywords for one matching the given string.
249 *
250 * Results:
251 * The index of the keyword, or -1 if it isn't there.
252 *

--- 1293 unchanged lines hidden (view full) ---

1546 */
1547void
1548Parse_AddIncludeDir(char *dir)
1549{
1550
1551 Path_AddDir(&parseIncPath, dir);
1552}
1553
318/*-
319 *----------------------------------------------------------------------
320 * ParseFindKeyword --
321 * Look in the table of keywords for one matching the given string.
322 *
323 * Results:
324 * The index of the keyword, or -1 if it isn't there.
325 *

--- 1293 unchanged lines hidden (view full) ---

1619 */
1620void
1621Parse_AddIncludeDir(char *dir)
1622{
1623
1624 Path_AddDir(&parseIncPath, dir);
1625}
1626
1554/*---------------------------------------------------------------------
1555 * ParseDoError --
1556 * Handle error directive
1557 *
1558 * The input is the line minus the ".error". We substitute variables,
1559 * print the message and exit(1) or just print a warning if the ".error"
1560 * directive is malformed.
1561 *
1562 *---------------------------------------------------------------------
1563 */
1564static void
1565ParseDoError(char *errmsg)
1566{
1567 Buffer *buf;
1568
1569 if (!isspace((unsigned char)*errmsg)) {
1570 Parse_Error(PARSE_WARNING, "invalid syntax: .error%s", errmsg);
1571 return;
1572 }
1573
1574 while (isspace((unsigned char)*errmsg))
1575 errmsg++;
1576
1577 buf = Var_Subst(NULL, errmsg, VAR_GLOBAL, FALSE);
1578 Parse_Error(PARSE_FATAL, "%s", Buf_Data(buf));
1579 Buf_Destroy(buf, TRUE);
1580
1581 /* Terminate immediately. */
1582 exit(1);
1583}
1584
1585/*---------------------------------------------------------------------
1586 * ParseDoWarning --
1587 * Handle warning directive
1588 *
1589 * The input is the line minus the ".warning". We substitute variables
1590 * and print the message or just print a warning if the ".warning"
1591 * directive is malformed.
1592 *
1593 *---------------------------------------------------------------------
1594 */
1595static void
1596ParseDoWarning(char *warnmsg)
1597{
1598 Buffer *buf;
1599
1600 if (!isspace((unsigned char)*warnmsg)) {
1601 Parse_Error(PARSE_WARNING, "invalid syntax: .warning%s",
1602 warnmsg);
1603 return;
1604 }
1605
1606 while (isspace((unsigned char)*warnmsg))
1607 warnmsg++;
1608
1609 buf = Var_Subst(NULL, warnmsg, VAR_GLOBAL, FALSE);
1610 Parse_Error(PARSE_WARNING, "%s", Buf_Data(buf));
1611 Buf_Destroy(buf, TRUE);
1612}
1613
1614/*-
1615 *---------------------------------------------------------------------
1627/*-
1628 *---------------------------------------------------------------------
1616 * ParseDoInclude --
1617 * Push to another file.
1618 *
1619 * The input is the line minus the #include. A file spec is a string
1620 * enclosed in <> or "". The former is looked for only in sysIncPath.
1621 * The latter in . and the directories specified by -I command line
1622 * options
1623 *
1624 * Results:
1625 * None
1626 *
1627 * Side Effects:
1628 * A structure is added to the includes Lst and readProc.
1629 *---------------------------------------------------------------------
1630 */
1631static void
1632ParseDoInclude(char *file)
1633{
1634 char *fullname; /* full pathname of file */
1635 char endc; /* the character which ends the file spec */
1636 char *cp; /* current position in file spec */
1637 Boolean isSystem; /* TRUE if makefile is a system makefile */
1638 Buffer *buf;
1639
1640 /*
1641 * Skip to delimiter character so we know where to look
1642 */
1643 while (*file == ' ' || *file == '\t') {
1644 file++;
1645 }
1646
1647 if (*file != '"' && *file != '<') {
1648 Parse_Error(PARSE_FATAL,
1649 ".include filename must be delimited by '\"' or '<'");
1650 return;
1651 }
1652
1653 /*
1654 * Set the search path on which to find the include file based on the
1655 * characters which bracket its name. Angle-brackets imply it's
1656 * a system Makefile while double-quotes imply it's a user makefile
1657 */
1658 if (*file == '<') {
1659 isSystem = TRUE;
1660 endc = '>';
1661 } else {
1662 isSystem = FALSE;
1663 endc = '"';
1664 }
1665
1666 /*
1667 * Skip to matching delimiter
1668 */
1669 for (cp = ++file; *cp && *cp != endc; cp++) {
1670 continue;
1671 }
1672
1673 if (*cp != endc) {
1674 Parse_Error(PARSE_FATAL,
1675 "Unclosed %cinclude filename. '%c' expected", '.', endc);
1676 return;
1677 }
1678 *cp = '\0';
1679
1680 /*
1681 * Substitute for any variables in the file name before trying to
1682 * find the thing.
1683 */
1684 buf = Var_Subst(NULL, file, VAR_CMD, FALSE);
1685 file = Buf_Peel(buf);
1686
1687 /*
1688 * Now we know the file's name and its search path, we attempt to
1689 * find the durn thing. A return of NULL indicates the file don't
1690 * exist.
1691 */
1692 if (!isSystem) {
1693 /*
1694 * Include files contained in double-quotes are first searched
1695 * for relative to the including file's location. We don't want
1696 * to cd there, of course, so we just tack on the old file's
1697 * leading path components and call Dir_FindFile to see if
1698 * we can locate the beast.
1699 */
1700 char *prefEnd, *Fname;
1701
1702 /* Make a temporary copy of this, to be safe. */
1703 Fname = estrdup(CURFILE->fname);
1704
1705 prefEnd = strrchr(Fname, '/');
1706 if (prefEnd != (char *)NULL) {
1707 char *newName;
1708
1709 *prefEnd = '\0';
1710 if (file[0] == '/')
1711 newName = estrdup(file);
1712 else
1713 newName = str_concat(Fname, file, STR_ADDSLASH);
1714 fullname = Path_FindFile(newName, &parseIncPath);
1715 if (fullname == NULL) {
1716 fullname = Path_FindFile(newName,
1717 &dirSearchPath);
1718 }
1719 free(newName);
1720 *prefEnd = '/';
1721 } else {
1722 fullname = NULL;
1723 }
1724 free(Fname);
1725 } else {
1726 fullname = NULL;
1727 }
1728
1729 if (fullname == NULL) {
1730 /*
1731 * System makefile or makefile wasn't found in same directory as
1732 * included makefile. Search for it first on the -I search path,
1733 * then on the .PATH search path, if not found in a -I
1734 * directory.
1735 * XXX: Suffix specific?
1736 */
1737 fullname = Path_FindFile(file, &parseIncPath);
1738 if (fullname == NULL) {
1739 fullname = Path_FindFile(file, &dirSearchPath);
1740 }
1741 }
1742
1743 if (fullname == NULL) {
1744 /*
1745 * Still haven't found the makefile. Look for it on the system
1746 * path as a last resort.
1747 */
1748 fullname = Path_FindFile(file, &sysIncPath);
1749 }
1750
1751 if (fullname == NULL) {
1752 *cp = endc;
1753 Parse_Error(PARSE_FATAL, "Could not find %s", file);
1754 /* XXXHB free(file) */
1755 return;
1756 }
1757
1758 free(file);
1759
1760 /*
1761 * We set up the name of the file to be the absolute
1762 * name of the include file so error messages refer to the right
1763 * place.
1764 */
1765 ParsePushInput(fullname, NULL, NULL, 0);
1766}
1767
1768/*-
1769 *---------------------------------------------------------------------
1770 * Parse_FromString --
1771 * Start Parsing from the given string
1772 *
1773 * Results:
1774 * None
1775 *
1776 * Side Effects:
1777 * A structure is added to the includes Lst and readProc, curFile.lineno,

--- 26 unchanged lines hidden (view full) ---

1804 * curFile.fname and curFile.F are altered for the new file
1805 *---------------------------------------------------------------------
1806 */
1807static void
1808ParseTraditionalInclude(char *file)
1809{
1810 char *fullname; /* full pathname of file */
1811 char *cp; /* current position in file spec */
1629 * Parse_FromString --
1630 * Start Parsing from the given string
1631 *
1632 * Results:
1633 * None
1634 *
1635 * Side Effects:
1636 * A structure is added to the includes Lst and readProc, curFile.lineno,

--- 26 unchanged lines hidden (view full) ---

1663 * curFile.fname and curFile.F are altered for the new file
1664 *---------------------------------------------------------------------
1665 */
1666static void
1667ParseTraditionalInclude(char *file)
1668{
1669 char *fullname; /* full pathname of file */
1670 char *cp; /* current position in file spec */
1812 Buffer *buf;
1813
1814 /*
1815 * Skip over whitespace
1816 */
1817 while (*file == ' ' || *file == '\t') {
1818 file++;
1819 }
1820

--- 10 unchanged lines hidden (view full) ---

1831 }
1832
1833 *cp = '\0';
1834
1835 /*
1836 * Substitute for any variables in the file name before trying to
1837 * find the thing.
1838 */
1671
1672 /*
1673 * Skip over whitespace
1674 */
1675 while (*file == ' ' || *file == '\t') {
1676 file++;
1677 }
1678

--- 10 unchanged lines hidden (view full) ---

1689 }
1690
1691 *cp = '\0';
1692
1693 /*
1694 * Substitute for any variables in the file name before trying to
1695 * find the thing.
1696 */
1839 buf = Var_Subst(NULL, file, VAR_CMD, FALSE);
1840 file = Buf_Peel(buf);
1697 file = Buf_Peel(Var_Subst(NULL, file, VAR_CMD, FALSE));
1841
1842 /*
1843 * Now we know the file's name, we attempt to find the durn thing.
1844 * Search for it first on the -I search path, then on the .PATH
1845 * search path, if not found in a -I directory.
1846 */
1847 fullname = Path_FindFile(file, &parseIncPath);
1848 if (fullname == NULL) {

--- 395 unchanged lines hidden (view full) ---

2244 if (((const GNode *)Lst_Datum(ln))->type & OP_TRANSFORM)
2245 Suff_EndTransform(Lst_Datum(ln));
2246 }
2247 Lst_Destroy(&targets, ParseHasCommands);
2248 inLine = FALSE;
2249 }
2250}
2251
1698
1699 /*
1700 * Now we know the file's name, we attempt to find the durn thing.
1701 * Search for it first on the -I search path, then on the .PATH
1702 * search path, if not found in a -I directory.
1703 */
1704 fullname = Path_FindFile(file, &parseIncPath);
1705 if (fullname == NULL) {

--- 395 unchanged lines hidden (view full) ---

2101 if (((const GNode *)Lst_Datum(ln))->type & OP_TRANSFORM)
2102 Suff_EndTransform(Lst_Datum(ln));
2103 }
2104 Lst_Destroy(&targets, ParseHasCommands);
2105 inLine = FALSE;
2106 }
2107}
2108
2109/**
2110 * parse_include
2111 * Parse an .include directive and push the file onto the input stack.
2112 * The input is the line minus the .include. A file spec is a string
2113 * enclosed in <> or "". The former is looked for only in sysIncPath.
2114 * The latter in . and the directories specified by -I command line
2115 * options
2116 */
2117static void
2118parse_include(char *file, int code __unused, int lineno __unused)
2119{
2120 char *fullname; /* full pathname of file */
2121 char endc; /* the character which ends the file spec */
2122 char *cp; /* current position in file spec */
2123 Boolean isSystem; /* TRUE if makefile is a system makefile */
2124 char *prefEnd, *Fname;
2125 char *newName;
2252
2126
2127 /*
2128 * Skip to delimiter character so we know where to look
2129 */
2130 while (*file == ' ' || *file == '\t') {
2131 file++;
2132 }
2133
2134 if (*file != '"' && *file != '<') {
2135 Parse_Error(PARSE_FATAL,
2136 ".include filename must be delimited by '\"' or '<'");
2137 return;
2138 }
2139
2140 /*
2141 * Set the search path on which to find the include file based on the
2142 * characters which bracket its name. Angle-brackets imply it's
2143 * a system Makefile while double-quotes imply it's a user makefile
2144 */
2145 if (*file == '<') {
2146 isSystem = TRUE;
2147 endc = '>';
2148 } else {
2149 isSystem = FALSE;
2150 endc = '"';
2151 }
2152
2153 /*
2154 * Skip to matching delimiter
2155 */
2156 for (cp = ++file; *cp != endc; cp++) {
2157 if (*cp == '\0') {
2158 Parse_Error(PARSE_FATAL,
2159 "Unclosed .include filename. '%c' expected", endc);
2160 return;
2161 }
2162 }
2163 *cp = '\0';
2164
2165 /*
2166 * Substitute for any variables in the file name before trying to
2167 * find the thing.
2168 */
2169 file = Buf_Peel(Var_Subst(NULL, file, VAR_CMD, FALSE));
2170
2171 /*
2172 * Now we know the file's name and its search path, we attempt to
2173 * find the durn thing. A return of NULL indicates the file don't
2174 * exist.
2175 */
2176 if (!isSystem) {
2177 /*
2178 * Include files contained in double-quotes are first searched
2179 * for relative to the including file's location. We don't want
2180 * to cd there, of course, so we just tack on the old file's
2181 * leading path components and call Dir_FindFile to see if
2182 * we can locate the beast.
2183 */
2184
2185 /* Make a temporary copy of this, to be safe. */
2186 Fname = estrdup(CURFILE->fname);
2187
2188 prefEnd = strrchr(Fname, '/');
2189 if (prefEnd != NULL) {
2190 *prefEnd = '\0';
2191 if (file[0] == '/')
2192 newName = estrdup(file);
2193 else
2194 newName = str_concat(Fname, file, STR_ADDSLASH);
2195 fullname = Path_FindFile(newName, &parseIncPath);
2196 if (fullname == NULL) {
2197 fullname = Path_FindFile(newName,
2198 &dirSearchPath);
2199 }
2200 free(newName);
2201 *prefEnd = '/';
2202 } else {
2203 fullname = NULL;
2204 }
2205 free(Fname);
2206 } else {
2207 fullname = NULL;
2208 }
2209
2210 if (fullname == NULL) {
2211 /*
2212 * System makefile or makefile wasn't found in same directory as
2213 * included makefile. Search for it first on the -I search path,
2214 * then on the .PATH search path, if not found in a -I
2215 * directory.
2216 * XXX: Suffix specific?
2217 */
2218 fullname = Path_FindFile(file, &parseIncPath);
2219 if (fullname == NULL) {
2220 fullname = Path_FindFile(file, &dirSearchPath);
2221 }
2222 }
2223
2224 if (fullname == NULL) {
2225 /*
2226 * Still haven't found the makefile. Look for it on the system
2227 * path as a last resort.
2228 */
2229 fullname = Path_FindFile(file, &sysIncPath);
2230 }
2231
2232 if (fullname == NULL) {
2233 *cp = endc;
2234 Parse_Error(PARSE_FATAL, "Could not find %s", file);
2235 free(file);
2236 return;
2237 }
2238 free(file);
2239
2240 /*
2241 * We set up the name of the file to be the absolute
2242 * name of the include file so error messages refer to the right
2243 * place.
2244 */
2245 ParsePushInput(fullname, NULL, NULL, 0);
2246}
2247
2248/**
2249 * parse_message
2250 * Parse a .warning or .error directive
2251 *
2252 * The input is the line minus the ".error"/".warning". We substitute
2253 * variables, print the message and exit(1) (for .error) or just print
2254 * a warning if the directive is malformed.
2255 */
2256static void
2257parse_message(char *line, int iserror, int lineno __unused)
2258{
2259
2260 if (!isspace((u_char)*line)) {
2261 Parse_Error(PARSE_WARNING, "invalid syntax: .%s%s",
2262 iserror ? "error" : "warning", line);
2263 return;
2264 }
2265
2266 while (isspace((u_char)*line))
2267 line++;
2268
2269 line = Buf_Peel(Var_Subst(NULL, line, VAR_GLOBAL, FALSE));
2270 Parse_Error(iserror ? PARSE_FATAL : PARSE_WARNING, "%s", line);
2271 free(line);
2272
2273 if (iserror) {
2274 /* Terminate immediately. */
2275 exit(1);
2276 }
2277}
2278
2279/**
2280 * parse_undef
2281 * Parse an .undef directive.
2282 */
2283static void
2284parse_undef(char *line, int code __unused, int lineno __unused)
2285{
2286 char *cp;
2287
2288 while (isspace((u_char)*line))
2289 line++;
2290
2291 for (cp = line; !isspace((u_char)*cp) && *cp != '\0'; cp++) {
2292 ;
2293 }
2294 *cp = '\0';
2295
2296 cp = Buf_Peel(Var_Subst(NULL, line, VAR_CMD, FALSE));
2297 Var_Delete(cp, VAR_GLOBAL);
2298 free(cp);
2299}
2300
2301/**
2302 * parse_for
2303 * Parse a .for directive.
2304 */
2305static void
2306parse_for(char *line, int code __unused, int lineno)
2307{
2308
2309 if (!For_For(line)) {
2310 /* syntax error */
2311 return;
2312 }
2313 line = NULL;
2314
2315 /*
2316 * Skip after the matching endfor.
2317 */
2318 do {
2319 free(line);
2320 line = ParseSkipLine(0, 1);
2321 if (line == NULL) {
2322 Parse_Error(PARSE_FATAL,
2323 "Unexpected end of file in for loop.\n");
2324 return;
2325 }
2326 } while (For_Eval(line));
2327 free(line);
2328
2329 /* execute */
2330 For_Run(lineno);
2331}
2332
2333/**
2334 * parse_endfor
2335 * Parse endfor. This may only happen if there was no matching .for.
2336 */
2337static void
2338parse_endfor(char *line __unused, int code __unused, int lineno __unused)
2339{
2340
2341 Parse_Error(PARSE_FATAL, "for-less endfor");
2342}
2343
2344/**
2345 * directive_hash
2346 */
2347static int
2348directive_hash(const u_char *key, size_t len)
2349{
2350 unsigned f0, f1;
2351 const u_char *kp = key;
2352
2353 if (len < 2 || len > 9)
2354 return (-1);
2355
2356 for (f0 = f1 = 0; kp < key + len; ++kp) {
2357 if (*kp < 97 || *kp > 119)
2358 return (-1);
2359 f0 += directive_T0[-97 + *kp];
2360 f1 += directive_T1[-97 + *kp];
2361 }
2362
2363 f0 %= 38;
2364 f1 %= 38;
2365
2366 return (directive_g[f0] + directive_g[f1]) % 18;
2367}
2368
2369/**
2370 * parse_directive
2371 * Got a line starting with a '.'. Check if this is a directive
2372 * and parse it.
2373 *
2374 * return:
2375 * TRUE if line was a directive, FALSE otherwise.
2376 */
2377static Boolean
2378parse_directive(char *line)
2379{
2380 char *start;
2381 char *cp;
2382 int dir;
2383
2384 /*
2385 * Get the keyword:
2386 * .[[:space:]]*\([[:alpha:]][[:alnum:]_]*\).*
2387 * \1 is the keyword.
2388 */
2389 for (start = line; isspace((u_char)*start); start++) {
2390 ;
2391 }
2392
2393 if (!isalpha((u_char)*start)) {
2394 return (FALSE);
2395 }
2396
2397 cp = start + 1;
2398 while (isalnum((u_char)*cp) || *cp == '_') {
2399 cp++;
2400 }
2401
2402 dir = directive_hash(start, cp - start);
2403 if (dir < 0 || dir >= (int)NDIRECTS ||
2404 (size_t)(cp - start) != strlen(directives[dir].name) ||
2405 strncmp(start, directives[dir].name, cp - start) != 0) {
2406 /* not actually matched */
2407 return (FALSE);
2408 }
2409
2410 if (!skipLine || directives[dir].skip_flag)
2411 (*directives[dir].func)(cp, directives[dir].code,
2412 CURFILE->lineno);
2413 return (TRUE);
2414}
2415
2253/*-
2254 *---------------------------------------------------------------------
2255 * Parse_File --
2256 * Parse a file into its component parts, incorporating it into the
2257 * current dependency graph. This is the main function and controls
2258 * almost every other function in this module
2259 *
2260 * Results:

--- 4 unchanged lines hidden (view full) ---

2265 * are added to the dependency graph. etc. etc. etc.
2266 *---------------------------------------------------------------------
2267 */
2268void
2269Parse_File(const char *name, FILE *stream)
2270{
2271 char *cp; /* pointer into the line */
2272 char *line; /* the line we're working on */
2416/*-
2417 *---------------------------------------------------------------------
2418 * Parse_File --
2419 * Parse a file into its component parts, incorporating it into the
2420 * current dependency graph. This is the main function and controls
2421 * almost every other function in this module
2422 *
2423 * Results:

--- 4 unchanged lines hidden (view full) ---

2428 * are added to the dependency graph. etc. etc. etc.
2429 *---------------------------------------------------------------------
2430 */
2431void
2432Parse_File(const char *name, FILE *stream)
2433{
2434 char *cp; /* pointer into the line */
2435 char *line; /* the line we're working on */
2273 Buffer *buf;
2274 int lineno;
2275
2276 inLine = FALSE;
2277 fatals = 0;
2278
2279 ParsePushInput(estrdup(name), stream, NULL, 0);
2280
2281 while ((line = ParseReadLine()) != NULL) {
2436
2437 inLine = FALSE;
2438 fatals = 0;
2439
2440 ParsePushInput(estrdup(name), stream, NULL, 0);
2441
2442 while ((line = ParseReadLine()) != NULL) {
2282 if (*line == '.') {
2283 /*
2284 * Lines that begin with the special character
2285 * are either include or undef directives.
2286 */
2287 for (cp = line + 1; isspace((unsigned char)*cp); cp++) {
2288 continue;
2289 }
2290 if (strncmp(cp, "include", 7) == 0) {
2291 ParseDoInclude(cp + 7);
2292 goto nextLine;
2293 } else if (strncmp(cp, "error", 5) == 0) {
2294 ParseDoError(cp + 5);
2295 goto nextLine;
2296 } else if (strncmp(cp, "warning", 7) == 0) {
2297 ParseDoWarning(cp + 7);
2298 goto nextLine;
2299 } else if (strncmp(cp, "undef", 5) == 0) {
2300 char *cp2;
2301 for (cp += 5; isspace((unsigned char)*cp);
2302 cp++) {
2303 continue;
2304 }
2305
2306 for (cp2 = cp; !isspace((unsigned char)*cp2) &&
2307 *cp2 != '\0'; cp2++) {
2308 continue;
2309 }
2310
2311 *cp2 = '\0';
2312
2313 buf = Var_Subst(NULL, cp, VAR_CMD, FALSE);
2314 cp = Buf_Peel(buf);
2315
2316 Var_Delete(cp, VAR_GLOBAL);
2317 goto nextLine;
2318
2319 } else if (For_Eval(line)) {
2320 lineno = CURFILE->lineno;
2321 do {
2322 /*
2323 * Skip after the matching end.
2324 */
2325 free(line);
2326 line = ParseSkipLine(0, 1);
2327 if (line == NULL) {
2328 Parse_Error(PARSE_FATAL,
2329 "Unexpected end of"
2330 " file in for loop.\n");
2331 goto nextLine;
2332 }
2333 } while (For_Eval(line));
2334 For_Run(lineno);
2335 goto nextLine;
2336
2337 } else {
2338 /*
2339 * The line might be a conditional. Ask the
2340 * conditional module about it and act
2341 * accordingly
2342 */
2343 int cond = Cond_Eval(line, CURFILE->lineno);
2344
2345 if (cond == COND_SKIP) {
2346 /*
2347 * Skip to next conditional that
2348 * evaluates to COND_PARSE.
2349 */
2350 do {
2351 free(line);
2352 line = ParseSkipLine(1, 0);
2353 } while (line && Cond_Eval(line,
2354 CURFILE->lineno) != COND_PARSE);
2355 goto nextLine;
2356 }
2357 if (cond == COND_PARSE)
2358 goto nextLine;
2359 }
2443 if (*line == '.' && parse_directive(line + 1)) {
2444 /* directive consumed */
2445 goto nextLine;
2360 }
2446 }
2361 if (*line == '#') {
2362 /*
2363 * If we're this far, the line must be
2364 * a comment.
2365 */
2447 if (skipLine || *line == '#') {
2448 /* Skipping .if block or comment. */
2366 goto nextLine;
2367 }
2368
2369 if (*line == '\t') {
2370 /*
2371 * If a line starts with a tab, it can only
2372 * hope to be a creation command.
2373 */

--- 55 unchanged lines hidden (view full) ---

2429 * being parsed. Tell the variable module to
2430 * complain if some variable is undefined...
2431 * To make life easier on novices, if the line
2432 * is indented we first make sure the line has
2433 * a dependency operator in it. If it doesn't
2434 * have an operator and we're in a dependency
2435 * line's script, we assume it's actually a
2436 * shell command and add it to the current
2449 goto nextLine;
2450 }
2451
2452 if (*line == '\t') {
2453 /*
2454 * If a line starts with a tab, it can only
2455 * hope to be a creation command.
2456 */

--- 55 unchanged lines hidden (view full) ---

2512 * being parsed. Tell the variable module to
2513 * complain if some variable is undefined...
2514 * To make life easier on novices, if the line
2515 * is indented we first make sure the line has
2516 * a dependency operator in it. If it doesn't
2517 * have an operator and we're in a dependency
2518 * line's script, we assume it's actually a
2519 * shell command and add it to the current
2437 * list of targets.
2520 * list of targets. XXX this comment seems wrong.
2438 */
2439 cp = line;
2440 if (isspace((unsigned char)line[0])) {
2441 while (*cp != '\0' &&
2442 isspace((unsigned char)*cp)) {
2443 cp++;
2444 }
2445 if (*cp == '\0') {
2446 goto nextLine;
2447 }
2448 }
2449
2450 ParseFinishLine();
2451
2521 */
2522 cp = line;
2523 if (isspace((unsigned char)line[0])) {
2524 while (*cp != '\0' &&
2525 isspace((unsigned char)*cp)) {
2526 cp++;
2527 }
2528 if (*cp == '\0') {
2529 goto nextLine;
2530 }
2531 }
2532
2533 ParseFinishLine();
2534
2452 buf = Var_Subst(NULL, line, VAR_CMD, TRUE);
2453 cp = Buf_Peel(buf);
2535 cp = Buf_Peel(Var_Subst(NULL, line, VAR_CMD, TRUE));
2454
2455 free(line);
2456 line = cp;
2457
2458 /*
2459 * Need a non-circular list for the target nodes
2460 */
2461 Lst_Destroy(&targets, NOFREE);

--- 13 unchanged lines hidden (view full) ---

2475 */
2476 Cond_End();
2477
2478 if (fatals)
2479 errx(1, "fatal errors encountered -- cannot continue");
2480}
2481
2482/*-
2536
2537 free(line);
2538 line = cp;
2539
2540 /*
2541 * Need a non-circular list for the target nodes
2542 */
2543 Lst_Destroy(&targets, NOFREE);

--- 13 unchanged lines hidden (view full) ---

2557 */
2558 Cond_End();
2559
2560 if (fatals)
2561 errx(1, "fatal errors encountered -- cannot continue");
2562}
2563
2564/*-
2483 *---------------------------------------------------------------------
2484 * Parse_Init --
2485 * initialize the parsing module
2486 *
2487 * Results:
2488 * none
2489 *
2490 * Side Effects:
2491 * the parseIncPath list is initialized...
2492 *---------------------------------------------------------------------
2493 */
2494void
2495Parse_Init(void)
2496{
2497
2498 mainNode = NULL;
2499}
2500
2501/*-
2502 *-----------------------------------------------------------------------
2503 * Parse_MainName --
2504 * Return a Lst of the main target to create for main()'s sake. If
2505 * no such target exists, we Punt with an obnoxious error message.
2506 *
2507 * Results:
2508 * A Lst of the single node to create.
2509 *

--- 18 unchanged lines hidden ---
2565 *-----------------------------------------------------------------------
2566 * Parse_MainName --
2567 * Return a Lst of the main target to create for main()'s sake. If
2568 * no such target exists, we Punt with an obnoxious error message.
2569 *
2570 * Results:
2571 * A Lst of the single node to create.
2572 *

--- 18 unchanged lines hidden ---