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