Sun Apr 21 21:59:48 2024 UTC (18d)
make: trim down code for parsing the :gmtime and :localtime modifiers

The :gmtime and :localtime modifiers are not used often and thus are not
time-critical. Exchange the custom code that parses an integer from a
substring for an additional memory allocation.

Thanks sjg@ for suggesting to avoid the custom parsing code.


(rillig)
diff -r1.1103 -r1.1104 src/usr.bin/make/var.c

cvs diff -r1.1103 -r1.1104 src/usr.bin/make/var.c (expand / switch to unified diff)

--- src/usr.bin/make/var.c 2024/04/21 08:56:49 1.1103
+++ src/usr.bin/make/var.c 2024/04/21 21:59:48 1.1104
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: var.c,v 1.1103 2024/04/21 08:56:49 rillig Exp $ */ 1/* $NetBSD: var.c,v 1.1104 2024/04/21 21:59:48 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990, 1993 4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -127,27 +127,27 @@ @@ -127,27 +127,27 @@
127#include <sys/types.h> 127#include <sys/types.h>
128#include <regex.h> 128#include <regex.h>
129#include <errno.h> 129#include <errno.h>
130#include <inttypes.h> 130#include <inttypes.h>
131#include <limits.h> 131#include <limits.h>
132#include <time.h> 132#include <time.h>
133 133
134#include "make.h" 134#include "make.h"
135#include "dir.h" 135#include "dir.h"
136#include "job.h" 136#include "job.h"
137#include "metachar.h" 137#include "metachar.h"
138 138
139/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */ 139/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
140MAKE_RCSID("$NetBSD: var.c,v 1.1103 2024/04/21 08:56:49 rillig Exp $"); 140MAKE_RCSID("$NetBSD: var.c,v 1.1104 2024/04/21 21:59:48 rillig Exp $");
141 141
142/* 142/*
143 * Variables are defined using one of the VAR=value assignments. Their 143 * Variables are defined using one of the VAR=value assignments. Their
144 * value can be queried by expressions such as $V, ${VAR}, or with modifiers 144 * value can be queried by expressions such as $V, ${VAR}, or with modifiers
145 * such as ${VAR:S,from,to,g:Q}. 145 * such as ${VAR:S,from,to,g:Q}.
146 * 146 *
147 * There are 3 kinds of variables: scope variables, environment variables, 147 * There are 3 kinds of variables: scope variables, environment variables,
148 * undefined variables. 148 * undefined variables.
149 * 149 *
150 * Scope variables are stored in a GNode.scope. The only way to undefine 150 * Scope variables are stored in a GNode.scope. The only way to undefine
151 * a scope variable is using the .undef directive. In particular, it must 151 * a scope variable is using the .undef directive. In particular, it must
152 * not be possible to undefine a variable during the evaluation of an 152 * not be possible to undefine a variable during the evaluation of an
153 * expression, or Var.name might point nowhere. (There is another, 153 * expression, or Var.name might point nowhere. (There is another,
@@ -2505,78 +2505,59 @@ TryParseTime(const char **pp, time_t *ou @@ -2505,78 +2505,59 @@ TryParseTime(const char **pp, time_t *ou
2505 if (!ch_isdigit(**pp)) 2505 if (!ch_isdigit(**pp))
2506 return false; 2506 return false;
2507 2507
2508 errno = 0; 2508 errno = 0;
2509 n = strtoul(*pp, &end, 10); 2509 n = strtoul(*pp, &end, 10);
2510 if (n == ULONG_MAX && errno == ERANGE) 2510 if (n == ULONG_MAX && errno == ERANGE)
2511 return false; 2511 return false;
2512 2512
2513 *pp = end; 2513 *pp = end;
2514 *out_time = (time_t)n; /* ignore possible truncation for now */ 2514 *out_time = (time_t)n; /* ignore possible truncation for now */
2515 return true; 2515 return true;
2516} 2516}
2517 2517
2518static bool 
2519Substring_ParseTime(Substring s, time_t *out_time) 
2520{ 
2521 const char *p; 
2522 unsigned long n; 
2523 
2524 n = 0; 
2525 for (p = s.start; p != s.end && ch_isdigit(*p); p++) { 
2526 unsigned long next = 10 * n + ((unsigned)*p - '0'); 
2527 if (next < n) 
2528 return false; 
2529 n = next; 
2530 } 
2531 if (p == s.start || p != s.end) 
2532 return false; 
2533 
2534 *out_time = (time_t)n; /* ignore possible truncation for now */ 
2535 return true; 
2536} 
2537 
2538/* :gmtime and :localtime */ 2518/* :gmtime and :localtime */
2539static ApplyModifierResult 2519static ApplyModifierResult
2540ApplyModifier_Time(const char **pp, ModChain *ch) 2520ApplyModifier_Time(const char **pp, ModChain *ch)
2541{ 2521{
2542 Expr *expr; 2522 Expr *expr;
2543 time_t t; 2523 time_t t;
2544 const char *args; 2524 const char *args;
2545 const char *mod = *pp; 2525 const char *mod = *pp;
2546 bool gmt = mod[0] == 'g'; 2526 bool gmt = mod[0] == 'g';
2547 2527
2548 if (!ModMatchEq(mod, gmt ? "gmtime" : "localtime", ch)) 2528 if (!ModMatchEq(mod, gmt ? "gmtime" : "localtime", ch))
2549 return AMR_UNKNOWN; 2529 return AMR_UNKNOWN;
2550 args = mod + (gmt ? 6 : 9); 2530 args = mod + (gmt ? 6 : 9);
2551 2531
2552 if (args[0] == '=') { 2532 if (args[0] == '=') {
2553 const char *p = args + 1; 2533 const char *p = args + 1;
2554 LazyBuf buf; 2534 LazyBuf buf;
 2535 FStr arg;
2555 if (!ParseModifierPartSubst(&p, true, '\0', ch->expr->emode, 2536 if (!ParseModifierPartSubst(&p, true, '\0', ch->expr->emode,
2556 ch, &buf, NULL, NULL)) 2537 ch, &buf, NULL, NULL))
2557 return AMR_CLEANUP; 2538 return AMR_CLEANUP;
 2539 arg = LazyBuf_DoneGet(&buf);
2558 if (ModChain_ShouldEval(ch)) { 2540 if (ModChain_ShouldEval(ch)) {
2559 Substring arg = LazyBuf_Get(&buf); 2541 const char *arg_p = arg.str;
2560 if (!Substring_ParseTime(arg, &t)) { 2542 if (!TryParseTime(&arg_p, &t) || *arg_p != '\0') {
2561 Parse_Error(PARSE_FATAL, 2543 Parse_Error(PARSE_FATAL,
2562 "Invalid time value \"%.*s\"", 2544 "Invalid time value \"%s\"", arg.str);
2563 (int)Substring_Length(arg), arg.start); 2545 FStr_Done(&arg);
2564 LazyBuf_Done(&buf); 
2565 return AMR_CLEANUP; 2546 return AMR_CLEANUP;
2566 } 2547 }
2567 } else 2548 } else
2568 t = 0; 2549 t = 0;
2569 LazyBuf_Done(&buf); 2550 FStr_Done(&arg);
2570 *pp = p; 2551 *pp = p;
2571 } else { 2552 } else {
2572 t = 0; 2553 t = 0;
2573 *pp = args; 2554 *pp = args;
2574 } 2555 }
2575 2556
2576 expr = ch->expr; 2557 expr = ch->expr;
2577 if (Expr_ShouldEval(expr)) 2558 if (Expr_ShouldEval(expr))
2578 Expr_SetValueOwn(expr, FormatTime(Expr_Str(expr), t, gmt)); 2559 Expr_SetValueOwn(expr, FormatTime(Expr_Str(expr), t, gmt));
2579 2560
2580 return AMR_OK; 2561 return AMR_OK;
2581} 2562}
2582 2563