LCOV - code coverage report
Current view: top level - libreoffice/dmake - function.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 192 324 59.3 %
Date: 2012-12-17 Functions: 8 15 53.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             : --
       3             : -- SYNOPSIS
       4             : --      GNU style functions for dmake.
       5             : --
       6             : -- DESCRIPTION
       7             : --  All GNU style functions understood by dmake are implemented in this
       8             : --  file.  Currently the only such function is $(mktmp ...) which is
       9             : --  not part of GNU-make is an extension provided by dmake.
      10             : --
      11             : -- AUTHOR
      12             : --      Dennis Vadura, dvadura@dmake.wticorp.com
      13             : --
      14             : -- WWW
      15             : --      http://dmake.wticorp.com/
      16             : --
      17             : -- COPYRIGHT
      18             : --      Copyright (c) 1996,1997 by WTI Corp.  All rights reserved.
      19             : --
      20             : --      This program is NOT free software; you can redistribute it and/or
      21             : --      modify it under the terms of the Software License Agreement Provided
      22             : --      in the file <distribution-root>/readme/license.txt.
      23             : --
      24             : -- LOG
      25             : --      Use cvs log to obtain detailed change logs.
      26             : */
      27             : 
      28             : #include "extern.h"
      29             : 
      30             : static char *_exec_mktmp  ANSI((char *, char *, char *));
      31             : static char *_exec_subst  ANSI((char *, char *, char *));
      32             : static char *_exec_iseq   ANSI((char *, char *, char *, int));
      33             : static char *_exec_sort   ANSI((char *));
      34             : static char *_exec_echo   ANSI((char *));
      35             : static char *_exec_uniq   ANSI((char *));
      36             : static char *_exec_shell  ANSI((char *, int));
      37             : static char *_exec_call   ANSI((char *, char *));
      38             : static char *_exec_assign ANSI((char *));
      39             : static char *_exec_foreach ANSI((char *, char *, char *));
      40             : static char *_exec_andor  ANSI((char *, int));
      41             : static char *_exec_not    ANSI((char *));
      42             : static int   _mystrcmp    ANSI((const DMPVOID, const DMPVOID));
      43             : 
      44             : 
      45             : PUBLIC char *
      46       29592 : Exec_function(buf)/*
      47             : ====================
      48             :    Execute the function given by the value of args.
      49             : 
      50             :    So far mktmp is the only valid function, anything else elicits and error
      51             :    message.  It is my hope to support the GNU style functions in this portion
      52             :    of the code at some time in the future. */
      53             : char *buf;
      54             : {
      55             :    char *fname;
      56             :    char *args;
      57             :    char *mod1;
      58       29592 :    char *mod2 = NIL(char);
      59       29592 :    int mod_count = 0;
      60       29592 :    char *res  = NIL(char);
      61             : 
      62             :    /* This must succeed since the presence of ' ', \t or \n is what
      63             :     * determines if this function is called in the first place.
      64             :     * Unfortunately this prohibits the use of whitespaces in parameters
      65             :     * for macro functions. */
      66             :    /* ??? Using ScanToken to find the next ' ', \t or \n and discarding
      67             :     * the returned, evaluated result is a misuse of that function. */
      68       29592 :    FREE(ScanToken(buf, &args, FALSE));
      69       29592 :    fname = DmSubStr(buf, args);
      70             :    /* args points to the whitespace after the found token, this leads
      71             :     * to leading whitespaces. */
      72       29592 :    if( *args ) {
      73       29592 :       args = DmStrSpn(args," \t"); /* strip whitespace before */
      74       29592 :       if( *args ) {                /* ... and after value */
      75             :      char *q;
      76       29592 :      for(q=args+strlen(args)-1; ((*q == ' ')||(*q == '\t')); q--);
      77       29592 :      *++q = '\0';
      78             :       }
      79             :    }
      80             : 
      81             :    /* ??? Some function macros expect comma seperated parameters, but
      82             :     * no decent parser is included. The desirable solution would be
      83             :     * to parse fname for the correct number of parameters in fname
      84             :     * when a function is recognized. We only count the parameters
      85             :     * at the moment. Note "" is a valid parameter. */
      86       29592 :    if( (mod1 = strchr(fname,',')) != NIL(char) ){
      87       27528 :       *mod1 = '\0';
      88       27528 :       mod1++;
      89       27528 :       mod_count++;
      90             : 
      91       27528 :       if( (mod2 = strchr(mod1,',')) != NIL(char) ){
      92       26336 :      *mod2 = '\0';
      93       26336 :      mod2++;
      94       26336 :      mod_count++;
      95             :       }
      96             :    }
      97             : 
      98             :    /* ??? At the moment only the leading part of fname compared if it
      99             :     * matches a known function macro. For example assignXXX or even
     100             :     * assign,,,, is also erroneously accepted. */
     101       29592 :    switch( *fname ) {
     102             :       case 'a':
     103          22 :      if(strncmp(fname,"assign",6) == 0)
     104          22 :         res = _exec_assign(args);
     105           0 :          else if(strncmp(fname,"and",3) == 0)
     106           0 :             res = _exec_andor(args, TRUE);
     107             :          else
     108           0 :             res = _exec_call(fname,args);
     109          22 :      break;
     110             : 
     111             :       case 'e':
     112         310 :      if(strncmp(fname,"eq",2) == 0)
     113         310 :         if( mod_count == 2 )
     114         310 :           res = _exec_iseq(mod1,mod2,args,TRUE);
     115             :         else
     116           0 :           Fatal( "Two comma-seperated arguments expected in [%s].\n", buf );
     117           0 :      else if (strncmp(fname,"echo",4) == 0)
     118           0 :         res = _exec_echo(args);
     119             :          else
     120           0 :             res = _exec_call(fname,args);
     121         310 :      break;
     122             : 
     123             :       case 'f':
     124        5796 :      if(strncmp(fname,"foreach",7) == 0)
     125        5796 :         if( mod_count == 2 )
     126        5796 :           res = _exec_foreach(mod1,mod2,args);
     127             :         else
     128           0 :           Fatal( "Two comma-seperated arguments expected in [%s].\n", buf );
     129             :      else
     130           0 :         res = _exec_call(fname,args);
     131        5796 :      break;
     132             : 
     133             :       case 'm':
     134         362 :      if(strncmp(fname,"mktmp",5) == 0)
     135         362 :         if( mod_count < 3 )
     136         362 :           res = _exec_mktmp(mod1,mod2,args);
     137             :         else
     138           0 :           Fatal( "Maximal two comma-seperated arguments expected in [%s].\n", buf );
     139             :      else
     140           0 :         res = _exec_call(fname,args);
     141         362 :      break;
     142             : 
     143             :       case 'n':
     144        1192 :      if( strncmp(fname,"null", 4) == 0 )
     145        1192 :         res = _exec_iseq(mod1,NIL(char),args,TRUE);
     146           0 :      else if (strncmp(fname,"nil",3) == 0 ) {
     147           0 :         FREE(Expand(args));
     148           0 :         res = DmStrDup("");
     149             :      }
     150           0 :      else if (strncmp(fname,"not",3) == 0 )
     151           0 :         res = _exec_not(args);
     152           0 :      else if (strncmp(fname,"normpath",8) == 0 ) {
     153           0 :         char *eargs = Expand(args);
     154             : 
     155           0 :         if( mod_count == 0 ) {
     156           0 :            res = exec_normpath(eargs);
     157             :         }
     158           0 :         else if( mod_count == 1 ) {
     159           0 :            char *para = Expand(mod1);
     160           0 :            int tmpUseWinpath = UseWinpath;
     161             : 
     162           0 :            if( !*para || strcmp(para, "\"\"") == 0 ) {
     163           0 :           UseWinpath = FALSE;
     164             :            } else {
     165           0 :           UseWinpath = TRUE;
     166             :            }
     167           0 :            res = exec_normpath(eargs);
     168           0 :            UseWinpath = tmpUseWinpath;
     169           0 :            FREE(para);
     170             :         }
     171             :         else
     172           0 :            Fatal( "One or no comma-seperated arguments expected in [%s].\n", buf );
     173             : 
     174           0 :         FREE(eargs);
     175             :      }
     176             :          else
     177           0 :             res = _exec_call(fname,args);
     178        1192 :      break;
     179             : 
     180             :       case '!':
     181           0 :      if(strncmp(fname,"!null",5) == 0)
     182           0 :         res = _exec_iseq(mod1,NIL(char),args,FALSE);
     183           0 :      else if(strncmp(fname,"!eq",3) ==0)
     184           0 :         if( mod_count == 2 )
     185           0 :           res = _exec_iseq(mod1,mod2,args,FALSE);
     186             :         else
     187           0 :           Fatal( "Two comma-seperated arguments expected in [%s].\n", buf );
     188             :      else
     189           0 :         res = _exec_call(fname,args);
     190           0 :      break;
     191             : 
     192             :       case 'o':
     193           0 :      if(strncmp(fname,"or",2) == 0)
     194           0 :             res = _exec_andor(args, FALSE);
     195             :          else
     196           0 :             res = _exec_call(fname,args);
     197           0 :      break;
     198             : 
     199             :       case 's':
     200       21394 :      if(strncmp(fname,"sort",4) == 0)
     201           0 :         res = _exec_sort(args);
     202       21394 :      else if(strncmp(fname,"shell",5)==0)
     203         384 :         if( mod_count == 0 ) {
     204         384 :            res = _exec_shell(args, FALSE);
     205             :         }
     206           0 :         else if( mod_count == 1 ) {
     207           0 :            char *emod = Expand(mod1);
     208           0 :            if(strncmp(emod,"expand",7)==0)
     209           0 :           res = _exec_shell(args, TRUE);
     210             :            else
     211           0 :           Fatal( "Unknown argument [%s] to shell in [%s].\n", emod, buf );
     212           0 :            FREE(emod);
     213             :         }
     214             :         else
     215           0 :            Fatal( "One or no comma-seperated arguments expected in [%s].\n", buf );
     216       21010 :      else if(strncmp(fname,"strip",5)==0)
     217         780 :         res = Tokenize(Expand(args)," ",'t',TRUE);
     218       20230 :      else if(strncmp(fname,"subst",5)==0) {
     219       20230 :         if( mod_count == 2 )
     220       20230 :           res = _exec_subst(mod1,mod2,args);
     221             :         else
     222           0 :           Fatal( "Two comma-seperated arguments expected in [%s].\n", buf );
     223             :      }
     224             :          else
     225           0 :             res = _exec_call(fname,args);
     226       21394 :      break;
     227             : 
     228             :       case 'u':
     229         516 :      if(strncmp(fname,"uniq",4) == 0)
     230         516 :         res = _exec_uniq(args);
     231             :          else
     232           0 :             res = _exec_call(fname,args);
     233         516 :      break;
     234             : 
     235             :       default:
     236           0 :      res = _exec_call(fname,args);
     237             :    }
     238             : 
     239       29592 :    if( res == NIL(char) ) res = DmStrDup("");
     240             : 
     241       29592 :    FREE(fname);
     242       29592 :    return(res);
     243             : }
     244             : 
     245             : 
     246             : static char *
     247          22 : _exec_assign( macrostring )
     248             : char *macrostring;
     249             : {
     250          22 :    if ( !Parse_macro(macrostring, M_MULTI|M_FORCE) ) {
     251           0 :       Error( "Dynamic macro assignment failed, while making [%s]\n",
     252           0 :      Current_target ? Current_target->CE_NAME : "NIL");
     253           0 :       return(DmStrDup(""));
     254             :    }
     255             : 
     256          22 :    return(DmStrDup(LastMacName));
     257             : }
     258             : 
     259             : 
     260             : static char *
     261           0 : _exec_echo(data)
     262             : char *data;
     263             : {
     264           0 :    return(DmStrDup(DmStrSpn(data," \t")));
     265             : }
     266             : 
     267             : 
     268             : static char *
     269           0 : _exec_call( var, list )/*
     270             : =========================
     271             :   Return the (recursively expanded) value of macro var. Expand list and
     272             :   discard the result.
     273             : */
     274             : char *var;  /* Name of the macro (until first whitespace). */
     275             : char *list; /* Rest data (after the whitespace). */
     276             : {
     277           0 :    char *res = NIL(char);
     278             : 
     279             :    /* the argument part is expanded. */
     280           0 :    FREE(Expand(list));
     281             : 
     282             :    /* Prepend '$(' and append ')' so that Expand will return the value
     283             :     * of the 'var' macro. */
     284           0 :    var = DmStrJoin(DmStrJoin("$(",var,-1,FALSE),")",-1,TRUE);
     285           0 :    res = Expand(var);
     286             : 
     287           0 :    FREE(var);
     288           0 :    return(res);
     289             : }
     290             : 
     291             : 
     292             : static char *
     293        5796 : _exec_foreach( var, list, data )
     294             : char *var;
     295             : char *list;
     296             : char *data;
     297             : {
     298        5796 :    char *res = NIL(char);
     299             :    char *s;
     300             :    TKSTR tk;
     301             :    HASHPTR hp;
     302             : 
     303        5796 :    var = Expand(var);
     304        5796 :    list = Expand(list);
     305             : 
     306        5796 :    data = DmStrSpn(data," \t\n");
     307        5796 :    SET_TOKEN(&tk,list);
     308             :    /* push previous macro definition and redefine. */
     309        5796 :    hp = Def_macro(var,"",M_MULTI|M_NOEXPORT|M_FORCE|M_PUSH);
     310             : 
     311       39330 :    while( *(s=Get_token(&tk, "", FALSE)) != '\0' ) {
     312       27738 :       Def_macro(var,s,M_MULTI|M_NOEXPORT|M_FORCE);
     313       27738 :       res = DmStrAdd(res,Expand(data),TRUE);
     314             :    }
     315             : 
     316        5796 :    CLEAR_TOKEN(&tk);
     317        5796 :    Pop_macro(hp);   /* Get back old macro definition. */
     318        5796 :    FREE(hp->ht_name);
     319        5796 :    if(hp->ht_value) FREE(hp->ht_value);
     320        5796 :    FREE(hp);
     321        5796 :    FREE(var);
     322        5796 :    FREE(list);
     323             : 
     324        5796 :    return(res);
     325             : }
     326             : 
     327             : 
     328             : static char *
     329         362 : _exec_mktmp( file, text, data )
     330             : char *file;
     331             : char *text;
     332             : char *data;
     333             : {
     334             :    char *tmpname;
     335             :    char *name;
     336         362 :    FILE *tmpfile = NIL(FILE);
     337             : 
     338             :    /* This is only a test of the recipe line so prevent the tempfile side
     339             :     * effects. */
     340         362 :    if( Suppress_temp_file ) return(NIL(char));
     341             : 
     342         362 :    name = Current_target ? Current_target->CE_NAME:"makefile text";
     343             : 
     344         362 :    if( file && *file ) {
     345             :       /* Expand the file parameter to mktmp if present. */
     346           0 :       tmpname = Expand(file);
     347             : 
     348           0 :       if( *tmpname ) {
     349             : #ifdef HAVE_MKSTEMP
     350             :      /* Only use umask if we are also using mkstemp - this basically
     351             :       * avoids using the incompatible implementation from MSVC. */
     352             :      mode_t       mask;
     353             : 
     354             :      /* Create tempfile with 600 permissions. */
     355           0 :      mask = umask(0066);
     356             : #endif
     357             : 
     358           0 :      if( (tmpfile = fopen(tmpname, "w")) == NIL(FILE) )
     359           0 :         Open_temp_error( tmpname, name );
     360             : #ifdef HAVE_MKSTEMP
     361           0 :      umask(mask);
     362             : #endif
     363             : 
     364           0 :      Def_macro("TMPFILE", tmpname, M_EXPANDED|M_MULTI);
     365           0 :      Link_temp( Current_target, tmpfile, tmpname );
     366             : 
     367             :      /* Don't free tmpname if it is used. It is stored in a FILELIST
     368             :       * member in Link_temp() and freed by Unlink_temp_files(). */
     369             :       }
     370             :       else
     371           0 :      FREE(tmpname);
     372             :    }
     373             : 
     374             :    /* If file expanded to a non empty value tmpfile is already opened,
     375             :     * otherwise open it now. */
     376         362 :    if( !tmpfile )
     377         362 :       tmpfile = Start_temp( "", Current_target, &tmpname );
     378             : 
     379             :    /* If the text parameter is given return its expanded value
     380             :     * instead of the used filename. */
     381         362 :    if( !text || !*text ) {
     382             :       /* tmpname is freed by Unlink_temp_files(). */
     383         362 :       text = DmStrDup(DO_WINPATH(tmpname));
     384             :    }
     385             :    else {
     386           0 :       text = Expand(text);
     387             :    }
     388             : 
     389         362 :    data = Expand(data);
     390             : 
     391         362 :    Append_line( data, TRUE, tmpfile, name, FALSE, FALSE );
     392         362 :    Close_temp( Current_target, tmpfile );
     393         362 :    FREE(data);
     394             : 
     395         362 :    return( text );
     396             : }
     397             : 
     398             : 
     399             : static char *
     400        1502 : _exec_iseq( lhs, rhs, data, eq )
     401             : char *lhs;
     402             : char *rhs;
     403             : char *data;
     404             : int  eq;
     405             : {
     406        1502 :    char *l = Expand(lhs);
     407        1502 :    char *r = Expand(rhs);
     408        1502 :    char *i = DmStrSpn(data, " \t\n");
     409        1502 :    char *e = strchr(i, ' ');
     410        1502 :    char *res = NIL(char);
     411        1502 :    int  val = strcmp(l,r);
     412             : 
     413        1502 :    if( (!val && eq) || (val && !eq) ) {
     414        1290 :       if( e != NIL(char) ) *e = '\0';
     415        1290 :       res = Expand(i);
     416             :    }
     417         212 :    else if( e != NIL(char) ) {
     418         212 :       e = DmStrSpn(e," \t\n");
     419         212 :       if( *e ) res = Expand(e);
     420             :    }
     421             : 
     422        1502 :    FREE(l);
     423        1502 :    FREE(r);
     424        1502 :    return(res);
     425             : }
     426             : 
     427             : 
     428             : static char *
     429           0 : _exec_sort( args )
     430             : char *args;
     431             : {
     432           0 :    char *res  = NIL(char);
     433           0 :    char *data = Expand(args);
     434             :    char **tokens;
     435             :    char *p;
     436           0 :    char *white = " \t\n";
     437             :    int  j;
     438             :    int  i;
     439             : 
     440           0 :    for(i=0,p=DmStrSpn(data,white);*p;p=DmStrSpn(DmStrPbrk(p,white),white),i++);
     441             : 
     442           0 :    if( i != 0 ) {
     443           0 :       TALLOC(tokens, i, char *);
     444             : 
     445           0 :       for( i=0,p=DmStrSpn(data,white); *p; p=DmStrSpn(p,white),i++){
     446           0 :      tokens[i] = p;
     447           0 :      p = DmStrPbrk(p,white);
     448           0 :      if( *p ) *p++ = '\0';
     449             :       }
     450             : 
     451           0 :       qsort( tokens, i, sizeof(char *), _mystrcmp );
     452             : 
     453           0 :       for( j=0; j<i; j++ ) res = DmStrApp(res, tokens[j]);
     454           0 :       FREE(data);
     455           0 :       FREE(tokens);
     456             :    }
     457             : 
     458           0 :    return(res);
     459             : }
     460             : 
     461             : 
     462             : static char *
     463         516 : _exec_uniq( args )
     464             : char *args;
     465             : {
     466         516 :   char *res  = NIL(char);
     467         516 :   char *data = Expand(args);
     468             :   char **tokens;
     469             :   char **tokens_after;
     470             :   char *p;
     471         516 :   char *white = " \t\n";
     472             :   int  j;
     473             :   int  i;
     474         516 :   char *last = "";
     475         516 :   int  k = 0;
     476             : 
     477         516 :   for(i=0,p=DmStrSpn(data,white);*p;p=DmStrSpn(DmStrPbrk(p,white),white),i++);
     478             : 
     479         516 :   if( i != 0 ) {
     480           2 :     TALLOC(tokens, i, char *);
     481           2 :     TALLOC(tokens_after, i, char *);
     482             : 
     483           4 :     for( i=0,p=DmStrSpn(data,white); *p; p=DmStrSpn(p,white),i++){
     484           2 :       tokens[i] = p;
     485           2 :       p = DmStrPbrk(p,white);
     486           2 :       if( *p ) *p++ = '\0';
     487             :     }
     488             : 
     489           2 :     qsort( tokens, i, sizeof(char *), _mystrcmp );
     490             : 
     491           4 :     for( j=0; j<i; j++ ) {
     492           2 :       if (strcmp(tokens[j], last) != 0) {
     493           2 :         tokens_after[k++] = tokens[j];
     494           2 :         last = tokens[j];
     495             :       }
     496             :     }
     497             : 
     498           2 :     for( j=0; j<k; j++ ) res = DmStrApp(res, tokens_after[j]);
     499           2 :     FREE(tokens);
     500           2 :     FREE(tokens_after);
     501             :   }
     502             : 
     503         516 :   FREE(data);
     504         516 :   return(res);
     505             : }
     506             : 
     507             : static int
     508           0 : _mystrcmp( p, q )
     509             : const DMPVOID p;
     510             : const DMPVOID q;
     511             : {
     512           0 :    return(strcmp(*((const char **)p),*((const char **)q)));
     513             : }
     514             : 
     515             : 
     516             : static char *
     517       20230 : _exec_subst( pat, subst, data )
     518             : char *pat;
     519             : char *subst;
     520             : char *data;
     521             : {
     522             :    char *res;
     523             : 
     524       20230 :    pat = Expand(pat);
     525       20230 :    subst = Expand(subst);
     526             : 
     527             :    /* This implies FREE(Expand(data)) */
     528       20230 :    res = Apply_edit( Expand(data), pat, subst, TRUE, FALSE );
     529       20230 :    FREE(pat);
     530       20230 :    FREE(subst);
     531             : 
     532       20230 :    return(res);
     533             : }
     534             : 
     535             : 
     536             : static char *
     537         384 : _exec_shell( data, expand )/*
     538             : =============================
     539             :    Capture the stdout of an execuded command.
     540             :    If expand is TRUE expand the result. */
     541             : char *data;
     542             : int expand;
     543             : {
     544             :    extern char *tempnam();
     545             :    int  bsize;
     546             :    char *buffer;
     547             :    char *tmpnm;
     548         384 :    FILE *old_stdout_redir = stdout_redir;
     549             : 
     550         384 :    int wait     = Wait_for_completion;
     551         384 :    int old_is_exec_shell = Is_exec_shell;
     552         384 :    CELLPTR old_Shell_exec_target = Shell_exec_target;
     553         384 :    uint16 vflag = Verbose;
     554         384 :    int tflag    = Trace;
     555         384 :    char *res    = NIL(char);
     556             :    CELL cell;
     557             :    STRING rcp;
     558             :    HASH   cname;
     559             : 
     560         384 :    if( Suppress_temp_file ) return(NIL(char));
     561             : 
     562             :    /* Set the temp CELL used for building prerequisite candidates to
     563             :     * all zero so that we don't have to keep initializing all the
     564             :     * fields. */
     565             :    {
     566         384 :       register char *s = (char *) &cell;
     567         384 :       register int   n = sizeof(CELL);
     568         384 :       while( n ) { *s++ = '\0'; n--; }
     569             :    }
     570         384 :    rcp.st_string  = DmStrSpn(data, " \t+-%@");
     571         384 :    rcp.st_attr    = Rcp_attribute( data );
     572         384 :    rcp.st_next    = NIL(STRING);
     573         384 :    cname.ht_name  = "Shell escape";
     574         384 :    cell.ce_name   = &cname;
     575         384 :    cell.ce_all.cl_prq = &cell;
     576         384 :    cell.ce_all.cl_next = NIL(LINK);
     577         384 :    cell.ce_all.cl_flag = 0;
     578         384 :    cell.ce_fname  = cname.ht_name;
     579         384 :    cell.ce_recipe = &rcp;
     580         384 :    cell.ce_flag   = F_TARGET|F_RULES;
     581             :    /* Setting A_SILENT supresses the recipe output from Print_cmnd(). */
     582         384 :    cell.ce_attr   = A_PHONY|A_SILENT|A_SHELLESC;
     583             : 
     584         384 :    if( Measure & M_TARGET )
     585           0 :       Do_profile_output( "s", M_TARGET, &cell );
     586             : 
     587             :    /* Print the shell escape command. */
     588         384 :    if( Verbose & V_FORCEECHO ) {
     589           0 :       printf( "%s: Executing shell macro: %s\n", Pname, data );
     590           0 :       fflush(stdout);
     591             :    }
     592             : 
     593         384 :    if( (stdout_redir = Get_temp(&tmpnm, "w+")) == NIL(FILE) )
     594           0 :       Open_temp_error( tmpnm, cname.ht_name );
     595             : 
     596         384 :    bsize  = (Buffer_size < BUFSIZ)?BUFSIZ:Buffer_size;
     597         384 :    buffer = MALLOC(bsize,char);
     598             : 
     599             :    /* As this function redirects the output of stdout we have to make sure
     600             :     * that only this single command is executed and all previous recipe lines
     601             :     * that belong to the same target have finished. With Shell_exec_target and
     602             :     * Wait_for_completion set this is realized. Current_target being NIL(CELL)
     603             :     * outside of recipe lines makes sure that no waiting for previous recipe
     604             :     * lines has to be done. */
     605         384 :    Wait_for_completion = TRUE;
     606         384 :    Is_exec_shell = TRUE;
     607         384 :    Shell_exec_target = Current_target;
     608         384 :    Verbose &= V_LEAVE_TMP;
     609         384 :    Trace   = FALSE;
     610             : 
     611             :    /* The actual redirection happens in runargv(). */
     612         384 :    Exec_commands( &cell );
     613             : 
     614         384 :    Unlink_temp_files( &cell );
     615             : 
     616         384 :    Trace   = tflag;
     617         384 :    Verbose = vflag;
     618         384 :    Wait_for_completion = wait;
     619         384 :    Is_exec_shell = old_is_exec_shell;
     620         384 :    Shell_exec_target = old_Shell_exec_target;
     621             : 
     622             :    /* Now we have to read the temporary file, get the tokens and return them
     623             :     * as a string. */
     624         384 :    rewind(stdout_redir);
     625        1150 :    while( fgets(buffer, bsize, stdout_redir) ) {
     626         382 :       char *p = strchr(buffer, '\n');
     627             : 
     628         382 :       if( p == NIL(char) )
     629         184 :      res = DmStrJoin(res,buffer,-1,TRUE);
     630             :       else {
     631         198 :      *p = '\0';
     632             :      /* You might encounter '\r\n' on windows, handle it. */
     633         198 :      if( p > buffer && *(p-1) == '\r')
     634           0 :         *(p-1) = '\0';
     635         198 :          res = DmStrApp(res,buffer);
     636             :       }
     637             :    }
     638             : 
     639         384 :    fclose(stdout_redir);
     640         384 :    Remove_file(tmpnm);
     641         384 :    FREE(tmpnm);
     642         384 :    FREE(buffer);
     643             : 
     644         384 :    stdout_redir = old_stdout_redir;
     645             : 
     646         384 :    if ( expand ) {
     647             :       char *exp_res;
     648           0 :       exp_res = Expand(res);
     649           0 :       FREE(res);
     650           0 :       res = exp_res;
     651             :    }
     652             : 
     653         384 :    return(res);
     654             : }
     655             : 
     656             : 
     657             : static char *
     658           0 : _exec_andor( args, doand )
     659             : char *args;
     660             : int  doand;
     661             : {
     662             :    char *next;
     663             :    char *p;
     664           0 :    char *white = " \t\n";
     665           0 :    int  res=doand;
     666             : 
     667           0 :    args = DmStrSpn(args,white);
     668             :    do {
     669           0 :       p=ScanToken(args, &next, TRUE);
     670             : 
     671           0 :       if (doand ? !*p : *p) {
     672           0 :          res = !doand;
     673           0 :          FREE(p);
     674           0 :          break;
     675             :       }
     676             : 
     677           0 :       FREE(p);
     678             :    }
     679           0 :    while (*(args=DmStrSpn(next,white)));
     680             : 
     681           0 :    return(res ? DmStrDup("t") : DmStrDup(""));
     682             : }
     683             : 
     684             : 
     685             : static char *
     686           0 : _exec_not( args )
     687             : char *args;
     688             : {
     689           0 :    char *white = " \t\n";
     690           0 :    char *p=Expand(args);
     691           0 :    int  res = (*DmStrSpn(p,white) == '\0');
     692             : 
     693           0 :    FREE(p);
     694           0 :    return(res ? DmStrDup("t") : DmStrDup(""));
     695             : }
     696             : 
     697             : 
     698             : char *
     699           0 : exec_normpath( args )/*
     700             : =======================
     701             :    Normalize token-wise. The normalised filenames are returned in a new
     702             :    string, the original string is not freed. Quoted tokens remain quoted
     703             :    after the normalizaton. */
     704             : char *args;
     705             : {
     706             :    TKSTR str;
     707             :    char  *s, *res;
     708             : 
     709             :    /* This honors .WINPATH . */
     710           0 :    SET_TOKEN( &str, args );
     711           0 :    res = NIL(char);
     712           0 :    while( *(s = Get_token( &str, "", FALSE )) != '\0' ) {
     713           0 :       if(str.tk_quote == 0) {
     714             :      /* Add leading quote. */
     715           0 :      res = DmStrApp(res, "\"");
     716           0 :      res = DmStrJoin(res, DO_WINPATH(normalize_path(s)), -1, TRUE);
     717             :      /* Append the trailing quote. */
     718           0 :      res = DmStrJoin(res, "\"", 1, TRUE);
     719             :       } else {
     720           0 :      res = DmStrApp(res, DO_WINPATH(normalize_path(s)));
     721             :       }
     722             :    }
     723           0 :    return res;
     724             : }

Generated by: LCOV version 1.10