let encode_c_string s = 
  (* borrowed from OCaml's string.ml *)
  let n = ref 0 in
  for i = 0 to String.length s - 1 do
    n := !n +
        (match String.unsafe_get s i with
          '"' | '\\' | '\n' | '\t' -> 2
        | c -> if is_printable c then 1 else 4)
  done;
  if !n = String.length s then s else begin
    let s' = String.create !n in
    n := 0;
    for i = 0 to String.length s - 1 do
      begin
        match String.unsafe_get s i with
          ('"' | '\\'as c ->
            String.unsafe_set s' !n '\\'; incr n; String.unsafe_set s' !n c
        | '\010' ->
            String.unsafe_set s' !n '\\'; incr n; String.unsafe_set s' !n 'n'
        | '\t' ->
            String.unsafe_set s' !n '\\'; incr n; String.unsafe_set s' !n 't'
        | c ->
            if is_printable c then
              String.unsafe_set s' !n c
            else begin
              let a = Char.code c in
              String.unsafe_set s' !n '\\';
              incr n;
              String.unsafe_set s' !n (Char.chr (48 + a / 64));
              incr n;
              String.unsafe_set s' !n (Char.chr (48 + (a / 8) mod 8));
              incr n;
              String.unsafe_set s' !n (Char.chr (48 + a mod 8))
            end
      end;
      incr n
    done;
    s'
  end