--- /dev/null
+(define-module (lang elisp primitives match)
+ #:use-module (lang elisp internals fset)
+ #:use-module (ice-9 regex)
+ #:use-module (ice-9 optargs))
+
+(define last-match #f)
+
+(fset 'string-match
+ (lambda (regexp string . start)
+
+ (define emacs-string-match
+
+ (if (defined? 'make-emacs-regexp)
+
+ ;; This is what we would do if we had an
+ ;; Emacs-compatible regexp primitive, here called
+ ;; `make-emacs-regexp'.
+ (lambda (pattern str . args)
+ (let ((rx (make-emacs-regexp pattern))
+ (start (if (pair? args) (car args) 0)))
+ (regexp-exec rx str start)))
+
+ ;; But we don't have Emacs-compatible regexps, and I
+ ;; don't think it's worthwhile at this stage to write
+ ;; generic regexp conversion code. So work around the
+ ;; discrepancies between Guile/libc and Emacs regexps by
+ ;; substituting the regexps that actually occur in the
+ ;; elisp code that we want to read.
+ (lambda (pattern str . args)
+ (let loop ((discrepancies '(("^[0-9]+\\.\\([0-9]+\\)" .
+ "^[0-9]+\\.([0-9]+)"))))
+ (or (null? discrepancies)
+ (if (string=? pattern (caar discrepancies))
+ (set! pattern (cdar discrepancies))
+ (loop (cdr discrepancies)))))
+ (apply string-match pattern str args))))
+
+ (let ((match (apply emacs-string-match regexp string start)))
+ (set! last-match
+ (if match
+ (apply append!
+ (map (lambda (n)
+ (list (match:start match n)
+ (match:end match n)))
+ (iota (match:count match))))
+ #f)))
+
+ (if last-match (car last-match) %nil)))
+
+(fset 'match-beginning
+ (lambda (subexp)
+ (list-ref last-match (* 2 subexp))))
+
+(fset 'match-end
+ (lambda (subexp)
+ (list-ref last-match (+ (* 2 subexp) 1))))
+
+(fset 'substring substring)
+
+(fset 'match-data
+ (lambda* (#:optional integers reuse)
+ last-match))
+
+(fset 'set-match-data
+ (lambda (list)
+ (set! last-match list)))
+
+(fset 'store-match-data 'set-match-data)