7
(defun next-newline (str pos len)
9
; Return the position of the next newline character in str starting with pos,
10
; if any; else return len.
14
((eql (char str pos) #\Newline)
16
(t (next-newline str (1+ pos) len))))
18
(defun break-string-into-lines-rec (str pos len acc)
20
; Break str into lines, discarding empty lines.
24
((eql (char str pos) #\Newline)
25
(break-string-into-lines-rec str (1+ pos) len acc))
26
(t (let ((new-pos (next-newline str pos len)))
27
(break-string-into-lines-rec str new-pos len
28
(cons (subseq str pos new-pos)
31
(defun find-whitespace-string (string-list)
32
(cond ((endp string-list)
34
((let* ((str (car string-list))
36
(or (member-char-stringp #\Space str (1- len))
37
(member-char-stringp #\Tab str (1- len))))
39
(t (find-whitespace-string (cdr string-list)))))
41
(defun break-string-into-lines (str msg ctx state)
42
(let* ((lines (break-string-into-lines-rec str 0 (length str) nil))
43
(bad-line (find-whitespace-string lines)))
44
(cond (bad-line (er soft ctx
45
"Found ~@0 line with whitespace:~%~x1~|"
50
(defun process-book-readme-fn (readme-filename state)
51
(declare (xargs :guard (stringp readme-filename)))
52
(let ((ctx 'process-book-readme))
55
(open-input-channel readme-filename :object state)
59
"Unable to open file ~x0 for input."
63
(read-object channel state)
65
(close-input-channel channel state)
66
(cond (eofp (er soft ctx
67
"No form could be read from input file ~x0."
69
((not (and (true-list-listp alist)
70
(alistp (strip-cdrs alist))))
72
"The form read from a book's Readme.lsp file should be ~
73
an list of true lists each with at least two elements, ~
75
alist (default-evisc-tuple state)))
76
(t (let* ((files-entry (assoc-eq :FILES alist))
77
(title-entry (assoc-eq :TITLE alist))
78
(author/s-entry (assoc-eq :AUTHOR/S alist))
79
(keywords-entry (assoc-eq :KEYWORDS alist))
80
(abstract-entry (assoc-eq :ABSTRACT alist))
81
(perm-entry (assoc-eq :PERMISSION alist))
82
(files (and (true-listp files-entry)
83
(eql (length files-entry) 2)
84
(stringp (cadr files-entry))
86
(title (and (true-listp title-entry)
87
(eql (length title-entry) 2)
88
(stringp (cadr title-entry))
90
(author/s (and (string-listp (cdr author/s-entry))
91
(cdr author/s-entry)))
92
(keywords (and (string-listp (cdr keywords-entry))
93
(cdr keywords-entry)))
94
(abstract (and (true-listp abstract-entry)
95
(eql (length abstract-entry) 2)
96
(stringp (cadr abstract-entry))
97
(cadr abstract-entry)))
98
(perm (and (true-listp perm-entry)
99
(eql (length perm-entry) 2)
100
(stringp (cadr perm-entry))
103
((not (and files title author/s keywords abstract perm))
105
"No valid field for ~x0 in Readme.lsp alist."
109
((not author/s) :AUTHOR/S)
110
((not keywords) :KEYWORDS)
111
((not abstract) :ABSTRACT)
114
(pprogn (fms "File ~s0 PASSES the check.~|"
115
(list (cons #\0 readme-filename))
116
(standard-co state) state nil)
117
(value :invisible))))))))))))))
119
(defmacro process-book-readme (&key dir)
120
(declare (xargs :guard (or (null dir)
122
`(process-book-readme-fn
127
(cond ((eql (char dir (1- (length dir)))
128
*directory-separator*)
130
(t (concatenate 'string dir
131
*directory-separator-string*))))
136
; Last updated: Fri Feb 24 11:36:55 2006