├── .gitignore ├── LICENSE ├── META.in ├── Makefile ├── README.md ├── VERSION ├── demo.ml ├── dum.ml ├── dum.mli ├── dum.opam ├── dune └── dune-project /.gitignore: -------------------------------------------------------------------------------- 1 | _build/ 2 | _opam/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The Library is distributed under the terms of the GNU Library General 2 | Public License version 2 (included below). 3 | 4 | As a special exception to the GNU Library General Public License, you 5 | may link, statically or dynamically, a "work that uses the Library" 6 | with a publicly distributed version of the Library to produce an 7 | executable file containing portions of the Library, and distribute 8 | that executable file under terms of your choice, without any of the 9 | additional requirements listed in clause 6 of the GNU Library General 10 | Public License. By "a publicly distributed version of the Library", 11 | we mean either the unmodified Library as distributed by INRIA, or a 12 | modified version of the Library that is distributed under the 13 | conditions defined in clause 2 of the GNU Library General Public 14 | License. This exception does not however invalidate any other reasons 15 | why the executable file might be covered by the GNU Library General 16 | Public License. 17 | 18 | ---------------------------------------------------------------------- 19 | 20 | GNU LIBRARY GENERAL PUBLIC LICENSE 21 | Version 2, June 1991 22 | 23 | Copyright (C) 1991 Free Software Foundation, Inc. 24 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 25 | Everyone is permitted to copy and distribute verbatim copies 26 | of this license document, but changing it is not allowed. 27 | 28 | [This is the first released version of the library GPL. It is 29 | numbered 2 because it goes with version 2 of the ordinary GPL.] 30 | 31 | Preamble 32 | 33 | The licenses for most software are designed to take away your 34 | freedom to share and change it. By contrast, the GNU General Public 35 | Licenses are intended to guarantee your freedom to share and change 36 | free software--to make sure the software is free for all its users. 37 | 38 | This license, the Library General Public License, applies to some 39 | specially designated Free Software Foundation software, and to any 40 | other libraries whose authors decide to use it. You can use it for 41 | your libraries, too. 42 | 43 | When we speak of free software, we are referring to freedom, not 44 | price. Our General Public Licenses are designed to make sure that you 45 | have the freedom to distribute copies of free software (and charge for 46 | this service if you wish), that you receive source code or can get it 47 | if you want it, that you can change the software or use pieces of it 48 | in new free programs; and that you know you can do these things. 49 | 50 | To protect your rights, we need to make restrictions that forbid 51 | anyone to deny you these rights or to ask you to surrender the rights. 52 | These restrictions translate to certain responsibilities for you if 53 | you distribute copies of the library, or if you modify it. 54 | 55 | For example, if you distribute copies of the library, whether gratis 56 | or for a fee, you must give the recipients all the rights that we gave 57 | you. You must make sure that they, too, receive or can get the source 58 | code. If you link a program with the library, you must provide 59 | complete object files to the recipients so that they can relink them 60 | with the library, after making changes to the library and recompiling 61 | it. And you must show them these terms so they know their rights. 62 | 63 | Our method of protecting your rights has two steps: (1) copyright 64 | the library, and (2) offer you this license which gives you legal 65 | permission to copy, distribute and/or modify the library. 66 | 67 | Also, for each distributor's protection, we want to make certain 68 | that everyone understands that there is no warranty for this free 69 | library. If the library is modified by someone else and passed on, we 70 | want its recipients to know that what they have is not the original 71 | version, so that any problems introduced by others will not reflect on 72 | the original authors' reputations. 73 | 74 | Finally, any free program is threatened constantly by software 75 | patents. We wish to avoid the danger that companies distributing free 76 | software will individually obtain patent licenses, thus in effect 77 | transforming the program into proprietary software. To prevent this, 78 | we have made it clear that any patent must be licensed for everyone's 79 | free use or not licensed at all. 80 | 81 | Most GNU software, including some libraries, is covered by the ordinary 82 | GNU General Public License, which was designed for utility programs. This 83 | license, the GNU Library General Public License, applies to certain 84 | designated libraries. This license is quite different from the ordinary 85 | one; be sure to read it in full, and don't assume that anything in it is 86 | the same as in the ordinary license. 87 | 88 | The reason we have a separate public license for some libraries is that 89 | they blur the distinction we usually make between modifying or adding to a 90 | program and simply using it. Linking a program with a library, without 91 | changing the library, is in some sense simply using the library, and is 92 | analogous to running a utility program or application program. However, in 93 | a textual and legal sense, the linked executable is a combined work, a 94 | derivative of the original library, and the ordinary General Public License 95 | treats it as such. 96 | 97 | Because of this blurred distinction, using the ordinary General 98 | Public License for libraries did not effectively promote software 99 | sharing, because most developers did not use the libraries. We 100 | concluded that weaker conditions might promote sharing better. 101 | 102 | However, unrestricted linking of non-free programs would deprive the 103 | users of those programs of all benefit from the free status of the 104 | libraries themselves. This Library General Public License is intended to 105 | permit developers of non-free programs to use free libraries, while 106 | preserving your freedom as a user of such programs to change the free 107 | libraries that are incorporated in them. (We have not seen how to achieve 108 | this as regards changes in header files, but we have achieved it as regards 109 | changes in the actual functions of the Library.) The hope is that this 110 | will lead to faster development of free libraries. 111 | 112 | The precise terms and conditions for copying, distribution and 113 | modification follow. Pay close attention to the difference between a 114 | "work based on the library" and a "work that uses the library". The 115 | former contains code derived from the library, while the latter only 116 | works together with the library. 117 | 118 | Note that it is possible for a library to be covered by the ordinary 119 | General Public License rather than by this special one. 120 | 121 | GNU LIBRARY GENERAL PUBLIC LICENSE 122 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 123 | 124 | 0. This License Agreement applies to any software library which 125 | contains a notice placed by the copyright holder or other authorized 126 | party saying it may be distributed under the terms of this Library 127 | General Public License (also called "this License"). Each licensee is 128 | addressed as "you". 129 | 130 | A "library" means a collection of software functions and/or data 131 | prepared so as to be conveniently linked with application programs 132 | (which use some of those functions and data) to form executables. 133 | 134 | The "Library", below, refers to any such software library or work 135 | which has been distributed under these terms. A "work based on the 136 | Library" means either the Library or any derivative work under 137 | copyright law: that is to say, a work containing the Library or a 138 | portion of it, either verbatim or with modifications and/or translated 139 | straightforwardly into another language. (Hereinafter, translation is 140 | included without limitation in the term "modification".) 141 | 142 | "Source code" for a work means the preferred form of the work for 143 | making modifications to it. For a library, complete source code means 144 | all the source code for all modules it contains, plus any associated 145 | interface definition files, plus the scripts used to control compilation 146 | and installation of the library. 147 | 148 | Activities other than copying, distribution and modification are not 149 | covered by this License; they are outside its scope. The act of 150 | running a program using the Library is not restricted, and output from 151 | such a program is covered only if its contents constitute a work based 152 | on the Library (independent of the use of the Library in a tool for 153 | writing it). Whether that is true depends on what the Library does 154 | and what the program that uses the Library does. 155 | 156 | 1. You may copy and distribute verbatim copies of the Library's 157 | complete source code as you receive it, in any medium, provided that 158 | you conspicuously and appropriately publish on each copy an 159 | appropriate copyright notice and disclaimer of warranty; keep intact 160 | all the notices that refer to this License and to the absence of any 161 | warranty; and distribute a copy of this License along with the 162 | Library. 163 | 164 | You may charge a fee for the physical act of transferring a copy, 165 | and you may at your option offer warranty protection in exchange for a 166 | fee. 167 | 168 | 2. You may modify your copy or copies of the Library or any portion 169 | of it, thus forming a work based on the Library, and copy and 170 | distribute such modifications or work under the terms of Section 1 171 | above, provided that you also meet all of these conditions: 172 | 173 | a) The modified work must itself be a software library. 174 | 175 | b) You must cause the files modified to carry prominent notices 176 | stating that you changed the files and the date of any change. 177 | 178 | c) You must cause the whole of the work to be licensed at no 179 | charge to all third parties under the terms of this License. 180 | 181 | d) If a facility in the modified Library refers to a function or a 182 | table of data to be supplied by an application program that uses 183 | the facility, other than as an argument passed when the facility 184 | is invoked, then you must make a good faith effort to ensure that, 185 | in the event an application does not supply such function or 186 | table, the facility still operates, and performs whatever part of 187 | its purpose remains meaningful. 188 | 189 | (For example, a function in a library to compute square roots has 190 | a purpose that is entirely well-defined independent of the 191 | application. Therefore, Subsection 2d requires that any 192 | application-supplied function or table used by this function must 193 | be optional: if the application does not supply it, the square 194 | root function must still compute square roots.) 195 | 196 | These requirements apply to the modified work as a whole. If 197 | identifiable sections of that work are not derived from the Library, 198 | and can be reasonably considered independent and separate works in 199 | themselves, then this License, and its terms, do not apply to those 200 | sections when you distribute them as separate works. But when you 201 | distribute the same sections as part of a whole which is a work based 202 | on the Library, the distribution of the whole must be on the terms of 203 | this License, whose permissions for other licensees extend to the 204 | entire whole, and thus to each and every part regardless of who wrote 205 | it. 206 | 207 | Thus, it is not the intent of this section to claim rights or contest 208 | your rights to work written entirely by you; rather, the intent is to 209 | exercise the right to control the distribution of derivative or 210 | collective works based on the Library. 211 | 212 | In addition, mere aggregation of another work not based on the Library 213 | with the Library (or with a work based on the Library) on a volume of 214 | a storage or distribution medium does not bring the other work under 215 | the scope of this License. 216 | 217 | 3. You may opt to apply the terms of the ordinary GNU General Public 218 | License instead of this License to a given copy of the Library. To do 219 | this, you must alter all the notices that refer to this License, so 220 | that they refer to the ordinary GNU General Public License, version 2, 221 | instead of to this License. (If a newer version than version 2 of the 222 | ordinary GNU General Public License has appeared, then you can specify 223 | that version instead if you wish.) Do not make any other change in 224 | these notices. 225 | 226 | Once this change is made in a given copy, it is irreversible for 227 | that copy, so the ordinary GNU General Public License applies to all 228 | subsequent copies and derivative works made from that copy. 229 | 230 | This option is useful when you wish to copy part of the code of 231 | the Library into a program that is not a library. 232 | 233 | 4. You may copy and distribute the Library (or a portion or 234 | derivative of it, under Section 2) in object code or executable form 235 | under the terms of Sections 1 and 2 above provided that you accompany 236 | it with the complete corresponding machine-readable source code, which 237 | must be distributed under the terms of Sections 1 and 2 above on a 238 | medium customarily used for software interchange. 239 | 240 | If distribution of object code is made by offering access to copy 241 | from a designated place, then offering equivalent access to copy the 242 | source code from the same place satisfies the requirement to 243 | distribute the source code, even though third parties are not 244 | compelled to copy the source along with the object code. 245 | 246 | 5. A program that contains no derivative of any portion of the 247 | Library, but is designed to work with the Library by being compiled or 248 | linked with it, is called a "work that uses the Library". Such a 249 | work, in isolation, is not a derivative work of the Library, and 250 | therefore falls outside the scope of this License. 251 | 252 | However, linking a "work that uses the Library" with the Library 253 | creates an executable that is a derivative of the Library (because it 254 | contains portions of the Library), rather than a "work that uses the 255 | library". The executable is therefore covered by this License. 256 | Section 6 states terms for distribution of such executables. 257 | 258 | When a "work that uses the Library" uses material from a header file 259 | that is part of the Library, the object code for the work may be a 260 | derivative work of the Library even though the source code is not. 261 | Whether this is true is especially significant if the work can be 262 | linked without the Library, or if the work is itself a library. The 263 | threshold for this to be true is not precisely defined by law. 264 | 265 | If such an object file uses only numerical parameters, data 266 | structure layouts and accessors, and small macros and small inline 267 | functions (ten lines or less in length), then the use of the object 268 | file is unrestricted, regardless of whether it is legally a derivative 269 | work. (Executables containing this object code plus portions of the 270 | Library will still fall under Section 6.) 271 | 272 | Otherwise, if the work is a derivative of the Library, you may 273 | distribute the object code for the work under the terms of Section 6. 274 | Any executables containing that work also fall under Section 6, 275 | whether or not they are linked directly with the Library itself. 276 | 277 | 6. As an exception to the Sections above, you may also compile or 278 | link a "work that uses the Library" with the Library to produce a 279 | work containing portions of the Library, and distribute that work 280 | under terms of your choice, provided that the terms permit 281 | modification of the work for the customer's own use and reverse 282 | engineering for debugging such modifications. 283 | 284 | You must give prominent notice with each copy of the work that the 285 | Library is used in it and that the Library and its use are covered by 286 | this License. You must supply a copy of this License. If the work 287 | during execution displays copyright notices, you must include the 288 | copyright notice for the Library among them, as well as a reference 289 | directing the user to the copy of this License. Also, you must do one 290 | of these things: 291 | 292 | a) Accompany the work with the complete corresponding 293 | machine-readable source code for the Library including whatever 294 | changes were used in the work (which must be distributed under 295 | Sections 1 and 2 above); and, if the work is an executable linked 296 | with the Library, with the complete machine-readable "work that 297 | uses the Library", as object code and/or source code, so that the 298 | user can modify the Library and then relink to produce a modified 299 | executable containing the modified Library. (It is understood 300 | that the user who changes the contents of definitions files in the 301 | Library will not necessarily be able to recompile the application 302 | to use the modified definitions.) 303 | 304 | b) Accompany the work with a written offer, valid for at 305 | least three years, to give the same user the materials 306 | specified in Subsection 6a, above, for a charge no more 307 | than the cost of performing this distribution. 308 | 309 | c) If distribution of the work is made by offering access to copy 310 | from a designated place, offer equivalent access to copy the above 311 | specified materials from the same place. 312 | 313 | d) Verify that the user has already received a copy of these 314 | materials or that you have already sent this user a copy. 315 | 316 | For an executable, the required form of the "work that uses the 317 | Library" must include any data and utility programs needed for 318 | reproducing the executable from it. However, as a special exception, 319 | the source code distributed need not include anything that is normally 320 | distributed (in either source or binary form) with the major 321 | components (compiler, kernel, and so on) of the operating system on 322 | which the executable runs, unless that component itself accompanies 323 | the executable. 324 | 325 | It may happen that this requirement contradicts the license 326 | restrictions of other proprietary libraries that do not normally 327 | accompany the operating system. Such a contradiction means you cannot 328 | use both them and the Library together in an executable that you 329 | distribute. 330 | 331 | 7. You may place library facilities that are a work based on the 332 | Library side-by-side in a single library together with other library 333 | facilities not covered by this License, and distribute such a combined 334 | library, provided that the separate distribution of the work based on 335 | the Library and of the other library facilities is otherwise 336 | permitted, and provided that you do these two things: 337 | 338 | a) Accompany the combined library with a copy of the same work 339 | based on the Library, uncombined with any other library 340 | facilities. This must be distributed under the terms of the 341 | Sections above. 342 | 343 | b) Give prominent notice with the combined library of the fact 344 | that part of it is a work based on the Library, and explaining 345 | where to find the accompanying uncombined form of the same work. 346 | 347 | 8. You may not copy, modify, sublicense, link with, or distribute 348 | the Library except as expressly provided under this License. Any 349 | attempt otherwise to copy, modify, sublicense, link with, or 350 | distribute the Library is void, and will automatically terminate your 351 | rights under this License. However, parties who have received copies, 352 | or rights, from you under this License will not have their licenses 353 | terminated so long as such parties remain in full compliance. 354 | 355 | 9. You are not required to accept this License, since you have not 356 | signed it. However, nothing else grants you permission to modify or 357 | distribute the Library or its derivative works. These actions are 358 | prohibited by law if you do not accept this License. Therefore, by 359 | modifying or distributing the Library (or any work based on the 360 | Library), you indicate your acceptance of this License to do so, and 361 | all its terms and conditions for copying, distributing or modifying 362 | the Library or works based on it. 363 | 364 | 10. Each time you redistribute the Library (or any work based on the 365 | Library), the recipient automatically receives a license from the 366 | original licensor to copy, distribute, link with or modify the Library 367 | subject to these terms and conditions. You may not impose any further 368 | restrictions on the recipients' exercise of the rights granted herein. 369 | You are not responsible for enforcing compliance by third parties to 370 | this License. 371 | 372 | 11. If, as a consequence of a court judgment or allegation of patent 373 | infringement or for any other reason (not limited to patent issues), 374 | conditions are imposed on you (whether by court order, agreement or 375 | otherwise) that contradict the conditions of this License, they do not 376 | excuse you from the conditions of this License. If you cannot 377 | distribute so as to satisfy simultaneously your obligations under this 378 | License and any other pertinent obligations, then as a consequence you 379 | may not distribute the Library at all. For example, if a patent 380 | license would not permit royalty-free redistribution of the Library by 381 | all those who receive copies directly or indirectly through you, then 382 | the only way you could satisfy both it and this License would be to 383 | refrain entirely from distribution of the Library. 384 | 385 | If any portion of this section is held invalid or unenforceable under any 386 | particular circumstance, the balance of the section is intended to apply, 387 | and the section as a whole is intended to apply in other circumstances. 388 | 389 | It is not the purpose of this section to induce you to infringe any 390 | patents or other property right claims or to contest validity of any 391 | such claims; this section has the sole purpose of protecting the 392 | integrity of the free software distribution system which is 393 | implemented by public license practices. Many people have made 394 | generous contributions to the wide range of software distributed 395 | through that system in reliance on consistent application of that 396 | system; it is up to the author/donor to decide if he or she is willing 397 | to distribute software through any other system and a licensee cannot 398 | impose that choice. 399 | 400 | This section is intended to make thoroughly clear what is believed to 401 | be a consequence of the rest of this License. 402 | 403 | 12. If the distribution and/or use of the Library is restricted in 404 | certain countries either by patents or by copyrighted interfaces, the 405 | original copyright holder who places the Library under this License may add 406 | an explicit geographical distribution limitation excluding those countries, 407 | so that distribution is permitted only in or among countries not thus 408 | excluded. In such case, this License incorporates the limitation as if 409 | written in the body of this License. 410 | 411 | 13. The Free Software Foundation may publish revised and/or new 412 | versions of the Library General Public License from time to time. 413 | Such new versions will be similar in spirit to the present version, 414 | but may differ in detail to address new problems or concerns. 415 | 416 | Each version is given a distinguishing version number. If the Library 417 | specifies a version number of this License which applies to it and 418 | "any later version", you have the option of following the terms and 419 | conditions either of that version or of any later version published by 420 | the Free Software Foundation. If the Library does not specify a 421 | license version number, you may choose any version ever published by 422 | the Free Software Foundation. 423 | 424 | 14. If you wish to incorporate parts of the Library into other free 425 | programs whose distribution conditions are incompatible with these, 426 | write to the author to ask for permission. For software which is 427 | copyrighted by the Free Software Foundation, write to the Free 428 | Software Foundation; we sometimes make exceptions for this. Our 429 | decision will be guided by the two goals of preserving the free status 430 | of all derivatives of our free software and of promoting the sharing 431 | and reuse of software generally. 432 | 433 | NO WARRANTY 434 | 435 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 436 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 437 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 438 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 439 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 440 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 441 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 442 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 443 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 444 | 445 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 446 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 447 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 448 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 449 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 450 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 451 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 452 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 453 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 454 | DAMAGES. 455 | 456 | END OF TERMS AND CONDITIONS 457 | 458 | Appendix: How to Apply These Terms to Your New Libraries 459 | 460 | If you develop a new library, and you want it to be of the greatest 461 | possible use to the public, we recommend making it free software that 462 | everyone can redistribute and change. You can do so by permitting 463 | redistribution under these terms (or, alternatively, under the terms of the 464 | ordinary General Public License). 465 | 466 | To apply these terms, attach the following notices to the library. It is 467 | safest to attach them to the start of each source file to most effectively 468 | convey the exclusion of warranty; and each file should have at least the 469 | "copyright" line and a pointer to where the full notice is found. 470 | 471 | 472 | Copyright (C) 473 | 474 | This library is free software; you can redistribute it and/or 475 | modify it under the terms of the GNU Library General Public 476 | License as published by the Free Software Foundation; either 477 | version 2 of the License, or (at your option) any later version. 478 | 479 | This library is distributed in the hope that it will be useful, 480 | but WITHOUT ANY WARRANTY; without even the implied warranty of 481 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 482 | Library General Public License for more details. 483 | 484 | You should have received a copy of the GNU Library General Public 485 | License along with this library; if not, write to the Free 486 | Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, 487 | MA 02111-1307, USA 488 | 489 | Also add information on how to contact you by electronic and paper mail. 490 | 491 | You should also get your employer (if you work as a programmer) or your 492 | school, if any, to sign a "copyright disclaimer" for the library, if 493 | necessary. Here is a sample; alter the names: 494 | 495 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 496 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 497 | 498 | , 1 April 1990 499 | Ty Coon, President of Vice 500 | 501 | That's all there is to it! 502 | -------------------------------------------------------------------------------- /META.in: -------------------------------------------------------------------------------- 1 | version = "@VERSION@" 2 | description = "Dump OCaml values" 3 | requires = "easy-format" 4 | archive(byte) = "dum.cma" 5 | archive(native) = "dum.cmxa" 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VERSION = 1.0.1 2 | 3 | .PHONY: default 4 | default: all opt 5 | 6 | .PHONY: all opt install uninstall clean release doc VERSION 7 | all: VERSION 8 | ocamlfind ocamlc -c -g dum.mli -package easy-format 9 | ocamlfind ocamlc -c -g dum.ml -package easy-format 10 | ocamlfind ocamlc -a -g -o dum.cma dum.cmo -package easy-format 11 | touch done-all 12 | opt: VERSION 13 | ocamlfind ocamlc -c -g dum.mli -package easy-format 14 | ocamlfind ocamlopt -c -g dum.ml -package easy-format 15 | ocamlfind ocamlopt -a -g -o dum.cmxa dum.cmx -package easy-format 16 | touch done-opt 17 | install: META 18 | ocamlfind install dum META dum.mli dum.cmi \ 19 | `test -f done-all && echo dum.cma || :`\ 20 | `test -f done-opt && echo dum.cmx dum.cmxa dum.o dum.a || :` 21 | uninstall: 22 | ocamlfind remove dum 23 | 24 | doc: 25 | mkdir -p doc/html 26 | ocamlfind ocamldoc -d doc/html -package easy-format dum.mli -html 27 | 28 | clean: 29 | rm -f *.cm[aiox] *.cmxa *.a *.o *.annot *.opt *.run *~ \ 30 | done-all done-opt 31 | rm -rf doc 32 | 33 | VERSION: 34 | echo "$(VERSION)" > VERSION 35 | 36 | META: 37 | sed -e 's:@VERSION@:$(VERSION):' META.in > META 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Dum 2 | === 3 | 4 | Purpose 5 | ------- 6 | 7 | Inspecting arbitrary OCaml values for debugging or just for fun. 8 | 9 | Cycles are detected and an additional limit on the size of the dump is 10 | set by default. It is therefore safe to use for printing out 11 | exceptions in error messages. 12 | 13 | Closure fields and object fields are printed. 14 | 15 | All the lazy values (forced or not) can be printed but this is optional. 16 | Some forced lazy values will always be printed no matter what. 17 | 18 | 19 | Installation 20 | ------------ 21 | 22 | ``` 23 | $ opam update 24 | $ opam install dum 25 | ``` 26 | 27 | Usage 28 | ----- 29 | 30 | We do not recommend the use of this library in production code due to 31 | its reliance on OCaml internals and unsafe memory access. 32 | 33 | ```ocaml 34 | $ utop -require dum 35 | # Dum.to_stdout (123, "abc", Not_found, [`A; `B 'x']);; 36 | (123 "abc" object-7 () [ 65 (66 120) ]) 37 | ``` 38 | 39 | A circular list is printed as follows: 40 | 41 | ```ocaml 42 | # let rec cyc = 1 :: 2 :: 3 :: cyc;; 43 | val cyc : int list = [1; 2; 3; ] 44 | 45 | utop # Dum.to_stdout cyc;; 46 | #0: (1 (2 (3 #0))) 47 | ``` 48 | 49 | First-class modules can be inspected as well. Here's what I get for the `Sys` module: 50 | 51 | ```ocaml 52 | # module type Sys = module type of Sys;; 53 | # Dum.to_stdout (module Sys : Sys);; 54 | ( 55 | ("/home/martin/.opam/4.05.0/bin/utop" "-require" "dum") 56 | "/home/martin/.opam/4.05.0/bin/utop" 57 | closure () 58 | (1) 59 | "Unix" 60 | 1 61 | 1 62 | 0 63 | 0 64 | 64 65 | 63 66 | 0 67 | 144115188075855863 68 | 18014398509481983 69 | #0: closure () 70 | -1 71 | -2 72 | -3 73 | -4 74 | -5 75 | -6 76 | -7 77 | -8 78 | -9 79 | -10 80 | -11 81 | -12 82 | -13 83 | -14 84 | -15 85 | -16 86 | -17 87 | -18 88 | -19 89 | -20 90 | -21 91 | -22 92 | -23 93 | -24 94 | -25 95 | -26 96 | -27 97 | -28 98 | #1: object1 () 99 | closure (#0 -6 #1) 100 | "4.05.0" 101 | closure () 102 | closure () 103 | ) 104 | ``` 105 | 106 | See `dum.mli` for more information. 107 | 108 | License 109 | ------- 110 | 111 | GNU LGPL with exception on static linking, see file LICENSE. 112 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 1.0.0 2 | -------------------------------------------------------------------------------- /demo.ml: -------------------------------------------------------------------------------- 1 | 2 | type t = A of int list | B of int * int | C of t * t 3 | 4 | let demo ?lim () = 5 | let tbl = Hashtbl.create 5 in 6 | let rec l = 3 :: 4 :: 5 :: l in 7 | let rec v = C (A [1;2;3], v) in 8 | Hashtbl.add tbl `A ("abc", `Table (tbl, l)); 9 | Hashtbl.add tbl `B ("xyz", `List (1 :: 2 :: l)); 10 | Hashtbl.add tbl (`C (Some 1.234)) ("C", `Fun (fun () -> ())); 11 | Hashtbl.add tbl `D ("", `Variant (B (3, 4))); 12 | let x = 13 | (object (self) 14 | method tbl = tbl 15 | end), 16 | [| 1.0; 2.0 |], 17 | { Complex.re = 0.; 18 | im = 1. }, 19 | (Failure "test"), 20 | [ true; false ], 21 | () 22 | in 23 | 24 | Dum.to_stdout ?lim x; 25 | print_newline () 26 | 27 | let _ = 28 | demo (); 29 | demo ~lim:10 (); 30 | demo ~lim:2 () 31 | 32 | -------------------------------------------------------------------------------- /dum.ml: -------------------------------------------------------------------------------- 1 | 2 | (**************************************************************************) 3 | (* *) 4 | (* Copyright (C) 2008 Wink Technologies Inc. (contact martin@wink.com) *) 5 | (* Copyright (C) 2008 Jean-Christophe Filliatre *) 6 | (* Copyright (C) 2005 Merjis Ltd., Richard W.M. Jones *) 7 | (* *) 8 | (* This software is free software; you can redistribute it and/or *) 9 | (* modify it under the terms of the GNU Library General Public *) 10 | (* License version 2.1, with the special exception on linking *) 11 | (* described in file LICENSE. *) 12 | (* *) 13 | (* This software is distributed in the hope that it will be useful, *) 14 | (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) 15 | (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *) 16 | (* *) 17 | (**************************************************************************) 18 | 19 | 20 | open Printf 21 | 22 | (* Pointers already visited are stored in a hash-table, where 23 | comparisons are done using physical equality. *) 24 | 25 | module H = Hashtbl.Make( 26 | struct 27 | type t = Obj.t 28 | let equal = (==) 29 | let hash r = Hashtbl.hash (Obj.obj r : int) 30 | end) 31 | 32 | type node = 33 | Int of int 34 | | Cycle of address option ref 35 | | Block of block 36 | 37 | and block_value = 38 | String of string 39 | | Float of float 40 | | Array of node list 41 | | Float_array of float array 42 | | Tag of (int * node list) 43 | | Object of (int * node list) 44 | | Closure of node list 45 | | Lazy of node (* a closure *) 46 | | Forward of node 47 | | Opaque of string (* not representable *) 48 | | List of node list (* anything that could be a non-empty list *) 49 | 50 | and address = int 51 | 52 | and block = { 53 | mutable address : address option ref; 54 | mutable show_address : bool; 55 | node_value : block_value lazy_t; 56 | } 57 | 58 | let create_node_table () = 59 | let counter = ref 0 in 60 | counter, (H.create 257 : block H.t) 61 | 62 | let get (_, tbl) r = 63 | try 64 | let x = H.find tbl r in 65 | x.show_address <- true; 66 | Some x.address 67 | with Not_found -> 68 | None 69 | 70 | let add (counter, tbl) r lz = 71 | assert (not (H.mem tbl r)); 72 | let x = { 73 | address = ref None; 74 | show_address = false; 75 | node_value = lz 76 | } in 77 | H.add tbl r x; 78 | x 79 | 80 | 81 | (* Don't use an array here. 82 | (unless you make sure it's not created as a double array) 83 | *) 84 | let get_fields r n = 85 | let l = ref [] in 86 | for i = n - 1 downto 0 do 87 | l := Obj.field r i :: !l 88 | done; 89 | !l 90 | 91 | 92 | let is_list tbl r = 93 | let rec is_list tbl r = 94 | if Obj.is_int r then 95 | r = Obj.repr 0 (* [] *) 96 | else 97 | let s = Obj.size r and t = Obj.tag r in 98 | t = 0 && s = 2 && not (H.mem tbl r) && 99 | (H.add tbl r (); 100 | let tail = Obj.field r 1 in 101 | is_list tbl tail) 102 | in 103 | let b = is_list tbl r in 104 | H.clear tbl; 105 | b 106 | 107 | 108 | let rec get_list accu r = 109 | if Obj.is_int r then 110 | List.rev accu 111 | else 112 | let h = Obj.field r 0 in 113 | get_list (h :: accu) (Obj.field r 1) 114 | 115 | 116 | let map f l = List.rev (List.rev_map f l) 117 | 118 | 119 | let default_lim = ref 100 120 | let default_show_lazy = ref false 121 | 122 | exception Too_big 123 | 124 | let rev_iter f l = List.iter f (List.rev l) 125 | 126 | 127 | (* Set the show_address field *) 128 | let rec force = function 129 | Int _ -> () 130 | | Cycle _ -> () 131 | | Block b -> 132 | match Lazy.force b.node_value with 133 | String _ -> () 134 | | Float _ -> () 135 | | Array l -> List.iter force l 136 | | Float_array _ -> () 137 | | Tag (t, l) -> List.iter force l 138 | | Object (id, l) -> List.iter force l 139 | | Closure l -> List.iter force l 140 | | Lazy x -> force x 141 | | Forward x -> force x 142 | | Opaque _ -> () 143 | | List l -> List.iter force l 144 | 145 | (* Set the actual addresses, using left-to-right numbering *) 146 | let set_addresses x = 147 | let counter = ref 0 in 148 | 149 | let rec force = function 150 | Int _ -> () 151 | | Cycle _ -> () 152 | | Block b -> 153 | if b.show_address then ( 154 | b.address := Some !counter; 155 | incr counter 156 | ); 157 | match Lazy.force b.node_value with 158 | String s -> () 159 | | Float _ -> () 160 | | Array l -> List.iter force l 161 | | Float_array _ -> () 162 | | Tag (t, l) -> List.iter force l 163 | | Object (id, l) -> List.iter force l 164 | | Closure l -> List.iter force l 165 | | Lazy x -> force x 166 | | Forward x -> force x 167 | | Opaque _ -> () 168 | | List l -> List.iter force l 169 | in 170 | 171 | force x 172 | 173 | 174 | 175 | let dump_tree ?show_lazy ?lim x = 176 | 177 | let lim = max 1 ( 178 | match lim with 179 | None -> !default_lim 180 | | Some n -> n 181 | ) in 182 | 183 | let show_lazy = 184 | match show_lazy with 185 | None -> !default_show_lazy 186 | | Some b -> b 187 | in 188 | 189 | let tbl = create_node_table () in 190 | let tbl2 = H.create 10 in 191 | let size = ref 0 in 192 | 193 | let rec dump r = 194 | incr size; 195 | if !size > lim then 196 | raise Too_big 197 | else 198 | if Obj.is_int r then 199 | Int (Obj.obj r : int) 200 | else 201 | dump_block r 202 | 203 | and dump_block r = 204 | match get tbl r with 205 | Some addr -> Cycle addr 206 | | None -> 207 | let lz = lazy ( 208 | let saved_size = !size in 209 | try 210 | dump_shared_block r 211 | with Too_big -> 212 | size := saved_size; 213 | Opaque "..." 214 | ) in 215 | Block (add tbl r lz) 216 | 217 | and dump_shared_block r = 218 | let s = Obj.size r and t = Obj.tag r in 219 | if is_list tbl2 r then 220 | let fields = get_list [] r in 221 | List (map dump fields) 222 | else if t = 0 then 223 | let fields = get_fields r s in 224 | Array (map dump fields) 225 | else if t = Obj.double_array_tag then 226 | Float_array (Obj.obj r : float array) 227 | else if t = Obj.lazy_tag then 228 | if show_lazy then ( 229 | assert (s = 1); 230 | Lazy (dump (Obj.field r 0)) 231 | ) 232 | else 233 | Opaque "lazy" 234 | else if t = Obj.forward_tag then ( 235 | if show_lazy then ( 236 | assert (Lazy.lazy_is_val (Obj.obj r)); 237 | Forward (dump (Obj.repr (Lazy.force_val (Obj.obj r)))) 238 | ) 239 | else 240 | Opaque "forward" 241 | ) 242 | else if t = Obj.closure_tag then 243 | let fields = get_fields r s in 244 | assert (s >= 1); 245 | Closure (map dump (List.tl fields)) 246 | 247 | else if t = Obj.object_tag then 248 | let fields = get_fields r s in 249 | assert (s >= 2); 250 | let id = 251 | let r = Obj.repr (List.nth fields 1) in 252 | assert (Obj.is_int r); 253 | (Obj.obj r : int) 254 | in 255 | let slots = map dump (List.tl (List.tl fields)) in 256 | (* No information on decoding the class (first field). 257 | So just print out the ID and the slots. *) 258 | Object (id, slots) 259 | 260 | else if t = Obj.infix_tag then 261 | Opaque "infix" 262 | else if t < Obj.no_scan_tag then 263 | let fields = get_fields r s in 264 | Tag (t, map dump fields) 265 | else if t = Obj.string_tag then ( 266 | let str = (Obj.obj r : string) in 267 | size := !size + (String.length str / 8); 268 | if !size > lim then 269 | raise Too_big 270 | else 271 | String str 272 | ) 273 | else if t = Obj.double_tag then 274 | Float (Obj.obj r : float) 275 | else if t = Obj.abstract_tag then 276 | Opaque "abstract" 277 | else if t = Obj.custom_tag then 278 | Opaque "custom" 279 | else if t = Obj.final_tag then 280 | Opaque "final" 281 | else if t = Obj.out_of_heap_tag then 282 | Opaque "out of heap" 283 | else 284 | Opaque ("unknown tag " ^ string_of_int t) 285 | 286 | in 287 | 288 | let result = dump (Obj.repr x) in 289 | force result; 290 | set_addresses result; 291 | result 292 | 293 | 294 | 295 | module E = Easy_format 296 | 297 | 298 | let atom = E.atom 299 | 300 | let list = E.list 301 | 302 | let tuple = { list with 303 | E.space_after_opening = false; 304 | space_before_closing = false } 305 | 306 | let label = E.label 307 | 308 | let format_float x = E.Atom (string_of_float x, atom) 309 | 310 | let rec format = function 311 | Int i -> E.Atom (string_of_int i, atom) 312 | | Cycle x -> 313 | (match !x with 314 | None -> assert false 315 | | Some n -> E.Atom (sprintf "#%i" n, atom)) 316 | | Block b -> 317 | let node = 318 | match Lazy.force b.node_value with 319 | String s -> E.Atom (sprintf "%S" s, atom) 320 | | Float f -> format_float f 321 | 322 | | Array a -> 323 | let l = map format a in 324 | E.List (("(", "", ")", tuple), l) 325 | 326 | | Float_array a -> 327 | let l = 328 | Array.to_list (Array.map format_float a) in 329 | E.List (("[|", "", "|]", list), l) 330 | 331 | | Tag (t, a) -> 332 | let l = map format a in 333 | E.Label ( 334 | (E.Atom (sprintf "tag%i" t, atom), label), 335 | E.List (("(", "", ")", tuple), l) 336 | ) 337 | 338 | | Object (id, a) -> 339 | let l = map format a in 340 | E.Label ( 341 | (E.Atom (sprintf "object%i" id, atom), label), 342 | E.List (("(", "", ")", tuple), l) 343 | ) 344 | 345 | | Closure a -> 346 | let l = map format a in 347 | E.Label ( 348 | (E.Atom ("closure", atom), label), 349 | E.List (("(", "", ")", tuple), l) 350 | ) 351 | 352 | | Lazy x -> 353 | let l = [ format x ] in 354 | E.Label ( 355 | (E.Atom ("lazy", atom), label), 356 | E.List (("(", "", ")", tuple), l) 357 | ) 358 | 359 | | Forward x -> 360 | let l = [ format x ] in 361 | E.Label ( 362 | (E.Atom ("forward", atom), label), 363 | E.List (("(", "", ")", tuple), l) 364 | ) 365 | 366 | | Opaque s -> 367 | E.Atom (sprintf "<%s>" s, atom) 368 | 369 | | List nodes -> 370 | let l = map format nodes in 371 | E.List (("[", "", "]", list), l) 372 | in 373 | if b.show_address then 374 | let n = 375 | match !(b.address) with 376 | None -> assert false 377 | | Some n -> n 378 | in 379 | E.Label ( 380 | (E.Atom (sprintf "#%i:" n, atom), label), 381 | node 382 | ) 383 | else 384 | node 385 | 386 | 387 | let to_eformat ?show_lazy ?lim x = format (dump_tree ?show_lazy ?lim x) 388 | 389 | let to_string ?show_lazy ?lim x = 390 | E.Pretty.to_string (to_eformat ?show_lazy ?lim x) 391 | let to_stdout ?show_lazy ?lim x = 392 | E.Pretty.to_stdout (to_eformat ?show_lazy ?lim x) 393 | let to_stderr ?show_lazy ?lim x = 394 | E.Pretty.to_stderr (to_eformat ?show_lazy ?lim x) 395 | let to_channel ?show_lazy ?lim oc x = 396 | E.Pretty.to_channel oc (to_eformat ?show_lazy ?lim x) 397 | let to_formatter ?show_lazy ?lim fmt x = 398 | E.Pretty.to_formatter fmt (to_eformat ?show_lazy ?lim x) 399 | let to_buffer ?show_lazy ?lim buf x = 400 | E.Pretty.to_buffer buf (to_eformat ?show_lazy ?lim x) 401 | 402 | let p = to_string 403 | -------------------------------------------------------------------------------- /dum.mli: -------------------------------------------------------------------------------- 1 | (**************************************************************************) 2 | (* *) 3 | (* Copyright (C) 2008 Wink Technologies Inc. (contact martin@wink.com) *) 4 | (* Copyright (C) 2008 Jean-Christophe Filliatre *) 5 | (* Copyright (C) 2005 Merjis Ltd., Richard W.M. Jones *) 6 | (* *) 7 | (* This software is free software; you can redistribute it and/or *) 8 | (* modify it under the terms of the GNU Library General Public *) 9 | (* License version 2.1, with the special exception on linking *) 10 | (* described in file LICENSE. *) 11 | (* *) 12 | (* This software is distributed in the hope that it will be useful, *) 13 | (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) 14 | (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *) 15 | (* *) 16 | (**************************************************************************) 17 | 18 | (** 19 | This module dumps arbitrary OCaml values into a human-readable format 20 | and always terminates. 21 | 22 | Dum was derived from both the Size module and 23 | from the Std.dump function of Extlib formerly known as Dumper. 24 | 25 | The output format is not formally defined and is meant only 26 | to be inspected by humans. The basic conventions (subject to change) 27 | are the following: 28 | - parentheses [(...)] delimit blocks such as tuples or anything equivalent. 29 | - square brackets [[...]] delimit a chain of blocks that is compatible 30 | with the structure of a finite list, i.e. [[ 1 2 3 ]] is the same as 31 | [(1 (2 (3 0)))]. 32 | - angle brackets [<...>] delimit something that is not shown in depth 33 | for some reason. 34 | - the number sign [#] followed by a number denotes a reference to a shared 35 | value, e.g. [#0: (1 (2 #0))] can be obtained with 36 | [let rec l = 1 :: 2 :: l in Dum.p l]. 37 | - the regular OCaml array notation [[|...|]] is reserved to unboxed 38 | arrays of floats. 39 | 40 | The rest is self-explanatory. 41 | *) 42 | 43 | 44 | val default_lim : int ref 45 | (** 46 | Default limit of the number of nodes to dump: 100. 47 | Strings account for one eighth of their length. 48 | *) 49 | 50 | val default_show_lazy : bool ref 51 | (** 52 | Whether to inspect lazy values. This is false by default. 53 | 54 | Warning: this relies on unofficially documented material of the 55 | standard distribution (file lazy.ml) and lazy values altogether 56 | are an experimental feature of OCaml. 57 | 58 | This functionality may disappear in the future. 59 | *) 60 | 61 | val to_eformat : ?show_lazy:bool -> ?lim:int -> 'a -> Easy_format.t 62 | (** 63 | Convert any OCaml value into an Easy_format.t tree. 64 | *) 65 | 66 | val to_string : ?show_lazy:bool -> ?lim:int -> 'a -> string 67 | val p : ?show_lazy:bool -> ?lim:int -> 'a -> string 68 | (** 69 | Dump to a string. [Dum.to_string] and [Dum.p] are equivalent. 70 | *) 71 | 72 | val to_stdout : ?show_lazy:bool -> ?lim:int -> 'a -> unit 73 | (** Dump to [stdout]. *) 74 | 75 | val to_stderr : ?show_lazy:bool -> ?lim:int -> 'a -> unit 76 | (** Dump to [stderr]. *) 77 | 78 | val to_channel : ?show_lazy:bool -> ?lim:int -> out_channel -> 'a -> unit 79 | (** Dump to the specified [out_channel] *) 80 | 81 | val to_formatter : 82 | ?show_lazy:bool -> ?lim:int -> Format.formatter -> 'a -> unit 83 | (** Dump to a formatter created by the Format module. *) 84 | 85 | val to_buffer : ?show_lazy:bool -> ?lim:int -> Buffer.t -> 'a -> unit 86 | (** Dump to a buffer. *) 87 | -------------------------------------------------------------------------------- /dum.opam: -------------------------------------------------------------------------------- 1 | # This file is generated by dune, edit dune-project instead 2 | opam-version: "2.0" 3 | synopsis: "Inspect the runtime representation of arbitrary OCaml values" 4 | description: """ 5 | Dum is a library for inspecting the runtime representation of 6 | arbitrary OCaml values. Shared or cyclic data are detected 7 | and labelled. This guarantees that printing would always 8 | terminate. This makes it possible to print values such as closures, 9 | objects or exceptions in depth and without risk.""" 10 | maintainer: ["martin@mjambon.com"] 11 | authors: ["Martin Jambon" "Jean-Christophe Filliatre" "Richard W.M. Jones"] 12 | license: "LGPL-2.1-or-later WITH OCaml-LGPL-linking-exception" 13 | homepage: "https://github.com/mjambon/dum" 14 | bug-reports: "https://github.com/mjambon/dum/issues" 15 | depends: [ 16 | "dune" {>= "2.0"} 17 | "easy-format" 18 | ] 19 | build: [ 20 | ["dune" "subst"] {pinned} 21 | [ 22 | "dune" 23 | "build" 24 | "-p" 25 | name 26 | "-j" 27 | jobs 28 | "@install" 29 | "@runtest" {with-test} 30 | "@doc" {with-doc} 31 | ] 32 | ] 33 | dev-repo: "git+https://github.com/mjambon/dum.git" 34 | -------------------------------------------------------------------------------- /dune: -------------------------------------------------------------------------------- 1 | (library 2 | (public_name dum) 3 | (modules dum) 4 | (libraries easy-format)) 5 | -------------------------------------------------------------------------------- /dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 2.0) 2 | (name dum) 3 | (generate_opam_files true) 4 | 5 | (maintainers "martin@mjambon.com") 6 | (authors 7 | "Martin Jambon" 8 | "Jean-Christophe Filliatre" 9 | "Richard W.M. Jones") 10 | (license "LGPL-2.1-or-later WITH OCaml-LGPL-linking-exception") 11 | (source (github mjambon/dum)) 12 | 13 | (package 14 | (name dum) 15 | (synopsis "Inspect the runtime representation of arbitrary OCaml values") 16 | (description "Dum is a library for inspecting the runtime representation of 17 | arbitrary OCaml values. Shared or cyclic data are detected 18 | and labelled. This guarantees that printing would always 19 | terminate. This makes it possible to print values such as closures, 20 | objects or exceptions in depth and without risk.") 21 | (depends 22 | easy-format)) 23 | --------------------------------------------------------------------------------