Automake/Libtool warning fix/suppression
[sxemacs] / lisp / syntax.el
1 ;; syntax.el --- Syntax-table hacking stuff, moved from syntax.c
2
3 ;; Copyright (C) 1993, 1997 Free Software Foundation, Inc.
4 ;; Copyright (C) 1995 Sun Microsystems.
5
6 ;; This file is part of SXEmacs.
7
8 ;; SXEmacs is free software: you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation, either version 3 of the License, or
11 ;; (at your option) any later version.
12
13 ;; SXEmacs is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;; GNU General Public License for more details.
17
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
21 ;;; Synched up with: FSF 19.28.
22
23 ;;; Commentary:
24
25 ;; This file is dumped with SXEmacs.
26
27 ;; Note: FSF does not have a file syntax.el.  This stuff is
28 ;; in syntax.c.  See comments there about not merging past 19.28.
29
30 ;; Significantly hacked upon by Ben Wing.
31
32 ;;; Code:
33
34 (defun make-syntax-table (&optional oldtable)
35   "Return a new syntax table.
36 It inherits all characters from the standard syntax table."
37   (make-char-table 'syntax))
38
39 (defun simple-set-syntax-entry (char spec table)
40   (put-char-table char spec table))
41
42 (defun char-syntax-from-code (code)
43   "Extract the syntax designator from the internal syntax code CODE.
44 CODE is the value actually contained in the syntax table."
45   (if (consp code)
46       (setq code (car code)))
47   (aref (syntax-designator-chars) (logand code 127)))
48
49 (defun set-char-syntax-in-code (code desig)
50   "Return a new internal syntax code whose syntax designator is DESIG.
51 Other characteristics are the same as in CODE."
52   (let ((newcode (if (consp code) (car code) code)))
53     (setq newcode (logior (string-match
54                            (regexp-quote (char-to-string desig))
55                            (syntax-designator-chars))
56                           (logand newcode (lognot 127))))
57     (if (consp code) (cons newcode (cdr code))
58       newcode)))
59
60 (defun syntax-code-to-string (code)
61   "Return a string equivalent to internal syntax code CODE.
62 The string can be passed to `modify-syntax-entry'.
63 If CODE is invalid, return nil."
64   (let ((match (and (consp code) (cdr code)))
65         (codes (syntax-designator-chars)))
66     (if (consp code)
67         (setq code (car code)))
68     (if (or (not (integerp code))
69             (> (logand code 127) (length codes)))
70         nil
71       (with-output-to-string
72        (let* ((spec (elt codes (logand code 127)))
73               (b3 (lsh code -16))
74               (start1  (/= 0 (logand b3 128))) ;logtest!
75               (start1b (/= 0 (logand b3  64)))
76               (start2  (/= 0 (logand b3  32)))
77               (start2b (/= 0 (logand b3  16)))
78               (end1    (/= 0 (logand b3   8)))
79               (end1b   (/= 0 (logand b3   4)))
80               (end2    (/= 0 (logand b3   2)))
81               (end2b   (/= 0 (logand b3   1)))
82               (prefix  (/= 0 (logand code 128)))
83               (single-char-p (or (= spec ?<) (= spec ?>)))
84               )
85          (write-char spec)
86          (write-char (if match match 32))
87 ;;;     (if start1 (if single-char-p (write-char ?a) (write-char ?1)))
88          (if start1 (if single-char-p (write-char ? ) (write-char ?1)))
89          (if start2 (write-char ?2))
90 ;;;     (if end1 (if single-char-p (write-char ?a) (write-char ?3)))
91          (if end1 (if single-char-p (write-char ? ) (write-char ?3)))
92          (if end2 (write-char ?4))
93          (if start1b (if single-char-p (write-char ?b) (write-char ?5)))
94          (if start2b (write-char ?6))
95          (if end1b (if single-char-p (write-char ?b) (write-char ?7)))
96          (if end2b (write-char ?8))
97          (if prefix (write-char ?p)))))))
98
99 (defun syntax-string-to-code (string)
100   "Return the internal syntax code equivalent to STRING.
101 STRING should be something acceptable as the second argument to
102 `modify-syntax-entry'.
103 If STRING is invalid, signal an error."
104   (let* ((bflag nil)
105          (b3 0)
106          (ch0 (aref string 0))
107          (len (length string))
108          (code (string-match (regexp-quote (char-to-string ch0))
109                              (syntax-designator-chars)))
110          (i 2)
111          ch)
112     (or code
113         (error "Invalid syntax designator: %S" string))
114     (while (< i len)
115       (setq ch (aref string i))
116       (incf i)
117       (case ch
118         (?1 (setq b3 (logior b3 128)))
119         (?2 (setq b3 (logior b3  32)))
120         (?3 (setq b3 (logior b3   8)))
121         (?4 (setq b3 (logior b3   2)))
122         (?5 (setq b3 (logior b3  64)))
123         (?6 (setq b3 (logior b3  16)))
124         (?7 (setq b3 (logior b3   4)))
125         (?8 (setq b3 (logior b3   1)))
126         (?a (case ch0
127               (?< (setq b3 (logior b3 128)))
128               (?> (setq b3 (logior b3   8)))))
129         (?b (case ch0
130               (?< (setq b3 (logior b3  64) bflag t))
131               (?> (setq b3 (logior b3   4) bflag t))))
132         (?p (setq code (logior code (lsh 1 7))))
133         (?\  nil) ;; ignore for compatibility
134         (otherwise
135          (error "Invalid syntax description flag: %S" string))))
136     ;; default single char style if `b' has not been seen
137     (if (not bflag)
138         (case ch0
139           (?< (setq b3 (logior b3 128)))
140           (?> (setq b3 (logior b3   8)))))
141     (setq code (logior code (lsh b3 16)))
142     (if (and (> len 1)
143              ;; tough luck if you want to make space a paren!
144              (/= (aref string 1) ?\  ))
145         (setq code (cons code (aref string 1))))
146     code))
147
148 (defun modify-syntax-entry (char-range spec &optional syntax-table)
149   "Set syntax for the characters CHAR-RANGE according to string SPEC.
150 CHAR-RANGE is a single character or a range of characters,
151  as per `put-char-table'.
152 The syntax is changed only for SYNTAX-TABLE, which defaults to
153  the current buffer's syntax table.
154 The first character of SPEC should be one of the following:
155   Space    whitespace syntax.    w   word constituent.
156   _        symbol constituent.   .   punctuation.
157   \(        open-parenthesis.     \)   close-parenthesis.
158   \"        string quote.         \\   character-quote.
159   $        paired delimiter.     '   expression quote or prefix operator.
160   <        comment starter.      >   comment ender.
161   /        character-quote.      @   inherit from `standard-syntax-table'.
162
163 Only single-character comment start and end sequences are represented thus.
164 Two-character sequences are represented as described below.
165 The second character of SPEC is the matching parenthesis,
166  used only if the first character is `(' or `)'.
167 Any additional characters are flags.
168 Defined flags are the characters 1, 2, 3, 4, 5, 6, 7, 8, p, a, and b.
169  1 means C is the first of a two-char comment start sequence of style a.
170  2 means C is the second character of such a sequence.
171  3 means C is the first of a two-char comment end sequence of style a.
172  4 means C is the second character of such a sequence.
173  5 means C is the first of a two-char comment start sequence of style b.
174  6 means C is the second character of such a sequence.
175  7 means C is the first of a two-char comment end sequence of style b.
176  8 means C is the second character of such a sequence.
177  p means C is a prefix character for `backward-prefix-chars';
178    such characters are treated as whitespace when they occur
179    between expressions.
180  a means C is comment starter or comment ender for comment style a (default)
181  b means C is comment starter or comment ender for comment style b."
182   (interactive
183    ;; I really don't know why this is interactive
184    ;; help-form should at least be made useful while reading the second arg
185    "cSet syntax for character: \nsSet syntax for %c to: ")
186   (simple-set-syntax-entry
187    char-range
188    (syntax-string-to-code spec)
189    (cond ((syntax-table-p syntax-table)
190           syntax-table)
191          ((null syntax-table)
192           (syntax-table))
193          (t
194           (wrong-type-argument 'syntax-table-p syntax-table))))
195   nil)
196
197 (defun map-syntax-table (__function __syntax_table &optional __range)
198   "Map FUNCTION over entries in SYNTAX-TABLE, collapsing inheritance.
199 This is similar to `map-char-table', but works only on syntax tables, and
200  collapses any entries that call for inheritance by invisibly substituting
201  the inherited values from the standard syntax table."
202   (check-argument-type 'syntax-table-p __syntax_table)
203   (map-char-table #'(lambda (__key __value)
204                       (if (eq ?@ (char-syntax-from-code __value))
205                           (map-char-table #'(lambda (__key __value)
206                                               (funcall __function
207                                                        __key __value))
208                                           (standard-syntax-table)
209                                           __key)
210                         (funcall __function __key __value)))
211                   __syntax_table __range))
212
213 ;(defun test-xm ()
214 ;  (let ((o (copy-syntax-table))
215 ;        (n (copy-syntax-table))
216 ;        (codes (syntax-designator-chars))
217 ;        (flags "12345678abp"))
218 ;    (while t
219 ;      (let ((spec (concat (char-to-string (elt codes
220 ;                                               (random (length codes))))))
221 ;                          (if (= (random 4) 0)
222 ;                              "b"
223 ;                              " ")
224 ;                          (let* ((n (random 4))
225 ;                                 (s (make-string n 0)))
226 ;                            (while (> n 0)
227 ;                              (setq n (1- n))
228 ;                              (aset s n (aref flags (random (length flags)))))
229 ;                            s))))
230 ;        (message "%S..." spec)
231 ;        (modify-syntax-entry ?a spec o)
232 ;        (xmodify-syntax-entry ?a spec n)
233 ;        (or (= (aref o ?a) (aref n ?a))
234 ;            (error "%s"
235 ;                   (format "fucked with %S: %x %x"
236 ;                           spec (aref o ?a) (aref n ?a))))))))
237 \f
238
239 (defun describe-syntax-table (table stream)
240   (let (first-char
241         last-char
242         prev-val
243         (describe-one
244          (if (featurep 'mule)
245              #'(lambda (first last value stream)
246                  (if (equal first last)
247                      (cond ((vectorp first)
248                             (princ (format "%s, row %d\t"
249                                            (charset-name
250                                             (aref first 0))
251                                            (aref first 1))
252                                    stream))
253                            ((symbolp first)
254                             (princ first stream)
255                             (princ "\t" stream))
256                            (t
257                             (princ (text-char-description first) stream)
258                             (princ "\t" stream)))
259                    (cond ((vectorp first)
260                           (princ (format "%s, rows %d .. %d\t"
261                                          (charset-name
262                                           (aref first 0))
263                                          (aref first 1)
264                                          (aref last 1))
265                                  stream))
266                          ((symbolp first)
267                           (princ (format "%s .. %s\t" first last) stream))
268                          (t
269                           (princ (format "%s .. %s\t"
270                                          (text-char-description first)
271                                          (text-char-description last))
272                                  stream))))
273                  (describe-syntax-code value stream))
274            #'(lambda (first last value stream)
275                (let* ((tem (text-char-description first))
276                       (pos (length tem))
277                       ;;(limit (cond ((numberp ctl-arrow) ctl-arrow)
278                       ;;             ((memq ctl-arrow '(t nil)) 256)
279                       ;;             (t 160)))
280                       )
281                  (princ tem stream)
282                  (if (> last first)
283                      (progn
284                        (princ " .. " stream)
285                        (setq tem (text-char-description last))
286                        (princ tem stream)
287                        (setq pos (+ pos (length tem) 4))))
288                  (while (progn (write-char ?\  stream)
289                                (setq pos (1+ pos))
290                                (< pos 16))))
291                (describe-syntax-code value stream)))))
292     (map-syntax-table
293      #'(lambda (range value)
294          (cond
295           ((not first-char)
296            (setq first-char range
297                  last-char range
298                  prev-val value))
299           ((and (equal value prev-val)
300                 (or
301                  (and (characterp range)
302                       (characterp first-char)
303                       (or (not (featurep 'mule))
304                           (eq (char-charset range)
305                               (char-charset first-char)))
306                       (= (char-int last-char) (1- (char-int range))))
307                  (and (vectorp range)
308                       (vectorp first-char)
309                       (eq (aref range 0) (aref first-char 0))
310                       (= (aref last-char 1) (1- (aref range 1))))))
311            (setq last-char range))
312           (t
313            (funcall describe-one first-char last-char prev-val stream)
314            (setq first-char range
315                  last-char range
316                  prev-val value)))
317          nil)
318      table)
319     (if first-char
320         (funcall describe-one first-char last-char prev-val stream))))
321
322 (defun describe-syntax-code (code stream)
323   (let ((match (and (consp code) (cdr code)))
324         (invalid (gettext "**invalid**")) ;(empty "") ;constants
325         (standard-output (or stream standard-output))
326         ;; #### I18N3 should temporarily set buffer to output-translatable
327         (in #'(lambda (string)
328                 (princ ",\n\t\t\t\t ")
329                 (princ string)))
330         (syntax-string (syntax-code-to-string code)))
331     (if (consp code)
332         (setq code (car code)))
333     (if (null syntax-string)
334         (princ invalid)
335       (princ syntax-string)
336       (princ "\tmeaning: ")
337       (princ (aref ["whitespace" "punctuation" "word-constituent"
338                     "symbol-constituent" "open-paren" "close-paren"
339                     "expression-prefix" "string-quote" "paired-delimiter"
340                     "escape" "character-quote" "comment-begin" "comment-end"
341                     "inherit" "extended-word-constituent"]
342                    (logand code 127)))
343
344       (if match
345           (progn
346             (princ ", matches ")
347             (princ (text-char-description match))))
348       (let* ((spec (elt syntax-string 0))
349              (b3 (lsh code -16))
350              (start1  (/= 0 (logand b3 128))) ;logtest!
351              (start1b (/= 0 (logand b3  64)))
352              (start2  (/= 0 (logand b3  32)))
353              (start2b (/= 0 (logand b3  16)))
354              (end1    (/= 0 (logand b3   8)))
355              (end1b   (/= 0 (logand b3   4)))
356              (end2    (/= 0 (logand b3   2)))
357              (end2b   (/= 0 (logand b3   1)))
358              (prefix  (/= 0 (logand code 128)))
359              (single-char-p (or (= spec ?<) (= spec ?>))))
360         (if start1
361             (if single-char-p
362                 (princ ", style A")
363               (funcall in
364                        (gettext "first character of comment-start sequence A"))))
365         (if start2
366             (funcall in
367                      (gettext "second character of comment-start sequence A")))
368         (if end1
369             (if single-char-p
370                 (princ ", style A")
371               (funcall in
372                        (gettext "first character of comment-end sequence A"))))
373         (if end2
374             (funcall in
375                      (gettext "second character of comment-end sequence A")))
376         (if start1b
377             (if single-char-p
378                 (princ ", style B")
379               (funcall in
380                        (gettext "first character of comment-start sequence B"))))
381         (if start2b
382             (funcall in
383                      (gettext "second character of comment-start sequence B")))
384         (if end1b
385             (if single-char-p
386                 (princ ", style B")
387               (funcall in
388                        (gettext "first character of comment-end sequence B"))))
389         (if end2b
390             (funcall in
391                      (gettext "second character of comment-end sequence B")))
392         (if prefix
393             (funcall in
394                      (gettext "prefix character for `backward-prefix-chars'"))))
395       (terpri stream))))
396
397 (defun symbol-near-point ()
398   "Return the first textual item to the nearest point."
399   (interactive)
400   ;alg stolen from etag.el
401   (save-excursion
402         (if (or (bobp) (not (memq (char-syntax (char-before)) '(?w ?_))))
403             (while (not (looking-at #r"\sw\|\s_\|\'"))
404               (forward-char 1)))
405         (while (looking-at #r"\sw\|\s_")
406           (forward-char 1))
407         (if (re-search-backward #r"\sw\|\s_" nil t)
408             (regexp-quote
409              (progn (forward-char 1)
410                     (buffer-substring (point)
411                                       (progn (forward-sexp -1)
412                                              (while (looking-at "\\s'")
413                                                (forward-char 1))
414                                              (point)))))
415           nil)))
416
417 ;;; syntax.el ends here