Skip to content

Commit 45a0a11

Browse files
committed
New lexer rules and udunits2 decodeInput function
1 parent 26629c4 commit 45a0a11

File tree

2 files changed

+46
-6
lines changed

2 files changed

+46
-6
lines changed

lib/scanner.l

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ from [Ff][Rr][Oo][Mm]
140140
since [Ss][Ii][Nn][Cc][Ee]
141141
ref [Rr][Ee][Ff]
142142
per [Pp][Ee][Rr]
143-
143+
nanspell ([nN][aA][nN](\([^()]*\))?)
144+
infspell ([iI][nN][fF]([iI][nN][iI][tT][yY])?)
145+
idchar [A-Za-z0-9_]
144146
%Start ID_SEEN SHIFT_SEEN DATE_SEEN CLOCK_SEEN
145147

146148
%%
@@ -149,6 +151,12 @@ per [Pp][Ee][Rr]
149151
_restartScanner = 0;
150152
}
151153

154+
<INITIAL,SHIFT_SEEN>{sign}?{nanspell}{idchar} { yyless(0);}
155+
<INITIAL,SHIFT_SEEN>{sign}?{infspell}{idchar} { yyless(0);}
156+
157+
<INITIAL,SHIFT_SEEN>{sign}?{nanspell} { yyerror("NaN is not allowed in unit expressions."); return 0; }
158+
<INITIAL,SHIFT_SEEN>{sign}?{infspell} { yyerror("Infinity is not allowed in unit expressions."); return 0; }
159+
152160
<INITIAL,ID_SEEN>{space}*(@|{after}|{from}|{ref}|{since}){space}* {
153161
BEGIN SHIFT_SEEN;
154162
return SHIFT;

prog/udunits2.c

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <stdarg.h>
2828
#include <stdio.h>
2929
#include <stdlib.h>
30+
#include <math.h>
3031
#include <string.h>
3132
#ifndef _MSC_VER
3233
#include <strings.h>
@@ -423,11 +424,42 @@ decodeInput(
423424

424425
ut_free(_haveUnit);
425426

426-
int nbytes;
427-
if (sscanf(input, "%lg %n", &_haveUnitAmount, &nbytes) == 1) {
428-
input += nbytes;
429-
}
430-
else {
427+
int nbytes = 0;
428+
double amt;
429+
const char *p = input;
430+
char *endp = NULL;
431+
432+
errno = 0;
433+
amt = strtod(p, &endp);
434+
435+
if (endp != p) {
436+
/* We did consume something that looks like a number? */
437+
int next = (unsigned char)*endp;
438+
439+
/* If the numeric value is non-finite (NaN/Inf) ... */
440+
if (!isfinite(amt)) {
441+
/* ... but the next char continues an identifier, then that was not an amount.
442+
Example: "nanosecond" -> "n" "a" "n" then "o" (identifier char).*/
443+
if (isalpha(next) || next == '_') {
444+
/* Treat as: no leading number; let ut_parse() see the whole string. */
445+
_haveUnitAmount = 1;
446+
/* DO NOT advance input. */
447+
} else {
448+
/* Truly a standalone non-finite amount (e.g. "nan m", "inf s") -> reject */
449+
errMsg("NaN or Infinity is not allowed in unit expressions.");
450+
return 0;
451+
}
452+
} else {
453+
/* Finite amount is OK: Accept and advance to the remainder. */
454+
_haveUnitAmount = amt;
455+
input = endp;
456+
/* Optional: skip a single ASCII space if present (traditional behavior). */
457+
while (*input && isspace((unsigned char)*input)) {
458+
++input;
459+
}
460+
}
461+
} else {
462+
/* No leading number parsed at all. */
431463
_haveUnitAmount = 1;
432464
}
433465

0 commit comments

Comments
 (0)