diff options
| author | Jim Blandy | 1991-06-25 20:50:00 +0000 |
|---|---|---|
| committer | Jim Blandy | 1991-06-25 20:50:00 +0000 |
| commit | c6045832a14f0c18966c00cea7025f5069b3f610 (patch) | |
| tree | 4ec57dbc1318e2cee93c367bc685dbfb528be0c9 /src | |
| parent | 80856e74d89434011cd01f6f96e85d84052c81b7 (diff) | |
| download | emacs-c6045832a14f0c18966c00cea7025f5069b3f610.tar.gz emacs-c6045832a14f0c18966c00cea7025f5069b3f610.zip | |
Initial revision
Diffstat (limited to 'src')
| -rw-r--r-- | src/doc.c | 492 |
1 files changed, 492 insertions, 0 deletions
diff --git a/src/doc.c b/src/doc.c new file mode 100644 index 00000000000..952268ccdbb --- /dev/null +++ b/src/doc.c | |||
| @@ -0,0 +1,492 @@ | |||
| 1 | /* Record indices of function doc strings stored in a file. | ||
| 2 | Copyright (C) 1985, 1986 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 1, or (at your option) | ||
| 9 | any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
| 19 | |||
| 20 | |||
| 21 | #include "config.h" | ||
| 22 | |||
| 23 | #include <sys/types.h> | ||
| 24 | #include <sys/file.h> /* Must be after sys/types.h for USG and BSD4_1*/ | ||
| 25 | |||
| 26 | #ifdef USG5 | ||
| 27 | #include <fcntl.h> | ||
| 28 | #endif | ||
| 29 | |||
| 30 | #ifndef O_RDONLY | ||
| 31 | #define O_RDONLY 0 | ||
| 32 | #endif | ||
| 33 | |||
| 34 | #undef NULL | ||
| 35 | #include "lisp.h" | ||
| 36 | #include "buffer.h" | ||
| 37 | |||
| 38 | Lisp_Object Vdoc_file_name; | ||
| 39 | |||
| 40 | Lisp_Object | ||
| 41 | get_doc_string (filepos) | ||
| 42 | long filepos; | ||
| 43 | { | ||
| 44 | char buf[512 * 32 + 1]; | ||
| 45 | register int fd; | ||
| 46 | register char *name; | ||
| 47 | register char *p, *p1; | ||
| 48 | register int count; | ||
| 49 | extern char *index (); | ||
| 50 | |||
| 51 | if (XTYPE (Vexec_directory) != Lisp_String | ||
| 52 | || XTYPE (Vdoc_file_name) != Lisp_String) | ||
| 53 | return Qnil; | ||
| 54 | |||
| 55 | name = (char *) alloca (XSTRING (Vexec_directory)->size | ||
| 56 | + XSTRING (Vdoc_file_name)->size + 8); | ||
| 57 | strcpy (name, XSTRING (Vexec_directory)->data); | ||
| 58 | strcat (name, XSTRING (Vdoc_file_name)->data); | ||
| 59 | #ifdef VMS | ||
| 60 | #ifndef VMS4_4 | ||
| 61 | /* For VMS versions with limited file name syntax, | ||
| 62 | convert the name to something VMS will allow. */ | ||
| 63 | p = name; | ||
| 64 | while (*p) | ||
| 65 | { | ||
| 66 | if (*p == '-') | ||
| 67 | *p = '_'; | ||
| 68 | p++; | ||
| 69 | } | ||
| 70 | #endif /* not VMS4_4 */ | ||
| 71 | #ifdef VMS4_4 | ||
| 72 | strcpy (name, sys_translate_unix (name)); | ||
| 73 | #endif /* VMS4_4 */ | ||
| 74 | #endif /* VMS */ | ||
| 75 | |||
| 76 | fd = open (name, O_RDONLY, 0); | ||
| 77 | if (fd < 0) | ||
| 78 | error ("Cannot open doc string file \"%s\"", name); | ||
| 79 | if (0 > lseek (fd, filepos, 0)) | ||
| 80 | { | ||
| 81 | close (fd); | ||
| 82 | error ("Position %ld out of range in doc string file \"%s\"", | ||
| 83 | filepos, name); | ||
| 84 | } | ||
| 85 | p = buf; | ||
| 86 | while (p != buf + sizeof buf - 1) | ||
| 87 | { | ||
| 88 | count = read (fd, p, 512); | ||
| 89 | p[count] = 0; | ||
| 90 | if (!count) | ||
| 91 | break; | ||
| 92 | p1 = index (p, '\037'); | ||
| 93 | if (p1) | ||
| 94 | { | ||
| 95 | *p1 = 0; | ||
| 96 | p = p1; | ||
| 97 | break; | ||
| 98 | } | ||
| 99 | p += count; | ||
| 100 | } | ||
| 101 | close (fd); | ||
| 102 | return make_string (buf, p - buf); | ||
| 103 | } | ||
| 104 | |||
| 105 | DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 1, 0, | ||
| 106 | "Return the documentation string of FUNCTION.") | ||
| 107 | (fun1) | ||
| 108 | Lisp_Object fun1; | ||
| 109 | { | ||
| 110 | Lisp_Object fun; | ||
| 111 | Lisp_Object funcar; | ||
| 112 | Lisp_Object tem; | ||
| 113 | |||
| 114 | fun = fun1; | ||
| 115 | while (XTYPE (fun) == Lisp_Symbol) | ||
| 116 | { | ||
| 117 | QUIT; | ||
| 118 | fun = Fsymbol_function (fun); | ||
| 119 | } | ||
| 120 | |||
| 121 | switch (XTYPE (fun)) | ||
| 122 | { | ||
| 123 | case Lisp_Subr: | ||
| 124 | if (XSUBR (fun)->doc == 0) return Qnil; | ||
| 125 | if ((int) XSUBR (fun)->doc >= 0) | ||
| 126 | return Fsubstitute_command_keys (build_string (XSUBR (fun)->doc)); | ||
| 127 | else | ||
| 128 | return | ||
| 129 | Fsubstitute_command_keys (get_doc_string (- (int) XSUBR (fun)->doc)); | ||
| 130 | |||
| 131 | case Lisp_Compiled: | ||
| 132 | if (XVECTOR (fun)->size <= COMPILED_DOC_STRING) | ||
| 133 | return Qnil; | ||
| 134 | tem = XVECTOR (fun)->contents[COMPILED_DOC_STRING]; | ||
| 135 | if (XTYPE (tem) == Lisp_String) | ||
| 136 | return Fsubstitute_command_keys (tem); | ||
| 137 | if (XTYPE (tem) == Lisp_Int && XINT (tem) >= 0) | ||
| 138 | return Fsubstitute_command_keys (get_doc_string (XFASTINT (tem))); | ||
| 139 | return Qnil; | ||
| 140 | |||
| 141 | case Lisp_String: | ||
| 142 | case Lisp_Vector: | ||
| 143 | return build_string ("Keyboard macro."); | ||
| 144 | |||
| 145 | case Lisp_Cons: | ||
| 146 | funcar = Fcar (fun); | ||
| 147 | if (XTYPE (funcar) != Lisp_Symbol) | ||
| 148 | return Fsignal (Qinvalid_function, Fcons (fun, Qnil)); | ||
| 149 | if (XSYMBOL (funcar) == XSYMBOL (Qkeymap)) | ||
| 150 | return build_string ("Prefix command (definition is a keymap associating keystrokes with\n\ | ||
| 151 | subcommands.)"); | ||
| 152 | if (XSYMBOL (funcar) == XSYMBOL (Qlambda) | ||
| 153 | || XSYMBOL (funcar) == XSYMBOL (Qautoload)) | ||
| 154 | { | ||
| 155 | tem = Fcar (Fcdr (Fcdr (fun))); | ||
| 156 | if (XTYPE (tem) == Lisp_String) | ||
| 157 | return Fsubstitute_command_keys (tem); | ||
| 158 | if (XTYPE (tem) == Lisp_Int && XINT (tem) >= 0) | ||
| 159 | return Fsubstitute_command_keys (get_doc_string (XFASTINT (tem))); | ||
| 160 | return Qnil; | ||
| 161 | } | ||
| 162 | if (XSYMBOL (funcar) == XSYMBOL (Qmocklisp)) | ||
| 163 | return Qnil; | ||
| 164 | if (XSYMBOL (funcar) == XSYMBOL (Qmacro)) | ||
| 165 | return Fdocumentation (Fcdr (fun)); | ||
| 166 | |||
| 167 | /* Fall through to the default to report an error. */ | ||
| 168 | |||
| 169 | default: | ||
| 170 | return Fsignal (Qinvalid_function, Fcons (fun, Qnil)); | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | DEFUN ("documentation-property", Fdocumentation_property, | ||
| 175 | Sdocumentation_property, 2, 2, 0, | ||
| 176 | "Return the documentation string that is SYMBOL's PROP property.\n\ | ||
| 177 | This differs from using `get' only in that it can refer to strings\n\ | ||
| 178 | stored in the `etc/DOC' file.") | ||
| 179 | (sym, prop) | ||
| 180 | Lisp_Object sym, prop; | ||
| 181 | { | ||
| 182 | register Lisp_Object tem; | ||
| 183 | |||
| 184 | tem = Fget (sym, prop); | ||
| 185 | if (XTYPE (tem) == Lisp_Int) | ||
| 186 | tem = get_doc_string (XINT (tem) > 0 ? XINT (tem) : - XINT (tem)); | ||
| 187 | return Fsubstitute_command_keys (tem); | ||
| 188 | } | ||
| 189 | |||
| 190 | DEFUN ("Snarf-documentation", Fsnarf_documentation, Ssnarf_documentation, | ||
| 191 | 1, 1, 0, | ||
| 192 | "Used during Emacs initialization, before dumping runnable Emacs,\n\ | ||
| 193 | to find pointers to doc strings stored in `etc/DOC...' and\n\ | ||
| 194 | record them in function definitions.\n\ | ||
| 195 | One arg, FILENAME, a string which does not include a directory.\n\ | ||
| 196 | The file is found in `../etc' now; found in the `exec-directory'\n\ | ||
| 197 | when doc strings are referred to later in the dumped Emacs.") | ||
| 198 | (filename) | ||
| 199 | Lisp_Object filename; | ||
| 200 | { | ||
| 201 | int fd; | ||
| 202 | char buf[1024 + 1]; | ||
| 203 | register int filled; | ||
| 204 | register int pos; | ||
| 205 | register char *p, *end; | ||
| 206 | Lisp_Object sym, fun, tem; | ||
| 207 | char *name; | ||
| 208 | extern char *index (); | ||
| 209 | |||
| 210 | CHECK_STRING (filename, 0); | ||
| 211 | |||
| 212 | #ifndef CANNOT_DUMP | ||
| 213 | name = (char *) alloca (XSTRING (filename)->size + 8); | ||
| 214 | strcpy (name, "../etc/"); | ||
| 215 | #else /* CANNOT_DUMP */ | ||
| 216 | CHECK_STRING (Vexec_directory, 0); | ||
| 217 | name = (char *) alloca (XSTRING (filename)->size + | ||
| 218 | XSTRING (Vexec_directory)->size + 1); | ||
| 219 | strcpy (name, XSTRING (Vexec_directory)->data); | ||
| 220 | #endif /* CANNOT_DUMP */ | ||
| 221 | strcat (name, XSTRING (filename)->data); /*** Add this line ***/ | ||
| 222 | #ifdef VMS | ||
| 223 | #ifndef VMS4_4 | ||
| 224 | /* For VMS versions with limited file name syntax, | ||
| 225 | convert the name to something VMS will allow. */ | ||
| 226 | p = name; | ||
| 227 | while (*p) | ||
| 228 | { | ||
| 229 | if (*p == '-') | ||
| 230 | *p = '_'; | ||
| 231 | p++; | ||
| 232 | } | ||
| 233 | #endif /* not VMS4_4 */ | ||
| 234 | #ifdef VMS4_4 | ||
| 235 | strcpy (name, sys_translate_unix (name)); | ||
| 236 | #endif /* VMS4_4 */ | ||
| 237 | #endif /* VMS */ | ||
| 238 | |||
| 239 | fd = open (name, O_RDONLY, 0); | ||
| 240 | if (fd < 0) | ||
| 241 | report_file_error ("Opening doc string file", | ||
| 242 | Fcons (build_string (name), Qnil)); | ||
| 243 | Vdoc_file_name = filename; | ||
| 244 | filled = 0; | ||
| 245 | pos = 0; | ||
| 246 | while (1) | ||
| 247 | { | ||
| 248 | if (filled < 512) | ||
| 249 | filled += read (fd, &buf[filled], sizeof buf - 1 - filled); | ||
| 250 | if (!filled) | ||
| 251 | break; | ||
| 252 | |||
| 253 | buf[filled] = 0; | ||
| 254 | p = buf; | ||
| 255 | end = buf + (filled < 512 ? filled : filled - 128); | ||
| 256 | while (p != end && *p != '\037') p++; | ||
| 257 | /* p points to ^_Ffunctionname\n or ^_Vvarname\n. */ | ||
| 258 | if (p != end) | ||
| 259 | { | ||
| 260 | end = index (p, '\n'); | ||
| 261 | sym = oblookup (Vobarray, p + 2, end - p - 2); | ||
| 262 | if (XTYPE (sym) == Lisp_Symbol) | ||
| 263 | { | ||
| 264 | /* Attach a docstring to a variable? */ | ||
| 265 | if (p[1] == 'V') | ||
| 266 | { | ||
| 267 | /* Install file-position as variable-documentation property | ||
| 268 | and make it negative for a user-variable | ||
| 269 | (doc starts with a `*'). */ | ||
| 270 | Fput (sym, Qvariable_documentation, | ||
| 271 | make_number ((pos + end + 1 - buf) | ||
| 272 | * (end[1] == '*' ? -1 : 1))); | ||
| 273 | } | ||
| 274 | |||
| 275 | /* Attach a docstring to a function? The type determines where | ||
| 276 | the docstring is stored. */ | ||
| 277 | else if (p[1] == 'F') | ||
| 278 | { | ||
| 279 | fun = XSYMBOL (sym)->function; | ||
| 280 | |||
| 281 | /* Lisp_Subrs have a slot for it. */ | ||
| 282 | if (XTYPE (fun) == Lisp_Subr) | ||
| 283 | XSUBR (fun)->doc = (char *) - (pos + end + 1 - buf); | ||
| 284 | |||
| 285 | /* If it's a lisp form, stick it in the form. */ | ||
| 286 | else if (CONSP (fun)) | ||
| 287 | { | ||
| 288 | tem = XCONS (fun)->car; | ||
| 289 | if (EQ (tem, Qlambda) || EQ (tem, Qautoload)) | ||
| 290 | { | ||
| 291 | tem = Fcdr (Fcdr (fun)); | ||
| 292 | if (CONSP (tem) && | ||
| 293 | XTYPE (XCONS (tem)->car) == Lisp_Int) | ||
| 294 | XFASTINT (XCONS (tem)->car) = (pos + end + 1 - buf); | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 298 | /* Bytecode objects sometimes have slots for it. */ | ||
| 299 | else if (XTYPE (fun) == Lisp_Compiled) | ||
| 300 | { | ||
| 301 | /* This bytecode object must have a slot for the | ||
| 302 | docstring, since we've found a docstring for it. */ | ||
| 303 | if (XVECTOR (fun)->size <= COMPILED_DOC_STRING) | ||
| 304 | abort (); | ||
| 305 | |||
| 306 | XFASTINT (XVECTOR (fun)->contents[COMPILED_DOC_STRING]) | ||
| 307 | = pos + end + 1 - buf; | ||
| 308 | } | ||
| 309 | } | ||
| 310 | else error ("DOC file invalid at position %d", pos); | ||
| 311 | } | ||
| 312 | } | ||
| 313 | pos += end - buf; | ||
| 314 | filled -= end - buf; | ||
| 315 | bcopy (end, buf, filled); | ||
| 316 | } | ||
| 317 | close (fd); | ||
| 318 | return Qnil; | ||
| 319 | } | ||
| 320 | |||
| 321 | DEFUN ("substitute-command-keys", Fsubstitute_command_keys, | ||
| 322 | Ssubstitute_command_keys, 1, 1, 0, | ||
| 323 | "Substitute key descriptions for command names in STRING.\n\ | ||
| 324 | Return a new string which is STRING with substrings of the form \\=\\[COMMAND]\n\ | ||
| 325 | replaced by either: a keystroke sequence that will invoke COMMAND,\n\ | ||
| 326 | or \"M-x COMMAND\" if COMMAND is not on any keys.\n\ | ||
| 327 | Substrings of the form \\=\\{MAPVAR} are replaced by summaries\n\ | ||
| 328 | \(made by describe-bindings) of the value of MAPVAR, taken as a keymap.\n\ | ||
| 329 | Substrings of the form \\=\\<MAPVAR> specify to use the value of MAPVAR\n\ | ||
| 330 | as the keymap for future \\=\\[COMMAND] substrings.\n\ | ||
| 331 | \\=\\= quotes the following character and is discarded;\n\ | ||
| 332 | thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output.") | ||
| 333 | (str) | ||
| 334 | Lisp_Object str; | ||
| 335 | { | ||
| 336 | unsigned char *buf; | ||
| 337 | int changed = 0; | ||
| 338 | register unsigned char *strp; | ||
| 339 | register unsigned char *bufp; | ||
| 340 | int idx; | ||
| 341 | int bsize; | ||
| 342 | unsigned char *new; | ||
| 343 | register Lisp_Object tem; | ||
| 344 | Lisp_Object keymap; | ||
| 345 | unsigned char *start; | ||
| 346 | int length; | ||
| 347 | struct gcpro gcpro1; | ||
| 348 | |||
| 349 | if (NULL (str)) | ||
| 350 | return Qnil; | ||
| 351 | |||
| 352 | CHECK_STRING (str, 0); | ||
| 353 | GCPRO1 (str); | ||
| 354 | |||
| 355 | keymap = current_buffer->keymap; | ||
| 356 | |||
| 357 | bsize = XSTRING (str)->size; | ||
| 358 | bufp = buf = (unsigned char *) xmalloc (bsize); | ||
| 359 | |||
| 360 | strp = (unsigned char *) XSTRING (str)->data; | ||
| 361 | while (strp < (unsigned char *) XSTRING (str)->data + XSTRING (str)->size) | ||
| 362 | { | ||
| 363 | if (strp[0] == '\\' && strp[1] == '=') | ||
| 364 | { | ||
| 365 | /* \= quotes the next character; | ||
| 366 | thus, to put in \[ without its special meaning, use \=\[. */ | ||
| 367 | changed = 1; | ||
| 368 | *bufp++ = strp[2]; | ||
| 369 | strp += 3; | ||
| 370 | } | ||
| 371 | else if (strp[0] == '\\' && strp[1] == '[') | ||
| 372 | { | ||
| 373 | changed = 1; | ||
| 374 | strp += 2; /* skip \[ */ | ||
| 375 | start = strp; | ||
| 376 | |||
| 377 | while ((strp - (unsigned char *) XSTRING (str)->data | ||
| 378 | < XSTRING (str)->size) | ||
| 379 | && *strp != ']') | ||
| 380 | strp++; | ||
| 381 | length = strp - start; | ||
| 382 | strp++; /* skip ] */ | ||
| 383 | |||
| 384 | /* Save STRP in IDX. */ | ||
| 385 | idx = strp - (unsigned char *) XSTRING (str)->data; | ||
| 386 | tem = Fintern (make_string (start, length), Qnil); | ||
| 387 | tem = Fwhere_is_internal (tem, keymap, Qnil, Qt, Qnil); | ||
| 388 | |||
| 389 | if (NULL (tem)) /* but not on any keys */ | ||
| 390 | { | ||
| 391 | new = (unsigned char *) xrealloc (buf, bsize += 4); | ||
| 392 | bufp += new - buf; | ||
| 393 | buf = new; | ||
| 394 | bcopy ("M-x ", bufp, 4); | ||
| 395 | bufp += 4; | ||
| 396 | goto subst; | ||
| 397 | } | ||
| 398 | else | ||
| 399 | { /* function is on a key */ | ||
| 400 | tem = Fkey_description (tem); | ||
| 401 | goto subst_string; | ||
| 402 | } | ||
| 403 | } | ||
| 404 | /* \{foo} is replaced with a summary of the keymap (symbol-value foo). | ||
| 405 | \<foo> just sets the keymap used for \[cmd]. */ | ||
| 406 | else if (strp[0] == '\\' && (strp[1] == '{' || strp[1] == '<')) | ||
| 407 | { | ||
| 408 | struct buffer *oldbuf; | ||
| 409 | Lisp_Object name; | ||
| 410 | |||
| 411 | changed = 1; | ||
| 412 | strp += 2; /* skip \{ or \< */ | ||
| 413 | start = strp; | ||
| 414 | |||
| 415 | while ((strp - (unsigned char *) XSTRING (str)->data | ||
| 416 | < XSTRING (str)->size) | ||
| 417 | && *strp != '}' && *strp != '>') | ||
| 418 | strp++; | ||
| 419 | length = strp - start; | ||
| 420 | strp++; /* skip } or > */ | ||
| 421 | |||
| 422 | /* Save STRP in IDX. */ | ||
| 423 | idx = strp - (unsigned char *) XSTRING (str)->data; | ||
| 424 | |||
| 425 | /* Get the value of the keymap in TEM, or nil if undefined. | ||
| 426 | Do this while still in the user's current buffer | ||
| 427 | in case it is a local variable. */ | ||
| 428 | name = Fintern (make_string (start, length), Qnil); | ||
| 429 | tem = Fboundp (name); | ||
| 430 | if (! NULL (tem)) | ||
| 431 | { | ||
| 432 | tem = Fsymbol_value (name); | ||
| 433 | if (! NULL (tem)) | ||
| 434 | tem = get_keymap_1 (tem, 0); | ||
| 435 | } | ||
| 436 | |||
| 437 | /* Now switch to a temp buffer. */ | ||
| 438 | oldbuf = current_buffer; | ||
| 439 | set_buffer_internal (XBUFFER (Vprin1_to_string_buffer)); | ||
| 440 | |||
| 441 | if (NULL (tem)) | ||
| 442 | { | ||
| 443 | name = Fsymbol_name (name); | ||
| 444 | insert_string ("\nUses keymap \""); | ||
| 445 | insert_from_string (name, 0, XSTRING (name)->size); | ||
| 446 | insert_string ("\", which is not currently defined.\n"); | ||
| 447 | if (start[-1] == '<') keymap = Qnil; | ||
| 448 | } | ||
| 449 | else if (start[-1] == '<') | ||
| 450 | keymap = tem; | ||
| 451 | else | ||
| 452 | describe_map_tree (tem, 1, Qnil); | ||
| 453 | tem = Fbuffer_string (); | ||
| 454 | Ferase_buffer (); | ||
| 455 | set_buffer_internal (oldbuf); | ||
| 456 | |||
| 457 | subst_string: | ||
| 458 | start = XSTRING (tem)->data; | ||
| 459 | length = XSTRING (tem)->size; | ||
| 460 | subst: | ||
| 461 | new = (unsigned char *) xrealloc (buf, bsize += length); | ||
| 462 | bufp += new - buf; | ||
| 463 | buf = new; | ||
| 464 | bcopy (start, bufp, length); | ||
| 465 | bufp += length; | ||
| 466 | /* Check STR again in case gc relocated it. */ | ||
| 467 | strp = (unsigned char *) XSTRING (str)->data + idx; | ||
| 468 | } | ||
| 469 | else /* just copy other chars */ | ||
| 470 | *bufp++ = *strp++; | ||
| 471 | } | ||
| 472 | |||
| 473 | if (changed) /* don't bother if nothing substituted */ | ||
| 474 | tem = make_string (buf, bufp - buf); | ||
| 475 | else | ||
| 476 | tem = str; | ||
| 477 | UNGCPRO; | ||
| 478 | free (buf); | ||
| 479 | return tem; | ||
| 480 | } | ||
| 481 | |||
| 482 | syms_of_doc () | ||
| 483 | { | ||
| 484 | DEFVAR_LISP ("internal-doc-file-name", &Vdoc_file_name, | ||
| 485 | "Name of file containing documentation strings of built-in symbols."); | ||
| 486 | Vdoc_file_name = Qnil; | ||
| 487 | |||
| 488 | defsubr (&Sdocumentation); | ||
| 489 | defsubr (&Sdocumentation_property); | ||
| 490 | defsubr (&Ssnarf_documentation); | ||
| 491 | defsubr (&Ssubstitute_command_keys); | ||
| 492 | } | ||