📄 tmp.c
字号:
/* tmp.c *//* Author: * Steve Kirkendall * 14407 SW Teal Blvd. #C * Beaverton, OR 97005 * kirkenda@cs.pdx.edu *//* This file contains functions which create & readback a TMPFILE */#include "config.h"#include "vi.h"#if TOS# include <stat.h>#else# if OSK# include "osk.h"# else# if AMIGA# include "amistat.h"# else# include <sys/stat.h># endif# endif#endif#if TURBOC# include <process.h>#endif#ifndef NO_MODELINESstatic void do_modelines(l, stop) long l; /* line number to start at */ long stop; /* line number to stop at */{ char *str; /* used to scan through the line */ char *start; /* points to the start of the line */ char buf[80]; /* if modelines are disabled, then do nothing */ if (!*o_modelines) { return; } /* for each line... */ for (; l <= stop; l++) { /* for each position in the line.. */ for (str = fetchline(l); *str; str++) { /* if it is the start of a modeline command... */ if ((str[0] == 'e' && str[1] == 'x' || str[0] == 'v' && str[1] == 'i') && str[2] == ':') { start = str += 3; /* find the end */ for (str = start + strlen(start); *--str != ':'; ) { } /* if it is a well-formed modeline, execute it */ if (str > start && str - start < sizeof buf) { strncpy(buf, start, (int)(str - start)); exstring(buf, str - start, '\\'); break; } } } }}#endif/* The FAIL() macro prints an error message and then exits. */#define FAIL(why,arg) mode = MODE_EX; msg(why, arg); endwin(); exit(9)/* This is the name of the temp file */static char tmpname[80];/* This function creates the temp file and copies the original file into it. * Returns if successful, or stops execution if it fails. */int tmpstart(filename) char *filename; /* name of the original file */{ int origfd; /* fd used for reading the original file */ struct stat statb; /* stat buffer, used to examine inode */ REG BLK *this; /* pointer to the current block buffer */ REG BLK *next; /* pointer to the next block buffer */ int inbuf; /* number of characters in a buffer */ int nread; /* number of bytes read */ REG int j, k; int i; long nbytes; /* switching to a different file certainly counts as a change */ changes++; redraw(MARK_UNSET, FALSE); /* open the original file for reading */ *origname = '\0'; if (filename && *filename) { strcpy(origname, filename); origfd = open(origname, O_RDONLY); if (origfd < 0 && errno != ENOENT) { msg("Can't open \"%s\"", origname); return tmpstart(""); } if (origfd >= 0) { if (stat(origname, &statb) < 0) { FAIL("Can't stat \"%s\"", origname); }#if TOS if (origfd >= 0 && (statb.st_mode & S_IJDIR))#else# if OSK if (origfd >= 0 && (statb.st_mode & S_IFDIR))# else if (origfd >= 0 && (statb.st_mode & S_IFMT) != S_IFREG)# endif#endif { msg("\"%s\" is not a regular file", origname); return tmpstart(""); } } else { stat(".", &statb); } if (origfd >= 0) { origtime = statb.st_mtime;#if OSK if (*o_readonly || !(statb.st_mode & ((getuid() >> 16) == 0 ? S_IOWRITE | S_IWRITE : ((statb.st_gid != (getuid() >> 16) ? S_IOWRITE : S_IWRITE)))))#endif#if AMIGA || MSDOS || (TOS && defined(__GNUC__)) if (*o_readonly || !(statb.st_mode & S_IWRITE))#endif#if TOS && !defined(__GNUC__) if (*o_readonly || (statb.st_mode & S_IJRON))#endif#if ANY_UNIX if (*o_readonly || !(statb.st_mode & ((geteuid() == 0) ? 0222 : ((statb.st_uid != geteuid() ? 0022 : 0200)))))#endif#if VMS if (*o_readonly)#endif { setflag(file, READONLY); } } else { origtime = 0L; } } else { setflag(file, NOFILE); origfd = -1; origtime = 0L; stat(".", &statb); } /* make a name for the tmp file */ tmpnum++;#if MSDOS || TOS /* MS-Dos doesn't allow multiple slashes, but supports drives * with current directories. * This relies on TMPNAME beginning with "%s\\"!!!! */ strcpy(tmpname, o_directory); if ((i = strlen(tmpname)) && !strchr(":/\\", tmpname[i-1])) tmpname[i++]=SLASH; sprintf(tmpname+i, TMPNAME+3, getpid(), tmpnum);#else sprintf(tmpname, TMPNAME, o_directory, getpid(), tmpnum);#endif /* make sure nobody else is editing the same file */ if (access(tmpname, 0) == 0) { FAIL("Temp file \"%s\" already exists?", tmpname); } /* create the temp file */#if ANY_UNIX close(creat(tmpname, 0600)); /* only we can read it */#else close(creat(tmpname, FILEPERMS)); /* anybody body can read it, alas */#endif tmpfd = open(tmpname, O_RDWR | O_BINARY); if (tmpfd < 0) { FAIL("Can't create temp file... Does directory \"%s\" exist?", o_directory); return 1; } /* allocate space for the header in the file */ write(tmpfd, hdr.c, (unsigned)BLKSIZE); write(tmpfd, tmpblk.c, (unsigned)BLKSIZE);#ifndef NO_RECYCLE /* initialize the block allocator */ /* This must already be done here, before the first attempt * to write to the new file! GB */ garbage();#endif /* initialize lnum[] */ for (i = 1; i < MAXBLKS; i++) { lnum[i] = INFINITY; } lnum[0] = 0; /* if there is no original file, then create a 1-line file */ if (origfd < 0) { hdr.n[0] = 0; /* invalid inode# denotes new file */ this = blkget(1); /* get the new text block */ strcpy(this->c, "\n"); /* put a line in it */ lnum[1] = 1L; /* block 1 ends with line 1 */ nlines = 1L; /* there is 1 line in the file */ nbytes = 1L; if (*origname) { msg("\"%s\" [NEW FILE] 1 line, 1 char", origname); } else { msg("\"[NO FILE]\" 1 line, 1 char"); } } else /* there is an original file -- read it in */ { nbytes = nlines = 0; /* preallocate 1 "next" buffer */ i = 1; next = blkget(i); inbuf = 0; /* loop, moving blocks from orig to tmp */ for (;;) { /* "next" buffer becomes "this" buffer */ this = next; /* read [more] text into this block */ nread = tread(origfd, &this->c[inbuf], BLKSIZE - 1 - inbuf); if (nread < 0) { close(origfd); close(tmpfd); tmpfd = -1; unlink(tmpname); FAIL("Error reading \"%s\"", origname); } /* convert NUL characters to something else */ for (j = k = inbuf; k < inbuf + nread; k++) { if (!this->c[k]) { setflag(file, HADNUL); this->c[j++] = 0x80; }#ifndef CRUNCH else if (*o_beautify && this->c[k] < ' ' && this->c[k] > 0) { if (this->c[k] == '\t' || this->c[k] == '\n' || this->c[k] == '\f') { this->c[j++] = this->c[k]; } else if (this->c[k] == '\b') { /* delete '\b', but complain */ setflag(file, HADBS); } /* else silently delete control char */ }#endif else { this->c[j++] = this->c[k]; } } inbuf = j; /* if the buffer is empty, quit */ if (inbuf == 0) { goto FoundEOF; }#if MSDOS || TOS/* BAH! MS text mode read fills inbuf, then compresses eliminating \r but leaving garbage at end of buf. The same is true for TURBOC. GB. */ memset(this->c + inbuf, '\0', BLKSIZE - inbuf);#endif /* search backward for last newline */ for (k = inbuf; --k >= 0 && this->c[k] != '\n';) { } if (k++ < 0) { if (inbuf >= BLKSIZE - 1) { k = 80; } else { k = inbuf; } } /* allocate next buffer */ next = blkget(++i); /* move fragmentary last line to next buffer */ inbuf -= k; for (j = 0; k < BLKSIZE; j++, k++) { next->c[j] = this->c[k]; this->c[k] = 0; } /* if necessary, add a newline to this buf */ for (k = BLKSIZE - inbuf; --k >= 0 && !this->c[k]; ) { } if (this->c[k] != '\n') { setflag(file, ADDEDNL); this->c[k + 1] = '\n'; } /* count the lines in this block */ for (k = 0; k < BLKSIZE && this->c[k]; k++) { if (this->c[k] == '\n') { nlines++; } nbytes++; } lnum[i - 1] = nlines; }FoundEOF: /* if this is a zero-length file, add 1 line */ if (nlines == 0) { this = blkget(1); /* get the new text block */ strcpy(this->c, "\n"); /* put a line in it */ lnum[1] = 1; /* block 1 ends with line 1 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -