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 --- |