Annotation of GNUtools/emacs/src/callint.c, revision 1.1

1.1     ! root        1: /* Call a Lisp function interactively.
        !             2:    Copyright (C) 1985, 1986, 1992 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: #include "lisp.h"
        !            23: #include "buffer.h"
        !            24: #include "commands.h"
        !            25: #include "window.h"
        !            26: 
        !            27: extern Lisp_Object global_map;
        !            28: 
        !            29: extern int num_input_chars;
        !            30: 
        !            31: Lisp_Object Vprefix_arg, Vcurrent_prefix_arg, Qminus;
        !            32: Lisp_Object Qcall_interactively;
        !            33: Lisp_Object Vcommand_history;
        !            34: 
        !            35: extern Lisp_Object ml_apply ();
        !            36: extern Lisp_Object Fread_buffer (), Fread_key_sequence (), Fread_file_name ();
        !            37: 
        !            38: /* This comment supplies the doc string for interactive,
        !            39:    for make-docfile to see.  We cannot put this in the real DEFUN
        !            40:    due to limits in the Unix cpp.
        !            41: 
        !            42: DEFUN ("interactive", Ffoo, Sfoo, 0, 0, 0,
        !            43:  "Specify a way of parsing arguments for interactive use of a function.\n\
        !            44: For example, write\n\
        !            45:   (defun fun (arg) \"Doc string\" (interactive \"p\") ...use arg...)\n\
        !            46: to make arg be the prefix numeric argument when foo is called as a command.\n\
        !            47: This is actually a declaration rather than a function;\n\
        !            48:  it tells  call-interactively  how to read arguments\n\
        !            49:  to pass to the function.\n\
        !            50: When actually called,  interactive  just returns nil.\n\
        !            51: \n\
        !            52: The argument of  interactive  is usually a string containing a code letter\n\
        !            53:  followed by a prompt.  (Some code letters do not use I/O to get\n\
        !            54:  the argument and do not need prompts.)  To prompt for multiple arguments,\n\
        !            55:  give a code letter, its prompt, a newline, and another code letter, etc.\n\
        !            56: If the argument is not a string, it is evaluated to get a list of\n\
        !            57:  arguments to pass to the function.\n\
        !            58: Just  (interactive)  means pass no args when calling interactively.\n\
        !            59: \nCode letters available are:\n\
        !            60: a -- Function name: symbol with a function definition.\n\
        !            61: b -- Name of existing buffer.\n\
        !            62: B -- Name of buffer, possibly nonexistent.\n\
        !            63: c -- Character.\n\
        !            64: C -- Command name: symbol with interactive function definition.\n\
        !            65: d -- Value of point as number.  Does not do I/O.\n\
        !            66: D -- Directory name.\n\
        !            67: f -- Existing file name.\n\
        !            68: F -- Possibly nonexistent file name.\n\
        !            69: k -- Key sequence (string).\n\
        !            70: m -- Value of mark as number.  Does not do I/O.\n\
        !            71: n -- Number read using minibuffer.\n\
        !            72: N -- Prefix arg converted to number, or if none, do like code `n'.\n\
        !            73: p -- Prefix arg converted to number.  Does not do I/O.\n\
        !            74: P -- Prefix arg in raw form.  Does not do I/O.\n\
        !            75: r -- Region: point and mark as 2 numeric args, smallest first.  Does no I/O.\n\
        !            76: s -- Any string.\n\
        !            77: S -- Any symbol.\n\
        !            78: v -- Variable name: symbol that is user-variable-p.\n\
        !            79: x -- Lisp expression read but not evaluated.\n\
        !            80: X -- Lisp expression read and evaluated.\n\
        !            81: In addition, if the first character of the string is '*' then an error is\n\
        !            82:  signaled if the buffer is read-only.\n\
        !            83:  This happens before reading any arguments.")
        !            84: */
        !            85: 
        !            86: /* ARGSUSED */
        !            87: DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0,
        !            88:   0 /* See immediately above */)
        !            89:   (args)
        !            90:      Lisp_Object args;
        !            91: {
        !            92:   return Qnil;
        !            93: }
        !            94: 
        !            95: /* Quotify EXP: if EXP is constant, return it.
        !            96:    If EXP is not constant, return (quote EXP).  */
        !            97: Lisp_Object
        !            98: quotify_arg (exp)
        !            99:      register Lisp_Object exp;
        !           100: {
        !           101:   if (XTYPE (exp) != Lisp_Int && XTYPE (exp) != Lisp_String
        !           102:       && !NULL (exp) && !EQ (exp, Qt))
        !           103:     return Fcons (Qquote, Fcons (exp, Qnil));
        !           104: 
        !           105:   return exp;
        !           106: }
        !           107: 
        !           108: /* Modify EXP by quotifying each element (except the first).  */
        !           109: Lisp_Object
        !           110: quotify_args (exp)
        !           111:      Lisp_Object exp;
        !           112: {
        !           113:   register Lisp_Object tail;
        !           114:   register struct Lisp_Cons *ptr;
        !           115:   for (tail = exp; CONSP (tail); tail = ptr->cdr)
        !           116:     {
        !           117:       ptr = XCONS (tail);
        !           118:       ptr->car = quotify_arg (ptr->car);
        !           119:     }
        !           120:   return exp;
        !           121: }
        !           122: 
        !           123: char *callint_argfuns[]
        !           124:     = {"", "point", "mark", "region-beginning", "region-end"};
        !           125: 
        !           126: static void
        !           127: check_mark ()
        !           128: {
        !           129:   Lisp_Object tem = Fmarker_buffer (current_buffer->mark);
        !           130:   if (NULL (tem) || (XBUFFER (tem) != current_buffer))
        !           131:     error ("The mark is not set now");
        !           132: }
        !           133: 
        !           134: 
        !           135: DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 2, 0,
        !           136:   "Call FUNCTION, reading args according to its interactive calling specs.\n\
        !           137: The function contains a specification of how to do the argument reading.\n\
        !           138: In the case of user-defined functions, this is specified by placing a call\n\
        !           139: to the function `interactive' at the top level of the function body.\n\
        !           140: See `interactive'.\n\
        !           141: \n\
        !           142: Optional second arg RECORD-FLAG non-nil\n\
        !           143: means unconditionally put this command in the command-history.\n\
        !           144: Otherwise, this is done only if an arg is read using the minibuffer.")
        !           145:   (function, record)
        !           146:      Lisp_Object function, record;
        !           147: {
        !           148:   Lisp_Object *args, *visargs;
        !           149:   unsigned char **argstrings;
        !           150:   Lisp_Object fun;
        !           151:   Lisp_Object funcar;
        !           152:   Lisp_Object specs;
        !           153:   Lisp_Object teml;
        !           154: 
        !           155:   Lisp_Object prefix_arg;
        !           156:   unsigned char *string;
        !           157:   unsigned char *tem;
        !           158:   int *varies;
        !           159:   register int i, j;
        !           160:   int count, foo;
        !           161:   char prompt[100];
        !           162:   char prompt1[100];
        !           163:   char *tem1;
        !           164:   int arg_from_tty = 0;
        !           165:   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
        !           166:   extern char *index ();
        !           167: 
        !           168:   /* Save this now, since use ofminibuffer will clobber it. */
        !           169:   prefix_arg = Vcurrent_prefix_arg;
        !           170: 
        !           171:  retry:
        !           172: 
        !           173:   for (fun = function;
        !           174:        XTYPE (fun) == Lisp_Symbol && !EQ (fun, Qunbound);
        !           175:        fun = XSYMBOL (fun)->function)
        !           176:     {
        !           177:       QUIT;
        !           178:     }
        !           179: 
        !           180:   if (XTYPE (fun) == Lisp_Subr)
        !           181:     {
        !           182:       string = (unsigned char *) XSUBR (fun)->prompt;
        !           183:       if (!string)
        !           184:        {
        !           185:        lose:
        !           186:          function = wrong_type_argument (Qcommandp, function, 0);
        !           187:          goto retry;
        !           188:        }
        !           189:       else if ((int) string == 1)
        !           190:        return call0 (function);
        !           191:     }
        !           192:   else if (!CONSP (fun))
        !           193:     goto lose;
        !           194:   else if (funcar = Fcar (fun), EQ (funcar, Qautoload))
        !           195:     {
        !           196:       GCPRO2 (function, prefix_arg);
        !           197:       do_autoload (fun, function);
        !           198:       UNGCPRO;
        !           199:       goto retry;
        !           200:     }
        !           201:   else if (EQ (funcar, Qlambda))
        !           202:     {
        !           203:       specs = Fassq (Qinteractive, Fcdr (Fcdr (fun)));
        !           204:       if (NULL (specs))
        !           205:        goto lose;
        !           206:       specs = Fcar (Fcdr (specs));
        !           207:       if (XTYPE (specs) == Lisp_String)
        !           208:        {
        !           209:          /* Make a copy of string so that if a GC relocates specs,
        !           210:             `string' will still be valid.  */
        !           211:          string = (unsigned char *) alloca (XSTRING (specs)->size + 1);
        !           212:          bcopy (XSTRING (specs)->data, string, XSTRING (specs)->size + 1);
        !           213:        }
        !           214:       else
        !           215:        {
        !           216:          i = num_input_chars;
        !           217:          specs = Feval (specs);
        !           218:          if (i != num_input_chars || !NULL (record))
        !           219:            Vcommand_history
        !           220:              = Fcons (Fcons (function, quotify_args (Fcopy_sequence (specs))),
        !           221:                       Vcommand_history);
        !           222:          return apply1 (function, specs);
        !           223:        }
        !           224:     }
        !           225:   else if (EQ (funcar, Qmocklisp))
        !           226:     return ml_apply (fun, Qinteractive);
        !           227:   else
        !           228:     goto lose;
        !           229: 
        !           230:   /* Here if function specifies a string to control parsing the defaults */
        !           231: 
        !           232:   /* First character '*' means barf if buffer read-only */
        !           233:   if (*string == '*')
        !           234:     {
        !           235:       string++;
        !           236:       if (!NULL (current_buffer->read_only))
        !           237:        Fbarf_if_buffer_read_only ();
        !           238:     }
        !           239: 
        !           240:   tem = string;
        !           241:   for (j = 0; *tem; j++)
        !           242:     {
        !           243:       if (*tem == 'r') j++;
        !           244:       tem = (unsigned char *) index (tem, '\n');
        !           245:       if (tem) tem++;
        !           246:       else tem = (unsigned char *) "";
        !           247:     }
        !           248:   count = j;
        !           249: 
        !           250:   args = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object));
        !           251:   visargs = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object));
        !           252:   argstrings = (unsigned char **) alloca ((count + 1) * sizeof (char *));
        !           253:   varies = (int *) alloca ((count + 1) * sizeof (int));
        !           254: 
        !           255:   for (i = 0; i < (count + 1); i++)
        !           256:     {
        !           257:       args[i] = Qnil;
        !           258:       visargs[i] = Qnil;
        !           259:       varies[i] = 0;
        !           260:     }
        !           261: 
        !           262:   GCPRO4 (prefix_arg, function, *args, *visargs);
        !           263:   gcpro3.nvars = (count + 1);
        !           264:   gcpro4.nvars = (count + 1);
        !           265: 
        !           266:   tem = string;
        !           267:    for (i = 1; *tem; i++)
        !           268:     {
        !           269:       strncpy (prompt1, tem + 1, sizeof prompt1 - 1);
        !           270:       prompt1[sizeof prompt1 - 1] = 0;
        !           271:       tem1 = index (prompt1, '\n');
        !           272:       if (tem1) *tem1 = 0;
        !           273:       /* Fill argstrings with a vector of C strings
        !           274:         corresponding to the Lisp strings in visargs.  */
        !           275:       for (j = 1; j < i; j++)
        !           276:        argstrings[j]
        !           277:          = EQ (visargs[j], Qnil)
        !           278:            ? (unsigned char *) ""
        !           279:            : XSTRING (visargs[j])->data;
        !           280: 
        !           281:       doprnt (prompt, sizeof prompt, prompt1, j - 1, argstrings + 1);
        !           282: 
        !           283:       switch (*tem)
        !           284:        {
        !           285:        case 'a':               /* Symbol defined as a function */
        !           286:          visargs[i] = Fcompleting_read (build_string (prompt),
        !           287:                                         Vobarray, Qfboundp, Qt, Qnil);
        !           288:          /* Passing args[i] directly stimulates compiler bug */
        !           289:          teml = visargs[i];
        !           290:          args[i] = Fintern (teml, Qnil);
        !           291:          break;
        !           292: 
        !           293:        case 'b':               /* Name of existing buffer */
        !           294:          args[i] = Fcurrent_buffer ();
        !           295:          if (EQ (selected_window, minibuf_window))
        !           296:            args[i] = Fother_buffer (args[i]);
        !           297:          args[i] = Fread_buffer (build_string (prompt), args[i], Qt);
        !           298:          break;
        !           299: 
        !           300:        case 'B':               /* Name of buffer, possibly nonexistent */
        !           301:          args[i] = Fread_buffer (build_string (prompt),
        !           302:                                  Fother_buffer (Fcurrent_buffer ()), Qnil);
        !           303:          break;
        !           304: 
        !           305:         case 'c':              /* Character */
        !           306:          message1 (prompt);
        !           307:          args[i] = Fread_char ();
        !           308:          /* Passing args[i] directly stimulates compiler bug */
        !           309:          teml = args[i];
        !           310:          visargs[i] = Fchar_to_string (teml);
        !           311:          break;
        !           312: 
        !           313:        case 'C':               /* Command: symbol with interactive function */
        !           314:          visargs[i] = Fcompleting_read (build_string (prompt),
        !           315:                                         Vobarray, Qcommandp, Qt, Qnil);
        !           316:          /* Passing args[i] directly stimulates compiler bug */
        !           317:          teml = visargs[i];
        !           318:          args[i] = Fintern (teml, Qnil);
        !           319:          break;
        !           320: 
        !           321:        case 'd':               /* Value of point.  Does not do I/O.  */
        !           322:          XFASTINT (args[i]) = point;
        !           323:          /* visargs[i] = Qnil; */
        !           324:          varies[i] = 1;
        !           325:          break;
        !           326: 
        !           327:        case 'D':               /* Directory name. */
        !           328:          args[i] = Fread_file_name (build_string (prompt), Qnil,
        !           329:                                     current_buffer->directory, Qlambda);
        !           330:          break;
        !           331: 
        !           332:        case 'f':               /* Existing file name. */
        !           333:          /* On VMS, treat 'f' like 'F', because 'f' fails to work
        !           334:             for multivalued logical names or for explicit versions.  */
        !           335: #ifndef VMS
        !           336:          args[i] = Fread_file_name (build_string (prompt),
        !           337:                                     Qnil, Qnil, Qlambda);
        !           338:          break;
        !           339: #endif
        !           340: 
        !           341:        case 'F':               /* Possibly nonexistent file name. */
        !           342:          args[i] = Fread_file_name (build_string (prompt),
        !           343:                                     Qnil, Qnil, Qnil);
        !           344:          break;
        !           345: 
        !           346:        case 'k':               /* Key sequence (string) */
        !           347:          args[i] = Fread_key_sequence (build_string (prompt));
        !           348:          teml = args[i];
        !           349:          visargs[i] = Fkey_description (teml);
        !           350:          break;
        !           351: 
        !           352:        case 'm':               /* Value of mark.  Does not do I/O.  */
        !           353:          check_mark ();
        !           354:          /* visargs[i] = Qnil; */
        !           355:          XFASTINT (args[i]) = marker_position (current_buffer->mark);
        !           356:          varies[i] = 2;
        !           357:          break;
        !           358: 
        !           359:        case 'N':               /* Prefix arg, else number from minibuffer */
        !           360:          if (!NULL (prefix_arg))
        !           361:            goto have_prefix_arg;
        !           362:        case 'n':               /* Read number from minibuffer.  */
        !           363:          do
        !           364:            args[i] = Fread_minibuffer (build_string (prompt), Qnil);
        !           365:          while (XTYPE (args[i]) != Lisp_Int);
        !           366:          visargs[i] = last_minibuf_string;
        !           367:          break;
        !           368: 
        !           369:        case 'P':               /* Prefix arg in raw form.  Does no I/O.  */
        !           370:          args[i] = prefix_arg;
        !           371:          /* visargs[i] = Qnil; */
        !           372:          varies[i] = -1;
        !           373:          break;
        !           374: 
        !           375:        case 'p':               /* Prefix arg converted to number.  No I/O. */
        !           376:        have_prefix_arg:
        !           377:          args[i] = Fprefix_numeric_value (prefix_arg);
        !           378:          /* visargs[i] = Qnil; */
        !           379:          varies[i] = -1;
        !           380:          break;
        !           381: 
        !           382:        case 'r':               /* Region, point and mark as 2 args. */
        !           383:          check_mark ();
        !           384:          /* visargs[i+1] = Qnil; */
        !           385:          foo = marker_position (current_buffer->mark);
        !           386:          /* visargs[i] = Qnil; */
        !           387:          XFASTINT (args[i]) = point < foo ? point : foo;
        !           388:          varies[i] = 3;
        !           389:          XFASTINT (args[++i]) = point > foo ? point : foo;
        !           390:          varies[i] = 4;
        !           391:          break;
        !           392: 
        !           393:        case 's':               /* String read via minibuffer.  */
        !           394:          args[i] = Fread_string (build_string (prompt), Qnil);
        !           395:          break;
        !           396: 
        !           397:        case 'S':               /* Any symbol.  */
        !           398:          visargs[i] = read_minibuf (Vminibuffer_local_ns_map,
        !           399:                                     Qnil,
        !           400:                                     build_string (prompt),
        !           401:                                     0);
        !           402:          /* Passing args[i] directly stimulates compiler bug */
        !           403:          teml = visargs[i];
        !           404:          args[i] = Fintern (teml, Qnil);
        !           405:          break;
        !           406: 
        !           407:        case 'v':               /* Variable name: symbol that is
        !           408:                                   user-variable-p. */
        !           409:          args[i] = Fread_variable (build_string (prompt));
        !           410:          visargs[i] = last_minibuf_string;
        !           411:          break;
        !           412: 
        !           413:        case 'x':               /* Lisp expression read but not evaluated */
        !           414:          args[i] = Fread_minibuffer (build_string (prompt), Qnil);
        !           415:          visargs[i] = last_minibuf_string;
        !           416:          break;
        !           417: 
        !           418:        case 'X':               /* Lisp expression read and evaluated */
        !           419:          args[i] = Feval_minibuffer (build_string (prompt), Qnil);
        !           420:          visargs[i] = last_minibuf_string;
        !           421:          break;
        !           422: 
        !           423:        default:
        !           424:          error ("Invalid control letter \"%c\" (%03o) in interactive calling string",
        !           425:                 *tem, *tem);
        !           426:        }
        !           427: 
        !           428:       if (varies[i] == 0)
        !           429:        arg_from_tty = 1;
        !           430: 
        !           431:       if (NULL (visargs[i]) && XTYPE (args[i]) == Lisp_String)
        !           432:        visargs[i] = args[i];
        !           433: 
        !           434:       tem = (unsigned char *) index (tem, '\n');
        !           435:       if (tem) tem++;
        !           436:       else tem = (unsigned char *) "";
        !           437:     }
        !           438: 
        !           439:   QUIT;
        !           440: 
        !           441:   args[0] = function;
        !           442: 
        !           443:   if (arg_from_tty || !NULL (record))
        !           444:     {
        !           445:       visargs[0] = function;
        !           446:       for (i = 1; i < count + 1; i++)
        !           447:        if (varies[i] > 0)
        !           448:          visargs[i] = Fcons (intern (callint_argfuns[varies[i]]), Qnil);
        !           449:        else
        !           450:          visargs[i] = quotify_arg (args[i]);
        !           451:       Vcommand_history = Fcons (Flist (count + 1, visargs),
        !           452:                                Vcommand_history);
        !           453:     }
        !           454: 
        !           455:   teml = Ffuncall (count + 1, args);
        !           456:   UNGCPRO;
        !           457:   return teml;
        !           458: }  
        !           459: 
        !           460: DEFUN ("prefix-numeric-value", Fprefix_numeric_value, Sprefix_numeric_value,
        !           461:   1, 1, 0,
        !           462:   "Return numeric meaning of raw prefix argument ARG.\n\
        !           463: A raw prefix argument is what you get from (interactive \"P\").")
        !           464:   (raw)
        !           465:      Lisp_Object raw;
        !           466: {
        !           467:   Lisp_Object val;
        !           468:   
        !           469:   if (NULL (raw))
        !           470:     XFASTINT (val) = 1;
        !           471:   else if (XTYPE (raw) == Lisp_Symbol)
        !           472:     {
        !           473:       XFASTINT (val) = 0;
        !           474:       XSETINT (val, -1);
        !           475:     }
        !           476:   else if (CONSP (raw))
        !           477:     val = XCONS (raw)->car;
        !           478:   else if (XTYPE (raw) == Lisp_Int)
        !           479:     val = raw;
        !           480:   else
        !           481:     XFASTINT (val) = 1;
        !           482: 
        !           483:   return val;
        !           484: }
        !           485: 
        !           486: syms_of_callint ()
        !           487: {
        !           488:   Qminus = intern ("-");
        !           489:   staticpro (&Qminus);
        !           490: 
        !           491:   Qcall_interactively = intern ("call-interactively");
        !           492:   staticpro (&Qcall_interactively);
        !           493: 
        !           494:   DEFVAR_LISP ("prefix-arg", &Vprefix_arg,
        !           495:     "The value of the prefix argument for the next editing command.\n\
        !           496: It may be a number, or the symbol - for just a minus sign as arg,\n\
        !           497: or a list whose car is a number for just one or more C-U's\n\
        !           498: or nil if no argument has been specified.\n\
        !           499: \n\
        !           500: You cannot examine this variable to find the argument for this command\n\
        !           501: since it has been set to nil by the time you can look.\n\
        !           502: Instead, you should use the variable current-prefix-arg, although\n\
        !           503: normally commands can get this prefix argument with (interactive \"P\").");
        !           504:   Vprefix_arg = Qnil;
        !           505: 
        !           506:   DEFVAR_LISP ("current-prefix-arg", &Vcurrent_prefix_arg,
        !           507:     "The value of the prefix argument for this editing command.\n\
        !           508: It may be a number, or the symbol - for just a minus sign as arg,\n\
        !           509: or a list whose car is a number for just one or more C-U's\n\
        !           510: or nil if no argument has been specified.\n\
        !           511: This is what (interactive \"P\") returns.");
        !           512:   Vcurrent_prefix_arg = Qnil;
        !           513: 
        !           514:   DEFVAR_LISP ("command-history", &Vcommand_history,
        !           515:     "List of recent commands that read arguments from terminal.\n\
        !           516: Each command is represented as a form to evaluate.");
        !           517:   Vcommand_history = Qnil;
        !           518: 
        !           519:   defsubr (&Sinteractive);
        !           520:   defsubr (&Scall_interactively);
        !           521:   defsubr (&Sprefix_numeric_value);
        !           522: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.