let unquote_string s =
    let length = String.length s in
    let chr n =
        if n > 255 || n < 0 then begin
            print_string "escape sequence out of range for character";
            '?'
        end
        else
            Char.chr n
    in
    let rec continue i =
        if i >= length then
            []
        else if s.[i] = '\\' then
            if i + 1 <= length && s.[i + 1] >= '0' && s.[i + 1] <= '7' then
                let c1 = Char.code s.[i + 1] - Char.code '0' in
                if i + 2 <= length && s.[i + 2] >= '0' && s.[i + 2] <= '7' then
                    let c2 = Char.code s.[i + 2] - Char.code '0' in
                    if i + 3 <= length && s.[i + 3] >= '0' && s.[i + 3] <= '7' then
                        let c3 = Char.code s.[i + 3] - Char.code '0' in
                        chr (c1 * 64 + c2 * 8 + c3)::continue (i + 4)
                    else
                        chr (c1 * 8 + c2)::continue (i + 3)
                else
                    chr c1::continue (i + 2)
            else
                match s.[i + 1] with
                    't' -> '\009'::continue (i + 2)
                  | 'a' -> '\007'::continue (i + 2)
                  | 'r' -> '\013'::continue (i + 2)
                  | 'n' -> '\010'::continue (i + 2)
                  | 'v' -> '\011'::continue (i + 2)
                  | 'b' -> '\008'::continue (i + 2)
                  | 'f' -> '\012'::continue (i + 2)
                  | '\\' -> '\\'::continue (i + 2)
                  | '?' -> '?'::continue (i + 2)
                  | '\'' -> '\''::continue (i + 2)
                  | '"' -> '"'::continue (i + 2)
                  | c -> c::continue (i + 2)
        else
            s.[i]::continue (i + 1)
    in
    continue 0