LCOV - code coverage report
Current view: top level - libreoffice/dmake - dag.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 199 239 83.3 %
Date: 2012-12-17 Functions: 12 12 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             : --
       3             : -- SYNOPSIS
       4             : --      Routines to construct the internal dag.
       5             : --
       6             : -- DESCRIPTION
       7             : --  This file contains all the routines that are responsible for
       8             : --  defining and manipulating all objects used by the make facility.
       9             : --
      10             : -- AUTHOR
      11             : --      Dennis Vadura, dvadura@dmake.wticorp.com
      12             : --
      13             : -- WWW
      14             : --      http://dmake.wticorp.com/
      15             : --
      16             : -- COPYRIGHT
      17             : --      Copyright (c) 1996,1997 by WTI Corp.  All rights reserved.
      18             : --
      19             : --      This program is NOT free software; you can redistribute it and/or
      20             : --      modify it under the terms of the Software License Agreement Provided
      21             : --      in the file <distribution-root>/readme/license.txt.
      22             : --
      23             : -- LOG
      24             : --      Use cvs log to obtain detailed change logs.
      25             : */
      26             : 
      27             : #include "extern.h"
      28             : 
      29             : 
      30             : static void
      31        9112 : set_macro_value(hp)/*
      32             : =====================
      33             :   Set the macro according to its type. In addition to the string value
      34             :   in hp->ht_value a macro can stores a value casted with its type.
      35             : */
      36             : HASHPTR hp;
      37             : {
      38        9112 :    switch( hp->ht_flag & M_VAR_MASK )   /* only one var type per var */
      39             :    {
      40             :       case M_VAR_STRING:
      41        2024 :      *hp->MV_SVAR = hp->ht_value;
      42             :      /* Add special treatment for PWD/MAKEDIR for .WINPATH. */
      43        2024 :      if( hp->MV_SVAR == &Pwd_macval ) {
      44           0 :         if( Pwd )
      45           0 :            FREE(Pwd);
      46           0 :         Pwd = hp->ht_value;
      47             :         /* Use the "DOSified" path for the macro. */
      48           0 :         *hp->MV_SVAR = hp->ht_value = DmStrDup(DO_WINPATH(hp->ht_value));
      49             :         DB_PRINT( "smv", ("PWD: %s/%s", Pwd_macval, Pwd) );
      50        2024 :      } else if( hp->MV_SVAR == &Makedir_macval ) {
      51           0 :         if( Makedir )
      52           0 :            FREE(Makedir);
      53           0 :         Makedir = hp->ht_value;
      54             :         /* Use the "DOSified" path for the macro. */
      55           0 :         *hp->MV_SVAR = hp->ht_value = DmStrDup(DO_WINPATH(hp->ht_value));
      56             :         DB_PRINT( "smv", ("MAKEDIR: %s/%s", Makedir_macval, Makedir) );
      57             :      }
      58             :      /* No special treatment for TMD needed. */
      59        2024 :      break;
      60             : 
      61             :       case M_VAR_CHAR:
      62           0 :          *hp->MV_CVAR = (hp->ht_value == NIL(char)) ? '\0':*hp->ht_value;
      63           0 :          break;
      64             : 
      65             :       case M_VAR_INT: {
      66             :          int tvalue;
      67         924 :          if( hp->MV_IVAR == NIL(int) ) break;   /* first time */
      68             : 
      69         924 :          tvalue = atoi(hp->ht_value);
      70         924 :          if( hp->MV_IVAR == &Buffer_size ) {
      71             :         /* If Buffer_size (MAXLINELENGTH) is modified then make sure
      72             :          * you change the size of the real buffer as well. As the
      73             :          * value will at least be BUFSIZ this might lead to the
      74             :          * situation that the (string) value of MAXLINELENGTH is
      75             :          * smaller than the integer value. */
      76         556 :             tvalue = (tvalue < (BUFSIZ-2)) ? BUFSIZ : tvalue+2;
      77         556 :             if( Buffer_size == tvalue ) break;
      78         556 :             if( Buffer ) FREE(Buffer);
      79         556 :             if((Buffer=MALLOC(tvalue, char)) == NIL(char)) No_ram();
      80         556 :             *Buffer = '\0';
      81             :          }
      82         924 :          *hp->MV_IVAR = tvalue;
      83             : 
      84         924 :          if( hp->MV_IVAR == &Max_proc || hp->MV_IVAR == &Max_proclmt ) {
      85         368 :             if( tvalue < 1 )
      86           0 :                Fatal( "Process limit value must be > 1" );
      87             : 
      88             : #if defined(USE_CREATEPROCESS)
      89             :             if( Max_proclmt > MAXIMUM_WAIT_OBJECTS )
      90             :                Fatal( "Specified maximum # of processes (MAXPROCESSLIMIT)"
      91             :               " exceeds OS limit of [%d].", MAXIMUM_WAIT_OBJECTS );
      92             : #endif
      93             : 
      94         368 :             if( Max_proc > Max_proclmt )
      95           0 :                Fatal( "Specified # of processes exceeds limit of [%d]",
      96             :                       Max_proclmt );
      97             : 
      98             :         /* Don't change MAXPROCESS value if .SEQUENTIAL is set. */
      99         368 :         if( (Glob_attr & A_SEQ) && (Max_proc != 1) ) {
     100           0 :            Warning( "Macro MAXPROCESS set to 1 because .SEQUENTIAL is set." );
     101           0 :            Max_proc = 1;
     102           0 :            if( hp->ht_value != NIL(char) ) FREE(hp->ht_value);
     103           0 :            hp->ht_value = DmStrDup( "1" );
     104             :         }
     105             :          }
     106         924 :       } break;
     107             : 
     108             :       case M_VAR_BIT:
     109             :          /* Bit variables are set to 1 if ht_value is not NULL and 0
     110             :           * otherwise */
     111             : 
     112         368 :          if( hp->ht_value == NIL(char) )
     113         184 :             *hp->MV_BVAR &= ~hp->MV_MASK;
     114             :          else {
     115         184 :             *hp->MV_BVAR |= hp->MV_MASK;
     116             :         /* If we're setting .SEQUENTIAL set MAXPROCESS=1. */
     117         184 :         if( (hp->MV_MASK & A_SEQ) && (Max_proc != 1) )
     118           0 :            Def_macro( "MAXPROCESS", "1", M_MULTI|M_EXPANDED);
     119             :      }
     120             : 
     121             : #if defined(__CYGWIN__)
     122             :      /* Global .WINPATH change. Only needed for cygwin. */
     123             :      if(hp->MV_MASK & A_WINPATH) {
     124             :         UseWinpath = ((Glob_attr&A_WINPATH) != 0);
     125             :         /* Change MAKEDIR, PWD according to .WINPATH. During
     126             :          * makefile evaluation this cannot change TMD (it is "."
     127             :          * and later TMD is set in Make() according to the
     128             :          * .WINPATH attribute. */
     129             :         Def_macro( "MAKEDIR", Makedir, M_FORCE | M_EXPANDED );
     130             :         Def_macro( "PWD", Pwd, M_FORCE | M_EXPANDED );
     131             :      }
     132             : #endif
     133         368 :      break;
     134             :    }
     135        9112 : }
     136             : 
     137             : 
     138             : PUBLIC HASHPTR
     139     1827870 : Get_name( name, tab, define )/*
     140             : ===============================
     141             :     Look to see if the name is defined, if it is then return
     142             :     a pointer to its node, if not return NIL(HASH).
     143             :     If define is TRUE and the name is not found it will be added. */
     144             : 
     145             : char    *name;          /* name we are looking for   */
     146             : HASHPTR *tab;           /* the hash table to look in */
     147             : int define;         /* TRUE => add to table      */
     148             : {
     149             :    register HASHPTR hp;
     150             :    register char    *p;
     151             :    uint16           hv;
     152             :    uint32           hash_key;
     153             : 
     154             :    DB_ENTER( "Get_name" );
     155             :    DB_PRINT( "name", ("Looking for %s", name) );
     156             : 
     157     1827870 :    hp = Search_table( tab, name, &hv, &hash_key );
     158             : 
     159     1827870 :    if( hp == NIL(HASH) && define ) {
     160             :       /* Check to make sure that CELL name contains only printable chars */
     161     7758840 :       for( p=name; *p; p++ )
     162     7358336 :      if( !isprint(*p) && !iswhite(*p) && *p != '\n' )
     163           0 :         Fatal( "Name contains non-printable character [0x%02x]", *p );
     164             : 
     165      400504 :       TALLOC( hp, 1, HASH );        /* allocate a cell and add it in */
     166             : 
     167      400504 :       hp->ht_name  = DmStrDup( name );
     168      400504 :       hp->ht_hash  = hash_key;
     169      400504 :       hp->ht_next  = tab[ hv ];
     170      400504 :       tab[ hv ]    = hp;
     171             : 
     172             :       DB_PRINT( "name", ("Adding %s", name) );
     173             :    }
     174             : 
     175             :    DB_PRINT( "name",("Returning: [%s,%lu]",
     176             :          (hp == NIL(HASH)) ? "":hp->ht_name, hv) );
     177     1827870 :    DB_RETURN( hp );
     178             : }
     179             : 
     180             : 
     181             : PUBLIC HASHPTR
     182     1827870 : Search_table( tab, name, phv, phkey )
     183             : HASHPTR *tab;
     184             : char    *name;
     185             : uint16  *phv;
     186             : uint32  *phkey;
     187             : {
     188             :    HASHPTR hp;
     189             : 
     190     1827870 :    *phv = Hash( name, phkey );
     191             : 
     192     9124707 :    for( hp = tab[ *phv ]; hp != NIL(HASH); hp = hp->ht_next )
     193     8584896 :       if(    hp->ht_hash == *phkey
     194     1288059 :       && !strcmp(hp->ht_name, name) )
     195     1288059 :          break;
     196             : 
     197     1827870 :    return( hp );
     198             : }
     199             : 
     200             : 
     201             : PUBLIC HASHPTR
     202        5796 : Push_macro(hp)/*
     203             : ================
     204             :   This function pushes hp into the hash of all macros. If a previous
     205             :   instance of the macro exists it is hidden by the new one. If one
     206             :   existed before the new instance inherits some values from the preexisting
     207             :   macro (see below for details).
     208             : */
     209             : HASHPTR hp;
     210             : {
     211             :    HASHPTR cur,prev;
     212             :    uint16  hv;
     213             :    uint32  key;
     214             : 
     215        5796 :    hv = Hash(hp->ht_name, &key);
     216             : 
     217             :    /* Search for an existing instance of hp->ht_name, if found cur will point
     218             :     * to it. */
     219        8154 :    for(prev=NIL(HASH),cur=Macs[hv]; cur!=NIL(HASH); prev=cur,cur=cur->ht_next)
     220        8154 :       if(    cur->ht_hash == key
     221        5796 :       && !strcmp(cur->ht_name, hp->ht_name) )
     222        5796 :          break;
     223             : 
     224        5796 :    if (cur == NIL(HASH) || prev == NIL(HASH)) {
     225             :       /* If no match or was found or the first element of Macs[hv] was
     226             :        * the match insert hp at the beginning. */
     227        5208 :       hp->ht_next  = Macs[hv];
     228        5208 :       Macs[hv] = hp;
     229             :    }
     230             :    else {
     231             :       /* otherwise insert hp in the chain. */
     232         588 :       hp->ht_next = prev->ht_next;
     233         588 :       prev->ht_next = hp;
     234             :    }
     235             : 
     236             :    /* Inherit some parts of the former instance. Copying cur->var to hp->var
     237             :     * copies the old value. Keeping the M_VAR_MASK (variable type) makes sure
     238             :     * the type stays the same keeping M_PRECIOUS assures that the old values
     239             :     * cannot be overridden if it is/was set. */
     240        5796 :    if (cur) {
     241        5796 :       memcpy((void *)&hp->var, (void *)&cur->var, sizeof(hp->var));
     242        5796 :       hp->ht_flag |= ((M_VAR_MASK|M_PRECIOUS) & cur->ht_flag);
     243             :    }
     244             : 
     245        5796 :    return(hp);
     246             : }
     247             : 
     248             : 
     249             : PUBLIC HASHPTR
     250        5796 : Pop_macro(hp)/*
     251             : ================
     252             :   This function pops (removes) hp from the hash of all macros. If a previous
     253             :   instance of the macro existed it becomes accessible again.
     254             : */
     255             : 
     256             : HASHPTR hp;
     257             : {
     258             :    HASHPTR cur,prev;
     259             :    uint16  hv;
     260             :    uint32  key;
     261             : 
     262        5796 :    hv = Hash(hp->ht_name, &key);
     263             : 
     264             :    /* Try to find hp. */
     265        8154 :    for(prev=NIL(HASH),cur=Macs[hv]; cur != NIL(HASH);prev=cur,cur=cur->ht_next)
     266        8154 :       if (cur == hp)
     267        5796 :      break;
     268             : 
     269             :    /* If cur == NIL macros was not found. */
     270        5796 :    if (cur == NIL(HASH))
     271           0 :       return(NIL(HASH));
     272             : 
     273             :    /* Remove hp from the linked list. */
     274        5796 :    if (prev)
     275         588 :       prev->ht_next = cur->ht_next;
     276             :    else
     277        5208 :       Macs[hv] = cur->ht_next;
     278             : 
     279             :    /* Look for a previous (older) instance of hp->ht_name. */
     280        5796 :    for(cur=cur->ht_next; cur != NIL(HASH); cur=cur->ht_next)
     281        5796 :       if(    cur->ht_hash == key
     282        5796 :       && !strcmp(cur->ht_name, hp->ht_name) )
     283        5796 :          break;
     284             : 
     285             :    /* If one was found we restore the typecast values. */
     286        5796 :    if (cur)
     287        5796 :       set_macro_value(cur);
     288             : 
     289        5796 :    hp->ht_next = NIL(HASH);
     290        5796 :    return(hp);
     291             : }
     292             : 
     293             : 
     294             : 
     295             : PUBLIC HASHPTR
     296      771959 : Def_macro( name, value, flags )/*
     297             : =================================
     298             :    This routine is used to define a macro, and it's value. A copy of
     299             :    the content of value is stored and not the pointer to the value.
     300             :    The flags indicates if it is a permanent macro or if it's value
     301             :    can be redefined.  A flags of M_PRECIOUS means it is a precious
     302             :    macro and cannot be further redefined unless M_FORCE is used.
     303             :    If the flags flag contains the M_MULTI bit it means that the macro
     304             :    can be redefined multiple times and no warning of the redefinitions
     305             :    should be issued.
     306             :    Once a macro's VAR flags are set they are preserved through all future
     307             :    macro definitions.
     308             : 
     309             :    Macro definitions that have one of the variable bits set are treated
     310             :    specially.  In each case the hash table entry var field points at the
     311             :    global variable that can be set by assigning to the macro.
     312             : 
     313             :    bit valued global vars must be computed when the macro value is changed.
     314             :    char valued global vars must have the first char of ht_value copied to
     315             :    them.  string valued global vars have the same value as ht_value and should
     316             :    just have the new value of ht_value copied to them.  */
     317             : 
     318             : char    *name;          /* macro name to define */
     319             : char    *value;         /* macro value to set   */
     320             : int     flags;          /* initial ht_flags */
     321             : {
     322             :    register HASHPTR   hp;
     323             :    register char      *p, *q;
     324             : 
     325             :    DB_ENTER( "Def_macro" );
     326             :    DB_PRINT( "mac", ("Defining macro %s = %s, %x", name, value, flags) );
     327             : 
     328             :    /* check to see if name is in the table, if so then just overwrite
     329             :       the previous definition.  Otherwise allocate a new node, and
     330             :       stuff it in the hash table, at the front of any linked list */
     331             : 
     332      771959 :    if( Readenv ) flags |= M_LITERAL|M_EXPANDED;
     333             : 
     334      771959 :    hp = Get_name( name, Macs, TRUE );
     335             : 
     336      771959 :    if ((flags & M_PUSH) && hp->ht_name != NIL(char)) {
     337        5796 :       HASHPTR thp=hp;
     338        5796 :       TALLOC(hp,1,HASH);
     339        5796 :       hp->ht_name  = DmStrDup(thp->ht_name);
     340        5796 :       hp->ht_hash  = thp->ht_hash;
     341        5796 :       Push_macro(hp);
     342        5796 :       flags |= hp->ht_flag;
     343             :    }
     344      771959 :    flags &= ~M_PUSH;
     345             : 
     346      771959 :    if( (hp->ht_flag & M_PRECIOUS) && !(flags & M_FORCE) ) {
     347         368 :       if  (Verbose & V_WARNALL)
     348           0 :          Warning( "Macro `%s' cannot be redefined", name );
     349         368 :       DB_RETURN( hp );
     350             :    }
     351             : 
     352             :    /* Make sure we don't export macros whose names contain legal macro
     353             :     * assignment operators, since we can't do proper quoting in the
     354             :     * environment. */
     355      771591 :    if( *DmStrPbrk(name, "*+:=") != '\0' ) flags |= M_NOEXPORT;
     356             : 
     357      771591 :    if( hp->ht_value != NIL(char) ) FREE( hp->ht_value );
     358             : 
     359      771591 :    if( (hp->ht_flag & M_USED) && !((flags | hp->ht_flag) & M_MULTI) )
     360         186 :       Warning( "Macro `%s' redefined after use", name );
     361             : 
     362             :    /* If an empty string ("") is given set ht_value to NIL(char) */
     363      771591 :    if( (value != NIL(char)) && (*value) ) {
     364             : 
     365      419323 :       if( !(flags & M_LITERAL) ) {
     366      332107 :      q = DmStrDup(value);
     367             :      /* strip out any \<nl> combinations where \ is the current
     368             :       * CONTINUATION char */
     369      712212 :      for(p=q; (p=strchr(p,CONTINUATION_CHAR))!=NIL(char); )
     370       47998 :         if( p[1] == '\n' ) {
     371       45970 :            size_t len = strlen(p+2)+1;
     372       45970 :            memmove ( p, p+2, len );
     373             :         }
     374             :         else
     375        2028 :            p++;
     376             : 
     377      332107 :      p = DmStrSpn(q ," \t");    /* Strip white space before ... */
     378      332107 :      if( p != q ) {
     379         968 :         size_t len = strlen(p)+1;
     380         968 :         memmove( q, p, len );
     381         968 :         p = q;
     382             :      }
     383             : 
     384      332107 :      if( *p ) {         /* ... and after the value. */
     385      331545 :         for(q=p+strlen(p)-1; ((*q == ' ')||(*q == '\t')); q--);
     386      331545 :         *++q = '\0';
     387             :      }
     388      332107 :      flags &= ~M_LITERAL;
     389             :       }
     390             :       else
     391       87216 :      p = DmStrDup( value );         /* take string literally   */
     392             : 
     393      419323 :       if( !*p ) {               /* check if result is ""   */
     394         562 :          FREE( p );
     395         562 :          p = NIL(char);
     396         562 :      flags |= M_EXPANDED;
     397             :       }
     398      418761 :       else if( *DmStrPbrk( p, "${}" ) == '\0' )
     399      326953 :      flags |= M_EXPANDED;
     400             : 
     401      419323 :       hp->ht_value = p;
     402             :    }
     403             :    else {
     404      352268 :       hp->ht_value = NIL(char);
     405      352268 :       flags |= M_EXPANDED;
     406             :    }
     407             : 
     408             :    /* Assign the hash table flag less the M_MULTI flag, it is used only
     409             :     * to silence the warning.  But carry it over if it was previously
     410             :     * defined in ht_flag, as this is a permanent M_MULTI variable. Keep
     411             :     * the M_PRECIOUS flag and strip the M_INIT flag. */
     412             : 
     413     2314773 :    hp->ht_flag = ((flags & ~(M_MULTI|M_FORCE)) |
     414     1543182 :           (hp->ht_flag & (M_VAR_MASK|M_MULTI|M_PRECIOUS))) & ~M_INIT;
     415             : 
     416             :    /* Check for macro variables and make the necessary adjustment in the
     417             :     * corresponding global variables */
     418             : 
     419      771591 :    if( hp->ht_flag & M_VAR_MASK ) {
     420        3316 :       if( !(flags & M_EXPANDED) )
     421           0 :      Error( "Macro variable '%s' must be assigned with :=", name );
     422             :       else
     423        3316 :          set_macro_value(hp);
     424             :    }
     425             : 
     426      771591 :    DB_RETURN( hp );
     427             : }
     428             : 
     429             : 
     430             : 
     431             : PUBLIC CELLPTR
     432      126972 : Def_cell( name )/*
     433             : ==================
     434             :    Check if a cell for "name" already exists, if not create a new cell.
     435             :    The value of name is normalized before checking/creating the cell to
     436             :    avoid creating multiple cells for the same target file.
     437             :    The function returns a pointer to the cell. */
     438             : char    *name;
     439             : {
     440             :    register HASHPTR  hp;
     441             :    register CELLPTR  cp;
     442             :    register CELLPTR  lib;
     443             :    char          *member;
     444             :    char          *end;
     445             : 
     446             :    DB_ENTER( "Def_cell" );
     447             : 
     448             :    /* Check to see if the cell is a member of the form lib(member) or
     449             :     * lib((symbol)) and handle the cases appropriately.
     450             :     * What we do is we look at the target, if it is of the above two
     451             :     * forms we get the lib, and add the member/symbol to the list of
     452             :     * prerequisites for the library.  If this is a symbol name def'n
     453             :     * we additionally add the attribute A_SYMBOL, so that stat can
     454             :     * try to do the right thing.  */
     455             : 
     456      126972 :    if( ((member = strchr(name, '('))     != NIL(char)) &&
     457       18934 :        ((end    = strrchr(member,  ')')) != NIL(char)) &&
     458       18934 :        (member > name) && (member[-1] != '$') &&
     459           0 :        (end > member+1)  && (end[1] == '\0') )
     460             :    {
     461           0 :       *member++ = *end = '\0';
     462             : 
     463           0 :       if( (*member == '(') && (member[strlen(member)-1] == ')') ) {
     464           0 :      member[ strlen(member)-1 ] = '\0';
     465           0 :      cp = Def_cell( member+1 );
     466           0 :      cp->ce_attr |= A_SYMBOL;
     467             :       }
     468             :       else
     469           0 :      cp = Def_cell( member );
     470             : 
     471           0 :       lib  = Def_cell( name );
     472             : 
     473           0 :       Add_prerequisite( lib, cp, FALSE, FALSE );
     474           0 :       lib->ce_attr |= A_LIBRARY | A_COMPOSITE;
     475             : 
     476           0 :       if( !Def_targets ) cp = lib;
     477             :    }
     478             :    else {
     479             :       /* Normalize the name. */
     480             :       DB_PRINT( "path", ("Normalizing [%s]", name) );
     481             : 
     482             :       /* The normalizing function returns a pointer to a static buffer. */
     483      126972 :       name = normalize_path(name);
     484             : 
     485      126972 :       hp = Get_name( name, Defs, TRUE );/* get the name from hash table */
     486             : 
     487      126972 :       if( hp->CP_OWNR == NIL(CELL) )    /* was it previously defined    */
     488             :       {                 /* NO, so define a new cell */
     489             :      DB_PRINT( "cell", ("Defining cell [%s]", name) );
     490             : 
     491       73952 :      TALLOC( cp, 1, CELL );
     492       73952 :      hp->CP_OWNR = cp;
     493       73952 :      cp->ce_name = hp;
     494       73952 :      cp->ce_fname = hp->ht_name;
     495       73952 :      cp->ce_all.cl_prq = cp;
     496             :       }
     497             :       else              /* YES, so return the old cell  */
     498             :       {
     499             :      DB_PRINT( "cell", ("Getting cell [%s]", hp->ht_name) );
     500       53020 :      cp = hp->CP_OWNR;
     501             :       }
     502             :    }
     503             : 
     504      126972 :    DB_RETURN( cp );
     505             : }
     506             : 
     507             : 
     508             : 
     509             : 
     510             : PUBLIC LINKPTR
     511       69544 : Add_prerequisite( cell, prq, head, force )/*
     512             : ============================================
     513             :     Add a dependency node to the dag.  It adds it to the prerequisites,
     514             :     if any, of the cell and makes certain they are in linear order.
     515             :     If head == 1, then add to head of the prerequisite list, else
     516             :     add to tail. */
     517             : CELLPTR cell;
     518             : CELLPTR prq;
     519             : int     head;
     520             : int     force;
     521             : {
     522             :    register LINKPTR lp, tlp;
     523             : 
     524             :    DB_ENTER( "Add_prerequisite" );
     525             :    DB_PRINT( "cell", ("Defining prerequisite %s", prq->CE_NAME) );
     526             : 
     527       69544 :    if( (prq->ce_flag & (F_MAGIC | F_PERCENT)) && !force )
     528           0 :       Fatal( "Special target [%s] cannot be a prerequisite",
     529           0 :              prq->CE_NAME );
     530             : 
     531       69544 :    if( cell->ce_prq == NIL(LINK) ) {    /* it's the first one   */
     532       21768 :       TALLOC( lp, 1, LINK );
     533       21768 :       lp->cl_prq   = prq;
     534       21768 :       cell->ce_prq = lp;
     535             :    }
     536             :    else {   /* search the list, checking for duplicates */
     537    12242284 :       for( lp = cell->ce_prq;
     538    24341412 :        (lp->cl_next != NIL(LINK)) && (lp->cl_prq != prq);
     539    12146732 :        lp = lp->cl_next );
     540             : 
     541             :       /* If the prq is not found and we are at the last prq in the list,
     542             :        * allocate a new prq and place it into the list, insert it at the
     543             :        * head if head == 1, else we add it to the end. */
     544             : 
     545       47776 :       if( lp->cl_prq != prq ) {
     546       47432 :      TALLOC( tlp, 1, LINK );
     547       47432 :      tlp->cl_prq = prq;
     548             : 
     549       47432 :      if( head ) {
     550           0 :         tlp->cl_next = cell->ce_prq;
     551           0 :         cell->ce_prq = tlp;
     552             :      }
     553             :      else
     554       47432 :         lp->cl_next  = tlp;
     555             : 
     556       47432 :      lp = tlp;
     557             :       }
     558             :    }
     559             : 
     560       69544 :    DB_RETURN( lp );
     561             : }
     562             : 
     563             : 
     564             : 
     565             : PUBLIC void
     566        2226 : Clear_prerequisites( cell )/*
     567             : =============================
     568             :     Clear out the list of prerequisites, freeing all of the LINK nodes,
     569             :     and setting the list to NULL */
     570             : CELLPTR cell;
     571             : {
     572             :    LINKPTR lp, tlp;
     573             : 
     574             :    DB_ENTER( "Clear_prerequisites" );
     575             :    DB_PRINT( "cell", ("Nuking prerequisites") );
     576             : 
     577        2226 :    if( cell == NIL(CELL) ) { DB_VOID_RETURN; }
     578             : 
     579        2962 :    for( lp=cell->ce_prq; lp != NIL(LINK); lp=tlp ) {
     580         736 :       tlp=lp->cl_next;
     581         736 :       FREE( lp );
     582             :    }
     583             : 
     584        2226 :    cell->ce_prq = NIL(LINK);
     585             : 
     586        2226 :    DB_VOID_RETURN;
     587             : }
     588             : 
     589             : 
     590             : PUBLIC int
     591       88190 : Test_circle( cp, fail )/*
     592             : =========================
     593             :     Actually run through the graph */
     594             : CELLPTR cp;
     595             : int     fail;
     596             : {
     597             :    register LINKPTR lp;
     598       88190 :    int res = 0;
     599             : 
     600             :    DB_ENTER( "Test_circle" );
     601             :    DB_PRINT( "tc", ("checking [%s]", cp->CE_NAME) );
     602             : 
     603       88190 :    if( cp->ce_flag & F_MARK ) {
     604           0 :       if( fail )
     605           0 :      Fatal("Detected circular dependency in graph at [%s]", cp->CE_NAME);
     606             :       else
     607           0 :      DB_RETURN( 1 );
     608             :    }
     609             : 
     610       88190 :    cp->ce_flag |= F_MARK;
     611      171524 :    for( lp = cp->ce_prq; !res && lp != NIL(LINK); lp = lp->cl_next )
     612       83334 :       res = Test_circle( lp->cl_prq, fail );
     613       88190 :    cp->ce_flag ^= F_MARK;
     614             : 
     615       88190 :    DB_RETURN( res );
     616             : }
     617             : 
     618             : 
     619             : 
     620             : PUBLIC STRINGPTR
     621       44922 : Def_recipe( rcp, sp, white_too, no_check )/*
     622             : =============================================
     623             :    Take the recipe (rcp) and add it to the list of recipes pointed to by
     624             :    sp (sp points to the last element).  If white_too == TRUE add the recipe
     625             :    even if it contains only white space or an empty string.
     626             :    Return a pointer to the new recipe (or sp if it was discarded).
     627             :    If no_check is true then don't look for -@ at the start of the recipe
     628             :    line. */
     629             : char      *rcp;
     630             : STRINGPTR sp;
     631             : int       white_too;
     632             : int       no_check;
     633             : {
     634             :    register STRINGPTR nsp;
     635             :    register char      *rp;
     636             : 
     637             :    DB_ENTER( "Def_recipe" );
     638             :    DB_PRINT( "rul", ("Defining recipe %s", rcp) );
     639             : 
     640       44922 :    if( !white_too ) rcp = DmStrSpn( rcp, " \t" );
     641       44922 :    if( (rcp == NIL(char)) || (*rcp == 0 && !white_too) )
     642           8 :       DB_RETURN( sp );       /* return last recipe when new recipe not added */
     643             : 
     644       44914 :    rp = no_check ? rcp : DmStrSpn( rcp, " \t@-+%" );
     645             : 
     646       44914 :    TALLOC(nsp, 1, STRING);
     647       44914 :    nsp->st_string = DmStrDup( rp );
     648             : 
     649       44914 :    if( sp != NIL(STRING) ) sp->st_next = nsp;
     650       44914 :    nsp->st_next = NIL(STRING);
     651             : 
     652       44914 :    if( !no_check ) nsp->st_attr |= Rcp_attribute( rcp );
     653             : 
     654       44914 :    DB_RETURN( nsp );
     655             : }
     656             : 
     657             : 
     658             : PUBLIC t_attr
     659       46174 : Rcp_attribute( rp )/*
     660             : ======================
     661             :    Look at the recipe and return the set of attributes that it defines. */
     662             : char *rp;
     663             : {
     664       46174 :    t_attr flag = A_DEFAULT;
     665       46174 :    int    done = FALSE;
     666       46174 :    int atcount = 0;
     667             : 
     668      185146 :    while( !done )
     669       92798 :       switch( *rp++ )
     670             :       {
     671       39974 :      case '@' : ++atcount;        break;
     672        6090 :      case '-' : flag |= A_IGNORE; break;
     673         552 :      case '+' : flag |= A_SHELL;  break;
     674             :      case '%' :
     675             : #if defined(MSDOS)
     676             :         /* Ignore % in the non-MSDOS case. */
     677             :         flag |= A_SWAP;
     678             : #endif
     679           0 :         break;
     680             : 
     681             :      case ' ' :
     682           8 :      case '\t': break;
     683             : 
     684       46174 :      default: done = TRUE; break;
     685             :       }
     686             : 
     687       46174 :    if( !(Verbose & V_FORCEECHO) && atcount-- ) {
     688       34878 :       flag |= A_SILENT;
     689             :       /* hide output if more than one @ are encountered. */
     690       34878 :       if( atcount )
     691        5096 :      flag |= A_MUTE;
     692             :    }
     693             : 
     694       46174 :    return(flag);
     695             : }

Generated by: LCOV version 1.10