home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d523 / bmake.lha / BMake / source.lzh / cond.c < prev    next >
C/C++ Source or Header  |  1991-07-20  |  6KB  |  254 lines

  1. /*    cond.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 <fcntl.h>
  10.  
  11. #include "make.h"
  12. #include "depend.h"
  13. #include "cond.h"
  14.  
  15. /*    binary search to find the function */
  16. struct drctvs *
  17. find_drctvs( struct drctvs *array, int array_size, char *name )
  18. {
  19.     int first = 0L;
  20.     int last = array_size - 1;
  21.     int mid;
  22.     int diff, len;
  23.  
  24.     /* binary search */
  25.     while( first <= last ) {
  26.         mid = (first+last) / 2;
  27.         len = strlen( array[ mid ].directive );
  28.         diff = strncmp( name, array[ mid ].directive, len );
  29.         if( !diff ) return( &array[ mid ] ); /* found */
  30.         if( first == last ) break; /* not found */
  31.         if( diff < 0 ) last = mid - 1;
  32.         else first = mid + 1;
  33.     }
  34.     return( NULL ); /* not found */
  35. }
  36.  
  37. int
  38. push_state( struct List *stack, long state )
  39. {
  40.     struct mstate *new = (struct mstate *)malloc( sizeof(struct mstate));
  41.     if( !new ) return( 1 ); /* no memory */
  42.     new->node.ln_Type = NT_USER;
  43.     new->state = state;
  44.     AddHead( stack, &new->node );
  45.     return( 0 );
  46. }
  47.  
  48. int
  49. pop_state( struct List *stack )
  50. {
  51.     struct mstate *new = (struct mstate *)RemHead( stack );
  52.     int state;
  53.     if( !new ) return( 0 ); /* no state */
  54.     state = new->state;
  55.     free( new );
  56.     return( state );
  57. }
  58.  
  59. void
  60. clear_stack( struct List *stack )
  61. {
  62.     struct Node *node, *succ;
  63.  
  64.     for( node = stack->lh_Head; node->ln_Succ; node = succ ) {
  65.         succ = node->ln_Succ;
  66.         free( node );
  67.     }
  68.     NewList( stack );
  69. }
  70.  
  71. /*    returns true if we are still within a conditional */
  72. int
  73. get_directive_state( struct List *stack )
  74. {
  75.     struct mstate *first = (struct mstate *)stack->lh_Head;
  76.     if( !first->node.ln_Succ ) return( 0 );
  77.     return( first->state );
  78. }
  79.  
  80. /* conditions return 0 for false, 1 for true, -1 for error */
  81. int
  82. do_condeq( char *string, int negate )
  83. {
  84.     char *exp1 = NULL, *exp2 = NULL;
  85.     char *lparen = string, *comma, *rparen;
  86.     int retval = -1; /* default to error */
  87.  
  88.     exp1 = (char*)malloc( Param.MaxLine );
  89.     exp2 = (char*)malloc( Param.MaxLine );
  90.     if( !exp1 || !exp2 ) goto death;
  91.  
  92.     while( *lparen && *lparen != '(' ) lparen++;
  93.     if( *lparen != '(' ) goto death;
  94.     comma = lparen + 1;
  95.     while( *comma && *comma != ',' ) comma++;
  96.     if( *comma != ',' ) goto death;
  97.     rparen = comma + 1;
  98.     while( *rparen && *rparen != ')' ) rparen++;
  99.     if( *rparen != ')' ) goto death;
  100.  
  101.     *comma = *rparen = (char)0;
  102.     if( expand_macros( exp1, lparen + 1, Param.MaxLine ) ||
  103.         expand_macros( exp2, comma + 1, Param.MaxLine )) goto death;
  104.  
  105.     if( negate )
  106.         retval = stricmp( exp1, exp2 ) ? 1 : 0; /* set condition code */
  107.     else
  108.         retval = stricmp( exp1, exp2 ) ? 0 : 1; /* set condition code */
  109.  
  110. death:
  111.     if( exp1 ) free( exp1 );
  112.     if( exp2 ) free( exp2 );
  113.     return( retval );
  114. }
  115.  
  116. int
  117. do_conddef( char *string, int negate )
  118. {
  119.     char *lparen = string, *rparen;
  120.     int retval = -1; /* default to error */
  121.  
  122.     while( *lparen && *lparen != '(' ) lparen++;
  123.     if( *lparen != '(' ) goto death;
  124.     rparen = lparen + 1;
  125.     while( *rparen && *rparen != ')' ) rparen++;
  126.     if( *rparen != ')' ) goto death;
  127.  
  128.     *rparen = (char)0;
  129.     retval = find_macro( lparen + 1 ) ? 1 : 0;
  130.     if( negate ) retval = retval ? 0 : 1;
  131. death:
  132.     return( retval );
  133. }
  134.  
  135. int
  136. do_condexists( char *string, int negate )
  137. {
  138.     char *lparen = string, *rparen;
  139.     int retval = -1; /* default to error */
  140.  
  141.     while( *lparen && *lparen != '(' ) lparen++;
  142.     if( *lparen != '(' ) goto death;
  143.     rparen = lparen + 1;
  144.     while( *rparen && *rparen != ')' ) rparen++;
  145.     if( *rparen != ')' ) goto death;
  146.  
  147.     *rparen = (char)0;
  148.     retval = access( lparen + 1, 0 ) ? 0 : 1;
  149.     if( negate ) retval = retval ? 0 : 1;
  150. death:
  151.     return( retval );
  152. }
  153.  
  154. int
  155. cdrctv_eq( char *string )
  156. {
  157.     return( do_condeq( string, 0 ));
  158. }
  159. int
  160. cdrctv_neq( char *string )
  161. {
  162.     return( do_condeq( string, 1 ));
  163. }
  164.  
  165. int
  166. cdrctv_def( char *string )
  167. {
  168.     return( do_conddef( string, 0 ));
  169. }
  170. int
  171. cdrctv_ndef( char *string )
  172. {
  173.     return( do_conddef( string, 1 ));
  174. }
  175.  
  176. int
  177. cdrctv_exists( char *string )
  178. {
  179.     return( do_condexists( string, 0 ));
  180. }
  181. int
  182. cdrctv_nexists( char *string )
  183. {
  184.     return( do_condexists( string, 1 ));
  185. }
  186.  
  187. /* keep it sorted for binary search */
  188. struct drctvs carray[ MAX_CDRCTVS ] = {
  189.     { "def",     cdrctv_def    },
  190.     { "eq",      cdrctv_eq    },
  191.     { "exists",    cdrctv_exists },
  192.     { "ndef",    cdrctv_ndef    },
  193.     { "neq",     cdrctv_neq    },
  194.     { "nexists",    cdrctv_nexists }
  195. };
  196.  
  197. int
  198. drctv_else( char *string, struct List *stack )
  199. {
  200.     int state = pop_state( stack );
  201.     int newstate = 0;
  202.  
  203.     if( state != STATE_IF_T && state != STATE_IF_F ) {
  204.         logfile( "ERROR:  else with no matching conditional\n" );
  205.         return( 1 );
  206.     }
  207.     newstate = (state == STATE_IF_T) ? STATE_EL_T : STATE_EL_F;
  208.     debugprintf( 4, ("else changes state from %d to %d\n",
  209.         state, newstate ));
  210.     push_state( stack, newstate );
  211.     return( 0 );
  212. }
  213.  
  214. int
  215. drctv_endif( char *string, struct List *stack )
  216. {
  217.     int state = pop_state( stack );
  218.  
  219.     if( !state ) {
  220.         logfile( "ERROR:  endif with no matching conditional\n" );
  221.         return( 1 );
  222.     }
  223.     return( 0 );
  224. }
  225.  
  226. int
  227. drctv_if( char *string, struct List *stack )
  228. {
  229.     struct drctvs *cdrctv;
  230.     int condition;
  231.  
  232.     while( isspace( *string )) string++;
  233.     if( !*string ) {
  234.         logfile( "No condition given\n" );
  235.         return( 1 );
  236.     }
  237.  
  238.     if( cdrctv = find_drctvs( carray, MAX_CDRCTVS, string )) {
  239.         debugprintf( 4, ("condition %s\n", string ));
  240.         condition = (*cdrctv->call)( string + strlen( cdrctv->directive ));
  241.         debugprintf( 4, ("condition returns %d\n", condition ));
  242.         if( condition < 0 ) {
  243.             logprintf( "Error in condition: %s\n", string );
  244.             return( 1 );
  245.         }
  246.         else {
  247.             push_state( stack, ( condition ? STATE_IF_T : STATE_IF_F ));
  248.             return( 0 );
  249.         }
  250.     }
  251.     logprintf( "Unrecognized condition: %s\n", string );
  252.     return( 1 );
  253. }
  254.