#! /bin/sh
#|
exec racket -tm "$0" ${1+"$@"}
|#

#lang racket

;; ---------------------------------------------------------------------------------------------------
;; compare two xml streams 

(provide
 ;; String String -> Boolean 
 ;; effect: spit out distinct XML elements 
 main)

;; if you want to see these messages in error elements
; (define verbose (make-parameter #f))

;; ---------------------------------------------------------------------------------------------------
;; Implementation 

(require "Lib/xml.rkt" xml)

(define (main file1 file2)
  (parameterize ((verbose #false)) ;; set to #t to see error messages 
    (define ip1 (open-file-or-port file1))
    (define ip2 (open-file-or-port file2))
    (if (diff ip1 ip2) 'success '**failure**)))

;; String -> InputPort 
(define (open-file-or-port file1)
  (cond
    [(string=? "-" file1) (current-input-port)]
    [(file-exists? file1) (open-input-file file1)]
    [else (error 'diff-xml "file not found: ~e" file1)]))

;; InputPort InputPort -> Boolean 
(define (diff ip1 ip2)
  (define (diff1 t ip next)
    (let diff1 ([next next])
      (unless (eof-object? next)
        (printf "additional lines in ~a:\n" t)
        (pretty-print next)
        (diff1 (read-xml-from-stdin ip))))
    #f)
  (let diff ([result #t])
    (define in1 (read-xml-from-stdin ip1))
    (define in2 (read-xml-from-stdin ip2))
    (cond
      [(and (eof-object? in1) (eof-object? in2)) result]
      [(eof-object? in1) (diff1 2 ip2 in2)]
      [(eof-object? in2) (diff1 1 ip1 in1)]
      [else (diff (xml-element-diff in1 in2))])))

;; InputPort -> Xexpr 
(define (read-xml-from-stdin ip)
  (with-handlers ((exn:xml? (λ (x) eof)))
    (xml->xexpr ((eliminate-whitespace '() (λ (x) #t)) (read-xml/element ip)))))
