Mercurial > hg > xemacs-beta
comparison lisp/autoload.el @ 996:25e260cb7994
[xemacs-hg @ 2002-09-10 15:27:02 by james]
Enable unloading of dynamic modules. Create the first two internal XEmacs
modules: LDAP and postgreSQL. Update the sample directory to contain a
sample internal XEmacs module and a sample external XEmacs module. Improve
support for autoloading modules. Make internal module code compile into the
XEmacs binary if XEmacs is configured without module support. Make the
internal module directories self-contained so that they can be distributed
separately from XEmacs.
author | james |
---|---|
date | Tue, 10 Sep 2002 15:27:39 +0000 |
parents | d41e92ee6d12 |
children | edc95b5fe4cb |
comparison
equal
deleted
inserted
replaced
995:4575a219af58 | 996:25e260cb7994 |
---|---|
33 ;; lisp source files in various useful ways. To learn more, read the | 33 ;; lisp source files in various useful ways. To learn more, read the |
34 ;; source; if you're going to use this, you'd better be able to. | 34 ;; source; if you're going to use this, you'd better be able to. |
35 | 35 |
36 ;; ChangeLog: | 36 ;; ChangeLog: |
37 | 37 |
38 ;; Jun-25-2002: Jerry James added code for processing C files, to | |
39 ;; support modularization | |
38 ;; Sep-26-1997: slb removed code dealing with customization. | 40 ;; Sep-26-1997: slb removed code dealing with customization. |
39 | 41 |
40 ;;; Code: | 42 ;;; Code: |
41 | 43 |
42 (defun make-autoload (form file) | 44 (defun make-autoload (form file) |
66 (eq car 'define-derived-mode) | 68 (eq car 'define-derived-mode) |
67 (eq (car-safe (car form)) 'interactive)) | 69 (eq (car-safe (car form)) 'interactive)) |
68 (if macrop (list 'quote 'macro) nil))) | 70 (if macrop (list 'quote 'macro) nil))) |
69 nil))) | 71 nil))) |
70 | 72 |
73 (defun make-c-autoload (module) | |
74 "Make an autoload list for the DEFUN at point in MODULE. | |
75 Returns nil if the DEFUN is malformed." | |
76 (and | |
77 ;; Match the DEFUN | |
78 (search-forward "DEFUN" nil t) | |
79 ;; Match the opening parenthesis | |
80 (progn | |
81 (skip-syntax-forward " ") | |
82 (eq (char-after) ?\()) | |
83 ;; Match the opening quote of the Lisp function name | |
84 (progn | |
85 (forward-char) | |
86 (skip-syntax-forward " ") | |
87 (eq (char-after) ?\")) | |
88 ;; Extract the Lisp function name, interactive indicator, and docstring | |
89 (let* ((func-name (let ((begin (progn (forward-char) (point)))) | |
90 (search-forward "\"" nil t) | |
91 (backward-char) | |
92 (intern (buffer-substring begin (point))))) | |
93 (interact (progn | |
94 (search-forward "," nil t 4) | |
95 (skip-syntax-forward " ") | |
96 (not (eq (char-after) ?0)))) | |
97 (begin (progn | |
98 (search-forward "/*" nil t) | |
99 (forward-line 1) | |
100 (point)))) | |
101 (search-forward "*/" nil t) | |
102 (goto-char (match-beginning 0)) | |
103 (skip-chars-backward " \t\n\f") | |
104 (list 'autoload (list 'quote func-name) module | |
105 (buffer-substring begin (point)) interact nil)))) | |
106 | |
71 (defvar generate-autoload-cookie ";;;###autoload" | 107 (defvar generate-autoload-cookie ";;;###autoload" |
72 "Magic comment indicating the following form should be autoloaded. | 108 "Magic comment indicating the following form should be autoloaded. |
73 Used by `update-file-autoloads'. This string should be | 109 Used by `update-file-autoloads'. This string should be |
74 meaningless to Lisp (e.g., a comment). | 110 meaningless to Lisp (e.g., a comment). |
75 | 111 |
81 If this string appears alone on a line, the following form will be | 117 If this string appears alone on a line, the following form will be |
82 read and an autoload made for it. If it is followed by the string | 118 read and an autoload made for it. If it is followed by the string |
83 \"immediate\", then the form on the following line will be copied | 119 \"immediate\", then the form on the following line will be copied |
84 verbatim. If there is further text on the line, that text will be | 120 verbatim. If there is further text on the line, that text will be |
85 copied verbatim to `generated-autoload-file'.") | 121 copied verbatim to `generated-autoload-file'.") |
122 | |
123 (defvar generate-c-autoload-cookie "/* ###autoload" | |
124 "Magic C comment indicating the following form should be autoloaded. | |
125 Used by `update-file-autoloads'. This string should be | |
126 meaningless to C (e.g., a comment). | |
127 | |
128 This string is used: | |
129 | |
130 /* ###autoload */ | |
131 DEFUN (\"function-to-be-autoloaded\", ... ) | |
132 | |
133 If this string appears alone on a line, the following form will be | |
134 read and an autoload made for it. If there is further text on the line, | |
135 that text will be copied verbatim to `generated-autoload-file'.") | |
136 | |
137 (defvar generate-c-autoload-module "/* ###module" | |
138 "Magic C comment indicating the module containing autoloaded functions. | |
139 Since a module can consist of multiple C files, the module name may not be | |
140 the same as the C source file base name. In that case, use this comment to | |
141 indicate the actual name of the module from which to autoload functions.") | |
86 | 142 |
87 (defvar generate-autoload-section-header "\f\n;;;### " | 143 (defvar generate-autoload-section-header "\f\n;;;### " |
88 "String inserted before the form identifying | 144 "String inserted before the form identifying |
89 the section of autoloads for a file.") | 145 the section of autoloads for a file.") |
90 | 146 |
136 autoloads are generated for defuns and defmacros in FILE | 192 autoloads are generated for defuns and defmacros in FILE |
137 marked by `generate-autoload-cookie' (which see). | 193 marked by `generate-autoload-cookie' (which see). |
138 If FILE is being visited in a buffer, the contents of the buffer | 194 If FILE is being visited in a buffer, the contents of the buffer |
139 are used." | 195 are used." |
140 (interactive "fGenerate autoloads for file: ") | 196 (interactive "fGenerate autoloads for file: ") |
141 (generate-file-autoloads-1 file funlist)) | 197 (if (string-match "\\.el$" file) |
198 (generate-file-autoloads-1 file funlist) | |
199 (generate-c-file-autoloads-1 file funlist))) | |
142 | 200 |
143 (defun* generate-file-autoloads-1 (file funlist) | 201 (defun* generate-file-autoloads-1 (file funlist) |
144 "Insert at point a loaddefs autoload section for FILE. | 202 "Insert at point a loaddefs autoload section for FILE. |
145 autoloads are generated for defuns and defmacros in FILE | 203 autoloads are generated for defuns and defmacros in FILE |
146 marked by `generate-autoload-cookie' (which see). | 204 marked by `generate-autoload-cookie' (which see). |
212 'doc-string-elt))) | 270 'doc-string-elt))) |
213 (if autoload | 271 (if autoload |
214 (setq autoloads-done (cons (nth 1 form) | 272 (setq autoloads-done (cons (nth 1 form) |
215 autoloads-done)) | 273 autoloads-done)) |
216 (setq autoload form)) | 274 (setq autoload form)) |
217 (if (and doc-string-elt | 275 (print-autoload autoload doc-string-elt outbuf)) |
218 (stringp (nth doc-string-elt autoload))) | |
219 ;; We need to hack the printing because the | |
220 ;; doc-string must be printed specially for | |
221 ;; make-docfile (sigh). | |
222 (let* ((p (nthcdr (1- doc-string-elt) | |
223 autoload)) | |
224 (elt (cdr p))) | |
225 (setcdr p nil) | |
226 (princ "\n(" outbuf) | |
227 ;; XEmacs change: don't let ^^L's get into | |
228 ;; the file or sorting is hard. | |
229 (let ((print-escape-newlines t) | |
230 (p (save-excursion | |
231 (set-buffer outbuf) | |
232 (point))) | |
233 p2) | |
234 (mapcar (function (lambda (elt) | |
235 (prin1 elt outbuf) | |
236 (princ " " outbuf))) | |
237 autoload) | |
238 (save-excursion | |
239 (set-buffer outbuf) | |
240 (setq p2 (point-marker)) | |
241 (goto-char p) | |
242 (save-match-data | |
243 (while (search-forward "\^L" p2 t) | |
244 (delete-char -1) | |
245 (insert "\\^L"))) | |
246 (goto-char p2) | |
247 )) | |
248 (princ "\"\\\n" outbuf) | |
249 (let ((begin (save-excursion | |
250 (set-buffer outbuf) | |
251 (point)))) | |
252 (princ (substring | |
253 (prin1-to-string (car elt)) 1) | |
254 outbuf) | |
255 ;; Insert a backslash before each ( that | |
256 ;; appears at the beginning of a line in | |
257 ;; the doc string. | |
258 (save-excursion | |
259 (set-buffer outbuf) | |
260 (save-excursion | |
261 (while (search-backward "\n(" begin t) | |
262 (forward-char 1) | |
263 (insert "\\")))) | |
264 (if (null (cdr elt)) | |
265 (princ ")" outbuf) | |
266 (princ " " outbuf) | |
267 (princ (substring | |
268 (prin1-to-string (cdr elt)) | |
269 1) | |
270 outbuf)) | |
271 (terpri outbuf))) | |
272 ;; XEmacs change: another fucking ^L hack | |
273 (let ((p (save-excursion | |
274 (set-buffer outbuf) | |
275 (point))) | |
276 (print-escape-newlines t) | |
277 p2) | |
278 (print autoload outbuf) | |
279 (save-excursion | |
280 (set-buffer outbuf) | |
281 (setq p2 (point-marker)) | |
282 (goto-char p) | |
283 (save-match-data | |
284 (while (search-forward "\^L" p2 t) | |
285 (delete-char -1) | |
286 (insert "\\^L"))) | |
287 (goto-char p2) | |
288 )) | |
289 )) | |
290 ;; Copy the rest of the line to the output. | 276 ;; Copy the rest of the line to the output. |
291 (let ((begin (point))) | 277 (let ((begin (point))) |
292 ;; (terpri outbuf) | 278 ;; (terpri outbuf) |
293 (cond ((looking-at "immediate\\s *$") ; XEmacs | 279 (cond ((looking-at "immediate\\s *$") ; XEmacs |
294 ;; This is here so that you can automatically | 280 ;; This is here so that you can automatically |
344 (goto-char output-end) | 330 (goto-char output-end) |
345 (insert generate-autoload-section-trailer))) | 331 (insert generate-autoload-section-trailer))) |
346 (or noninteractive ; XEmacs: only need one line in -batch mode. | 332 (or noninteractive ; XEmacs: only need one line in -batch mode. |
347 (message "Generating autoloads for %s...done" file)))) | 333 (message "Generating autoloads for %s...done" file)))) |
348 | 334 |
335 (defun* generate-c-file-autoloads-1 (file funlist) | |
336 "Insert at point a loaddefs autoload section for the C file FILE. | |
337 autoloads are generated for Defuns and defmacros in FILE | |
338 marked by `generate-c-autoload-cookie' (which see). | |
339 If FILE is being visited in a buffer, the contents of the buffer | |
340 are used." | |
341 (let ((outbuf (current-buffer)) | |
342 (autoloads-done '()) | |
343 (load-name (replace-in-string (file-name-nondirectory file) | |
344 "\\.c?$" | |
345 "")) | |
346 (trim-name (autoload-trim-file-name file)) | |
347 (print-length nil) | |
348 (print-readably t) | |
349 (float-output-format nil) | |
350 ;; (done-any nil) | |
351 (visited (get-file-buffer file)) | |
352 output-end) | |
353 | |
354 ;; If the autoload section we create here uses an absolute | |
355 ;; pathname for FILE in its header, and then Emacs is installed | |
356 ;; under a different path on another system, | |
357 ;; `update-autoloads-here' won't be able to find the files to be | |
358 ;; autoloaded. So, if FILE is in the same directory or a | |
359 ;; subdirectory of the current buffer's directory, we'll make it | |
360 ;; relative to the current buffer's directory. | |
361 (setq file (expand-file-name file)) | |
362 | |
363 (save-excursion | |
364 (unwind-protect | |
365 (progn | |
366 (let ((find-file-hooks nil) | |
367 (enable-local-variables nil)) | |
368 (set-buffer (or visited (find-file-noselect file t t))) | |
369 ;; This doesn't look right, but it is. The only place we need | |
370 ;; the syntax table is when snarfing the Lisp function name. | |
371 (set-syntax-table emacs-lisp-mode-syntax-table)) | |
372 (save-excursion | |
373 (save-restriction | |
374 (widen) | |
375 (goto-char (point-min)) | |
376 ;; Is there a module name comment? | |
377 (when (search-forward generate-c-autoload-module nil t) | |
378 (skip-chars-forward " \t") | |
379 (let ((begin (point))) | |
380 (skip-chars-forward "^ \t\n\f") | |
381 (setq load-name (buffer-substring begin (point))))) | |
382 (if funlist | |
383 (progn | |
384 (message "Generating autoloads for %s..." trim-name) | |
385 (dolist (arg funlist) | |
386 (goto-char (point-min)) | |
387 (re-search-forward | |
388 (concat "DEFUN (\"" | |
389 (regexp-quote (symbol-name arg)) | |
390 "\"")) | |
391 (goto-char (match-beginning 0)) | |
392 (let ((autoload (make-c-autoload load-name))) | |
393 (when autoload | |
394 (push (nth 1 (nth 1 autoload)) autoloads-done) | |
395 (print-autoload autoload 3 outbuf))))) | |
396 (goto-char (point-min)) | |
397 (let ((match | |
398 (search-forward generate-c-autoload-cookie nil t))) | |
399 (unless match | |
400 (message "No autoloads found in %s" trim-name) | |
401 (return-from generate-c-file-autoloads-1)) | |
402 | |
403 (message "Generating autoloads for %s..." trim-name) | |
404 (while match | |
405 (forward-line 1) | |
406 (let ((autoload (make-c-autoload load-name))) | |
407 (when autoload | |
408 (push (nth 1 (nth 1 autoload)) autoloads-done) | |
409 (print-autoload autoload 3 outbuf))) | |
410 (setq match | |
411 (search-forward generate-c-autoload-cookie nil t)) | |
412 )))))) | |
413 (unless visited | |
414 ;; We created this buffer, so we should kill it. | |
415 (kill-buffer (current-buffer))) | |
416 (set-buffer outbuf) | |
417 (setq output-end (point-marker)))) | |
418 (insert generate-autoload-section-header) | |
419 (prin1 (list 'autoloads autoloads-done load-name trim-name) outbuf) | |
420 (terpri outbuf) | |
421 (when (< output-end (point)) | |
422 (setq output-end (point-marker))) | |
423 (goto-char output-end) | |
424 (insert generate-autoload-section-trailer) | |
425 (or noninteractive ; XEmacs: only need one line in -batch mode. | |
426 (message "Generating autoloads for %s...done" trim-name)))) | |
427 | |
428 (defun print-autoload (autoload doc-string-elt outbuf) | |
429 "Print an autoload form, handling special characters. | |
430 In particular, print docstrings with escapes inserted before left parentheses | |
431 at the beginning of lines and ^L characters." | |
432 (if (and doc-string-elt (stringp (nth doc-string-elt autoload))) | |
433 ;; We need to hack the printing because the doc-string must be | |
434 ;; printed specially for make-docfile (sigh). | |
435 (let* ((p (nthcdr (1- doc-string-elt) autoload)) | |
436 (elt (cdr p))) | |
437 (setcdr p nil) | |
438 (princ "\n(" outbuf) | |
439 ;; XEmacs change: don't let ^^L's get into | |
440 ;; the file or sorting is hard. | |
441 (let ((print-escape-newlines t) | |
442 (p (save-excursion | |
443 (set-buffer outbuf) | |
444 (point))) | |
445 p2) | |
446 (mapcar #'(lambda (elt) | |
447 (prin1 elt outbuf) | |
448 (princ " " outbuf)) | |
449 autoload) | |
450 (save-excursion | |
451 (set-buffer outbuf) | |
452 (setq p2 (point-marker)) | |
453 (goto-char p) | |
454 (save-match-data | |
455 (while (search-forward "\^L" p2 t) | |
456 (delete-char -1) | |
457 (insert "\\^L"))) | |
458 (goto-char p2))) | |
459 (princ "\"\\\n" outbuf) | |
460 (let ((begin (save-excursion | |
461 (set-buffer outbuf) | |
462 (point)))) | |
463 (princ (substring (prin1-to-string (car elt)) 1) outbuf) | |
464 ;; Insert a backslash before each ( that appears at the beginning | |
465 ;; of a line in the doc string. | |
466 (save-excursion | |
467 (set-buffer outbuf) | |
468 (save-excursion | |
469 (while (search-backward "\n(" begin t) | |
470 (forward-char 1) | |
471 (insert "\\")))) | |
472 (if (null (cdr elt)) | |
473 (princ ")" outbuf) | |
474 (princ " " outbuf) | |
475 (princ (substring (prin1-to-string (cdr elt)) 1) outbuf)) | |
476 (terpri outbuf))) | |
477 ;; XEmacs change: another ^L hack | |
478 (let ((p (save-excursion | |
479 (set-buffer outbuf) | |
480 (point))) | |
481 (print-escape-newlines t) | |
482 p2) | |
483 (print autoload outbuf) | |
484 (save-excursion | |
485 (set-buffer outbuf) | |
486 (setq p2 (point-marker)) | |
487 (goto-char p) | |
488 (save-match-data | |
489 (while (search-forward "\^L" p2 t) | |
490 (delete-char -1) | |
491 (insert "\\^L"))) | |
492 (goto-char p2))))) | |
493 | |
349 | 494 |
350 (defconst autoload-file-name "auto-autoloads.el" | 495 (defconst autoload-file-name "auto-autoloads.el" |
351 "Generic filename to put autoloads into. | 496 "Generic filename to put autoloads into. |
352 Unless you are an XEmacs maintainer, it is probably unwise to change this.") | 497 Unless you are an XEmacs maintainer, it is probably unwise to change this.") |
353 | 498 |
381 (when (and (file-newer-than-file-p file generated-autoload-file) | 526 (when (and (file-newer-than-file-p file generated-autoload-file) |
382 (not (member (file-name-nondirectory file) | 527 (not (member (file-name-nondirectory file) |
383 (list autoload-file-name)))) | 528 (list autoload-file-name)))) |
384 | 529 |
385 (let ((load-name (replace-in-string (file-name-nondirectory file) | 530 (let ((load-name (replace-in-string (file-name-nondirectory file) |
386 "\\.elc?$" | 531 "\\.\\(elc?\\|c\\)$" |
387 "")) | 532 "")) |
388 (trim-name (autoload-trim-file-name file)) | 533 (trim-name (autoload-trim-file-name file)) |
389 section-begin form) | 534 section-begin form) |
390 (save-excursion | 535 (save-excursion |
391 (let ((find-file-hooks nil)) | 536 (let ((find-file-hooks nil)) |
471 (generate-file-autoloads file))))))) | 616 (generate-file-autoloads file))))))) |
472 | 617 |
473 ;;;###autoload | 618 ;;;###autoload |
474 (defun update-autoloads-from-directory (dir) | 619 (defun update-autoloads-from-directory (dir) |
475 "Update `generated-autoload-file' with all the current autoloads from DIR. | 620 "Update `generated-autoload-file' with all the current autoloads from DIR. |
476 This runs `update-file-autoloads' on each .el file in DIR. | 621 This runs `update-file-autoloads' on each .el and .c file in DIR. |
477 Obsolete autoload entries for files that no longer exist are deleted. | 622 Obsolete autoload entries for files that no longer exist are deleted. |
478 Note that, if this function is called from `batch-update-directory', | 623 Note that, if this function is called from `batch-update-directory', |
479 `generated-autoload-file' was rebound in that function. | 624 `generated-autoload-file' was rebound in that function. |
480 | 625 |
481 You don't really want to be calling this function. Try using | 626 You don't really want to be calling this function. Try using |
503 (file-name-nondirectory file) dir)))) | 648 (file-name-nondirectory file) dir)))) |
504 ;; Remove the obsolete section. | 649 ;; Remove the obsolete section. |
505 (search-forward generate-autoload-section-trailer) | 650 (search-forward generate-autoload-section-trailer) |
506 (delete-region begin (point))))) | 651 (delete-region begin (point))))) |
507 ;; Update or create autoload sections for existing files. | 652 ;; Update or create autoload sections for existing files. |
508 (mapcar 'update-file-autoloads (directory-files dir t "^[^=].*\\.el$")) | 653 (mapcar 'update-file-autoloads |
654 (directory-files dir t "^[^=].*\\.\\(el\\|c\\)$")) | |
509 (unless noninteractive | 655 (unless noninteractive |
510 (save-buffer))))) | 656 (save-buffer))))) |
511 | 657 |
512 (defun fixup-autoload-buffer (sym) | 658 (defun fixup-autoload-buffer (sym) |
513 (save-excursion | 659 (save-excursion |