home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / prog / c / bmake15.lzh / read.c < prev    next >
C/C++ Source or Header  |  1991-10-10  |  9KB  |  397 lines

  1. /*    read.c
  2.  *    (c) Copyright 1991 by Ben Eng, All Rights Reserved
  3.  *
  4.  */
  5.  
  6. #include <ctype.h>
  7. #include <clib/exec_protos.h>
  8.  
  9. #include "make.h"
  10. #include "depend.h"
  11. #include "cond.h"
  12.  
  13. extern int line_number;
  14.  
  15. /*    process a line that looks like
  16.  *    target names: dependencies
  17.  */
  18. struct target *
  19. process_targetline( char *line, struct List *cmdlist )
  20. {
  21.     struct target *first_targ = NULL;
  22.     struct target *targ = NULL;
  23.     struct List *ownerlist = NULL;
  24.     char *delim, *nexttar;
  25.     char name[ MAXPATHNAME ];
  26.     char *expandlhs = NULL, *expandrhs = NULL;
  27.     long len;
  28.     int dbl_colon_flag = 0;
  29.  
  30.     struct depend *dep = NULL;
  31.     struct command *cmd = NULL;
  32.     char *next;
  33.  
  34.     if( !(expandlhs = (char *)malloc( Param.MaxLine )) ||
  35.         !(expandrhs = (char *)malloc( Param.MaxLine )))
  36.         goto death;
  37.  
  38.     while( isspace( *line )) line++;
  39.     delim = find_token( line + 1, ':' );
  40.     if( !delim )
  41.         goto death;
  42.     len = (long)(delim - line);
  43.     if( !len )
  44.         goto death;
  45.  
  46.     if( delim[1] == ':' ) {
  47.         dbl_colon_flag = 1;
  48.         delim++;
  49.     }
  50.  
  51.     memset( name, 0, sizeof( name ));
  52.     strncpy( name, line, (int)(delim - line));
  53.  
  54.     /* expand macros in targetnames */
  55.     if( expand_macros( expandlhs, name, Param.MaxLine ))
  56.         goto death;
  57.     nexttar = expandlhs;
  58.  
  59.     /* for each target name left of the colon */
  60.     for(;;) {
  61.         dep = NULL;
  62.         cmd = NULL;
  63.         
  64.         nexttar = parse_str( name, nexttar, sizeof( name ));
  65.         if( !*name )
  66.             break; /* no more names */
  67.  
  68.         if( dbl_colon_flag)
  69.             targ = NULL;
  70.         else
  71.             targ = find_target( name );
  72.         if( !targ ) {
  73.             targ = new_target( name );
  74.             if( !targ )
  75.                 goto death;
  76.             targ->line_number = line_number;
  77.         }
  78.         if( Global.builtin_flag )
  79.             targ->flags |= TF_BUILTIN;
  80.         if( dbl_colon_flag )
  81.             targ->flags |= TF_DBLCOLON;
  82.  
  83.         debugprintf( 5, ( "new target: %s\n", targ->name ) );
  84.  
  85.         if( !first_targ ) {
  86.             first_targ = targ;
  87.             first_targ->flags |= TF_OWNER;
  88.             ownerlist = &targ->commandlist;
  89.         }
  90.  
  91.         set_target_macros( name, NULL );
  92.  
  93.         /* find the dependencies */
  94.         next = delim + 1;
  95.         while( isspace( *next )) next++;
  96.  
  97.         /* expand macros in dependencies */
  98.         if( expand_macros( expandrhs, next, Param.MaxLine ))
  99.             goto death;
  100.         next = expandrhs;
  101.  
  102.         /* for each dependency add to list */
  103.         for( ;; ) {
  104.             next = parse_str( name, next, sizeof( name ));
  105.             if( !*name )
  106.                 break; /* no more names */
  107.  
  108.             if( *name == '.' ) {
  109.                 if( !stricmp( name+1, ONCE_TARGET )) {
  110.                     targ->flags |= TF_ONCE;
  111.                     continue;
  112.                 }
  113.                 else if( !stricmp( name+1, INVIS_TARGET )) {
  114.                     targ->flags |= TF_INVIS;
  115.                     continue;
  116.                 }
  117.                 else if( !stricmp( name+1, ALWAYS_TARGET )) {
  118.                     targ->flags |= TF_ALWAYS;
  119.                     continue;
  120.                 }
  121.                 else if( !stricmp( name+1, NEVER_TARGET )) {
  122.                     targ->flags |= TF_NEVER;
  123.                     continue;
  124.                 }
  125.             }
  126.  
  127.             /* first check if that dependency already exists */
  128.             for( dep = targ->dependlist.lh_Head; dep->node.ln_Succ;
  129.                 dep = dep->node.ln_Succ ) {
  130.                 if( !stricmp( dep->name, name ))
  131.                     break;
  132.             }
  133.  
  134.             if( !dep->node.ln_Succ ) { /* doesn't exist already */
  135.                 if(  dep = new_depend( name ))
  136.                     AddTail( &targ->dependlist, &dep->node );
  137.                 else
  138.                     goto death;
  139.             }
  140.             else {
  141.                 logprintf( "duplicate dependency %s for target %s\n",
  142.                     name, targ->name );
  143.             }
  144.         }
  145.         /* for each command add to list */
  146.         if( targ->flags & TF_OWNER ) {
  147.             delete_commandlist( &targ->commandlist );
  148.             attach_list( &targ->commandlist, cmdlist );
  149.         }
  150.         else targ->alternate = ownerlist;
  151.  
  152.         if( !stricmp( targ->name, DEFAULT_TARGET )) {
  153.             set_default_target( targ );
  154.         }
  155.         else if( !(targ->flags & TF_ADDED )) {
  156.             if( ((dep = targ->dependlist.lh_Head) &&
  157.                 strchr( dep->name, PATMATCH_CHAR )) ||
  158.                 strchr( targ->name, PATMATCH_CHAR )) {
  159.                 add_pattern_rule( targ );
  160.             }
  161.             else {
  162.                 targ->flags |= TF_ADDED;
  163.                 AddTail( &Global.targetlist, &targ->node );
  164.             }
  165.         }
  166.         targ = NULL;
  167.     } /* for */
  168.  
  169. death:
  170.     set_target_macros( NULL, NULL ); /* delete $@ $* and $< */
  171.  
  172.     if( targ )
  173.         free( targ );
  174.     if( expandrhs )
  175.         free( expandrhs );
  176.     if( expandlhs )
  177.         free( expandlhs );
  178.     if( dbl_colon_flag ) {
  179.         logfile( "WARNING:  double colon rules do not work!\n" );
  180.     }
  181.     return( first_targ );
  182. }
  183.  
  184. /*    process a line that looks like
  185.  *    variable = value
  186.  */
  187. struct macro *
  188. process_macroline( char *line )
  189. {
  190.     struct macro *mac = NULL;
  191.     char *delim, *next;
  192.     char macroname[ MAX_MACRONAME ], *rhs;
  193.     char *expansion = NULL; /* dynamic */
  194.     long namelen, explen;
  195.     int do_expansion = 0;
  196.     int do_addition = 0;
  197.  
  198.     debugprintf( 5, ( "macroline %d: %s\n", line_number, line ) );
  199.  
  200.     while( isspace( *line ))
  201.         line++; /* skip whitespace */
  202.  
  203.     delim = strchr( line, '=' ); /* cannot be escaped by backslash */
  204.     if( !delim )
  205.         goto death;
  206.     rhs = delim + 1;
  207.  
  208.     namelen = min( (long)(delim - line), sizeof(macroname)-1);
  209.     if( !namelen )
  210.         goto death;
  211.  
  212.     switch( *(delim-1)) {
  213.     case ':':
  214.         do_expansion = 1;
  215.         delim--;
  216.         namelen--;
  217.         break;
  218.     case '+':
  219.         do_addition = 1;
  220.         delim--;
  221.         namelen--;
  222.         break;
  223.     }
  224.  
  225.     next = line;
  226.     while( isspace( *next )) next++;
  227.     memset( macroname, 0, sizeof( macroname ));
  228.     for( int i = 0; next < delim && i < 79; i++ ) {
  229.         if( isspace( *next ))
  230.             break;
  231.         macroname[ i ] = *next++;
  232.     }
  233.  
  234.     while( isspace( *rhs )) rhs++; /* skip whitespace */
  235.  
  236.     if( do_expansion && *rhs ) {
  237.         expansion = (char *)malloc( Param.MaxLine );
  238.         if( !expansion )
  239.             goto death;
  240.         if( expand_macros( expansion, rhs, Param.MaxLine ))
  241.             goto death;
  242.             /* expand rhs */
  243.         rhs = expansion;
  244.     }
  245.  
  246.     if( mac = find_macro( macroname )) {
  247.         char *old = mac->expansion;
  248.  
  249.         mac->flags &= ~MF_SIMPLE;
  250.         if( do_addition && old ) {
  251.             if( mac->expansion = malloc(strlen( old ) + strlen( rhs ) + 1)) {
  252.                 strcpy( mac->expansion, old );
  253.                 strcat( mac->expansion, " " );
  254.                 strcat( mac->expansion, rhs );
  255.             }
  256.         }
  257.         else mac->expansion = strdup( rhs );
  258.         if( old )
  259.             free( old );
  260.     }
  261.     else mac = new_macro( macroname, rhs );
  262.  
  263.     if( mac ) {
  264.         if( do_expansion )
  265.             mac->flags |= MF_SIMPLE;
  266.         if( !(mac->flags & MF_ADDED )) {
  267.             mac->flags |= MF_ADDED;
  268.             AddTail( &Global.macrolist, &mac->node );
  269.         }
  270.         debugprintf( 5, ( "assigned macro [%s] = [%s]\n",
  271.             mac->name, mac->expansion ));
  272.     }
  273.     else {
  274.         debugprintf( 2, ("error assigning macro [%s]\n", macroname ) );
  275.     }
  276.  
  277.     if( expansion )
  278.         free( expansion );
  279.     return( mac );
  280. death:
  281.     if( expansion )
  282.         free( expansion );
  283.     if( mac )
  284.         free( mac );
  285.     return( NULL );
  286. }
  287.  
  288. /*    read in all rules and variables from this makefile
  289. */
  290. int
  291. input_makefile( const char *makefile )
  292. {
  293.     char *curline = NULL;
  294.     char *commandline = NULL;
  295.     FILE *infile = NULL;
  296.     int targetcount = 0, macrocount = 0;
  297.     int st;
  298.  
  299.     curline = (char *)malloc( Param.MaxLine );
  300.     commandline = (char *)malloc( Param.MaxLine );
  301.     if( !curline || !commandline )
  302.         goto death;
  303.  
  304.     infile = fopen( makefile, "r" );
  305.     if( !infile ) {
  306.         logprintf( "Cannot open %s\n", makefile );
  307.         goto death;
  308.     }
  309.  
  310.     debugprintf( 3,( "input Makefile: %s\n", makefile ));
  311.  
  312.     line_number = 0;
  313.     if( st = getline( curline, Param.MaxLine, infile ))
  314.         goto death;
  315.     while( !st ) {
  316.         /* debugprintf( 5,( "getline %d: %s\n", line_number, curline )); */
  317.         if( strchr( curline, '=' )) {
  318.             macrocount++;
  319.             process_macroline( curline );
  320.  
  321.             st = getline( curline, Param.MaxLine, infile );
  322.         }
  323.         else if( isemptyline( curline )) {
  324.             st = getline( curline, Param.MaxLine, infile );
  325.         }
  326.         else {
  327.             struct List cmdList;
  328.             struct target *targ = NULL;
  329.             struct command *cmd = NULL;
  330.             char *delim;
  331.  
  332.             NewList( &cmdList );
  333.  
  334.             targetcount++;
  335.             *commandline = (char)0;
  336.  
  337.             delim = find_token( curline + 1, ':' );
  338.             if( delim ) {
  339.                 if( delim = find_token( delim + 1, ';' ) ) {
  340.                     *delim++ = (char)0;
  341.                     *commandline = '\t'; /* commandlines begin with a tab */
  342.                     strcpy( commandline + 1, delim );
  343.                 }
  344.             }
  345.  
  346.             if( st = ( *commandline ) ? 0 :
  347.                 getline( commandline, Param.MaxLine, infile )) break;
  348.             while( !st && isspace( *commandline )) {
  349.                 debugprintf( 5,("tabline %d: %s\n",line_number, commandline));
  350.                 delim = commandline;
  351.                 while( isspace( *delim )) delim++;
  352.                 if( *delim ) { /* line is not empty */
  353.                     if( cmd = new_command( delim ))
  354.                         AddTail( &cmdList, &cmd->node );
  355.                     else {
  356.                         logprintf( "Could not add command for target\n" ); 
  357.                         goto death;
  358.                     }
  359.                 }
  360.                 st = getline( commandline, Param.MaxLine, infile );
  361.             } /* while */
  362.  
  363.             debugprintf( 4, ("targetline %d is %s\n", line_number, curline));
  364.             targ = process_targetline( curline, &cmdList );
  365.             if( !targ ) {
  366.                 logprintf( "Error in Makefile before line %d: %s\n",
  367.                     line_number, curline );
  368.                 goto death;
  369.             }
  370.  
  371.             strcpy( curline, commandline );
  372.         } /* else */
  373.     } /* while */
  374.  
  375.     debugprintf( 2,( "targetcount = %d\nmacrocount = %d\n", targetcount,
  376.         macrocount ));
  377.  
  378. #if DEBUG
  379.     if( Param.debug && Param.verbosity >= 5 ) {
  380.         dump_all();
  381.     }
  382. #endif
  383.  
  384.     free( commandline );
  385.     free( curline );
  386.     fclose( infile );
  387.     return( 0 );
  388. death:
  389.     if( commandline )
  390.         free( commandline );
  391.     if( curline )
  392.         free( curline );
  393.     if( infile )
  394.         fclose( infile );
  395.     return( 1 );
  396. }
  397.