LCOV - code coverage report
Current view: top level - libreoffice/dmake - make.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 359 642 55.9 %
Date: 2012-12-17 Functions: 17 23 73.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             : --
       3             : -- SYNOPSIS
       4             : --      Perform the update of all outdated targets.
       5             : --
       6             : -- DESCRIPTION
       7             : --  This is where we traverse the make graph looking for targets that
       8             : --  are out of date, and we try to infer how to make them if we can.
       9             : --  The usual make macros are understood, as well as some new ones:
      10             : --
      11             : --      $$  - expands to $
      12             : --      $@      - full target name
      13             : --      $*      - target name with no suffix, same as $(@:db)
      14             : --            or, the value of % in % meta rule recipes
      15             : --      $?      - list of out of date prerequisites
      16             : --      $<      - all prerequisites associated with rules line
      17             : --      $&  - all prerequisites associated with target
      18             : --      $>      - library name for target (if any)
      19             : --      $^  - out of date prerequisites taken from value of $<
      20             : --
      21             : -- AUTHOR
      22             : --      Dennis Vadura, dvadura@dmake.wticorp.com
      23             : --
      24             : -- WWW
      25             : --      http://dmake.wticorp.com/
      26             : --
      27             : -- COPYRIGHT
      28             : --      Copyright (c) 1996,1997 by WTI Corp.  All rights reserved.
      29             : --
      30             : --      This program is NOT free software; you can redistribute it and/or
      31             : --      modify it under the terms of the Software License Agreement Provided
      32             : --      in the file <distribution-root>/readme/license.txt.
      33             : --
      34             : -- LOG
      35             : --      Use cvs log to obtain detailed change logs.
      36             : */
      37             : 
      38             : #include "extern.h"
      39             : #include "sysintf.h"
      40             : 
      41             : typedef struct cell {
      42             :    char            *datum;
      43             :    struct  cell    *next;
      44             :    size_t           len;
      45             : } LISTCELL, *LISTCELLPTR;
      46             : 
      47             : typedef struct {
      48             :    LISTCELLPTR  first;
      49             :    LISTCELLPTR  last;
      50             :    size_t       len;
      51             : } LISTSTRING, *LISTSTRINGPTR;
      52             : 
      53             : 
      54             : static  void    _drop_mac ANSI((HASHPTR));
      55             : static  void    _set_recipe ANSI((char*, int));
      56             : static  void    _set_tmd ANSI(());
      57             : static  void    _append_file ANSI((STRINGPTR, FILE*, char*, int));
      58             : static  LINKPTR _dup_prq ANSI((LINKPTR));
      59             : static  LINKPTR _expand_dynamic_prq ANSI(( LINKPTR, LINKPTR, char * ));
      60             : static  char*   _prefix ANSI((char *, char *));
      61             : static  char*   _pool_lookup ANSI((char *));
      62             : static  int _explode_graph ANSI((CELLPTR, LINKPTR, CELLPTR));
      63             : 
      64             : 
      65             : #define RP_GPPROLOG       0
      66             : #define RP_RECIPE         1
      67             : #define RP_GPEPILOG       2
      68             : #define NUM_RECIPES       3
      69             : 
      70             : static STRINGPTR _recipes[NUM_RECIPES];
      71             : static LISTCELLPTR _freelist=NULL;
      72             : 
      73             : static LISTCELLPTR
      74       89548 : get_cell()
      75             : {
      76             :    LISTCELLPTR cell;
      77             : 
      78       89548 :    if (!_freelist) {
      79       49854 :       if ((cell=MALLOC(1,LISTCELL)) == NULL)
      80           0 :          No_ram();
      81             :    }
      82             :    else {
      83       39694 :       cell = _freelist;
      84       39694 :       _freelist = cell->next;
      85             :    }
      86             : 
      87       89548 :    return(cell);
      88             : }
      89             : 
      90             : 
      91             : static void
      92       89548 : free_cell(LISTCELLPTR cell)
      93             : {
      94       89548 :    cell->next = _freelist;
      95       89548 :    _freelist = cell;
      96       89548 : }
      97             : 
      98             : 
      99             : static void
     100      163356 : free_list(LISTCELLPTR c)
     101             : {
     102      163356 :    if(c) {
     103          64 :       free_list(c->next);
     104          64 :       free_cell(c);
     105             :    }
     106      163356 : }
     107             : 
     108             : 
     109             : static void
     110      176682 : list_init(LISTSTRINGPTR s)
     111             : {
     112      176682 :    s->first = NULL;
     113      176682 :    s->last = NULL;
     114      176682 :    s->len = 0;
     115      176682 : }
     116             : 
     117             : 
     118             : static void
     119       89548 : list_add(LISTSTRINGPTR s, char *str)
     120             : {
     121             :    LISTCELLPTR p;
     122             :    int l;
     123             : 
     124       89548 :    if ((l = strlen(str)) == 0)
     125       89548 :       return;
     126             : 
     127       89548 :    p = get_cell();
     128       89548 :    p->datum = str;
     129       89548 :    p->next  = NULL;
     130       89548 :    p->len   = l;
     131             : 
     132       89548 :    if(s->first == NULL)
     133       13406 :       s->first = p;
     134             :    else
     135       76142 :       s->last->next = p;
     136             : 
     137       89548 :    s->last = p;
     138       89548 :    s->len += l+1;
     139             : }
     140             : 
     141             : 
     142             : static char *
     143      160632 : gen_path_list_string(LISTSTRINGPTR s)/*
     144             : =======================================
     145             :    Take a list of filepaths and create a string from it separating
     146             :    the filenames by a space.
     147             :    This function honors the cygwin specific .WINPATH attribute. */
     148             : {
     149             :    LISTCELLPTR next, cell;
     150             :    int         len;
     151             :    int         slen, slen_rest;
     152             :    char        *result;
     153             :    char        *p, *tpath;
     154             : 
     155      160632 :    if( (slen_rest = slen = s->len) == 0)
     156      147242 :       return(NIL(char));
     157             : 
     158             :    /* reserve enough space to hold the concated original filenames. */
     159       13390 :    if((p = result = MALLOC(slen, char)) == NULL) No_ram();
     160             : 
     161      102874 :    for (cell=s->first; cell; cell=next) {
     162             : #if !defined(__CYGWIN__)
     163       89484 :       tpath = cell->datum;
     164       89484 :       len=cell->len;
     165             : #else
     166             :       /* For cygwin with .WINPATH set the lenght of the converted
     167             :        * filepaths might be longer. Extra checking is needed ... */
     168             :       tpath = DO_WINPATH(cell->datum);
     169             :       if( tpath == cell->datum ) {
     170             :      len=cell->len;
     171             :       }
     172             :       else {
     173             :      /* ... but only if DO_WINPATH() did something. */
     174             :      len = strlen(tpath);
     175             :       }
     176             :       if( len >= slen_rest ) {
     177             :      /* We need more memory. As DOS paths are usually shorter than the
     178             :       * original cygwin POSIX paths (exception mounted paths) this should
     179             :       * rarely happen. */
     180             :      int p_offset = p - result;
     181             :      /* Get more than needed. */
     182             :      slen = slen + len - slen_rest + 128;
     183             :      if((result = realloc( result, slen ) ) == NULL)
     184             :         No_ram();
     185             :      p = result + p_offset;
     186             :       }
     187             : #endif
     188             : 
     189       89484 :       memcpy((void *)p, (void *)tpath, len);
     190       89484 :       p += len;
     191       89484 :       *p++ = ' ';
     192             : 
     193             : #if defined(__CYGWIN__)
     194             :       /* slen_rest is only used in the cygwin / .WINPATH case. */
     195             :       slen_rest = slen - (p - result);
     196             : #endif
     197             : 
     198       89484 :       next = cell->next;
     199       89484 :       free_cell(cell);
     200             :    }
     201             : 
     202       13390 :    *--p = '\0';
     203       13390 :    list_init(s);
     204             : 
     205       13390 :    return(result);
     206             : }
     207             : 
     208             : 
     209             : PUBLIC int
     210         184 : Make_targets()/*
     211             : ================
     212             :    Actually go and make the targets on the target list */
     213             : {
     214             :    LINKPTR lp;
     215         184 :    int     done = 0;
     216             : 
     217             :    DB_ENTER( "Make_targets" );
     218             : 
     219         184 :    Read_state();
     220         184 :    _set_recipe( ".GROUPPROLOG", RP_GPPROLOG );
     221         184 :    _set_recipe( ".GROUPEPILOG", RP_GPEPILOG );
     222             : 
     223             :    /* Prevent recipe inference for .ROOT */
     224         184 :    if ( Root->ce_recipe == NIL(STRING) ) {
     225           0 :       TALLOC( Root->ce_recipe, 1, STRING );
     226           0 :       Root->ce_recipe->st_string = "";
     227             :    }
     228             : 
     229             :    /* Prevent recipe inference for .TARGETS */
     230         184 :    if ( Targets->ce_recipe == NIL(STRING) ) {
     231         184 :       TALLOC( Targets->ce_recipe, 1, STRING );
     232         184 :       Targets->ce_recipe->st_string = "";
     233             :    }
     234             : 
     235             :    /* Make sure that user defined targets are marked as root targets */
     236         368 :    for( lp = Targets->ce_prq; lp != NIL(LINK); lp = lp->cl_next )
     237         184 :       lp->cl_prq->ce_attr |= A_ROOT;
     238             : 
     239         597 :    while( !done ) {
     240             :       int rval;
     241             : 
     242         229 :       if( (rval = Make(Root, NIL(CELL))) == -1 )
     243           0 :      DB_RETURN(1);
     244             :       else
     245         229 :      done = Root->ce_flag & F_MADE;
     246             : 
     247         229 :       if( !rval && !done ) Wait_for_child( FALSE, -1 );
     248             :    }
     249             : 
     250         368 :    for( lp = Targets->ce_prq; lp != NIL(LINK); lp = lp->cl_next ) {
     251         184 :       CELLPTR tgt = lp->cl_prq;
     252         184 :       if( !(tgt->ce_attr & A_UPDATED)
     253           0 :           && (Verbose & V_MAKE) )
     254           0 :           printf( "`%s' is up to date\n", tgt->CE_NAME );
     255             :    }
     256             : 
     257         184 :    DB_RETURN( 0 );
     258             : }
     259             : 
     260             : 
     261             : 
     262             : PUBLIC int
     263       40823 : Make( cp, setdirroot )/*
     264             : ========================
     265             :    Make target cp. Make() is also called on prerequisites that have no rule
     266             :    associated (F_TARGET is not set) to verify that they exist. */
     267             : CELLPTR cp;
     268             : CELLPTR setdirroot;
     269             : {
     270             :    register LINKPTR dp, prev,next;
     271             :    register CELLPTR tcp;
     272             :    CELLPTR          nsetdirroot;
     273             :    char         *name, *lib;
     274             :    HASHPTR      m_at, m_q, m_b, m_g, m_l, m_bb, m_up;
     275             :    LISTSTRING       all_list, imm_list, outall_list, inf_list;
     276       40823 :    char             *all    = NIL(char);
     277       40823 :    char             *inf    = NIL(char);
     278       40823 :    char             *outall = NIL(char);
     279       40823 :    char             *imm    = NIL(char);
     280       40823 :    int              rval    = 0; /* 0==ready, 1==target still running, -1==error */
     281       40823 :    int          push    = 0;
     282       40823 :    int          made    = F_MADE;
     283             :    int          ignore;
     284       40823 :    time_t           otime   = (time_t) 1L; /* Hold time of newest prerequisite. */
     285       40823 :    int          mark_made = FALSE;
     286             : 
     287             : #if defined(__CYGWIN__)
     288             :    /* static variable to hold .WINPATH status of previously made target.
     289             :     * 0, 1 are .WINPATH states, -1 indicates the first target. */
     290             :    static int prev_winpath_attr = -1;
     291             : #endif
     292             : 
     293             :    DB_ENTER( "Make" );
     294             :    DB_PRINT( "mem", ("%s:-> mem %ld", cp->CE_NAME, (long) coreleft()) );
     295             : 
     296             :    /* Initialize the various temporary storage */
     297       40823 :    m_q = m_b = m_g = m_l = m_bb = m_up = NIL(HASH);
     298       40823 :    list_init(&all_list);
     299       40823 :    list_init(&imm_list);
     300       40823 :    list_init(&outall_list);
     301       40823 :    list_init(&inf_list);
     302             : 
     303       40823 :    if (cp->ce_set && cp->ce_set != cp) {
     304           0 :       if( Verbose & V_MAKE )
     305           0 :      printf( "%s:  Building .UPDATEALL representative [%s]\n", Pname,
     306           0 :           cp->ce_set->CE_NAME );
     307           0 :       cp = cp->ce_set;
     308             :    }
     309             : 
     310             :    /* If we are supposed to change directories for this target then do so.
     311             :     * If we do change dir, then modify the setdirroot variable to reflect
     312             :     * that fact for all of the prerequisites that we will be making. */
     313             : 
     314       40823 :    nsetdirroot = setdirroot;
     315       40823 :    ignore = (((cp->ce_attr|Glob_attr)&A_IGNORE) != 0);
     316             : 
     317             :    /* Set the UseWinpath variable to reflect the (global/local) .WINPATH
     318             :     * attribute. The variable is used by DO_WINPATH() and in some other
     319             :     * places. */
     320       40823 :    UseWinpath = (((cp->ce_attr|Glob_attr)&A_WINPATH) != 0);
     321             : 
     322             :    /* m_at needs to be defined before going to a "stop_making_it" where
     323             :     * a _drop_mac( m_at ) would try to free it. */
     324             :    /* FIXME: m_at can most probably not be changed before the next
     325             :     * Def_macro("@", ...) command. Check if both this and the next
     326             :     * call are needed. */
     327       40823 :    m_at = Def_macro("@", DO_WINPATH(cp->ce_fname), M_MULTI);
     328             : 
     329       40823 :    if( cp->ce_attr & A_SETDIR ) {
     330             :       /* Change directory only if the previous .SETDIR is a different
     331             :        * directory from the current one.  ie. all cells with the same .SETDIR
     332             :        * attribute are assumed to come from the same directory. */
     333             : 
     334           0 :       if( (setdirroot == NIL(CELL) || setdirroot->ce_dir != cp->ce_dir) &&
     335           0 :           (push = Push_dir(cp->ce_dir,cp->CE_NAME,ignore)) != 0 )
     336           0 :      setdirroot = cp;
     337             :    }
     338             : 
     339             :    DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
     340             : 
     341             :    /* FIXME: F_MULTI targets don't have cp->ce_recipe set but the recipes
     342             :     * are known nevertheless. It is not necessary to infer them.
     343             :     * If (cp->ce_flag & F_MULTI) is true the recipes of the corresponding
     344             :     * subtargets can be used. */
     345       40823 :    if( cp->ce_recipe == NIL(STRING) ) {
     346       34255 :       char *dir = cp->ce_dir;
     347             : 
     348       34255 :       if( Verbose & V_MAKE )
     349           0 :      printf( "%s:  Infering prerequisite(s) and recipe for [%s]\n", Pname,
     350           0 :           cp->CE_NAME );
     351             : 
     352       34255 :       Infer_recipe( cp, setdirroot );
     353             : 
     354             :       /* See if the directory has changed, if it has then make sure we
     355             :        * push it. */
     356       34255 :       if( dir != cp->ce_dir ) {
     357           0 :      if( push ) Pop_dir(FALSE);
     358           0 :          push = Push_dir( cp->ce_dir, cp->CE_NAME, ignore );
     359           0 :      setdirroot = cp;
     360             :       }
     361             :    }
     362             : 
     363       81646 :    for(dp=CeMeToo(cp); dp; dp=dp->cl_next) {
     364       40823 :       tcp = dp->cl_prq;
     365       40823 :       if( push ) {
     366             :      /* If we changed the directory because of .SETDIR write Pwd into
     367             :       * tcp->ce_dir so that it holds an absolute path. */
     368           0 :      if( !(tcp->ce_attr & A_POOL) && tcp->ce_dir ) FREE( tcp->ce_dir );
     369           0 :      tcp->ce_dir   = _pool_lookup(Pwd);
     370           0 :      tcp->ce_attr |= A_SETDIR|A_POOL;
     371             :       }
     372       40823 :       tcp->ce_setdir = nsetdirroot;
     373             :    }
     374             : 
     375             :    DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
     376             :    /* If we have not yet statted the target then do so. */
     377       40823 :    if( !(cp->ce_flag & F_STAT) && !(cp->ce_attr&A_PHONY) ) {
     378       32581 :       if (cp->ce_parent && (cp->ce_parent->ce_flag & F_MULTI)) {
     379             :      /* Inherit the stat info from the F_MULTI parent. */
     380           0 :      cp->ce_time  = cp->ce_parent->ce_time;
     381           0 :      cp->ce_flag |= F_STAT;
     382             :      /* Propagate the A_PRECIOUS attribute from the parent. */
     383           0 :      cp->ce_attr |= cp->ce_parent->ce_attr & A_PRECIOUS;
     384             :       }
     385             :       else {
     386       65162 :      for(dp=CeMeToo(cp); dp; dp=dp->cl_next) {
     387       32581 :         tcp = dp->cl_prq;
     388             :         /* Check if target already exists. */
     389       32581 :         Stat_target( tcp, 1, FALSE );
     390             : 
     391       32581 :         if( tcp->ce_time != (time_t)0L ) {
     392             :            /* File exists so don't remove it later. */
     393       31464 :            tcp->ce_attr |= A_PRECIOUS;
     394             :         }
     395             : 
     396       32581 :         if( Verbose & V_MAKE )
     397           0 :            printf("%s:  Time stamp of [%s] is %ld\n",Pname,tcp->CE_NAME,
     398             :               tcp->ce_time);
     399             :      }
     400             :       }
     401             :    }
     402             : 
     403             :    DB_PRINT( "make", ("(%s, %ld, 0x%08x, 0x%04x)", cp->CE_NAME,
     404             :             cp->ce_time, cp->ce_attr, cp->ce_flag) );
     405             : 
     406             :    /* Handle targets without rule and without existing file. */
     407       40823 :    if( !(cp->ce_flag & F_TARGET) && (cp->ce_time == (time_t) 0L) ) {
     408         572 :       if( Makemkf ) {
     409         554 :      rval = -1;
     410         554 :      goto stop_making_it;
     411             :       }
     412          18 :       else if( cp->ce_prq != NIL(LINK)
     413           0 :             || (STOBOOL(Augmake) && (cp->ce_flag&F_EXPLICIT)))
     414             :      /* Assume an empty recipe for a target that we have run inference on
     415             :       * but do not have a set of rules for but for which we have inferred
     416             :       * a list of prerequisites. */
     417          18 :      cp->ce_flag |= F_RULES;
     418             :       else
     419           0 :      Fatal( "`%s' not found, and can't be made", cp->CE_NAME );
     420             :    }
     421             : 
     422             :    DB_PRINT( "mem", ("%s:-A mem %ld", cp->CE_NAME, (long) coreleft()) );
     423             : 
     424             :    /* set value of $* if we have not infered a recipe, in this case $* is
     425             :     * the same as $(@:db), this allows us to be compatible with BSD make */
     426       40269 :    if( cp->ce_per == NIL(char) ) cp->ce_per = "$(@:db)";
     427             : 
     428             :    /* Search the prerequisite list for dynamic prerequisites and if we find
     429             :     * them copy the list of prerequisites for potential later re-use. */
     430       40269 :    if ( cp->ce_prqorg == NIL(LINK) ) {
     431       63521 :       for( dp = cp->ce_prq; dp != NIL(LINK); dp = dp->cl_next )
     432       27886 :      if ( strchr(dp->cl_prq->CE_NAME, '$') != NULL )
     433        4634 :         break;
     434             : 
     435       40269 :       if (dp != NIL(LINK)) {
     436        4634 :      cp->ce_prqorg = _dup_prq(cp->ce_prq);
     437             :       }
     438             :    }
     439             : 
     440             :    /* Define $@ macro. The only reason for defining it here (that I see ATM)
     441             :     * is that $@ is already defined in conditional macros. */
     442             :    /* FIXME: check if both this and the previous Def_macro("@", ...) call
     443             :     * are needed. */
     444       40269 :    m_at = Def_macro("@", DO_WINPATH(cp->ce_fname), M_MULTI);
     445             : 
     446             :    /* Define conditional macros if any, note this is done BEFORE we process
     447             :     * prerequisites for the current target.  Thus the making of a prerequisite
     448             :     * is done using the current value of the conditional macro. */
     449       80538 :    for(dp=CeMeToo(cp); dp; dp=dp->cl_next) {
     450       40269 :       tcp=dp->cl_prq;
     451       40269 :       if (tcp->ce_cond != NIL(STRING)) {
     452             :      STRINGPTR sp;
     453             : 
     454           0 :      tcp->ce_pushed = NIL(HASH);
     455           0 :      for(sp=tcp->ce_cond; sp; sp=sp->st_next) {
     456           0 :         if(Parse_macro(sp->st_string,M_MULTI|M_PUSH)) {
     457             :            HASHPTR hp;
     458             : 
     459           0 :            hp = GET_MACRO(LastMacName);
     460           0 :            hp->ht_link = tcp->ce_pushed;
     461           0 :            tcp->ce_pushed = hp;
     462             :         }
     463             :         else {
     464           0 :           Error("Invalid conditional macro expression [%s]",sp->st_string);
     465             :         }
     466             :      }
     467             :       }
     468             :    }
     469             : 
     470             :    /* First round, will be repeated a second time below. */
     471       91361 :    for( prev=NULL,dp=cp->ce_prq; dp != NIL(LINK); prev=dp, dp=next ) {
     472             :       int seq;
     473             : 
     474             :       /* This loop executes Make() to build prerequisites if needed.
     475             :        * The only macro that needs to be reset after a Make() was executed
     476             :        * is $@ as it might be used when expanding potential dynamic
     477             :        * prerequisites. As UseWinpath is a global variable we also
     478             :        * need to restore it. */
     479       51162 :       if (m_at->ht_value == NIL(char)) {
     480             :      /* This check effectively tests if Make() was run before because
     481             :       * Make() frees all dynamic macro values at the end. */
     482       34271 :      UseWinpath = (((cp->ce_attr|Glob_attr)&A_WINPATH) != 0);
     483       34271 :      m_at = Def_macro("@", DO_WINPATH(cp->ce_fname), M_MULTI);
     484             :       }
     485             : 
     486             :       /* Make the prerequisite, note that if the current target has the
     487             :        * .LIBRARY attribute set we pass on to the prerequisite the .LIBRARYM
     488             :        * attribute and pass on the name of the current target as the library
     489             :        * name, and we take it away when we are done.  */
     490       51162 :       next = dp->cl_next;
     491             : 
     492       51162 :       tcp = dp->cl_prq;
     493       51162 :       if( Verbose & V_MAKE )
     494           0 :      printf("Checking prerequisite [%s]\n", tcp->CE_NAME);
     495             : 
     496       51162 :       seq = (((cp->ce_attr | Glob_attr) & A_SEQ) != 0);
     497             : 
     498             :       /* This checks if this prerequisite is still in the making, if yes
     499             :        * come back later. */
     500       51162 :       if( tcp->ce_flag & F_VISITED ) {
     501             :      /* Check if this currently or fully made target has the same
     502             :       * .SETDIR setting. If yes, continue if it was made or come
     503             :       * back later otherwise. */
     504       11097 :      if( _explode_graph(tcp, dp, setdirroot) == 0 ) {
     505             :         /* didn't blow it up so see if we need to wait for it. */
     506       11097 :         if( tcp->ce_flag & F_MADE ) {
     507             :            /* Target was made. */
     508       11072 :            continue;
     509             :         }
     510             :         else
     511             :            /* Target is still in the making ... */
     512          25 :            goto stop_making_it;
     513             :      }
     514             :      else
     515             :         /* Use the new prerequisite with the new .SETDIR value. */
     516           0 :         tcp = dp->cl_prq;
     517             :       }
     518             : 
     519             :       /* If the previous target (prereq) is not yet ready return if
     520             :        * seq is TRUE. */
     521       40065 :       if( seq && !made ) goto stop_making_it;
     522             : 
     523             :       /* Expand dynamic prerequisites. The F_MARK flag is guarging against
     524             :        * possible double expandion of dynamic prerequisites containing more
     525             :        * than one prerequisite. */
     526             :       /* A new A_DYNAMIC attribute could save a lot of strchr( ,'$') calls. */
     527       40040 :       if ( tcp && !(tcp->ce_flag & F_MARK) && strchr(tcp->CE_NAME, '$') ) {
     528             :      /* Replace this dynamic prerequisite with the the real prerequisite,
     529             :       * and add the additional prerequisites if there are more than one.*/
     530             : 
     531       22862 :      name = Expand( tcp->CE_NAME );
     532       22862 :      if( strcmp(name,cp->CE_NAME) == 0 )
     533           0 :         Fatal("Detected circular dynamic dependency; generated '%s'",name);
     534             : 
     535             :      /* Call helper for dynamic prerequisite expansion to replace the
     536             :       * prerequisite with the expanded version and add the new
     537             :       * prerequisites, if the macro expanded to more than one, after
     538             :       * the current list element. */
     539       22862 :      dp = _expand_dynamic_prq( cp->ce_prq, dp, name );
     540       22862 :      FREE( name );
     541             : 
     542             :      /* _expand_dynamic_prq() probably changed dp->cl_prq. */
     543       22862 :      tcp = dp->cl_prq;
     544       22862 :      if ( tcp ) {
     545       22860 :         next = dp->cl_next;
     546             :      }
     547             :       }
     548             : 
     549             :       /* Dynamic expansion results in a NULL cell only when the the new
     550             :        * prerequisite is already in the prerequisite list or empty. In this
     551             :        * case delete the cell and continue. */
     552       40040 :       if ( tcp == NIL(CELL) ) {
     553           2 :      FREE(dp);
     554           2 :      if ( prev == NIL(LINK) ) {
     555           2 :         cp->ce_prq = next;
     556           2 :         dp = NULL;      /* dp will be the new value of prev. */
     557             :      }
     558             :      else {
     559           0 :         prev->cl_next = next;
     560           0 :         dp = prev;
     561             :      }
     562           2 :      continue;
     563             :       }
     564             : 
     565             :       /* Clear F_MARK flag that could have been set by _expand_dynamic_prq(). */
     566       40038 :       tcp->ce_flag &= ~(F_MARK);
     567             : 
     568       40038 :       if( cp->ce_attr & A_LIBRARY ) {
     569           0 :          tcp->ce_attr |= A_LIBRARYM;
     570           0 :      tcp->ce_lib   = cp->ce_fname;
     571             :       }
     572             : 
     573             :       /* Propagate the parent's F_REMOVE and F_INFER flags to the
     574             :        * prerequisites. */
     575       40038 :       tcp->ce_flag |= cp->ce_flag & (F_REMOVE|F_INFER);
     576             : 
     577             :       /* Propagate parents A_ROOT attribute to a child if the parent is a
     578             :        * F_MULTI target. */
     579       40038 :       if( (cp->ce_flag & F_MULTI) && (cp->ce_attr & A_ROOT) )
     580           0 :      tcp->ce_attr |= A_ROOT;
     581             : 
     582       40038 :       tcp->ce_parent = cp;
     583       40038 :       rval |= Make(tcp, setdirroot);
     584             : 
     585       40038 :       if( cp->ce_attr & A_LIBRARY )
     586           0 :          tcp->ce_attr ^= A_LIBRARYM;
     587             : 
     588             :       /* Return on error or if Make() is still running and A_SEQ is set.
     589             :        * (All F_MULTI targets have the A_SEQ attribute.)  */
     590       40038 :       if( rval == -1 || (seq && (rval==1)) )
     591             :      goto stop_making_it;
     592             : 
     593             :       /* If tcp is ready, set made = F_MADE. */
     594       40018 :       made &= tcp->ce_flag & F_MADE;
     595             :    }
     596             : 
     597             : 
     598             :    /* Do the loop again.  We are most definitely going to make the current
     599             :     * cell now.  NOTE:  doing this loop here also results in a reduction
     600             :     * in peak memory usage by the algorithm. */
     601             : 
     602       91119 :    for( dp = cp->ce_prq; dp != NIL(LINK); dp = dp->cl_next ) {
     603             :       int  tgflg;
     604       50961 :       tcp  = dp->cl_prq;
     605       50961 :       if( tcp == NIL(CELL) )
     606           0 :      Fatal("Internal Error: Found prerequisite list cell without prerequisite!");
     607             : 
     608       50961 :       name = tcp->ce_fname;
     609             : 
     610             :       /* make certain that all prerequisites are made prior to advancing. */
     611       50961 :       if( !(tcp->ce_flag & F_MADE) ) goto stop_making_it;
     612             : 
     613             :       /* If the target is a library, then check to make certain that a member
     614             :        * is newer than an object file sitting on disk.  If the disk version
     615             :        * is newer then set the time stamps so that the archived member is
     616             :        * replaced. */
     617       50920 :       if( cp->ce_attr & A_LIBRARY )
     618           0 :      if( tcp->ce_time <= cp->ce_time ) {
     619           0 :         time_t mtime = Do_stat( name, tcp->ce_lib, NIL(char *), FALSE );
     620           0 :         if( mtime < tcp->ce_time ) tcp->ce_time = cp->ce_time+1L;
     621             :      }
     622             : 
     623             :       /* Set otime to the newest time stamp of all prereqs or 1 if there
     624             :        * are no prerequisites. */
     625       50920 :       if( tcp->ce_time > otime ) otime = tcp->ce_time;
     626             : 
     627       50920 :       list_add(&all_list, name);
     628       50920 :       if( (tgflg = (dp->cl_flag & F_TARGET)) != 0 )
     629       35472 :          list_add(&inf_list, name);
     630             : 
     631       50920 :       if((cp->ce_time<tcp->ce_time) || ((tcp->ce_flag & F_TARGET) && Force)) {
     632        2226 :          list_add(&outall_list, name);
     633        2226 :          if( tgflg )
     634         930 :             list_add(&imm_list, name);
     635             :       }
     636             :    }
     637             : 
     638             :    /* If we are building a F_MULTI target inherit the time from
     639             :     * its children. */
     640       40158 :    if( (cp->ce_flag & F_MULTI) )
     641           0 :       cp->ce_time = otime;
     642             : 
     643             :    /* All prerequisites are made, now make the current target. */
     644             : 
     645             :    /* Restore UseWinpath and $@ if needed, see above for an explanation. */
     646       40158 :    if (m_at->ht_value == NIL(char)) {
     647             :       /* This check effectively tests if Make() was run before because
     648             :        * Make() frees all dynamic macro values at the end. */
     649        5706 :       UseWinpath = (((cp->ce_attr|Glob_attr)&A_WINPATH) != 0);
     650        5706 :       m_at = Def_macro("@", DO_WINPATH(cp->ce_fname), M_MULTI);
     651             :    }
     652             : 
     653             :    /* Create a string with all concatenate filenames. The function
     654             :     * respects .WINPATH.  Note that gen_path_list_string empties its
     655             :     * parameter :( */
     656       40158 :    all = gen_path_list_string(&all_list);
     657       40158 :    imm = gen_path_list_string(&imm_list);
     658       40158 :    outall = gen_path_list_string(&outall_list);
     659       40158 :    inf = gen_path_list_string(&inf_list);
     660             : 
     661             :    DB_PRINT( "mem", ("%s:-C mem %ld", cp->CE_NAME, (long) coreleft()) );
     662             :    DB_PRINT( "make", ("I make '%s' if %ld > %ld", cp->CE_NAME, otime,
     663             :           cp->ce_time) );
     664             : 
     665       40158 :    if( Verbose & V_MAKE ) {
     666           0 :       printf( "%s:  >>>> Making ", Pname );
     667             :       /* Also print the F_MULTI master target. */
     668           0 :       if( cp->ce_flag & F_MULTI )
     669           0 :      printf( "(::-\"master\" target) " );
     670           0 :       if( cp->ce_count != 0 )
     671           0 :      printf( "[%s::{%d}]\n", cp->CE_NAME, cp->ce_count );
     672             :       else
     673           0 :      printf( "[%s]\n", cp->CE_NAME );
     674             :    }
     675             : 
     676             : 
     677             :    /* Only PWD, TMD, MAKEDIR and the dynamic macros are affected by
     678             :     * .WINPATH. $@ is handled earlier, do the rest now. */
     679             : #if defined(__CYGWIN__)
     680             :    /* This is only relevant for cygwin. */
     681             :    if( UseWinpath != prev_winpath_attr ) {
     682             :       Def_macro( "MAKEDIR", Makedir, M_FORCE | M_EXPANDED );
     683             :       /* If push is TRUE (Push_dir() was used) PWD and TMD are already
     684             :        * set. */
     685             :       if( !push ) {
     686             :      Def_macro( "PWD", Pwd, M_FORCE | M_EXPANDED );
     687             :      _set_tmd();
     688             :       }
     689             :    }
     690             :    prev_winpath_attr = UseWinpath;
     691             : #endif
     692             : 
     693             :    /* Set the remaining dynamic macros $*, $>, $?, $<, $& and $^. */
     694             : 
     695             :    /* $* is either expanded as the result of a % inference or defined to
     696             :     * $(@:db) and hence unexpanded otherwise. The latter doesn't start
     697             :     * with / and will therefore not be touched by DO_WINPATH(). */
     698       40158 :    m_bb = Def_macro( "*", DO_WINPATH(cp->ce_per),   M_MULTI );
     699             : 
     700             :    /* This is expanded. */
     701       40158 :    m_g  = Def_macro( ">", DO_WINPATH(cp->ce_lib),   M_MULTI|M_EXPANDED );
     702             :    /* These strings are generated with gen_path_list_string() and honor
     703             :     * .WINPATH */
     704       40158 :    m_q  = Def_macro( "?", outall,       M_MULTI|M_EXPANDED );
     705       40158 :    m_b  = Def_macro( "<", inf,          M_MULTI|M_EXPANDED );
     706       40158 :    m_l  = Def_macro( "&", all,          M_MULTI|M_EXPANDED );
     707       40158 :    m_up = Def_macro( "^", imm,          M_MULTI|M_EXPANDED );
     708             : 
     709       40158 :    _recipes[ RP_RECIPE ] = cp->ce_recipe;
     710             : 
     711             :    /* We attempt to make the target if
     712             :     *   1. it has a newer prerequisite
     713             :     *   2. It is a target and Force is set
     714             :     *   3. It's set of recipe lines has changed.
     715             :     */
     716       40158 :    if(   Check_state(cp, _recipes, NUM_RECIPES )
     717       40158 :       || (cp->ce_time < otime)
     718       38684 :       || ((cp->ce_flag & F_TARGET) && Force)
     719             :      ) {
     720             : 
     721        1474 :       if( Measure & M_TARGET )
     722           0 :      Do_profile_output( "s", M_TARGET, cp );
     723             : 
     724             :       /* Only checking so stop as soon as we determine we will make
     725             :        * something */
     726        1474 :       if( Check ) {
     727           0 :      rval = -1;
     728           0 :      goto stop_making_it;
     729             :       }
     730             : 
     731        1474 :       if( Verbose & V_MAKE )
     732           0 :      printf( "%s:  Updating [%s], (%ld > %ld)\n", Pname,
     733           0 :          cp->CE_NAME, otime, cp->ce_time );
     734             : 
     735             :       /* In order to check if a targets time stamp was properly updated
     736             :        * after the target was made and to keep the dependency chain valid
     737             :        * for targets without recipes we store the minimum required file
     738             :        * time. If the target time stamp is older than the newest
     739             :        * prerequisite use that time, otherwise the current time. (This
     740             :        * avoids the call to Do_time() for every target, still checks
     741             :        * if the target time is new enough for the given prerequisite and
     742             :        * mintime is also the newest time of the given prerequisites and
     743             :        * can be used for targets without recipes.)
     744             :        * We reuse the ce_time member to store this minimum time until
     745             :        * the target is finished by Update_time_stamp(). This function
     746             :        * checks if the file time was updated properly and warns if it was
     747             :        * not. (While making a target this value does not change.) */
     748        1474 :       cp->ce_time = ( cp->ce_time < otime ? otime : Do_time() );
     749             :       DB_PRINT( "make", ("Set ce_time (mintime) to: %ld", cp->ce_time) );
     750             : 
     751        2948 :       if( Touch ) {
     752           0 :      name = cp->ce_fname;
     753           0 :      lib  = cp->ce_lib;
     754             : 
     755           0 :      if( (!(Glob_attr & A_SILENT) || !Trace) && !(cp->ce_attr & A_PHONY) ) {
     756           0 :         if( lib == NIL(char) )
     757           0 :            printf("touch(%s)", name );
     758           0 :         else if( cp->ce_attr & A_SYMBOL )
     759           0 :            printf("touch(%s((%s)))", lib, name );
     760             :         else
     761           0 :            printf("touch(%s(%s))", lib, name );
     762             :      }
     763             : 
     764           0 :      if( !Trace && !(cp->ce_attr & A_PHONY) )
     765           0 :         if( Do_touch( name, lib,
     766           0 :         (cp->ce_attr & A_SYMBOL) ? &name : NIL(char *) ) != 0 )
     767           0 :            printf( "  not touched - non-existant" );
     768             : 
     769           0 :      if( (!(Glob_attr & A_SILENT) || !Trace) && !(cp->ce_attr & A_PHONY) )
     770           0 :         printf( "\n" );
     771             : 
     772           0 :      Update_time_stamp( cp );
     773             :       }
     774        1474 :       else if( cp->ce_recipe != NIL(STRING) ) {
     775             :      /* If a recipe is found use it. Note this misses F_MULTI targets. */
     776        1284 :      if( !(cp->ce_flag & F_SINGLE) ) /* Execute the recipes once ... */
     777        1284 :            rval = Exec_commands( cp );
     778             :      /* Update_time_stamp() is called inside Exec_commands() after the
     779             :       * last recipe line is finished. (In _finished_child()) */
     780             :      else {              /* or for every out of date dependency
     781             :                       * if the ruleop ! was used. */
     782             :         TKSTR tk;
     783             : 
     784             :         /* We will redefine $? to be the prerequisite that the recipes
     785             :          * are currently evaluated for. */
     786           0 :         _drop_mac( m_q );
     787             : 
     788             :         /* Execute recipes for each out out of date prerequisites.
     789             :          * WARNING! If no prerequisite is given the recipes are not
     790             :          * executed at all! */
     791           0 :         if( outall && *outall ) {
     792             :            /* Wait for each prerequisite to finish, save the status
     793             :         * of Wait_for_completion. */
     794           0 :            int wait_for_completion_status = Wait_for_completion;
     795           0 :            Wait_for_completion = TRUE;
     796             : 
     797           0 :            SET_TOKEN( &tk, outall );
     798             : 
     799             :            /* No need to update the target timestamp/removing temporary
     800             :         * prerequisites (Update_time_stamp() in _finished_child())
     801             :         * until all prerequisites are done. */
     802           0 :            Doing_bang = TRUE;
     803           0 :            name = Get_token( &tk, "", FALSE );
     804             :            /* This loop might fail if outall contains filenames with
     805             :         * spaces. */
     806             :            do {
     807             :           /* Set $? to current prerequisite. */
     808           0 :           m_q->ht_value = name;
     809             : 
     810           0 :           rval = Exec_commands( cp );
     811             :           /* Thanks to Wait_for_completion = TRUE we are allowed
     812             :            * to remove the temp files here. */
     813           0 :           Unlink_temp_files(cp);
     814             :            }
     815           0 :            while( *(name = Get_token( &tk, "", FALSE )) != '\0' );
     816           0 :            Wait_for_completion = wait_for_completion_status;
     817           0 :            Doing_bang = FALSE;
     818             :         }
     819             : 
     820           0 :         Update_time_stamp( cp );
     821             :         /* Erase $? again. Don't free the pointer, it was part of outall. */
     822           0 :         m_q->ht_value = NIL(char);
     823             :      }
     824             :       }
     825         362 :       else if( !(cp->ce_flag & F_RULES) && !(cp->ce_flag & F_STAT) &&
     826         344 :            (!(cp->ce_attr & A_ROOT) || !(cp->ce_flag & F_EXPLICIT)) &&
     827           0 :            !(cp->ce_count) )
     828             :      /* F_MULTI subtargets should evaluate its parents F_RULES value
     829             :       * but _make_multi always sets the F_RULES value of the master
     830             :       * target. Assume F_RULES is set for subtargets. This might not
     831             :       * be true if there are no prerequisites and no recipes in any
     832             :       * of the subtargets. (FIXME) */
     833           0 :      Fatal( "Don't know how to make `%s'",cp->CE_NAME );
     834             :       else {
     835             :          /* Empty recipe, set the flag as MADE and update the time stamp */
     836             :          /* This might be a the master cell of a F_MULTI target. */
     837         190 :      Update_time_stamp( cp );
     838             :       }
     839             :    }
     840             :    else {
     841       38684 :       if( Verbose & V_MAKE )
     842           0 :      printf( "%s:  Up to date [%s], prq time = %ld , target time = %ld)\n", Pname,
     843           0 :          cp->CE_NAME, otime, cp->ce_time );
     844       38684 :       mark_made = TRUE;
     845             :    }
     846             : 
     847             :    /* If mark_made == TRUE the target is up-to-date otherwise it is
     848             :     * currently in the making. */
     849             : 
     850             :    /* Update all targets in .UPDATEALL rule / only target cp. */
     851       80316 :    for(dp=CeMeToo(cp); dp; dp=dp->cl_next) {
     852       40158 :       tcp=dp->cl_prq;
     853             : 
     854             :       /* Set the time stamp of those prerequisites without rule to the current
     855             :        * time if Force is TRUE to make sure that targets depending on those
     856             :        * prerequisites get remade. */
     857       40158 :       if( !(tcp->ce_flag & F_TARGET) && Force ) tcp->ce_time = Do_time();
     858       40158 :       if( mark_made ) {
     859       38684 :      tcp->ce_flag |= F_MADE;
     860       38684 :      if( tcp->ce_flag & F_MULTI ) {
     861             :         LINKPTR tdp;
     862           0 :         for( tdp = tcp->ce_prq; tdp != NIL(LINK); tdp = tdp->cl_next )
     863           0 :            tcp->ce_attr |= tdp->cl_prq->ce_attr & A_UPDATED;
     864             :      }
     865             :       }
     866             : 
     867             :       /* Note that the target is in the making. */
     868       40158 :       tcp->ce_flag |= F_VISITED;
     869             : 
     870             :       /* Note:  If the prerequisite was made using a .SETDIR= attribute
     871             :        *    directory then we will include the directory in the fname
     872             :        *        of the target.  */
     873       40158 :       if( push ) {
     874           0 :      char *dir   = nsetdirroot ? nsetdirroot->ce_dir : Makedir;
     875             :      /* get relative path from current SETDIR to new SETDIR. */
     876             :      /* Attention, even with .WINPATH set this has to be a POSIX
     877             :       * path as ce_fname neeed to be POSIX. */
     878           0 :      char *pref  = _prefix( dir, tcp->ce_dir );
     879           0 :      char *nname = Build_path(pref, tcp->ce_fname);
     880             : 
     881           0 :      FREE(pref);
     882           0 :      if( (tcp->ce_attr & A_FFNAME) && (tcp->ce_fname != NIL(char)) )
     883           0 :         FREE( tcp->ce_fname );
     884             : 
     885           0 :      tcp->ce_fname = DmStrDup(nname);
     886           0 :      tcp->ce_attr |= A_FFNAME;
     887             :       }
     888             :    }
     889             : 
     890             : stop_making_it:
     891       40823 :    _drop_mac( m_g  );
     892       40823 :    _drop_mac( m_q  );
     893       40823 :    _drop_mac( m_b  );
     894       40823 :    _drop_mac( m_l  );
     895       40823 :    _drop_mac( m_bb );
     896       40823 :    _drop_mac( m_up );
     897       40823 :    _drop_mac( m_at );
     898             : 
     899             :    /* undefine conditional macros if any */
     900       81646 :    for(dp=CeMeToo(cp); dp; dp=dp->cl_next) {
     901       40823 :       tcp=dp->cl_prq;
     902             : 
     903       81646 :       while (tcp->ce_pushed != NIL(HASH)) {
     904           0 :      HASHPTR cur = tcp->ce_pushed;
     905           0 :      tcp->ce_pushed = cur->ht_link;
     906             : 
     907           0 :      Pop_macro(cur);
     908           0 :      FREE(cur->ht_name);
     909           0 :      if(cur->ht_value)
     910           0 :         FREE(cur->ht_value);
     911           0 :      FREE(cur);
     912             :       }
     913             :    }
     914             : 
     915       40823 :    if( push )
     916           0 :       Pop_dir(FALSE);
     917             : 
     918             :    /* Undefine the strings that we used for constructing inferred
     919             :     * prerequisites. */
     920       40823 :    if( inf    != NIL(char) ) FREE( inf    );
     921       40823 :    if( all    != NIL(char) ) FREE( all    );
     922       40823 :    if( imm    != NIL(char) ) FREE( imm    );
     923       40823 :    if( outall != NIL(char) ) FREE( outall );
     924       40823 :    free_list(all_list.first);
     925       40823 :    free_list(imm_list.first);
     926       40823 :    free_list(outall_list.first);
     927       40823 :    free_list(inf_list.first);
     928             : 
     929             :    DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) );
     930       40823 :    DB_RETURN(rval);
     931             : }
     932             : 
     933             : 
     934             : static char *
     935           0 : _prefix( pfx, pat )/*
     936             : =====================
     937             :    Return the relative path from pfx to pat. Both paths have to be absolute
     938             :    paths. If the paths are on different resources or drives (if applicable)
     939             :    or only share a relative path going up to the root dir and down again
     940             :    return pat. */
     941             : char *pfx;
     942             : char *pat;
     943             : {
     944           0 :    char *cmp1=pfx;
     945           0 :    char *cmp2=pat;
     946           0 :    char *tpat=pat; /* Keep pointer to original pat. */
     947             :    char *result;
     948             :    char *up;
     949           0 :    int first = 1;
     950           0 :    int samerootdir = 1; /* Marks special treatment for the root dir. */
     951             : #ifdef HAVE_DRIVE_LETTERS
     952             :    int pfxdl = 0;
     953             :    int patdl = 0;
     954             : #endif
     955             : 
     956             :    /* Micro optimization return immediately if pfx and pat are equal. */
     957           0 :    if( strcmp(pfx, pat) == 0 )
     958           0 :       return(DmStrDup(""));
     959             : 
     960             : #ifdef HAVE_DRIVE_LETTERS
     961             :    /* remove the drive letters to avoid getting them into the relative
     962             :     * path later. */
     963             :    if( *pfx && pfx[1] == ':' && isalpha(*pfx) ) {
     964             :       pfxdl = 1;
     965             :       cmp1 = DmStrSpn(pfx+2, DirBrkStr);
     966             :    }
     967             :    if( *pat && pat[1] == ':' && isalpha(*pat) ) {
     968             :       patdl = 1;
     969             :       cmp2 = DmStrSpn(pat+2, DirBrkStr);
     970             :    }
     971             :    /* If the drive letters are different use the abs. path. */
     972             :    if( pfxdl && patdl && (tolower(*pfx) != tolower(*pat)) )
     973             :       return(DmStrDup(pat));
     974             : 
     975             :    /* If only one has a drive letter also use the abs. path. */
     976             :    if( pfxdl != patdl )
     977             :       return(DmStrDup(pat));
     978             :    else if( pfxdl )
     979             :       /* If both are the same drive letter, disable the special top
     980             :        * dir treatment. */
     981             :       samerootdir = 0;
     982             : 
     983             :    /* Continue without the drive letters. (Either none was present,
     984             :     * or both were the same. This also solves the problem that the
     985             :     * case of the drive letters sometimes depends on the shell.
     986             :     * (cmd.exe vs. cygwin bash) */
     987             :    pfx = cmp1;
     988             :    pat = cmp2;
     989             : #endif
     990             : 
     991             :    /* Cut off equal leading parts of pfx, pat. Both have to be abs. paths. */
     992           0 :    while(*pfx && *pat) {
     993             :       /* skip leading dir. separators. */
     994           0 :       pfx = DmStrSpn(cmp1, DirBrkStr);
     995           0 :       pat = DmStrSpn(cmp2, DirBrkStr);
     996             : 
     997             :       /* Only check in the first run of the loop. Leading slashes can only
     998             :        * mean POSIX paths or Windows resources (two) slashes. Drive letters
     999             :        * have no leading slash. In any case, if the number of slashes are
    1000             :        * not equal there can be no relative path from one two the other.
    1001             :        * In this case return the absolute path. */
    1002           0 :       if( first ) {
    1003           0 :      if( cmp1-pfx != cmp2-pat ) {
    1004           0 :         return(DmStrDup(tpat));
    1005             :      }
    1006           0 :      first = 0;
    1007             :       }
    1008             : 
    1009             :       /* find next dir. separator (or ""). */
    1010           0 :       cmp1 = DmStrPbrk(pfx, DirBrkStr);
    1011           0 :       cmp2 = DmStrPbrk(pat, DirBrkStr);
    1012             : 
    1013             :       /* if length of directory name is equal compare the strings. If equal
    1014             :        * go into next loop. If not equal and directory names in the root
    1015             :        * dir are compared return the absolut path otherwise break the loop
    1016             :        * and construct the relative path from pfx to pat. */
    1017           0 :       if ( (cmp1-pfx) != (cmp2-pat) || strncmp(pfx,pat,cmp1-pfx) != 0 ) {
    1018           0 :      if( samerootdir ) {
    1019           0 :         return(DmStrDup(tpat));
    1020             :      }
    1021           0 :      break;
    1022             :       }
    1023             : 
    1024           0 :       if( samerootdir ) {
    1025             : #if __CYGWIN__
    1026             :      /* If the toplevel directory is /cygdrive (or the equivalent prefix)
    1027             :       * treat the following level also as rootdir. If we are here cmp1-pfx
    1028             :       * cannot be zero so we won't compare with an empty cygdrive prefix. */
    1029             :      if ( (cmp1-pfx) == CygDrvPreLen && strncmp(pfx,CygDrvPre,CygDrvPreLen) == 0 )
    1030             :         samerootdir = 1;
    1031             :      else
    1032             : #endif
    1033           0 :         samerootdir = 0;
    1034             :       }
    1035             :    }
    1036             : 
    1037           0 :    result = DmStrDup("");
    1038           0 :    up = DmStrJoin("..",DirSepStr,-1,FALSE);
    1039           0 :    cmp1 = pfx;
    1040             :    /* Add "../" for each directory in pfx */
    1041           0 :    while ( *(pfx=DmStrSpn(cmp1,DirBrkStr)) != '\0' ) {
    1042           0 :       cmp1 = DmStrPbrk(pfx,DirBrkStr);
    1043           0 :       result = DmStrJoin(result,up,-1,TRUE);
    1044             :    }
    1045           0 :    FREE(up);
    1046             : 
    1047           0 :    pat = DmStrSpn(pat,DirBrkStr);
    1048             :    /* Append pat to result. */
    1049           0 :    if( *pat != '\0' ) {
    1050           0 :       cmp2 = DmStrDup(Build_path(result, pat));
    1051           0 :       FREE(result);
    1052           0 :       result = cmp2;
    1053             :    } else {
    1054             :       /* if pat is empty and result exists remove the trailing slash
    1055             :        * from the last "../". */
    1056           0 :       if( *result ) {
    1057           0 :      result[strlen(result)-1] = '\0';
    1058             :       }
    1059             :    }
    1060             : 
    1061           0 :    return(result);
    1062             : }
    1063             : 
    1064             : 
    1065             : static LINKPTR
    1066       32120 : _dup_prq( lp )
    1067             : LINKPTR lp;
    1068             : {
    1069             :    LINKPTR tlp;
    1070             : 
    1071       32120 :    if( lp == NIL(LINK) ) return(lp);
    1072             : 
    1073       27486 :    TALLOC(tlp, 1, LINK);
    1074       27486 :    tlp->cl_prq  = lp->cl_prq;
    1075       27486 :    tlp->cl_flag = lp->cl_flag;
    1076       27486 :    tlp->cl_next = _dup_prq( lp->cl_next );
    1077             : 
    1078       27486 :    return(tlp);
    1079             : }
    1080             : 
    1081             : 
    1082             : static LINKPTR
    1083       22862 : _expand_dynamic_prq( head, lp, name )/*
    1084             : =======================================
    1085             :    The string name can contain one or more target names. Check if these are
    1086             :    already a prerequisite for the current target. If not add them to the list
    1087             :    of prerequisites. If no prerequisites were added set lp->cl_prq to NULL.
    1088             :    Set the F_MARK flag to indicate that the prerequisite was expanded.
    1089             :    Use cl_flag instead?? */
    1090             : LINKPTR head;
    1091             : LINKPTR lp;
    1092             : char *name;
    1093             : {
    1094       22862 :    CELLPTR cur = lp->cl_prq;
    1095             : 
    1096       22862 :    if( !(*name) ) {
    1097             :       /* If name is empty this leaves lp->cl_prq unchanged -> No prerequisite added. */
    1098             :       ;
    1099             :    }
    1100       22860 :    else if ( strchr(name, ' ') == NIL(char) ) {
    1101             :       /* If condition above is true, no space is found. */
    1102       22828 :       CELLPTR prq  = Def_cell(name);
    1103             :       LINKPTR tmp;
    1104             : 
    1105             :       /* Check if prq already exists. */
    1106       22828 :       for(tmp=head;tmp != NIL(LINK) && tmp->cl_prq != prq;tmp=tmp->cl_next);
    1107             : 
    1108             :       /* If tmp is NULL then the prerequisite is new and is added to the list. */
    1109       22828 :       if ( !tmp ) {
    1110             :      /* replace the prerequisite with the expanded version. */
    1111       22828 :      lp->cl_prq = prq;
    1112       22828 :      lp->cl_prq->ce_flag |= F_MARK;
    1113             :       }
    1114             :    }
    1115             :    else {
    1116          32 :       LINKPTR tlp  = lp;
    1117          32 :       LINKPTR next = lp->cl_next;
    1118             :       TKSTR token;
    1119             :       char  *p;
    1120          32 :       int   first=TRUE;
    1121             : 
    1122             :       /* Handle more than one prerequisite. */
    1123          32 :       SET_TOKEN(&token, name);
    1124         584 :       while (*(p=Get_token(&token, "", FALSE)) != '\0') {
    1125         520 :      CELLPTR prq = Def_cell(p);
    1126             :      LINKPTR tmp;
    1127             : 
    1128         520 :      for(tmp=head;tmp != NIL(LINK) && tmp->cl_prq != prq;tmp=tmp->cl_next);
    1129             : 
    1130             :      /* If tmp is not NULL the prerequisite already exists. */
    1131         520 :      if ( tmp ) continue;
    1132             : 
    1133             :      /* Add list elements behind the first if more then one new
    1134             :       * prerequisite is found. */
    1135         520 :      if ( first ) {
    1136          32 :         first = FALSE;
    1137             :      }
    1138             :      else {
    1139         488 :         TALLOC(tlp->cl_next,1,LINK);
    1140         488 :         tlp = tlp->cl_next;
    1141         488 :         tlp->cl_flag |= F_TARGET;
    1142         488 :         tlp->cl_next = next;
    1143             :      }
    1144             : 
    1145         520 :      tlp->cl_prq = prq;
    1146         520 :      tlp->cl_prq->ce_flag |= F_MARK;
    1147             :       }
    1148          32 :       CLEAR_TOKEN( &token );
    1149             :    }
    1150             : 
    1151             :    /* If the condition is true no new prerequisits were found. */
    1152       22862 :    if ( lp->cl_prq == cur ) {
    1153           2 :       lp->cl_prq = NIL(CELL);
    1154           2 :       lp->cl_flag = 0;
    1155             :    }
    1156             : 
    1157             :    /* Is returned unchanged. */
    1158       22862 :    return(lp);
    1159             : }
    1160             : 
    1161             : 
    1162             : static void
    1163      285761 : _drop_mac( hp )/*
    1164             : ================ set a macro value to zero. */
    1165             : HASHPTR hp;
    1166             : {
    1167      285761 :    if( hp && hp->ht_value != NIL(char) ) {
    1168       94310 :       FREE( hp->ht_value );
    1169       94310 :       hp->ht_value = NIL(char);
    1170             :    }
    1171      285761 : }
    1172             : 
    1173             : 
    1174             : 
    1175             : static int
    1176       11097 : _explode_graph( cp, parent, setdirroot )/*
    1177             : ==========================================
    1178             :    Check to see if we have made the node already.  If so then don't do
    1179             :    it again, except if the cell's ce_setdir field is set to something other
    1180             :    than the value of setdirroot.  If they differ then, and we have made it
    1181             :    already, then make it again and set the cell's stat bit to off so that
    1182             :    we do the stat again.  */
    1183             : CELLPTR cp;
    1184             : LINKPTR parent;
    1185             : CELLPTR setdirroot;
    1186             : {
    1187             :    static CELLPTR removecell = NIL(CELL);
    1188             : 
    1189       11097 :    if ( removecell == NIL(CELL) )
    1190         184 :       removecell = Def_cell(".REMOVE");
    1191             : 
    1192             :    /* we may return if we made it already from the same setdir location,
    1193             :     * or if it is not a library member whose lib field is non NULL.  (if
    1194             :     * it is such a member then we have a line of the form:
    1195             :     *   lib1 lib2 .LIBRARY : member_list...
    1196             :     * and we have to make sure all members are up to date in both libs. */
    1197             : 
    1198       11097 :    if ( setdirroot == removecell )
    1199           0 :       return( 0 );
    1200             : 
    1201       22194 :    if( cp->ce_setdir == setdirroot &&
    1202       11097 :        !((cp->ce_attr & A_LIBRARYM) && (cp->ce_lib != NIL(char))) )
    1203       11097 :       return( 0 );
    1204             : 
    1205             :    /* We check to make sure that we are comming from a truly different
    1206             :     * directory, ie. ".SETDIR=joe : a.c b.c d.c" are all assumed to come
    1207             :     * from the same directory, even though setdirroot is different when
    1208             :     * making dependents of each of these targets. */
    1209             : 
    1210           0 :    if( cp->ce_setdir != NIL(CELL) &&
    1211           0 :        setdirroot != NIL(CELL) &&
    1212           0 :        cp->ce_dir &&
    1213           0 :        setdirroot->ce_dir &&
    1214           0 :        !strcmp(cp->ce_dir, setdirroot->ce_dir) )
    1215           0 :       return( 0 );
    1216             : 
    1217           0 :    if( Max_proc > 1 ) {
    1218             :       LINKPTR dp;
    1219             : 
    1220           0 :       TALLOC(parent->cl_prq, 1, CELL);
    1221           0 :       *parent->cl_prq = *cp;
    1222           0 :       cp = parent->cl_prq;
    1223           0 :       cp->ce_prq = _dup_prq(cp->ce_prqorg);
    1224           0 :       cp->ce_all.cl_prq = cp;
    1225           0 :       CeNotMe(cp) = _dup_prq(CeNotMe(cp));
    1226             : 
    1227           0 :       for(dp=CeNotMe(cp);dp;dp=dp->cl_next) {
    1228           0 :      CELLPTR tcp = dp->cl_prq;
    1229           0 :      TALLOC(dp->cl_prq,1,CELL);
    1230           0 :      *dp->cl_prq = *tcp;
    1231           0 :      dp->cl_prq->ce_flag &= ~(F_STAT|F_VISITED|F_MADE);
    1232           0 :      dp->cl_prq->ce_set   = cp;
    1233             :       }
    1234             :    }
    1235           0 :    cp->ce_flag  &= ~(F_STAT|F_VISITED|F_MADE);
    1236             : 
    1237             :    /* Indicate that we exploded the graph and that the current node should
    1238             :     * be made. */
    1239           0 :    return(1);
    1240             : }
    1241             : 
    1242             : 
    1243             : 
    1244             : PUBLIC int
    1245        1668 : Exec_commands( cp )/*
    1246             : =====================
    1247             :   Execute the commands one at a time that are pointed to by the rules pointer
    1248             :   of the target cp if normal (non-group) recipes are defined. If a group recipe
    1249             :   is found all commands are written into a temporary file first and this
    1250             :   (group-) shell script is executed all at once.
    1251             :   If a group is indicated, then the ce_attr determines .IGNORE and .SILENT
    1252             :   treatment for the group.
    1253             : 
    1254             :   The function returns 0, if the command is executed and has successfully
    1255             :   returned, and it returns 1 if the command is executing but has not yet
    1256             :   returned or -1 if an error occurred (Return value from Do_cmnd()).
    1257             : 
    1258             :   Macros that are found in recipe lines are expanded in this function, in
    1259             :   parallel builds this can mean they are expanded before the previous recipe
    1260             :   lines are finished. (Exception: $(shell ..) waits until all previous recipe
    1261             :   lines are done.)
    1262             : 
    1263             :   The F_MADE bit in the cell is guaranteed set when the command has
    1264             :   successfully completed.  */
    1265             : CELLPTR cp;
    1266             : {
    1267             :    static HASHPTR useshell = NIL(HASH);
    1268             :    static HASHPTR command  = NIL(HASH);
    1269             :    static         int   read_cmnd = 0;
    1270             :    register STRINGPTR   rp;
    1271             :    STRINGPTR            orp;
    1272             :    char         *cmnd;
    1273             :    char         *groupfile;
    1274        1668 :    FILE         *tmpfile = 0;
    1275             :    int          do_it;
    1276             :    t_attr       attr;
    1277             :    int          group;
    1278             :    int          trace;
    1279        1668 :    int          rval  = 0;
    1280             : 
    1281             :    DB_ENTER( "Exec_commands" );
    1282             : 
    1283        1668 :    if( cp->ce_recipe == NIL(STRING) )
    1284           0 :       Fatal("Internal Error: No recipe found!");
    1285             : 
    1286        1668 :    attr  = Glob_attr | cp->ce_attr;
    1287        1668 :    trace = Trace || !(attr & A_SILENT);
    1288        1668 :    group = cp->ce_flag & F_GROUP;
    1289             : 
    1290             :    /* Do it again here for those that call us from places other than Make()
    1291             :     * above. */
    1292        1668 :    orp = _recipes[ RP_RECIPE ];
    1293        1668 :    _recipes[ RP_RECIPE ] = cp->ce_recipe;
    1294             : 
    1295        1668 :    if( group ) {
    1296             :       /* Leave this assignment of Current_target here.  It is needed just
    1297             :        * incase the user hits ^C after the tempfile for the group recipe
    1298             :        * has been opened. */
    1299           0 :       Current_target = cp;
    1300           0 :       trace  = Trace || !(attr & A_SILENT);
    1301             : 
    1302           0 :       if( !Trace ) tmpfile = Start_temp( Grp_suff, cp, &groupfile );
    1303           0 :       if( trace )  fputs( "[\n", stdout );
    1304             : 
    1305             :       /* Emit group prolog */
    1306           0 :       if( attr & A_PROLOG )
    1307           0 :          _append_file( _recipes[RP_GPPROLOG], tmpfile, cp->CE_NAME, trace );
    1308             :    }
    1309             : 
    1310        1668 :    if( !useshell )
    1311         184 :       useshell=Def_macro("USESHELL",NIL(char),M_MULTI|M_EXPANDED);
    1312             : 
    1313        1668 :    if( !read_cmnd ) {
    1314         184 :       command = GET_MACRO("COMMAND");
    1315         184 :       read_cmnd = 1;
    1316             :    }
    1317             : 
    1318             :    /* Process commands in recipe. If in group, merely append to file.
    1319             :     * Otherwise, run them.  */
    1320        3852 :    for( rp=_recipes[RP_RECIPE]; rp != NIL(STRING); rp=rp->st_next) {
    1321        2184 :       t_attr a_attr = A_DEFAULT;
    1322             :       t_attr l_attr;
    1323             :       char   *p;
    1324        2184 :       int    new_attr = FALSE;
    1325             :       int    shell; /* True if the recipe shall run in shell. */
    1326             : 
    1327             :       /* Reset it for each recipe line otherwise tempfiles don't get removed.
    1328             :        * Since processing of $(mktmp ...) depends on Current_target being
    1329             :        * correctly set. */
    1330        2184 :       Current_target = cp;
    1331             : 
    1332             :       /* Only check for +,-,%,@ if the recipe line begins with a '$' macro
    1333             :        * expansion.  Otherwise there is no way it is going to find these
    1334             :        * now. */
    1335        2184 :       if( *rp->st_string == '$' && !group ) {
    1336         876 :          t_attr s_attr = Glob_attr;
    1337         876 :      Glob_attr |= A_SILENT;
    1338         876 :      Suppress_temp_file = TRUE;
    1339         876 :      cmnd = Expand(rp->st_string);
    1340         876 :      Suppress_temp_file = FALSE;
    1341         876 :      a_attr |= Rcp_attribute(cmnd);
    1342         876 :      FREE(cmnd);
    1343         876 :      ++new_attr;
    1344         876 :      Glob_attr = s_attr;
    1345             :       }
    1346             : 
    1347        2184 :       l_attr = attr|a_attr|rp->st_attr;
    1348        2184 :       shell  = ((l_attr & A_SHELL) != 0);
    1349        2184 :       useshell->ht_value = (group||shell)?"yes":"no";
    1350             : 
    1351             :       /* All macros are expanded before putting them in the "process queue".
    1352             :        * Nothing in Expand() should be able to change dynamic macros. */
    1353        2184 :       cmnd = Expand( rp->st_string );
    1354             : 
    1355        2184 :       if( new_attr && (p = DmStrSpn(cmnd," \t\n+-@%")) != cmnd ) {
    1356           4 :      size_t len = strlen(p)+1;
    1357           4 :      memmove(cmnd,p,len);
    1358             :       }
    1359             : 
    1360             :       /* COMMAND macro is set to "$(CMNDNAME) $(CMNDARGS)" by default, it is
    1361             :        * possible for the user to reset it to, for example
    1362             :        *    COMMAND = $(CMNDNAME) @$(mktmp $(CMNDARGS))
    1363             :        * in order to get a different interface for his command execution. */
    1364        2184 :       if( command != NIL(HASH) && !group ) {
    1365           0 :      char *cname = cmnd;
    1366             :          char cmndbuf[30];
    1367             : 
    1368           0 :      if ( *(p=DmStrPbrk(cmnd," \t\n")) != '\0' ) {
    1369           0 :         *p = '\0';
    1370           0 :         (void)Def_macro("CMNDARGS",DmStrSpn(p+1," \t\n"),M_MULTI|M_EXPANDED);
    1371             :      }
    1372             :      else
    1373           0 :         (void) Def_macro("CMNDARGS","",M_MULTI|M_EXPANDED);
    1374             : 
    1375           0 :      (void) Def_macro("CMNDNAME",cname,M_MULTI|M_EXPANDED);
    1376             : 
    1377           0 :          strcpy(cmndbuf, "$(COMMAND)");
    1378           0 :      cmnd = Expand(cmndbuf);
    1379           0 :      FREE(cname);           /* cname == cmnd at this point. */
    1380             : 
    1381             :      /* Collect up any new attributes */
    1382           0 :      l_attr |= Rcp_attribute(cmnd);
    1383           0 :      shell  = ((l_attr & A_SHELL) != 0);
    1384             : 
    1385             :      /* clean up the attributes that we may have just added. */
    1386           0 :      if( (p = DmStrSpn(cmnd," \t\n+-@%")) != cmnd ) {
    1387           0 :         size_t len = strlen(p)+1;
    1388           0 :         memmove(cmnd,p,len);
    1389             :      }
    1390             :       }
    1391             : 
    1392             : #if defined(MSDOS)
    1393             :       Swap_on_exec = ((l_attr & A_SWAP) != 0);    /* Swapping for DOS only */
    1394             : #endif
    1395        2184 :       do_it = !Trace;
    1396             : 
    1397             :       /* We force execution of the recipe if we are tracing and the .EXECUTE
    1398             :        * attribute was given or if the it is not a group recipe and the
    1399             :        * recipe line contains the string $(MAKE). Wait_for_completion might
    1400             :        * be changed gobaly but this is without consequences as we wait for
    1401             :        * every recipe with .EXECUTE and don't start anything else. */
    1402        2184 :       if( Trace
    1403           0 :        && ((l_attr & A_EXECUTE)||(!group && DmStrStr(rp->st_string,"$(MAKE)")))
    1404             :       ) {
    1405           0 :      Wait_for_completion |= Trace;
    1406           0 :      do_it = TRUE;
    1407             :       }
    1408             : 
    1409        2184 :       if( group )
    1410             :      /* Append_line() calls Print_cmnd(). */
    1411           0 :          Append_line( cmnd, TRUE, tmpfile, cp->CE_NAME, trace, 0 );
    1412             :       else {
    1413             :      /* Don't print empty recipe lines. .ROOT and .TARGETS
    1414             :       * deliberately might have empty "" recipes and we don't want
    1415             :       * to output empty recipe lines for them. */
    1416        2184 :      if ( *cmnd ) {
    1417             :         /* Print command and remove continuation sequence from cmnd. */
    1418        1094 :         Print_cmnd(cmnd, !(do_it && (l_attr & A_SILENT)), 0);
    1419             :      }
    1420        2184 :      rval=Do_cmnd(&cmnd,FALSE,do_it,cp,l_attr,
    1421        2184 :               rp->st_next == NIL(STRING) );
    1422             :       }
    1423             : 
    1424        2184 :       FREE(cmnd);
    1425             :    }
    1426             : 
    1427             :    /* If it is a group then output the EPILOG if required and possibly
    1428             :     * execute the command */
    1429        1668 :    if( group && !(cp->ce_attr & A_ERROR) ) {
    1430           0 :       if( attr & A_EPILOG ) /* emit epilog */
    1431           0 :      _append_file( _recipes[RP_GPEPILOG], tmpfile, cp->CE_NAME, trace );
    1432             : 
    1433           0 :       if( trace ) fputs("]\n", stdout);
    1434             : 
    1435           0 :       do_it = !Trace;
    1436           0 :       if( do_it )
    1437             :     {
    1438           0 :         Close_temp( cp, tmpfile );
    1439             : #if defined(UNIX)
    1440             : 
    1441             :          chmod(groupfile,0700);
    1442             : #endif
    1443             :     }
    1444           0 :       rval = Do_cmnd(&groupfile, TRUE, do_it, cp, attr | A_SHELL, TRUE);
    1445             :    }
    1446             : 
    1447        1668 :    _recipes[ RP_RECIPE ] = orp;
    1448        1668 :    cp->ce_attr &= ~A_ERROR;
    1449        1668 :    DB_RETURN( rval );
    1450             : }
    1451             : 
    1452             : 
    1453             : PUBLIC void
    1454        1456 : Print_cmnd( cmnd, echo, map )/*
    1455             : ================================
    1456             :    This routine is called to print out the command to stdout.  If echo is
    1457             :    false the printing to stdout is supressed.
    1458             :    The routine is also used to remove the line continuation sequence
    1459             :    \<nl> from the command string and convert escape sequences if the
    1460             :    map flag is set.
    1461             :    The changed string is used later to actually to execute the command. */
    1462             : char *cmnd;
    1463             : int  echo;
    1464             : int  map;
    1465             : {
    1466             :    register char *p;
    1467             :    register char *n;
    1468             :    char tmp[3];
    1469             : 
    1470             :    DB_ENTER( "Print_cmnd" );
    1471             : 
    1472        1456 :    if( echo ) {
    1473           6 :       printf( "%s\n", cmnd  );
    1474           6 :       fflush(stdout);
    1475             :    }
    1476             : 
    1477        1456 :    tmp[0] = ESCAPE_CHAR;
    1478        1456 :    tmp[1] = CONTINUATION_CHAR;
    1479        1456 :    tmp[2] = '\0';
    1480             : 
    1481        2912 :    for( p=cmnd; *(n = DmStrPbrk(p,tmp)) != '\0'; )
    1482             :       /* Remove the \<nl> sequences. */
    1483           0 :       if(*n == CONTINUATION_CHAR && n[1] == '\n') {
    1484           0 :      size_t len = strlen(n+2)+1;
    1485             :      DB_PRINT( "make", ("fixing [%s]", p) );
    1486           0 :      memmove( n, n+2, len );
    1487           0 :      p = n;
    1488             :       }
    1489             :       /* Look for an escape sequence and replace it by it's corresponding
    1490             :        * character value. */
    1491             :       else {
    1492           0 :          if( *n == ESCAPE_CHAR && map ) Map_esc( n );
    1493           0 :      p = n+1;
    1494             :       }
    1495             : 
    1496        1456 :    DB_VOID_RETURN;
    1497             : }
    1498             : 
    1499             : 
    1500             : 
    1501             : /* These routines are used to maintain a stack of directories when making
    1502             :  * the targets.  If a target cd's to the directory then it is assumed that
    1503             :  * it will undo it when it is finished making itself. */
    1504             : 
    1505             : static STRINGPTR dir_stack = NIL(STRING);
    1506             : 
    1507             : PUBLIC int
    1508           0 : Push_dir( dir, name, ignore )/*
    1509             : ===============================
    1510             :    Change the current working directory to dir and save the current
    1511             :    working directory on the stack so that we can come back.
    1512             : 
    1513             :    If ignore is TRUE then do not complain about _ch_dir if not possible.
    1514             : 
    1515             :    Return 1 if the directory change was successfull and 0 otherwise. */
    1516             : char *dir;
    1517             : char *name;
    1518             : int  ignore;
    1519             : {
    1520             :    STRINGPTR   new_dir;
    1521             : 
    1522             :    DB_ENTER( "Push_dir" );
    1523             : 
    1524           0 :    if( dir == NIL(char)  || *dir == '\0' ) dir = Pwd;
    1525           0 :    if( *dir == '\'' && dir[strlen(dir)-1] == '\'' ) {
    1526           0 :       dir = DmStrDup(dir+1);
    1527           0 :       dir[strlen(dir)-1]='\0';
    1528             :    }
    1529           0 :    else if (strchr(dir,'$') != NIL(char))
    1530           0 :       dir = Expand(dir);
    1531             :    else
    1532           0 :       dir = DmStrDup(dir);
    1533             : 
    1534           0 :    if( Set_dir(dir) ) {
    1535           0 :       if( !ignore )
    1536           0 :          Fatal( "Unable to change to directory `%s', target is [%s]",
    1537             :             dir, name );
    1538           0 :       FREE(dir);
    1539           0 :       DB_RETURN( 0 );
    1540             :    }
    1541             : 
    1542             :    DB_PRINT( "dir", ("Push: [%s]", dir) );
    1543           0 :    if( Verbose & V_DIR_SET )
    1544           0 :       printf( "%s:  Changed to directory [%s]\n", Pname, dir  );
    1545             : 
    1546           0 :    FREE( dir );
    1547           0 :    TALLOC( new_dir, 1, STRING );
    1548           0 :    new_dir->st_next   = dir_stack;
    1549           0 :    dir_stack          = new_dir;
    1550           0 :    new_dir->st_string = DmStrDup( Pwd );
    1551             : 
    1552           0 :    Def_macro( "PWD", Get_current_dir(), M_FORCE | M_EXPANDED );
    1553           0 :    _set_tmd();
    1554             : 
    1555           0 :    DB_RETURN( 1 );
    1556             : }
    1557             : 
    1558             : 
    1559             : 
    1560             : PUBLIC void
    1561           0 : Pop_dir(ignore)/*
    1562             : =================
    1563             :    Change the current working directory to the previous saved dir. */
    1564             : int ignore;
    1565             : {
    1566             :    STRINGPTR old_dir;
    1567             :    char      *dir;
    1568             : 
    1569             :    DB_ENTER( "Pop_dir" );
    1570             : 
    1571           0 :    if( dir_stack == NIL(STRING) ) {
    1572           0 :       if( ignore ) {
    1573           0 :          DB_VOID_RETURN;
    1574             :       }
    1575             :       else
    1576           0 :      Error( "Directory stack empty for return from .SETDIR" );
    1577             :    }
    1578             : 
    1579           0 :    if( Set_dir(dir = dir_stack->st_string) )
    1580           0 :       Fatal( "Could not change to directory `%s'", dir );
    1581             : 
    1582           0 :    Def_macro( "PWD", dir, M_FORCE | M_EXPANDED );
    1583             :    DB_PRINT( "dir", ("Pop: [%s]", dir) );
    1584           0 :    if( Verbose & V_DIR_SET )
    1585           0 :       printf( "%s:  Changed back to directory [%s]\n", Pname, dir);
    1586             : 
    1587           0 :    old_dir   = dir_stack;
    1588           0 :    dir_stack = dir_stack->st_next;
    1589             : 
    1590           0 :    FREE( old_dir->st_string );
    1591           0 :    FREE( old_dir );
    1592           0 :    _set_tmd();
    1593             : 
    1594           0 :    DB_VOID_RETURN;
    1595             : }
    1596             : 
    1597             : 
    1598             : 
    1599             : static void
    1600           0 : _set_tmd()/*
    1601             : ============
    1602             :    Set the TMD Macro and the Tmd global variable. TMD stands for "To MakeDir"
    1603             :    and is the path from the present directory (value of $(PWD)) to the directory
    1604             :    dmake was started up in (value of $(MAKEDIR)). As _prefix() can return absolute
    1605             :    paths some special .WINPATH treatment is needed.
    1606             : */
    1607             : {
    1608             :    char  *tmd;
    1609             : 
    1610           0 :    if( Tmd )
    1611           0 :       FREE(Tmd);
    1612             : 
    1613           0 :    tmd = _prefix(Pwd, Makedir);
    1614           0 :    if( *tmd ) {
    1615           0 :       Def_macro( "TMD", DO_WINPATH(tmd), M_FORCE | M_EXPANDED );
    1616           0 :       Tmd = DmStrDup(tmd);
    1617             :    } else {
    1618           0 :       Def_macro( "TMD", ".", M_FORCE | M_EXPANDED );
    1619           0 :       Tmd = DmStrDup(".");
    1620             :    }
    1621           0 :    FREE( tmd );
    1622           0 : }
    1623             : 
    1624             : 
    1625             : static void
    1626         368 : _set_recipe( target, ind )/*
    1627             : ============================
    1628             :    Set up the _recipes static variable so that the slot passed in points
    1629             :    at the rules corresponding to the target supplied. */
    1630             : char *target;
    1631             : int  ind;
    1632             : {
    1633             :    CELLPTR cp;
    1634             :    HASHPTR hp;
    1635             : 
    1636         368 :    if( (hp = Get_name(target, Defs, FALSE)) != NIL(HASH) ) {
    1637           0 :       cp = hp->CP_OWNR;
    1638           0 :       _recipes[ ind ] = cp->ce_recipe;
    1639             :    }
    1640             :    else
    1641         368 :       _recipes[ ind ] = NIL(STRING);
    1642         368 : }
    1643             : 
    1644             : 
    1645             : 
    1646             : PUBLIC void
    1647         362 : Append_line( cmnd, newline, tmpfile, name, printit, map )
    1648             : char *cmnd;
    1649             : int  newline;
    1650             : FILE *tmpfile;
    1651             : char *name;
    1652             : int  printit;
    1653             : int  map;
    1654             : {
    1655         362 :    Print_cmnd( cmnd, printit, map );
    1656             : 
    1657         724 :    if( Trace ) return;
    1658             : 
    1659         362 :    fputs(cmnd, tmpfile);
    1660         362 :    if( newline ) fputc('\n', tmpfile);
    1661         362 :    fflush(tmpfile);
    1662             : 
    1663         362 :    if( ferror(tmpfile) )
    1664           0 :       Fatal("Write error on temporary file, while processing `%s'", name);
    1665             : }
    1666             : 
    1667             : 
    1668             : 
    1669             : static void
    1670           0 : _append_file( rp, tmpfile, name, printit )
    1671             : register STRINGPTR rp;
    1672             : FILE           *tmpfile;
    1673             : char           *name;
    1674             : int            printit;
    1675             : {
    1676             :    char *cmnd;
    1677             : 
    1678           0 :    while( rp != NIL(STRING) ) {
    1679           0 :       Append_line(cmnd = Expand(rp->st_string), TRUE, tmpfile, name, printit,0);
    1680           0 :       FREE(cmnd);
    1681           0 :       rp = rp->st_next;
    1682             :    }
    1683           0 : }
    1684             : 
    1685             : 
    1686             : #define NUM_BUCKETS 20
    1687             : 
    1688             : typedef struct strpool {
    1689             :    char       *string;  /* a pointer to the string value */
    1690             :    uint32     keyval;   /* the strings hash value    */
    1691             :    struct strpool *next;    /* hash table link pointer   */
    1692             : } POOL, *POOLPTR;
    1693             : 
    1694             : static POOLPTR strings[ NUM_BUCKETS ];
    1695             : 
    1696             : static char *
    1697           0 : _pool_lookup( str )/*
    1698             : =====================
    1699             :    Scan down the list of chained strings and see if one of them matches
    1700             :    the string we are looking for. */
    1701             : char    *str;
    1702             : {
    1703             :    register POOLPTR key;
    1704             :    uint32   keyval;
    1705             :    uint16   hv;
    1706             :    uint16   keyindex;
    1707             :    char     *string;
    1708             : 
    1709             :    DB_ENTER( "_pool_lookup" );
    1710             : 
    1711           0 :    if( str == NIL(char) ) DB_RETURN("");
    1712             : 
    1713           0 :    hv  = Hash(str, &keyval);
    1714           0 :    key = strings[ keyindex = (hv % NUM_BUCKETS) ];
    1715             : 
    1716           0 :    while( key != NIL(POOL) )
    1717           0 :       if( (key->keyval != keyval) || strcmp(str, key->string) )
    1718           0 :      key = key->next;
    1719             :       else
    1720             :      break;
    1721             : 
    1722           0 :    if( key == NIL(POOL) ) {
    1723             :       DB_PRINT( "pool", ("Adding string [%s]", str) );
    1724           0 :       TALLOC( key, 1, POOL );           /* not found so add string */
    1725             : 
    1726           0 :       key->string = string = DmStrDup(str);
    1727           0 :       key->keyval = keyval;
    1728             : 
    1729           0 :       key->next           = strings[ keyindex ];
    1730           0 :       strings[ keyindex ] = key;
    1731             :    }
    1732             :    else {
    1733             :       DB_PRINT( "pool", ("Found string [%s], key->string") );
    1734           0 :       string = key->string;
    1735             :    }
    1736             : 
    1737           0 :    DB_RETURN( string );
    1738             : }
    1739             : 
    1740             : 
    1741             : void
    1742           4 : Unmake( cp )/*
    1743             : ==============
    1744             :    Remove flags indicating that a target was previously made.  This
    1745             :    is used for infered makefiles. */
    1746             : CELLPTR cp;
    1747             : {
    1748             :    LINKPTR dp, ep;
    1749             :    CELLPTR tcp, pcp;
    1750             : 
    1751             :    DB_ENTER( "Unmake" );
    1752             : 
    1753           8 :    for(dp=CeMeToo(cp); dp; dp=dp->cl_next) {
    1754           4 :       tcp = dp->cl_prq;
    1755             : 
    1756             :       /* Unmake the prerequisites. */
    1757           6 :       for( ep = tcp->ce_prq; ep != NIL(LINK); ep = ep->cl_next ) {
    1758           2 :      pcp  = ep->cl_prq;
    1759             : 
    1760           2 :      Unmake(pcp);
    1761             :       }
    1762             :       DB_PRINT( "unmake", ("Unmake [%s]", tcp->CE_NAME) );
    1763             : 
    1764           4 :       tcp->ce_flag &= ~(F_MADE|F_VISITED|F_STAT);
    1765           4 :       tcp->ce_time  = (time_t)0L;
    1766             :    }
    1767             : 
    1768           4 :    DB_VOID_RETURN;
    1769             : }

Generated by: LCOV version 1.10