parent
4b00815e3d
commit
4696d0f378
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: make.1,v 1.296 2021/02/04 21:42:46 rillig Exp $
|
||||
.\" $NetBSD: make.1,v 1.297 2021/07/30 19:55:22 sjg Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
|
@ -29,7 +29,7 @@
|
|||
.\"
|
||||
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
|
||||
.\"
|
||||
.Dd December 22, 2020
|
||||
.Dd July 30, 2020
|
||||
.Dt MAKE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -1232,8 +1232,18 @@ but selects all words which do not match
|
|||
.Ar pattern .
|
||||
.It Cm \&:O
|
||||
Orders every word in variable alphabetically.
|
||||
.It Cm \&:On
|
||||
Orders every word in variable numerically.
|
||||
A number followed by one of
|
||||
.Ql K ,
|
||||
.Ql M
|
||||
or
|
||||
.Ql G
|
||||
is multiplied by the appropriate factor.
|
||||
.It Cm \&:Or
|
||||
Orders every word in variable in reverse alphabetical order.
|
||||
.It Cm \&:Orn
|
||||
Orders every word in variable in reverse numerical order.
|
||||
.It Cm \&:Ox
|
||||
Shuffles the words in variable.
|
||||
The results will be different each time you are referring to the
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.280 2021/06/29 00:35:23 sjg Exp $
|
||||
# $NetBSD: Makefile,v 1.281 2021/07/30 19:55:22 sjg Exp $
|
||||
#
|
||||
# Unit tests for make(1)
|
||||
#
|
||||
|
@ -355,6 +355,7 @@ TESTS+= varmod-match
|
|||
TESTS+= varmod-match-escape
|
||||
TESTS+= varmod-no-match
|
||||
TESTS+= varmod-order
|
||||
TESTS+= varmod-order-numeric
|
||||
TESTS+= varmod-order-reverse
|
||||
TESTS+= varmod-order-shuffle
|
||||
TESTS+= varmod-path
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
exit status 0
|
|
@ -0,0 +1,18 @@
|
|||
# $NetBSD: varmod-order-numeric.mk,v 1.1 2021/07/30 19:55:22 sjg Exp $
|
||||
#
|
||||
# Tests for the :On variable modifier, which returns the words, sorted in
|
||||
# ascending numeric order.
|
||||
|
||||
NUMBERS= 3 5 7 1 42 -42 1M 1k
|
||||
|
||||
.if ${NUMBERS:On} != "-42 1 3 5 7 42 1k 1M"
|
||||
. error ${NUMBERS:On}
|
||||
.endif
|
||||
|
||||
.if ${NUMBERS:Orn} != "1M 1k 42 7 5 3 1 -42"
|
||||
. error ${NUMBERS:Orn}
|
||||
.endif
|
||||
|
||||
|
||||
all:
|
||||
@:;
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: var.c,v 1.938 2021/06/21 18:25:20 rillig Exp $ */
|
||||
/* $NetBSD: var.c,v 1.939 2021/07/30 19:55:22 sjg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1989, 1990, 1993
|
||||
|
@ -140,7 +140,7 @@
|
|||
#include "metachar.h"
|
||||
|
||||
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
|
||||
MAKE_RCSID("$NetBSD: var.c,v 1.938 2021/06/21 18:25:20 rillig Exp $");
|
||||
MAKE_RCSID("$NetBSD: var.c,v 1.939 2021/07/30 19:55:22 sjg Exp $");
|
||||
|
||||
/*
|
||||
* Variables are defined using one of the VAR=value assignments. Their
|
||||
|
@ -3272,6 +3272,56 @@ bad_modifier:
|
|||
return AMR_BAD;
|
||||
}
|
||||
|
||||
#ifndef NUM_TYPE
|
||||
# define NUM_TYPE long long
|
||||
#endif
|
||||
|
||||
static NUM_TYPE
|
||||
num_val(const char *s)
|
||||
{
|
||||
NUM_TYPE val;
|
||||
char *ep;
|
||||
|
||||
val = strtoll(s, &ep, 0);
|
||||
if (ep != s) {
|
||||
switch (*ep) {
|
||||
case 'K':
|
||||
case 'k':
|
||||
val <<= 10;
|
||||
break;
|
||||
case 'M':
|
||||
case 'm':
|
||||
val <<= 20;
|
||||
break;
|
||||
case 'G':
|
||||
case 'g':
|
||||
val <<= 30;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
static int
|
||||
num_cmp_asc(const void *sa, const void *sb)
|
||||
{
|
||||
NUM_TYPE a, b;
|
||||
|
||||
a = num_val(*(const char *const *)sa);
|
||||
b = num_val(*(const char *const *)sb);
|
||||
return (a > b) ? 1 : (b > a) ? -1 : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
num_cmp_desc(const void *sa, const void *sb)
|
||||
{
|
||||
NUM_TYPE a, b;
|
||||
|
||||
a = num_val(*(const char *const *)sa);
|
||||
b = num_val(*(const char *const *)sb);
|
||||
return (a > b) ? -1 : (b > a) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int
|
||||
str_cmp_asc(const void *a, const void *b)
|
||||
{
|
||||
|
@ -3297,22 +3347,35 @@ ShuffleStrings(char **strs, size_t n)
|
|||
}
|
||||
}
|
||||
|
||||
/* :O (order ascending) or :Or (order descending) or :Ox (shuffle) */
|
||||
/* :O (order ascending) or :Or (order descending) or :Ox (shuffle) or
|
||||
* :On (numeric ascending) or :Onr or :Orn (numeric descending)
|
||||
*/
|
||||
static ApplyModifierResult
|
||||
ApplyModifier_Order(const char **pp, ModChain *ch)
|
||||
{
|
||||
const char *mod = (*pp)++; /* skip past the 'O' in any case */
|
||||
Words words;
|
||||
enum SortMode {
|
||||
ASC, DESC, SHUFFLE
|
||||
ASC, DESC, NUM_ASC, NUM_DESC, SHUFFLE
|
||||
} mode;
|
||||
|
||||
if (IsDelimiter(mod[1], ch)) {
|
||||
mode = ASC;
|
||||
} else if (mod[1] == 'n') {
|
||||
mode = NUM_ASC;
|
||||
(*pp)++;
|
||||
if (!IsDelimiter(mod[2], ch)) {
|
||||
(*pp)++;
|
||||
if (mod[2] == 'r')
|
||||
mode = NUM_DESC;
|
||||
}
|
||||
} else if ((mod[1] == 'r' || mod[1] == 'x') &&
|
||||
IsDelimiter(mod[2], ch)) {
|
||||
(*pp)++;
|
||||
mode = mod[1] == 'r' ? DESC : SHUFFLE;
|
||||
} else if (mod[1] == 'r' && mod[2] == 'n') {
|
||||
(*pp) += 2;
|
||||
mode = NUM_DESC;
|
||||
} else
|
||||
return AMR_BAD;
|
||||
|
||||
|
@ -3322,6 +3385,9 @@ ApplyModifier_Order(const char **pp, ModChain *ch)
|
|||
words = Str_Words(ch->expr->value.str, false);
|
||||
if (mode == SHUFFLE)
|
||||
ShuffleStrings(words.words, words.len);
|
||||
else if (mode == NUM_ASC || mode == NUM_DESC)
|
||||
qsort(words.words, words.len, sizeof words.words[0],
|
||||
mode == NUM_ASC ? num_cmp_asc : num_cmp_desc);
|
||||
else
|
||||
qsort(words.words, words.len, sizeof words.words[0],
|
||||
mode == ASC ? str_cmp_asc : str_cmp_desc);
|
||||
|
|
Loading…
Reference in New Issue