This file is indexed.

/usr/lib/s9fes/regex.scm is in scheme9 2010.11.13-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
; Scheme 9 from Empty Space, Function Library
; By Nils M Holm, 2009,2010
; See the LICENSE file of the S9fES package for terms of use
;
; (re-comp string)                         ==>  list
; (re-match list string)                   ==>  list | #f
; (re-match list string 'symbol ...)       ==>  list | #f
; (re-subst list string1 string2)          ==>  list | #f
; (re-subst list string1 string2 'symbol)  ==>  list | #f
;
; (load-from-library "regex.scm")
;
; Compile, match, and substitute regular expressions.
;
; RE-COMP compiles a regular expression (RE) and returns it.
; Compiled REs (CREs) are represented by lists.
;
; RE-MATCH matches a compiled RE against a string. When (part of) the
; string matches the CRE, it returns a list of the form
;
;       ((first limit) ...)
;
; where FIRST is the index of the first character matching the RE and
; LIMIT is the first character *after* the match (so the match can be
; extracted with SUBSTRING). When no submatches are used, just a list
; of the form ((first limit)) will be returned. When submatches using
; \( and \) are contained in the regular expression, the subsequent pairs
; will contain the ranges matched by the sub-expressions (in order of
; occurrence of sub-expressions in the RE). See examples.
;
; When the CRE does not match the string, RE-MATCH returns #F.
;
; A special case occurs when a given pattern may match a string of zero
; length. In this case, RE-MATCH returns () when no better match could
; be found.
;
; When 'LAZY is passed as an additional argument to RE-MATCH, it matches
; repetitions "lazily," e.g.: "A+" will match "A" (rather than "AAA")
; in "AAAB".
;
; When 'ALL is passed as an additional argument to RE-MATCH, it will
; generate a list of *all* matches found in the given string, i.e. a
; list of the form:
;
;       (((first limit) ...) ...)
;
; The following RE patterns are evaluated:
; .          match any character
; [char...]  match character class (may contain ranges of the form c1-c2)
; ^          match beginning of line
; $          match end of line
; *          match zero or more instances of the preceding pattern
; +          match one or more instances of the preceding pattern
; ?          match the preceding pattern optionally
; \          match the following character literally (exception below!)
; \(         mark the beginning of a submatch
; \)         mark the end of a submatch
;
; RE-SUBST attempts to match the CRE LIST against STRING1. When it
; succeeds, it returns a fresh copy of STRING1 with the match replaced
; by STRING2. When the 'ALL option is used (see RE-MATCH), all occurrences
; of the match will be replaced. When the CRE contains submatches, they can
; be referred to in STRING2 by using a backslash and the position of the
; submatch, i.e.: \1, \2, ... The notation \0 denotes the entire match. To
; include a literal backslash in the replacement string, use \\. (Of course,
; Scheme strings use backslashes for escaping, so you will have to use \\1
; in the place of \1 and \\\\ in the place of \\. Yes, this is awkward.)
; When SUBST fails to match the CRE, it returns #F.
;
; Example:   (re-match (re-comp "^a[1-9]*z$") "a1289z")     ==>  ((0 6))
;            (re-match (re-comp "a[1-9]+z") "___a123z___")  ==>  ((3 8))
;            (re-match (re-comp "a[^1-9]+z") "a123z")       ==>  #f
;            (re-match (re-comp "[1-9]*") "__1__")          ==>  ((2 3))
;            (re-match (re-comp "[1-9]*") "_____")          ==>  ()
;
;            (re-match (re-comp "f\\(.\\)\\(.\\)bar")
;                      "foobar")                      ==>  ((0 6) (1 2) (2 3))
;
;            (re-match (re-comp "a\\(.\\)a") "aba_aca_ada" 'all)
;                                                     ==> (((0 3) (1 2))
;                                                          ((4 7) (5 6))
;                                                          ((8 11) (9 10)))
;
;            (re-subst (re-comp "\\([0-9]+\\)\\.\\([0-9]+\\)\\.")
;                      "_01.1._31.12._"
;                      "\\2/\\1"
;                      'all)                          ==>  "_1/01_12/31_"

(load-from-library "and-letstar.scm")

(define (re-comp re)

  (define LP   #\()
  (define RP   #\))

  (define (make-range c0 cn cls)
      (if (> c0 cn)
          cls
          (make-range (+ 1 c0)
                      cn
                      (cons (integer->char c0) cls))))

  (define (compile-class in out cls first)
    (cond ((null? in)
            #f)
          ((char=? #\] (car in))
            (list (cdr in) (cons (reverse! cls) out)))
          ((and first (char=? #\^ (car in)))
            (compile-class (cdr in) out (list #\]) #f))
          ((and (not first)
                (not (null? (cdr cls)))
                (char=? #\- (car in))
                (pair? (cdr in))
                (not (char=? #\] (cadr in))))
            (let ((c0 (char->integer (car cls)))
                  (cn (char->integer (cadr in))))
              (if (< c0 cn)
                  (compile-class (cddr in)
                                 out
                                 (make-range c0 cn (cdr cls)) #f)
                  (compile-class (cdr in)
                                 out
                                 (cons #\- cls) #f))))
          (else
            (compile-class (cdr in)
                           out
                           (cons (car in) cls) #f))))

  (let compile ((in-sub #f)
                (in     (string->list re))
                (out    '()))
    (cond
      ((not in)
        #f)
      ((null? in)
        (if in-sub
            #f
            (reverse! out)))
      (else
        (case (car in)
              ((#\\)
                (if (pair? (cdr in))
                    (if (memv (cadr in) '(#\( #\)))
                        (if (or (and      in-sub  (char=? LP (cadr in)))
                                (and (not in-sub) (char=? RP (cadr in))))
                            #f
                            (compile (char=? (cadr in) LP)
                                     (cddr in)
                                     (cons (list (cadr in)) out)))
                        (compile in-sub
                                 (cddr in)
                                 (cons (cadr in) out)))
                    #f))
              ((#\^ #\$ #\.)
                (compile in-sub
                         (cdr in)
                         (cons (list (car in)) out)))
              ((#\* #\?)
                (compile in-sub
                         (cdr in)
                         (if (null? out)
                             (cons (car in) out)
                             (cons (list (car in) (car out))
                                   (cdr out)))))
              ((#\+)
                (compile in-sub
                         (cdr in)
                         (if (null? out)
                             (cons (car in) out)
                             (cons (list #\* (car out)) out))))
              ((#\[)
                (let ((class (compile-class (cdr in) out (list #\[) #t)))
                  (if class
                      (apply compile in-sub class)
                      #f)))
              (else
                (compile in-sub
                         (cdr in)
                         (cons (car in) out))))))))

(define (re-match cre s . opts)

  (define lazy        #f)
  (define all-matches #f)
  (define LP          #\()
  (define RP          #\))

  (define (match-char p c)
    (cond ((char? p)
            (char=? p c))
          ((char=? #\. (car p)))
          ((char=? #\[ (car p))
            (memv c (cdr p)))
          ((char=? #\] (car p))
            (not (memv c (cdr p))))
          (else
            #f)))

  (define (extend-match m n)
    (if (null? m)
        (list (list n 0))
        (cons (cons (+ 1 (caar m)) (cdar m)) (cdr m))))

  (define (make-choices cre s m)
    (if (or (null? s)
            (not (match-char (cadar cre) (car s))))
        (list (list s m))
        (cons (list s m)
              (make-choices cre (cdr s) (extend-match m 1)))))

  (define (begin-submatch m)
    (if (null? m)
        `((0 0) (0 0))
        `((,(caar m) ,(caar m)) ,(car m) ,@(cdr m))))

  (define (end-submatch m)
    (let ((sub  (car m))
          (main (cadr m)))
      `((,(car sub) ,(cadr main)) ,sub ,@(cddr m))))

  (define (match-cre cre s pos m)
    (cond
      ((null? cre)
        (map reverse! m))
      ((null? s)
        (cond ((equal? cre '((#\$)))
                (match-cre '() '() pos m))
              ((equal? cre `((,RP)))
                (match-cre '() '() pos (end-submatch m)))
              ((and (pair? (car cre))
                    (char=? #\* (caar cre))
                    (null? (cdr cre)))
                '())
              (else
                #f)))
      ((pair? (car cre))
        (cond ((char=? LP (caar cre))
                (match-cre (cdr cre)
                           s
                           pos
                           (begin-submatch m)))
              ((char=? RP (caar cre))
                (match-cre (cdr cre)
                           s
                           pos
                           (end-submatch m)))
              ((char=? #\* (caar cre))
                (match-star cre s pos m))
              ((char=? #\? (caar cre))
                (if (match-char (cadar cre) (car s))
                    (match-cre (cdr cre)
                               (cdr s)
                               (+ 1 pos)
                               (extend-match m 1))
                    (match-cre (cdr cre) s pos m)))
              ((match-char (car cre) (car s))
                (match-cre (cdr cre)
                           (cdr s)
                           (+ 1 pos)
                           (extend-match m 1)))
              (else
                #f)))
      ((char=? (car cre) (car s))
        (match-cre (cdr cre)
                   (cdr s)
                   (+ 1 pos)
                   (extend-match m 1)))
      (else
        #f)))

  (define (match-star cre s pos m)
    (let try-choices ((c* (if lazy
                              (make-choices cre s m)
                              (reverse (make-choices cre s m)))))
      (and (not (null? c*))
           (let ((r (match-cre (cdr cre) (caar c*) pos (cadar c*))))
             (or r
                 (try-choices (cdr c*)))))))

  (define (adjust res pos)
    (and res
         (let ((res (map (lambda (range)
                           (map (lambda (x)
                                  (+ x pos))
                                range))
                         res)))
           `(,(car res) ,@(reverse! (cdr res))))))

  (define (try-matches cre s pos)
    (cond ((null? s)
            (match-cre cre s pos '()))
          (else
            (let ((r (match-cre cre s pos '())))
              (if (or (not r)
                      (null? r)
                      (and (pair? r)
                           (null? (car r))))
                  (try-matches cre (cdr s) (+ 1 pos))
                  (adjust r pos))))))

  (define (collect-matches cre s pos)
    (let loop ((r  (try-matches cre s pos))
               (m* '()))
      (if (or (not r)
              (null? r))
          (reverse! m*)
          (let ((k (cadar r)))
            (loop (try-matches cre (list-tail s k) (+ k pos))
                  (cons r m*))))))

  (if (memq 'lazy opts)
      (set! lazy #t))

  (if (memq 'all opts)
      (set! all-matches #t))

  (cond ((equal? cre '((#\^)))
          (if all-matches
              `(((0 0)))
              `((0 0))))
        ((equal? cre '((#\$)))
          (let ((k (string-length s)))
            (if all-matches
                `(((,k ,k)))
                `((,k ,k)))))
        ((and (pair? cre)
              (equal? '(#\^) (car cre)))
          (let ((m (adjust (match-cre (cdr cre) (string->list s) 0 '()) 0)))
            (if all-matches
                (list m)
                m)))
        (all-matches
          (collect-matches cre (string->list s) 0))
        (else
          (try-matches cre (string->list s) 0))))

(define (replacement-string new m*)
  (letrec
    ((append-match
       (lambda (m* i out)
         (let loop ((in  (string->list (list-ref m* i)))
                    (out out))
           (if (null? in)
               out
               (loop (cdr in) (cons (car in) out)))))))
    (let ((k (string-length new))
          (n (length m*)))
      (let loop ((i   0)
                 (out '()))
        (cond ((>= i k)
                (list->string (reverse! out)))
              ((char=? #\\ (string-ref new i))
                (cond ((and-let* ((_ (< i (- k 1)))
                                  (c (string-ref new (+ 1 i)))
                                  (_ (char<=? #\0 c #\9))
                                  (j (- (char->integer c)
                                        (char->integer #\0)))
                                  (_ (<= 0 j n)))
                         j)
                         => (lambda (j)
                              (loop (+ 2 i) (append-match m* j out))))
                       ((< i (- k 1))
                         (loop (+ 2 i) (cons (string-ref new (+ 1 i)) out)))
                       (else
                         (loop (+ 1 i) out))))
                (else
                  (loop (+ 1 i) (cons (string-ref new i) out))))))))

(define re-subst
  (let ((replacement-string replacement-string))
    (lambda (cre old new . opts)
      (and-let* ((pos** (apply re-match cre old opts))
                 (_     (not (null? pos**)))
                 (pos** (if (memq 'all opts)
                            pos**
                            (list pos**)))
                 (m**   (map (lambda (pos*)
                               (map (lambda (pos)
                                      (substring old (car pos) (cadr pos)))
                                    pos*))
                             pos**)))
        (let ((repl* (map (lambda (m*)
                            (replacement-string new m*))
                          m**)))
          (let loop ((pos*  (append '((0 0))
                                    (map car pos**)
                                    (list (list (string-length old)
                                                (string-length old)))))
                     (repl* repl*)
                     (out   '()))
            (cond ((null? (cdr pos*))
                    (apply string-append (reverse! out)))
                  (else
                    (let ((s (substring old (cadar pos*) (caadr pos*)))
                          (r (if (null? repl*) "" (car repl*))))
                      (loop (cdr pos*)
                            (if (null? repl*) '() (cdr repl*))
                            (cons r (cons s out))))))))))))