Line data Source code
1 : /*
2 : --
3 : -- SYNOPSIS
4 : -- Parse the input, and perform semantic analysis
5 : --
6 : -- DESCRIPTION
7 : -- This file contains the routines that parse the input makefile and
8 : -- call the appropriate routines to perform the semantic analysis and
9 : -- build the internal dag.
10 : --
11 : -- AUTHOR
12 : -- Dennis Vadura, dvadura@dmake.wticorp.com
13 : --
14 : -- WWW
15 : -- http://dmake.wticorp.com/
16 : --
17 : -- COPYRIGHT
18 : -- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
19 : --
20 : -- This program is NOT free software; you can redistribute it and/or
21 : -- modify it under the terms of the Software License Agreement Provided
22 : -- in the file <distribution-root>/readme/license.txt.
23 : --
24 : -- LOG
25 : -- Use cvs log to obtain detailed change logs.
26 : */
27 :
28 : #include "extern.h"
29 :
30 :
31 : PUBLIC void
32 4960 : Parse( fil )/*
33 : ============== Parse the makefile input */
34 : FILE *fil;
35 : {
36 4960 : int rule = FALSE; /* have seen a recipe line */
37 : char *p; /* termporary pointer into Buffer */
38 : char *pTmpBuf;
39 :
40 : DB_ENTER( "Parse" );
41 :
42 4960 : State = NORMAL_SCAN;
43 4960 : Group = FALSE; /* true if scanning a group rcpe */
44 : while( TRUE ) {
45 474522 : if( Get_line( Buffer, fil ) ) {
46 4960 : if( Group ) Fatal( "Incomplete rule recipe group detected" );
47 :
48 : /* If we are still in RULE_SCAN mode there might be unbound recipes. */
49 4960 : if( State == RULE_SCAN )
50 478 : Bind_rules_to_targets( F_DEFAULT );
51 :
52 4960 : if( fil != NIL( FILE ) ) /* end of parsable input */
53 4592 : Closefile();
54 :
55 9920 : DB_VOID_RETURN;
56 : }
57 : else {
58 :
59 : #ifdef _MPW
60 : if ( Buffer[0] == 10 )
61 : pTmpBuf = Buffer+1;
62 : else
63 : #endif
64 469562 : pTmpBuf = Buffer;
65 :
66 : #ifdef _MPW
67 : p = pTmpBuf;
68 : while ( *p )
69 : {
70 : if ( *p == 10 )
71 : *p = '\t';
72 : p++;
73 : }
74 : #endif
75 :
76 469562 : switch( State ) {
77 : case RULE_SCAN:
78 :
79 : /* Check for the `[' that starts off a group recipe definition.
80 : * It must appear as the first non-white space
81 : * character in the line. */
82 :
83 88910 : p = DmStrSpn( Buffer, " \t\r\n" );
84 88910 : if( Set_group_attributes( p ) ) {
85 0 : if( Group )
86 0 : Fatal( "New group recipe begin found within group recipe." );
87 0 : else if( rule )
88 0 : Fatal( "Cannot mix single and group recipe lines." );
89 : else
90 0 : Group = TRUE;
91 :
92 0 : rule = TRUE;
93 :
94 0 : break; /* ignore the group start */
95 : }
96 :
97 88910 : if( Group ) {
98 0 : if( *p != ']' ) {
99 0 : Add_recipe_to_list( pTmpBuf, TRUE, TRUE );
100 0 : rule = TRUE;
101 : }
102 : else
103 0 : State = NORMAL_SCAN;
104 : }
105 : else {
106 88910 : if( *pTmpBuf == '\t'
107 88910 : || (Notabs && *pTmpBuf == ' ') ) {
108 41610 : Add_recipe_to_list( pTmpBuf, FALSE, FALSE );
109 41610 : rule = TRUE;
110 : }
111 47300 : else if( *p == ']' )
112 0 : Fatal( "Found unmatched ']'" );
113 47300 : else if( *pTmpBuf ) /* Something that was no recipe. */
114 18400 : State = NORMAL_SCAN;
115 : /* The only thing that was not handled was an empty line. */
116 : }
117 :
118 88910 : if( State == RULE_SCAN ) break; /* ie. keep going */
119 :
120 18400 : Bind_rules_to_targets( (Group) ? F_GROUP: F_DEFAULT );
121 :
122 18400 : rule = FALSE;
123 18400 : if( Group ) {
124 0 : Group = FALSE;
125 0 : break;
126 : }
127 : /*FALLTRHOUGH*/
128 :
129 : /* In this case we broke out of the rule scan because we do not
130 : * have a recipe line that begins with a <TAB>, so lets
131 : * try to scan the thing as a macro or rule definition. */
132 :
133 :
134 : case NORMAL_SCAN:
135 399052 : if( !*pTmpBuf ) continue; /* we have null input line */
136 :
137 : /* STUPID AUGMAKE uses "include" at the start of a line as
138 : * a signal to include a new file, so let's look for it.
139 : * if we see it replace it by .INCLUDE: and stick this back
140 : * into the buffer. */
141 300318 : if( !strncmp( "include", pTmpBuf, 7 ) &&
142 0 : (pTmpBuf[7] == ' ' || pTmpBuf[7] == '\t') )
143 : {
144 : char *tmp;
145 :
146 0 : tmp = DmStrJoin( ".INCLUDE:", pTmpBuf+7, -1, FALSE );
147 0 : strcpy( pTmpBuf, tmp );
148 0 : FREE( tmp );
149 : }
150 :
151 : /* look for a macro definition, they all contain an = sign
152 : * if we fail to recognize it as a legal macro op then try to
153 : * parse the same line as a rule definition, it's one or the
154 : * other */
155 :
156 300318 : if( Parse_macro(pTmpBuf, M_DEFAULT) ) break;/* it's a macro def*/
157 27336 : if( Parse_rule_def( &State ) ) break;/* it's a rule def */
158 :
159 : /* if it is an empty or blank line then ignore it */
160 1042 : if( !*Buffer || *DmStrSpn( Buffer, " \t\r\n" ) == '\0' ) break;
161 :
162 : /* otherwise assume it was a line of unrecognized input, or a
163 : * recipe line out of place so print a message */
164 :
165 0 : Fatal( "Expecting macro or rule defn, found neither" );
166 0 : break;
167 :
168 : default:
169 0 : Fatal( "Internal -- UNKNOWN Parser state %d", State );
170 : }
171 : }
172 469562 : }
173 : }
174 :
|