From c026e114b7ea36a15fcd6b8eb8c9e3068d5cc34c Mon Sep 17 00:00:00 2001 From: David Allsopp Date: Mon, 13 Jun 2016 22:27:27 +0100 Subject: [PATCH] Fix empty values in environment file Empty strings cause corrupt environment files, since two tabs are written in a row which are of course lexed as a single piece of whitespace. Alter the format so that the @ symbol on its own means an empty string (I'd have used something closer to $\epsilon$, but it'd never be portable...). The single string @ is represented by \@. Signed-off-by: David Allsopp --- src/format/opamFile.ml | 7 ++++++- src/format/opamLineLexer.mll | 12 ++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/format/opamFile.ml b/src/format/opamFile.ml index 9ca4c348c6a..8288bc147d2 100644 --- a/src/format/opamFile.ml +++ b/src/format/opamFile.ml @@ -294,7 +294,12 @@ module LinesBase = struct aux acc (i-1) in aux ([],0) (len - 1) - let escape_spaces str = + let escape_spaces = function + | "" -> + "@" + | "@" -> + "\\@" + | str -> let len = String.length str in match find_escapes str len with | [], _ -> str diff --git a/src/format/opamLineLexer.mll b/src/format/opamLineLexer.mll index 44ed6318671..e7d44305302 100644 --- a/src/format/opamLineLexer.mll +++ b/src/format/opamLineLexer.mll @@ -20,14 +20,19 @@ let word = Buffer.create 57 } -let normalchar = [^' ' '\t' '\n' '\\'] +let normalchar = [^' ' '\t' '\r' '\n' '\\'] rule main = parse -| '\n' { Lexing.new_line lexbuf; NEWLINE } +| '\n' | "\r\n" + { Lexing.new_line lexbuf; NEWLINE } | [' ' '\t']+ { main lexbuf } +| ('@' normalchar*) as w '\\' + { Buffer.reset word ; Buffer.add_string word w; escaped lexbuf } +| ('@' normalchar*) as w + { if w = "@" then WORD "" else WORD w } | (normalchar* as w) '\\' { Buffer.reset word ; Buffer.add_string word w; escaped lexbuf } -| (normalchar* as w) +| (normalchar+ as w) { WORD w } | eof { EOF } @@ -42,7 +47,6 @@ and escaped = parse let main lexbuf = let rec aux lines words = match main lexbuf with - | WORD "" -> aux lines words | WORD s -> aux lines (s::words) | NEWLINE -> let lines = if words = [] then lines else List.rev words::lines in