# 2.11BSD#431 - /usr/src/bin/tcsh/ed.inputl.c

##### Functions

    G_N_Char          X
    Inputl            X
    PushMacro         X

##### Macros

    OKCMD             X
    TRY_AGAIN         X

       1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/ed.inputl.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
       2: /*
       3:  * ed.inputl.c: Input line handling.
       4:  */
       5: /*-
       6:  * Copyright (c) 1980, 1991 The Regents of the University of California.
       7:  * All rights reserved.
       8:  *
       9:  * Redistribution and use in source and binary forms, with or without
      10:  * modification, are permitted provided that the following conditions
      11:  * are met:
      12:  * 1. Redistributions of source code must retain the above copyright
      13:  *    notice, this list of conditions and the following disclaimer.
      14:  * 2. Redistributions in binary form must reproduce the above copyright
      15:  *    notice, this list of conditions and the following disclaimer in the
      16:  *    documentation and/or other materials provided with the distribution.
      17:  * 3. All advertising materials mentioning features or use of this software
      18:  *    must display the following acknowledgement:
      19:  *	This product includes software developed by the University of
      20:  *	California, Berkeley and its contributors.
      21:  * 4. Neither the name of the University nor the names of its contributors
      22:  *    may be used to endorse or promote products derived from this software
      23:  *    without specific prior written permission.
      24:  *
      25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      35:  * SUCH DAMAGE.
      36:  */
      37: #include "config.h"
      38: #if !defined(lint) && !defined(pdp11)
      39: static char *rcsid()
      40:     { return "$Id: ed.inputl.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
      41: #endif
      42:
      43: #include "sh.h"
      44: #include "ed.h"
      45: #include "ed.defns.h"       /* for the function names */
      46: #include "tw.h"         /* for twenex stuff */
      47:
      48: #define OKCMD (INBUFSIZ+INBUFSIZ)
      49: extern CCRETVAL e_up_hist();
      50: extern CCRETVAL e_ex_history();
      51:
      52: /* ed.inputl -- routines to get a single line from the input. */
      53:
      54: extern bool tellwhat;
      55: extern bool MapsAreInited;
      56: extern bool Tty_raw_mode;
      57:
      58: /* mismatched first character */
      59: static Char mismatch[] = {'!', '\\', '^', '-', '%', '\0'};
      60:
      61: static  int G_N_Command __P((KEYCMD *, Char *));
      62: static  int SpellLine   __P((int));
      63:
      64: /* CCRETVAL */
      65: int
      66: Inputl()
      67: {
      68:     CCRETVAL retval;
      69:     KEYCMD  cmdnum = 0;
      70:     extern KEYCMD NumFuns;
      71:     unsigned char tch;      /* the place where read() goes */
      72:     Char    ch;
      73:     int     num;        /* how many chars we have read at NL */
      74:     struct varent *crct = adrof(STRcorrect);
      75:     struct varent *matchbeep = adrof(STRmatchbeep);
      76:     Char   *SaveChar, *CorrChar;
      77:     Char    Origin[INBUFSIZ], Change[INBUFSIZ];
      78:     int     matchval;       /* from tenematch() */
      79:
      80:     if (!MapsAreInited)     /* double extra just in case */
      81:     ed_IMaps();
      82:
      83:     ClearDisp();        /* reset the display stuff */
      84:     ResetInLine();      /* reset the input pointers */
      85:     if (GettingInput)
      86:     MacroLvl = -1;      /* editor was interrupted during input */
      87:
      88: #ifdef FIONREAD
      89:     if (!Tty_raw_mode && MacroLvl < 0) {
      90:     long    chrs = 0;
      91:
      92:     (void) ioctl(SHIN, FIONREAD, (ioctl_t) & chrs);
      93:     if (chrs == 0) {
      94:         if (Rawmode() < 0)
      95:         return 0;
      96:     }
      97:     }
      98: #endif
      99:
     100:     GettingInput = 1;
     101:     NeedsRedraw = 0;
     102:
     103:     if (tellwhat) {
     104:     copyn(InputBuf, WhichBuf, INBUFSIZ);
     105:     LastChar = InputBuf + (LastWhich - WhichBuf);
     106:     Cursor = InputBuf + (CursWhich - WhichBuf);
     107:     tellwhat = 0;
     108:     Hist_num = HistWhich;
     109:     }
     110:     if (Expand) {
     111:     (void) e_up_hist();
     112:     Expand = 0;
     113:     }
     114:     Refresh();          /* print the prompt */
     115:
     116:     for (num = OKCMD; num == OKCMD;) {  /* while still editing this line */
     117: #ifdef DEBUG_EDIT
     118:     if (Cursor > LastChar)
     119:         xprintf("Cursor > LastChar\r\n");
     120:     if (Cursor < InputBuf)
     121:         xprintf("Cursor < InputBuf\r\n");
     122:     if (Cursor > InputLim)
     123:         xprintf("Cursor > InputLim\r\n");
     124:     if (LastChar > InputLim)
     125:         xprintf("LastChar > InputLim\r\n");
     126:     if (InputLim != &InputBuf[INBUFSIZ - 2])
     127:         xprintf("InputLim != &InputBuf[INBUFSIZ-2]\r\n");
     128:     if ((!DoingArg) && (Argument != 1))
     129:         xprintf("(!DoingArg) && (Argument != 1)\r\n");
     130:     if (CcKeyMap[0] == 0)
     131:         xprintf("CcKeyMap[0] == 0 (maybe not inited)\r\n");
     132: #endif
     133:
     134:     /* if EOF or error */
     135:     if ((num = G_N_Command(&cmdnum, &ch)) != OKCMD) {
     136:         break;
     137:     }
     138:
     139:     if (cmdnum >= NumFuns) {/* BUG CHECK command */
     140: #ifdef DEBUG_EDIT
     141:         xprintf("ERROR: illegal command from key 0%o\r\n", ch);
     142: #endif
     143:         continue;       /* try again */
     144:     }
     145:
     146:     /* now do the real command */
     147:     retval = (*CcFuncTbl[cmdnum]) (ch);
     148:
     149:     /* save the last command here */
     150:     LastCmd = cmdnum;
     151:
     152:     /* use any return value */
     153:     switch (retval) {
     154:
     155:     case CC_REFRESH:
     156:         Refresh();
     157:         /* fall through */
     158:     case CC_NORM:       /* normal char */
     159:         Argument = 1;
     160:         DoingArg = 0;
     161:         /* fall through */
     162:     case CC_ARGHACK:    /* Suggested by Rich Salz */
     163:         /* <rsalz@pineapple.bbn.com> */
     164:         break;      /* keep going... */
     165:
     166:     case CC_EOF:        /* end of file typed */
     167: #ifdef notdef
     168:         PromptBuf[0] = '\0';
     169: #endif
     170:         num = 0;
     171:         break;
     172:
     173:     case CC_WHICH:      /* tell what this command does */
     174:         tellwhat = 1;
     175:         copyn(WhichBuf, InputBuf, INBUFSIZ);
     176:         LastWhich = WhichBuf + (LastChar - InputBuf);
     177:         CursWhich = WhichBuf + (Cursor - InputBuf);
     178:         *LastChar++ = '\n'; /* for the benifit of CSH */
     179:         HistWhich = Hist_num;
     180:         Hist_num = 0;   /* for the history commands */
     181:         num = LastChar - InputBuf;  /* number characters read */
     182: #ifdef notdef
     183:         ResetInLine();  /* reset the input pointers */
     184: #endif
     185:         break;
     186:
     187:     case CC_NEWLINE:    /* normal end of line */
     188:         if (crct && (!Strcmp(*(crct->vec), STRcmd) ||
     189:              !Strcmp(*(crct->vec), STRall))) {
     190:         (void) Strcpy(Origin, InputBuf);
     191:         SaveChar = LastChar;
     192:         if (SpellLine(!Strcmp(*(crct->vec), STRcmd)) == 1) {
     193:             (void) Strcpy(Change, InputBuf);
     194:             *Strchr(Change, '\n') = '\0';
     195:             CorrChar = LastChar;    /* Save the corrected end */
     196:             LastChar = InputBuf;    /* Null the current line */
     197:             Beep();
     198:             printprompt(2, Change);
     199:             Refresh();
     200:             (void) read(SHIN, (char *) &tch, 1);
     201:             ch = tch;
     202:             if (ch != 'y' && ch != ' ') {
     203:             (void) Strcpy(InputBuf, Origin);
     204:             LastChar = SaveChar;
     205:             xprintf("no\n");
     206:             }
     207:             else {
     208:             LastChar = CorrChar;    /* Restore the corrected end */
     209:             xprintf("yes\n");
     210:             }
     211:             flush();
     212:         }
     213:         }           /* end CORRECT code */
     214:         tellwhat = 0;   /* just in case */
     215:         Hist_num = 0;   /* for the history commands */
     216:         num = LastChar - InputBuf;  /* return the number of chars read */
     217:         /*
     218: 	     * For continuation lines, we set the prompt to prompt 2
     219: 	     */
     220:         printprompt(1, NULL);
     221: #ifdef notdef
     222:         ResetInLine();  /* reset the input pointers */
     223:         PromptBuf[0] = '\0';
     224: #endif
     225:         break;
     226:
     227:     case CC_CORRECT:
     228:         if (tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf,
     229:               SPELL) < 0)
     230:         Beep();     /* Beep = No match/ambiguous */
     231:         if (NeedsRedraw) {
     232:         ClearLines();
     233:         ClearDisp();
     234:         NeedsRedraw = 0;
     235:         }
     236:         Refresh();
     237:         Argument = 1;
     238:         DoingArg = 0;
     239:         break;
     240:
     241:     case CC_CORRECT_L:
     242:         if (SpellLine(FALSE) < 0)
     243:         Beep();     /* Beep = No match/ambiguous */
     244:         if (NeedsRedraw) {
     245:         ClearLines();
     246:         ClearDisp();
     247:         NeedsRedraw = 0;
     248:         }
     249:         Refresh();
     250:         Argument = 1;
     251:         DoingArg = 0;
     252:         break;
     253:
     254:
     255:     case CC_COMPLETE:
     256:         if (adrof(STRa_expand))
     257:         (void) e_ex_history();
     258:         /*
     259: 	     * Modified by Martin Boyer (gamin@ireq-robot.hydro.qc.ca):
     260: 	     * A separate variable now controls beeping after
     261: 	     * completion, independently of autolisting.
     262: 	     */
     263:         switch (matchval =
     264:             tenematch(InputBuf, INBUFSIZ, Cursor-InputBuf, RECOGNIZE)) {
     265:         case 1:
     266:         if (non_unique_match && matchbeep &&
     267:             (Strcmp(*(matchbeep->vec), STRnotunique) == 0))
     268:             Beep();
     269:         break;
     270:         case 0:
     271:         if (matchbeep) {
     272:             if (Strcmp(*(matchbeep->vec), STRnomatch) == 0 ||
     273:             Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
     274:             Strcmp(*(matchbeep->vec), STRnotunique) == 0)
     275:             Beep();
     276:         }
     277:         else
     278:             Beep();
     279:         break;
     280:         default:
     281:         if (matchval < 0)   /* Error from tenematch */
     282:             Beep();
     283:         else if (matchbeep) {
     284:             if ((Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
     285:              Strcmp(*(matchbeep->vec), STRnotunique) == 0))
     286:             Beep();
     287:         }
     288:         else
     289:             Beep();
     290:         /*
     291: 		 * Addition by David C Lawrence <tale@pawl.rpi.edu>: If an
     292: 		 * attempted completion is ambiguous, list the choices.
     293: 		 * (PWP: this is the best feature addition to tcsh I have
     294: 		 * seen in many months.)
     295: 		 */
     296:         if (adrof(STRa_list)) {
     297:             PastBottom();
     298:             (void) tenematch(InputBuf, INBUFSIZ, Cursor-InputBuf, LIST);
     299:         }
     300:         break;
     301:         }
     302:         if (NeedsRedraw) {
     303:         PastBottom();
     304:         ClearLines();
     305:         ClearDisp();
     306:         NeedsRedraw = 0;
     307:         }
     308:         Refresh();
     309:         Argument = 1;
     310:         DoingArg = 0;
     311:         break;
     312:
     313:     case CC_LIST_CHOICES:
     314:         /* should catch ^C here... */
     315:         (void) tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf, LIST);
     316:         Refresh();
     317:         Argument = 1;
     318:         DoingArg = 0;
     319:         break;
     320:
     321:     case CC_LIST_GLOB:
     322:         (void) tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf, GLOB);
     323:         Refresh();
     324:         Argument = 1;
     325:         DoingArg = 0;
     326:         break;
     327:
     328:     case CC_EXPAND_GLOB:
     329:         if (tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf,
     330:               GLOB_EXPAND) <= 0)
     331:         Beep();     /* Beep = No match */
     332:         if (NeedsRedraw) {
     333:         ClearLines();
     334:         ClearDisp();
     335:         NeedsRedraw = 0;
     336:         }
     337:         Refresh();
     338:         Argument = 1;
     339:         DoingArg = 0;
     340:         break;
     341:
     342:     case CC_EXPAND_VARS:
     343:         if (tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf,
     344:               VARS_EXPAND) <= 0)
     345:         Beep();     /* Beep = No match */
     346:         if (NeedsRedraw) {
     347:         ClearLines();
     348:         ClearDisp();
     349:         NeedsRedraw = 0;
     350:         }
     351:         Refresh();
     352:         Argument = 1;
     353:         DoingArg = 0;
     354:         break;
     355:
     356:     case CC_HELPME:
     357:         xputchar('\n');
     358:         /* should catch ^C here... */
     359:         (void) tenematch(InputBuf, INBUFSIZ, LastChar - InputBuf,
     360:                  PRINT_HELP);
     361:         Refresh();
     362:         Argument = 1;
     363:         DoingArg = 0;
     364:         break;
     365:
     366:     case CC_FATAL:      /* fatal error, reset to known state */
     367: #ifdef DEBUG_EDIT
     368:         xprintf("*** editor fatal ERROR ***\r\n\n");
     369: #endif				/* DEBUG_EDIT */
     370:         /* put (real) cursor in a known place */
     371:         ClearDisp();    /* reset the display stuff */
     372:         ResetInLine();  /* reset the input pointers */
     373:         Refresh();      /* print the prompt again */
     374:         Argument = 1;
     375:         DoingArg = 0;
     376:         break;
     377:
     378:     case CC_ERROR:
     379:     default:        /* functions we don't know about */
     380:         DoingArg = 0;
     381:         Argument = 1;
     382:         Beep();
     383:         flush();
     384:         break;
     385:     }
     386:     }
     387:     (void) Cookedmode();    /* make sure the tty is set up correctly */
     388:     GettingInput = 0;
     389:     flush();            /* flush any buffered output */
     390:     return num;
     391: }
     392:
     393: void
     394: PushMacro(str)
     395:     Char   *str;
     396: {
     397:     if (str != NULL && MacroLvl + 1 < MAXMACROLEVELS) {
     398:     MacroLvl++;
     399:     KeyMacro[MacroLvl] = str;
     400:     }
     401:     else {
     402:     Beep();
     403:     flush();
     404:     }
     405: }
     406:
     407: static int
     408: G_N_Command(cmdnum, ch)
     409:     KEYCMD *cmdnum;
     410:     register Char *ch;
     411: {
     412:     KEYCMD  cmd = 0;
     413:     int     num;
     414:     Char   *str;
     415:
     416:     for (; cmd == 0 || cmd == F_XKEY;) {
     417:     if ((num = G_N_Char(ch)) != 1) {    /* if EOF or error */
     418:         return num;
     419:     }
     420: #ifdef  KANJI
     421:     if (*ch & META) {
     422:         MetaNext = 0;
     423:         cmd = CcViMap[' '];
     424:         break;
     425:     }
     426:     else
     427: #endif				/* KANJI */
     428:     if (MetaNext) {
     429:         MetaNext = 0;
     430:         *ch |= META;
     431:     }
     432:     cmd = Cur_KeyMap[(unsigned char) *ch];
     433:     if (cmd == F_XKEY) {
     434:         if (GetXkey(ch, &str))
     435:         cmd = (KEYCMD) * str;
     436:         else
     437:         PushMacro(str);
     438:     }
     439:     if (!AltKeyMap) {
     440:         Cur_KeyMap = CcKeyMap;
     441:     }
     442:     }
     443:     *cmdnum = cmd;
     444:     return OKCMD;
     445: }
     446:
     447: int
     448: G_N_Char(cp)
     449:     register Char *cp;
     450: {
     451:     register int num_read;
     452:
     453: #if defined(EWOULDBLOCK) || (defined(POSIX) && defined(EAGAIN))
     454: # if defined(FIONBIO) || (defined(F_SETFL) && defined(O_NDELAY))
     455: #  define TRY_AGAIN
     456:     int     tried = 0;
     457:
     458: # endif				/* FIONBIO || (F_SETFL && O_NDELAY) */
     459: #endif				/* EWOULDBLOCK || (POSIX && EAGAIN) */
     460:     unsigned char tcp;
     461:
     462:     for (;;) {
     463:     if (MacroLvl < 0) {
     464:         if (!Load_input_line())
     465:         break;
     466:     }
     467:     if (*KeyMacro[MacroLvl] == 0) {
     468:         MacroLvl--;
     469:         continue;
     470:     }
     471:     *cp = *KeyMacro[MacroLvl]++ & CHAR;
     472:     if (*KeyMacro[MacroLvl] == 0) { /* Needed for QMode On */
     473:         MacroLvl--;
     474:     }
     475:     return (1);
     476:     }
     477:
     478:     if (Rawmode() < 0)      /* make sure the tty is set up correctly */
     479:     return 0;       /* oops: SHIN was closed */
     480:
     481:     while ((num_read = read(SHIN, (char *) &tcp, 1)) == -1)
     482:     switch (errno) {
     483:         /*
     484: 	     * Someone might have set our file descriptor to non blocking From
     485: 	     * Gray Watson (gray%antr.uucp@med.pitt.edu), Thanks!!!
     486: 	     */
     487: #ifdef EWOULDBLOCK
     488:     case EWOULDBLOCK:
     489: #endif				/* EWOULDBLOCK */
     490: #if defined(POSIX) && defined(EAGAIN)
     491: # if defined(EWOULDBLOCK) && EAGAIN != EWOULDBLOCK
     492:     case EAGAIN:
     493: # endif				/* EWOULDBLOCK && EAGAIN != EWOULDBLOCK */
     494: #endif				/* POSIX && EAGAIN */
     495: #ifdef TRY_AGAIN
     496:         if (!tried) {
     497: # if defined(F_SETFL) && defined(O_NDELAY)
     498:         (void) fcntl(SHIN, F_SETFL,
     499:                  fcntl(SHIN, F_GETFL, 0) & ~O_NDELAY);
     500: # endif				/* F_SETFL && O_NDELAY */
     501: # ifdef FIONBIO
     502:         (void) ioctl(SHIN, FIONBIO, (ioctl_t) & tried);
     503: # endif				/* FIONBIO */
     504:         tried = 1;
     505:         break;
     506:         }
     507: #endif
     508:         *cp = tcp;
     509:         return (num_read);
     510: #ifdef _SEQUENT_
     511:     case EBADF:
     512: #endif				/* _SEQUENT_ */
     513:     case EINTR:
     514:         break;
     515:     default:
     516:         xprintf("G_N_Char(): errno == %d\n", errno);
     517:         *cp = tcp;
     518:         return num_read;
     519:     }
     520:     *cp = tcp;
     521:     return num_read;
     522: }
     523:
     524: /*
     525:  * SpellLine - do spelling correction on the entire command line
     526:  * (which may have trailing newline).
     527:  * If cmdonly is set, only check spelling of command words.
     528:  * Return value:
     529:  * -1: Something was incorrectible, and nothing was corrected
     530:  *  0: Everything was correct
     531:  *  1: Something was corrected
     532:  */
     533: static int
     534: SpellLine(cmdonly)
     535:     int     cmdonly;
     536: {
     537:     int     endflag, matchval;
     538:     Char   *argptr, *OldCursor, *OldLastChar;
     539:
     540:     OldLastChar = LastChar;
     541:     OldCursor = Cursor;
     542:     argptr = InputBuf;
     543:     endflag = 1;
     544:     matchval = 0;
     545:     do {
     546:     while (ismeta(*argptr) || iscmdmeta(*argptr))
     547:         argptr++;
     548:     for (Cursor = argptr;
     549:          *Cursor != '\0' && !ismeta(*Cursor) && !iscmdmeta(*Cursor);
     550:          Cursor++);
     551:     if (*Cursor == '\0') {
     552:         Cursor = LastChar;
     553:         if (LastChar[-1] == '\n')
     554:         Cursor--;
     555:         endflag = 0;
     556:     }
     557:     if (!Strchr(mismatch, *argptr) &&
     558:         (!cmdonly || starting_a_command(argptr, InputBuf))) {
     559:         switch (tenematch(InputBuf, INBUFSIZ, Cursor - InputBuf, SPELL)) {
     560:         case 1:     /* corrected */
     561:         matchval = 1;
     562:         break;
     563:         case -1:        /* couldn't be corrected */
     564:         if (!matchval)
     565:             matchval = -1;
     566:         break;
     567:         default:        /* was correct */
     568:         break;
     569:         }
     570:         if (LastChar != OldLastChar) {
     571:         if (argptr < OldCursor)
     572:             OldCursor += (LastChar - OldLastChar);
     573:         OldLastChar = LastChar;
     574:         }
     575:     }
     576:     argptr = Cursor;
     577:     } while (endflag);
     578:     Cursor = OldCursor;
     579:     return matchval;
     580: }

#### Defined functions

G_N_Char defined in line 447; used 3 times

- in line 417
- in /usr/src/bin/tcsh/ed.inputl.c line 417
- in /usr/src/bin/tcsh/ed.xmap.c line 203

G_N_Command defined in line 407; used 1 times

- in line 135

Inputl defined in line 65; used 1 times

- in /usr/src/bin/tcsh/sh.lex.c line 1455

PushMacro defined in line 393; used 3 times

- in line 437
- in /usr/src/bin/tcsh/ed.init.c line 1019
- in /usr/src/bin/tcsh/ed.inputl.c line 437

SpellLine defined in line 533; used 2 times

- in line 192, 242

rcsid defined in line 39; never used

#### Defined variables

mismatch defined in line 59; used 1 times

- in line 557

#### Defined macros

OKCMD defined in line 48; used 4 times

- in line 116(2), 135, 444

TRY_AGAIN defined in line 455; used 1 times

- in line 495

Last modified: 1991-08-21 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1203 |