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

  1. /*    fncall.c
  2.  *    (c) Copyright 1991 by Ben Eng, All Rights Reserved
  3.  *
  4.  */
  5.  
  6. #include <clib/exec_protos.h>
  7.  
  8. #include <ctype.h>
  9. #include <scdir.h>
  10.  
  11. #include "make.h"
  12. #include "depend.h"
  13.  
  14. #if FNCALLS
  15.  
  16. /*    function calls (mac, string)
  17.  *
  18.  *    The string parameter is the rest of the arguments passed to the
  19.  *    function call.  string is modifiable in fncalls because it is
  20.  *    actually contained within the macroname array[] which isn't
  21.  *    really used again after the fncall returns.
  22.  *
  23.  *    returns 0 if successful, 1 if error
  24.  *    with side effect:  mac->expansion = strdup( result_string );
  25.  *
  26.  */
  27.  
  28. static char argument_missing[] = "argument missing: %s %s\n";
  29. static char error_no_memory[] = "error:  no memory\n";
  30.  
  31. static int
  32. do_basename( struct macro *mac, char *string, how_basename )
  33. {
  34.     char *filelist = NULL;
  35.     char *out, *text, *cptr;
  36.     int len = 0;
  37.     char word[ MAXPATHNAME ];
  38.  
  39.     filelist = (char *)calloc( Param.MaxLine, 1 );
  40.     if( !filelist ) {
  41.         logfile( error_no_memory );
  42.         return( 1 );
  43.     }
  44.     
  45.     out = filelist;
  46.     text = string;
  47.  
  48.     while( len < Param.MaxLine ) {
  49.         text = parse_str( word, text, sizeof(word));
  50.         if( !*word ) break; /* no more words in text */
  51.         cptr = strrchr( word, '.' );
  52.         if( how_basename ) { /* take the basename */
  53.             if( cptr && basename(word) <= cptr ) {
  54.                 *cptr = (char)0; /* truncate the word at the `.' */
  55.             }
  56.         }
  57.         else { /* take the suffix */
  58.             if( cptr && basename(word) <= cptr ) {
  59.                 shift_string_left( word, (int)(cptr - word));
  60.             }
  61.         }
  62.         len += strlen( word );
  63.         if( len + 1 < Param.MaxLine ) {
  64.             if( out != filelist ) {
  65.                 *out++ = ' ';
  66.                 len++;
  67.             }
  68.             strcpy( out, word );
  69.             out = filelist + len;
  70.         }
  71.         else break;
  72.     } /* while */
  73.     *out = (char)0;
  74.     if( len > 0 ) mac->expansion = strdup( filelist );
  75.     free( filelist );
  76.     return( 0 );
  77. }
  78.  
  79. static int
  80. fn_basename( struct macro *mac, char *string )
  81. {
  82.     return( do_basename( mac, string, 1 ));
  83. }
  84.  
  85. static int
  86. fn_suffix( struct macro *mac, char *string )
  87. {
  88.     return( do_basename( mac, string, 0 ));
  89. }
  90.  
  91. static int
  92. do_addfix( struct macro *mac, char *string, int how_fix )
  93. {
  94.     char *filelist = NULL;
  95.     char *suf, *str = string;
  96.  
  97.     filelist = (char *)calloc( Param.MaxLine, 1 );
  98.     if( !filelist ) {
  99.         logfile( error_no_memory );
  100.         return( 1 );
  101.     }
  102.  
  103.     while( isspace( *str )) str++;
  104.     suf = str;
  105.     while( *str && *str != ',' && str[-1] != '\\' ) str++;
  106.     if( *suf != ',' && *str == ',' && str[-1] != '\\' ) {
  107.         char *out, *text, *cptr;
  108.         int suflen, len = 0;
  109.         char word[ MAXPATHNAME ];
  110.  
  111.         *str++ = (char)0; /* null terminate the suffix */
  112.         suflen = strlen( suf );
  113.         out = filelist;
  114.         text = str;
  115.  
  116.         while( len < Param.MaxLine ) {
  117.             text = parse_str( word, text, sizeof(word));
  118.             if( !*word ) break; /* no more words in text */
  119.             if( (strlen( word )+suflen) < sizeof(word)) {
  120.                 if( how_fix ) /* append the suffix */
  121.                     strcat( word, suf );
  122.                 else { /* prepend the prefix */
  123.                     len += strlen( suf );
  124.                     if( len + 1 < Param.MaxLine ) {
  125.                         if( out != filelist ) {
  126.                             *out++ = ' ';
  127.                             len++;
  128.                         }
  129.                         strcpy( out, suf );
  130.                         out = filelist + len;
  131.                     }
  132.                 }
  133.             }
  134.             len += strlen( word );
  135.             if( len + 1 < Param.MaxLine ) {
  136.                 if( out != filelist & how_fix ) {
  137.                     *out++ = ' ';
  138.                     len++;
  139.                 }
  140.                 strcpy( out, word );
  141.                 out = filelist + len;
  142.             }
  143.             else break;
  144.         } /* while */
  145.         *out = (char)0;
  146.         if( len > 0 ) mac->expansion = strdup( filelist );
  147.     }
  148.     free( filelist );
  149.     return( 0 );
  150. }
  151.  
  152. static int
  153. fn_addprefix( struct macro *mac, char *string )
  154. {
  155.     return( do_addfix( mac, string, 0 ));
  156. }
  157.  
  158. static int
  159. fn_addsuffix( struct macro *mac, char *string )
  160. {
  161.     return( do_addfix( mac, string, 1 ));
  162. }
  163.  
  164. static int
  165. do_dir( struct macro *mac, char *string, int how_dir )
  166. {
  167.     char *filelist = NULL;
  168.     char *str = string;
  169.     char *out, *text, *cptr;
  170.     int len = 0;
  171.     char word[ MAXPATHNAME ];
  172.  
  173.     filelist = (char *)calloc( Param.MaxLine, 1 );
  174.     if( !filelist ) {
  175.         logfile( error_no_memory );
  176.         return( 1 );
  177.     }
  178.  
  179.     while( isspace( *str )) str++;
  180.     out = filelist;
  181.     text = str;
  182.  
  183.     while( len < Param.MaxLine ) {
  184.         text = parse_str( word, text, sizeof(word));
  185.         if( !*word ) break; /* no more words in text */
  186.         cptr = basename( word );
  187.         if( how_dir ) { /* keep only the directory part */
  188.             *cptr = (char)0;
  189.         }
  190.         else { /* prepend the prefix */
  191.             shift_string_left( word, (int)(cptr - word));
  192.         }
  193.         len += strlen( word );
  194.         if( len + 1 < Param.MaxLine ) {
  195.             if( out != filelist ) {
  196.                 *out++ = ' ';
  197.                 len++;
  198.             }
  199.             strcpy( out, word );
  200.             out = filelist + len;
  201.         }
  202.         else break;
  203.     } /* while */
  204.     *out = (char)0;
  205.     if( len > 0 ) mac->expansion = strdup( filelist );
  206.     free( filelist );
  207.     return( 0 );
  208. }
  209.  
  210. static int
  211. fn_dir( struct macro *mac, char *string )
  212. {
  213.     return( do_dir( mac, string, 1 ));
  214. }
  215.  
  216. static int
  217. fn_notdir( struct macro *mac, char *string )
  218. {
  219.     return( do_dir( mac, string, 0 ));
  220. }
  221.  
  222. static int
  223. do_filter( struct macro *mac, char *string, int how_filter )
  224. {
  225.     char *str = string;
  226.     char *pat;
  227.     int len;
  228.  
  229.     while( isspace( *str )) str++;
  230.     pat = str;
  231.     while( *str && *str != ',' && str[-1] != '\\' ) str++;
  232.     if( *pat != ',' && *str == ',' && str[-1] != '\\' ) {
  233.         char word[ 80 ];
  234.         char *text, *out;
  235.  
  236.         *str++ = (char)0;
  237.  
  238.         if( !( mac->expansion = strdup( str )))
  239.             return( 0 ); /* no mem */
  240.         out = mac->expansion;
  241.  
  242.         for( text = out;; ) {
  243.             text = parse_str( word, text, sizeof(word));
  244.             if( !*word ) break; /* no more words in text */
  245.  
  246.             if( how_filter ) {
  247.                 if( pattern_match( pat, word )) {
  248.                     out = text + 1;
  249.                 }
  250.                 else { /* no match remove it */
  251.                     while( isspace( *text )) text++;
  252.                     shift_string_left( out, (int)(text - out));
  253.                     text = out;
  254.                 }
  255.             }
  256.             else {
  257.                 if( pattern_match( pat, word )) {
  258.                     while( isspace( *text )) text++;
  259.                     shift_string_left( out, (int)(text - out));
  260.                     text = out;
  261.                 }
  262.                 else { /* no match remove it */
  263.                     out = text + 1;
  264.                 }
  265.             }
  266.         } /* for */
  267.         *out = (char)0;
  268.         return( 0 );
  269.     }
  270.     logprintf( argument_missing, "filter", string );
  271.     return( 1 );
  272. }
  273.  
  274. static int
  275. fn_filter( struct macro *mac, char *string )
  276. {
  277.     return( do_filter( mac, string, 1 ));
  278. }
  279.  
  280. static int
  281. fn_filter_out( struct macro *mac, char *string )
  282. {
  283.     return( do_filter( mac, string, 0 ));
  284. }
  285.  
  286. static int
  287. fn_findstring( struct macro *mac, char *string )
  288. {
  289.     char *find, *in, *str = string;
  290.     int len;
  291.     
  292.     while( isspace( *str )) str++;
  293.     find = str;
  294.     while( *str && *str != ',' && str[-1] != '\\' ) str++;
  295.     if( *find != ',' && *str == ',' && str[-1] != '\\' ) {
  296.         *str++ = (char)0;
  297.         in = str;
  298.         while( *str ) str++;    /* find end string */
  299.         len = strlen( find );
  300.         str -= len;    /* str marks the end of searching */
  301.  
  302.         while( in <= str ) {
  303.             /* logprintf( "looking for \"%s\" in \"%s\"\n", find, in ); */
  304.  
  305.             if( !strncmp( find, in, len )) { /* found */
  306.                 mac->expansion = strdup( find );
  307.                 break;
  308.             }
  309.             in++; 
  310.         }
  311.     }
  312.     else {
  313.         logprintf( argument_missing, "findstring", string );
  314.         return( 1 );
  315.     }
  316.     return( 0 );
  317. }
  318.  
  319. static int
  320. fn_getenv( struct macro *mac, char *string )
  321. {
  322.     char *evalue;
  323.     while( isspace( *string )) string++;
  324.  
  325.     evalue = getenv( string );
  326.     if( evalue && *evalue ) mac->expansion = strdup( evalue );
  327.     return( 0 );
  328. }
  329.  
  330. static int
  331. fn_join( struct macro *mac, char *string )
  332. {
  333.     char *filelist = NULL;
  334.     char *str = string;
  335.     char *text1, *text2;
  336.     
  337.     filelist = (char *)calloc( Param.MaxLine, 1 );
  338.     if( !filelist ) {
  339.         logfile( error_no_memory );
  340.         return( 1 );
  341.     }
  342.  
  343.     while( isspace( *str )) str++;
  344.     text1 = str;
  345.     while( *str && *str != ',' && str[-1] != '\\' ) str++;
  346.     if( *text1 != ',' && *str == ',' && str[-1] != '\\' ) {
  347.         char *out;
  348.         int len = 0;
  349.         char word1[ MAXPATHNAME ], word2[ MAXPATHNAME ];
  350.  
  351.         *str++ = (char)0; /* null terminate the suffix */
  352.         out = filelist;
  353.         text2 = str;
  354.  
  355.         *word1 = *word2 = ' '; /* dummy for first iteration */
  356.         while( len < Param.MaxLine ) {
  357.             if( *word1 ) text1 = parse_str( word1, text1, sizeof(word1));
  358.             if( *word2 ) text2 = parse_str( word2, text2, sizeof(word2));
  359.             if( !*word1 && !*word2 ) break; /* no more words */
  360.  
  361.             len += strlen( word1 ) + strlen( word2 );
  362.             if( len + 1 < Param.MaxLine ) {
  363.                 if( out != filelist ) {
  364.                     *out++ = ' ';
  365.                     len++;
  366.                 }
  367.                 strcpy( out, word1 );
  368.                 strcat( out, word2 );
  369.                 out = filelist + len;
  370.             }
  371.             else break;
  372.         } /* while */
  373.         *out = (char)0;
  374.         if( len > 0 ) mac->expansion = strdup( filelist );
  375.     }
  376.     if( filelist ) free( filelist );
  377.     return( 0 );
  378. }
  379.  
  380. static int
  381. fn_patsubst( struct macro *mac, char *string )
  382. {
  383.     char *str = string;
  384.     char *from, *to, *text;
  385.     
  386.     while( isspace( *str )) str++;
  387.     from = str;
  388.     while( *str && *str != ',' && str[-1] != '\\' ) str++;
  389.     if( *from != ',' && *str == ',' && str[-1] != '\\' ) {
  390.         *str++ = (char)0;
  391.         to = str;
  392.         while( *str && *str != ',' && str[-1] != '\\' ) str++;
  393.         if( *to != ',' && *str == ',' && str[-1] != '\\' && str[ 1 ] ) {
  394.             char *expansion = NULL, *out;
  395.             int len = 0;
  396.  
  397.             *str++ = (char)0;
  398.             while( *str && isspace( *str )) str++;
  399.             text = str;
  400.  
  401.             out = expansion = (char *)malloc( Param.MaxLine );
  402.             if( !expansion ) {
  403.                 logfile( error_no_memory );
  404.                 return( 1 );
  405.             }
  406.             while( *str ) {
  407.                 while( *str && !isspace( *str )) str++;
  408.                 if( !*str && str == text ) break;
  409.                 if( *str ) *str++ = (char)0;
  410.                 if( len + (int)(str - text) < Param.MaxLine ) {
  411.                     if( out > expansion ) {
  412.                         *out++ = ' ';
  413.                         len++;
  414.                     }
  415.                     if( pattern_match( from, text )) {
  416.                         /* needs to do bounds checking to prevent */
  417.                         /* overflowing of the expansion string! */
  418.                         /* neglected for now - user discretion advised */
  419.                         if( map_to_pattern( out, from, to, text )) break;
  420.                     }
  421.                     else strcpy( out, text );
  422.                 }
  423.                 len += strlen( out );
  424.                 out = expansion + len;
  425.                 while( *str && isspace( *str )) str++;
  426.                 text = str;
  427.             }
  428.             *out = (char)0;
  429.             if( *expansion ) mac->expansion = strdup( expansion );
  430.             free( expansion );
  431.             return( 0 );
  432.         }
  433.     }
  434.     logprintf( argument_missing, "patsubst", string );
  435.     return( 1 );
  436. }
  437.  
  438. static int
  439. sortcomp( char **s1, char **s2 )
  440. {
  441.     return( stricmp( *s1, *s2 ));
  442. }
  443.  
  444. static int
  445. fn_sort( struct macro *mac, char *string )
  446. {
  447.     int i, nel;
  448.     char **array = NULL;
  449.     char *expansion = NULL;
  450.     char *out, *str = string;
  451.  
  452.     while( isspace( *str )) str++;
  453.     nel = count_args( str );
  454.     array = (char **)calloc( sizeof(char *), nel );
  455.     expansion = (char *)malloc( Param.MaxLine );
  456.     if( !array || !expansion ) {
  457.         logfile( error_no_memory );
  458.         if( array ) free( array );
  459.         if( expansion ) free( expansion );
  460.         return( 1 );
  461.     }
  462.  
  463.     for( i = 0; i < nel && *str; i++ ) {
  464.         while( isspace( *str )) str++;
  465.         if( *str ) array[ i ] = str++;
  466.         while( !isspace( *str ) && *str ) str++;
  467.         if( isspace( *str )) *str++ = (char)0;
  468.     }
  469.  
  470.     qsort( array, nel, sizeof(char *), sortcomp );
  471.     out = expansion;
  472.     for( i = 0; i < nel; i++ ) {
  473.         if( i ) *out++ = ' ';
  474.         strcpy( out, array[ i ] );
  475.         out += strlen( out );
  476.     }
  477.  
  478.     free( array );
  479.     mac->expansion = strdup( expansion );
  480.     free( expansion );
  481.     return( 0 );
  482. }
  483.  
  484. static int
  485. fn_strip( struct macro *mac, char *str )
  486. {
  487.     while( isspace( *str )) str++;
  488.     if( *str && (mac->expansion = strdup( str ))) {
  489.         register char *d = mac->expansion;
  490.         register char *s = mac->expansion;
  491.         while( *s ) {
  492.             *d++ = *s;
  493.             if( isspace(*s)) while( isspace( *s)) s++;
  494.             else s++;
  495.         }
  496.         if( isspace( *d )) {
  497.             while( isspace( *d ) && d > mac->expansion ) d--;
  498.             d++;
  499.         }
  500.         *d = (char)0;
  501.     }
  502.     return( 0 );
  503. }
  504.  
  505. static int
  506. fn_subst( struct macro *mac, char *string )
  507. {
  508.     char *str = string;
  509.     char *from, *to, *text, *out;
  510.     char *expansion = NULL;
  511.     int fromlen, tolen;
  512.     
  513.     while( isspace( *str )) str++;
  514.     from = str;
  515.     while( *str && *str != ',' && str[-1] != '\\' ) str++;
  516.     if( *from != ',' && *str == ',' && str[-1] != '\\' ) {
  517.         *str++ = (char)0;
  518.         to = str;
  519.         while( *str && *str != ',' && str[-1] != '\\' ) str++;
  520.         if( *to != ',' && *str == ',' && str[-1] != '\\' && str[ 1 ] ) {
  521.             *str++ = (char)0;
  522.             text = str;
  523.             fromlen = strlen( from );
  524.             tolen = strlen( to );
  525.             while( *str ) str++;    /* find end string */
  526.             str -= fromlen;
  527.  
  528.             out = expansion = (char *)malloc( Param.MaxLine );
  529.             if( !expansion ) {
  530.                 logfile( error_no_memory );
  531.                 return( 1 );
  532.             }
  533.             while( text <= str ) {
  534.                 if( !strncmp( from, text, fromlen )) { /* found */
  535.                     if( (int)(out - expansion) + tolen < Param.MaxLine ) {
  536.                         strcpy( out, to );
  537.                         out += tolen;
  538.                     }
  539.                     else break;
  540.                     text += fromlen;
  541.                 }
  542.                 else if((int)(out - expansion) + tolen < Param.MaxLine ) {
  543.                     *out++ = *text++;
  544.                 }
  545.                 else break;
  546.             }
  547.             *out = (char)0;
  548.             if( *expansion ) mac->expansion = strdup( expansion );
  549.             free( expansion );
  550.             return( 0 );
  551.         }
  552.     }
  553.     logprintf( argument_missing, "subst", string );
  554.     return( 1 );
  555. }
  556.  
  557. static int
  558. fn_wildcard( struct macro *mac, char *string )
  559. {
  560.     char *filelist = NULL;
  561.     char *pat = string;
  562.  
  563.     filelist = (char *)calloc( Param.MaxLine, 1 );
  564.     if( !filelist ) {
  565.         logfile( error_no_memory );
  566.         return( 1 );
  567.     }
  568.     while( isspace( *pat )) pat++;
  569.     if( *pat ) {
  570.         char *out = filelist;
  571.         char *fn;
  572.         int len = 0;
  573.  
  574.         while( len < Param.MaxLine ) {
  575.             if( !(fn = scdir( pat ))) break; /* no more */
  576.             if( out != filelist ) {
  577.                 *out++ = ' ';
  578.                 len++;
  579.             }
  580.             len += strlen( fn );
  581.             if( len < Param.MaxLine ) {
  582.                 strcpy( out, fn );
  583.                 out = filelist + len;
  584.             }
  585.         }
  586.         if( len > 0 ) mac->expansion = strdup( filelist );
  587.         scdir_abort();
  588.     }
  589.     free( filelist );
  590.     return( 0 );
  591. }
  592.  
  593.  
  594. int
  595. do_word( struct macro *mac, char *string, int word )
  596. {
  597.     char *begin, *end;
  598.  
  599.     if( begin = find_word( string, word )) {
  600.         end = begin;
  601.         while( *end && !isspace( *end )) end++;
  602.         *end = (char)0; /* null terminate past the end of word */
  603.         mac->expansion = strdup( begin );
  604.     }
  605.     return( 0 );
  606. }
  607.  
  608. static int
  609. fn_firstword( struct macro *mac, char *string )
  610. {
  611.     while( isspace( *string )) string++;
  612.     return( do_word( mac, string, 1 ));
  613. }
  614.  
  615. static int
  616. fn_word( struct macro *mac, char *string )
  617. {
  618.     char *comma;
  619.     int word;
  620.  
  621.     while( isspace( *string )) string++;
  622.     if( *string && (comma = find_token( string, ',' ))) {
  623.         *comma = (char)0;
  624.         word = atoi( string );
  625.         /* else word not found */
  626.         return( do_word( mac, comma + 1, word ));
  627.     }
  628.     logprintf( argument_missing, "word", string );
  629.     return( 1 );
  630. }
  631.  
  632. static int
  633. fn_words( struct macro *mac, char *string )
  634. {
  635.     char buf[ 20 ];
  636.     sprintf( buf, "%d", count_args( string ));
  637.     mac->expansion = strdup( buf );
  638.     return( 0 );
  639. }
  640.  
  641. static int
  642. fn_notimp( struct macro *mac, char *string )
  643. {
  644.     logfile( "Function call not implemented\n" );
  645.     return( 1 );
  646. }
  647.  
  648. /*************************************************************************/
  649.  
  650. /* sorted array for binary search */
  651. #define MAX_FNCALL 22
  652. static struct fncall fncarray[ MAX_FNCALL ] = {
  653.     "addprefix",    fn_addprefix,
  654.     "addsuffix",    fn_addsuffix,
  655.     "basename",        fn_basename,
  656.     "dir",            fn_dir,
  657.     "filter",        fn_filter,
  658.     "filter-out",    fn_filter_out,
  659.     "findstring",    fn_findstring,
  660.     "firstword",    fn_firstword,
  661.     "foreach",        fn_notimp,
  662.     "getenv",        fn_getenv,
  663.     "join",            fn_join,
  664.     "notdir",        fn_notdir,
  665.     "origin",        fn_notimp,
  666.     "patsubst",        fn_patsubst,
  667.     "shell",        fn_notimp,
  668.     "sort",            fn_sort,
  669.     "strip",        fn_strip,
  670.     "subst",        fn_subst,
  671.     "suffix",        fn_suffix,
  672.     "wildcard",        fn_wildcard,
  673.     "word",            fn_word,
  674.     "words",        fn_words
  675. };
  676.  
  677. /*    binary search to find the function */
  678. struct fncall *
  679. find_fncall( char *name )
  680. {
  681.     register struct fncall *array = fncarray;
  682.     int first = 0L;
  683.     int last = MAX_FNCALL - 1;
  684.     int mid;
  685.     int diff;
  686.  
  687.     /* binary search */
  688.     while( first <= last ) {
  689.         mid = (first+last) / 2;
  690.         diff = stricmp( name, array[ mid ].name );
  691.         if( !diff )
  692.             return( &array[ mid ] ); /* found */
  693.         if( first == last ) break; /* not found */
  694.         if( diff < 0 ) last = mid - 1;
  695.         else first = mid + 1;
  696.     }
  697.     return( NULL ); /* not found */
  698. }
  699.  
  700. #else
  701.  
  702. /*    No FNCALLS */
  703. struct fncall *
  704. find_fncall( char *name )
  705. {
  706.     return( NULL ); /* not found */
  707. }
  708.  
  709. #endif
  710.  
  711.