office-gobmx/dmake/parse.c
2012-06-28 19:59:06 +01:00

174 lines
4.8 KiB
C

/*
--
-- SYNOPSIS
-- Parse the input, and perform semantic analysis
--
-- DESCRIPTION
-- This file contains the routines that parse the input makefile and
-- call the appropriate routines to perform the semantic analysis and
-- build the internal dag.
--
-- AUTHOR
-- Dennis Vadura, dvadura@dmake.wticorp.com
--
-- WWW
-- http://dmake.wticorp.com/
--
-- COPYRIGHT
-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
--
-- This program is NOT free software; you can redistribute it and/or
-- modify it under the terms of the Software License Agreement Provided
-- in the file <distribution-root>/readme/license.txt.
--
-- LOG
-- Use cvs log to obtain detailed change logs.
*/
#include "extern.h"
PUBLIC void
Parse( fil )/*
============== Parse the makefile input */
FILE *fil;
{
int rule = FALSE; /* have seen a recipe line */
char *p; /* termporary pointer into Buffer */
char *pTmpBuf;
DB_ENTER( "Parse" );
State = NORMAL_SCAN;
Group = FALSE; /* true if scanning a group rcpe */
while( TRUE ) {
if( Get_line( Buffer, fil ) ) {
if( Group ) Fatal( "Incomplete rule recipe group detected" );
/* If we are still in RULE_SCAN mode there might be unbound recipes. */
if( State == RULE_SCAN )
Bind_rules_to_targets( F_DEFAULT );
if( fil != NIL( FILE ) ) /* end of parsable input */
Closefile();
DB_VOID_RETURN;
}
else {
#ifdef _MPW
if ( Buffer[0] == 10 )
pTmpBuf = Buffer+1;
else
#endif
pTmpBuf = Buffer;
#ifdef _MPW
p = pTmpBuf;
while ( *p )
{
if ( *p == 10 )
*p = '\t';
p++;
}
#endif
switch( State ) {
case RULE_SCAN:
/* Check for the `[' that starts off a group recipe definition.
* It must appear as the first non-white space
* character in the line. */
p = DmStrSpn( Buffer, " \t\r\n" );
if( Set_group_attributes( p ) ) {
if( Group )
Fatal( "New group recipe begin found within group recipe." );
else if( rule )
Fatal( "Cannot mix single and group recipe lines." );
else
Group = TRUE;
rule = TRUE;
break; /* ignore the group start */
}
if( Group ) {
if( *p != ']' ) {
Add_recipe_to_list( pTmpBuf, TRUE, TRUE );
rule = TRUE;
}
else
State = NORMAL_SCAN;
}
else {
if( *pTmpBuf == '\t'
|| (Notabs && *pTmpBuf == ' ') ) {
Add_recipe_to_list( pTmpBuf, FALSE, FALSE );
rule = TRUE;
}
else if( *p == ']' )
Fatal( "Found unmatched ']'" );
else if( *pTmpBuf ) /* Something that was no recipe. */
State = NORMAL_SCAN;
/* The only thing that was not handled was an empty line. */
}
if( State == RULE_SCAN ) break; /* ie. keep going */
Bind_rules_to_targets( (Group) ? F_GROUP: F_DEFAULT );
rule = FALSE;
if( Group ) {
Group = FALSE;
break;
}
/*FALLTRHOUGH*/
/* In this case we broke out of the rule scan because we do not
* have a recipe line that begins with a <TAB>, so lets
* try to scan the thing as a macro or rule definition. */
case NORMAL_SCAN:
if( !*pTmpBuf ) continue; /* we have null input line */
/* STUPID AUGMAKE uses "include" at the start of a line as
* a signal to include a new file, so let's look for it.
* if we see it replace it by .INCLUDE: and stick this back
* into the buffer. */
if( !strncmp( "include", pTmpBuf, 7 ) &&
(pTmpBuf[7] == ' ' || pTmpBuf[7] == '\t') )
{
char *tmp;
tmp = DmStrJoin( ".INCLUDE:", pTmpBuf+7, -1, FALSE );
strcpy( pTmpBuf, tmp );
FREE( tmp );
}
/* look for a macro definition, they all contain an = sign
* if we fail to recognize it as a legal macro op then try to
* parse the same line as a rule definition, it's one or the
* other */
if( Parse_macro(pTmpBuf, M_DEFAULT) ) break;/* it's a macro def*/
if( Parse_rule_def( &State ) ) break;/* it's a rule def */
/* if it is an empty or blank line then ignore it */
if( !*Buffer || *DmStrSpn( Buffer, " \t\r\n" ) == '\0' ) break;
/* otherwise assume it was a line of unrecognized input, or a
* recipe line out of place so print a message */
Fatal( "Expecting macro or rule defn, found neither" );
break;
default:
Fatal( "Internal -- UNKNOWN Parser state %d", State );
}
}
}
}