@@ -9,6 +9,7 @@ Require Import Crypto.Util.OptionList.
9
9
Require Import Crypto.Util.Strings.Parse.Common.
10
10
Require Import Crypto.Util.Strings.ParseArithmetic.
11
11
Require Import Crypto.Util.Strings.String.
12
+ Require Crypto.Util.Strings.Ascii.
12
13
Require Import Crypto.Util.Strings.Show .
13
14
Require Import Crypto.Util.Strings.Show .Enum.
14
15
Require Import Crypto.Util.Listable.
@@ -177,6 +178,52 @@ Definition parse_OpPrefix_list : list (string * OpPrefix)
177
178
Definition parse_OpPrefix : ParserAction OpPrefix
178
179
:= parse_strs parse_OpPrefix_list.
179
180
181
+ Definition chars_to_escape_list : list (string * ascii)
182
+ := Eval vm_compute in
183
+ List.map
184
+ (fun '(name, char) => (String name EmptyString, char))
185
+ [("b", Ascii.Backspace)
186
+ ; ("f", Ascii.FormFeed)
187
+ ; ("n", Ascii.LF)
188
+ ; ("r", Ascii.CR)
189
+ ; ("t", Ascii.HorizontalTab)
190
+ ; ("v", Ascii.VerticalTab)
191
+ ; ("""", """")
192
+ ; ("'", "'")
193
+ ; ("\", "\")
194
+ ; ("0", Ascii.Null)
195
+ ]%char.
196
+ Definition parse_escaped_char : ParserAction ascii :=
197
+ "\" ;;R
198
+ (parse_or_else
199
+ (parse_map ascii_of_N
200
+ (("x" ;;R parse_N_fixed_digits 16 false 2)
201
+ || (parse_N_fixed_digits 8 false 3)))
202
+ (parse_strs chars_to_escape_list)).
203
+
204
+ Definition should_escape (ch : ascii) : bool
205
+ := (List.existsb (Ascii.eqb ch) (List.map snd chars_to_escape_list))
206
+ || negb (Ascii.is_printable ch).
207
+
208
+ Definition escape_char (ch : ascii) : string :=
209
+ match List.find (fun '(escape_str, ch') => Ascii.eqb ch ch') chars_to_escape_list, should_escape ch with
210
+ | Some (escape_str, _), _ => "\" ++ escape_str
211
+ | None, true =>
212
+ let hex := Hex.show_N (Ascii.N_of_ascii ch) in
213
+ let hex := String.substring 2 (String.length hex) hex in
214
+ let hex := if (String.length hex <? 2)%nat then "0" ++ hex else hex in
215
+ let hex := if (String.length hex <? 2)%nat then "0" ++ hex else hex in
216
+ "\x" ++ hex
217
+ | None, false => String ch EmptyString
218
+ end %string.
219
+
220
+ Definition escape_string (s : string) : string :=
221
+ String.concat "" (List.map escape_char (list_ascii_of_string s)).
222
+
223
+ Definition unescape_string (s : string) : string :=
224
+ Option.value (finalize (parse_map string_of_list_ascii ( (parse_or_else parse_escaped_char (fun s => match s with EmptyString => [] | String char s => [(char, s)] end )* ))) s) s.
225
+
226
+
180
227
(** assumes no leading nor trailing whitespace and no comment *)
181
228
Definition parse_RawLine {opts : assembly_program_options} : ParserAction RawLine
182
229
:= fun s => (
@@ -194,6 +241,10 @@ Definition parse_RawLine {opts : assembly_program_options} : ParserAction RawLin
194
241
then [(DEFAULT_REL, "")]
195
242
else if String.endswith ":" s
196
243
then [(LABEL (substring 0 (pred (String.length s)) s), "")]
244
+ else if (String.to_upper mnemonic =? ".ASCII") && (String.startswith """" args) && (String.endswith """" args)
245
+ then [(ASCII (unescape_string (String.substring 1 (String.length args - 2) args)), "")]
246
+ else if (String.to_upper mnemonic =? ".ASCIZ") && (String.startswith """" args) && (String.endswith """" args)
247
+ then [(ASCIZ (unescape_string (String.substring 1 (String.length args - 2) args)), "")]
197
248
else if (s =? "")
198
249
then [(EMPTY, "")]
199
250
else if (List.find (String.eqb (String.to_lower mnemonic))
@@ -381,6 +432,8 @@ Global Instance show_RawLine : Show RawLine
381
432
| EMPTY => ""
382
433
| INSTR instr => show instr
383
434
| DIRECTIVE s => s
435
+ | ASCII s => ".ascii """ ++ escape_string s ++ """"
436
+ | ASCIZ s => ".asciz """ ++ escape_string s ++ """"
384
437
end .
385
438
386
439
Global Instance show_Line : Show Line
@@ -627,6 +680,8 @@ Fixpoint get_initial_data (ls : Lines) : list (AccessSize * list Z)
627
680
=> get_initial_data ls
628
681
| SECTION _
629
682
| ALIGN _
683
+ | ASCII _
684
+ | ASCIZ _
630
685
=> []
631
686
end
632
687
end .
0 commit comments