# 2.11BSD#431 - /usr/src/ucb/ex/ex_io.c

##### Functions

    checkmodeline     X
    clrstats          X
    edfile            X
    filename          X
    getargs           X
    getfile           X
    getone            X
    glob              X
    gscan             X
    iostats           X
    putfile           X
    rop               X
    rop2              X
    rop3              X
    samei             X
    source            X
    wop               X
    wrerror           X

##### Variables

    G                 X
    altdot            X
    cntch             X
    cntln             X
    cntnull           X
    cntodd            X
    isalt             X
    nextip            X
    oldadot           X
    slevel            X
    ttyindes          X
    wasalt            X

##### Macros

    EDF               X
    NOTEDF            X
    PARTBUF           X
    index             X
    rindex            X

       1: /*
       2:  * Copyright (c) 1980 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  */
       6:
       7: #if !defined(lint) && defined(DOSCCS)
       8: static char *sccsid = "@(#)ex_io.c	7.11.1.1 (Berkeley) 8/12/86";
       9: #endif
      10:
      11: #include "ex.h"
      12: #include "ex_argv.h"
      13: #include "ex_temp.h"
      14: #include "ex_tty.h"
      15: #include "ex_vis.h"
      16:
      17: /*
      18:  * File input/output, source, preserve and recover
      19:  */
      20:
      21: /*
      22:  * Following remember where . was in the previous file for return
      23:  * on file switching.
      24:  */
      25: int altdot;
      26: int oldadot;
      27: bool    wasalt;
      28: short   isalt;
      29:
      30: long    cntch;          /* Count of characters on unit io */
      31: #ifndef VMUNIX
      32: short   cntln;          /* Count of lines " */
      33: #else
      34: int cntln;
      35: #endif
      36: long    cntnull;        /* Count of nulls " */
      37: long    cntodd;         /* Count of non-ascii characters " */
      38:
      39: /*
      40:  * Parse file name for command encoded by comm.
      41:  * If comm is E then command is doomed and we are
      42:  * parsing just so user won't have to retype the name.
      43:  */
      44: filename(comm)
      45:     int comm;
      46: {
      47:     register int c = comm, d;
      48:     register int i;
      49:
      50:     d = getchar();
      51:     if (endcmd(d)) {
      52:         if (savedfile[0] == 0 && comm != 'f')
      53:             error("No file|No current filename");
      54:         CP(file, savedfile);
      55:         wasalt = (isalt > 0) ? isalt-1 : 0;
      56:         isalt = 0;
      57:         oldadot = altdot;
      58:         if (c == 'e' || c == 'E')
      59:             altdot = lineDOT();
      60:         if (d == EOF)
      61:             ungetchar(d);
      62:     } else {
      63:         ungetchar(d);
      64:         getone();
      65:         eol();
      66:         if (savedfile[0] == 0 && c != 'E' && c != 'e') {
      67:             c = 'e';
      68:             edited = 0;
      69:         }
      70:         wasalt = strcmp(file, altfile) == 0;
      71:         oldadot = altdot;
      72:         switch (c) {
      73:
      74:         case 'f':
      75:             edited = 0;
      76:             /* fall into ... */
      77:
      78:         case 'e':
      79:             if (savedfile[0]) {
      80:                 altdot = lineDOT();
      81:                 CP(altfile, savedfile);
      82:             }
      83:             CP(savedfile, file);
      84:             break;
      85:
      86:         default:
      87:             if (file[0]) {
      88:                 if (c != 'E')
      89:                     altdot = lineDOT();
      90:                 CP(altfile, file);
      91:             }
      92:             break;
      93:         }
      94:     }
      95:     if (hush && comm != 'f' || comm == 'E')
      96:         return;
      97:     if (file[0] != 0) {
      98:         lprintf("\"%s\"", file);
      99:         if (comm == 'f') {
     100:             if (value(READONLY))
     101:                 printf(" [Read only]");
     102:             if (!edited)
     103:                 printf(" [Not edited]");
     104:             if (tchng)
     105:                 printf(" [Modified]");
     106:         }
     107:         flush();
     108:     } else
     109:         printf("No file ");
     110:     if (comm == 'f') {
     111:         if (!(i = lineDOL()))
     112:             i++;
     113:         printf(" line %d of %d --%ld%%--", lineDOT(), lineDOL(),
     114:             (long) 100 * lineDOT() / i);
     115:     }
     116: }
     117:
     118: /*
     119:  * Get the argument words for a command into genbuf
     120:  * expanding # and %.
     121:  */
     122: getargs()
     123: {
     124:     register int c;
     125:     register char *cp, *fp;
     126:     static char fpatbuf[32];    /* hence limit on :next +/pat */
     127:
     128:     pastwh();
     129:     if (peekchar() == '+') {
     130:         for (cp = fpatbuf;;) {
     131:             c = *cp++ = getchar();
     132:             if (cp >= &fpatbuf[sizeof(fpatbuf)])
     133:                 error("Pattern too long");
     134:             if (c == '\\' && isspace(peekchar()))
     135:                 c = getchar();
     136:             if (c == EOF || isspace(c)) {
     137:                 ungetchar(c);
     138:                 *--cp = 0;
     139:                 firstpat = &fpatbuf[1];
     140:                 break;
     141:             }
     142:         }
     143:     }
     144:     if (skipend())
     145:         return (0);
     146:     CP(genbuf, "echo "); cp = &genbuf[5];
     147:     for (;;) {
     148:         c = getchar();
     149:         if (endcmd(c)) {
     150:             ungetchar(c);
     151:             break;
     152:         }
     153:         switch (c) {
     154:
     155:         case '\\':
     156:             if (any(peekchar(), "#%|"))
     157:                 c = getchar();
     158:             /* fall into... */
     159:
     160:         default:
     161:             if (cp > &genbuf[LBSIZE - 2])
     162: flong:
     163:                 error("Argument buffer overflow");
     164:             *cp++ = c;
     165:             break;
     166:
     167:         case '#':
     168:             fp = altfile;
     169:             if (*fp == 0)
     170:                 error("No alternate filename@to substitute for #");
     171:             goto filexp;
     172:
     173:         case '%':
     174:             fp = savedfile;
     175:             if (*fp == 0)
     176:                 error("No current filename@to substitute for %%");
     177: filexp:
     178:             while (*fp) {
     179:                 if (cp > &genbuf[LBSIZE - 2])
     180:                     goto flong;
     181:                 *cp++ = *fp++;
     182:             }
     183:             break;
     184:         }
     185:     }
     186:     *cp = 0;
     187:     return (1);
     188: }
     189:
     190: /*
     191:  * Glob the argument words in genbuf, or if no globbing
     192:  * is implied, just split them up directly.
     193:  */
     194: glob(gp)
     195:     struct glob *gp;
     196: {
     197:     int pvec[2];
     198:     register char **argv = gp->argv;
     199:     register char *cp = gp->argspac;
     200:     register int c;
     201:     char ch;
     202:     int nleft = NCARGS;
     203:
     204:     gp->argc0 = 0;
     205:     if (gscan() == 0) {
     206:         register char *v = genbuf + 5;      /* strlen("echo ") */
     207:
     208:         for (;;) {
     209:             while (isspace(*v))
     210:                 v++;
     211:             if (!*v)
     212:                 break;
     213:             *argv++ = cp;
     214:             while (*v && !isspace(*v))
     215:                 *cp++ = *v++;
     216:             *cp++ = 0;
     217:             gp->argc0++;
     218:         }
     219:         *argv = 0;
     220:         return;
     221:     }
     222:     if (pipe(pvec) < 0)
     223:         error("Can't make pipe to glob");
     224:     pid = fork();
     225:     io = pvec[0];
     226:     if (pid < 0) {
     227:         close(pvec[1]);
     228:         error("Can't fork to do glob");
     229:     }
     230:     if (pid == 0) {
     231:         int oerrno;
     232:
     233:         close(1);
     234:         dup(pvec[1]);
     235:         close(pvec[0]);
     236:         close(2);   /* so errors don't mess up the screen */
     237:         open("/dev/null", 1);
     238:         execl(svalue(SHELL), "sh", "-c", genbuf, 0);
     239:         oerrno = errno; close(1); dup(2); errno = oerrno;
     240:         filioerr(svalue(SHELL));
     241:     }
     242:     close(pvec[1]);
     243:     do {
     244:         *argv = cp;
     245:         for (;;) {
     246:             if (read(io, &ch, 1) != 1) {
     247:                 close(io);
     248:                 c = -1;
     249:             } else
     250:                 c = ch & TRIM;
     251:             if (c <= 0 || isspace(c))
     252:                 break;
     253:             *cp++ = c;
     254:             if (--nleft <= 0)
     255:                 error("Arg list too long");
     256:         }
     257:         if (cp != *argv) {
     258:             --nleft;
     259:             *cp++ = 0;
     260:             gp->argc0++;
     261:             if (gp->argc0 >= NARGS)
     262:                 error("Arg list too long");
     263:             argv++;
     264:         }
     265:     } while (c >= 0);
     266:     waitfor();
     267:     if (gp->argc0 == 0)
     268:         error("No match");
     269: }
     270:
     271: /*
     272:  * Scan genbuf for shell metacharacters.
     273:  * Set is union of v7 shell and csh metas.
     274:  */
     275: gscan()
     276: {
     277:     register char *cp;
     278:
     279:     for (cp = genbuf; *cp; cp++)
     280:         if (any(*cp, "~{[*?$`'\"\\"))
     281:             return (1);
     282:     return (0);
     283: }
     284:
     285: /*
     286:  * Parse one filename into file.
     287:  */
     288: struct glob G;
     289: getone()
     290: {
     291:     register char *str;
     292:
     293:     if (getargs() == 0)
     294:         error("Missing filename");
     295:     glob(&G);
     296:     if (G.argc0 > 1)
     297:         error("Ambiguous|Too many file names");
     298:     str = G.argv[G.argc0 - 1];
     299:     if (strlen(str) > FNSIZE - 4)
     300:         error("Filename too long");
     301: samef:
     302:     CP(file, str);
     303: }
     304:
     305: /*
     306:  * Read a file from the world.
     307:  * C is command, 'e' if this really an edit (or a recover).
     308:  */
     309: rop(c)
     310:     int c;
     311: {
     312:     register int i;
     313:     struct stat stbuf;
     314:     short magic;
     315:     static int ovro;    /* old value(READONLY) */
     316:     static int denied;  /* 1 if READONLY was set due to file permissions */
     317:
     318:     io = open(file, 0);
     319:     if (io < 0) {
     320:         if (c == 'e' && errno == ENOENT) {
     321:             edited++;
     322:             /*
     323: 			 * If the user just did "ex foo" he is probably
     324: 			 * creating a new file.  Don't be an error, since
     325: 			 * this is ugly, and it screws up the + option.
     326: 			 */
     327:             if (!seenprompt) {
     328:                 printf(" [New file]");
     329:                 noonl();
     330:                 return;
     331:             }
     332:         }
     333:         syserror();
     334:     }
     335:     if (fstat(io, &stbuf))
     336:         syserror();
     337:     switch (stbuf.st_mode & S_IFMT) {
     338:
     339:     case S_IFBLK:
     340:         error(" Block special file");
     341:
     342:     case S_IFCHR:
     343:         if (isatty(io))
     344:             error(" Teletype");
     345:         if (samei(&stbuf, "/dev/null"))
     346:             break;
     347:         error(" Character special file");
     348:
     349:     case S_IFDIR:
     350:         error(" Directory");
     351:
     352:     case S_IFREG:
     353:         i = read(io, (char *) &magic, sizeof(magic));
     354:         lseek(io, 0l, 0);
     355:         if (i != sizeof(magic))
     356:             break;
     357:         switch (magic) {
     358:
     359:         case 0405:  /* data overlay on exec */
     360:         case 0407:  /* unshared */
     361:         case 0410:  /* shared text */
     362:         case 0411:  /* separate I/D */
     363:         case 0413:  /* VM/Unix demand paged */
     364:         case 0430:  /* PDP-11 Overlay shared */
     365:         case 0431:  /* PDP-11 Overlay sep I/D */
     366:             error(" Executable");
     367:
     368:         /*
     369: 		 * We do not forbid the editing of portable archives
     370: 		 * because it is reasonable to edit them, especially
     371: 		 * if they are archives of text files.  This is
     372: 		 * especially useful if you archive source files together
     373: 		 * and copy them to another system with ~%take, since
     374: 		 * the files sometimes show up munged and must be fixed.
     375: 		 */
     376:         case 0177545:
     377:         case 0177555:
     378:             error(" Archive");
     379:
     380:         default:
     381: #ifdef mbb
     382:             /* C/70 has a 10 bit byte */
     383:             if (magic & 03401600)
     384: #else
     385:             /* Everybody else has an 8 bit byte */
     386:             if (magic & 0100200)
     387: #endif
     388:                 error(" Non-ascii file");
     389:             break;
     390:         }
     391:     }
     392:     if (c != 'r') {
     393:         if (value(READONLY) && denied) {
     394:             value(READONLY) = ovro;
     395:             denied = 0;
     396:         }
     397:         if ((stbuf.st_mode & 0222) == 0 || access(file, 2) < 0) {
     398:             ovro = value(READONLY);
     399:             denied = 1;
     400:             value(READONLY) = 1;
     401:         }
     402:     }
     403:     if (value(READONLY)) {
     404:         printf(" [Read only]");
     405:         flush();
     406:     }
     407:     if (c == 'r')
     408:         setdot();
     409:     else
     410:         setall();
     411:     if (FIXUNDO && inopen && c == 'r')
     412:         undap1 = undap2 = dot + 1;
     413:     rop2();
     414:     rop3(c);
     415: }
     416:
     417: rop2()
     418: {
     419:     line *first, *last, *a;
     420:     struct stat statb;
     421:
     422:     deletenone();
     423:     clrstats();
     424:     first = addr2 + 1;
     425:     if (fstat(io, &statb) < 0)
     426:         bsize = LBSIZE;
     427:     else {
     428:         bsize = statb.st_blksize;
     429:         if (bsize <= 0)
     430:             bsize = LBSIZE;
     431:     }
     432:     ignore(append(getfile, addr2));
     433:     last = dot;
     434:     /*
     435: 	 *	if the modeline variable is set,
     436: 	 *	check the first and last five lines of the file
     437: 	 *	for a mode line.
     438: 	 */
     439:     if (value(MODELINE)) {
     440:         for (a=first; a<=last; a++) {
     441:             if (a==first+5 && last-first > 10)
     442:                 a = last - 4;
     443:             getline(*a);
     444:             checkmodeline(linebuf);
     445:         }
     446:     }
     447: }
     448:
     449: rop3(c)
     450:     int c;
     451: {
     452:
     453:     if (iostats() == 0 && c == 'e')
     454:         edited++;
     455:     if (c == 'e') {
     456:         if (wasalt || firstpat) {
     457:             register line *addr = zero + oldadot;
     458:
     459:             if (addr > dol)
     460:                 addr = dol;
     461:             if (firstpat) {
     462:                 globp = (*firstpat) ? firstpat : "$";
     463:                 commands(1,1);
     464:                 firstpat = 0;
     465:             } else if (addr >= one) {
     466:                 if (inopen)
     467:                     dot = addr;
     468:                 markpr(addr);
     469:             } else
     470:                 goto other;
     471:         } else
     472: other:
     473:             if (dol > zero) {
     474:                 if (inopen)
     475:                     dot = one;
     476:                 markpr(one);
     477:             }
     478:         if(FIXUNDO)
     479:             undkind = UNDNONE;
     480:         if (inopen) {
     481:             vcline = 0;
     482:             vreplace(0, LINES, lineDOL());
     483:         }
     484:     }
     485: }
     486:
     487: /*
     488:  * Are these two really the same inode?
     489:  */
     490: samei(sp, cp)
     491:     struct stat *sp;
     492:     char *cp;
     493: {
     494:     struct stat stb;
     495:
     496:     if (stat(cp, &stb) < 0 || sp->st_dev != stb.st_dev)
     497:         return (0);
     498:     return (sp->st_ino == stb.st_ino);
     499: }
     500:
     501: /* Returns from edited() */
     502: #define EDF 0       /* Edited file */
     503: #define NOTEDF  -1      /* Not edited file */
     504: #define PARTBUF 1       /* Write of partial buffer to Edited file */
     505:
     506: /*
     507:  * Write a file.
     508:  */
     509: wop(dofname)
     510: bool dofname;   /* if 1 call filename, else use savedfile */
     511: {
     512:     register int c, exclam, nonexist;
     513:     line *saddr1, *saddr2;
     514:     struct stat stbuf;
     515:
     516:     c = 0;
     517:     exclam = 0;
     518:     if (dofname) {
     519:         if (peekchar() == '!')
     520:             exclam++, ignchar();
     521:         ignore(skipwh());
     522:         while (peekchar() == '>')
     523:             ignchar(), c++, ignore(skipwh());
     524:         if (c != 0 && c != 2)
     525:             error("Write forms are 'w' and 'w>>'");
     526:         filename('w');
     527:     } else {
     528:         if (savedfile[0] == 0)
     529:             error("No file|No current filename");
     530:         saddr1=addr1;
     531:         saddr2=addr2;
     532:         addr1=one;
     533:         addr2=dol;
     534:         CP(file, savedfile);
     535:         if (inopen) {
     536:             vclrech(0);
     537:             splitw++;
     538:         }
     539:         lprintf("\"%s\"", file);
     540:     }
     541:     nonexist = stat(file, &stbuf);
     542:     switch (c) {
     543:
     544:     case 0:
     545:         if (!exclam && (!value(WRITEANY) || value(READONLY)))
     546:         switch (edfile()) {
     547:
     548:         case NOTEDF:
     549:             if (nonexist)
     550:                 break;
     551:             if ((stbuf.st_mode & S_IFMT) == S_IFCHR) {
     552:                 if (samei(&stbuf, "/dev/null"))
     553:                     break;
     554:                 if (samei(&stbuf, "/dev/tty"))
     555:                     break;
     556:             }
     557:             io = open(file, 1);
     558:             if (io < 0)
     559:                 syserror();
     560:             if (!isatty(io))
     561:                 serror(" File exists| File exists - use \"w! %s\" to overwrite", file);
     562:             close(io);
     563:             break;
     564:
     565:         case EDF:
     566:             if (value(READONLY))
     567:                 error(" File is read only");
     568:             break;
     569:
     570:         case PARTBUF:
     571:             if (value(READONLY))
     572:                 error(" File is read only");
     573:             error(" Use \"w!\" to write partial buffer");
     574:         }
     575: cre:
     576: /*
     577: 		synctmp();
     578: */
     579: #ifdef V6
     580:         io = creat(file, 0644);
     581: #else
     582:         io = creat(file, 0666);
     583: #endif
     584:         if (io < 0)
     585:             syserror();
     586:         writing = 1;
     587:         if (hush == 0)
     588:             if (nonexist)
     589:                 printf(" [New file]");
     590:             else if (value(WRITEANY) && edfile() != EDF)
     591:                 printf(" [Existing file]");
     592:         break;
     593:
     594:     case 2:
     595:         io = open(file, 1);
     596:         if (io < 0) {
     597:             if (exclam || value(WRITEANY))
     598:                 goto cre;
     599:             syserror();
     600:         }
     601:         lseek(io, 0l, 2);
     602:         break;
     603:     }
     604:     putfile(0);
     605:     ignore(iostats());
     606:     if (c != 2 && addr1 == one && addr2 == dol) {
     607:         if (eq(file, savedfile))
     608:             edited = 1;
     609:         sync();
     610:     }
     611:     if (!dofname) {
     612:         addr1 = saddr1;
     613:         addr2 = saddr2;
     614:     }
     615:     writing = 0;
     616: }
     617:
     618: /*
     619:  * Is file the edited file?
     620:  * Work here is that it is not considered edited
     621:  * if this is a partial buffer, and distinguish
     622:  * all cases.
     623:  */
     624: edfile()
     625: {
     626:
     627:     if (!edited || !eq(file, savedfile))
     628:         return (NOTEDF);
     629:     return (addr1 == one && addr2 == dol ? EDF : PARTBUF);
     630: }
     631:
     632: /*
     633:  * Extract the next line from the io stream.
     634:  */
     635: char *nextip;
     636:
     637: getfile()
     638: {
     639:     register short c;
     640:     register char *lp, *fp;
     641:
     642:     lp = linebuf;
     643:     fp = nextip;
     644:     do {
     645:         if (--ninbuf < 0) {
     646:             ninbuf = read(io, genbuf, bsize) - 1;
     647:             if (ninbuf < 0) {
     648:                 if (lp != linebuf) {
     649:                     lp++;
     650:                     printf(" [Incomplete last line]");
     651:                     break;
     652:                 }
     653:                 return (EOF);
     654:             }
     655:             fp = genbuf;
     656:             cntch += ninbuf+1;
     657:         }
     658:         if (lp >= &linebuf[LBSIZE]) {
     659:             error(" Line too long");
     660:         }
     661:         c = *fp++;
     662:         if (c == 0) {
     663:             cntnull++;
     664:             continue;
     665:         }
     666:         if (c & QUOTE) {
     667:             cntodd++;
     668:             c &= TRIM;
     669:             if (c == 0)
     670:                 continue;
     671:         }
     672:         *lp++ = c;
     673:     } while (c != '\n');
     674:     *--lp = 0;
     675:     nextip = fp;
     676:     cntln++;
     677:     return (0);
     678: }
     679:
     680: /*
     681:  * Write a range onto the io stream.
     682:  */
     683: putfile(isfilter)
     684: int isfilter;
     685: {
     686:     line *a1;
     687:     register char *fp, *lp;
     688:     register int nib;
     689:     struct stat statb;
     690:
     691:     a1 = addr1;
     692:     clrstats();
     693:     cntln = addr2 - a1 + 1;
     694:     if (cntln == 0)
     695:         return;
     696:     if (fstat(io, &statb) < 0)
     697:         bsize = LBSIZE;
     698:     else {
     699:         bsize = statb.st_blksize;
     700:         if (bsize <= 0)
     701:             bsize = LBSIZE;
     702:     }
     703:     nib = bsize;
     704:     fp = genbuf;
     705:     do {
     706:         getline(*a1++);
     707:         lp = linebuf;
     708:         for (;;) {
     709:             if (--nib < 0) {
     710:                 nib = fp - genbuf;
     711:                 if (write(io, genbuf, nib) != nib) {
     712:                     wrerror();
     713:                 }
     714:                 cntch += nib;
     715:                 nib = bsize - 1;
     716:                 fp = genbuf;
     717:             }
     718:             if ((*fp++ = *lp++) == 0) {
     719:                 fp[-1] = '\n';
     720:                 break;
     721:             }
     722:         }
     723:     } while (a1 <= addr2);
     724:     nib = fp - genbuf;
     725:     if (write(io, genbuf, nib) != nib) {
     726:         wrerror();
     727:     }
     728:     cntch += nib;
     729: }
     730:
     731: /*
     732:  * A write error has occurred;  if the file being written was
     733:  * the edited file then we consider it to have changed since it is
     734:  * now likely scrambled.
     735:  */
     736: wrerror()
     737: {
     738:
     739:     if (eq(file, savedfile) && edited)
     740:         change();
     741:     syserror();
     742: }
     743:
     744: /*
     745:  * Source command, handles nested sources.
     746:  * Traps errors since it mungs unit 0 during the source.
     747:  */
     748: short slevel;
     749: short ttyindes;
     750:
     751: source(fil, okfail)
     752:     char *fil;
     753:     bool okfail;
     754: {
     755:     jmp_buf osetexit;
     756:     register int saveinp, ointty, oerrno;
     757:     char *saveglobp;
     758:     short savepeekc;
     759:
     760:     signal(SIGINT, SIG_IGN);
     761:     saveinp = dup(0);
     762:     savepeekc = peekc;
     763:     saveglobp = globp;
     764:     peekc = 0; globp = 0;
     765:     if (saveinp < 0)
     766:         error("Too many nested sources");
     767:     if (slevel <= 0)
     768:         ttyindes = saveinp;
     769:     close(0);
     770:     if (open(fil, 0) < 0) {
     771:         oerrno = errno;
     772:         setrupt();
     773:         dup(saveinp);
     774:         close(saveinp);
     775:         errno = oerrno;
     776:         if (!okfail)
     777:             filioerr(fil);
     778:         return;
     779:     }
     780:     slevel++;
     781:     ointty = intty;
     782:     intty = isatty(0);
     783:     oprompt = value(PROMPT);
     784:     value(PROMPT) &= intty;
     785:     getexit(osetexit);
     786:     setrupt();
     787:     if (setexit() == 0)
     788:         commands(1, 1);
     789:     else if (slevel > 1) {
     790:         close(0);
     791:         dup(saveinp);
     792:         close(saveinp);
     793:         slevel--;
     794:         resexit(osetexit);
     795:         reset();
     796:     }
     797:     intty = ointty;
     798:     value(PROMPT) = oprompt;
     799:     close(0);
     800:     dup(saveinp);
     801:     close(saveinp);
     802:     globp = saveglobp;
     803:     peekc = savepeekc;
     804:     slevel--;
     805:     resexit(osetexit);
     806: }
     807:
     808: /*
     809:  * Clear io statistics before a read or write.
     810:  */
     811: clrstats()
     812: {
     813:
     814:     ninbuf = 0;
     815:     cntch = 0;
     816:     cntln = 0;
     817:     cntnull = 0;
     818:     cntodd = 0;
     819: }
     820:
     821: /*
     822:  * Io is finished, close the unit and print statistics.
     823:  */
     824: iostats()
     825: {
     826:
     827:     (void) fsync(io);
     828:     close(io);
     829:     io = -1;
     830:     if (hush == 0) {
     831:         if (value(TERSE))
     832:             printf(" %d/%D", cntln, cntch);
     833:         else
     834:             printf(" %d line%s, %D character%s", cntln, plural((long) cntln),
     835:                 cntch, plural(cntch));
     836:         if (cntnull || cntodd) {
     837:             printf(" (");
     838:             if (cntnull) {
     839:                 printf("%D null", cntnull);
     840:                 if (cntodd)
     841:                     printf(", ");
     842:             }
     843:             if (cntodd)
     844:                 printf("%D non-ASCII", cntodd);
     845:             putchar(')');
     846:         }
     847:         noonl();
     848:         flush();
     849:     }
     850:     return (cntnull != 0 || cntodd != 0);
     851: }
     852:
     853: #if USG | USG3TTY
     854: /* It's so wonderful how we all speak the same language... */
     855: # define index strchr
     856: # define rindex strrchr
     857: #endif
     858:
     859: checkmodeline(line)
     860: char *line;
     861: {
     862:     char *beg, *end;
     863:     char cmdbuf[1024];
     864:     char *index(), *rindex();
     865:
     866:     beg = index(line, ':');
     867:     if (beg == NULL)
     868:         return;
     869:     if (&beg[-3] < line)
     870:         return;
     871:     if (!(  ( (beg[-3] == ' ' || beg[-3] == '\t')
     872:             && beg[-2] == 'e'
     873:         && beg[-1] == 'x')
     874:          || ( (beg[-3] == ' ' || beg[-3] == '\t')
     875:             && beg[-2] == 'v'
     876:         && beg[-1] == 'i'))) return;
     877:     strncpy(cmdbuf, beg+1, sizeof cmdbuf);
     878:     end = rindex(cmdbuf, ':');
     879:     if (end == NULL)
     880:         return;
     881:     *end = 0;
     882:     globp = cmdbuf;
     883:     commands(1, 1);
     884: }

#### Defined functions

checkmodeline defined in line 859; used 1 times

- in line 444

clrstats defined in line 811; used 2 times

- in line 423, 692

edfile defined in line 624; used 2 times

- in line 546, 590

filename defined in line 44; used 7 times

- in line 526
- in /usr/src/ucb/ex/ex_cmds.c line 269, 293, 398, 497, 507, 545

getargs defined in line 122; used 2 times

- in line 293
- in /usr/src/ucb/ex/ex_cmds.c line 394

getfile defined in line 637; used 3 times

- in line 432
- in /usr/src/ucb/ex/ex.h line 363
- in /usr/src/ucb/ex/ex_cmdsub.c line 549

getone defined in line 289; used 3 times

- in line 64
- in /usr/src/ucb/ex/ex_cmds.c line 215, 585

glob defined in line 194; used 2 times

- in line 295
- in /usr/src/ucb/ex/ex_cmds2.c line 231

gscan defined in line 275; used 1 times

- in line 205

iostats defined in line 824; used 2 times

- in line 453, 605

putfile defined in line 683; used 1 times

- in line 604

rop defined in line 309; used 2 times

- in /usr/src/ucb/ex/ex_cmds.c line 280, 546

rop2 defined in line 417; used 2 times

- in line 413
- in /usr/src/ucb/ex/ex_cmds.c line 517

rop3 defined in line 449; used 2 times

- in line 414
- in /usr/src/ucb/ex/ex_cmds.c line 520

samei defined in line 490; used 3 times

- in line 345, 552-554(2)

source defined in line 751; used 3 times

- in /usr/src/ucb/ex/ex.c line 313, 323
- in /usr/src/ucb/ex/ex_cmds.c line 587

wop defined in line 509; used 2 times

- in /usr/src/ucb/ex/ex.h line 241
- in /usr/src/ucb/ex/ex_cmds.c line 710

wrerror defined in line 736; used 2 times

- in line 712, 726

#### Defined variables

G defined in line 288; used 4 times

- in line 295-298(4)

altdot defined in line 25; used 5 times

- in line 57-59(2), 71, 80, 89

cntch defined in line 30; used 7 times

- in line 656, 714, 728, 815, 832-835(3)

cntln defined in line 34; used 7 times

- in line 676, 693-694(2), 816, 832-834(3)

cntnull defined in line 36; used 6 times

- in line 663, 817, 836-839(3), 850

cntodd defined in line 37; used 7 times

- in line 667, 818, 836-844(4), 850

isalt defined in line 28; used 3 times

- in line 55-56(3)

nextip defined in line 635; used 2 times

- in line 643, 675

oldadot defined in line 26; used 3 times

- in line 57, 71, 457

sccsid defined in line 8; never used
slevel defined in line 748; used 5 times

- in line 767, 780, 789-793(2), 804

ttyindes defined in line 749; used 1 times

- in line 768

wasalt defined in line 27; used 3 times

- in line 55, 70, 456

#### Defined macros

EDF defined in line 502; used 2 times

- in line 590, 629

NOTEDF defined in line 503; used 1 times

- in line 628

PARTBUF defined in line 504; used 1 times

- in line 629

index defined in line 855; used 2 times

- in line 864-866(2)

rindex defined in line 856; used 2 times

- in line 864, 878

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