2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
9 static char sccsid
[] = "$Id: ex_write.c,v 8.19 1993/12/18 11:28:32 bostic Exp $ (Berkeley) $Date: 1993/12/18 11:28:32 $";
12 #include <sys/types.h>
24 enum which
{WQ
, WRITE
, XIT
};
26 static int exwr
__P((SCR
*, EXF
*, EXCMDARG
*, enum which
));
29 * ex_wq -- :wq[!] [>>] [file]
40 if (exwr(sp
, ep
, cmdp
, WQ
))
43 force
= F_ISSET(cmdp
, E_FORCE
);
44 if (!force
&& ep
->refcnt
<= 1 && file_unedited(sp
) != NULL
) {
46 "More files to edit; use \":n\" to go to the next file");
50 F_SET(sp
, force
? S_EXIT_FORCE
: S_EXIT
);
55 * ex_write -- :write[!] [>>] [file]
60 ex_write(sp
, ep
, cmdp
)
65 return (exwr(sp
, ep
, cmdp
, WRITE
));
70 * ex_xit -- :x[it]! [file]
72 * Write out any modifications and quit.
82 if (F_ISSET((ep
), F_MODIFIED
) && exwr(sp
, ep
, cmdp
, XIT
))
85 force
= F_ISSET(cmdp
, E_FORCE
);
86 if (!force
&& ep
->refcnt
<= 1 && file_unedited(sp
) != NULL
) {
88 "More files to edit; use \":n\" to go to the next file");
92 F_SET(sp
, force
? S_EXIT_FORCE
: S_EXIT
);
98 * The guts of the ex write commands.
101 exwr(sp
, ep
, cmdp
, cmd
)
112 /* All write commands can have an associated '!'. */
113 LF_INIT(FS_POSSIBLE
);
114 if (F_ISSET(cmdp
, E_FORCE
))
117 /* Skip any leading whitespace. */
119 for (p
= cmdp
->argv
[0]->bp
; *p
&& isblank(*p
); ++p
);
121 /* If no arguments, just write the file back. */
122 if (cmdp
->argc
== 0 || *p
== '\0') {
123 if (F_ISSET(cmdp
, E_ADDR2_ALL
))
125 return (file_write(sp
, ep
,
126 &cmdp
->addr1
, &cmdp
->addr2
, NULL
, flags
));
129 /* If "write !" it's a pipe to a utility. */
131 if (cmd
== WRITE
&& *p
== '!') {
132 for (++p
; *p
&& isblank(*p
); ++p
);
134 msgq(sp
, M_ERR
, "Usage: %s.", cmdp
->cmd
->usage
);
137 /* Expand the argument. */
138 if (argv_exp1(sp
, ep
, cmdp
, p
, strlen(p
), 0))
140 if (filtercmd(sp
, ep
, &cmdp
->addr1
, &cmdp
->addr2
,
141 &rm
, cmdp
->argv
[1]->bp
, FILTER_WRITE
))
147 /* If "write >>" it's an append to a file. */
148 if (cmd
!= XIT
&& p
[0] == '>' && p
[1] == '>') {
151 /* Skip ">>" and whitespace. */
152 for (p
+= 2; *p
&& isblank(*p
); ++p
);
155 /* Build an argv so we get an argument count and file expansion. */
156 if (argv_exp2(sp
, ep
, cmdp
, p
, strlen(p
), 0))
159 switch (cmdp
->argc
) {
162 * Nothing to expand, write the current file.
164 * Should never happen, already checked this case.
169 /* One new argument, write it. */
170 name
= cmdp
->argv
[exp
->argsoff
- 1]->bp
;
171 set_alt_name(sp
, name
);
174 /* If expanded to more than one argument, object. */
175 msgq(sp
, M_ERR
, "%s expanded into too many file names",
177 msgq(sp
, M_ERR
, "Usage: %s.", cmdp
->cmd
->usage
);
181 if (F_ISSET(cmdp
, E_ADDR2_ALL
))
183 return (file_write(sp
, ep
, &cmdp
->addr1
, &cmdp
->addr2
, name
, flags
));
188 * Write a range of lines to a FILE *.
191 ex_writefp(sp
, ep
, name
, fp
, fm
, tm
, nlno
, nch
)
199 register u_long ccnt
, fline
, tline
;
213 * The vi filter code has multiple processes running simultaneously,
214 * and one of them calls ex_writefp(). The "unsafe" function calls
215 * in this code are to file_gline() and msgq(). File_gline() is safe,
216 * see the comment in filter.c:filtercmd() for details. We don't call
217 * msgq if the multiple process bit in the EXF is set.
220 * Historic vi permitted files of 0 length to be written. However,
221 * since the way vi got around dealing with "empty" files was to
222 * always have a line in the file no matter what, it wrote them as
223 * files of a single, empty line. We write empty files.
225 * "Alex, I'll take vi trivia for $1000."
228 for (; fline
<= tline
; ++fline
) {
229 if ((p
= file_gline(sp
, ep
, fline
, &len
)) == NULL
)
231 if (fwrite(p
, 1, len
, fp
) != len
) {
232 msgq(sp
, M_SYSERR
, name
);
237 if (putc('\n', fp
) != '\n')
242 if (!F_ISSET(ep
, F_MULTILOCK
))
243 msgq(sp
, M_SYSERR
, name
);
248 *nlno
= tm
->lno
== 0 ? 0 : tm
->lno
- fm
->lno
+ 1;