📄 edit.c
字号:
/* edit.c: * A simple buffer editor; primarily for use with TFS files. * * General notice: * This code is part of a boot-monitor package developed as a generic base * platform for embedded system designs. As such, it is likely to be * distributed to various projects beyond the control of the original * author. Please notify the author of any enhancements made or bugs found * so that all may benefit from the changes. In addition, notification back * to the author will allow the new user to pick up changes that may have * been made by other users after this version of the code was distributed. * * Note1: the majority of this code was edited with 4-space tabs. * Note2: as more and more contributions are accepted, the term "author" * is becoming a mis-representation of credit. * * Original author: Ed Sutter * Email: esutter@lucent.com * Phone: 908-582-2351 */#include "config.h"#if INCLUDE_EDIT#include "stddefs.h"#include "genlib.h"#include "tfs.h"#include "tfsprivate.h"#include "ctype.h"#include "cli.h"extern char *file_line_edit(char *);static int rmCR(char *,int);static int gotoline(char *,char *,char **,char *,int);static int searchfor(char *,char *,char **,char *);static int whatlineisthis(char *,char *);static int getrange(char *,int *,int *,char *,char *,char *);static void lnprbuf(char *,char *,char *);static void prbuf(char *,char *);static void prlno(int,int);static void deletelines(char *,int,char *,char **,char **);static char *prline(char *,char *);static char *skipwhite(char *);#define BREAK 1#define CONTINUE 2#define FALLTHROUGH 3#define INSERT 4#define COMMAND 5#define ESCAPE 0x1b#define ILCMAX 8voidefree(int size, char *buffer){ if (size != 0) free(buffer);}/* Help text while in the editor: */char *edithelp[] = { "Editor commands:", "d{LRNG} delete line",#if INCLUDE_LINEEDIT "e# edit line # (uses 'ksh/vi-like' command line editing)",#endif "i enter insert mode (use '.' to exit insert mode)", "a enter append mode (use '.' to exit append mode)", "j# join line '#' with line '#+1'", "P[LRNG] print buffer with line numbers", "p print buffer", "q[fname] quit edit, write file", "s[srchstr] goto line containing search string", "x exit edit, do not write file", "# goto line # (use '$' to go to last line)", ".+/-# goto line relative to current position", "", "Where...", "# represents a decimal number;", "LRNG represents a line number or inclusive line range (# or #-#);", 0,};/* Help text outside the editor: */char *EditHelp[] = { "Edit file or buffer", "-[b:c:f:i:rs:] [filename]", " -b {adr} specify buffer base address", " -c {cmd} in-line command", " -f {flgs} file flags (see tfs)", " -i {info} file info (see tfs)", " -m {size} specify allocation size for buffer", " -r do not automatically remove carriage returns from file", " -s {size} size of buffer", " -t convert tabs to spaces", 0,};intEdit(int argc,char *argv[]){ int i, opt, tfd, quit, mode, bsize; char ln[128], *lp, *cp, *cp1, *filename, *flags, *info; char *buffer, *bp; /* Buffer and pointer into buffer. */ char *eob; /* Current EOF pointer (max distance between */ /* bp and buffer). */ char *inlinecmd[ILCMAX]; /* If non-NULL, it points to a list of */ /* commands to be executed prior to going */ /* into interactive mode. */ int ilcidx; /* Index into in-line command table. */ int len; /* Length of the incoming line. */ int size; /* Size of buffer specified on command line. */ int cmdtot; /* Running total of incoming lines. */ int delcnt; /* Used by :d when a range is specified. */ int noCR; /* Set by -r option to remove Carriage Returns */ TFILE tstruct, *tfp; tfp = (TFILE *)0; size = bsize = 0; flags = filename = (char*)0; buffer = (char *)getAppRamStart(); info = (char *)0; noCR = 1; ilcidx = 0; for(i=0;i<8;i++) inlinecmd[i] = (char *)0; while ((opt = getopt(argc, argv, "b:c:f:i:m:rs:")) != -1) { switch (opt) { case 'b': buffer = (char *)strtol(optarg,(char **)0,0); break; case 'c': if (ilcidx < ILCMAX-1) inlinecmd[ilcidx++] = optarg; break; case 'f': flags = optarg; break; case 'i': info = optarg; break; case 'm': bsize = strtol(optarg,0,0); break; case 'r': noCR = 0; break; case 's': size = (int)strtol(optarg,(char **)0,0); break; default: return (CMD_PARAM_ERROR); } } if (bsize != 0) { buffer = malloc(bsize); if (!buffer) return(CMD_FAILURE); } if (argc == optind+1) { filename = argv[optind]; if (tfsfstat(filename,&tstruct) != -1) { tfp = &tstruct; size = TFS_SIZE(tfp); if ((bsize > 0) && (size > bsize)) { printf("Allocation too small\n"); efree(bsize,buffer); return(CMD_FAILURE); } tfd = tfsopen(filename,TFS_RDONLY,0); if (tfd < 0) { printf("%s: %s\n",filename,(char *)tfsctrl(TFS_ERRMSG,tfd,0)); efree(bsize,buffer); return(CMD_FAILURE); } else { tfsread(tfd,buffer,size); tfsclose(tfd,0); } } } if (noCR) size -= rmCR(buffer,size); bp = buffer; eob = buffer + size; if (!ilcidx) printf("Edit buffer = 0x%lx.\nType '?' for help\n",(ulong)buffer); quit = 0; cmdtot = 0; mode = COMMAND; while(!quit) { lp = ln; if (ilcidx > cmdtot) strcpy(ln,inlinecmd[cmdtot]); else if (ilcidx) { /* If ILC command set doesn't terminate */ /* the edit session, force it here. */ efree(bsize,buffer); return(CMD_SUCCESS); } else getline(ln,sizeof(ln),0); cmdtot++; if (mode == INSERT) { if (!strcmp(lp,".")) mode = COMMAND; else { len = strlen(lp) + 1; cp1 = eob + len; cp = eob; while(cp > bp) *--cp1 = *--cp; while(*lp) *bp++ = *lp++; *bp++ = '\n'; eob += len; } continue; } if (!strcmp(ln,"x")) { /* Exit editor now. */ efree(bsize,buffer); return(CMD_SUCCESS); } else if (!strcmp(ln,"?")) { /* Display help info. */ char **eh; eh = edithelp; while(*eh) printf("%s\n",*eh++); } else if (!strcmp(ln,"p")) /* Print buffer. */ prbuf(buffer,eob); else if (!strcmp(ln,"P")) /* Print buffer with lines. */ lnprbuf(buffer,bp,eob); else if (!strcmp(ln,"i")) /* Enter insert mode. */ mode = INSERT; else if (!strcmp(ln,"a")) { /* Enter insert mode at */ mode = INSERT; /* next line */ gotoline(".+1",buffer,&bp,eob,0); } else if (!strcmp(ln,"$")) { /* Goto last line. */ gotoline(ln,buffer,&bp,eob,0); gotoline(".-1",buffer,&bp,eob,1); } else if (isdigit(ln[0]) || (ln[0]=='.')) /* Goto line. */ gotoline(ln,buffer,&bp,eob,1); else if (ln[0] == 's') { /* Go to line containing string. */ char *str; str = skipwhite(&ln[1]); if (!*str) gotoline(".+1",buffer,&bp,eob,0); searchfor(str,buffer,&bp,eob); }#if INCLUDE_LINEEDIT else if (ln[0] == 'e') { char *copy, *cp2, crlf[2]; int oldlnsize, newlnsize, toendsize; if (gotoline(&ln[1],buffer,&bp,eob,0) == -1) continue; copy = malloc(sizeof(ln)); if (!copy) continue; cp = bp; cp1 = copy; oldlnsize = 0; while (*cp != 0x0a && *cp != 0x0d) { if (*cp == '\t') /* Tabs are replaced with spaces to */ *cp = ' '; /* eliminate whitespace confusion in */ putchar(*cp); /* the line editor. */ *cp1++ = *cp++; oldlnsize++; } crlf[0] = *cp; if (*cp != *(cp+1)) { crlf[1] = *(cp+1); if (*(cp+1) == 0x0a || *(cp+1) == 0x0d) oldlnsize++; } else { crlf[1] = 0; } oldlnsize++; *cp1++ = ESCAPE; *cp1 = 0; file_line_edit(copy); newlnsize = strlen(copy); toendsize = eob - (bp+oldlnsize); copy[newlnsize++] = crlf[0]; if (crlf[1] == 0x0d || crlf[1] == 0x0a) copy[newlnsize++] = crlf[1]; copy[newlnsize] = 0; if (oldlnsize == newlnsize) { memcpy(bp,copy,newlnsize); } else if (oldlnsize > newlnsize) { strcpy(bp,copy); memcpy(bp+newlnsize,cp+1,toendsize); } else { cp1 = eob-1; cp2 = (char *)(eob+(newlnsize-oldlnsize)-1); for(i=0;i<toendsize;i++) *cp2-- = *cp1--; memcpy(bp,copy,newlnsize); } eob -= oldlnsize; eob += newlnsize; free(copy); }#endif else if (ln[0] == 'P') { int range, first, last, currentline; range = getrange(&ln[1],&first,&last,buffer,bp,eob); if (range > 0) { char *bpcpy; bpcpy = bp; gotoline(".",buffer,&bpcpy,eob,0); currentline = whatlineisthis(buffer,bpcpy); if (gotoline(&ln[1],buffer,&bpcpy,eob,0) == -1) continue; for(i=first;i<=last;i++) { prlno(i,currentline); bpcpy = prline(bpcpy,eob); } } } else if (ln[0] == 'j') { /* Join line specified with next line */ char *tmpeob; if (gotoline(&ln[1],buffer,&bp,eob,0) == -1) continue; tmpeob=eob-1; while(bp < tmpeob) { if (*bp == '\n') { memcpy(bp,bp+1,eob-bp); eob--; break; } bp++; } } else if (ln[0] == 'd') { /* Delete line (or range of lines) */ delcnt = getrange(&ln[1],0,0,buffer,bp,eob); deletelines(&ln[1],delcnt,buffer,&bp,&eob); } else if (ln[0] == 'q') { /* Quit edit, if filename is present */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -