home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / proglang / dmake38a.arj / PARSE.C < prev    next >
C/C++ Source or Header  |  1992-01-23  |  5KB  |  159 lines

  1. /* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/parse.c,v 1.1 1992/01/24 03:26:53 dvadura Exp $
  2. -- SYNOPSIS -- parse the input, and perform semantic analysis
  3. -- 
  4. -- DESCRIPTION
  5. --     This file contains the routines that parse the input makefile and
  6. --    call the appropriate routines to perform the semantic analysis and
  7. --    build the internal dag.
  8. --
  9. -- AUTHOR
  10. --      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  11. --      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  12. --
  13. -- COPYRIGHT
  14. --      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  15. -- 
  16. --      This program is free software; you can redistribute it and/or
  17. --      modify it under the terms of the GNU General Public License
  18. --      (version 1), as published by the Free Software Foundation, and
  19. --      found in the file 'LICENSE' included with this distribution.
  20. -- 
  21. --      This program is distributed in the hope that it will be useful,
  22. --      but WITHOUT ANY WARRANTY; without even the implied warrant of
  23. --      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24. --      GNU General Public License for more details.
  25. -- 
  26. --      You should have received a copy of the GNU General Public License
  27. --      along with this program;  if not, write to the Free Software
  28. --      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  29. --
  30. -- LOG
  31. --     $Log: parse.c,v $
  32.  * Revision 1.1  1992/01/24  03:26:53  dvadura
  33.  * dmake Version 3.8, Initial revision
  34.  *
  35. */
  36.  
  37. #include "extern.h"
  38.  
  39.  
  40. PUBLIC void
  41. Parse( fil )/*
  42. ==============  Parse the makefile input */
  43. FILE *fil;
  44. {
  45.    int  rule  = FALSE;                 /* have seen a recipe line        */
  46.    char *p;                   /* termporary pointer into Buffer */
  47.  
  48.    DB_ENTER( "Parse" );
  49.  
  50.    State = NORMAL_SCAN;
  51.    Group = FALSE;                 /* true if scanning a group rcpe  */
  52.    while( TRUE ) {
  53.       if( Get_line( Buffer, fil ) ) {
  54.      if( fil != NIL( FILE ) )               /* end of parsable input */
  55.         Closefile();
  56.  
  57.      Bind_rules_to_targets( F_DEFAULT );
  58.          if( Group )  Fatal( "Incomplete rule recipe group detected" );
  59.  
  60.      DB_VOID_RETURN;
  61.       }
  62.       else {
  63.          switch( State ) {
  64.         case RULE_SCAN:
  65.  
  66.            /* Check for the `[' that starts off a group rule definition.  It
  67.             * must appear as the first non-white space
  68.         * character in the line. */
  69.  
  70.            p = _strspn( Buffer, " \t\r\n" );
  71.                if( Set_group_attributes( p ) ) {
  72.                   if( rule && Group )
  73.                      Fatal( "Cannot mix single and group recipe lines" );
  74.                   else
  75.                      Group = TRUE;
  76.  
  77.                   rule = TRUE;
  78.  
  79.                   break;                     /* ignore the group start  */
  80.                }
  81.  
  82.                if( Group ) {
  83.                   if( *p != ']' ) {
  84.                      Add_recipe_to_list( Buffer, TRUE, TRUE );
  85.                      rule = TRUE;
  86.                   }
  87.                   else
  88.                      State = NORMAL_SCAN;
  89.                }
  90.                else {
  91.                   if(    *Buffer == '\t'
  92.               || (Notabs && *Buffer == ' ') ) {
  93.                      Add_recipe_to_list( Buffer, FALSE, FALSE );
  94.                      rule = TRUE;
  95.                   }
  96.                   else if( *p == ']' )
  97.                      Fatal( "Found unmatched ']'" );
  98.                   else if( *Buffer && *p || (Notabs && !*Buffer && !*p))
  99.              State = NORMAL_SCAN;
  100.                }
  101.  
  102.                if( State == RULE_SCAN ) break;     /* ie. keep going    */
  103.                
  104.            Bind_rules_to_targets( (Group) ? F_GROUP: F_DEFAULT );
  105.  
  106.                rule = FALSE;
  107.                if( Group ) {
  108.                   Group = FALSE;
  109.                   break;
  110.                }
  111.            /*FALLTRHOUGH*/
  112.  
  113.                /* In this case we broke out of the rule scan because we do not
  114.                 * have a recipe line that begins with a <TAB>, so lets
  115.         * try to scan the thing as a macro or rule definition. */
  116.                
  117.  
  118.         case NORMAL_SCAN:
  119.            if( !*Buffer ) continue;         /* we have null input line */
  120.  
  121.            /* STUPID AUGMAKE uses "include" at the start of a line as
  122.             * a signal to include a new file, so let's look for it.
  123.         * if we see it replace it by .INCLUDE: and stick this back
  124.         * into the buffer. */
  125.            if( !strncmp( "include", Buffer, 7 ) &&
  126.            (Buffer[7] == ' ' || Buffer[7] == '\t') )
  127.            {
  128.           char *tmp;
  129.  
  130.           tmp = _strjoin( ".INCLUDE:", Buffer+7, -1, FALSE );
  131.           strcpy( Buffer, tmp );
  132.           FREE( tmp );
  133.            }
  134.  
  135.                /* look for a macro definition, they all contain an = sign
  136.             * if we fail to recognize it as a legal macro op then try to
  137.         * parse the same line as a rule definition, it's one or the
  138.         * other */
  139.         
  140.            if( Parse_macro(Buffer, M_DEFAULT) ) break;/* it's a macro def */
  141.            if( Parse_rule_def( &State ) )         break;/* it's a rule def  */
  142.  
  143.            /* if just blank line then ignore it */
  144.            if( *_strspn( Buffer, " \t\r\n" ) == '\0' ) break;
  145.            
  146.            /* otherwise assume it was a line of unrecognized input, or a
  147.             * recipe line out of place so print a message */
  148.         
  149.            Fatal( "Expecting macro or rule defn, found neither" );
  150.            break;
  151.  
  152.         default:
  153.            Fatal( "Internal -- UNKNOWN Parser state %d", State );
  154.      }
  155.       }
  156.    }
  157. }
  158.  
  159.