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