This file is meant to collect the various "here's how to do X" advice we like to send around in emails and then promptly forget. ----------------------- slicer for globals ---------------------- I (Scott) just implemented a simple extension to cilly.asm.exe (really, just a small modification to 'rmtmps') which lets you slice a given C file so that it only contains things which contribute to a given global's type (actually, you can name as many root globals as you want). I think this will be useful for tracking down merger problems in big programs. To use this, just add #pragma cilnoremove("my_symbol") to the file in question, and then run $cil/obj/x86_LINUX/cilly.asm.exe \ --sliceGlobal --out file.cil.c file.i (where file.i is preprocessed file.c). This will slice file.i so it only contains things which are needed for 'my_symbol' to compile successfully, and write the output to file.cil.c. The symbol in question can be a function, enum tag, struct tag, typedef name, or global variable. Add more #pragma cilnoremove's to add more things to the root set. Update: It doesn't work very well for types. Instead, if you want to slice on a type, add at the end of the file #pragma cilnoremove("myGlobalVar") struct typeOfInterest myGlobalVar; then the slicer will retain 'typeOfInterest'. ------------------- trusted expressions ------------------ > Here's another idea: can we mark certain expressions as "trusted"? Yes. Enclose the expression (say, "x=a;") as follows: { __NOBOXBLOCK x=a; } This causes markptr to ignore the expression (so no edges/flags are generated and thus the solver won't become upset by anything that happens there) and boxing to ... do the best it can, with everything in there lean. --------------------- invoking the Ocaml debugger ---------------------- I have just written some Elisp code that allows you to enter the debugger very easily: First the usage: Say you want to debug the ccured invocation for the command make test/array1 INFERBOX=infer You start emacs, go to directory cil/test (in which the above command makes sense) and then do M-x my-camldebug This will ask you how to run the debugger. You write the following make test/array1 INFERBOX=infer OCAMLDEBUG=1 This will call ocamldebug when appropriately with the right arguments and with proper setting of source directories. After that it feels like gdb (see the manual though). The time travel (i.e. backwards stepping) is great. Now the Lisp magic. Put this in your .emacs: (defvar ocamldebug-history nil) (defun my-camldebug (command-line) "Run camldebug on program FILE in buffer *camldebug-FILE*. The directory containing FILE becomes the initial working directory and source-file directory for camldebug. If you wish to change this, use the camldebug commands `cd DIR' and `directory'." (interactive (list (read-from-minibuffer "Run ocamldebug (like this): " (if (consp ocamldebug-history) (car ocamldebug-history) "ocamldebug") nil nil '(ocamldebug-history . 1)))) ; call something from camldebug.el to make sure it is loaded (camldebug-numeric-arg 1) (pop-to-buffer (concat "*camldebug*")) (setq words (gud-chop-words command-line)) (message "Current directory is %s" default-directory) (apply 'make-comint (cons "camldebug" (cons (car words) (cons nil (cdr words))))) (set-process-filter (get-buffer-process (current-buffer)) 'camldebug-filter) (set-process-sentinel (get-buffer-process (current-buffer)) 'camldebug-sentinel) (camldebug-mode) (camldebug-set-buffer)) --------------------- mapping backwards through #line ------------------- by Scott 6/18/02 02:41 The typical CCured build involves many source translation steps. Usually, we use the --commPrintLn flag to emit #line directives, but commented-out, so we see the final translation product in gdb. However, it's often useful to see the original source also, or the intermediate stages, when debugging. I've written an elisp macro to look backwards in the current file for the #line directives which tell the file/line from which the current one came, and then open that file and position the cursor at the right line. It's called "map-hashline-back", and is among those defined below. ; search backwards in a file for the nearest #line directive that ; mentions the filename (defun find-enclosing-hashline () "Search backwards for #line directive with filename" (interactive) (re-search-backward "^/?/?#\\(line\\)? [0-9]+ ") ) (defun find-enclosing-hashline-any () "Search backwards for any #line directive" (interactive) (re-search-backward "^/?/?#\\(line\\)? [0-9]+") ) (defun match-string (n) "Return string matched by most recent search; 'n' is parethesis grouping number, where 0 means entire search string." (buffer-substring (match-beginning n) (match-end n)) ) (defun current-hashline-line () "Extract and return line number of #line directive at cursor." (re-search-forward "#\\(line\\)? \\([0-9]+\\)") (string-to-number (match-string 2)) ) (defun current-hashline-file () "Extract and return file name of #line directive at cursor." (re-search-forward "#\\(line\\)? [0-9]+ \"\\(.*\\)\"") (match-string 2) ) (defun map-hashline-back () "Given a #line directive at cursor, open file it refers to, at the line position given." (interactive) (let ((curPosn (point))) ; save current cursor position (find-enclosing-hashline-any) (let ((lineNumber (current-hashline-line))) (goto-char curPosn) ; restore original buffer's position (find-enclosing-hashline) (let ((fileName (current-hashline-file))) (goto-char curPosn) ; restore original buffer's position (if (file-exists-p fileName) (find-file fileName) ; open the named file ; try one level up, which is needed for our current ; C++/CCured build process where we move files around ; after translation (if (file-exists-p (concat "../" fileName)) (find-file (concat "../" fileName)) (error "File does not exist: %s" fileName) )) (goto-line lineNumber) ; go to right line ; print where we went (princ fileName) (princ ":") (princ lineNumber) ) ) ) ) ; this doesn't work as advertised, but it's close enough (defun run-previous-M-x-command () "Run the last command interactively entered with M-x." (interactive) (let ((prevCmd (car command-history))) (princ prevCmd) (eval prevCmd) ) ) ; after doing M-x map-hashline-back once, now ctl+alt+p will ; go back through successive layers (global-set-key [(control meta p)] 'run-previous-M-x-command ) --------------------- navigating .infer files ------------------ by Scott 6/18/02 02:42 (George had a different way of doing this; how does his work?) When I use .infer files, it's always to do one thing: given a WILD node, trace backwards to the cast which caused it. The macro goto-prev-wild will do one step of the mapping. Then, use ctl+alt+p (above) to go more steps. (defun get-wild-source () "Search forward to the next WILD/() string, and extract and return that node id." (re-search-forward "WILD/[A-Za-z_]+(\\([0-9]+\\))") (string-to-number (match-string 1)) ) (defun goto-infer-node (n) "Find the information section for node 'n'." (goto-char 0) (re-search-forward (format "^%d :" n)) ) (defun goto-prev-wild () "Go to the node which caused this one to be WILD." (interactive) (let ((source (get-wild-source))) (princ (format "Node %d" source)) (goto-infer-node source) ) )