Annotation of coherent/g/usr/bin/vi/ex.c, revision 1.1

1.1     ! root        1: /* ex.c */
        !             2: 
        !             3: /* Author:
        !             4:  *     Steve Kirkendall
        !             5:  *     14407 SW Teal Blvd. #C
        !             6:  *     Beaverton, OR 97005
        !             7:  *     [email protected]
        !             8:  */
        !             9: 
        !            10: 
        !            11: /* This file contains the code for reading ex commands. */
        !            12: 
        !            13: #include "config.h"
        !            14: #include "ctype.h"
        !            15: #include "vi.h"
        !            16: 
        !            17: /* This data type is used to describe the possible argument combinations */
        !            18: typedef short ARGT;
        !            19: #define FROM   1               /* allow a linespec */
        !            20: #define        TO      2               /* allow a second linespec */
        !            21: #define BANG   4               /* allow a ! after the command name */
        !            22: #define EXTRA  8               /* allow extra args after command name */
        !            23: #define XFILE  16              /* expand wildcards in extra part */
        !            24: #define NOSPC  32              /* no spaces allowed in the extra part */
        !            25: #define        DFLALL  64              /* default file range is 1,$ */
        !            26: #define DFLNONE        128             /* no default file range */
        !            27: #define NODFL  256             /* do not default to the current file name */
        !            28: #define EXRCOK 512             /* can be in a .exrc file */
        !            29: #define NL     1024            /* if mode!=MODE_EX, then write a newline first */
        !            30: #define PLUS   2048            /* allow a line number, as in ":e +32 foo" */
        !            31: #define ZERO   4096            /* allow 0 to be given as a line number */
        !            32: #define NOBAR  8192            /* treat following '|' chars as normal */
        !            33: #define FILES  (XFILE + EXTRA) /* multiple extra files allowed */
        !            34: #define WORD1  (EXTRA + NOSPC) /* one extra word allowed */
        !            35: #define FILE1  (FILES + NOSPC) /* 1 file allowed, defaults to current file */
        !            36: #define NAMEDF (FILE1 + NODFL) /* 1 file allowed, defaults to "" */
        !            37: #define NAMEDFS        (FILES + NODFL) /* multiple files allowed, default is "" */
        !            38: #define RANGE  (FROM + TO)     /* range of linespecs allowed */
        !            39: #define NONE   0               /* no args allowed at all */
        !            40: 
        !            41: /* This array maps ex command names to command codes. The order in which
        !            42:  * command names are listed below is significant -- ambiguous abbreviations
        !            43:  * are always resolved to be the first possible match.  (e.g. "r" is taken
        !            44:  * to mean "read", not "rewind", because "read" comes before "rewind")
        !            45:  */
        !            46: static struct
        !            47: {
        !            48:        char    *name;  /* name of the command */
        !            49:        CMD     code;   /* enum code of the command */
        !            50:        void    (*fn)();/* function which executes the command */
        !            51:        ARGT    argt;   /* command line arguments permitted/needed/used */
        !            52: }
        !            53:        cmdnames[] =
        !            54: {   /* cmd name        cmd code        function        arguments */
        !            55:        {"append",      CMD_APPEND,     cmd_append,     FROM+ZERO+BANG  },
        !            56: #ifdef DEBUG
        !            57:        {"bug",         CMD_DEBUG,      cmd_debug,      RANGE+BANG+EXTRA+NL},
        !            58: #endif
        !            59:        {"change",      CMD_CHANGE,     cmd_append,     RANGE+BANG      },
        !            60:        {"delete",      CMD_DELETE,     cmd_delete,     RANGE+WORD1     },
        !            61:        {"edit",        CMD_EDIT,       cmd_edit,       BANG+FILE1+PLUS },
        !            62:        {"file",        CMD_FILE,       cmd_file,       NAMEDF          },
        !            63:        {"global",      CMD_GLOBAL,     cmd_global,     RANGE+BANG+EXTRA+DFLALL+NOBAR},
        !            64:        {"insert",      CMD_INSERT,     cmd_append,     FROM+BANG       },
        !            65:        {"join",        CMD_INSERT,     cmd_join,       RANGE+BANG      },
        !            66:        {"k",           CMD_MARK,       cmd_mark,       FROM+WORD1      },
        !            67:        {"list",        CMD_LIST,       cmd_print,      RANGE+NL        },
        !            68:        {"move",        CMD_MOVE,       cmd_move,       RANGE+EXTRA     },
        !            69:        {"next",        CMD_NEXT,       cmd_next,       BANG+NAMEDFS    },
        !            70:        {"Next",        CMD_PREVIOUS,   cmd_next,       BANG            },
        !            71:        {"print",       CMD_PRINT,      cmd_print,      RANGE+NL        },
        !            72:        {"quit",        CMD_QUIT,       cmd_xit,        BANG            },
        !            73:        {"read",        CMD_READ,       cmd_read,       FROM+ZERO+NAMEDF},
        !            74:        {"substitute",  CMD_SUBSTITUTE, cmd_substitute, RANGE+EXTRA     },
        !            75:        {"to",          CMD_COPY,       cmd_move,       RANGE+EXTRA     },
        !            76:        {"undo",        CMD_UNDO,       cmd_undo,       NONE            },
        !            77:        {"vglobal",     CMD_VGLOBAL,    cmd_global,     RANGE+EXTRA+DFLALL+NOBAR},
        !            78:        {"write",       CMD_WRITE,      cmd_write,      RANGE+BANG+FILE1+DFLALL},
        !            79:        {"xit",         CMD_XIT,        cmd_xit,        BANG+NL         },
        !            80:        {"yank",        CMD_YANK,       cmd_delete,     RANGE+WORD1     },
        !            81: 
        !            82:        {"!",           CMD_BANG,       cmd_shell,      EXRCOK+RANGE+NAMEDFS+DFLNONE+NL+NOBAR},
        !            83:        {"#",           CMD_NUMBER,     cmd_print,      RANGE+NL        },
        !            84:        {"<",           CMD_SHIFTL,     cmd_shift,      RANGE           },
        !            85:        {">",           CMD_SHIFTR,     cmd_shift,      RANGE           },
        !            86:        {"=",           CMD_EQUAL,      cmd_file,       RANGE           },
        !            87:        {"&",           CMD_SUBAGAIN,   cmd_substitute, RANGE           },
        !            88: #ifndef NO_AT
        !            89:        {"@",           CMD_AT,         cmd_at,         EXTRA           },
        !            90: #endif
        !            91: 
        !            92: #ifndef NO_ABBR
        !            93:        {"abbreviate",  CMD_ABBR,       cmd_map,        EXRCOK+BANG+EXTRA},
        !            94: #endif
        !            95:        {"args",        CMD_ARGS,       cmd_args,       EXRCOK+NAMEDFS  },
        !            96: #ifndef NO_ERRLIST
        !            97:        {"cc",          CMD_CC,         cmd_make,       BANG+FILES      },
        !            98: #endif
        !            99:        {"cd",          CMD_CD,         cmd_cd,         EXRCOK+BANG+NAMEDF},
        !           100:        {"copy",        CMD_COPY,       cmd_move,       RANGE+EXTRA     },
        !           101: #ifndef NO_DIGRAPH
        !           102:        {"digraph",     CMD_DIGRAPH,    cmd_digraph,    EXRCOK+BANG+EXTRA},
        !           103: #endif
        !           104: #ifndef NO_ERRLIST
        !           105:        {"errlist",     CMD_ERRLIST,    cmd_errlist,    BANG+NAMEDF     },
        !           106: #endif
        !           107:        {"ex",          CMD_EDIT,       cmd_edit,       BANG+FILE1      },
        !           108:        {"mark",        CMD_MARK,       cmd_mark,       FROM+WORD1      },
        !           109: #ifndef NO_MKEXRC
        !           110:        {"mkexrc",      CMD_MKEXRC,     cmd_mkexrc,     NAMEDF          },
        !           111: #endif
        !           112:        {"number",      CMD_NUMBER,     cmd_print,      RANGE+NL        },
        !           113:        {"put",         CMD_PUT,        cmd_put,        FROM+ZERO+WORD1 },
        !           114:        {"set",         CMD_SET,        cmd_set,        EXRCOK+EXTRA    },
        !           115:        {"shell",       CMD_SHELL,      cmd_shell,      NL              },
        !           116:        {"source",      CMD_SOURCE,     cmd_source,     EXRCOK+NAMEDF   },
        !           117: #ifdef SIGTSTP
        !           118:        {"stop",        CMD_STOP,       cmd_suspend,    NONE            },
        !           119: #endif
        !           120:        {"tag",         CMD_TAG,        cmd_tag,        BANG+WORD1      },
        !           121:        {"version",     CMD_VERSION,    cmd_version,    EXRCOK+NONE     },
        !           122:        {"visual",      CMD_VISUAL,     cmd_edit,       BANG+NAMEDF     },
        !           123:        {"wq",          CMD_WQUIT,      cmd_xit,        NL              },
        !           124: 
        !           125: #ifdef DEBUG
        !           126:        {"debug",       CMD_DEBUG,      cmd_debug,      RANGE+BANG+EXTRA+NL},
        !           127:        {"validate",    CMD_VALIDATE,   cmd_validate,   BANG+NL         },
        !           128: #endif
        !           129:        {"chdir",       CMD_CD,         cmd_cd,         EXRCOK+BANG+NAMEDF},
        !           130: #ifndef NO_COLOR
        !           131:        {"color",       CMD_COLOR,      cmd_color,      EXRCOK+EXTRA    },
        !           132: #endif
        !           133: #ifndef NO_ERRLIST
        !           134:        {"make",        CMD_MAKE,       cmd_make,       BANG+NAMEDFS    },
        !           135: #endif
        !           136:        {"map",         CMD_MAP,        cmd_map,        EXRCOK+BANG+EXTRA},
        !           137:        {"previous",    CMD_PREVIOUS,   cmd_next,       BANG            },
        !           138:        {"rewind",      CMD_REWIND,     cmd_next,       BANG            },
        !           139: #ifdef SIGTSTP
        !           140:        {"suspend",     CMD_SUSPEND,    cmd_suspend,    NONE            },
        !           141: #endif
        !           142:        {"unmap",       CMD_UNMAP,      cmd_map,        EXRCOK+BANG+EXTRA},
        !           143: #ifndef NO_ABBR
        !           144:        {"unabbreviate",CMD_UNABBR,     cmd_map,        EXRCOK+WORD1    },
        !           145: #endif
        !           146: 
        !           147:        {(char *)0}
        !           148: };
        !           149: 
        !           150: 
        !           151: /* This function parses a search pattern - given a pointer to a / or ?,
        !           152:  * it replaces the ending / or ? with a \0, and returns a pointer to the
        !           153:  * stuff that came after the pattern.
        !           154:  */
        !           155: char   *parseptrn(ptrn)
        !           156:        REG char        *ptrn;
        !           157: {
        !           158:        REG char        *scan;
        !           159: 
        !           160:        for (scan = ptrn + 1;
        !           161:             *scan && *scan != *ptrn;
        !           162:             scan++)
        !           163:        {
        !           164:                /* allow backslashed versions of / and ? in the pattern */
        !           165:                if (*scan == '\\' && scan[1] != '\0')
        !           166:                {
        !           167:                        scan++;
        !           168:                }
        !           169:        }
        !           170:        if (*scan)
        !           171:        {
        !           172:                *scan++ = '\0';
        !           173:        }
        !           174: 
        !           175:        return scan;
        !           176: }
        !           177: 
        !           178: 
        !           179: /* This function parses a line specifier for ex commands */
        !           180: char *linespec(s, markptr)
        !           181:        REG char        *s;             /* start of the line specifier */
        !           182:        MARK            *markptr;       /* where to store the mark's value */
        !           183: {
        !           184:        long            num;
        !           185:        REG char        *t;
        !           186: 
        !           187:        /* parse each ;-delimited clause of this linespec */
        !           188:        do
        !           189:        {
        !           190:                /* skip an initial ';', if any */
        !           191:                if (*s == ';')
        !           192:                {
        !           193:                        s++;
        !           194:                }
        !           195: 
        !           196:                /* skip leading spaces */
        !           197:                while (isspace(*s))
        !           198:                {
        !           199:                        s++;
        !           200:                }
        !           201: 
        !           202:                /* dot means current position */
        !           203:                if (*s == '.')
        !           204:                {
        !           205:                        s++;
        !           206:                        *markptr = cursor;
        !           207:                }
        !           208:                /* '$' means the last line */
        !           209:                else if (*s == '$')
        !           210:                {
        !           211:                        s++;
        !           212:                        *markptr = MARK_LAST;
        !           213:                }
        !           214:                /* digit means an absolute line number */
        !           215:                else if (isdigit(*s))
        !           216:                {
        !           217:                        for (num = 0; isdigit(*s); s++)
        !           218:                        {
        !           219:                                num = num * 10 + *s - '0';
        !           220:                        }
        !           221:                        *markptr = MARK_AT_LINE(num);
        !           222:                }
        !           223:                /* appostrophe means go to a set mark */
        !           224:                else if (*s == '\'')
        !           225:                {
        !           226:                        s++;
        !           227:                        *markptr = m_tomark(cursor, 1L, (int)*s);
        !           228:                        s++;
        !           229:                }
        !           230:                /* slash means do a search */
        !           231:                else if (*s == '/' || *s == '?')
        !           232:                {
        !           233:                        /* put a '\0' at the end of the search pattern */
        !           234:                        t = parseptrn(s);
        !           235: 
        !           236:                        /* search for the pattern */
        !           237:                        *markptr &= ~(BLKSIZE - 1);
        !           238:                        if (*s == '/')
        !           239:                        {
        !           240:                                pfetch(markline(*markptr));
        !           241:                                if (plen > 0)
        !           242:                                        *markptr += plen - 1;
        !           243:                                *markptr = m_fsrch(*markptr, s);
        !           244:                        }
        !           245:                        else
        !           246:                        {
        !           247:                                *markptr = m_bsrch(*markptr, s);
        !           248:                        }
        !           249: 
        !           250:                        /* adjust command string pointer */
        !           251:                        s = t;
        !           252:                }
        !           253: 
        !           254:                /* if linespec was faulty, quit now */
        !           255:                if (!*markptr)
        !           256:                {
        !           257:                        return s;
        !           258:                }
        !           259: 
        !           260:                /* maybe add an offset */
        !           261:                t = s;
        !           262:                if (*t == '-' || *t == '+')
        !           263:                {
        !           264:                        s++;
        !           265:                        for (num = 0; isdigit(*s); s++)
        !           266:                        {
        !           267:                                num = num * 10 + *s - '0';
        !           268:                        }
        !           269:                        if (num == 0)
        !           270:                        {
        !           271:                                num = 1;
        !           272:                        }
        !           273:                        *markptr = m_updnto(*markptr, num, *t);
        !           274:                }
        !           275:        } while (*s == ';' || *s == '+' || *s == '-');
        !           276: 
        !           277:        /* protect against invalid line numbers */
        !           278:        num = markline(*markptr);
        !           279:        if (num < 1L || num > nlines)
        !           280:        {
        !           281:                msg("Invalid line number -- must be from 1 to %ld", nlines);
        !           282:                *markptr = MARK_UNSET;
        !           283:        }
        !           284: 
        !           285:        return s;
        !           286: }
        !           287: 
        !           288: 
        !           289: 
        !           290: /* This function reads an ex command and executes it. */
        !           291: void ex()
        !           292: {
        !           293:        char            cmdbuf[150];
        !           294:        REG int         cmdlen;
        !           295:        static long     oldline;
        !           296: 
        !           297:        significant = FALSE;
        !           298:        oldline = markline(cursor);
        !           299: 
        !           300:        while (mode == MODE_EX)
        !           301:        {
        !           302:                /* read a line */
        !           303: #ifdef CRUNCH
        !           304:                cmdlen = vgets(':', cmdbuf, sizeof(cmdbuf));
        !           305: #else
        !           306:                cmdlen = vgets(*o_prompt ? ':' : '\0', cmdbuf, sizeof(cmdbuf));
        !           307: #endif
        !           308:                if (cmdlen < 0)
        !           309:                {
        !           310:                        return;
        !           311:                }
        !           312: 
        !           313:                /* if empty line, assume ".+1" */
        !           314:                if (cmdlen == 0)
        !           315:                {
        !           316:                        strcpy(cmdbuf, ".+1");
        !           317:                        qaddch('\r');
        !           318:                        clrtoeol();
        !           319:                }
        !           320:                else
        !           321:                {
        !           322:                        addch('\n');
        !           323:                }
        !           324:                refresh();
        !           325: 
        !           326:                /* parse & execute the command */
        !           327:                doexcmd(cmdbuf);
        !           328: 
        !           329:                /* handle autoprint */
        !           330:                if (significant || markline(cursor) != oldline)
        !           331:                {
        !           332:                        significant = FALSE;
        !           333:                        oldline = markline(cursor);
        !           334:                        if (*o_autoprint && mode == MODE_EX)
        !           335:                        {
        !           336:                                cmd_print(cursor, cursor, CMD_PRINT, FALSE, "");
        !           337:                        }
        !           338:                }
        !           339:        }
        !           340: }
        !           341: 
        !           342: void doexcmd(cmdbuf)
        !           343:        char            *cmdbuf;        /* string containing an ex command */
        !           344: {
        !           345:        REG char        *scan;          /* used to scan thru cmdbuf */
        !           346:        MARK            frommark;       /* first linespec */
        !           347:        MARK            tomark;         /* second linespec */
        !           348:        REG int         cmdlen;         /* length of the command name given */
        !           349:        CMD             cmd;            /* what command is this? */
        !           350:        ARGT            argt;           /* argument types for this command */
        !           351:        short           forceit;        /* bang version of a command? */
        !           352:        REG int         cmdidx;         /* index of command */
        !           353:        REG char        *build;         /* used while copying filenames */
        !           354:        int             iswild;         /* boolean: filenames use wildcards? */
        !           355:        int             isdfl;          /* using default line ranges? */
        !           356:        int             didsub;         /* did we substitute file names for % or # */
        !           357: 
        !           358:        /* ex commands can't be undone via the shift-U command */
        !           359:        U_line = 0L;
        !           360: 
        !           361:        /* permit extra colons at the start of the line */
        !           362:        for (; *cmdbuf == ':'; cmdbuf++)
        !           363:        {
        !           364:        }
        !           365: 
        !           366:        /* ignore command lines that start with a double-quote */
        !           367:        if (*cmdbuf == '"')
        !           368:        {
        !           369:                return;
        !           370:        }
        !           371:        scan = cmdbuf;
        !           372: 
        !           373:        /* parse the line specifier */
        !           374:        if (nlines < 1)
        !           375:        {
        !           376:                /* no file, so don't allow addresses */
        !           377:        }
        !           378:        else if (*scan == '%')
        !           379:        {
        !           380:                /* '%' means all lines */
        !           381:                frommark = MARK_FIRST;
        !           382:                tomark = MARK_LAST;
        !           383:                scan++;
        !           384:        }
        !           385:        else if (*scan == '0')
        !           386:        {
        !           387:                scan++;
        !           388:                frommark = tomark = (*scan ? MARK_UNSET : MARK_FIRST);
        !           389:        }
        !           390:        else
        !           391:        {
        !           392:                frommark = cursor;
        !           393:                scan = linespec(scan, &frommark);
        !           394:                tomark = frommark;
        !           395:                if (frommark && *scan == ',')
        !           396:                {
        !           397:                        scan++;
        !           398:                        scan = linespec(scan, &tomark);
        !           399:                }
        !           400:                if (!tomark)
        !           401:                {
        !           402:                        /* faulty line spec -- fault already described */
        !           403:                        return;
        !           404:                }
        !           405:                if (frommark > tomark)
        !           406:                {
        !           407:                        msg("first address exceeds the second");
        !           408:                        return;
        !           409:                }
        !           410:        }
        !           411:        isdfl = (scan == cmdbuf);
        !           412: 
        !           413:        /* skip whitespace */
        !           414:        while (isspace(*scan))
        !           415:        {
        !           416:                scan++;
        !           417:        }
        !           418: 
        !           419:        /* if no command, then just move the cursor to the mark */
        !           420:        if (!*scan)
        !           421:        {
        !           422:                if (tomark != MARK_UNSET)
        !           423:                        cursor = tomark;
        !           424:                return;
        !           425:        }
        !           426: 
        !           427:        /* figure out how long the command name is */
        !           428:        if (!isalpha(*scan))
        !           429:        {
        !           430:                cmdlen = 1;
        !           431:        }
        !           432:        else
        !           433:        {
        !           434:                for (cmdlen = 1;
        !           435:                     isalpha(scan[cmdlen]);
        !           436:                     cmdlen++)
        !           437:                {
        !           438:                }
        !           439:        }
        !           440: 
        !           441:        /* lookup the command code */
        !           442:        for (cmdidx = 0;
        !           443:             cmdnames[cmdidx].name && strncmp(scan, cmdnames[cmdidx].name, cmdlen);
        !           444:             cmdidx++)
        !           445:        {
        !           446:        }
        !           447:        argt = cmdnames[cmdidx].argt;
        !           448:        cmd = cmdnames[cmdidx].code;
        !           449:        if (cmd == CMD_NULL)
        !           450:        {
        !           451:                msg("Unknown command \"%.*s\"", cmdlen, scan);
        !           452:                return;
        !           453:        }
        !           454: 
        !           455:        /* !!! if the command doesn't have NOBAR set, then replace | with \0 */
        !           456: 
        !           457:        /* if the command ended with a bang, set the forceit flag */
        !           458:        scan += cmdlen;
        !           459:        if ((argt & BANG) && *scan == '!')
        !           460:        {
        !           461:                scan++;
        !           462:                forceit = 1;
        !           463:        }
        !           464:        else
        !           465:        {
        !           466:                forceit = 0;
        !           467:        }
        !           468: 
        !           469:        /* skip any more whitespace, to leave scan pointing to arguments */
        !           470:        while (isspace(*scan))
        !           471:        {
        !           472:                scan++;
        !           473:        }
        !           474: 
        !           475:        /* a couple of special cases for filenames */
        !           476:        if (argt & XFILE)
        !           477:        {
        !           478:                /* if names were given, process them */
        !           479:                if (*scan)
        !           480:                {
        !           481:                        for (build = tmpblk.c, iswild = didsub = FALSE; *scan; scan++)
        !           482:                        {
        !           483:                                switch (*scan)
        !           484:                                {
        !           485:                                  case '\\':
        !           486:                                        if (scan[1] == '\\' || scan[1] == '%' || scan[1] == '#')
        !           487:                                        {
        !           488:                                                *build++ = *++scan;
        !           489:                                        }
        !           490:                                        else
        !           491:                                        {
        !           492:                                                *build++ = '\\';
        !           493:                                        }
        !           494:                                        break;
        !           495: 
        !           496:                                  case '%':
        !           497:                                        if (!*origname)
        !           498:                                        {
        !           499:                                                msg("No filename to substitute for %%");
        !           500:                                                return;
        !           501:                                        }
        !           502:                                        strcpy(build, origname);
        !           503:                                        while (*build)
        !           504:                                        {
        !           505:                                                build++;
        !           506:                                        }
        !           507:                                        didsub = TRUE;
        !           508:                                        break;
        !           509: 
        !           510:                                  case '#':
        !           511:                                        if (!*prevorig)
        !           512:                                        {
        !           513:                                                msg("No filename to substitute for #");
        !           514:                                                return;
        !           515:                                        }
        !           516:                                        strcpy(build, prevorig);
        !           517:                                        while (*build)
        !           518:                                        {
        !           519:                                                build++;
        !           520:                                        }
        !           521:                                        didsub = TRUE;
        !           522:                                        break;
        !           523: 
        !           524:                                  case '*':
        !           525:                                  case '?':
        !           526: #if !(MSDOS || TOS)
        !           527:                                  case '[':
        !           528:                                  case '`':
        !           529:                                  case '{': /* } */
        !           530:                                  case '$':
        !           531:                                  case '~':
        !           532: #endif
        !           533:                                        *build++ = *scan;
        !           534:                                        iswild = TRUE;
        !           535:                                        break;
        !           536: 
        !           537:                                  default:
        !           538:                                        *build++ = *scan;
        !           539:                                }
        !           540:                        }
        !           541:                        *build = '\0';
        !           542: 
        !           543:                        if (cmd == CMD_BANG
        !           544:                         || cmd == CMD_READ && tmpblk.c[0] == '!'
        !           545:                         || cmd == CMD_WRITE && tmpblk.c[0] == '!')
        !           546:                        {
        !           547:                                if (didsub)
        !           548:                                {
        !           549:                                        if (mode != MODE_EX)
        !           550:                                        {
        !           551:                                                addch('\n');
        !           552:                                        }
        !           553:                                        addstr(tmpblk.c);
        !           554:                                        addch('\n');
        !           555:                                        exrefresh();
        !           556:                                }
        !           557:                        }
        !           558:                        else
        !           559:                        {
        !           560:                                if (iswild && tmpblk.c[0] != '>')
        !           561:                                {
        !           562:                                        scan = wildcard(tmpblk.c);
        !           563:                                }
        !           564:                        }
        !           565:                }
        !           566:                else /* no names given, maybe assume origname */
        !           567:                {
        !           568:                        if (!(argt & NODFL))
        !           569:                        {
        !           570:                                strcpy(tmpblk.c, origname);
        !           571:                        }
        !           572:                        else
        !           573:                        {
        !           574:                                *tmpblk.c = '\0';
        !           575:                        }
        !           576:                }
        !           577: 
        !           578:                scan = tmpblk.c;
        !           579:        }
        !           580: 
        !           581:        /* bad arguments? */
        !           582:        if (!(argt & EXRCOK) && nlines < 1L)
        !           583:        {
        !           584:                msg("Can't use the \"%s\" command in a %s file", cmdnames[cmdidx].name, EXRC);
        !           585:                return;
        !           586:        }
        !           587:        if (!(argt & (ZERO | EXRCOK)) && frommark == MARK_UNSET)
        !           588:        {
        !           589:                msg("Can't use address 0 with \"%s\" command.", cmdnames[cmdidx].name);
        !           590:                return;
        !           591:        }
        !           592:        if (!(argt & FROM) && frommark != cursor && nlines >= 1L)
        !           593:        {
        !           594:                msg("Can't use address with \"%s\" command.", cmdnames[cmdidx].name);
        !           595:                return;
        !           596:        }
        !           597:        if (!(argt & TO) && tomark != frommark && nlines >= 1L)
        !           598:        {
        !           599:                msg("Can't use a range with \"%s\" command.", cmdnames[cmdidx].name);
        !           600:                return;
        !           601:        }
        !           602:        if (!(argt & EXTRA) && *scan)
        !           603:        {
        !           604:                msg("Extra characters after \"%s\" command.", cmdnames[cmdidx].name);
        !           605:                return;
        !           606:        }
        !           607:        if ((argt & NOSPC) && !(cmd == CMD_READ && (forceit || *scan == '!')))
        !           608:        {
        !           609:                build = scan;
        !           610: #ifndef CRUNCH
        !           611:                if ((argt & PLUS) && *build == '+')
        !           612:                {
        !           613:                        while (*build && !isspace(*build))
        !           614:                        {
        !           615:                                build++;
        !           616:                        }
        !           617:                        while (*build && isspace(*build))
        !           618:                        {
        !           619:                                build++;
        !           620:                        }
        !           621:                }
        !           622: #endif /* not CRUNCH */
        !           623:                for (; *build; build++)
        !           624:                {
        !           625:                        if (isspace(*build))
        !           626:                        {
        !           627:                                msg("Too many %s to \"%s\" command.",
        !           628:                                        (argt & XFILE) ? "filenames" : "arguments",
        !           629:                                        cmdnames[cmdidx].name);
        !           630:                                return;
        !           631:                        }
        !           632:                }
        !           633:        }
        !           634: 
        !           635:        /* some commands have special default ranges */
        !           636:        if (isdfl && (argt & DFLALL))
        !           637:        {
        !           638:                frommark = MARK_FIRST;
        !           639:                tomark = MARK_LAST;
        !           640:        }
        !           641:        else if (isdfl && (argt & DFLNONE))
        !           642:        {
        !           643:                frommark = tomark = 0L;
        !           644:        }
        !           645: 
        !           646:        /* write a newline if called from visual mode */
        !           647:        if ((argt & NL) && mode != MODE_EX && !exwrote)
        !           648:        {
        !           649:                addch('\n');
        !           650:                exrefresh();
        !           651:        }
        !           652: 
        !           653:        /* act on the command */
        !           654:        (*cmdnames[cmdidx].fn)(frommark, tomark, cmd, forceit, scan);
        !           655: }
        !           656: 
        !           657: 
        !           658: /* This function executes EX commands from a file.  It returns 1 normally, or
        !           659:  * 0 if the file could not be opened for reading.
        !           660:  */
        !           661: int doexrc(filename)
        !           662:        char    *filename;      /* name of a ".exrc" file */
        !           663: {
        !           664:        int     fd;             /* file descriptor */
        !           665:        int     len;            /* length of the ".exrc" file */
        !           666: 
        !           667: #ifdef CRUNCH
        !           668:        /* small address space - we need to conserve space */
        !           669: 
        !           670:        /* !!! kludge: we use U_text as the buffer.  This has the side-effect
        !           671:         * of interfering with the shift-U visual command.  Disable shift-U.
        !           672:         */
        !           673:        U_line = 0L;
        !           674: #else
        !           675: # if TINYSTACK
        !           676:        /* small stack - we need to conserve space */
        !           677: 
        !           678:        /* !!! kludge: we use U_text as the buffer.  This has the side-effect
        !           679:         * of interfering with the shift-U visual command.  Disable shift-U.
        !           680:         */
        !           681:        U_line = 0L;
        !           682: # else
        !           683:        /* This is how we would *like* to do it -- with a large buffer on the
        !           684:         * stack, so we can handle large .exrc files and also recursion.
        !           685:         */
        !           686:        char    U_text[4096];
        !           687: # endif
        !           688: #endif
        !           689: 
        !           690:        /* open the file, read it, and close */
        !           691:        fd = open(filename, O_RDONLY);
        !           692:        if (fd < 0)
        !           693:        {
        !           694:                return 0;
        !           695:        }
        !           696:        len = tread(fd, U_text, sizeof U_text);
        !           697:        close(fd);
        !           698: 
        !           699:        /* execute the string */
        !           700:        exstring(U_text, len, ctrl('V'));
        !           701: 
        !           702:        return 1;
        !           703: }
        !           704: 
        !           705: /* This function executes EX commands from a string.  The commands may be
        !           706:  * separated by newlines or by | characters.  It also handles quoting.
        !           707:  * Each individual command is limited to 132 bytes, but the total string
        !           708:  * may be longer.
        !           709:  */
        !           710: void exstring(buf, len, qchar)
        !           711:        char    *buf;   /* the commands to execute */
        !           712:        int     len;    /* the length of the string */
        !           713:        int     qchar;  /* the quote character -- ^V for file, or \ for kbd */
        !           714: {
        !           715:        char    single[133];    /* a single command */
        !           716:        char    *src, *dest;
        !           717:        int     i;
        !           718: 
        !           719:        /* find & do each command */
        !           720:        for (src = buf; src < &buf[len]; src++)
        !           721:        {
        !           722:                /* Copy a single command into single[].  Convert any quoted |
        !           723:                 * into a normal |, and stop at a newline or unquoted |.
        !           724:                 */
        !           725:                for (dest = single, i = 0;
        !           726:                     i < 132 && src < &buf[len] && *src != '\n' && *src != '|';
        !           727:                     src++, i++)
        !           728:                {
        !           729:                        if (src[0] == qchar && src[1] == '|')
        !           730:                        {
        !           731:                                src++;
        !           732:                        }
        !           733:                        *dest++ = *src;
        !           734:                }
        !           735:                *dest = '\0';
        !           736: 
        !           737:                /* do it */
        !           738:                doexcmd(single);
        !           739:        }
        !           740: }

unix.superglobalmegacorp.com

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