Skip to content
This repository
tag: v1699
Fetching contributors…

Cannot retrieve contributors at this time

file 102 lines (87 sloc) 2.84 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
(*
Copyright © 2011 MLstate

This file is part of OPA.

OPA is free software: you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License, version 3, as published by
the Free Software Foundation.

OPA is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
more details.

You should have received a copy of the GNU Affero General Public License
along with OPA. If not, see <http://www.gnu.org/licenses/>.
*)
module Obj = BaseObj

include Marshal

let buffer = Buffer.create 1000

let special_string = Obj.repr "i_am_a_trashed_closure"
let rec replacement_fun x =
  Printf.printf "BEWARE: unmarshalled fun is being called with %s.\n%!" (Obj.dump ~depth:5 x);
  Printf.printf "I will pretend that nothing happened but the program may segfault at any time.\n%!";
  Obj.magic replacement_fun
let replacement_fun = Obj.repr replacement_fun
let trashed_funs = Queue.create ()

let rec trash_obj obj =
  if Obj.is_block obj && Obj.tag obj < Obj.no_scan_tag then (
    for i = 0 to Obj.size obj - 1 do
      let sub = Obj.field obj i in
      if Obj.tag sub = Obj.closure_tag then (
        Queue.add sub trashed_funs;
        Obj.set_field obj i special_string
      ) else
        trash_obj sub
    done
  )

let trash_obj obj =
  let obj = Obj.repr obj in
  if Obj.tag obj = Obj.closure_tag || Obj.tag obj = Obj.infix_tag then
    failwith "trash_obj: cannot trash a closure"
  else (
    assert (Queue.is_empty trashed_funs);
    trash_obj obj
  )

let rec restore_obj obj =
  if Obj.is_block obj && Obj.tag obj < Obj.no_scan_tag then (
    for i = 0 to Obj.size obj - 1 do
      let sub = Obj.field obj i in
      if sub = special_string then
        Obj.set_field obj i (Queue.take trashed_funs)
      else
        restore_obj sub
    done
  )

let restore_obj obj =
  let obj = Obj.repr obj in
  if obj = special_string then
    failwith "cannot restore"
  else
    restore_obj obj

let rec fake_restore_obj obj =
  if Obj.is_block obj && Obj.tag obj < Obj.no_scan_tag then (
    for i = 0 to Obj.size obj - 1 do
      let sub = Obj.field obj i in
      if sub = special_string then
        Obj.set_field obj i replacement_fun
      else
        fake_restore_obj sub
    done
  )

let fake_restore_obj obj =
  let obj = Obj.repr obj in
  if obj = special_string then
    failwith "cannot fake_restore"
  else
    fake_restore_obj obj

let marshal_no_fun oc obj =
  trash_obj obj;
  try
    Marshal.to_channel oc obj [];
    restore_obj obj;
  with
  | e ->
    restore_obj obj;
    raise e

let unmarshal_no_fun ic =
  let obj = Marshal.from_channel ic in
  fake_restore_obj obj;
  obj
Something went wrong with that request. Please try again.