|
|
1.1 ! root 1: /* Record indices of function doc strings stored in a file. ! 2: Copyright (C) 1985 Richard M. Stallman. ! 3: ! 4: This file is part of GNU Emacs. ! 5: ! 6: GNU Emacs is distributed in the hope that it will be useful, ! 7: but WITHOUT ANY WARRANTY. No author or distributor ! 8: accepts responsibility to anyone for the consequences of using it ! 9: or for whether it serves any particular purpose or works at all, ! 10: unless he says so in writing. Refer to the GNU Emacs General Public ! 11: License for full details. ! 12: ! 13: Everyone is granted permission to copy, modify and redistribute ! 14: GNU Emacs, but only under the conditions described in the ! 15: GNU Emacs General Public License. A copy of this license is ! 16: supposed to have been given to you along with GNU Emacs so you ! 17: can know your rights and responsibilities. It should be in a ! 18: file named COPYING. Among other things, the copyright notice ! 19: and this notice must be preserved on all copies. */ ! 20: ! 21: ! 22: #include "config.h" ! 23: #include "lisp.h" ! 24: #include "buffer.h" ! 25: #include "paths.h" ! 26: ! 27: #include <sys/types.h> ! 28: #include <sys/file.h> /* Must be after sys/types.h for USG and BSD4_1*/ ! 29: ! 30: #ifdef USG5 ! 31: #include <fcntl.h> ! 32: #endif ! 33: ! 34: #ifndef O_RDONLY ! 35: #define O_RDONLY 0 ! 36: #endif ! 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 + 2); ! 57: strcpy (name, XSTRING (Vexec_directory)->data); ! 58: strcat (name, XSTRING (Vdoc_file_name)->data); ! 59: ! 60: fd = open (name, O_RDONLY, 0); ! 61: if (fd < 0) ! 62: error ("Cannot open doc string file \"%s\"", name); ! 63: if (0 > lseek (fd, filepos, 0)) ! 64: { ! 65: close (fd); ! 66: error ("Position %ld out of range in doc string file \"%s\"", ! 67: filepos, name); ! 68: } ! 69: p = buf; ! 70: while (p != buf + sizeof buf - 1) ! 71: { ! 72: count = read (fd, p, 512); ! 73: p[count] = 0; ! 74: if (!count) ! 75: break; ! 76: p1 = index (p, '\037'); ! 77: if (p1) ! 78: { ! 79: *p1 = 0; ! 80: p = p1; ! 81: break; ! 82: } ! 83: p += count; ! 84: } ! 85: close (fd); ! 86: return make_string (buf, p - buf); ! 87: } ! 88: ! 89: DEFUN ("documentation", Fdocumentation, Sdocumentation, 1, 1, 0, ! 90: "Return the documentation string of FUNCTION.") ! 91: (fun1) ! 92: Lisp_Object fun1; ! 93: { ! 94: Lisp_Object fun; ! 95: Lisp_Object funcar; ! 96: Lisp_Object tem; ! 97: ! 98: fun = fun1; ! 99: while (XTYPE (fun) == Lisp_Symbol) ! 100: fun = Fsymbol_function (fun); ! 101: if (XTYPE (fun) == Lisp_Subr) ! 102: { ! 103: if (XSUBR (fun)->doc == 0) return Qnil; ! 104: if ((int) XSUBR (fun)->doc >= 0) ! 105: return Fsubstitute_command_keys (build_string (XSUBR (fun)->doc)); ! 106: return Fsubstitute_command_keys (get_doc_string (- (int) XSUBR (fun)->doc)); ! 107: } ! 108: if (XTYPE (fun) == Lisp_Vector) ! 109: return build_string ("Prefix command (definition is a Lisp vector of subcommands)."); ! 110: if (XTYPE (fun) == Lisp_String) ! 111: return build_string ("Keyboard macro."); ! 112: if (!LISTP(fun)) ! 113: return Fsignal (Qinvalid_function, Fcons (fun, Qnil)); ! 114: funcar = Fcar (fun); ! 115: if (XTYPE (funcar) != Lisp_Symbol) ! 116: return Fsignal (Qinvalid_function, Fcons (fun, Qnil)); ! 117: if (XSYMBOL (funcar) == XSYMBOL (Qkeymap)) ! 118: return build_string ("Prefix command (definition is a list whose cdr is an alist of subcommands.)"); ! 119: if (XSYMBOL (funcar) == XSYMBOL (Qlambda) ! 120: || XSYMBOL (funcar) == XSYMBOL (Qautoload)) ! 121: { ! 122: tem = Fcar (Fcdr (Fcdr (fun))); ! 123: if (XTYPE (tem) == Lisp_String) ! 124: return Fsubstitute_command_keys (tem); ! 125: if (XTYPE (tem) == Lisp_Int && XINT (tem) >= 0) ! 126: return Fsubstitute_command_keys (get_doc_string (XFASTINT (tem))); ! 127: return Qnil; ! 128: } ! 129: if (XSYMBOL (funcar) == XSYMBOL (Qmocklisp)) ! 130: return Qnil; ! 131: if (XSYMBOL (funcar) == XSYMBOL (Qmacro)) ! 132: return Fdocumentation (Fcdr (fun)); ! 133: else ! 134: return Fsignal (Qinvalid_function, Fcons (fun, Qnil)); ! 135: } ! 136: ! 137: DEFUN ("Snarf-documentation", Fsnarf_documentation, Ssnarf_documentation, ! 138: 1, 1, 0, ! 139: "Used during Emacs initialization, before dumping runnable Emacs,\n\ ! 140: to find pointers to doc strings stored in etc/DOC... and\n\ ! 141: record them in function definitions.\n\ ! 142: One arg, FILENAME, a string which does not include a directory.\n\ ! 143: The file is found in ../etc now; found in the exec-directory\n\ ! 144: when doc strings are referred to later in the dumped Emacs.") ! 145: (filename) ! 146: Lisp_Object filename; ! 147: { ! 148: int fd; ! 149: char buf[1024 + 1]; ! 150: register int filled; ! 151: register int pos; ! 152: register char *p, *end; ! 153: Lisp_Object sym, fun, tem; ! 154: char *name; ! 155: extern char *index (); ! 156: ! 157: CHECK_STRING (filename, 0); ! 158: ! 159: #ifndef CANNOT_DUMP ! 160: name = (char *) alloca (XSTRING (filename)->size + 8); ! 161: strcpy (name, "../etc/"); ! 162: #else /* CANNOT_DUMP */ ! 163: name = (char *) alloca (XSTRING (filename)->size + sizeof(PATH_EXEC)+1); ! 164: strcpy (name, PATH_EXEC); ! 165: strcat (name, "/"); ! 166: #endif /* CANNOT_DUMP */ ! 167: strcat (name, XSTRING (filename)->data); /*** Add this line ***/ ! 168: ! 169: fd = open (name, O_RDONLY, 0); ! 170: if (fd < 0) ! 171: report_file_error ("Opening doc string file", Fcons (filename, Qnil)); ! 172: Vdoc_file_name = filename; ! 173: filled = 0; ! 174: pos = 0; ! 175: while (1) ! 176: { ! 177: if (filled < 512) ! 178: filled += read (fd, &buf[filled], sizeof buf - 1 - filled); ! 179: if (!filled) ! 180: break; ! 181: ! 182: buf[filled] = 0; ! 183: p = buf; ! 184: end = buf + (filled < 512 ? filled : filled - 128); ! 185: while (p != end && *p != '\037') p++; ! 186: if (p != end) ! 187: { ! 188: end = index (p, '\n'); ! 189: sym = oblookup (Vobarray, p + 1, end - p - 1); ! 190: if (XTYPE (sym) == Lisp_Symbol) ! 191: { ! 192: fun = XSYMBOL (sym)->function; ! 193: if (XTYPE (fun) == Lisp_Subr) ! 194: XSUBR (fun)->doc = (char *) - (pos + end + 1 - buf); ! 195: else if (LISTP (fun)) ! 196: { ! 197: tem = XCONS (fun)->car; ! 198: if (EQ (tem, Qlambda) || EQ (tem, Qautoload)) ! 199: { ! 200: tem = Fcdr (Fcdr (fun)); ! 201: if (LISTP (tem) && XTYPE (XCONS (tem)->car) == Lisp_Int) ! 202: XFASTINT (XCONS (tem)->car) = (pos + end + 1 - buf); ! 203: } ! 204: } ! 205: } ! 206: } ! 207: pos += end - buf; ! 208: filled -= end - buf; ! 209: bcopy (end, buf, filled); ! 210: } ! 211: close (fd); ! 212: return Qnil; ! 213: } ! 214: ! 215: extern Lisp_Object where_is_in_buffer (); ! 216: ! 217: DEFUN ("substitute-command-keys", Fsubstitute_command_keys, ! 218: Ssubstitute_command_keys, 1, 1, 0, ! 219: "Return the STRING with substrings of the form \\=\\[COMMAND]\n\ ! 220: replaced by either: a keystroke sequence that will invoke COMMAND,\n\ ! 221: or \"M-x COMMAND\" if COMMAND is not on any keys.\n\ ! 222: Substrings of the form \\=\\{MAPVAR} are replaced by summaries\n\ ! 223: \(made by describe-bindings) of the value of MAPVAR, taken as a keymap.\n\ ! 224: \\=\\= quotes the following character and is discarded;\n\ ! 225: thus, \\=\\=\\=\\= puts \\=\\= into the output, and \\=\\=\\=\\[ puts \\=\\[ into the output.") ! 226: (str) ! 227: Lisp_Object str; ! 228: { ! 229: unsigned char *buf; ! 230: int didone = 0; ! 231: register unsigned char *strp; ! 232: register unsigned char *bufp; ! 233: register unsigned char *send; ! 234: int bsize; ! 235: unsigned char *new; ! 236: Lisp_Object key, tem; ! 237: unsigned char *funp; ! 238: int func; ! 239: struct buffer *oldbuf; ! 240: ! 241: if (NULL (str)) ! 242: return Qnil; ! 243: ! 244: CHECK_STRING (str, 0); ! 245: strp = (unsigned char *) XSTRING (str)->data; ! 246: send = strp + XSTRING (str)->size; ! 247: ! 248: bsize = XSTRING (str)->size; ! 249: bufp = buf = (unsigned char *) xmalloc (bsize); ! 250: ! 251: while (strp < send) ! 252: { ! 253: if (strp[0] == '\\' && strp[1] == '=') ! 254: { ! 255: /* \= quotes the next character; ! 256: thus, to put in \[ without its special meaning, use \=\[. */ ! 257: didone = 1; ! 258: *bufp++ = strp[2]; ! 259: strp += 3; ! 260: } ! 261: else if (strp[0] == '\\' && strp[1] == '[') ! 262: { ! 263: didone = 1; ! 264: strp += 2; /* skip \[ */ ! 265: funp = strp; ! 266: ! 267: while (strp < send && *strp != ']') ! 268: strp++; ! 269: func = strp - funp; ! 270: ! 271: key = Fintern (make_string (funp, func), Qnil); ! 272: key = where_is_in_buffer (key, bf_cur, 1); ! 273: strp++; /* skip ] */ ! 274: ! 275: if (NULL (key)) /* but not on any keys */ ! 276: { ! 277: new = (unsigned char *) xrealloc (buf, bsize += 4); ! 278: bufp += new - buf; ! 279: buf = new; ! 280: strcpy (bufp, "M-x "); ! 281: bufp += 4; ! 282: } ! 283: else ! 284: { /* function is on a key */ ! 285: key = Fkey_description (key); ! 286: funp = XSTRING (key)->data; ! 287: func = XSTRING (key)->size; ! 288: } ! 289: ! 290: subst: ! 291: new = (unsigned char *) xrealloc (buf, bsize += func); ! 292: bufp += new - buf; ! 293: buf = new; ! 294: bcopy (funp, bufp, func); ! 295: bufp += func; ! 296: } ! 297: else if (strp[0] == '\\' && strp[1] == '{') ! 298: { ! 299: didone = 1; ! 300: strp += 2; /* skip \( */ ! 301: funp = strp; ! 302: ! 303: while (strp < send && *strp != '}') ! 304: strp++; ! 305: func = strp - funp; ! 306: strp++; /* skip } */ ! 307: ! 308: oldbuf = bf_cur; ! 309: SetBfp (XBUFFER (Vprin1_to_string_buffer)); ! 310: key = Fintern (make_string (funp, func), Qnil); ! 311: if ((tem = (Fboundp (key)), NULL (tem)) || ! 312: (tem = (Fsymbol_value (key)), NULL (tem))) ! 313: { ! 314: key = Fsymbol_name (key); ! 315: InsStr ("\nUses keymap \""); ! 316: InsCStr (XSTRING (key)->data, XSTRING (key)->size); ! 317: InsStr ("\", which is not currently defined.\n"); ! 318: } ! 319: else ! 320: { ! 321: key = Fsymbol_value (key); ! 322: describe_map_tree (key, 1); ! 323: } ! 324: key = Fbuffer_string (); ! 325: Ferase_buffer (); ! 326: SetBfp (oldbuf); ! 327: funp = XSTRING (key)->data; ! 328: func = XSTRING (key)->size; ! 329: goto subst; ! 330: } ! 331: else /* just copy other chars */ ! 332: *bufp++ = *strp++; ! 333: } ! 334: ! 335: if (didone) /* don't bother if nothing substituted */ ! 336: key = make_string (buf, bufp - buf); ! 337: else ! 338: key = str; ! 339: free (buf); ! 340: return key; ! 341: } ! 342: ! 343: syms_of_doc () ! 344: { ! 345: staticpro (&Vdoc_file_name); ! 346: Vdoc_file_name = Qnil; ! 347: ! 348: defsubr (&Sdocumentation); ! 349: defsubr (&Ssnarf_documentation); ! 350: defsubr (&Ssubstitute_command_keys); ! 351: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.