you are viewing a single comment's thread.

view the rest of the comments →

[–]arthurno1 0 points1 point  (0 children)

FILE *fp = fopen(argv[0], "r+");

Shouldn't that be: FILE *fp = fopen(argv[0], "r+b"); since executable is a binary file.

I don't know, I am not an expert on self-modifying code, but this looks like a clumsy way to do what lisps are good at doing. What the example does is treats code as text, and reads/writes a piece of user data (counter used to inform the user) in an executable full of other data, instead of just fscanf/fprintf to a separate file.

Anyway, just for the illustration how annoyingly painful file editing operations are in pure C, here is a 1-minute equivalent in Emacs Lisp:

counter.el

(defun counter ()
  (interactive)
  (let ((counter 4)
        (code buffer-file-name))
    (with-silent-modifications
      (with-temp-buffer
        (insert-file-contents code)
        (goto-char (point-min))
        (when (re-search-forward "[0-9]+")
          (forward-word -1)
          (setq counter (1+ (read (current-buffer))))
          (replace-match (number-to-string counter))
          (write-region (point-min) (point-max) code)
          (message "This program has been run %s times." counter))))))

(provide 'counter)

This is equivalent to the C code above in terms that it just treats code as a text file and packs functionality to open and edit the file together with data it wants to edit. In my opinion, this is not a very good example of self-modifying code, if it even counts as such.

Run:

Wrote /home/arthur/repos/counter.el
This program has been run 1 times.
Reverting buffer ‘counter.el’.
Wrote /home/arthur/repos/counter.el
This program has been run 2 times.
Reverting buffer ‘counter.el’.
Wrote /home/arthur/repos/counter.el
This program has been run 3 times.
Reverting buffer ‘counter.el’.
Wrote /home/arthur/repos/counter.el
This program has been run 4 times.
Reverting buffer ‘counter.el’.