~ubuntu-branches/ubuntu/saucy/pmake/saucy-proposed

« back to all changes in this revision

Viewing changes to var.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hocevar (Debian packages)
  • Date: 2005-07-07 10:20:56 UTC
  • mfrom: (0.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20050707102056-3nh411zy3wbwuwyr
Tags: 1.111-1
* New upstream snapshot.
* This version properly parses arguments and does not crash when parameters
  are missing (Closes: #287336, #316394).
* debian/control:
  + Set policy to 3.6.2.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*      $NetBSD: var.c,v 1.87 2004/02/20 09:03:26 sjg Exp $     */
 
1
/*      $NetBSD: var.c,v 1.96 2005/07/01 16:45:38 christos Exp $        */
2
2
 
3
3
/*
4
4
 * Copyright (c) 1988, 1989, 1990, 1993
68
68
 * SUCH DAMAGE.
69
69
 */
70
70
 
71
 
#ifdef MAKE_BOOTSTRAP
72
 
static char rcsid[] = "$NetBSD: var.c,v 1.87 2004/02/20 09:03:26 sjg Exp $";
 
71
#ifndef MAKE_NATIVE
 
72
static char rcsid[] = "$NetBSD: var.c,v 1.96 2005/07/01 16:45:38 christos Exp $";
73
73
#else
74
74
#include <sys/cdefs.h>
75
75
#ifndef lint
76
76
#if 0
77
77
static char sccsid[] = "@(#)var.c       8.3 (Berkeley) 3/19/94";
78
78
#else
79
 
__RCSID("$NetBSD: var.c,v 1.87 2004/02/20 09:03:26 sjg Exp $");
 
79
__RCSID("$NetBSD: var.c,v 1.96 2005/07/01 16:45:38 christos Exp $");
80
80
#endif
81
81
#endif /* not lint */
82
82
#endif
287
287
    const char *,
288
288
    Boolean (*)(GNode *, Var_Parse_State *, char *, Boolean, Buffer, ClientData),
289
289
    ClientData);
290
 
static char *VarSort(const char *);
 
290
static char *VarOrder(const char *, const char);
291
291
static char *VarUniq(const char *);
292
292
static int VarWordCompare(const void *, const void *);
293
293
static void VarPrintVar(ClientData);
362
362
     * look for it in VAR_CMD, VAR_GLOBAL and the environment, in that order,
363
363
     * depending on the FIND_* flags in 'flags'
364
364
     */
365
 
    var = Hash_FindEntry (&ctxt->context, name);
 
365
    var = Hash_FindEntry(&ctxt->context, name);
366
366
 
367
367
    if ((var == NULL) && (flags & FIND_CMD) && (ctxt != VAR_CMD)) {
368
 
        var = Hash_FindEntry (&VAR_CMD->context, name);
 
368
        var = Hash_FindEntry(&VAR_CMD->context, name);
369
369
    }
370
370
    if (!checkEnvFirst && (var == NULL) && (flags & FIND_GLOBAL) &&
371
371
        (ctxt != VAR_GLOBAL))
372
372
    {
373
 
        var = Hash_FindEntry (&VAR_GLOBAL->context, name);
 
373
        var = Hash_FindEntry(&VAR_GLOBAL->context, name);
374
374
    }
375
375
    if ((var == NULL) && (flags & FIND_ENV)) {
376
376
        char *env;
378
378
        if ((env = getenv (name)) != NULL) {
379
379
            int         len;
380
380
 
381
 
            v = (Var *) emalloc(sizeof(Var));
 
381
            v = emalloc(sizeof(Var));
382
382
            v->name = estrdup(name);
383
383
 
384
384
            len = strlen(env);
391
391
        } else if (checkEnvFirst && (flags & FIND_GLOBAL) &&
392
392
                   (ctxt != VAR_GLOBAL))
393
393
        {
394
 
            var = Hash_FindEntry (&VAR_GLOBAL->context, name);
 
394
            var = Hash_FindEntry(&VAR_GLOBAL->context, name);
395
395
            if (var == NULL) {
396
396
                return ((Var *) NIL);
397
397
            } else {
433
433
    int           len;
434
434
    Hash_Entry    *h;
435
435
 
436
 
    v = (Var *) emalloc (sizeof (Var));
 
436
    v = emalloc(sizeof(Var));
437
437
 
438
438
    len = val ? strlen(val) : 0;
439
439
    v->val = Buf_Init(len+1);
441
441
 
442
442
    v->flags = 0;
443
443
 
444
 
    h = Hash_CreateEntry (&ctxt->context, name, NULL);
 
444
    h = Hash_CreateEntry(&ctxt->context, name, NULL);
445
445
    Hash_SetValue(h, v);
446
446
    v->name = h->name;
447
447
    if (DEBUG(VAR)) {
524
524
        name = Var_Subst(NULL, cp, ctxt, 0);
525
525
    } else
526
526
        name = cp;
527
 
    v = VarFind (name, ctxt, 0);
 
527
    v = VarFind(name, ctxt, 0);
528
528
    if (v == (Var *) NIL) {
529
 
        VarAdd (name, val, ctxt);
 
529
        VarAdd(name, val, ctxt);
530
530
    } else {
531
531
        Buf_Discard(v->val, Buf_Size(v->val));
532
532
        Buf_AddBytes(v->val, strlen(val), (const Byte *)val);
595
595
    } else
596
596
        name = cp;
597
597
    
598
 
    v = VarFind (name, ctxt, (ctxt == VAR_GLOBAL) ? FIND_ENV : 0);
 
598
    v = VarFind(name, ctxt, (ctxt == VAR_GLOBAL) ? FIND_ENV : 0);
599
599
 
600
600
    if (v == (Var *) NIL) {
601
 
        VarAdd (name, val, ctxt);
 
601
        VarAdd(name, val, ctxt);
602
602
    } else {
603
603
        Buf_AddByte(v->val, (Byte)' ');
604
604
        Buf_AddBytes(v->val, strlen(val), (const Byte *)val);
616
616
             * export other variables...)
617
617
             */
618
618
            v->flags &= ~VAR_FROM_ENV;
619
 
            h = Hash_CreateEntry (&ctxt->context, name, NULL);
 
619
            h = Hash_CreateEntry(&ctxt->context, name, NULL);
620
620
            Hash_SetValue(h, v);
621
621
        }
622
622
    }
679
679
{
680
680
    Var            *v;
681
681
 
682
 
    v = VarFind (name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
 
682
    v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
683
683
    *frp = NULL;
684
684
    if (v != (Var *) NIL) {
685
685
        char *p = ((char *)Buf_GetAll(v->val, (int *)NULL));
717
717
 *-----------------------------------------------------------------------
718
718
 */
719
719
static Boolean
720
 
VarHead(GNode *ctx, Var_Parse_State *vpstate,
 
720
VarHead(GNode *ctx __unused, Var_Parse_State *vpstate,
721
721
        char *word, Boolean addSpace, Buffer buf,
722
722
        ClientData dummy)
723
723
{
729
729
            Buf_AddByte (buf, vpstate->varSpace);
730
730
        }
731
731
        *slash = '\0';
732
 
        Buf_AddBytes (buf, strlen (word), (Byte *)word);
 
732
        Buf_AddBytes(buf, strlen (word), (Byte *)word);
733
733
        *slash = '/';
734
734
        return (TRUE);
735
735
    } else {
765
765
 *-----------------------------------------------------------------------
766
766
 */
767
767
static Boolean
768
 
VarTail(GNode *ctx, Var_Parse_State *vpstate,
 
768
VarTail(GNode *ctx __unused, Var_Parse_State *vpstate,
769
769
        char *word, Boolean addSpace, Buffer buf,
770
770
        ClientData dummy)
771
771
{
778
778
    slash = strrchr (word, '/');
779
779
    if (slash != (char *)NULL) {
780
780
        *slash++ = '\0';
781
 
        Buf_AddBytes (buf, strlen(slash), (Byte *)slash);
 
781
        Buf_AddBytes(buf, strlen(slash), (Byte *)slash);
782
782
        slash[-1] = '/';
783
783
    } else {
784
 
        Buf_AddBytes (buf, strlen(word), (Byte *)word);
 
784
        Buf_AddBytes(buf, strlen(word), (Byte *)word);
785
785
    }
786
786
    return (dummy ? TRUE : TRUE);
787
787
}
807
807
 *-----------------------------------------------------------------------
808
808
 */
809
809
static Boolean
810
 
VarSuffix(GNode *ctx, Var_Parse_State *vpstate,
 
810
VarSuffix(GNode *ctx __unused, Var_Parse_State *vpstate,
811
811
          char *word, Boolean addSpace, Buffer buf,
812
812
          ClientData dummy)
813
813
{
819
819
            Buf_AddByte (buf, vpstate->varSpace);
820
820
        }
821
821
        *dot++ = '\0';
822
 
        Buf_AddBytes (buf, strlen (dot), (Byte *)dot);
 
822
        Buf_AddBytes(buf, strlen (dot), (Byte *)dot);
823
823
        dot[-1] = '.';
824
824
        addSpace = TRUE;
825
825
    }
848
848
 *-----------------------------------------------------------------------
849
849
 */
850
850
static Boolean
851
 
VarRoot(GNode *ctx, Var_Parse_State *vpstate,
 
851
VarRoot(GNode *ctx __unused, Var_Parse_State *vpstate,
852
852
        char *word, Boolean addSpace, Buffer buf,
853
853
        ClientData dummy)
854
854
{
861
861
    dot = strrchr (word, '.');
862
862
    if (dot != (char *)NULL) {
863
863
        *dot = '\0';
864
 
        Buf_AddBytes (buf, strlen (word), (Byte *)word);
 
864
        Buf_AddBytes(buf, strlen (word), (Byte *)word);
865
865
        *dot = '.';
866
866
    } else {
867
 
        Buf_AddBytes (buf, strlen(word), (Byte *)word);
 
867
        Buf_AddBytes(buf, strlen(word), (Byte *)word);
868
868
    }
869
869
    return (dummy ? TRUE : TRUE);
870
870
}
892
892
 *-----------------------------------------------------------------------
893
893
 */
894
894
static Boolean
895
 
VarMatch(GNode *ctx, Var_Parse_State *vpstate,
 
895
VarMatch(GNode *ctx __unused, Var_Parse_State *vpstate,
896
896
         char *word, Boolean addSpace, Buffer buf,
897
897
         ClientData pattern)
898
898
{
981
981
 *-----------------------------------------------------------------------
982
982
 */
983
983
static Boolean
984
 
VarNoMatch(GNode *ctx, Var_Parse_State *vpstate,
 
984
VarNoMatch(GNode *ctx __unused, Var_Parse_State *vpstate,
985
985
           char *word, Boolean addSpace, Buffer buf,
986
986
           ClientData pattern)
987
987
{
1018
1018
 *-----------------------------------------------------------------------
1019
1019
 */
1020
1020
static Boolean
1021
 
VarSubstitute(GNode *ctx, Var_Parse_State *vpstate,
 
1021
VarSubstitute(GNode *ctx __unused, Var_Parse_State *vpstate,
1022
1022
              char *word, Boolean addSpace, Buffer buf,
1023
1023
              ClientData patternp)
1024
1024
{
1218
1218
 *-----------------------------------------------------------------------
1219
1219
 */
1220
1220
static Boolean
1221
 
VarRESubstitute(GNode *ctx, Var_Parse_State *vpstate,
 
1221
VarRESubstitute(GNode *ctx __unused, Var_Parse_State *vpstate __unused,
1222
1222
                char *word, Boolean addSpace, Buffer buf,
1223
1223
                ClientData patternp)
1224
1224
{
1358
1358
 *-----------------------------------------------------------------------
1359
1359
 */
1360
1360
static Boolean
1361
 
VarLoopExpand(GNode *ctx, Var_Parse_State *vpstate,
 
1361
VarLoopExpand(GNode *ctx __unused, Var_Parse_State *vpstate __unused,
1362
1362
              char *word, Boolean addSpace, Buffer buf,
1363
1363
              ClientData loopp)
1364
1364
{
1401
1401
 *-----------------------------------------------------------------------
1402
1402
 */
1403
1403
static char *
1404
 
VarSelectWords(GNode *ctx, Var_Parse_State *vpstate,
 
1404
VarSelectWords(GNode *ctx __unused, Var_Parse_State *vpstate,
1405
1405
               const char *str, VarSelectWords_t *seldata)
1406
1406
{
1407
1407
    Buffer        buf;              /* Buffer for the new string */
1413
1413
    int ac, i;
1414
1414
    int start, end, step;
1415
1415
    
1416
 
    buf = Buf_Init (0);
 
1416
    buf = Buf_Init(0);
1417
1417
    addSpace = FALSE;
1418
1418
 
1419
1419
    if (vpstate->oneBigWord) {
1420
1420
        /* fake what brk_string() would do if there were only one word */
1421
1421
        ac = 1;
1422
 
        av = (char **)emalloc((ac + 1) * sizeof(char *));
 
1422
        av = emalloc((ac + 1) * sizeof(char *));
1423
1423
        as = strdup(str);
1424
1424
        av[0] = as;
1425
1425
        av[1] = NULL;
1468
1468
 
1469
1469
    Buf_AddByte (buf, '\0');
1470
1470
    as = (char *)Buf_GetAll (buf, (int *)NULL);
1471
 
    Buf_Destroy (buf, FALSE);
 
1471
    Buf_Destroy(buf, FALSE);
1472
1472
    return (as);
1473
1473
}
1474
1474
 
1506
1506
    char *as;                       /* word list memory */
1507
1507
    int ac, i;
1508
1508
 
1509
 
    buf = Buf_Init (0);
 
1509
    buf = Buf_Init(0);
1510
1510
    addSpace = FALSE;
1511
1511
 
1512
1512
    if (vpstate->oneBigWord) {
1513
1513
        /* fake what brk_string() would do if there were only one word */
1514
1514
        ac = 1;
1515
 
        av = (char **)emalloc((ac + 1) * sizeof(char *));
 
1515
        av = emalloc((ac + 1) * sizeof(char *));
1516
1516
        as = strdup(str);
1517
1517
        av[0] = as;
1518
1518
        av[1] = NULL;
1529
1529
 
1530
1530
    Buf_AddByte (buf, '\0');
1531
1531
    as = (char *)Buf_GetAll (buf, (int *)NULL);
1532
 
    Buf_Destroy (buf, FALSE);
 
1532
    Buf_Destroy(buf, FALSE);
1533
1533
    return (as);
1534
1534
}
1535
1535
 
1543
1543
 
1544
1544
/*-
1545
1545
 *-----------------------------------------------------------------------
1546
 
 * VarSort --
1547
 
 *      Sort the words in the string.
 
1546
 * VarOrder --
 
1547
 *      Order the words in the string.
1548
1548
 *
1549
1549
 * Input:
1550
 
 *      str             String whose words should be sorted
 
1550
 *      str             String whose words should be sorted.
 
1551
 *      otype           How to order: s - sort, x - random.
1551
1552
 *
1552
1553
 * Results:
1553
 
 *      A string containing the words sorted
 
1554
 *      A string containing the words ordered.
1554
1555
 *
1555
1556
 * Side Effects:
1556
1557
 *      None.
1558
1559
 *-----------------------------------------------------------------------
1559
1560
 */
1560
1561
static char *
1561
 
VarSort(const char *str)
 
1562
VarOrder(const char *str, const char otype)
1562
1563
{
1563
1564
    Buffer        buf;              /* Buffer for the new string */
1564
1565
    char **av;                      /* word list [first word does not count] */
1565
1566
    char *as;                       /* word list memory */
1566
1567
    int ac, i;
1567
1568
 
1568
 
    buf = Buf_Init (0);
 
1569
    buf = Buf_Init(0);
1569
1570
 
1570
1571
    av = brk_string(str, &ac, FALSE, &as);
1571
1572
 
1572
1573
    if (ac > 0)
1573
 
        qsort(av, ac, sizeof(char *), VarWordCompare);
 
1574
        switch (otype) {
 
1575
        case 's':       /* sort alphabetically */
 
1576
            qsort(av, ac, sizeof(char *), VarWordCompare);
 
1577
            break;
 
1578
        case 'x':       /* randomize */
 
1579
        {
 
1580
            int rndidx;
 
1581
            char *t;
 
1582
 
 
1583
            /*
 
1584
             * We will use [ac..2] range for mod factors. This will produce
 
1585
             * random numbers in [(ac-1)..0] interval, and minimal
 
1586
             * reasonable value for mod factor is 2 (the mod 1 will produce
 
1587
             * 0 with probability 1).
 
1588
             */
 
1589
            for (i = ac-1; i > 0; i--) {
 
1590
                rndidx = random() % (i + 1);
 
1591
                if (i != rndidx) {
 
1592
                    t = av[i];
 
1593
                    av[i] = av[rndidx];
 
1594
                    av[rndidx] = t;
 
1595
                }
 
1596
            }
 
1597
        }
 
1598
        } /* end of switch */
1574
1599
 
1575
1600
    for (i = 0; i < ac; i++) {
1576
1601
        Buf_AddBytes(buf, strlen(av[i]), (Byte *) av[i]);
1583
1608
 
1584
1609
    Buf_AddByte (buf, '\0');
1585
1610
    as = (char *)Buf_GetAll (buf, (int *)NULL);
1586
 
    Buf_Destroy (buf, FALSE);
 
1611
    Buf_Destroy(buf, FALSE);
1587
1612
    return (as);
1588
1613
}
1589
1614
 
1661
1686
 *-----------------------------------------------------------------------
1662
1687
 */
1663
1688
static char *
1664
 
VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate,
 
1689
VarGetPattern(GNode *ctxt, Var_Parse_State *vpstate __unused,
1665
1690
              int err, const char **tstr, int delim, int *flags,
1666
1691
              int *length, VarPattern *pattern)
1667
1692
{
1783
1808
    /* This should cover most shells :-( */
1784
1809
    static char meta[] = "\n \t'`\";&<>()|*?{}[]\\$!#^~";
1785
1810
 
1786
 
    buf = Buf_Init (MAKE_BSIZE);
 
1811
    buf = Buf_Init(MAKE_BSIZE);
1787
1812
    for (; *str; str++) {
1788
1813
        if (strchr(meta, *str) != NULL)
1789
1814
            Buf_AddByte(buf, (Byte)'\\');
1791
1816
    }
1792
1817
    Buf_AddByte(buf, (Byte) '\0');
1793
1818
    str = (char *)Buf_GetAll (buf, (int *)NULL);
1794
 
    Buf_Destroy (buf, FALSE);
 
1819
    Buf_Destroy(buf, FALSE);
1795
1820
    return str;
1796
1821
}
1797
1822
 
1819
1844
   int            (*modProc)(int);
1820
1845
 
1821
1846
   modProc = (upper ? toupper : tolower);
1822
 
   buf = Buf_Init (MAKE_BSIZE);
 
1847
   buf = Buf_Init(MAKE_BSIZE);
1823
1848
   for (; *str ; str++) {
1824
1849
       Buf_AddByte(buf, (Byte) modProc(*str));
1825
1850
   }
1826
1851
   Buf_AddByte(buf, (Byte) '\0');
1827
 
   str = (char *) Buf_GetAll (buf, (int *) NULL);
1828
 
   Buf_Destroy (buf, FALSE);
 
1852
   str = (char *) Buf_GetAll(buf, (int *) NULL);
 
1853
   Buf_Destroy(buf, FALSE);
1829
1854
   return str;
1830
1855
}
1831
1856
 
1879
1904
                                 * expanding it in a non-local context. This
1880
1905
                                 * is done to support dynamic sources. The
1881
1906
                                 * result is just the invocation, unaltered */
1882
 
    Var_Parse_State parsestate = {0}; /* Flags passed to helper functions */
 
1907
    Var_Parse_State parsestate; /* Flags passed to helper functions */
1883
1908
 
1884
1909
    *freePtr = FALSE;
1885
1910
    dynamic = FALSE;
1898
1923
        name[0] = str[1];
1899
1924
        name[1] = '\0';
1900
1925
 
1901
 
        v = VarFind (name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
 
1926
        v = VarFind(name, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
1902
1927
        if (v == (Var *)NIL) {
1903
1928
            *lengthPtr = 2;
1904
1929
 
1937
1962
 
1938
1963
        startc = str[1];
1939
1964
        endc = startc == '(' ? ')' : '}';
1940
 
        buf = Buf_Init (MAKE_BSIZE);
 
1965
        buf = Buf_Init(MAKE_BSIZE);
1941
1966
 
1942
1967
        /*
1943
1968
         * Skip to the end character or a colon, whichever comes first.
1981
2006
        str = Buf_GetAll(buf, (int *) NULL);
1982
2007
        vlen = strlen(str);
1983
2008
 
1984
 
        v = VarFind (str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
 
2009
        v = VarFind(str, ctxt, FIND_ENV | FIND_GLOBAL | FIND_CMD);
1985
2010
        if ((v == (Var *)NIL) && (ctxt != VAR_CMD) && (ctxt != VAR_GLOBAL) &&
1986
2011
            (vlen == 2) && (str[1] == 'F' || str[1] == 'D'))
1987
2012
        {
2029
2054
                        *freePtr = TRUE;
2030
2055
                        *lengthPtr = tstr-start+1;
2031
2056
                        *WR(tstr) = endc;
2032
 
                        Buf_Destroy (buf, TRUE);
 
2057
                        Buf_Destroy(buf, TRUE);
2033
2058
                        return(val);
2034
2059
                    }
2035
2060
                    break;
2088
2113
                    strncpy(pstr, start, *lengthPtr);
2089
2114
                    pstr[*lengthPtr] = '\0';
2090
2115
                    *freePtr = TRUE;
2091
 
                    Buf_Destroy (buf, TRUE);
 
2116
                    Buf_Destroy(buf, TRUE);
2092
2117
                    return(pstr);
2093
2118
                } else {
2094
 
                    Buf_Destroy (buf, TRUE);
 
2119
                    Buf_Destroy(buf, TRUE);
2095
2120
                    return (err ? var_Error : varNoError);
2096
2121
                }
2097
2122
            } else {
2099
2124
                 * Still need to get to the end of the variable specification,
2100
2125
                 * so kludge up a Var structure for the modifications
2101
2126
                 */
2102
 
                v = (Var *) emalloc(sizeof(Var));
 
2127
                v = emalloc(sizeof(Var));
2103
2128
                v->name = UNCONST(str);
2104
2129
                v->val = Buf_Init(1);
2105
2130
                v->flags = VAR_JUNK;
2106
 
                Buf_Destroy (buf, FALSE);
 
2131
                Buf_Destroy(buf, FALSE);
2107
2132
            }
2108
2133
        } else
2109
 
            Buf_Destroy (buf, TRUE);
 
2134
            Buf_Destroy(buf, TRUE);
2110
2135
    }
2111
2136
 
2112
2137
 
2150
2175
     *                          each word
2151
2176
     *            :R            Substitute the root of each word
2152
2177
     *                          (pathname minus the suffix).
2153
 
     *            :O            ("Order") Sort words in variable.
 
2178
     *            :O            ("Order") Alphabeticaly sort words in variable.
 
2179
     *            :Ox           ("intermiX") Randomize words in variable.
2154
2180
     *            :u            ("uniq") Remove adjacent duplicate words.
2155
2181
     *            :tu           Converts the variable contents to uppercase.
2156
2182
     *            :tl           Converts the variable contents to lowercase.
2247
2273
                    VarPattern  pattern;
2248
2274
                    int how;
2249
2275
 
 
2276
                    v_ctxt = ctxt;
 
2277
                    sv_name = NULL;
2250
2278
                    ++tstr;
2251
2279
                    if (v->flags & VAR_JUNK) {
2252
2280
                        /*
2255
2283
                         */
2256
2284
                        sv_name = v->name;
2257
2285
                        v->name = strdup(v->name);
2258
 
                        v_ctxt = ctxt;
2259
2286
                    } else if (ctxt != VAR_GLOBAL) {
2260
2287
                        if (VarFind(v->name, ctxt, 0) == (Var *)NIL)
2261
2288
                            v_ctxt = VAR_GLOBAL;
2262
 
                        else
2263
 
                            v_ctxt = ctxt;
2264
2289
                    }
2265
2290
                        
2266
2291
                    switch ((how = *tstr)) {
2273
2298
                        cp = ++tstr;
2274
2299
                        break;
2275
2300
                    }
2276
 
                        /* '{' */
 
2301
                        /* XXX: appease vi sm: '{' */
2277
2302
                    delim = '}';
2278
2303
                    pattern.flags = 0;
2279
2304
 
2297
2322
                        Var_Append(v->name, pattern.rhs, v_ctxt);
2298
2323
                        break;
2299
2324
                    case '!':
2300
 
                        newStr = Cmd_Exec (pattern.rhs, &emsg);
 
2325
                        newStr = Cmd_Exec(pattern.rhs, &emsg);
2301
2326
                        if (emsg)
2302
 
                            Error (emsg, nstr);
 
2327
                            Error(emsg, nstr);
2303
2328
                        else
2304
2329
                           Var_Set(v->name, newStr,  v_ctxt, 0);
2305
2330
                        if (newStr)
2449
2474
                                                     NULL, &pattern.rightLen,
2450
2475
                                                     NULL)) == NULL)
2451
2476
                        goto cleanup;
2452
 
                    newStr = Cmd_Exec (pattern.rhs, &emsg);
 
2477
                    newStr = Cmd_Exec(pattern.rhs, &emsg);
2453
2478
                    free(UNCONST(pattern.rhs));
2454
2479
                    if (emsg)
2455
 
                        Error (emsg, nstr);
 
2480
                        Error(emsg, nstr);
2456
2481
                    termc = *cp;
2457
2482
                    delim = '\0';
2458
2483
                    if (v->flags & VAR_JUNK) {
2631
2656
                                    cp = tstr + 4;
2632
2657
                                    break;
2633
2658
                                default:
2634
 
                                    if (isdigit(tstr[3])) {
 
2659
                                    if (isdigit((unsigned char)tstr[3])) {
2635
2660
                                        char *ep;
2636
2661
                                        
2637
2662
                                        parsestate.varSpace =
2651
2676
                                /*
2652
2677
                                 * Found ":ts<unrecognised><unrecognised>".
2653
2678
                                 */
2654
 
                                break;  /* not us */
 
2679
                                goto bad_modifier;
2655
2680
                            }
2656
2681
 
2657
2682
                            termc = *cp;
2676
2701
                             * ":tu", ":tl"
2677
2702
                             */
2678
2703
                            if (tstr[1] == 'u' || tstr[1] == 'l') {
2679
 
                                newStr = VarChangeCase (nstr, (tstr[1] == 'u'));
 
2704
                                newStr = VarChangeCase(nstr, (tstr[1] == 'u'));
2680
2705
                                cp = tstr + 2;
2681
2706
                                termc = *cp;
2682
2707
                            } else if (tstr[1] == 'W' || tstr[1] == 'w') {
2692
2717
                        } else {
2693
2718
                            /*
2694
2719
                             * Found ":t<unrecognised><unrecognised>".
2695
 
                             * Should this be an error?
2696
2720
                             */
 
2721
                            goto bad_modifier;
2697
2722
                        }
2698
2723
                    } else {
2699
2724
                        /*
2700
2725
                         * Found ":t<endc>" or ":t:".
2701
 
                         * Should this be an error?
2702
2726
                         */
 
2727
                        goto bad_modifier;
2703
2728
                    }
2704
2729
                    break;
2705
2730
                }
2872
2897
                                                     &pattern.rightLen,
2873
2898
                                                     NULL)) == NULL)
2874
2899
                        goto cleanup;
 
2900
                        /* XXX: appease vi sm: ')' '}' */
2875
2901
 
2876
2902
                    termc = *--cp;
2877
2903
                    delim = '\0';
2965
2991
#endif
2966
2992
                case 'Q':
2967
2993
                    if (tstr[1] == endc || tstr[1] == ':') {
2968
 
                        newStr = VarQuote (nstr);
 
2994
                        newStr = VarQuote(nstr);
2969
2995
                        cp = tstr + 1;
2970
2996
                        termc = *cp;
2971
2997
                        break;
2972
2998
                    }
2973
 
                    /*FALLTHRU*/
 
2999
                    goto default_case;
2974
3000
                case 'T':
2975
3001
                    if (tstr[1] == endc || tstr[1] == ':') {
2976
3002
                        newStr = VarModify(ctxt, &parsestate, nstr, VarTail,
2979
3005
                        termc = *cp;
2980
3006
                        break;
2981
3007
                    }
2982
 
                    /*FALLTHRU*/
 
3008
                    goto default_case;
2983
3009
                case 'H':
2984
3010
                    if (tstr[1] == endc || tstr[1] == ':') {
2985
3011
                        newStr = VarModify(ctxt, &parsestate, nstr, VarHead,
2988
3014
                        termc = *cp;
2989
3015
                        break;
2990
3016
                    }
2991
 
                    /*FALLTHRU*/
 
3017
                    goto default_case;
2992
3018
                case 'E':
2993
3019
                    if (tstr[1] == endc || tstr[1] == ':') {
2994
3020
                        newStr = VarModify(ctxt, &parsestate, nstr, VarSuffix,
2997
3023
                        termc = *cp;
2998
3024
                        break;
2999
3025
                    }
3000
 
                    /*FALLTHRU*/
 
3026
                    goto default_case;
3001
3027
                case 'R':
3002
3028
                    if (tstr[1] == endc || tstr[1] == ':') {
3003
3029
                        newStr = VarModify(ctxt, &parsestate, nstr, VarRoot,
3006
3032
                        termc = *cp;
3007
3033
                        break;
3008
3034
                    }
3009
 
                    /*FALLTHRU*/
 
3035
                    goto default_case;
3010
3036
                case 'O':
 
3037
                {
 
3038
                    char otype;
 
3039
 
 
3040
                    cp = tstr + 1;      /* skip to the rest in any case */
3011
3041
                    if (tstr[1] == endc || tstr[1] == ':') {
3012
 
                        newStr = VarSort (nstr);
3013
 
                        cp = tstr + 1;
3014
 
                        termc = *cp;
3015
 
                        break;
 
3042
                        otype = 's';
 
3043
                        termc = *cp;
 
3044
                    } else if ( (tstr[1] == 'x') &&
 
3045
                                (tstr[2] == endc || tstr[2] == ':') ) {
 
3046
                        otype = tstr[1];
 
3047
                        cp = tstr + 2;
 
3048
                        termc = *cp;
 
3049
                    } else {
 
3050
                        goto bad_modifier;
3016
3051
                    }
3017
 
                    /*FALLTHRU*/
 
3052
                    newStr = VarOrder(nstr, otype);
 
3053
                    break;
 
3054
                }
3018
3055
                case 'u':
3019
3056
                    if (tstr[1] == endc || tstr[1] == ':') {
3020
 
                        newStr = VarUniq (nstr);
 
3057
                        newStr = VarUniq(nstr);
3021
3058
                        cp = tstr + 1;
3022
3059
                        termc = *cp;
3023
3060
                        break;
3024
3061
                    }
3025
 
                    /*FALLTHRU*/
 
3062
                    goto default_case;
3026
3063
#ifdef SUNSHCMD
3027
3064
                case 's':
3028
3065
                    if (tstr[1] == 'h' && (tstr[2] == endc || tstr[2] == ':')) {
3029
3066
                        const char *emsg;
3030
 
                        newStr = Cmd_Exec (nstr, &emsg);
 
3067
                        newStr = Cmd_Exec(nstr, &emsg);
3031
3068
                        if (emsg)
3032
 
                            Error (emsg, nstr);
 
3069
                            Error(emsg, nstr);
3033
3070
                        cp = tstr + 2;
3034
3071
                        termc = *cp;
3035
3072
                        break;
3036
3073
                    }
3037
 
                    /*FALLTHRU*/
 
3074
                    goto default_case;
3038
3075
#endif
3039
3076
                default:
3040
3077
                default_case: 
3100
3137
                    } else
3101
3138
#endif
3102
3139
                    {
3103
 
                        Error ("Unknown modifier '%c'", *tstr);
 
3140
                        Error("Unknown modifier '%c'", *tstr);
3104
3141
                        for (cp = tstr+1;
3105
3142
                             *cp != ':' && *cp != endc && *cp != '\0';
3106
3143
                             cp++)
3225
3262
    Buffer        buf;              /* Buffer for forming things */
3226
3263
    char          *val;             /* Value to substitute for a variable */
3227
3264
    int           length;           /* Length of the variable invocation */
 
3265
    Boolean       trailingBslash;   /* variable ends in \ */
3228
3266
    Boolean       doFree;           /* Set true if val should be freed */
3229
3267
    static Boolean errorReported;   /* Set true if an error has already
3230
3268
                                     * been reported to prevent a plethora
3231
3269
                                     * of messages when recursing */
3232
3270
 
3233
 
    buf = Buf_Init (MAKE_BSIZE);
 
3271
    buf = Buf_Init(MAKE_BSIZE);
3234
3272
    errorReported = FALSE;
 
3273
    trailingBslash = FALSE;
3235
3274
 
3236
3275
    while (*str) {
 
3276
        if (*str == '\n' && trailingBslash)
 
3277
            Buf_AddByte(buf, ' ');
3237
3278
        if (var == NULL && (*str == '$') && (str[1] == '$')) {
3238
3279
            /*
3239
3280
             * A dollar sign may be escaped either with another dollar sign.
3309
3350
                    continue;
3310
3351
            }
3311
3352
 
3312
 
            val = Var_Parse (str, ctxt, undefErr, &length, &doFree);
 
3353
            val = Var_Parse(str, ctxt, undefErr, &length, &doFree);
3313
3354
 
3314
3355
            /*
3315
3356
             * When we come down here, val should either point to the
3333
3374
                     * when the file is parsed.
3334
3375
                     */
3335
3376
                    if (!errorReported) {
3336
 
                        Parse_Error (PARSE_FATAL,
 
3377
                        Parse_Error(PARSE_FATAL,
3337
3378
                                     "Undefined variable \"%.*s\"",length,str);
3338
3379
                    }
3339
3380
                    str += length;
3353
3394
                 * Copy all the characters from the variable value straight
3354
3395
                 * into the new string.
3355
3396
                 */
3356
 
                Buf_AddBytes (buf, strlen (val), (Byte *)val);
 
3397
                length = strlen(val);
 
3398
                Buf_AddBytes(buf, length, (Byte *)val);
 
3399
                trailingBslash = length > 0 && val[length - 1] == '\\';
3357
3400
                if (doFree) {
3358
3401
                    free ((Address)val);
3359
3402
                }
3363
3406
 
3364
3407
    Buf_AddByte (buf, '\0');
3365
3408
    val = (char *)Buf_GetAll (buf, (int *)NULL);
3366
 
    Buf_Destroy (buf, FALSE);
 
3409
    Buf_Destroy(buf, FALSE);
3367
3410
    return (val);
3368
3411
}
3369
3412
 
3431
3474
void
3432
3475
Var_Init(void)
3433
3476
{
3434
 
    VAR_GLOBAL = Targ_NewGN ("Global");
3435
 
    VAR_CMD = Targ_NewGN ("Command");
 
3477
    VAR_GLOBAL = Targ_NewGN("Global");
 
3478
    VAR_CMD = Targ_NewGN("Command");
3436
3479
 
3437
3480
}
3438
3481