;;; 5_7.ss ;;; Copyright 1984-2017 Cisco Systems, Inc. ;;; ;;; Licensed under the Apache License, Version 2.0 (the "License"); ;;; you may not use this file except in compliance with the License. ;;; You may obtain a copy of the License at ;;; ;;; http://www.apache.org/licenses/LICENSE-2.0 ;;; ;;; Unless required by applicable law or agreed to in writing, software ;;; distributed under the License is distributed on an "AS IS" BASIS, ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;;; See the License for the specific language governing permissions and ;;; limitations under the License. ;;; symbol functions (begin (define property-list (lambda (s) (unless (symbol? s) ($oops 'property-list "~s is not a symbol" s)) (list-copy ($symbol-property-list s)))) (define putprop (lambda (s p v) (if (symbol? s) (let pt ([pl ($symbol-property-list s)]) (cond [(null? pl) ($set-symbol-property-list! s (cons p (cons v ($symbol-property-list s))))] [(eq? (car pl) p) (set-car! (cdr pl) v)] [else (pt (cdr (cdr pl)))])) ($oops 'putprop "~s is not a symbol" s)))) (define remprop (lambda (s p) (if (symbol? s) (let pt ([pl ($symbol-property-list s)] [prev #f]) (cond [(null? pl) (void)] [(eq? (car pl) p) (if prev (set-cdr! prev (cdr (cdr pl))) ($set-symbol-property-list! s (cdr (cdr pl))))] [else (pt (cdr (cdr pl)) (cdr pl))])) ($oops 'remprop "~s is not a symbol" s)))) (define $sgetprop (lambda (s p d) (unless (symbol? s) ($oops '$sgetprop "~s is not a symbol" s)) (let gt ([pl ($system-property-list s)]) (if (null? pl) d (if (eq? (car pl) p) (car (cdr pl)) (gt (cdr (cdr pl)))))))) (define $sputprop (lambda (s p v) (unless (symbol? s) ($oops '$sputprop "~s is not a symbol" s)) (let ((plist ($system-property-list s))) (let pt ([pl plist]) (if (null? pl) ($set-system-property-list! s (cons p (cons v plist))) (if (eq? (car pl) p) (set-car! (cdr pl) v) (pt (cdr (cdr pl))))))))) (define $sremprop (lambda (s p) (unless (symbol? s) ($oops '$sremprop "~s is not a symbol" s)) (let rp ([pl ($system-property-list s)] [prev #f]) (unless (null? pl) (if (eq? (car pl) p) (if prev (set-cdr! prev (cdr (cdr pl))) ($set-system-property-list! s (cdr (cdr pl)))) (rp (cdr (cdr pl)) (cdr pl))))))) ) (eval-when (compile) (optimize-level 3)) (let ([prefix "g"] [count 0]) (define generate-unique-name ; a-z must come first in alphabet. separator must not be in alphabet. (let ([suffix 0]) (define unique-id (foreign-procedure "(cs)unique_id" () scheme-object)) (define (make-session-key) (define alphabet "abcdefghijklmnopqrstuvwxyz0123456789") (define separator #\-) (define b (string-length alphabet)) (define digit->char (lambda (n) (string-ref alphabet n))) (list->string (let loop ([n (unique-id)] [a (list separator)]) (if (< n b) ; ensure name starts with letter. assumes a-z first in alphabet. (if (< n 26) (cons (digit->char n) a) (cons* (string-ref alphabet 0) (digit->char n) a)) (loop (quotient n b) (cons (digit->char (remainder n b)) a)))))) (define (session-key) (or $session-key (let ([k (make-session-key)]) (set! $session-key k) (set! suffix -1) k))) (lambda () (define alphabet "0123456789") (define b (string-length alphabet)) (define digit->char (lambda (n) (string-ref alphabet n))) (let* ([k (session-key)] [n (string-length k)]) (set! suffix (fx+ suffix 1)) (let f ([i 0]) (if (fx= i n) (let g ([suffix suffix] [n (fx+ n 1)]) (if (< suffix b) (let ([s (make-string n)]) (string-set! s i (digit->char suffix)) s) (let ([s (g (quotient suffix b) (fx+ n 1))]) (string-set! s (fx+ i (fx- (string-length s) n)) (digit->char (remainder suffix b))) s))) (let ([s (f (fx+ i 1))]) (string-set! s i (string-ref k i)) s))))))) (define generate-pretty-name (lambda () (let ([count (let ([n count]) (set! count (+ n 1)) n)] [prefix prefix]) (if (and (string? prefix) (fixnum? count)) (let ([n1 (string-length prefix)]) (let l1 ([n (fx+ n1 1)] [d 10]) (if (fx> d count) (let ([s (make-string n)]) (let l2 ([i (fx- n1 1)]) (unless (fx< i 0) (string-set! s i (string-ref prefix i)) (l2 (fx- i 1)))) (let l3 ([i (fx- n 1)] [q count]) (unless (fx< i n1) (string-set! s i (string-ref "0123456789" (fxremainder q 10))) (l3 (fx- i 1) (fxquotient q 10)))) s) (l1 (fx+ n 1) (fx* d 10))))) (parameterize ([print-radix 10]) (format "~a~a" prefix count)))))) (define $strings->gensym (foreign-procedure "(cs)s_strings_to_gensym" (scheme-object scheme-object) scheme-object)) (set! $gensym->pretty-name (lambda (x) (with-tc-mutex (cond [($symbol-name x) => cdr] ; someone beat us to it [else (let ([name (generate-pretty-name)]) ($set-symbol-name! x (cons #f name)) name)])))) (set-who! gensym->unique-string (lambda (sym) (unless (symbol? sym) ($oops who "~s is not a gensym" sym)) (let ([name ($symbol-name sym)]) (or (and (pair? name) (car name)) ; get out quick if name already recorded (begin (unless (or (not name) (pair? name)) ($oops who "~s is not a gensym" sym)) (with-tc-mutex ; grab name again once safely inside the critical section (let ([name ($symbol-name sym)]) (if (not name) (let ([uname (generate-unique-name)]) ($set-symbol-name! sym (cons uname (generate-pretty-name))) ($intern-gensym sym) uname) (or (car name) (let ([uname (generate-unique-name)]) (set-car! name uname) ($intern-gensym sym) uname)))))))))) (set! gensym-prefix (case-lambda [() prefix] [(x) (set! prefix x)])) (set! gensym-count (case-lambda [() count] [(x) (unless (and (or (fixnum? x) (bignum? x)) (>= x 0)) ($oops 'gensym-count "~s is not a nonnegative integer" x)) (set! count x)])) (set-who! gensym (case-lambda [() (#3%gensym)] [(pretty-name) (unless (string? pretty-name) ($oops who "~s is not a string" pretty-name)) (#3%gensym pretty-name)] [(pretty-name unique-name) (unless (string? pretty-name) ($oops who "~s is not a string" pretty-name)) (unless (string? unique-name) ($oops who "~s is not a string" unique-name)) ($strings->gensym pretty-name unique-name)])))