(macro with-replacing-temp-file-io
(lambda (args)
`(let ((,(cadar args) (make-temp-filename-from ,(caar args))))
(prog1
(with-input-from "<" ,(caar args)
(with-output-to ">" ,(cadar args)
(progn ,@(cdr args))))
(close ,(caar args))
(close ,(cadar args))
(copy-mog ,(caar args) ,(cadar args))
(system-or-error "mv" ,(cadar args) ,(caar args))))))
;; line must be a string, but it may contain multiple lines separated
;; by "\n"
(defun insert-line-before (file-path line before-regex)
(with-existing-rooted-plain-file-a-rule (file-path fp)
("insert-line-before: in %s" file-path)
(let ((before-found false)
(lines-unfound (remove-if (lambda (x) (equal x ""))
(split "\n" line)))
(lines-found '()))
(with-input-from "<" fp
(dolines-until (lambda (l)
(when (match l before-regex)
(setq before-found true)))
(lambda (l)
(setq lines-unfound
(remove-if (lambda (lu) (equal lu l))
lines-unfound)))))
(close fp)
(cond
((and before-found (not (null lines-unfound)))
;; not all the requisite line(s) were found. but the before
;; regex was found. so we have to insert them.
(let ((before-line NR))
(with-replacing-temp-file-io (fp tp)
(dolines-until (lambda (l) (>= NR (- before-line 1)))
(lambda (l) (printf "%s\n" l)))
(printf "%s\n" line)
(dolines (lambda (l) (printf "%s\n" l))))))
(true (log-info "no change necessary"))))))