[net.micro.amiga] "make" for the Amiga

aaz@pucc-j (Marc Mengel) (12/06/85)

     Here is a (painfully) simple version of make (everyones favorite
     unix utility) I hacked together for the Amiga.  It only does
     explicit rules, and doesn't quite figure out when it doesn't know
     how to make something...  but It does work.  I may give it some
     useful options (like make -t) in the future, but right now it
     only knows -f (for a makefile other than Makefile) and -d (which
     prints hoards of debug info).  Included here is a sample makefile
     that can be used to compile/maintain/alter it.  (You will need
     to change the specification of where the include librarys are...)

     The following is a shell archive.  Give it as input to a shell...
-----------------------------cut here--------------------------------------
sed -e "s/^X//" > Makefile << Y
XSRC = make.c vars.c rules.c
XHDR = vars.h rules.h
XOBJ = make.o vars.o rules.o
X
Xmake : ${OBJ}
X   alink \
X         from    cbench:lib/Lstartup.obj+make.o+vars.o+rules.o \
X         library cbench:lib/lc.lib+cbench:lib/amiga.lib \
X         to      make \
X         map     nil:
X
Xmake.o : make.c vars.h rules.h
X   lc -icbench:include/ make.c
X
Xvars.o : vars.c vars.h
X   lc vars.c
X
Xrules.o : rules.c rules.h
X   lc rules.c
X
Xlist : makefile ${SRC} ${HDR}
X   echo "on what?"
X
Xclean :
X   rm ${OBJ}
Y
sed -e "s/^X//" > make.c << Y
X#include "rules.h"
X#include "vars.h"
X#include <stdio.h>
X#include <libraries/dos.h>
X
Xint debug;
Xlong int days, mins, secs;
X
Xmain( argc, argv )
X   int argc;
X   char **argv;
X{
X   FILE *MakeFile;
X   int i,j;
X
X   printf("Make V1.0 (c) 1985 by General Overall Design.\n");
X   printf("May (only) be distributed free of charge.\n");
X   /* General Overall Design
X    * P.O. Box 2039
X    * W. Lavayette IN 47906
X    */
X   if( argc > 2 && strcmp(argv[1], "-f")==0 ){       /* make -f file ... */
X      MakeFile = fopen( argv[2] , "r" );
X      argc -= 2;
X      argv += 2;
X   } else
X      MakeFile = fopen("makefile" , "r");
X
X   if( argc > 1 && strcmp( argv[1], "-d" ) == 0 ){
X      debug=1;
X      argc--;
X      argv++;
X      printf("debug on.\n");
X   }
X
X   if( MakeFile == NULL ){                  /* open failed  */
X      printf("make: can't open makefile\n");
X      exit( 1 );
X   }
X   if ( debug )
X      printf("makefile open\n");
X
X   Parse( MakeFile );
X
X   if( debug ){
X      printf("Variables:\n");
X      for( i=0 ; i < n_Vars ; i++ )
X         printf( "%s = '%s'\n", avr_Vars[i].pch_name , avr_Vars[i].string );
X      printf("Rules:\n");
X      for( i=0 ; i < n_Rules ; i++ ){
X         printf( "%s : ", arl_Rules[i].pch_target );
X         for( j = 0; j < arl_Rules[i].c_depend; j++ )
X            printf("'%s' ", arl_Rules[i].apch_depend[ j ] );
X         printf("\n");
X         for( j = 0; j < arl_Rules[i].c_action; j++ )
X            printf("%s\n", arl_Rules[i].apch_action[j] );
X      }
X   }
X
X   if( argc == 1 )
X      make( arl_Rules[0].pch_target, &days, &mins, &secs );
X   else
X      while( --argc != 0 )
X         make( *++argv, &days, &mins, &secs );
X
X   printf("done.\n");
X}
X
Xstatic char *GetLine(), *NextWord(), *malloc();
X
XParse( fd )
X    FILE *fd;
X{
X    char *pch_Position, *pch_Word, *pch_Target;
X
X    pch_Position = GetLine( fd );
X    while( pch_Position ){
X        if( debug )
X           printf("Parsing:%s\n", pch_Position );
X        if( '#' == *pch_Position ){
X            pch_Position = GetLine(fd);
X            continue;
X        }
X        pch_Word = pch_Position;
X        pch_Position = NextWord( pch_Position );
X        if( *pch_Position == '=' ){
X            DefineVar( pch_Word, ++ pch_Position );
X            pch_Position = GetLine( fd );
X        } else {
X            pch_Target = pch_Word;
X            pch_Word = pch_Position = NextWord( pch_Position );
X            pch_Position = NextWord( pch_Position );
X            while( pch_Word ){
X                 AddDependant( pch_Word, pch_Target );
X                 pch_Word = pch_Position;
X                 pch_Position = NextWord( pch_Position );
X            }
X            pch_Position = GetLine( fd );
X            while( ' ' == *pch_Position ){
X                 AddAction( pch_Position , pch_Target );
X                 pch_Position = GetLine( fd );
X            }
X        }
X    }
X}
X
Xchar *
XNextWord( pch )
X    char *pch;
X{
X    if( NULL == pch || NULL == *pch )
X        return NULL;
X    while( *pch && *pch != ' ' && *pch != '\t' && *pch != ',' )
X        pch++;
X    if( *pch == '\0' )
X        return NULL;
X    else
X        *pch = '\0';
X    do
X        pch++;
X    while ( *pch && (' ' == *pch || '\t' == *pch || ',' == *pch ));
X    if(*pch == '\0')
X        return NULL;
X    else
X        return pch;
X}
X
X/* states for GetLine */
X#define HALT        -1
X#define IGNOREWHITE  0
X#define START        1
X#define NONWHITE     2
X#define BACKSLASH    3
X#define VARIABLE     4
Xchar *names[]={"ignorewhite","start","nonwhite","backslash","variable"};
X
Xstatic char *
XGetLine( fd )
X   FILE *fd;
X{
X   static char buf[ 1024 ];
X   auto int pos = 0;
X   auto int state = START;
X   int ch;
X   char *pch_var, *pch_replace;
X
X   ch = getc(fd);
X   if( EOF == ch )
X      return NULL;
X   while( state != HALT ){
X       if( debug )
X          printf( "state: %s\n", names[state]);
X       switch( state ){
X       case IGNOREWHITE:
X                  if ( ' ' == ch || '\t' == ch || ',' == ch )
X                      ch = getc(fd);
X                  else
X                      state = START;
X                  break;
X       case START:
X                  if( ' ' == ch || '\t' == ch || ',' == ch ) {
X                      buf[pos++] = ch;
X                      ch = getc(fd);
X                      state = IGNOREWHITE;
X                      break;
X                  } else if( '$' == ch ) {
X                      state = VARIABLE;
X                      ch = getc(fd);
X                      break;
X                  } else if( '\\' == ch ) {
X                      ch = getc(fd);
X                      state = BACKSLASH;
X                      break;
X                  } else if( '\n' == ch || EOF == ch ) {
X                      state = HALT;
X                      break;
X                  } else {
X                      state = NONWHITE;
X                      break;
X                  }
X     case NONWHITE :
X                 if( ch != EOF && ch != '\n' && ch != '$' &&
X                     ch != '\\' && ch != ' ' && ch != '\t' && ch != ',' ) {
X                      buf[ pos++ ] = ch;
X                      ch = getc(fd);
X                 } else
X                      state = START;
X                 break;
X     case BACKSLASH:
X                 if( ch != '\n' ){
X                    buf[pos++] = '\\';
X                    buf[pos++] = ch;
X                 }
X                 ch = getc(fd );
X                 state = START;
X                 break;
X     case VARIABLE:
X                 if( '$' == ch ) {
X                    buf[pos++] = ch;
X                    state = START;
X                 } else if ( '{'== ch || '(' == ch ) {
X                    ch = getc(fd);
X                    pch_var = &buf[ pos ];
X                    while ( ')' != ch && '}' != ch ){
X                         buf[ pos++ ] = ch;
X                         ch = getc(fd);
X                    }
X                    ch = getc(fd);
X                    buf[pos]=NULL;
X                    pch_replace = VarLookup( pch_var );
X                    strcpy( pch_var , pch_replace );
X                    pos = strlen( buf );
X                    state = START;
X                 }
X                 break;
X         }
X     }
X     buf[pos] = NULL;
X     if( debug )
X        printf("buf='%s'\n", buf );
X     pch_replace = malloc( strlen(buf) + 1 );
X     if( pch_replace == NULL ){
X        printf("make: out of memory" );
X        exit(1);
X     }
X     strcpy( pch_replace , buf );
X     return pch_replace;
X}
X
Xmake( pch_Target, mydays, mymins, mytics )
X   char *pch_Target;
X   long int *mydays, *mymins, *mytics;
X{
X   long int hisdays, hismins, histics;
X   int fl_Action;
X   char **depends, **actions;
X
X   GetDate( pch_Target, mydays, mymins, mytics );
X   if( debug )
X      printf("make(): %s %ld %ld:%ld\n",pch_Target,*mydays,*mymins,*mytics );
X   depends = GetDependants( pch_Target );
X   actions = GetActions( pch_Target );
X   fl_Action = *mydays == 0 && *mymins == 0 && *mytics == 0;
X   while( *depends ){
X      if( make( *depends++, &hisdays, &hismins, &histics ) )
X         fl_Action = 1;
X      if( hisdays > *mydays || (hisdays == *mydays &&
X          ( hismins > *mymins || (hismins == *mymins && histics > *mytics ))))
X         fl_Action = 1;
X   }
X   if( fl_Action )
X      while( *actions ) {
X          printf("%s\n", *actions );
X          Execute( *actions, 0, 0 );
X          actions++;
X      }
X   return fl_Action;
X}
X
XGetDate( pch_FileName, days, mins, secs )
X   char *pch_FileName;
X   long int *days, *mins, *secs;
X{
X   static struct FileInfoBlock buf;
X   char *p;
X
X   if( p = (char *)Lock( pch_FileName, ACCESS_READ )){
X      if( Examine( p , &buf ) ) {
X         *days = buf.fib_Date.ds_Days;
X         *mins = buf.fib_Date.ds_Minute;
X         *secs = buf.fib_Date.ds_Tick;
X      } else
X         printf("Couldn't get info for %s\n", pch_FileName );
X      UnLock( p );
X   } else {
X      if ( debug )
X         printf("couldn't lock %s\n", pch_FileName );
X      *days = *mins = *secs = 0;
X   }
X}
Y
sed -e "s/^X//" > rules.c << Y
X#include "rules.h"
Xextern int debug;
X
XAddDependant( pch_name, pch_target )
X   char *pch_name, *pch_target;
X{
X   int pos;
X
X   pos = _Lookup( pch_target );
X   if( debug )
X      printf("Found %s at pos %d\n", pch_target, pos );
X   arl_Rules[ pos ].apch_depend[ arl_Rules[ pos ].c_depend++ ] = pch_name;
X}
X
Xchar **
XGetDependants( pch_target )
X   char *pch_target;
X{
X   int pos;
X
X   pos = _Lookup( pch_target );
X   return arl_Rules[ pos ].apch_depend;
X}
X
XAddAction( pch_action, pch_target )
X   char *pch_action, *pch_target;
X{
X   int pos;
X
X   pos = _Lookup( pch_target );
X   if( debug )
X      printf("Found %s at pos %d\n", pch_target, pos );
X   arl_Rules[ pos ].apch_action[ arl_Rules[ pos ].c_action++ ] = pch_action;
X}
X
Xchar **
XGetActions( pch_target )
X   char *pch_target;
X{
X   int pos;
X
X   pos = _Lookup( pch_target );
X   return arl_Rules[ pos ].apch_action;
X}
X
Xint n_Rules = 0;
Xstruct rule arl_Rules[ MAXRULES ];
X
X_Lookup( pch_target )
X   char *pch_target;
X{
X   int pos = 0;
X
X   arl_Rules[ n_Rules ].pch_target = pch_target;
X   arl_Rules[ n_Rules ].c_action = 0;
X   arl_Rules[ n_Rules ].c_depend = 0;
X   while( strcmp( arl_Rules[pos].pch_target , pch_target ) )
X      pos++;
X   if ( pos == n_Rules )
X      n_Rules++;
X   return pos;
X}
Y
sed -e "s/^X//" > rules.h << Y
X#define MAXDEPEND 100
X#define MAXACTION 20
X#define MAXRULES  50
X
X/*
X * struct rule -- storage for a rule of the form
X *
X * target : depend[0] depend[1] ... depend[c_depend]
X *        action[0]
X *        action[1]
X *           :
X *        action[c_action]
X *
X */
X 
Xextern struct rule {
X    char *pch_target;
X    int  c_depend;
X    char *apch_depend[ MAXDEPEND ];
X    int c_action;
X    char *apch_action[ MAXACTION ];
X} arl_Rules[ MAXRULES ];
X
Xextern int n_Rules;
Xextern char **GetDependants(), **GetActions();
Y
sed -e "s/^X//" > vars.c << Y
X#include "vars.h"
X#define NULL 0
Xextern int debug;
X
XDefineVar( pch_varname , pch_value )
X   char *pch_varname, *pch_value;
X{
X   int pos;
X
X   pos = _Lookup( pch_varname );
X   if( debug )
X      printf( "Found var '%s' at position %d, defining as %s\n", pch_varname,pos, pch_value );
X   if( NULL != avr_Vars[ pos ].string)
X      printf("Redefining %s\n", pch_varname );
X   avr_Vars[pos].string = pch_value;
X}
X
Xchar *
XVarLookup( pch_varname )
X   char *pch_varname;
X{
X   int pos;
X
X   pos = _Lookup( pch_varname );
X   if( debug )
X      printf("found '%s' at position %d, value is %s\n", pch_varname, pos, avr_Vars[pos].string );
X   return avr_Vars[pos].string;
X}
X
Xstatic int
X_Lookup( pch_varname )
X   char *pch_varname;
X{
X   int pos;
X
X   avr_Vars[n_Vars].pch_name = pch_varname;
X   avr_Vars[n_Vars].string = NULL;
X   pos = 0;
X   while( strcmp(pch_varname, avr_Vars[pos].pch_name ))
X      pos++;
X   if( pos == n_Vars )
X      n_Vars++;
X   return pos;
X}
X
Xint n_Vars = 0;
Xstruct var avr_Vars[ MAXVARS ];
Y
sed -e "s/^X//" > vars.h << Y
X#define MAXVARS 50
X
X/*
X * struct var -- storage for variable
X *            assignments of the form
X *
X * name = string
X *
X */
X
Xextern struct var {
X   char *pch_name;
X   char *string;
X} avr_Vars[ MAXVARS ];
X
Xextern int n_Vars;    /* count of defined variables */
Xextern DefineVar();
Xextern char *VarLookup();
Y