You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
("--allow-range", Arg.Unit (fun() -> opts := {!opts with allow_range=true}), "Allow the argument to be a range rather than a single number");
41
49
("--require-range", Arg.Unit (fun() -> opts := {!opts with require_range=true; allow_range=true}), "Require the argument to be a range rather than a single number");
50
+
("--hex", Arg.Unit (fun() -> opts := {!opts with parse_hex=true}), "Parse hexadecimal integers as valid numbers, complete with 0x-prefix");
51
+
("--octal", Arg.Unit (fun() -> opts := {!opts with parse_oct=true}), "Parse octal integers as valid numbers, complete with 0o-prefix");
52
+
("--binary", Arg.Unit (fun() -> opts := {!opts with parse_bin=true}), "Parse binary integers as valid numbers, complete with 0b-prefix");
53
+
("--decimal", Arg.Unit (fun() -> opts := {!opts with parse_dec=true}), "Continue to parse decimal numbers even when other radixes are requested, no prefix required");
42
54
("--", Arg.Rest (funs -> number_arg := s), "Interpret next item as an argument");
43
55
]
44
56
let usage =Printf.sprintf "Usage: %s [OPTIONS] <number>|<range>"Sys.argv.(0)
@@ -64,12 +76,24 @@ let check_positive opts m =
64
76
|Range_float_ ->
65
77
failwith "option '--positive does' not apply to a range value"
66
78
67
-
letlooks_like_numbervalue=
79
+
letlooks_like_decimalvalue=
68
80
trylet _ =Pcre2.exec ~pat:"^(\\-?)[0-9]+(\\.[0-9]+)?$" value intrue
69
81
withNot_found ->false
70
82
83
+
letlooks_like_hexvalue=
84
+
trylet _ =Pcre2.exec ~pat:"^(\\-?)0[xX][0-9a-fA-F]+$" value intrue
85
+
withNot_found ->false
86
+
87
+
letlooks_like_octalvalue=
88
+
trylet _ =Pcre2.exec ~pat:"^(\\-?)0[oO][0-7]+$" value intrue
89
+
withNot_found ->false
90
+
91
+
letlooks_like_binaryvalue=
92
+
trylet _ =Pcre2.exec ~pat:"^(\\-?)0[bB][0-1]+$" value intrue
93
+
withNot_found ->false
94
+
71
95
letis_relativevalue=
72
-
trylet _ =Pcre2.exec ~pat:"^[+-][0-9]+$" value intrue
96
+
trylet _ =Pcre2.exec ~pat:"^[+-](0[xboXBO])?[0-9a-fA-F]+$" value intrue
73
97
withNot_found ->false
74
98
75
99
letnumber_string_drop_modifiervalue=
@@ -87,24 +111,40 @@ let get_relative opts t =
87
111
else t
88
112
89
113
letnumber_of_stringoptss=
90
-
ifnot (looks_like_number s) thenPrintf.ksprintf failwith "'%s' is not a valid number" s else
91
-
let n = float_of_string_opt s in
92
-
match n with
93
-
|Somen ->
94
-
(* If floats are explicitly allowed, just return the number. *)
95
-
if opts.allow_float then n
96
-
(* If floats are not explicitly allowed, check if the argument has a decimal separator in it.
97
-
If the argument string contains a dot but float_of_string didn't dislike it,
98
-
it's a valid number but not an integer.
99
-
*)
100
-
elseifnot (String.contains s '.') then n
101
-
(* If float_of_string returned None, the argument string is just garbage rather than a number. *)
102
-
elsePrintf.ksprintf failwith "'%s' is not a valid integer number" s
103
-
|None ->
104
-
Printf.ksprintf failwith "'%s' is not a valid number" s
114
+
if (opts.allow_float &¬ opts.parse_dec) then
115
+
failwith "Only decimal numbers may be floating point"
116
+
elseif (opts.parse_hex && (looks_like_hex s)) ||
117
+
(opts.parse_oct && (looks_like_octal s)) ||
118
+
(opts.parse_bin && (looks_like_binary s)) then
119
+
(* float_of_string won't deal with octal or binary and hex-floats are just weird.
120
+
Easier to separate non-decimal parsing this way.
121
+
*)
122
+
let n = int_of_string_opt s in
123
+
match n with
124
+
|Somen ->
125
+
float_of_int n
126
+
|None ->
127
+
Printf.ksprintf failwith "'%s' is not a valid non-decimal number" s
128
+
elseif (opts.parse_dec && (looks_like_decimal s)) then
129
+
let n = float_of_string_opt s in
130
+
match n with
131
+
|Somen ->
132
+
(* If floats are explicitly allowed, just return the number. *)
133
+
if opts.allow_float then n
134
+
(* If floats are not explicitly allowed, check if the argument has a decimal separator in it.
135
+
If the argument string contains a dot but float_of_string didn't dislike it,
136
+
it's a valid number but not an integer.
137
+
*)
138
+
elseifnot (String.contains s '.') then n
139
+
(* If float_of_string returned None, the argument string is just garbage rather than a number. *)
140
+
elsePrintf.ksprintf failwith "'%s' is not a valid integer number" s
141
+
|None ->
142
+
Printf.ksprintf failwith "'%s' is not a valid number" s
143
+
elsePrintf.ksprintf failwith "'%s' is not a valid number" s
105
144
106
145
letrange_of_stringoptss=
107
-
let rs =String.split_on_char '-' s |>List.map String.trim |>List.map (number_of_string opts) in
146
+
let param_opts = { opts with parse_dec =true } in
147
+
let rs =String.split_on_char '-' s |>List.map String.trim |>List.map (number_of_string param_opts) in
108
148
match rs with
109
149
| [l; r] -> (l, r)
110
150
|exception (Failure msg) ->
@@ -148,7 +188,8 @@ let check_not_ranges opts m =
148
188
Printf.ksprintf failwith "Range is in one of excluded ranges"
149
189
150
190
letcheck_not_valuesoptsm=
151
-
let excluded_values =List.map (number_of_string opts) opts.not_values in
191
+
let param_opts = { opts with parse_dec =true } in
192
+
let excluded_values =List.map (number_of_string param_opts) opts.not_values in
152
193
if excluded_values =[]then()else
153
194
match m with
154
195
|Range_float_ -> Printf.ksprintf failwith "--not-value cannot be used with ranges"
@@ -170,17 +211,22 @@ let check_argument_type opts m =
170
211
elsePrintf.ksprintf failwith "Value must be a number, not a range"
171
212
172
213
letis_range_vals=
173
-
trylet _ =Pcre2.exec ~pat:"^[0-9]+-[0-9]+$" s intrue
214
+
trylet _ =Pcre2.exec ~pat:"^(0[xboXBO])?[0-9a-fA-F]+-(0[xboXBO])?[0-9a-fA-F]+$" s intrue
174
215
withNot_found ->false
175
216
176
217
letvar_numeric_strs=
177
218
match is_range_val s with
178
219
|true -> Range_string s
179
220
|false -> Number_string s
180
221
222
+
letcheck_default_radixopts=
223
+
if (not opts.parse_hex &¬ opts.parse_oct &¬ opts.parse_bin) then
0 commit comments