#!/usr/local/bin/gosh ;; -*- Scheme -*- ;; Convert a DOS text file to a Unix text file in place, preserving ;; timestamps. Or vice versa if invoked as unix2dos. 2001-09-30 ;; mac->unix and unix->mac added 2001-10-11. ;; Close output ports when done with them so scsh doesn't print obscure ;; messages on the screen. 2002-05-04 ;; Rewritten with gauche and non-regexps. Added mac->dos and ;; dos->mac. 2002-09-08 ;; Made λ-alias a syntax, not a define. 2002-09-13 (use file.util) (use gauche.auxsys) (define-syntax λ ;sue me (syntax-rules () ((_ args body1 body2 ...) (lambda args body1 body2 ...)))) (define nl (integer->char 10)) ;ascii (define cr (integer->char 13)) ;ascii (define (char-filter proc inport outport) (port-for-each (λ (c) (let ((to-output (proc c))) (if (char? to-output) (write-char to-output outport) (for-each (cut write-char <> outport) to-output)))) (cut read-char inport))) (define (peek-newline? port) (let ((c (peek-char port))) (and (char? c) (char=? c nl)))) (define (dos->unix inport outport) (char-filter (λ (c) (if (and (char=? c cr) (peek-newline? inport)) '() c)) inport outport)) (define (unix->dos inport outport) (char-filter (λ (c) (if (char=? c nl) (list cr nl) c)) inport outport)) (define (mac->unix inport outport) (char-filter (λ (c) (if (char=? cr c) nl c)) inport outport)) (define (unix->mac inport outport) (char-filter (λ (c) (if (char=? c nl) cr c)) inport outport)) (define (mac->dos inport outport) (char-filter (λ (c) (if (char=? c cr) (list cr nl) c)) inport outport)) (define (dos->mac inport outport) (char-filter (λ (c) (and (char=? c cr) (peek-newline? inport) (read-char inport)) ;discard newline c) inport outport)) (define converters (list (cons "dos2unix" dos->unix) (cons "unix2dos" unix->dos) (cons "mac2unix" mac->unix) (cons "unix2mac" unix->mac) (cons "mac2dos" mac->dos) (cons "dos2mac" dos->mac))) (define (duplicate-perms src-file dst-file) (sys-chmod dst-file (file-perm src-file))) (define (duplicate-owners src-file dst-file) (sys-chown dst-file (file-uid src-file) (file-gid src-file))) (define (duplicate-timestamp src-file dst-file) (sys-utime dst-file (file-atime src-file) (file-mtime src-file))) (define (convert-each-file files-list converter) (for-each (λ (infile) (call-with-input-file infile (λ (inport) (receive (outport outfile) (sys-mkstemp "__eolconv__") (format (current-error-port) "Converting ~a...~%" infile) (converter inport outport) (close-output-port outport) (with-error-handler (λ (err) (format (current-error-port) "~A (~A unchanged)~%" (slot-ref err 'message) infile) (sys-unlink outfile)) (λ () (duplicate-perms infile outfile) (duplicate-owners infile outfile) (duplicate-timestamp infile outfile) (move-file outfile infile :if-exists :supersede))))))) files-list)) (define (main args) (let* ((conv-name (sys-basename (car args))) (converter (assoc conv-name converters))) (if (not converter) (format (current-error-port) "No such converter ~a found\n" conv-name) (convert-each-file (cdr args) (cdr converter)))))