heirloom-ed
changeset 0:1493bea5ac22 0.1
Initial version of the standalone heirloom-ed
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Mon, 05 Sep 2011 16:31:35 +0200 |
parents | |
children | db609ba8ab93 |
files | LICENSE README ed.1 ed.c makefile regexp.h regexpr.c regexpr.h sigrelse.c sigset.c sigset.h |
diffstat | 11 files changed, 5368 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/LICENSE Mon Sep 05 16:31:35 2011 +0200 1.3 @@ -0,0 +1,1 @@ 1.4 +Look into the source files directly.
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/README Mon Sep 05 16:31:35 2011 +0200 2.3 @@ -0,0 +1,22 @@ 2.4 +Ed -- The Standard Text Editor 2.5 +============================== 2.6 + 2.7 +This version of ed had been cut out of Gunnar Ritter's Heirloom Toolchest. 2.8 +The reason for doing so is to have Heirloom ed quickly at hand when I am 2.9 +annoyed again by GNU ed. Having to configure and install the complete 2.10 +Heirloom Toolchest is more than I usually want. This ed is slightly 2.11 +stripped down as only the traditional variant gets created. Any references 2.12 +to the other variants and features only in them are removed from the man 2.13 +page. Parts of libcommon had been ripped out and included directly. Thus 2.14 +the makefile had been reworked. 2.15 + 2.16 +To install do: 2.17 + 2.18 + vi makefile 2.19 + make 2.20 + make install 2.21 + 2.22 + 2.23 +2011-09-05 2.24 +markus schnalke <meillo@marmaro.de> 2.25 +http://hg.marmaro.de/heirloom-ed
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/ed.1 Mon Sep 05 16:31:35 2011 +0200 3.3 @@ -0,0 +1,914 @@ 3.4 +'\" t 3.5 +.\" Sccsid @(#)ed.1 1.48 (gritter) 6/22/05 3.6 +.\" Parts taken from ed(1), Unix 7th edition: 3.7 +.\" Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. 3.8 +.\" 3.9 +.\" Redistribution and use in source and binary forms, with or without 3.10 +.\" modification, are permitted provided that the following conditions 3.11 +.\" are met: 3.12 +.\" Redistributions of source code and documentation must retain the 3.13 +.\" above copyright notice, this list of conditions and the following 3.14 +.\" disclaimer. 3.15 +.\" Redistributions in binary form must reproduce the above copyright 3.16 +.\" notice, this list of conditions and the following disclaimer in the 3.17 +.\" documentation and/or other materials provided with the distribution. 3.18 +.\" All advertising materials mentioning features or use of this software 3.19 +.\" must display the following acknowledgement: 3.20 +.\" This product includes software developed or owned by Caldera 3.21 +.\" International, Inc. 3.22 +.\" Neither the name of Caldera International, Inc. nor the names of 3.23 +.\" other contributors may be used to endorse or promote products 3.24 +.\" derived from this software without specific prior written permission. 3.25 +.\" 3.26 +.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA 3.27 +.\" INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 3.28 +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 3.29 +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3.30 +.\" ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE 3.31 +.\" LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR 3.32 +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3.33 +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 3.34 +.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 3.35 +.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 3.36 +.\" OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 3.37 +.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3.38 +.TH ED 1 "6/22/05" "Heirloom Toolchest" "User Commands" 3.39 +.if t .ds q \(aa 3.40 +.if n .ds q ' 3.41 +.SH NAME 3.42 +ed \- text editor 3.43 +.SH SYNOPSIS 3.44 +\fBed\fR [\fB\-\fR\ |\ \fB\-s\fR] [\fB\-p\fI\ prompt\fR] [\fIname\fR] 3.45 +.SH DESCRIPTION 3.46 +.I Ed 3.47 +is the standard text editor. 3.48 +.PP 3.49 +If a 3.50 +.I name 3.51 +argument is given, 3.52 +.I ed 3.53 +simulates an 3.54 +.I e 3.55 +command (see below)\| on the named file; that is to say, 3.56 +the file is read into 3.57 +.IR ed 's 3.58 +buffer so that it can be edited. 3.59 +The optional 3.60 +.B \- 3.61 +or 3.62 +.B \-s 3.63 +suppresses the printing 3.64 +of character counts by 3.65 +.IR e , 3.66 +.IR r , 3.67 +and 3.68 +.I w 3.69 +commands, 3.70 +and of the `!' after completion of a shell command. 3.71 +.PP 3.72 +With the 3.73 +.B \-p 3.74 +option, 3.75 +the given 3.76 +.I prompt 3.77 +string is printed before each command is read. 3.78 +.PP 3.79 +.I Ed 3.80 +operates on a copy of any file it is editing; changes made 3.81 +in the copy have no effect on the file until a 3.82 +.IR w "" 3.83 +(write)\| 3.84 +command is given. 3.85 +The copy of the text being edited resides 3.86 +in a temporary file called the 3.87 +.IR buffer . 3.88 +.PP 3.89 +The editor supports format specifications as defined in 3.90 +.IR fspec (5). 3.91 +If the terminal is configured to expand tabulators 3.92 +(as enabled with 3.93 +.I stty tab3 3.94 +or 3.95 +.IR "stty \-tabs"), 3.96 +and the first line of the file being edited 3.97 +contains a format specification, 3.98 +the 3.99 +.I t 3.100 +and 3.101 +.I s 3.102 +are interpreted, 3.103 +that is, tabulators are expanded and lines are truncated 3.104 +when printing to the terminal. For example, 3.105 +.RS 3.106 +<:t\-f s72:> 3.107 +.sp 3.108 +.RE 3.109 +selects FORTRAN format and truncates lines at 72 characters. 3.110 +No expansion or truncation is performed by 3.111 +.I ed 3.112 +when input is typed to the terminal. 3.113 +.PP 3.114 +Commands to 3.115 +.I ed 3.116 +have a simple and regular structure: zero or 3.117 +more 3.118 +.I addresses 3.119 +followed by a single character 3.120 +.I command, 3.121 +possibly 3.122 +followed by parameters to the command. 3.123 +These addresses specify one or more lines in the buffer. 3.124 +Missing addresses are supplied by default. 3.125 +.PP 3.126 +In general, only one command may appear on a line. 3.127 +Certain commands allow the 3.128 +addition of text to the buffer. 3.129 +While 3.130 +.I ed 3.131 +is accepting text, it is said 3.132 +to be in 3.133 +.I "input mode." 3.134 +In this mode, no commands are recognized; 3.135 +all input is merely collected. 3.136 +Input mode is left by typing a period `\fB.\fR' alone at the 3.137 +beginning of a line. 3.138 +.PP 3.139 +.I Ed 3.140 +supports a limited form of 3.141 +.I "regular expression" 3.142 +notation. 3.143 +A regular expression specifies 3.144 +a set of strings of characters. 3.145 +A member of this set of strings is said to be 3.146 +.I matched 3.147 +by the regular expression. 3.148 +In the following specification for regular expressions 3.149 +the word `character' means any character but newline. 3.150 +.B ed 3.151 +uses simple regular expressions. 3.152 +.SS "Simple Regular Expressions" 3.153 +.IP 1. 3.154 +Any character except a special character 3.155 +matches itself. 3.156 +Special characters are 3.157 +the regular expression delimiter plus 3.158 +.RB \e\|[\| . 3.159 +and sometimes ^\|*\|$. 3.160 +.IP 2. 3.161 +A 3.162 +.B .\& 3.163 +matches any character. 3.164 +.IP 3. 3.165 +A \fB\e\fR followed by any character except a digit 3.166 +or (\|) {\|} <\|> matches that character. 3.167 +.IP 4. 3.168 +A nonempty string 3.169 +.I s 3.170 +bracketed 3.171 +\fB[\fI\|s\|\fB]\fR 3.172 +(or 3.173 +\fB[^\fIs\|\fB]\fR) 3.174 +forms a \fIbracket expression\fR that 3.175 +matches any character in (or not in) 3.176 +.I s. 3.177 +In 3.178 +.I s, 3.179 +\e has no special meaning, and ] may only appear as 3.180 +the first letter. 3.181 +A substring 3.182 +\fIa\fB\-\fIb\fR, 3.183 +with 3.184 +.I a 3.185 +and 3.186 +.I b 3.187 +in ascending ASCII order, stands for the inclusive 3.188 +range of ASCII characters. 3.189 +.IP 5. 3.190 +A regular expression of form 1-4 followed by \fB*\fR matches a sequence of 3.191 +0 or more matches of the regular expression. 3.192 +.IP 6. 3.193 +A regular expression of form 1-4 3.194 +followed by \fB\e{\fIm\fB,\fIn\fB\e}\fR 3.195 +forms an \fIinterval expression\fR that 3.196 +matches a sequence of \fIm\fR through \fIn\fR matches, inclusive, 3.197 +of the regular expression. 3.198 +The values of \fIm\fR and \fIn\fR must be non-negative 3.199 +and smaller than 256. 3.200 +The form \fB\e{\fIm\fB\e}\fR matches exactly \fIm\fR occurrences, 3.201 +\fB\e{\fIm\fB,\e}\fR matches at least \fIm\fR occurrences. 3.202 +.IP 7. 3.203 +The sequence \fB\e<\fR forces the match 3.204 +to occur only at the beginning of a ``variable'' or ``word''; 3.205 +that is, either at the beginning of a line, 3.206 +or just before a letter, digit or underline 3.207 +and after a character not one of these. 3.208 +.IP 8. 3.209 +The sequence \fB\e>\fR matches the end 3.210 +of a ``variable'' or ``word'', 3.211 +i.\|e. either the end of the line 3.212 +or before character which is neither a letter, 3.213 +nor a digit, nor the underline character. 3.214 +.IP 9. 3.215 +A regular expression, 3.216 +.I x, 3.217 +of form 1-11, parenthesized 3.218 +\fB\e(\fI\|x\|\fB\e)\fR 3.219 +is called a \fIsubexpression\fR and 3.220 +matches what 3.221 +.I x 3.222 +matches. 3.223 +.IP 10. 3.224 +A \fB\e\fR followed by a digit 3.225 +.I n 3.226 +forms a \fIbackreference\fR and 3.227 +matches a copy of the string that the 3.228 +parenthesized regular expression beginning with the 3.229 +.IR n th 3.230 +\e( matched. 3.231 +.IP 11. 3.232 +A regular expression of form 1-11, 3.233 +.I x, 3.234 +followed by a regular expression of form 1-10, 3.235 +.I y 3.236 +matches a match for 3.237 +.I x 3.238 +followed by a match for 3.239 +.I y, 3.240 +with the 3.241 +.I x 3.242 +match being as long as possible while still permitting a 3.243 +.I y 3.244 +match. 3.245 +.IP 12. 3.246 +A regular expression of form 1-11 preceded by \fB^\fR 3.247 +(or followed by \fB$\fR), is constrained to matches that 3.248 +begin at the left (or end at the right) end of a line 3.249 +(\fIanchoring\fR). 3.250 +.IP 13. 3.251 +A regular expression of form 1-12 picks out the 3.252 +longest among the leftmost matches in a line. 3.253 +.IP 14. 3.254 +An empty regular expression stands for a copy of the 3.255 +last regular expression encountered. 3.256 +.PP 3.257 +Regular expressions are used in addresses to specify 3.258 +lines and in one command 3.259 +(see 3.260 +.I s 3.261 +below)\| 3.262 +to specify a portion of a line which is to be replaced. 3.263 +If it is desired to use one of 3.264 +the regular expression metacharacters as an ordinary 3.265 +character, that character may be preceded by `\e'. 3.266 +This also applies to the character bounding the regular 3.267 +expression (often `/')\| and to `\e' itself. 3.268 +.PP 3.269 +To understand addressing in 3.270 +.I ed 3.271 +it is necessary to know that at any time there is a 3.272 +.I "current line." 3.273 +Generally speaking, the current line is 3.274 +the last line affected by a command; however, 3.275 +the exact effect on the current line 3.276 +is discussed under the description of 3.277 +the command. 3.278 +Addresses are constructed as follows. 3.279 +.TP 3.280 +1. 3.281 +The character `\fB.\fR' addresses the current line. 3.282 +.TP 3.283 +2. 3.284 +The character `\fB$\fR' addresses the last line of the buffer. 3.285 +.TP 3.286 +3. 3.287 +A decimal number 3.288 +.I n 3.289 +addresses the 3.290 +.IR n -th 3.291 +line of the buffer. 3.292 +.TP 3.293 +4. 3.294 +`\fB\(fm\fIx\fR' addresses the line marked with the name 3.295 +.IR x , 3.296 +which must be a lower-case letter. 3.297 +Lines are marked with the 3.298 +.I k 3.299 +command described below. 3.300 +.TP 3.301 +5. 3.302 +A regular expression enclosed in slashes `\fB/\fR' addresses 3.303 +the line found by searching forward from the current line 3.304 +and stopping at the first line containing a 3.305 +string that matches the regular expression. 3.306 +If necessary the search wraps around to the beginning of the 3.307 +buffer. 3.308 +.TP 3.309 +6. 3.310 +A regular expression enclosed in queries `\fB?\fR' addresses 3.311 +the line found by searching backward from the current line 3.312 +and stopping at the first line containing 3.313 +a string that matches the regular expression. 3.314 +If necessary 3.315 +the search wraps around to the end of the buffer. 3.316 +.TP 3.317 +7. 3.318 +An address followed by a plus sign `\fB+\fR' 3.319 +or a minus sign `\fB\-\fR' followed by a decimal number 3.320 +specifies that address plus 3.321 +(resp. minus)\| the indicated number of lines. 3.322 +The plus sign may be omitted. 3.323 +.TP 3.324 +8. 3.325 +If an address begins with `\fB+\fR' or `\fB\-\fR' 3.326 +the addition or subtraction is taken with respect to the current line; 3.327 +e.g. `\-5' is understood to mean `\fB.\fR\-5'. 3.328 +.TP 3.329 +9. 3.330 +If an address ends with `\fB+\fR' or `\fB\-\fR', 3.331 +then 1 is added (resp. subtracted). 3.332 +As a consequence of this rule and rule 8, 3.333 +the address `\-' refers to the line before the current line. 3.334 +Moreover, 3.335 +trailing 3.336 +`+' and `\-' characters 3.337 +have cumulative effect, so `\-\-' refers to the current 3.338 +line less 2. 3.339 +.TP 3.340 +10. 3.341 +To maintain compatibility with earlier versions of the editor, 3.342 +the character `\fB^\fR' in addresses is 3.343 +equivalent to `\-'. 3.344 +.PP 3.345 +Commands may require zero, one, or two addresses. 3.346 +Commands which require no addresses regard the presence 3.347 +of an address as an error. 3.348 +Commands which accept one or two addresses 3.349 +assume default addresses when insufficient are given. 3.350 +If more addresses are given than such a command requires, 3.351 +the last one or two (depending on what is accepted)\| are used. 3.352 +.PP 3.353 +Addresses are separated from each other typically by a comma 3.354 +`\fB,\fR'. 3.355 +They may also be separated by a semicolon 3.356 +`\fB;\fR'. 3.357 +In this case the current line `\fB.\fR' is set to 3.358 +the previous address before the next address is interpreted. 3.359 +This feature can be used to determine the starting 3.360 +line for forward and backward searches (`/', `?')\|. 3.361 +The second address of any two-address sequence 3.362 +must correspond to a line following the line corresponding to the first address. 3.363 +.PP 3.364 +Omission of the first address causes 3.365 +the first line to be used with `,', 3.366 +or the current line with `;', respectively; 3.367 +if the second address is also omitted, 3.368 +the last line of the buffer is used. 3.369 +Thus a single `,' specifies the entire contents of the buffer, 3.370 +and a single `;' specifies the contents 3.371 +ranging from the current line to the last one. 3.372 +.PP 3.373 +In the following list of 3.374 +.I ed 3.375 +commands, the default addresses 3.376 +are shown in parentheses. 3.377 +The parentheses are not part of 3.378 +the address, but are used to show that the given addresses are 3.379 +the default. 3.380 +.PP 3.381 +As mentioned, it is generally illegal for more than one 3.382 +command to appear on a line. 3.383 +However, most commands may be suffixed by `p', `l', or `n', 3.384 +in which case 3.385 +the current line is either 3.386 +printed, listed, or numbered respectively 3.387 +in the way discussed below. 3.388 +.TP 5 3.389 +\fR(\|\fI.\|\fR)\fB\|a\fR 3.390 +.br 3.391 +.ns 3.392 +.TP 5 3.393 +<text> 3.394 +.br 3.395 +.ns 3.396 +.TP 5 3.397 +.B . 3.398 +.br 3.399 +The append command reads the given text 3.400 +and appends it after the addressed line. 3.401 +`\fB.\fR' is left 3.402 +on the last line input, if there 3.403 +were any, otherwise at the addressed line. 3.404 +Address `0' is legal for this command; text is placed 3.405 +at the beginning of the buffer. 3.406 +.TP 5 3.407 +\fR(\|\fI.\|\fB,\|\fI.\|\fR)\|\fBc\fR 3.408 +.br 3.409 +.ns 3.410 +.TP 5 3.411 +<text> 3.412 +.br 3.413 +.ns 3.414 +.TP 5 3.415 +.B . 3.416 +.br 3.417 +The change 3.418 +command deletes the addressed lines, then accepts input 3.419 +text which replaces these lines. 3.420 +`\fB.\fR' is left at the last line input; if there were none, 3.421 +it is left at the line preceding the deleted lines. 3.422 +.TP 5 3.423 +\fR(\|\fI.\|\fB,\|\fI.\|\fR)\|\fBd\fR 3.424 +The delete command deletes the addressed lines from the buffer. 3.425 +The line originally after the last line deleted becomes the current line; 3.426 +if the lines deleted were originally at the end, 3.427 +the new last line becomes the current line. 3.428 +.TP 5 3.429 +\fBe\ \fIfilename\fR 3.430 +The edit 3.431 +command causes the entire contents of the buffer to be deleted, 3.432 +and then the named file to be read in. 3.433 +`\fB.\fR' is set to the last line of the buffer. 3.434 +The number of characters read is typed. 3.435 +`\fIfilename\fR' is remembered for possible use as a default file name 3.436 +in a subsequent 3.437 +.I r 3.438 +or 3.439 +.I w 3.440 +command. 3.441 +If `\fIfilename\fR' is missing, the remembered name is used. 3.442 +A `\fIfilename\fR' starting with a `\fB!\fR' 3.443 +causes the output of the shell command following this character 3.444 +to be read in. 3.445 +.TP 5 3.446 +\fBE\ \fIfilename\fR 3.447 +This command is the same as 3.448 +.IR e , 3.449 +except that no diagnostic results when no 3.450 +.I w 3.451 +has been given since the last buffer alteration. 3.452 +.TP 5 3.453 +\fBf\ \fIfilename\fR 3.454 +The filename command prints the currently remembered file name. 3.455 +If `\fIfilename\fR' is given, 3.456 +the currently remembered file name is changed to `\fIfilename\fR'. 3.457 +.TP 5 3.458 +\fR(\fI1\fB,\fI$\fR)\|\fBg/\fIregular expression\fB/\fIcommand list\fR 3.459 +In the global 3.460 +command, the first step is to mark every line which matches 3.461 +the given \fIregular expression\fR. 3.462 +Then for every such line, the 3.463 +given \fIcommand list\fR is executed 3.464 +with `\fB.\fR' initially set to that line. 3.465 +A single command or the first of multiple commands 3.466 +appears on the same line with the global command. 3.467 +All lines of a multi-line list except the last line must be ended with `\e'. 3.468 +.I A, 3.469 +.I i, 3.470 +and 3.471 +.I c 3.472 +commands and associated input are permitted; 3.473 +the `\fB.\fR' terminating input mode may be omitted if it would be on the 3.474 +last line of the command list. 3.475 +The commands 3.476 +.I g 3.477 +and 3.478 +.I v 3.479 +are not permitted in the command list. 3.480 +.TP 5 3.481 +\fR(\fI1\fB,\fI$\fR)\|\fBG/\fIregular expression\fB/\fR 3.482 +The interactive global command 3.483 +first marks every line matching the given \fIregular expression\fR. 3.484 +Then each line is printed 3.485 +and a command is read and executed for this line. 3.486 +A single newline character causes the line to remain unchanged, 3.487 +an isolated `\fB&\fR' repeats the command given for the previous line. 3.488 +The command can be terminated by an interrupt signal. 3.489 +.TP 5 3.490 +.B h 3.491 +This command prints a verbose description for the 3.492 +last error encountered. 3.493 +.TP 3.494 +.B H 3.495 +This command acts like the 3.496 +.I h 3.497 +command, 3.498 +but also causes verbose descriptions to be printed 3.499 +on all following error conditions. 3.500 +Another 3.501 +.I H 3.502 +turns verbose mode off. 3.503 +.TP 5 3.504 +\fR(\|\fI.\|\fR)\|\fBi\fR 3.505 +.br 3.506 +.ns 3.507 +.TP 5 3.508 +<text> 3.509 +.br 3.510 +.ns 3.511 +.TP 5 3.512 +.B . 3.513 +.br 3.514 +This command inserts the given text before the addressed line. 3.515 +`\fB.\fR' is left at the last line input, or, if there were none, 3.516 +at the line before the addressed line. 3.517 +This command differs from the 3.518 +.I a 3.519 +command only in the placement of the 3.520 +text. 3.521 +.TP 5 3.522 +\fR(\|\fI.\|\fB,\|\fI.+1\fR)\|\fBj\fR 3.523 +This command joins the addressed lines into a single line; 3.524 +intermediate newlines simply disappear. 3.525 +`\fB.\fR' is left at the resulting line. 3.526 +.TP 5 3.527 +\fR(\fI.\fR)\|\fBk\fIx\fR 3.528 +The mark command marks the addressed line with 3.529 +name 3.530 +.IR x , 3.531 +which must be a lower-case letter. 3.532 +The address form `\(fm\fIx\fR' then addresses this line. 3.533 +.ne 2.5 3.534 +.TP 5 3.535 +\fR(\|\fI.\|\fB,\|\fI.\|\fR)\|\fBl\fR 3.536 +The list command 3.537 +prints the addressed lines in an unambiguous way: 3.538 +non-graphic control characters are printed in three-digit octal; 3.539 +Long lines are folded. 3.540 +The 3.541 +.I l 3.542 +command may be placed on the same line after any non-i/o 3.543 +command. 3.544 +.TP 5 3.545 +\fR(\|\fI.\|\fB,\|\fI.\|\fR)\|\fBm\fIa\fR 3.546 +The move command repositions the addressed lines after the line 3.547 +addressed by 3.548 +.IR a . 3.549 +The last of the moved lines becomes the current line. 3.550 +.TP 5 3.551 +\fR(\|\fI.\|\fB,\|\fI.\|\fR)\|\fBn\fR 3.552 +This command prints lines preceded by their line numbers. 3.553 +It otherwise acts like the 3.554 +.I p 3.555 +command described below. 3.556 +.TP 5 3.557 +\fR(\|\fI.\|\fB,\|\fI.\|\fR)\|\fBp\fR 3.558 +The print command prints the addressed lines. 3.559 +`\fB.\fR' 3.560 +is left at the last line printed. 3.561 +The 3.562 +.I p 3.563 +command 3.564 +may 3.565 +be placed on the same line after any non-i/o command. 3.566 +.TP 3.567 +.B P 3.568 +This command causes a prompt to be printed 3.569 +before following commands are read. 3.570 +The default prompt is a `*' character, 3.571 +but can be set with the 3.572 +.I \-p 3.573 +command line option (which also enables the prompt). 3.574 +Another 3.575 +.I P 3.576 +disables the prompt. 3.577 +.TP 5 3.578 +.B q 3.579 +The quit command causes 3.580 +.I ed 3.581 +to exit. 3.582 +No automatic write 3.583 +of a file is done. 3.584 +.TP 5 3.585 +.B Q 3.586 +This command is the same as 3.587 +.I q, 3.588 +except that no diagnostic results when no 3.589 +.I w 3.590 +has been given since the last buffer alteration. 3.591 +.TP 5 3.592 +\fR(\fI$\fR)\|\fBr\ \fIfilename\fR 3.593 +The read command 3.594 +reads in the given file after the addressed line. 3.595 +If no file name is given, 3.596 +the remembered file name, if any, is used 3.597 +(see 3.598 +.I e 3.599 +and 3.600 +.I f 3.601 +commands)\|. 3.602 +The file name is remembered if there was no 3.603 +remembered file name already. 3.604 +Address `0' is legal for 3.605 +.I r 3.606 +and causes the 3.607 +file to be read at the beginning of the buffer. 3.608 +If the read is successful, the number of characters 3.609 +read is typed. 3.610 +`\fB.\fR' is left at the last line read in from the file. 3.611 +A `filename' starting with a `\fB!\fR' 3.612 +causes the output of the shell command following this character 3.613 +to be read in. 3.614 +.TP 5 3.615 +\fR(\|\fI.\fB\|,\|\fI.\fR\|)\|\fBs/\fIregular expression\fB/\fIreplacement\fB/\fR or, 3.616 +.br 3.617 +.ns 3.618 +.TP 5 3.619 +\fR(\|\fI.\fB\|,\|\fI.\fR\|)\|\fBs/\fIregular expression\fB/\fIreplacement\fB/g\fR or, 3.620 +.br 3.621 +.ns 3.622 +.TP 5 3.623 +\fR(\|\fI.\fB\|,\|\fI.\fR\|)\|\fBs/\fIregular expression\fB/\fIreplacement\fB/\fInumber\fR 3.624 +The substitute command searches each addressed 3.625 +line for an occurrence of the specified regular expression. 3.626 +On each line in which a match is found, 3.627 +all matched strings are replaced by the replacement specified, 3.628 +if the global replacement indicator 3.629 +.RB ` g ' 3.630 +appears after the command. 3.631 +If the global indicator does not appear, only the first occurrence 3.632 +of the matched string is replaced; 3.633 +if the \fInumber\fR indicator is given, 3.634 +the numbered occurrence is replaced. 3.635 +It is an error for the substitution to fail on all addressed lines. 3.636 +Any character other than space or new-line 3.637 +may be used instead of `/' to delimit the regular expression 3.638 +and the replacement. 3.639 +`\fB.\fR' is left at the last line substituted. 3.640 +.IP 3.641 +An ampersand 3.642 +.RB ` & ' 3.643 +appearing in the replacement 3.644 +is replaced by the string matching the regular expression. 3.645 +The special meaning of `&' in this context may be 3.646 +suppressed by preceding it by 3.647 +.RB ` \e '. 3.648 +The characters `\|\fB\e\fIn\fR' 3.649 +where 3.650 +.I n 3.651 +is a digit, 3.652 +are replaced by the text matched by the 3.653 +.IR n -th 3.654 +regular subexpression 3.655 +enclosed between `\e(' and `\e)'. 3.656 +When 3.657 +nested, parenthesized subexpressions 3.658 +are present, 3.659 +.I n 3.660 +is determined by counting occurrences of `\e(' starting from the left. 3.661 +.IP 3.662 +A substitution string consisting of a single 3.663 +.RB ` % ' 3.664 +causes the string given on the previous substitution to be re-used. 3.665 +.IP 3.666 +Lines may be split by substituting new-line characters into them. 3.667 +The new-line in the 3.668 +replacement string 3.669 +must be escaped by preceding it by 3.670 +.RB ` \e '. 3.671 +.TP 5 3.672 +\fR(\|\fI.\|\fB,\|\fI.\|\fR)\|\fBt\|\fIa\fR 3.673 +This command acts just like the 3.674 +.I m 3.675 +command, except that a copy of the addressed lines is placed 3.676 +after address 3.677 +.I a 3.678 +(which may be 0). 3.679 +`\fB.\fR' is left on the last line of the copy. 3.680 +.TP 5 3.681 +.B u 3.682 +The undo command restores 3.683 +the contents of the buffer 3.684 +before the last command was executed. 3.685 +If the undo command is given twice, 3.686 +the current state is restored. 3.687 +.TP 5 3.688 +\fR(\fI1\fB,\fI$\fR)\|\fBv/\fIregular expression\fB/\fIcommand list\fR 3.689 +This command is the same as the global command 3.690 +.I g 3.691 +except that the command list is executed 3.692 +.I g 3.693 +with `\fB.\fR' initially set to every line 3.694 +.I except 3.695 +those 3.696 +matching the regular expression. 3.697 +.TP 5 3.698 +\fR(\fI1\fB,\fI$\fR)\|\fBV/\fIregular expression\fB/\fR 3.699 +This command is the same as the interactive global command 3.700 +.I G 3.701 +except that the commands are read 3.702 +.I g 3.703 +with `\fB.\fR' initially set to every line 3.704 +.I except 3.705 +those 3.706 +matching the regular expression. 3.707 +.TP 5 3.708 +\fR(\fI1\fB,\fI$\fR)\|\fBw\ \fIfilename\fR 3.709 +.br 3.710 +The write command writes the addressed lines onto 3.711 +the given file. 3.712 +If the file does not exist, 3.713 +it is created mode 666 (readable and writable by everyone)\|. 3.714 +The file name is remembered if there was no 3.715 +remembered file name already. 3.716 +If no file name is given, 3.717 +the remembered file name, if any, is used 3.718 +(see 3.719 +.I e 3.720 +and 3.721 +.I f 3.722 +commands)\|. 3.723 +`\fB.\fR' is unchanged. 3.724 +If the command is successful, the number of characters written is 3.725 +printed. 3.726 +A `filename' starting with a `\fB!\fR' 3.727 +causes the string following this character 3.728 +to be executed as a shell command 3.729 +with the addressed lines as standard input. 3.730 +.TP 3.731 +\fR(\fI1\fB,\fI$\fR)\fBW\ \fIfilename\fR 3.732 +This command is the same as 3.733 +.I w, 3.734 +except that the addressed lines are appended to the file. 3.735 +.TP 5 3.736 +\fR(\fI$\fR)\|\fB=\fR 3.737 +The line number of the addressed line is typed. 3.738 +`\fB.\fR' is unchanged by this command. 3.739 +.TP 5 3.740 +\fB!\fR<shell command> 3.741 +The remainder of the line after the `!' is sent 3.742 +to 3.743 +.IR sh (1) 3.744 +to be interpreted as a command. 3.745 +.RB ` . ' 3.746 +is unchanged. 3.747 +If the command starts with a 3.748 +.RB ` ! ', 3.749 +the previous command is inserted. 3.750 +A 3.751 +.RB ` % ' 3.752 +causes the current file name to be inserted. 3.753 +.TP 5 3.754 +\fR(\|\fI.+1\fR)\|<newline> 3.755 +An address alone on a line causes the addressed line to be printed. 3.756 +A blank line alone is equivalent to `.+1p'; it is useful 3.757 +for stepping through text. 3.758 +.PP 3.759 +The following commands are extensions: 3.760 +.TP 5 3.761 +\fR(\|\fI.\|\fR)\fB\|b\fR[\fIcount\fR] 3.762 +Prints a screenful of lines, 3.763 +starting at the addressed one, 3.764 +and browses forward in the buffer by this amount. 3.765 +With the optional 3.766 +.I count 3.767 +argument, the screen size for this and following 3.768 +.I b 3.769 +commands is set to the given number of lines. 3.770 +.TP 5 3.771 +.B help 3.772 +Causes a summary of 3.773 +.I ed 3.774 +commands along with short descriptions 3.775 +to be printed on the terminal. 3.776 +.TP 5 3.777 +.B N 3.778 +Makes the 3.779 +.I p 3.780 +command behave like the 3.781 +.I n 3.782 +command and vice-versa. 3.783 +If given a second time, 3.784 +the original semantics are restored. 3.785 +.TP 5 3.786 +\fR(\|\fI.\|\fR)\fB\|o\fR[\fIcount\fR] 3.787 +Prints a screenful of lines centered around the addressed one. 3.788 +The current line is not changed. 3.789 +With the optional 3.790 +.I count 3.791 +argument, the amount of lines printed above and below 3.792 +for this and following 3.793 +.I o 3.794 +commands is set to the given number. 3.795 +.TP 5 3.796 +.B z 3.797 +Performs the same actions as a 3.798 +.I w 3.799 +command followed by a 3.800 +.I q 3.801 +command. 3.802 +.PP 3.803 +If an interrupt signal is sent, 3.804 +.I ed 3.805 +prints a `?' and returns to its command level. 3.806 +.PP 3.807 +An input line that consists exactly of the two characters `\e.' 3.808 +causes a period `.' to be inserted with the 3.809 +.IR a , 3.810 +.IR c , 3.811 +and 3.812 +.IR i 3.813 +commands. 3.814 +.PP 3.815 +Some size limitations: 3.816 +The maximum number of bytes in the buffer 3.817 +corresponds to the address size; 3.818 +on machines with 32-bit addressing, 3.819 +it is 2\ G bytes, 3.820 +with 64-bit addressing, 3.821 +it is 9\ E bytes. 3.822 +The limit on the number of lines depends on the amount of core: 3.823 +each line takes 2 words. 3.824 +.PP 3.825 +If a line contains a NUL character, 3.826 +regular expressions cannot match beyond this character. 3.827 +A substitute command deletes a NUL 3.828 +and all following characters on the line. 3.829 +NUL characters in command input are discarded. 3.830 +If an input file does not end with a newline, 3.831 +.I ed 3.832 +prints a message and appends one. 3.833 +.PP 3.834 +Omission of the `/' character 3.835 +following the regular expression or the replacement string 3.836 +to the global and substitute commands 3.837 +causes the affected lines to be printed. 3.838 +Thus the following commands have the same effect: 3.839 +.RS 3.840 +g/pattern g/pattern/p 3.841 +.br 3.842 +s/pattern/repl s/pattern/repl/p 3.843 +.br 3.844 +s/pattern/ s/pattern//p 3.845 +.RE 3.846 +.SH "ENVIRONMENT VARIABLES" 3.847 +.TP 3.848 +.BR LANG ", " LC_ALL 3.849 +See 3.850 +.IR locale (7). 3.851 +.TP 3.852 +.B LC_CTYPE 3.853 +Determines the mapping of bytes to characters 3.854 +and the set of printable characters for the 3.855 +.I l 3.856 +command. 3.857 +.TP 3.858 +.B TMPDIR 3.859 +Determines the location of the temporary file 3.860 +if it contains the name of an accessible directory. 3.861 +.SH FILES 3.862 +/var/tmp/e* 3.863 +.br 3.864 +/tmp/e* 3.865 +.br 3.866 +ed.hup: work is saved here if terminal hangs up 3.867 +.SH "SEE ALSO" 3.868 +B. W. Kernighan, 3.869 +.I 3.870 +A Tutorial Introduction to the ED Text Editor 3.871 +.br 3.872 +B. W. Kernighan, 3.873 +.I Advanced editing on UNIX 3.874 +.br 3.875 +bfs(1), 3.876 +grep(1), 3.877 +sed(1), 3.878 +sh(1) 3.879 +.SH DIAGNOSTICS 3.880 +`?name' for inaccessible file; 3.881 +`?' for 3.882 +errors in commands, 3.883 +possibly followed by a verbose description 3.884 +(see the description for the 3.885 +.I h 3.886 +and 3.887 +.I H 3.888 +commands above). 3.889 +.PP 3.890 +To protect against throwing away valuable work, 3.891 +a 3.892 +.I q 3.893 +or 3.894 +.I e 3.895 +command is considered to be in error, unless a 3.896 +.I w 3.897 +has occurred since the last buffer change. 3.898 +A second 3.899 +.I q 3.900 +or 3.901 +.I e 3.902 +will be obeyed regardless. 3.903 +.SH NOTES 3.904 +A 3.905 +.I !\& 3.906 +command cannot be subject to a 3.907 +.I g 3.908 +command. 3.909 +.PP 3.910 +The LC_COLLATE variable has currently no effect. 3.911 +Ranges in bracket expressions are ordered 3.912 +as byte values in single-byte locales 3.913 +and as wide character values in multibyte locales. 3.914 +.PP 3.915 +For portable programs, restrict textual data 3.916 +to the US-ASCII character set and 3.917 +set the LC_CTYPE and LC_COLLATE variables to `C' or `POSIX'.
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/ed.c Mon Sep 05 16:31:35 2011 +0200 4.3 @@ -0,0 +1,2822 @@ 4.4 +/* 4.5 + * Editor 4.6 + */ 4.7 + 4.8 +/* 4.9 + * Changes by Gunnar Ritter, Freiburg i. Br., Germany, July 2003. 4.10 + */ 4.11 +/* from Unix 32V /usr/src/cmd/ed.c */ 4.12 +/* 4.13 + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. 4.14 + * 4.15 + * Redistribution and use in source and binary forms, with or without 4.16 + * modification, are permitted provided that the following conditions 4.17 + * are met: 4.18 + * Redistributions of source code and documentation must retain the 4.19 + * above copyright notice, this list of conditions and the following 4.20 + * disclaimer. 4.21 + * Redistributions in binary form must reproduce the above copyright 4.22 + * notice, this list of conditions and the following disclaimer in the 4.23 + * documentation and/or other materials provided with the distribution. 4.24 + * All advertising materials mentioning features or use of this software 4.25 + * must display the following acknowledgement: 4.26 + * This product includes software developed or owned by Caldera 4.27 + * International, Inc. 4.28 + * Neither the name of Caldera International, Inc. nor the names of 4.29 + * other contributors may be used to endorse or promote products 4.30 + * derived from this software without specific prior written permission. 4.31 + * 4.32 + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA 4.33 + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 4.34 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 4.35 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4.36 + * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE 4.37 + * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR 4.38 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 4.39 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 4.40 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 4.41 + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 4.42 + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 4.43 + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4.44 + */ 4.45 + 4.46 +#if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4 4.47 +#define USED __attribute__ ((used)) 4.48 +#elif defined __GNUC__ 4.49 +#define USED __attribute__ ((unused)) 4.50 +#else 4.51 +#define USED 4.52 +#endif 4.53 +#if defined (SU3) 4.54 +static const char sccsid[] USED = "@(#)ed_su3.sl 1.99 (gritter) 7/27/06"; 4.55 +#elif defined (SUS) 4.56 +static const char sccsid[] USED = "@(#)ed_sus.sl 1.99 (gritter) 7/27/06"; 4.57 +#elif defined (S42) 4.58 +static const char sccsid[] USED = "@(#)ed_s42.sl 1.99 (gritter) 7/27/06"; 4.59 +#else /* !SU3, !SUS, !S42 */ 4.60 +static const char sccsid[] USED = "@(#)ed.sl 1.99 (gritter) 7/27/06"; 4.61 +#endif /* !SU3, !SUS, !S42 */ 4.62 + 4.63 +#include <sys/types.h> 4.64 +#include <sys/stat.h> 4.65 +#include <sys/wait.h> 4.66 +#include <sys/stat.h> 4.67 +#include <fcntl.h> 4.68 +#include <unistd.h> 4.69 +#include <time.h> 4.70 +#include <string.h> 4.71 +#include <stdlib.h> 4.72 +#include <signal.h> 4.73 +#include "sigset.h" 4.74 +#include <termios.h> 4.75 +#include <setjmp.h> 4.76 +#include <libgen.h> 4.77 +#include <inttypes.h> 4.78 +#include <locale.h> 4.79 +#include <wchar.h> 4.80 +#include <ctype.h> 4.81 +#include <wctype.h> 4.82 +#include <limits.h> 4.83 +#include <termios.h> 4.84 +static int FNSIZE; 4.85 +static int LBSIZE; 4.86 +static int RHSIZE; 4.87 +#define ESIZE 2048 4.88 +static int GBSIZE; 4.89 +#undef EOF 4.90 +#define EOF -1 4.91 +#define puts(s) xxputs(s) 4.92 +#define getline(t, n) xxgetline(t, n) 4.93 + 4.94 +#if (LONG_MAX > 017777777777L) 4.95 +#define MAXCNT 0777777777777777777777L /* 2^63-1 */ 4.96 +#else 4.97 +#define MAXCNT 017777777777L /* 2^31-1 */ 4.98 +#endif 4.99 +#define BLKMSK (MAXCNT>>8) /* was 0377 */ 4.100 + 4.101 +#define READ 0 4.102 +#define WRITE 1 4.103 +#define EXIST 2 4.104 + 4.105 +struct tabulator { 4.106 + struct tabulator *t_nxt; /* next list element */ 4.107 + const char *t_str; /* tabulator string */ 4.108 + int t_tab; /* tab stop position */ 4.109 + int t_rep; /* repetitive tab count */ 4.110 +}; 4.111 + 4.112 +static int peekc; 4.113 +static int lastc; 4.114 +static char *savedfile; 4.115 +static char *file; 4.116 +static struct stat fstbuf; 4.117 +static char *linebuf; 4.118 +static char *rhsbuf; 4.119 +static char expbuf[ESIZE + 4]; 4.120 +static long *zero; 4.121 +static long *undzero; 4.122 +static long *dot; 4.123 +static long *unddot; 4.124 +static long *dol; 4.125 +static long *unddol; 4.126 +static long *addr1; 4.127 +static long *addr2; 4.128 +static char *genbuf; 4.129 +static long count; 4.130 +static char *linebp; 4.131 +static int ninbuf; 4.132 +static int io; 4.133 +static int ioeof; 4.134 +static int pflag; 4.135 +static char *wrtemp; 4.136 +static uid_t myuid; 4.137 +static void (*oldhup)(int); 4.138 +static void (*oldquit)(int); 4.139 +static void (*oldpipe)(int); 4.140 +static int vflag = 1; 4.141 +static int listf; 4.142 +static int numbf; 4.143 +static char *globp; 4.144 +static int tfile = -1; 4.145 +static long tline; 4.146 +static char tfname[64]; 4.147 +static char ibuff[512]; 4.148 +static int iblock = -1; 4.149 +static char obuff[512]; 4.150 +static int oblock = -1; 4.151 +static int ichanged; 4.152 +static int nleft; 4.153 +static long *names; 4.154 +static long *undnames; 4.155 +static int anymarks; 4.156 +static int subnewa; 4.157 +static int fchange; 4.158 +static int wrapp; 4.159 +static unsigned nlall = 128; 4.160 +static const char *progname; 4.161 +static const char *prompt = "*"; 4.162 +static int Pflag; 4.163 +static int prhelp; 4.164 +static const char *prvmsg; 4.165 +static int lastsig; 4.166 +static int pipid = -1; 4.167 +static int readop; 4.168 +static int status; 4.169 +static int mb_cur_max; 4.170 +static int needsub; 4.171 +static int insub; 4.172 +static struct tabulator *tabstops; 4.173 +static int maxlength; 4.174 +static int rspec; 4.175 +static int Nflag; 4.176 +static int bcount = 22; 4.177 +static int ocount = 11; 4.178 + 4.179 +static jmp_buf savej; 4.180 + 4.181 +static void usage(char, int); 4.182 +static void commands(void); 4.183 +static long *address(void); 4.184 +static void setdot(void); 4.185 +static void setall(void); 4.186 +static void setnoaddr(void); 4.187 +static void nonzero(void); 4.188 +static void newline(void); 4.189 +static void filename(int); 4.190 +static void exfile(void); 4.191 +static void onintr(int); 4.192 +static void onhup(int); 4.193 +static void onpipe(int); 4.194 +static void error(const char *); 4.195 +static void error2(const char *, const char *); 4.196 +static void errput(const char *, const char *); 4.197 +static int getchr(void); 4.198 +static int gettty(void); 4.199 +static long getnum(void); 4.200 +static int getfile(void); 4.201 +static void putfile(void); 4.202 +static int append(int (*)(void), long *); 4.203 +static void callunix(void); 4.204 +static char *readcmd(void); 4.205 +static void quit(int); 4.206 +static void delete(void); 4.207 +static void rdelete(long *, long *); 4.208 +static void gdelete(void); 4.209 +static char *getline(long, int); 4.210 +static int putline(void); 4.211 +static char *getblock(long, long); 4.212 +static void blkio(long, char *, int); 4.213 +static void init(void); 4.214 +static void global(int, int); 4.215 +static void globrd(char **, int); 4.216 +static void join(void); 4.217 +static void substitute(int); 4.218 +static int compsub(void); 4.219 +static int getsub(void); 4.220 +static int dosub(int); 4.221 +static int place(int, const char *, const char *); 4.222 +static void move(int); 4.223 +static void reverse(long *, long *); 4.224 +static int getcopy(void); 4.225 +static int execute(int, long *, int); 4.226 +static void cmplerr(int); 4.227 +static void doprnt(long *, long *); 4.228 +static void putd(long); 4.229 +static void puts(const char *); 4.230 +static void nlputs(const char *); 4.231 +static void list(const char *); 4.232 +static int lstchr(int); 4.233 +static void putstr(const char *); 4.234 +static void putchr(int); 4.235 +static void checkpoint(void); 4.236 +static void undo(void); 4.237 +static int maketf(int); 4.238 +static int creatf(const char *); 4.239 +static int sopen(const char *, int); 4.240 +static void sclose(int); 4.241 +static void fspec(const char *); 4.242 +static const char *ftok(const char **); 4.243 +static struct tabulator *tabstring(const char *); 4.244 +static void freetabs(void); 4.245 +static void expand(const char *); 4.246 +static void growlb(const char *); 4.247 +static void growrhs(const char *); 4.248 +static void growfn(const char *); 4.249 +static void help(void); 4.250 + 4.251 +#define INIT 4.252 +#define GETC() getchr() 4.253 +#define UNGETC(c) (peekc = c) 4.254 +#define PEEKC() (peekc = getchr()) 4.255 +#define RETURN(c) return c 4.256 +#define ERROR(c) cmplerr(c) 4.257 +static wint_t GETWC(char *); 4.258 + 4.259 +#if defined (SUS) || defined (S42) || defined (SU3) 4.260 + 4.261 +#include <regex.h> 4.262 + 4.263 +#define NBRA 9 4.264 + 4.265 +static char *braslist[NBRA]; 4.266 +static char *braelist[NBRA]; 4.267 +static char *loc1, *loc2, *locs; 4.268 +static int nbra; 4.269 +static int circf; 4.270 +static int nodelim; 4.271 + 4.272 +static char *compile(char *, char *, const char *, int); 4.273 +static int step(const char *, const char *); 4.274 + 4.275 +#else /* !SUS, !S42, !SU3 */ 4.276 + 4.277 +#include <regexp.h> 4.278 + 4.279 +#endif /* !SUS, !S42, !SU3 */ 4.280 + 4.281 +int 4.282 +main(int argc, char **argv) 4.283 +{ 4.284 + register int i; 4.285 + void (*oldintr)(int); 4.286 + 4.287 + progname = basename(argv[0]); 4.288 +#if defined (SUS) || defined (S42) || defined (SU3) 4.289 + setlocale(LC_COLLATE, ""); 4.290 +#endif 4.291 + setlocale(LC_CTYPE, ""); 4.292 + mb_cur_max = MB_CUR_MAX; 4.293 + myuid = getuid(); 4.294 + oldquit = sigset(SIGQUIT, SIG_IGN); 4.295 + oldhup = sigset(SIGHUP, SIG_IGN); 4.296 + oldintr = sigset(SIGINT, SIG_IGN); 4.297 + if (sigset(SIGTERM, SIG_IGN) != SIG_IGN) 4.298 + sigset(SIGTERM, quit); 4.299 + oldpipe = sigset(SIGPIPE, onpipe); 4.300 + argv++; 4.301 + while (argc > 1 && **argv=='-') { 4.302 + if ((*argv)[1] == '\0') { 4.303 + vflag = 0; 4.304 + goto next; 4.305 + } else if ((*argv)[1] == '-' && (*argv)[2] == '\0') { 4.306 + argv++; 4.307 + argc--; 4.308 + break; 4.309 + } 4.310 + letter: switch((*argv)[1]) { 4.311 + 4.312 + case 's': 4.313 + vflag = 0; 4.314 + break; 4.315 + 4.316 + case 'q': 4.317 + sigset(SIGQUIT, SIG_DFL); 4.318 + vflag = 1; 4.319 + break; 4.320 + 4.321 + case 'p': 4.322 + if ((*argv)[2]) 4.323 + prompt = &(*argv)[2]; 4.324 + else if (argv[1]) { 4.325 + prompt = argv[1]; 4.326 + argv++; 4.327 + argc--; 4.328 + } else 4.329 + usage((*argv)[1], 1); 4.330 + Pflag = 1; 4.331 + goto next; 4.332 + 4.333 + default: 4.334 + usage((*argv)[1], 0); 4.335 + } 4.336 + if ((*argv)[2]) { 4.337 + (*argv)++; 4.338 + goto letter; 4.339 + } 4.340 + next: argv++; 4.341 + argc--; 4.342 + } 4.343 + 4.344 + growfn("no space"); 4.345 + if (argc>1) { 4.346 + i = -1; 4.347 + do 4.348 + if (++i >= FNSIZE) 4.349 + growfn("maximum of characters in " 4.350 + "file names reached"); 4.351 + while (savedfile[i] = (*argv)[i]); 4.352 + globp = "e"; 4.353 + } 4.354 + names = malloc(26*sizeof *names); 4.355 + undnames = malloc(26*sizeof *undnames); 4.356 + zero = malloc(nlall*sizeof *zero); 4.357 + if ((undzero = malloc(nlall*sizeof *undzero)) == NULL) 4.358 + puts("no memory for undo"); 4.359 + growlb("no space"); 4.360 + growrhs("no space"); 4.361 + init(); 4.362 + if (oldintr != SIG_IGN) 4.363 + sigset(SIGINT, onintr); 4.364 + if (oldhup != SIG_IGN) 4.365 + sigset(SIGHUP, onhup); 4.366 + setjmp(savej); 4.367 + if (lastsig) { 4.368 + sigrelse(lastsig); 4.369 + lastsig = 0; 4.370 + } 4.371 + commands(); 4.372 + quit(0); 4.373 + /*NOTREACHED*/ 4.374 + return 0; 4.375 +} 4.376 + 4.377 +static void 4.378 +usage(char c, int misarg) 4.379 +{ 4.380 + if (c) { 4.381 + write(2, progname, strlen(progname)); 4.382 + if (misarg) 4.383 + write(2, ": option requires an argument -- ", 33); 4.384 + else 4.385 + write(2, ": illegal option -- ", 20); 4.386 + write(2, &c, 1); 4.387 + write(2, "\n", 1); 4.388 + } 4.389 + write(2, "usage: ", 7); 4.390 + write(2, progname, strlen(progname)); 4.391 + write(2, " [- | -s] [-p string] [file]\n", 29); 4.392 + exit(2); 4.393 +} 4.394 + 4.395 +static void 4.396 +commands(void) 4.397 +{ 4.398 + register long *a1; 4.399 + register int c; 4.400 + int n; 4.401 + 4.402 + for (;;) { 4.403 + if (pflag) { 4.404 + pflag = 0; 4.405 + addr1 = addr2 = dot; 4.406 + goto print; 4.407 + } 4.408 + if (Pflag && globp == NULL) 4.409 + write(1, prompt, strlen(prompt)); 4.410 + addr1 = 0; 4.411 + addr2 = 0; 4.412 + switch (c = getchr()) { 4.413 + case ',': 4.414 + case ';': 4.415 + addr2 = c == ',' ? zero+1 : dot; 4.416 + if (((peekc = getchr()) < '0' || peekc > '9') && 4.417 + peekc != ' ' && peekc != '\t' && 4.418 + peekc != '+' && peekc != '-' && 4.419 + peekc != '^' && peekc != '?' && 4.420 + peekc != '/' && peekc != '$' && 4.421 + peekc != '.' && peekc != '\'') { 4.422 + addr1 = addr2; 4.423 + a1 = dol; 4.424 + goto loop; 4.425 + } 4.426 + break; 4.427 + default: 4.428 + peekc = c; 4.429 + } 4.430 + do { 4.431 + addr1 = addr2; 4.432 + if ((a1 = address())==0) { 4.433 + c = getchr(); 4.434 + break; 4.435 + } 4.436 + loop: addr2 = a1; 4.437 + if ((c=getchr()) == ';') { 4.438 + c = ','; 4.439 + dot = a1; 4.440 + } 4.441 + } while (c==','); 4.442 + if (addr1==0) 4.443 + addr1 = addr2; 4.444 + switch(c) { 4.445 + 4.446 + case 'a': 4.447 + setdot(); 4.448 + newline(); 4.449 + checkpoint(); 4.450 + append(gettty, addr2); 4.451 + continue; 4.452 + 4.453 + case 'c': 4.454 +#if defined (SU3) 4.455 + if (addr1 == zero && addr1+1 <= dol) { 4.456 + if (addr1 == addr2) 4.457 + addr2++; 4.458 + addr1++; 4.459 + } 4.460 +#endif /* SU3 */ 4.461 + delete(); 4.462 + append(gettty, addr1-1); 4.463 +#if defined (SUS) || defined (SU3) 4.464 + if (dot == addr1-1 && addr1 <= dol) 4.465 + dot = addr1; 4.466 +#endif /* SUS || SU3 */ 4.467 + continue; 4.468 + 4.469 + case 'd': 4.470 + delete(); 4.471 + continue; 4.472 + 4.473 + case 'E': 4.474 + fchange = 0; 4.475 + c = 'e'; 4.476 + case 'e': 4.477 + setnoaddr(); 4.478 + if (vflag && fchange) { 4.479 + fchange = 0; 4.480 + error("warning: expecting `w'"); 4.481 + } 4.482 + filename(c); 4.483 + init(); 4.484 + addr2 = zero; 4.485 + goto caseread; 4.486 + 4.487 + case 'f': 4.488 + setnoaddr(); 4.489 + filename(c); 4.490 + puts(savedfile); 4.491 + continue; 4.492 + 4.493 + case 'g': 4.494 + global(1, 0); 4.495 + continue; 4.496 + 4.497 + case 'G': 4.498 + global(1, 1); 4.499 + continue; 4.500 + 4.501 + case 'H': 4.502 + prhelp = !prhelp; 4.503 + /*FALLTHRU*/ 4.504 + 4.505 + case 'h': 4.506 + if ((peekc = getchr()) == 'e') { 4.507 + peekc = 0; 4.508 + if (getchr() != 'l' || getchr() != 'p' || 4.509 + getchr() != '\n') 4.510 + error("illegal suffix"); 4.511 + setnoaddr(); 4.512 + help(); 4.513 + continue; 4.514 + } 4.515 + newline(); 4.516 + setnoaddr(); 4.517 + if (prvmsg) 4.518 + puts(prvmsg); 4.519 + continue; 4.520 + 4.521 + case 'i': 4.522 + setdot(); 4.523 +#if defined (SU3) 4.524 + if (addr1 == zero) { 4.525 + if (addr1 == addr2) 4.526 + addr2++; 4.527 + addr1++; 4.528 + if (dol != zero) 4.529 + nonzero(); 4.530 + } else 4.531 +#endif /* SU3 */ 4.532 + nonzero(); 4.533 + newline(); 4.534 + checkpoint(); 4.535 + append(gettty, addr2-1); 4.536 + if (dot == addr2-1) 4.537 + dot++; 4.538 + continue; 4.539 + 4.540 + 4.541 + case 'j': 4.542 + if (addr2==0) { 4.543 + addr1 = dot; 4.544 + addr2 = dot+1; 4.545 + } 4.546 + setdot(); 4.547 + newline(); 4.548 + nonzero(); 4.549 + checkpoint(); 4.550 + if (addr1 != addr2) 4.551 + join(); 4.552 + continue; 4.553 + 4.554 + case 'k': 4.555 + if ((c = getchr()) < 'a' || c > 'z') 4.556 + error("mark not lower case"); 4.557 + newline(); 4.558 + setdot(); 4.559 + nonzero(); 4.560 + names[c-'a'] = *addr2 & ~01; 4.561 + anymarks |= 01; 4.562 + continue; 4.563 + 4.564 + case 'm': 4.565 + move(0); 4.566 + continue; 4.567 + 4.568 + case '\n': 4.569 + if (addr2==0) 4.570 + addr2 = dot+1; 4.571 + addr1 = addr2; 4.572 + goto print; 4.573 + 4.574 + case 'n': 4.575 + numbf = 1; 4.576 + newline(); 4.577 + goto print; 4.578 + 4.579 + case 'N': 4.580 + newline(); 4.581 + setnoaddr(); 4.582 + Nflag = !Nflag; 4.583 + continue; 4.584 + 4.585 + case 'b': 4.586 + case 'o': 4.587 + n = getnum(); 4.588 + newline(); 4.589 + setdot(); 4.590 + nonzero(); 4.591 + if (n >= 0) { 4.592 + if (c == 'b') 4.593 + bcount = n; 4.594 + else 4.595 + ocount = n; 4.596 + } 4.597 + if (c == 'b') { 4.598 + a1 = addr2+bcount > dol ? dol : addr2 + bcount; 4.599 + doprnt(addr1, a1); 4.600 + dot = a1; 4.601 + } else { 4.602 + a1 = addr2+ocount > dol ? dol : addr2 + ocount; 4.603 + doprnt(addr2-ocount<zero+1?zero+1:addr2-ocount, a1); 4.604 + dot = addr2; 4.605 + } 4.606 + continue; 4.607 + 4.608 + case 'l': 4.609 + listf++; 4.610 + case 'p': 4.611 + newline(); 4.612 + print: 4.613 + setdot(); 4.614 + nonzero(); 4.615 + doprnt(addr1, addr2); 4.616 + dot = addr2; 4.617 + continue; 4.618 + 4.619 + case 'P': 4.620 + setnoaddr(); 4.621 + newline(); 4.622 + Pflag = !Pflag; 4.623 + continue; 4.624 + 4.625 + case 'Q': 4.626 + fchange = 0; 4.627 + case 'q': 4.628 + setnoaddr(); 4.629 + newline(); 4.630 + quit(0); 4.631 + 4.632 + case 'r': 4.633 + filename(c); 4.634 + caseread: 4.635 + if ((io = sopen(file, READ)) < 0) { 4.636 + lastc = '\n'; 4.637 + error2("cannot open input file", file); 4.638 + } 4.639 + ioeof = 0; 4.640 + setall(); 4.641 + ninbuf = 0; 4.642 + if (c == 'r') 4.643 + checkpoint(); 4.644 + n = zero != dol; 4.645 + rspec = (c == 'e' || !n) && file[0] != '!'; 4.646 + append(getfile, addr2); 4.647 + rspec = 0; 4.648 + exfile(); 4.649 + fchange = n; 4.650 + continue; 4.651 + 4.652 + case 's': 4.653 + setdot(); 4.654 + nonzero(); 4.655 + substitute(globp!=0); 4.656 + continue; 4.657 + 4.658 + case 't': 4.659 + move(1); 4.660 + continue; 4.661 + 4.662 + case 'u': 4.663 + setdot(); 4.664 + newline(); 4.665 + if (unddot == NULL) 4.666 + error("nothing to undo"); 4.667 + undo(); 4.668 + continue; 4.669 + 4.670 + case 'v': 4.671 + global(0, 0); 4.672 + continue; 4.673 + 4.674 + case 'V': 4.675 + global(0, 1); 4.676 + continue; 4.677 + 4.678 + case 'W': 4.679 + wrapp++; 4.680 + case 'w': 4.681 + write: 4.682 + setall(); 4.683 + if (zero != dol) 4.684 + nonzero(); 4.685 + filename(c); 4.686 + if(!wrapp || 4.687 + ((io = open(file,O_WRONLY|O_APPEND)) == -1) || 4.688 + ((lseek(io, 0, SEEK_END)) == -1)) { 4.689 + struct stat st; 4.690 + if (lstat(file, &st) == 0 && 4.691 + (st.st_mode&S_IFMT) == S_IFREG && 4.692 + st.st_nlink == 1 && 4.693 + (myuid==0 || myuid==st.st_uid)) { 4.694 + char *cp, *tp; 4.695 + int nio; 4.696 + if ((io = sopen(file, EXIST)) < 0) 4.697 + error("cannot create output file"); 4.698 + if ((wrtemp = malloc(strlen(file)+8)) == NULL) 4.699 + error("out of memory"); 4.700 + for (cp = file, tp = wrtemp; *cp; cp++) 4.701 + *tp++ = *cp; 4.702 + while (tp > wrtemp && tp[-1] != '/') 4.703 + tp--; 4.704 + for (cp = "\7XXXXXX"; *cp; cp++) 4.705 + *tp++ = *cp; 4.706 + *tp = '\0'; 4.707 + if ((nio = mkstemp(wrtemp)) < 0) { 4.708 + free(wrtemp); 4.709 + wrtemp = NULL; 4.710 + ftruncate(io, 0); 4.711 + } else { 4.712 + close(io); 4.713 + io = nio; 4.714 + } 4.715 + } else { 4.716 + if ((io = sopen(file, WRITE)) < 0) 4.717 + error("cannot create output file"); 4.718 + } 4.719 + } 4.720 + if (zero != dol) { 4.721 + ioeof = 0; 4.722 + wrapp = 0; 4.723 + putfile(); 4.724 + } 4.725 + exfile(); 4.726 + if (addr1==zero+1 && addr2==dol || addr1==addr2 && dol==zero) 4.727 + fchange = 0; 4.728 + if (c == 'z') 4.729 + quit(0); 4.730 + continue; 4.731 + 4.732 + case 'z': 4.733 + if ((peekc=getchr()) != '\n') 4.734 + error("illegal suffix"); 4.735 + setnoaddr(); 4.736 + goto write; 4.737 + 4.738 + case '=': 4.739 + setall(); 4.740 + newline(); 4.741 + putd((addr2-zero)&MAXCNT); 4.742 + putchr('\n'); 4.743 + continue; 4.744 + 4.745 + case '!': 4.746 + callunix(); 4.747 + continue; 4.748 + 4.749 + case EOF: 4.750 + return; 4.751 + 4.752 + } 4.753 + error("unknown command"); 4.754 + } 4.755 +} 4.756 + 4.757 +static long * 4.758 +address(void) 4.759 +{ 4.760 + register long *a1; 4.761 + register int minus, c; 4.762 + int n, relerr; 4.763 + 4.764 + minus = 0; 4.765 + a1 = 0; 4.766 + for (;;) { 4.767 + c = getchr(); 4.768 + if ('0'<=c && c<='9') { 4.769 + n = 0; 4.770 + do { 4.771 + n *= 10; 4.772 + n += c - '0'; 4.773 + } while ((c = getchr())>='0' && c<='9'); 4.774 + peekc = c; 4.775 + if (a1==0) 4.776 + a1 = zero; 4.777 + if (minus<0) 4.778 + n = -n; 4.779 + a1 += n; 4.780 + minus = 0; 4.781 + continue; 4.782 + } 4.783 + relerr = 0; 4.784 + if (a1 || minus) 4.785 + relerr++; 4.786 + switch(c) { 4.787 + case ' ': 4.788 + case '\t': 4.789 + continue; 4.790 + 4.791 + case '+': 4.792 + minus++; 4.793 + if (a1==0) 4.794 + a1 = dot; 4.795 + continue; 4.796 + 4.797 + case '-': 4.798 + case '^': 4.799 + minus--; 4.800 + if (a1==0) 4.801 + a1 = dot; 4.802 + continue; 4.803 + 4.804 + case '?': 4.805 + case '/': 4.806 + compile(NULL, expbuf, &expbuf[ESIZE], c); 4.807 + a1 = dot; 4.808 + for (;;) { 4.809 + if (c=='/') { 4.810 + a1++; 4.811 + if (a1 > dol) 4.812 + a1 = zero; 4.813 + } else { 4.814 + a1--; 4.815 + if (a1 < zero) 4.816 + a1 = dol; 4.817 + } 4.818 + if (execute(0, a1, 0)) 4.819 + break; 4.820 + if (a1==dot) 4.821 + error("search string not found"); 4.822 + } 4.823 + break; 4.824 + 4.825 + case '$': 4.826 + a1 = dol; 4.827 + break; 4.828 + 4.829 + case '.': 4.830 + a1 = dot; 4.831 + break; 4.832 + 4.833 + case '\'': 4.834 + if ((c = getchr()) < 'a' || c > 'z') 4.835 + error("mark not lower case"); 4.836 + for (a1=zero; a1<=dol; a1++) 4.837 + if (names[c-'a'] == (*a1 & ~01)) 4.838 + break; 4.839 + break; 4.840 + 4.841 + default: 4.842 + peekc = c; 4.843 + if (a1==0) 4.844 + return(0); 4.845 + a1 += minus; 4.846 + if (a1<zero || a1>dol) 4.847 + error("line out of range"); 4.848 + return(a1); 4.849 + } 4.850 + if (relerr) 4.851 + error("bad number"); 4.852 + } 4.853 +} 4.854 + 4.855 +static void 4.856 +setdot(void) 4.857 +{ 4.858 + if (addr2 == 0) 4.859 + addr1 = addr2 = dot; 4.860 + if (addr1 > addr2) 4.861 + error("bad range"); 4.862 +} 4.863 + 4.864 +static void 4.865 +setall(void) 4.866 +{ 4.867 + if (addr2==0) { 4.868 + addr1 = zero+1; 4.869 + addr2 = dol; 4.870 + if (dol==zero) 4.871 + addr1 = zero; 4.872 + } 4.873 + setdot(); 4.874 +} 4.875 + 4.876 +static void 4.877 +setnoaddr(void) 4.878 +{ 4.879 + if (addr2) 4.880 + error("Illegal address count"); 4.881 +} 4.882 + 4.883 +static void 4.884 +nonzero(void) 4.885 +{ 4.886 + if (addr1<=zero || addr2>dol) 4.887 + error("line out of range"); 4.888 +} 4.889 + 4.890 +static void 4.891 +newline(void) 4.892 +{ 4.893 + register int c; 4.894 + 4.895 + if ((c = getchr()) == '\n') 4.896 + return; 4.897 + if (c=='p' || c=='l' || c=='n') { 4.898 + pflag++; 4.899 + if (c=='l') 4.900 + listf++; 4.901 + else if (c=='n') 4.902 + numbf = 1; 4.903 + if (getchr() == '\n') 4.904 + return; 4.905 + } 4.906 + error("illegal suffix"); 4.907 +} 4.908 + 4.909 +static void 4.910 +filename(int comm) 4.911 +{ 4.912 + register char *p1, *p2; 4.913 + register int c, i; 4.914 + 4.915 + count = 0; 4.916 + c = getchr(); 4.917 + if (c=='\n' || c==EOF) { 4.918 + p1 = savedfile; 4.919 + if (*p1==0 && comm!='f') 4.920 + error("illegal or missing filename"); 4.921 + p2 = file; 4.922 + while (*p2++ = *p1++) 4.923 + ; 4.924 + return; 4.925 + } 4.926 + if (c!=' ') 4.927 + error("no space after command"); 4.928 + while ((c = getchr()) == ' ') 4.929 + ; 4.930 + if (c=='\n') 4.931 + error("illegal or missing filename"); 4.932 + i = 0; 4.933 + do { 4.934 + if (i >= FNSIZE) 4.935 + growfn("maximum of characters in file names reached"); 4.936 + file[i++] = c; 4.937 + if (c==' ' && file[0] != '!' || c==EOF) 4.938 + error("illegal or missing filename"); 4.939 + } while ((c = getchr()) != '\n'); 4.940 + file[i++] = 0; 4.941 + if ((savedfile[0]==0 || comm=='e' || comm=='f') && file[0] != '!') { 4.942 + p1 = savedfile; 4.943 + p2 = file; 4.944 + while (*p1++ = *p2++) 4.945 + ; 4.946 + } 4.947 +} 4.948 + 4.949 +static void 4.950 +exfile(void) 4.951 +{ 4.952 + sclose(io); 4.953 + io = -1; 4.954 + if (wrtemp) { 4.955 + extern int rename(const char *, const char *); 4.956 + if (rename(wrtemp, file) < 0) 4.957 + error("cannot create output file"); 4.958 + if (myuid == 0) 4.959 + chown(file, fstbuf.st_uid, fstbuf.st_gid); 4.960 + chmod(file, fstbuf.st_mode & 07777); 4.961 + free(wrtemp); 4.962 + wrtemp = NULL; 4.963 + } 4.964 + if (vflag) { 4.965 + putd(count); 4.966 + putchr('\n'); 4.967 + } 4.968 +} 4.969 + 4.970 +static void 4.971 +onintr(int signo) 4.972 +{ 4.973 + lastsig = signo; 4.974 + putchr('\n'); 4.975 + lastc = '\n'; 4.976 + if (readop) { 4.977 + puts("\007read may be incomplete - beware!\007"); 4.978 + fchange = 0; 4.979 + } 4.980 + error("interrupt"); 4.981 +} 4.982 + 4.983 +static void 4.984 +onhup(int signo) 4.985 +{ 4.986 + if (dol > zero && fchange) { 4.987 + addr1 = zero+1; 4.988 + addr2 = dol; 4.989 + io = creat("ed.hup", 0666); 4.990 + if (io < 0) { 4.991 + char *home = getenv("HOME"); 4.992 + if (home) { 4.993 + char *fn = malloc(strlen(home) + 10); 4.994 + if (fn) { 4.995 + strcpy(fn, home); 4.996 + strcat(fn, "/ed.hup"); 4.997 + io = creat(fn, 0666); 4.998 + } 4.999 + } 4.1000 + } 4.1001 + if (io >= 0) 4.1002 + putfile(); 4.1003 + } 4.1004 + fchange = 0; 4.1005 + status = 0200 | signo; 4.1006 + quit(0); 4.1007 +} 4.1008 + 4.1009 +static void 4.1010 +onpipe(int signo) 4.1011 +{ 4.1012 + lastsig = signo; 4.1013 + error("write or open on pipe failed"); 4.1014 +} 4.1015 + 4.1016 +static void 4.1017 +error(const char *s) 4.1018 +{ 4.1019 + error2(s, NULL); 4.1020 +} 4.1021 + 4.1022 +static void 4.1023 +error2(const char *s, const char *fn) 4.1024 +{ 4.1025 + register int c; 4.1026 + 4.1027 + wrapp = 0; 4.1028 + listf = 0; 4.1029 + numbf = 0; 4.1030 + errput(s, fn); 4.1031 + count = 0; 4.1032 + if (lseek(0, 0, SEEK_END) > 0) 4.1033 + status = 2; 4.1034 + pflag = 0; 4.1035 + if (globp) 4.1036 + lastc = '\n'; 4.1037 + globp = 0; 4.1038 + peekc = lastc; 4.1039 + if(lastc) 4.1040 + while ((c = getchr()) != '\n' && c != EOF) 4.1041 + ; 4.1042 + if (io > 0) { 4.1043 + sclose(io); 4.1044 + io = -1; 4.1045 + } 4.1046 + if (wrtemp) { 4.1047 + unlink(wrtemp); 4.1048 + free(wrtemp); 4.1049 + wrtemp = NULL; 4.1050 + } 4.1051 + longjmp(savej, 1); 4.1052 +} 4.1053 + 4.1054 +static void 4.1055 +errput(const char *s, const char *fn) 4.1056 +{ 4.1057 + prvmsg = s; 4.1058 + if (fn) { 4.1059 + putchr('?'); 4.1060 + puts(fn); 4.1061 + } else 4.1062 + puts("?"); 4.1063 + if (prhelp) 4.1064 + puts(s); 4.1065 +} 4.1066 + 4.1067 +static int 4.1068 +getchr(void) 4.1069 +{ 4.1070 + char c; 4.1071 + if (lastc=peekc) { 4.1072 + peekc = 0; 4.1073 + return(lastc); 4.1074 + } 4.1075 + if (globp) { 4.1076 + if ((lastc = *globp++) != 0) 4.1077 + return(lastc); 4.1078 + globp = 0; 4.1079 + return(EOF); 4.1080 + } 4.1081 + if (read(0, &c, 1) <= 0) 4.1082 + return(lastc = EOF); 4.1083 + lastc = c; 4.1084 + return(lastc); 4.1085 +} 4.1086 + 4.1087 +static int 4.1088 +gettty(void) 4.1089 +{ 4.1090 + register int c, i; 4.1091 + register char *gf; 4.1092 + 4.1093 + i = 0; 4.1094 + gf = globp; 4.1095 + while ((c = getchr()) != '\n') { 4.1096 + if (c==EOF) { 4.1097 + if (gf) 4.1098 + peekc = c; 4.1099 + return(c); 4.1100 + } 4.1101 + if (c == 0) 4.1102 + continue; 4.1103 + if (i >= LBSIZE) 4.1104 + growlb("line too long"); 4.1105 + linebuf[i++] = c; 4.1106 + } 4.1107 + if (i >= LBSIZE-2) 4.1108 + growlb("line too long"); 4.1109 + linebuf[i++] = 0; 4.1110 + if (linebuf[0]=='.' && linebuf[1]==0) 4.1111 + return(EOF); 4.1112 +#if !defined (SUS) && !defined (SU3) 4.1113 + if (linebuf[0]=='\\' && linebuf[1]=='.' && linebuf[2]==0) 4.1114 + linebuf[0]='.', linebuf[1]=0; 4.1115 +#endif 4.1116 + return(0); 4.1117 +} 4.1118 + 4.1119 +static long 4.1120 +getnum(void) 4.1121 +{ 4.1122 + char scount[20]; 4.1123 + int i; 4.1124 + 4.1125 + i = 0; 4.1126 + while ((peekc=getchr()) >= '0' && peekc <= '9' && i < sizeof scount) { 4.1127 + scount[i++] = peekc; 4.1128 + peekc = 0; 4.1129 + } 4.1130 + scount[i] = '\0'; 4.1131 + return i ? atol(scount) : -1; 4.1132 +} 4.1133 + 4.1134 +static int 4.1135 +getfile(void) 4.1136 +{ 4.1137 + register int c, i, j; 4.1138 + static int nextj; 4.1139 + 4.1140 + i = 0; 4.1141 + j = nextj; 4.1142 + do { 4.1143 + if (--ninbuf < 0) { 4.1144 + if (ioeof || (ninbuf=read(io, genbuf, LBSIZE)-1) < 0) { 4.1145 + if (ioeof == 0 && ninbuf < -1) { 4.1146 + puts("input error"); 4.1147 + status = 1; 4.1148 + } 4.1149 + if (i > 0) { 4.1150 + puts("'\\n' appended"); 4.1151 + c = '\n'; 4.1152 + ioeof = 1; 4.1153 + goto wrc; 4.1154 + } 4.1155 + return(EOF); 4.1156 + } 4.1157 + j = 0; 4.1158 + } 4.1159 + c = genbuf[j++]&0377; 4.1160 + wrc: if (i >= LBSIZE) { 4.1161 + lastc = '\n'; 4.1162 + growlb("line too long"); 4.1163 + } 4.1164 + linebuf[i++] = c ? c : '\n'; 4.1165 + count++; 4.1166 + } while (c != '\n'); 4.1167 + linebuf[--i] = 0; 4.1168 + nextj = j; 4.1169 + if (rspec && dot == zero) 4.1170 + fspec(linebuf); 4.1171 + if (maxlength && i > maxlength) { 4.1172 + putstr("line too long: lno = "); 4.1173 + putd((dot - zero+1)&MAXCNT); 4.1174 + putchr('\n'); 4.1175 + } 4.1176 + return(0); 4.1177 +} 4.1178 + 4.1179 +static void 4.1180 +putfile(void) 4.1181 +{ 4.1182 + long *a1; 4.1183 + int n; 4.1184 + register char *fp, *lp; 4.1185 + register int nib; 4.1186 + 4.1187 + nib = 512; 4.1188 + fp = genbuf; 4.1189 + a1 = addr1; 4.1190 + do { 4.1191 + lp = getline(*a1++, 0); 4.1192 + if (maxlength) { 4.1193 + for (n = 0; lp[n]; n++); 4.1194 + if (n > maxlength) { 4.1195 + putstr("line too long: lno = "); 4.1196 + putd((a1-1 - zero)&MAXCNT); 4.1197 + putchr('\n'); 4.1198 + } 4.1199 + } 4.1200 + for (;;) { 4.1201 + if (--nib < 0) { 4.1202 + n = fp-genbuf; 4.1203 + if(write(io, genbuf, n) != n) 4.1204 + error("write error"); 4.1205 + nib = 511; 4.1206 + fp = genbuf; 4.1207 + } 4.1208 + count++; 4.1209 + if ((*fp++ = *lp++) == 0) { 4.1210 + fp[-1] = '\n'; 4.1211 + break; 4.1212 + } else if (fp[-1] == '\n') 4.1213 + fp[-1] = '\0'; 4.1214 + } 4.1215 + } while (a1 <= addr2); 4.1216 + n = fp-genbuf; 4.1217 + if(write(io, genbuf, n) != n) 4.1218 + error("write error"); 4.1219 +} 4.1220 + 4.1221 +static int 4.1222 +append(int (*f)(void), long *a) 4.1223 +{ 4.1224 + register long *a1, *a2, *rdot; 4.1225 + int nline, tl; 4.1226 + 4.1227 + nline = 0; 4.1228 + dot = a; 4.1229 + while ((*f)() == 0) { 4.1230 + if ((dol-zero)+1 >= nlall) { 4.1231 + long *ozero = zero; 4.1232 + nlall += 512; 4.1233 + if ((zero = realloc(zero, nlall*sizeof *zero))==NULL) { 4.1234 + lastc = '\n'; 4.1235 + zero = ozero; 4.1236 + error("out of memory for append"); 4.1237 + } 4.1238 + dot += zero - ozero; 4.1239 + dol += zero - ozero; 4.1240 + addr1 += zero - ozero; 4.1241 + addr2 += zero - ozero; 4.1242 + if (unddot) { 4.1243 + unddot += zero - ozero; 4.1244 + unddol += zero - ozero; 4.1245 + } 4.1246 + if (undzero) { 4.1247 + ozero = undzero; 4.1248 + if ((undzero = realloc(undzero, 4.1249 + nlall*sizeof *undzero)) == 0) { 4.1250 + puts("no memory for undo"); 4.1251 + free(ozero); 4.1252 + } 4.1253 + } 4.1254 + } 4.1255 + tl = putline(); 4.1256 + nline++; 4.1257 + a1 = ++dol; 4.1258 + a2 = a1+1; 4.1259 + rdot = ++dot; 4.1260 + while (a1 > rdot) 4.1261 + *--a2 = *--a1; 4.1262 + *rdot = tl; 4.1263 + } 4.1264 + return(nline); 4.1265 +} 4.1266 + 4.1267 +static void 4.1268 +callunix(void) 4.1269 +{ 4.1270 + char *line; 4.1271 + void (*savint)(int); 4.1272 + pid_t pid, rpid; 4.1273 + int retcode; 4.1274 + 4.1275 + setnoaddr(); 4.1276 + line = readcmd(); 4.1277 + if ((pid = fork()) == 0) { 4.1278 + sigset(SIGHUP, oldhup); 4.1279 + sigset(SIGQUIT, oldquit); 4.1280 + sigset(SIGPIPE, oldpipe); 4.1281 + execl(SHELL, "sh", "-c", line, NULL); 4.1282 + _exit(0100); 4.1283 + } else if (pid < 0) 4.1284 + error("fork failed - try again"); 4.1285 + savint = sigset(SIGINT, SIG_IGN); 4.1286 + while ((rpid = wait(&retcode)) != pid && rpid != -1) 4.1287 + ; 4.1288 + sigset(SIGINT, savint); 4.1289 + if (vflag) 4.1290 + puts("!"); 4.1291 +} 4.1292 + 4.1293 +#define cmadd(c) ((i>=cmsize ? \ 4.1294 + ((line=realloc(line,cmsize+=128)) == 0 ? \ 4.1295 + (error("line too long"),0) : 0, 0) \ 4.1296 + : 0), line[i++]=(c)) 4.1297 + 4.1298 +static char * 4.1299 +readcmd(void) 4.1300 +{ 4.1301 + static char *line, *prev; 4.1302 + static int cmsize, pvsize; 4.1303 + char *pp; 4.1304 + int c, mod = 0, i; 4.1305 + 4.1306 + i = 0; 4.1307 + if ((c = getchr()) == '!') { 4.1308 + for (pp = prev; *pp; pp++) 4.1309 + line[i++] = *pp; 4.1310 + mod = 1; 4.1311 + c = getchr(); 4.1312 + } 4.1313 + while (c != '\n' && c != EOF) { 4.1314 + if (c == '\\') { 4.1315 + c = getchr(); 4.1316 + if (c != '%') 4.1317 + cmadd('\\'); 4.1318 + cmadd(c); 4.1319 + } else if (c == '%') { 4.1320 + for (pp = savedfile; *pp; pp++) 4.1321 + cmadd(*pp); 4.1322 + mod = 1; 4.1323 + } else 4.1324 + cmadd(c); 4.1325 + c = getchr(); 4.1326 + } 4.1327 + cmadd('\0'); 4.1328 + if (pvsize < cmsize && (prev = realloc(prev, pvsize=cmsize)) == 0) 4.1329 + error("line too long"); 4.1330 + strcpy(prev, line); 4.1331 + if (mod) 4.1332 + nlputs(line); 4.1333 + return line; 4.1334 +} 4.1335 + 4.1336 +static void 4.1337 +quit(int signo) 4.1338 +{ 4.1339 + lastsig = signo; 4.1340 + if (vflag && fchange) { 4.1341 + fchange = 0; 4.1342 + error("warning: expecting `w'"); 4.1343 + } 4.1344 + if (wrtemp) 4.1345 + unlink(wrtemp); 4.1346 + unlink(tfname); 4.1347 + exit(status); 4.1348 +} 4.1349 + 4.1350 +static void 4.1351 +delete(void) 4.1352 +{ 4.1353 + setdot(); 4.1354 + newline(); 4.1355 + nonzero(); 4.1356 + checkpoint(); 4.1357 + rdelete(addr1, addr2); 4.1358 +} 4.1359 + 4.1360 +static void 4.1361 +rdelete(long *ad1, long *ad2) 4.1362 +{ 4.1363 + register long *a1, *a2, *a3; 4.1364 + 4.1365 + a1 = ad1; 4.1366 + a2 = ad2+1; 4.1367 + a3 = dol; 4.1368 + dol -= a2 - a1; 4.1369 + do { 4.1370 + *a1++ = *a2++; 4.1371 + } while (a2 <= a3); 4.1372 + a1 = ad1; 4.1373 + if (a1 > dol) 4.1374 + a1 = dol; 4.1375 + dot = a1; 4.1376 + fchange = 1; 4.1377 +} 4.1378 + 4.1379 +static void 4.1380 +gdelete(void) 4.1381 +{ 4.1382 + register long *a1, *a2, *a3; 4.1383 + 4.1384 + a3 = dol; 4.1385 + for (a1=zero+1; (*a1&01)==0; a1++) 4.1386 + if (a1>=a3) 4.1387 + return; 4.1388 + for (a2=a1+1; a2<=a3;) { 4.1389 + if (*a2&01) { 4.1390 + a2++; 4.1391 + dot = a1; 4.1392 + } else 4.1393 + *a1++ = *a2++; 4.1394 + } 4.1395 + dol = a1-1; 4.1396 + if (dot>dol) 4.1397 + dot = dol; 4.1398 + fchange = 1; 4.1399 +} 4.1400 + 4.1401 +static char * 4.1402 +getline(long tl, int nulterm) 4.1403 +{ 4.1404 + register char *bp, *lp; 4.1405 + register long nl; 4.1406 + 4.1407 + lp = linebuf; 4.1408 + bp = getblock(tl, READ); 4.1409 + nl = nleft; 4.1410 + tl &= ~0377; 4.1411 + while (*lp++ = *bp++) { 4.1412 + if (lp[-1] == '\n' && nulterm) { 4.1413 + lp[-1] = '\0'; 4.1414 + break; 4.1415 + } 4.1416 + if (--nl == 0) { 4.1417 + bp = getblock(tl+=0400, READ); 4.1418 + nl = nleft; 4.1419 + } 4.1420 + } 4.1421 + return(linebuf); 4.1422 +} 4.1423 + 4.1424 +static int 4.1425 +putline(void) 4.1426 +{ 4.1427 + register char *bp, *lp; 4.1428 + register long nl; 4.1429 + long tl; 4.1430 + 4.1431 + fchange = 1; 4.1432 + lp = linebuf; 4.1433 + tl = tline; 4.1434 + bp = getblock(tl, WRITE); 4.1435 + nl = nleft; 4.1436 + tl &= ~0377; 4.1437 + while (*bp = *lp++) { 4.1438 + if (*bp++ == '\n' && insub) { 4.1439 + *--bp = 0; 4.1440 + linebp = lp; 4.1441 + break; 4.1442 + } 4.1443 + if (--nl == 0) { 4.1444 + bp = getblock(tl+=0400, WRITE); 4.1445 + nl = nleft; 4.1446 + } 4.1447 + } 4.1448 + nl = tline; 4.1449 + tline += (((lp-linebuf)+03)>>1)&(MAXCNT-1); 4.1450 + return(nl); 4.1451 +} 4.1452 + 4.1453 +static char * 4.1454 +getblock(long atl, long iof) 4.1455 +{ 4.1456 + register long bno, off; 4.1457 + 4.1458 + bno = (atl>>8)&BLKMSK; 4.1459 + off = (atl<<1)&0774; 4.1460 + if (bno >= BLKMSK) { 4.1461 + lastc = '\n'; 4.1462 + error("temp file too big"); 4.1463 + } 4.1464 + nleft = 512 - off; 4.1465 + if (bno==iblock) { 4.1466 + ichanged |= iof; 4.1467 + return(ibuff+off); 4.1468 + } 4.1469 + if (bno==oblock) 4.1470 + return(obuff+off); 4.1471 + if (iof==READ) { 4.1472 + if (ichanged) 4.1473 + blkio(iblock, ibuff, 1); 4.1474 + ichanged = 0; 4.1475 + iblock = bno; 4.1476 + blkio(bno, ibuff, 0); 4.1477 + return(ibuff+off); 4.1478 + } 4.1479 + if (oblock>=0) 4.1480 + blkio(oblock, obuff, 1); 4.1481 + oblock = bno; 4.1482 + return(obuff+off); 4.1483 +} 4.1484 + 4.1485 +static void 4.1486 +blkio(long b, char *buf, int wr) 4.1487 +{ 4.1488 + lseek(tfile, b<<9, SEEK_SET); 4.1489 + if ((wr ? write(tfile, buf, 512) : read (tfile, buf, 512)) != 512) { 4.1490 + status = 1; 4.1491 + error("I/O error on temp file"); 4.1492 + } 4.1493 +} 4.1494 + 4.1495 +static void 4.1496 +init(void) 4.1497 +{ 4.1498 + register long *markp; 4.1499 + 4.1500 + tline = 2; 4.1501 + for (markp = names; markp < &names[26]; markp++) 4.1502 + *markp = 0; 4.1503 + for (markp = undnames; markp < &undnames[26]; markp++) 4.1504 + *markp = 0; 4.1505 + subnewa = 0; 4.1506 + anymarks = 0; 4.1507 + iblock = -1; 4.1508 + oblock = -1; 4.1509 + ichanged = 0; 4.1510 + tfile = maketf(tfile); 4.1511 + dot = dol = zero; 4.1512 + unddot = NULL; 4.1513 +} 4.1514 + 4.1515 +static void 4.1516 +global(int k, int ia) 4.1517 +{ 4.1518 + register int c; 4.1519 + register long *a1; 4.1520 + static char *globuf; 4.1521 + char mb[MB_LEN_MAX+1]; 4.1522 + int spflag = 0; 4.1523 + 4.1524 + if (globp) 4.1525 + error("multiple globals not allowed"); 4.1526 + setall(); 4.1527 + nonzero(); 4.1528 + if ((c=GETWC(mb))=='\n') 4.1529 + error("incomplete global expression"); 4.1530 + compile(NULL, expbuf, &expbuf[ESIZE], c); 4.1531 + if (!ia) { 4.1532 + globrd(&globuf, EOF); 4.1533 + if (globuf[0] == '\n') 4.1534 + globuf[0] = 'p', globuf[1] = '\n', globuf[2] = '\0'; 4.1535 + } else { 4.1536 + newline(); 4.1537 + spflag = pflag; 4.1538 + pflag = 0; 4.1539 + } 4.1540 + checkpoint(); 4.1541 + for (a1=zero; a1<=dol; a1++) { 4.1542 + *a1 &= ~01; 4.1543 + if (a1>=addr1 && a1<=addr2 && execute(0, a1, 0)==k) 4.1544 + *a1 |= 01; 4.1545 + } 4.1546 + /* 4.1547 + * Special case: g/.../d (avoid n^2 algorithm) 4.1548 + */ 4.1549 + if (!ia && globuf[0]=='d' && globuf[1]=='\n' && globuf[2]=='\0') { 4.1550 + gdelete(); 4.1551 + return; 4.1552 + } 4.1553 + for (a1=zero; a1<=dol; a1++) { 4.1554 + if (*a1 & 01) { 4.1555 + *a1 &= ~01; 4.1556 + dot = a1; 4.1557 + if (ia) { 4.1558 + puts(getline(*a1, 0)); 4.1559 + if ((c = getchr()) == EOF) 4.1560 + error("command expected"); 4.1561 + if (c == 'a' || c == 'c' || c == 'i') 4.1562 + error("a, i, or c not allowed in G"); 4.1563 + else if (c == '&') { 4.1564 + if ((c = getchr()) != '\n') 4.1565 + error("end of line expected"); 4.1566 + if (globuf == 0 || *globuf == 0) 4.1567 + error("no remembered command"); 4.1568 + } else if (c == '\n') { 4.1569 + a1 = zero; 4.1570 + continue; 4.1571 + } else 4.1572 + globrd(&globuf, c); 4.1573 + } 4.1574 + globp = globuf; 4.1575 + commands(); 4.1576 + globp = NULL; 4.1577 + a1 = zero; 4.1578 + } 4.1579 + } 4.1580 + if (ia) 4.1581 + pflag = spflag; 4.1582 +} 4.1583 + 4.1584 +static void 4.1585 +globrd(char **globuf, register int c) 4.1586 +{ 4.1587 + register int i; 4.1588 + 4.1589 + if (*globuf == 0 && (*globuf = malloc(GBSIZE=256)) == 0) 4.1590 + error("global too long"); 4.1591 + i = 0; 4.1592 + if (c != EOF) 4.1593 + (*globuf)[i++] = c; 4.1594 + while ((c = getchr()) != '\n') { 4.1595 + if (c==EOF) 4.1596 + error("incomplete global expression"); 4.1597 + if (c=='\\') { 4.1598 + c = getchr(); 4.1599 + if (c!='\n') 4.1600 + (*globuf)[i++] = '\\'; 4.1601 + } 4.1602 + (*globuf)[i++] = c; 4.1603 + if (i>=GBSIZE-4 && (*globuf=realloc(*globuf,GBSIZE+=256)) == 0) 4.1604 + error("global too long"); 4.1605 + } 4.1606 + (*globuf)[i++] = '\n'; 4.1607 + (*globuf)[i++] = 0; 4.1608 +} 4.1609 + 4.1610 +static void 4.1611 +join(void) 4.1612 +{ 4.1613 + register int i, j; 4.1614 + register long *a1; 4.1615 + 4.1616 + j = 0; 4.1617 + for (a1=addr1; a1<=addr2; a1++) { 4.1618 + i = getline(*a1, 0) - linebuf; 4.1619 + while (genbuf[j] = linebuf[i++]) 4.1620 + if (j++ >= LBSIZE-2) 4.1621 + growlb("line too long"); 4.1622 + } 4.1623 + i = 0; 4.1624 + j = 0; 4.1625 + while (linebuf[i++] = genbuf[j++]) 4.1626 + ; 4.1627 + *addr1 = putline(); 4.1628 + if (addr1<addr2) 4.1629 + rdelete(addr1+1, addr2); 4.1630 + dot = addr1; 4.1631 +} 4.1632 + 4.1633 +static void 4.1634 +substitute(int inglob) 4.1635 +{ 4.1636 + register long *markp; 4.1637 + register long *a1; 4.1638 + intptr_t nl; 4.1639 + int gsubf; 4.1640 + 4.1641 + checkpoint(); 4.1642 + gsubf = compsub(); 4.1643 + insub = 1; 4.1644 + for (a1 = addr1; a1 <= addr2; a1++) { 4.1645 + long *ozero; 4.1646 + if (execute(0, a1, 1)==0) 4.1647 + continue; 4.1648 + inglob |= dosub(gsubf < 2); 4.1649 + if (gsubf) { 4.1650 + int i = 1; 4.1651 + 4.1652 + while (*loc2) { 4.1653 + if (execute(1, NULL, 1)==0) 4.1654 + break; 4.1655 + inglob |= dosub(gsubf == -1 || ++i == gsubf); 4.1656 + } 4.1657 + } 4.1658 + subnewa = putline(); 4.1659 + *a1 &= ~01; 4.1660 + if (anymarks) { 4.1661 + for (markp = names; markp < &names[26]; markp++) 4.1662 + if (*markp == *a1) 4.1663 + *markp = subnewa; 4.1664 + } 4.1665 + *a1 = subnewa; 4.1666 + ozero = zero; 4.1667 + nl = append(getsub, a1); 4.1668 + nl += zero-ozero; 4.1669 + a1 += nl; 4.1670 + addr2 += nl; 4.1671 + } 4.1672 + insub = 0; 4.1673 + if (inglob==0) 4.1674 + error("no match"); 4.1675 +} 4.1676 + 4.1677 +static int 4.1678 +compsub(void) 4.1679 +{ 4.1680 + register int seof, c, i; 4.1681 + static char *oldrhs; 4.1682 + static int orhssz; 4.1683 + char mb[MB_LEN_MAX+1]; 4.1684 + 4.1685 + if ((seof = GETWC(mb)) == '\n' || seof == ' ') 4.1686 + error("illegal or missing delimiter"); 4.1687 + nodelim = 0; 4.1688 + compile(NULL, expbuf, &expbuf[ESIZE], seof); 4.1689 + i = 0; 4.1690 + for (;;) { 4.1691 + c = GETWC(mb); 4.1692 + if (c=='\\') { 4.1693 + if (i >= RHSIZE-2) 4.1694 + growrhs("replacement string too long"); 4.1695 + rhsbuf[i++] = c; 4.1696 + c = GETWC(mb); 4.1697 + } else if (c=='\n') { 4.1698 + if (globp && *globp) { 4.1699 + if (i >= RHSIZE-2) 4.1700 + growrhs("replacement string too long"); 4.1701 + rhsbuf[i++] = '\\'; 4.1702 + } 4.1703 + else if (nodelim) 4.1704 + error("illegal or missing delimiter"); 4.1705 + else { 4.1706 + peekc = c; 4.1707 + pflag++; 4.1708 + break; 4.1709 + } 4.1710 + } else if (c==seof) 4.1711 + break; 4.1712 + for (c = 0; c==0 || mb[c]; c++) { 4.1713 + if (i >= RHSIZE-2) 4.1714 + growrhs("replacement string too long"); 4.1715 + rhsbuf[i++] = mb[c]; 4.1716 + } 4.1717 + } 4.1718 + rhsbuf[i++] = 0; 4.1719 + if (rhsbuf[0] == '%' && rhsbuf[1] == 0) { 4.1720 + if (orhssz == 0) 4.1721 + error("no remembered replacement string"); 4.1722 + strcpy(rhsbuf, oldrhs); 4.1723 + } else { 4.1724 + if (orhssz < RHSIZE && 4.1725 + (oldrhs = realloc(oldrhs, orhssz=RHSIZE)) == 0) 4.1726 + error("replacement string too long"); 4.1727 + strcpy(oldrhs, rhsbuf); 4.1728 + } 4.1729 + if ((peekc = getchr()) == 'g') { 4.1730 + peekc = 0; 4.1731 + newline(); 4.1732 + return(-1); 4.1733 + } else if (peekc >= '0' && peekc <= '9') { 4.1734 + c = getnum(); 4.1735 + if (c < 1 || c > LBSIZE) 4.1736 + error("invalid count"); 4.1737 + newline(); 4.1738 + return c; 4.1739 + } 4.1740 + newline(); 4.1741 + return(0); 4.1742 +} 4.1743 + 4.1744 +static int 4.1745 +getsub(void) 4.1746 +{ 4.1747 + register char *p1, *p2; 4.1748 + 4.1749 + p1 = linebuf; 4.1750 + if ((p2 = linebp) == 0) 4.1751 + return(EOF); 4.1752 + while (*p1++ = *p2++) 4.1753 + ; 4.1754 + linebp = 0; 4.1755 + return(0); 4.1756 +} 4.1757 + 4.1758 +static int 4.1759 +dosub(int really) 4.1760 +{ 4.1761 + register char *lp, *sp; 4.1762 + register int i, j, k; 4.1763 + int c; 4.1764 + 4.1765 + if (!really) 4.1766 + goto copy; 4.1767 + i = 0; 4.1768 + j = 0; 4.1769 + k = 0; 4.1770 + while (&linebuf[i] < loc1) 4.1771 + genbuf[j++] = linebuf[i++]; 4.1772 + while (c = rhsbuf[k++]&0377) { 4.1773 + if (c=='&') { 4.1774 + j = place(j, loc1, loc2); 4.1775 + continue; 4.1776 + } else if (c == '\\') { 4.1777 + c = rhsbuf[k++]&0377; 4.1778 + if (c >='1' && c < nbra+'1') { 4.1779 + j = place(j, braslist[c-'1'], braelist[c-'1']); 4.1780 + continue; 4.1781 + } 4.1782 + } 4.1783 + if (j >= LBSIZE) 4.1784 + growlb("line too long"); 4.1785 + genbuf[j++] = c; 4.1786 + } 4.1787 + i = loc2 - linebuf; 4.1788 + loc2 = j + linebuf; 4.1789 +#if defined (SUS) || defined (SU3) || defined (S42) 4.1790 + if (loc1 == &linebuf[i]) { 4.1791 + int n; 4.1792 + wchar_t wc; 4.1793 + if (mb_cur_max > 1 && (n = mbtowc(&wc, loc2, mb_cur_max)) > 0) 4.1794 + loc2 += n; 4.1795 + else 4.1796 + loc2++; 4.1797 + } 4.1798 +#endif /* SUS || SU3 || S42 */ 4.1799 + while (genbuf[j++] = linebuf[i++]) 4.1800 + if (j >= LBSIZE) 4.1801 + growlb("line too long"); 4.1802 + if (really) { 4.1803 + lp = linebuf; 4.1804 + sp = genbuf; 4.1805 + } else { 4.1806 + copy: sp = linebuf; 4.1807 + lp = genbuf; 4.1808 + } 4.1809 + while (*lp++ = *sp++) 4.1810 + ; 4.1811 + return really; 4.1812 +} 4.1813 + 4.1814 +static int 4.1815 +place(register int j, register const char *l1, register const char *l2) 4.1816 +{ 4.1817 + 4.1818 + while (l1 < l2) { 4.1819 + genbuf[j++] = *l1++; 4.1820 + if (j >= LBSIZE) 4.1821 + growlb("line too long"); 4.1822 + } 4.1823 + return(j); 4.1824 +} 4.1825 + 4.1826 +static void 4.1827 +move(int cflag) 4.1828 +{ 4.1829 + register long *adt, *ad1, *ad2; 4.1830 + 4.1831 + setdot(); 4.1832 + nonzero(); 4.1833 + if ((adt = address())==0) 4.1834 + error("illegal move destination"); 4.1835 + newline(); 4.1836 + checkpoint(); 4.1837 + if (cflag) { 4.1838 + long *ozero; 4.1839 + intptr_t delta; 4.1840 + ad1 = dol; 4.1841 + ozero = zero; 4.1842 + append(getcopy, ad1++); 4.1843 + ad2 = dol; 4.1844 + delta = zero - ozero; 4.1845 + ad1 += delta; 4.1846 + adt += delta; 4.1847 + } else { 4.1848 + ad2 = addr2; 4.1849 + for (ad1 = addr1; ad1 <= ad2;) 4.1850 + *ad1++ &= ~01; 4.1851 + ad1 = addr1; 4.1852 + } 4.1853 + ad2++; 4.1854 + if (adt<ad1) { 4.1855 + dot = adt + (ad2-ad1); 4.1856 + if ((++adt)==ad1) 4.1857 + return; 4.1858 + reverse(adt, ad1); 4.1859 + reverse(ad1, ad2); 4.1860 + reverse(adt, ad2); 4.1861 + } else if (adt >= ad2) { 4.1862 + dot = adt++; 4.1863 + reverse(ad1, ad2); 4.1864 + reverse(ad2, adt); 4.1865 + reverse(ad1, adt); 4.1866 + } else 4.1867 + error("illegal move destination"); 4.1868 + fchange = 1; 4.1869 +} 4.1870 + 4.1871 +static void 4.1872 +reverse(register long *a1, register long *a2) 4.1873 +{ 4.1874 + register int t; 4.1875 + 4.1876 + for (;;) { 4.1877 + t = *--a2; 4.1878 + if (a2 <= a1) 4.1879 + return; 4.1880 + *a2 = *a1; 4.1881 + *a1++ = t; 4.1882 + } 4.1883 +} 4.1884 + 4.1885 +static int 4.1886 +getcopy(void) 4.1887 +{ 4.1888 + if (addr1 > addr2) 4.1889 + return(EOF); 4.1890 + getline(*addr1++, 0); 4.1891 + return(0); 4.1892 +} 4.1893 + 4.1894 +static int 4.1895 +execute(int gf, long *addr, int subst) 4.1896 +{ 4.1897 + register char *p1, *p2, c; 4.1898 + 4.1899 + for (c=0; c<NBRA; c++) { 4.1900 + braslist[c&0377] = 0; 4.1901 + braelist[c&0377] = 0; 4.1902 + } 4.1903 + if (gf) { 4.1904 + if (circf) 4.1905 + return(0); 4.1906 + p1 = linebuf; 4.1907 + p2 = genbuf; 4.1908 + while (*p1++ = *p2++) 4.1909 + ; 4.1910 + locs = p1 = loc2; 4.1911 + } else { 4.1912 + if (addr==zero) 4.1913 + return(0); 4.1914 + p1 = getline(*addr, 1); 4.1915 + locs = 0; 4.1916 + } 4.1917 + needsub = subst; 4.1918 + return step(p1, expbuf); 4.1919 +} 4.1920 + 4.1921 +static void 4.1922 +cmplerr(int c) 4.1923 +{ 4.1924 + const char *msg; 4.1925 + 4.1926 +#if !defined (SUS) && !defined (S42) && !defined (SU3) 4.1927 + expbuf[0] = 0; 4.1928 +#endif 4.1929 + switch (c) { 4.1930 + case 11: 4.1931 + msg = "Range endpoint too large"; 4.1932 + break; 4.1933 + case 16: 4.1934 + msg = "bad number"; 4.1935 + break; 4.1936 + case 25: 4.1937 + msg = "`\\digit' out of range"; 4.1938 + break; 4.1939 + case 36: 4.1940 + msg = "illegal or missing delimiter"; 4.1941 + break; 4.1942 + case 41: 4.1943 + msg = "no remembered search string"; 4.1944 + break; 4.1945 + case 42: 4.1946 + msg = "'\\( \\)' imbalance"; 4.1947 + break; 4.1948 + case 43: 4.1949 + msg = "Too many `\\(' s"; 4.1950 + break; 4.1951 + case 44: 4.1952 + msg = "more than 2 numbers given"; 4.1953 + break; 4.1954 + case 45: 4.1955 + msg = "'\\}' expected"; 4.1956 + break; 4.1957 + case 46: 4.1958 + msg = "first number exceeds second"; 4.1959 + break; 4.1960 + case 49: 4.1961 + msg = "'[ ]' imbalance"; 4.1962 + break; 4.1963 + case 50: 4.1964 + msg = "regular expression overflow"; 4.1965 + break; 4.1966 + case 67: 4.1967 + msg = "illegal byte sequence"; 4.1968 + break; 4.1969 + default: 4.1970 + msg = "regular expression error"; 4.1971 + break; 4.1972 + } 4.1973 + error(msg); 4.1974 +} 4.1975 + 4.1976 +static void 4.1977 +doprnt(long *bot, long *top) 4.1978 +{ 4.1979 + long *a1; 4.1980 + 4.1981 + a1 = bot; 4.1982 + do { 4.1983 + if (numbf ^ Nflag) { 4.1984 + putd(a1-zero); 4.1985 + putchr('\t'); 4.1986 + } 4.1987 + nlputs(getline(*a1++, 0)); 4.1988 + } while (a1 <= top); 4.1989 + pflag = 0; 4.1990 + listf = 0; 4.1991 + numbf = 0; 4.1992 +} 4.1993 + 4.1994 +static void 4.1995 +putd(long c) 4.1996 +{ 4.1997 + register int r; 4.1998 + 4.1999 + r = c%10; 4.2000 + c /= 10; 4.2001 + if (c) 4.2002 + putd(c); 4.2003 + putchr(r + '0'); 4.2004 +} 4.2005 + 4.2006 +static void 4.2007 +nlputs(register const char *sp) 4.2008 +{ 4.2009 + if (listf) 4.2010 + list(sp); 4.2011 + else if (tabstops) 4.2012 + expand(sp); 4.2013 + else 4.2014 + puts(sp); 4.2015 +} 4.2016 + 4.2017 +static void 4.2018 +puts(register const char *sp) 4.2019 +{ 4.2020 + while (*sp) { 4.2021 + if (*sp != '\n') 4.2022 + putchr(*sp++ & 0377); 4.2023 + else 4.2024 + sp++, putchr('\0'); 4.2025 + } 4.2026 + putchr('\n'); 4.2027 +} 4.2028 + 4.2029 +static void 4.2030 +list(const char *lp) 4.2031 +{ 4.2032 + int col, n; 4.2033 + wchar_t c; 4.2034 + 4.2035 + col = numbf ^ Nflag ? 8 : 0; 4.2036 + while (*lp) { 4.2037 + if (mb_cur_max > 1 && *lp&0200) 4.2038 + n = mbtowc(&c, lp, mb_cur_max); 4.2039 + else { 4.2040 + n = 1; 4.2041 + c = *lp&0377; 4.2042 + } 4.2043 + if (col+1 >= 72) { 4.2044 + col = 0; 4.2045 + putchr('\\'); 4.2046 + putchr('\n'); 4.2047 + } 4.2048 + if (n<0 || 4.2049 +#if defined (SUS) || defined (S42) || defined (SU3) 4.2050 + c == '\\' || 4.2051 +#endif /* SUS || S42 || SU3 */ 4.2052 + !(mb_cur_max>1 ? iswprint(c) : isprint(c))) { 4.2053 + if (n<0) 4.2054 + n = 1; 4.2055 + while (n--) 4.2056 + col += lstchr(*lp++&0377); 4.2057 + } else if (mb_cur_max>1) { 4.2058 + col += wcwidth(c); 4.2059 + while (n--) 4.2060 + putchr(*lp++&0377); 4.2061 + } else { 4.2062 + putchr(*lp++&0377); 4.2063 + col++; 4.2064 + } 4.2065 + } 4.2066 +#if defined (SUS) || defined (S42) || defined (SU3) 4.2067 + putchr('$'); 4.2068 +#endif 4.2069 + putchr('\n'); 4.2070 +} 4.2071 + 4.2072 +static int 4.2073 +lstchr(int c) 4.2074 +{ 4.2075 + int cad = 1, d; 4.2076 + 4.2077 +#if !defined (SUS) && !defined (S42) && !defined (SU3) 4.2078 + if (c=='\t') { 4.2079 + c = '>'; 4.2080 + goto esc; 4.2081 + } 4.2082 + if (c=='\b') { 4.2083 + c = '<'; 4.2084 + esc: 4.2085 + putchr('-'); 4.2086 + putchr('\b'); 4.2087 + putchr(c); 4.2088 + } else if (c == '\n') { 4.2089 + putchr('\\'); 4.2090 + putchr('0'); 4.2091 + putchr('0'); 4.2092 + putchr('0'); 4.2093 + cad = 4; 4.2094 +#else /* !SUS, !S42, !SU3 */ 4.2095 + if (c == '\n') 4.2096 + c = '\0'; 4.2097 + if (c == '\\') { 4.2098 + putchr('\\'); 4.2099 + putchr('\\'); 4.2100 + cad = 2; 4.2101 + } else if (c == '\a') { 4.2102 + putchr('\\'); 4.2103 + putchr('a'); 4.2104 + cad = 2; 4.2105 + } else if (c == '\b') { 4.2106 + putchr('\\'); 4.2107 + putchr('b'); 4.2108 + cad = 2; 4.2109 + } else if (c == '\f') { 4.2110 + putchr('\\'); 4.2111 + putchr('f'); 4.2112 + cad = 2; 4.2113 + } else if (c == '\r') { 4.2114 + putchr('\\'); 4.2115 + putchr('r'); 4.2116 + cad = 2; 4.2117 + } else if (c == '\t') { 4.2118 + putchr('\\'); 4.2119 + putchr('t'); 4.2120 + cad = 2; 4.2121 + } else if (c == '\v') { 4.2122 + putchr('\\'); 4.2123 + putchr('v'); 4.2124 + cad = 2; 4.2125 +#endif /* !SUS, !S42, !SU3 */ 4.2126 + } else { 4.2127 + putchr('\\'); 4.2128 + putchr(((c&~077)>>6)+'0'); 4.2129 + c &= 077; 4.2130 + d = c & 07; 4.2131 + putchr(c > d ? ((c-d)>>3)+'0' : '0'); 4.2132 + putchr(d+'0'); 4.2133 + cad = 4; 4.2134 + } 4.2135 + return cad; 4.2136 +} 4.2137 + 4.2138 +static void 4.2139 +putstr(const char *s) 4.2140 +{ 4.2141 + while (*s) 4.2142 + putchr(*s++); 4.2143 +} 4.2144 + 4.2145 +static char line[70]; 4.2146 +static char *linp = line; 4.2147 + 4.2148 +static void 4.2149 +putchr(int ac) 4.2150 +{ 4.2151 + register char *lp; 4.2152 + register int c; 4.2153 + 4.2154 + lp = linp; 4.2155 + c = ac; 4.2156 + *lp++ = c; 4.2157 + if(c == '\n' || lp >= &line[64]) { 4.2158 + linp = line; 4.2159 + write(1, line, lp-line); 4.2160 + return; 4.2161 + } 4.2162 + linp = lp; 4.2163 +} 4.2164 + 4.2165 +static void 4.2166 +checkpoint(void) 4.2167 +{ 4.2168 + long *a1, *a2; 4.2169 + 4.2170 + if (undzero && globp == NULL) { 4.2171 + for (a1 = zero+1, a2 = undzero+1; a1 <= dol; a1++, a2++) 4.2172 + *a2 = *a1; 4.2173 + unddot = &undzero[dot-zero]; 4.2174 + unddol = &undzero[dol-zero]; 4.2175 + for (a1 = names, a2 = undnames; a1 < &names[26]; a1++, a2++) 4.2176 + *a2 = *a1; 4.2177 + } 4.2178 +} 4.2179 + 4.2180 +#define swap(a, b) (t = a, a = b, b = t) 4.2181 + 4.2182 +static void 4.2183 +undo(void) 4.2184 +{ 4.2185 + long *t; 4.2186 + 4.2187 + if (undzero == NULL) 4.2188 + error("no undo information saved"); 4.2189 + swap(zero, undzero); 4.2190 + swap(dot, unddot); 4.2191 + swap(dol, unddol); 4.2192 + swap(names, undnames); 4.2193 +} 4.2194 + 4.2195 +static int 4.2196 +maketf(int fd) 4.2197 +{ 4.2198 + char *tmpdir; 4.2199 + 4.2200 + if (fd == -1) { 4.2201 + if ((tmpdir = getenv("TMPDIR")) == NULL || 4.2202 + (fd = creatf(tmpdir)) < 0) 4.2203 + if ((fd = creatf("/var/tmp")) < 0 && 4.2204 + (fd = creatf("/tmp")) < 0) 4.2205 + error("cannot create temporary file"); 4.2206 + } else 4.2207 + ftruncate(fd, 0); /* blkio() will seek to 0 anyway */ 4.2208 + return fd; 4.2209 +} 4.2210 + 4.2211 +static int 4.2212 +creatf(const char *tmpdir) 4.2213 +{ 4.2214 + if (strlen(tmpdir) >= sizeof tfname - 9) 4.2215 + return -1; 4.2216 + strcpy(tfname, tmpdir); 4.2217 + strcat(tfname, "/eXXXXXX"); 4.2218 + return mkstemp(tfname); 4.2219 +} 4.2220 + 4.2221 +static int 4.2222 +sopen(const char *fn, int rdwr) 4.2223 +{ 4.2224 + int pf[2], fd = -1; 4.2225 + 4.2226 + if (fn[0] == '!') { 4.2227 + fn++; 4.2228 + if (pipe(pf) < 0) 4.2229 + error("write or open on pipe failed"); 4.2230 + switch (pipid = fork()) { 4.2231 + case 0: 4.2232 + if (rdwr == READ) 4.2233 + dup2(pf[1], 1); 4.2234 + else 4.2235 + dup2(pf[0], 0); 4.2236 + close(pf[0]); 4.2237 + close(pf[1]); 4.2238 + sigset(SIGHUP, oldhup); 4.2239 + sigset(SIGQUIT, oldquit); 4.2240 + sigset(SIGPIPE, oldpipe); 4.2241 + execl(SHELL, "sh", "-c", fn, NULL); 4.2242 + _exit(0100); 4.2243 + default: 4.2244 + close(pf[rdwr == READ ? 1 : 0]); 4.2245 + fd = pf[rdwr == READ ? 0 : 1]; 4.2246 + break; 4.2247 + case -1: 4.2248 + error("fork failed - try again"); 4.2249 + } 4.2250 + } else if (rdwr == READ) 4.2251 + fd = open(fn, O_RDONLY); 4.2252 + else if (rdwr == EXIST) 4.2253 + fd = open(fn, O_WRONLY); 4.2254 + else /*if (rdwr == WRITE)*/ 4.2255 + fd = creat(fn, 0666); 4.2256 + if (fd >= 0 && rdwr == READ) 4.2257 + readop = 1; 4.2258 + if (fd >= 0) 4.2259 + fstat(fd, &fstbuf); 4.2260 + return fd; 4.2261 +} 4.2262 + 4.2263 +static void 4.2264 +sclose(int fd) 4.2265 +{ 4.2266 + int status; 4.2267 + 4.2268 + close(fd); 4.2269 + if (pipid >= 0) { 4.2270 + while (wait(&status) != pipid); 4.2271 + pipid = -1; 4.2272 + } 4.2273 + readop = 0; 4.2274 +} 4.2275 + 4.2276 +static void 4.2277 +fspec(const char *lp) 4.2278 +{ 4.2279 + struct termios ts; 4.2280 + const char *cp; 4.2281 + 4.2282 + freetabs(); 4.2283 + maxlength = 0; 4.2284 + if (tcgetattr(1, &ts) < 0 4.2285 +#ifdef TAB3 4.2286 + || (ts.c_oflag&TAB3) == 0 4.2287 +#endif 4.2288 + ) 4.2289 + return; 4.2290 + while (lp[0]) { 4.2291 + if (lp[0] == '<' && lp[1] == ':') 4.2292 + break; 4.2293 + lp++; 4.2294 + } 4.2295 + if (lp[0]) { 4.2296 + lp += 2; 4.2297 + while ((cp = ftok(&lp)) != NULL) { 4.2298 + switch (*cp) { 4.2299 + case 't': 4.2300 + freetabs(); 4.2301 + if ((tabstops = tabstring(&cp[1])) == NULL) 4.2302 + goto err; 4.2303 + break; 4.2304 + case 's': 4.2305 + maxlength = atoi(&cp[1]); 4.2306 + break; 4.2307 + case 'm': 4.2308 + case 'd': 4.2309 + case 'e': 4.2310 + break; 4.2311 + case ':': 4.2312 + if (cp[1] == '>') { 4.2313 + if (tabstops == NULL) 4.2314 + if ((tabstops = tabstring("0")) 4.2315 + == NULL) 4.2316 + goto err; 4.2317 + return; 4.2318 + } 4.2319 + /*FALLTHRU*/ 4.2320 + default: 4.2321 + err: freetabs(); 4.2322 + maxlength = 0; 4.2323 + errput("PWB spec problem", NULL); 4.2324 + return; 4.2325 + } 4.2326 + } 4.2327 + } 4.2328 +} 4.2329 + 4.2330 +static const char * 4.2331 +ftok(const char **lp) 4.2332 +{ 4.2333 + const char *cp; 4.2334 + 4.2335 + while (**lp && **lp != ':' && (**lp == ' ' || **lp == '\t')) 4.2336 + (*lp)++; 4.2337 + cp = *lp; 4.2338 + while (**lp && **lp != ':' && **lp != ' ' && **lp != '\t') 4.2339 + (*lp)++; 4.2340 + return cp; 4.2341 +} 4.2342 + 4.2343 +static struct tabulator * 4.2344 +repetitive(int repetition) 4.2345 +{ 4.2346 + struct tabulator *tp, *tabspec; 4.2347 + int col, i; 4.2348 + 4.2349 + if ((tp = tabspec = calloc(1, sizeof *tp)) == NULL) 4.2350 + return NULL; 4.2351 + tp->t_rep = repetition; 4.2352 + if (repetition > 0) { 4.2353 + for (col = 1+repetition, i = 0; i < 22; col += repetition) { 4.2354 + if ((tp->t_nxt = calloc(1, sizeof *tp)) == NULL) 4.2355 + return NULL; 4.2356 + tp = tp->t_nxt; 4.2357 + tp->t_tab = col; 4.2358 + } 4.2359 + } 4.2360 + return tabspec; 4.2361 +} 4.2362 + 4.2363 +#define blank(c) ((c) == ' ' || (c) == '\t') 4.2364 + 4.2365 +static struct tabulator * 4.2366 +tablist(const char *s) 4.2367 +{ 4.2368 + struct tabulator *tp, *tabspec; 4.2369 + char *x; 4.2370 + int prev = 0, val; 4.2371 + 4.2372 + if ((tp = tabspec = calloc(1, sizeof *tp)) == NULL) 4.2373 + return NULL; 4.2374 + for (;;) { 4.2375 + while (*s == ',') 4.2376 + s++; 4.2377 + if (*s == '\0' || blank(*s) || *s == ':') 4.2378 + break; 4.2379 + val = strtol(s, &x, 10); 4.2380 + if (*s == '+') 4.2381 + val += prev; 4.2382 + prev = val; 4.2383 + if (*s == '-' || (*x != ',' && !blank(*x) && *x != ':' && 4.2384 + *x != '\0')) 4.2385 + return NULL; 4.2386 + s = x; 4.2387 + if ((tp->t_nxt = calloc(1, sizeof *tp)) == NULL) 4.2388 + return NULL; 4.2389 + tp = tp->t_nxt; 4.2390 + tp->t_tab = val; 4.2391 + } 4.2392 + return tabspec; 4.2393 +} 4.2394 + 4.2395 +static struct tabulator * 4.2396 +tabstring(const char *s) 4.2397 +{ 4.2398 + const struct { 4.2399 + const char *c_nam; 4.2400 + const char *c_str; 4.2401 + } canned[] = { 4.2402 + { "a", "1,10,16,36,72" }, 4.2403 + { "a2", "1,10,16,40,72" }, 4.2404 + { "c", "1,8,12,16,20,55" }, 4.2405 + { "c2", "1,6,10,14,49" }, 4.2406 + { "c3", "1,6,10,14,18,22,26,30,34,38,42,46,50,54,58,62,67" }, 4.2407 + { "f", "1,7,11,15,19,23" }, 4.2408 + { "p", "1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61" }, 4.2409 + { "s", "1,10,55" }, 4.2410 + { "u", "1,12,20,44" }, 4.2411 + { 0, 0 } 4.2412 + }; 4.2413 + 4.2414 + int i, j; 4.2415 + 4.2416 + if (s[0] == '-') { 4.2417 + if (s[1] >= '0' && s[1] <= '9' && ((i = atoi(&s[1])) != 0)) 4.2418 + return repetitive(i); 4.2419 + for (i = 0; canned[i].c_nam; i++) { 4.2420 + for (j = 0; canned[i].c_nam[j]; j++) 4.2421 + if (s[j+1] != canned[i].c_nam[j]) 4.2422 + break; 4.2423 + if ((s[j+1]=='\0' || s[j+1]==':' || blank(s[j+1])) && 4.2424 + canned[i].c_nam[j] == '\0') 4.2425 + return tablist(canned[i].c_str); 4.2426 + } 4.2427 + return NULL; 4.2428 + } else 4.2429 + return tablist(s); 4.2430 +} 4.2431 + 4.2432 +static void 4.2433 +freetabs(void) 4.2434 +{ 4.2435 + struct tabulator *tp; 4.2436 + 4.2437 + tp = tabstops; 4.2438 + while (tp) { 4.2439 + tabstops = tp->t_nxt; 4.2440 + free(tp); 4.2441 + tp = tabstops; 4.2442 + } 4.2443 +} 4.2444 + 4.2445 +static void 4.2446 +expand(const char *s) 4.2447 +{ 4.2448 + struct tabulator *tp = tabstops; 4.2449 + int col = 0, n = 1, m, tabcnt = 0, nspc; 4.2450 + wchar_t wc; 4.2451 + 4.2452 + while (*s) { 4.2453 + nspc = 0; 4.2454 + switch (*s) { 4.2455 + case '\n': 4.2456 + putchr('\0'); 4.2457 + s++; 4.2458 + continue; 4.2459 + case '\t': 4.2460 + if (tp) { 4.2461 + if (tp->t_rep) { 4.2462 + if (col % tp->t_rep == 0) { 4.2463 + nspc++; 4.2464 + col++; 4.2465 + } 4.2466 + while (col % tp->t_rep) { 4.2467 + nspc++; 4.2468 + col++; 4.2469 + } 4.2470 + break; 4.2471 + } 4.2472 + while (tp && (col>tp->t_tab || tp->t_tab == 0)) 4.2473 + tp = tp->t_nxt; 4.2474 + if (tp && col == tp->t_tab) { 4.2475 + nspc++; 4.2476 + col++; 4.2477 + tp = tp->t_nxt; 4.2478 + } 4.2479 + if (tp) { 4.2480 + while (col < tp->t_tab) { 4.2481 + nspc++; 4.2482 + col++; 4.2483 + } 4.2484 + tp = tp->t_nxt; 4.2485 + break; 4.2486 + } 4.2487 + } 4.2488 + tabcnt = 1; 4.2489 + nspc++; 4.2490 + break; 4.2491 + default: 4.2492 + if (mb_cur_max>1 && (n=mbtowc(&wc, s, mb_cur_max))>0) { 4.2493 + if ((m = wcwidth(wc)) > 0) 4.2494 + col += m; 4.2495 + } else { 4.2496 + col++; 4.2497 + n = 1; 4.2498 + } 4.2499 + } 4.2500 + if (maxlength && col > maxlength) { 4.2501 + putstr("\ntoo long"); 4.2502 + break; 4.2503 + } 4.2504 + if (nspc) { 4.2505 + while (nspc--) 4.2506 + putchr(' '); 4.2507 + s++; 4.2508 + } else 4.2509 + while (n--) 4.2510 + putchr(*s++); 4.2511 + } 4.2512 + if (tabcnt) 4.2513 + putstr("\ntab count"); 4.2514 + putchr('\n'); 4.2515 +} 4.2516 + 4.2517 +static wint_t 4.2518 +GETWC(char *mb) 4.2519 +{ 4.2520 + int c, n; 4.2521 + 4.2522 + n = 1; 4.2523 + mb[0] = c = GETC(); 4.2524 + mb[1] = '\0'; 4.2525 + if (mb_cur_max > 1 && c&0200 && c != EOF) { 4.2526 + int m; 4.2527 + wchar_t wc; 4.2528 + 4.2529 + while ((m = mbtowc(&wc, mb, mb_cur_max)) < 0 && n<mb_cur_max) { 4.2530 + mb[n++] = c = GETC(); 4.2531 + mb[n] = '\0'; 4.2532 + if (c == '\n' || c == EOF) 4.2533 + break; 4.2534 + } 4.2535 + if (m != n) 4.2536 + ERROR(67); 4.2537 + return wc; 4.2538 + } else 4.2539 + return c; 4.2540 +} 4.2541 + 4.2542 +static void 4.2543 +growlb(const char *msg) 4.2544 +{ 4.2545 + char *olb = linebuf; 4.2546 + int i; 4.2547 + 4.2548 + LBSIZE += 512; 4.2549 + if ((linebuf = realloc(linebuf, LBSIZE)) == NULL || 4.2550 + (genbuf = realloc(genbuf, LBSIZE)) == NULL) 4.2551 + error(msg); 4.2552 + if (linebuf != olb) { 4.2553 + loc1 += linebuf - olb; 4.2554 + loc2 += linebuf - olb; 4.2555 + for (i = 0; i < NBRA; i++) { 4.2556 + if (braslist[i]) 4.2557 + braslist[i] += linebuf - olb; 4.2558 + if (braelist[i]) 4.2559 + braelist[i] += linebuf - olb; 4.2560 + } 4.2561 + } 4.2562 +} 4.2563 + 4.2564 +static void 4.2565 +growrhs(const char *msg) 4.2566 +{ 4.2567 + RHSIZE += 256; 4.2568 + if ((rhsbuf = realloc(rhsbuf, RHSIZE)) == NULL) 4.2569 + error(msg); 4.2570 +} 4.2571 + 4.2572 +static void 4.2573 +growfn(const char *msg) 4.2574 +{ 4.2575 + FNSIZE += 64; 4.2576 + if ((savedfile = realloc(savedfile, FNSIZE)) == NULL || 4.2577 + (file = realloc(file, FNSIZE)) == NULL) 4.2578 + error(msg); 4.2579 + if (FNSIZE == 64) 4.2580 + file[0] = savedfile[0] = 0; 4.2581 +} 4.2582 + 4.2583 +#if defined (SUS) || defined (S42) || defined (SU3) 4.2584 +union ptrstore { 4.2585 + void *vp; 4.2586 + char bp[sizeof (void *)]; 4.2587 +}; 4.2588 + 4.2589 +static void * 4.2590 +fetchptr(const char *bp) 4.2591 +{ 4.2592 + union ptrstore u; 4.2593 + int i; 4.2594 + 4.2595 + for (i = 0; i < sizeof (void *); i++) 4.2596 + u.bp[i] = bp[i]; 4.2597 + return u.vp; 4.2598 +} 4.2599 + 4.2600 +static void 4.2601 +storeptr(void *vp, char *bp) 4.2602 +{ 4.2603 + union ptrstore u; 4.2604 + int i; 4.2605 + 4.2606 + u.vp = vp; 4.2607 + for (i = 0; i < sizeof (void *); i++) 4.2608 + bp[i] = u.bp[i]; 4.2609 +} 4.2610 + 4.2611 +#define add(c) ((i>=LBSIZE ? (growlb("regular expression overflow"),0) : 0), \ 4.2612 + genbuf[i++] = (c)) 4.2613 + 4.2614 +#define copy(s) { \ 4.2615 + int m; \ 4.2616 + for (m = 0; m==0 || s[m]; m++) \ 4.2617 + add(s[m]); \ 4.2618 +} 4.2619 + 4.2620 +static char * 4.2621 +compile(char *unused, char *ep, const char *endbuf, int seof) 4.2622 +{ 4.2623 + INIT 4.2624 + int c, d, i; 4.2625 + regex_t *rp; 4.2626 + char *op; 4.2627 + char mb[MB_LEN_MAX+1]; 4.2628 + 4.2629 + op = ep; 4.2630 + ep += 2; 4.2631 + if ((rp = fetchptr(ep)) == NULL) { 4.2632 + if ((rp = calloc(1, sizeof *rp)) == NULL) 4.2633 + ERROR(50); 4.2634 + storeptr(rp, ep); 4.2635 + } 4.2636 + ep += sizeof (void *); 4.2637 + i = 0; 4.2638 + nbra = 0; 4.2639 + do { 4.2640 + if ((c = GETWC(mb)) == seof) 4.2641 + add('\0'); 4.2642 + else if (c == '\\') { 4.2643 + copy(mb); 4.2644 + c = GETWC(mb); 4.2645 + if (c == '(') 4.2646 + nbra++; 4.2647 + goto normchar; 4.2648 + } else if (c == '[') { 4.2649 + add(c); 4.2650 + d = EOF; 4.2651 + do { 4.2652 + c = GETWC(mb); 4.2653 + if (c == EOF || c == '\n') 4.2654 + ERROR(49); 4.2655 + copy(mb); 4.2656 + if (d=='[' && (c==':' || c=='.' || c=='=')) { 4.2657 + d = c; 4.2658 + do { 4.2659 + c = GETWC(mb); 4.2660 + if (c == EOF || c == '\n') 4.2661 + ERROR(49); 4.2662 + copy(mb); 4.2663 + } while (c != d || PEEKC() != ']'); 4.2664 + c = GETWC(mb); 4.2665 + copy(mb); 4.2666 + c = EOF; 4.2667 + } 4.2668 + d = c; 4.2669 + } while (c != ']'); 4.2670 + } else { 4.2671 + if (c == EOF || c == '\n') { 4.2672 + if (c == '\n') 4.2673 + UNGETC(c); 4.2674 + mb[0] = c = '\0'; 4.2675 + } 4.2676 + if (c == '\0') 4.2677 + nodelim = 1; 4.2678 + normchar: copy(mb); 4.2679 + } 4.2680 + } while (genbuf[i-1] != '\0'); 4.2681 + if (genbuf[0]) { 4.2682 + int reflags = 0; 4.2683 + 4.2684 +#ifdef REG_ANGLES 4.2685 + reflags |= REG_ANGLES; 4.2686 +#endif 4.2687 +#if defined (SU3) && defined (REG_AVOIDNULL) 4.2688 + reflags |= REG_AVOIDNULL; 4.2689 +#endif 4.2690 + if (op[0]) 4.2691 + regfree(rp); 4.2692 + op[0] = 0; 4.2693 + switch (regcomp(rp, genbuf, reflags)) { 4.2694 + case 0: 4.2695 + break; 4.2696 + case REG_ESUBREG: 4.2697 + ERROR(25); 4.2698 + /*NOTREACHED*/ 4.2699 + case REG_EBRACK: 4.2700 + ERROR(49); 4.2701 + /*NOTREACHED*/ 4.2702 + case REG_EPAREN: 4.2703 + ERROR(42); 4.2704 + /*NOTREACHED*/ 4.2705 + case REG_BADBR: 4.2706 + case REG_EBRACE: 4.2707 + ERROR(45); 4.2708 + /*NOTREACHED*/ 4.2709 + case REG_ERANGE: 4.2710 + ERROR(11); 4.2711 + /*NOTREACHED*/ 4.2712 + case REG_ESPACE: 4.2713 + ERROR(50); 4.2714 + /*NOTREACHED*/ 4.2715 + default: 4.2716 + ERROR(-1); 4.2717 + } 4.2718 + op[0] = 1; 4.2719 + circf = op[1] = genbuf[0] == '^'; 4.2720 + } else if (op[0]) { 4.2721 + circf = op[1]; 4.2722 + } else 4.2723 + ERROR(41); 4.2724 + return ep + sizeof (void *); 4.2725 +} 4.2726 + 4.2727 +static int 4.2728 +step(const char *lp, const char *ep) 4.2729 +{ 4.2730 + regex_t *rp; 4.2731 + regmatch_t bralist[NBRA+1]; 4.2732 + int eflag = 0; 4.2733 + int res; 4.2734 + int i; 4.2735 + 4.2736 + rp = fetchptr(&ep[2]); 4.2737 + if (ep[0] == 0) 4.2738 + return 0; 4.2739 + if (locs) 4.2740 + eflag |= REG_NOTBOL; 4.2741 + if ((res = regexec(rp, lp, needsub? NBRA+1 : 0, bralist, eflag)) == 0 && 4.2742 + needsub) { 4.2743 + loc1 = (char *)lp + bralist[0].rm_so; 4.2744 + loc2 = (char *)lp + bralist[0].rm_eo; 4.2745 + for (i = 1; i <= NBRA; i++) { 4.2746 + if (bralist[i].rm_so != -1) { 4.2747 + braslist[i-1] = (char *)lp + bralist[i].rm_so; 4.2748 + braelist[i-1] = (char *)lp + bralist[i].rm_eo; 4.2749 + } else 4.2750 + braslist[i-1] = braelist[i-1] = NULL; 4.2751 + } 4.2752 + } 4.2753 + return res == 0; 4.2754 +} 4.2755 +#endif /* SUS || S42 || SU3 */ 4.2756 + 4.2757 +static void 4.2758 +help(void) 4.2759 +{ 4.2760 + const char *desc[] = { 4.2761 + "(.)a append up to .", 4.2762 + "(.)b[n] browse n lines", 4.2763 + "(.,.)c change up to .", 4.2764 + "(.,.)d delete lines", 4.2765 + "e [file] edit file", 4.2766 + "E [file] force edit", 4.2767 + "f [file] print or set file", 4.2768 + "(1,$)g/RE/cmd global cmd", 4.2769 + "(1,$)G/RE/ interactive global", 4.2770 + "h print last error", 4.2771 + "H toggle error messages", 4.2772 + "help print this screen", 4.2773 + "(.)i insert up to .", 4.2774 + "(.,.+1)j join lines", 4.2775 + "(.)kx mark line with x", 4.2776 + "(.,.)l list lines", 4.2777 + "(.,.)ma move lines to a", 4.2778 + "(.,.)n number lines", 4.2779 + "N revert n and p", 4.2780 + "(.)o[n] show n lines of context", 4.2781 + "(.,.)p print lines", 4.2782 + "P toggle prompt", 4.2783 + "q quit", 4.2784 + "Q force quit", 4.2785 + "($)r read file", 4.2786 + "(.,.)s/RE/repl/ search and replace", 4.2787 + "(.,.)s/RE/rp/g replace all occurrences", 4.2788 + "(.,.)s/RE/rp/n replace n-th occurrence", 4.2789 + "(.,.)ta transfer lines to a", 4.2790 + "u undo last change", 4.2791 + "(1,$)v/RE/cmd reverse global", 4.2792 + "(1,$)V/RE/ reverse i/a global", 4.2793 + "(1,$)w [file] write file", 4.2794 + "(1,$)W [file] append to file", 4.2795 + "z write buffer and quit", 4.2796 + "($)= print line number", 4.2797 + "!command execute shell command", 4.2798 + "(.+1)<newline> print one line", 4.2799 + "/RE find RE forwards", 4.2800 + "?RE find RE backwards", 4.2801 + "1 first line", 4.2802 + ". current line", 4.2803 + "$ last line", 4.2804 + ", 1,$", 4.2805 + "; .,$", 4.2806 + NULL 4.2807 + }; 4.2808 + char line[100]; 4.2809 + int c, half, i, k; 4.2810 + 4.2811 + half = (sizeof desc / sizeof *desc) / 2; 4.2812 + for (i = 0; i < half && desc[i]; i++) { 4.2813 + c = 0; 4.2814 + for (k = 0; desc[i][k]; k++) 4.2815 + line[c++] = desc[i][k]; 4.2816 + if (desc[i+half]) { 4.2817 + while (c < 40) 4.2818 + line[c++] = ' '; 4.2819 + for (k = 0; desc[i+half][k]; k++) 4.2820 + line[c++] = desc[i+half][k]; 4.2821 + } 4.2822 + line[c] = 0; 4.2823 + puts(line); 4.2824 + } 4.2825 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/makefile Mon Sep 05 16:31:35 2011 +0200 5.3 @@ -0,0 +1,121 @@ 5.4 +# 5.5 +# Root directory. Mainly useful for package building; leave empty for 5.6 +# normal installation. 5.7 +# 5.8 +ROOT = 5.9 + 5.10 +PREFIX = /usr/local 5.11 + 5.12 +# 5.13 +# Location for binaries. 5.14 +# 5.15 +BINDIR = $(PREFIX)/bin 5.16 + 5.17 +# 5.18 +# Location for manual pages (with man1, man1b ... man8 below). 5.19 +# 5.20 +MANDIR = $(PREFIX)/share/man 5.21 + 5.22 +# 5.23 +# Compiler and linker flags. 5.24 +# 5.25 + 5.26 +#CC = $(HOME)/src/diet gcc 5.27 +CC = cc 5.28 + 5.29 +LD = $(CC) 5.30 +#LDFLAGS = --static 5.31 +LDFLAGS = 5.32 + 5.33 +# 5.34 +# Flags for the C preprocessor. 5.35 +# On Linux with glibc or uClibc, add -D_GNU_SOURCE. 5.36 +# On Solaris, -D__EXTENSIONS__ should be added. 5.37 +# On HP-UX, -D_INCLUDE__STDC_A1_SOURCE must be added. 5.38 +# On AIX, -D_TPARM_COMPAT must be added. 5.39 +# On AIX, -D_MTEXTEND_H should be added if mtextend.h is not found. 5.40 +# On NetBSD, add -DUSE_TERMCAP. 5.41 +# 5.42 +CPPFLAGS = -D_GNU_SOURCE 5.43 + 5.44 +# 5.45 +# CFLAGS makes it possible to give special 5.46 +# compiler flags for objects where speed is critical. There is no other 5.47 +# purpose with this so setting all to -O will work too. 5.48 +# 5.49 +WARN = 5.50 +CFLAGS = -O -fomit-frame-pointer $(WARN) 5.51 + 5.52 + 5.53 +# 5.54 +# Whether to use the supplied widechar emulation library. This should 5.55 +# only be enabled if the system lacks appropriate widechar support. 5.56 +# It is currently needed on 5.57 +# - Linux/diet libc 5.58 +# - FreeBSD 4 5.59 +# - NetBSD 1.x, because it lacks wctype_t/wctrans_t etc. in wctype.h. 5.60 +# - OpenBSD 5.61 +# 5.62 +#IWCHAR = -I../libwchar 5.63 +#LWCHAR = -L../libwchar -lwchar 5.64 + 5.65 + 5.66 +# 5.67 +# Binaries are stripped with this command after installation. 5.68 +# 5.69 +STRIP = strip -s -R .comment -R .note 5.70 + 5.71 +# 5.72 +# This is the shell used for the compilation phase, the execution of most 5.73 +# installed scripts, and the shell escapes in the traditional command 5.74 +# versions. It needs not conform to POSIX. The system shell should work 5.75 +# fine; for maximum compatibility with traditional tools, the Heirloom 5.76 +# Bourne shell is recommended. It then must obviously be compiled and 5.77 +# installed first. 5.78 +# 5.79 +SHELL = /bin/sh 5.80 + 5.81 +# 5.82 +# Don't change the rest of this file unless you really know what you are 5.83 +# doing. 5.84 +# 5.85 + 5.86 +######################################################################## 5.87 +######################################################################## 5.88 +######################################################################## 5.89 +######################################################################## 5.90 +######################################################################## 5.91 + 5.92 +all: ed 5.93 + 5.94 +ed: ed.o regexpr.o sigset.o sigrelse.o 5.95 + $(LD) $(LDFLAGS) ed.o -o ed 5.96 + 5.97 +ed.o: ed.c regexp.h 5.98 + $(CC) $(CFLAGS) $(CPPFLAGS) $(IWCHAR) -DSHELL='"$(SHELL)"' -I. -c ed.c 5.99 + 5.100 +regexpr.o: regexpr.c regexpr.h regexp.h 5.101 + $(CC) $(CFLAGS) $(CPPFLAGS) $(IWCHAR) -I. -c regexpr.c 5.102 + 5.103 +sigset.o: sigset.c sigset.h 5.104 + $(CC) $(CFLAGS) $(CPPFLAGS) -I. -c sigset.c 5.105 + 5.106 +sigrelse.o: sigrelse.c sigset.h 5.107 + $(CC) $(CFLAGS) $(CPPFLAGS) -I. -c sigrelse.c 5.108 + 5.109 + 5.110 +install: all 5.111 + mkdir -p $(ROOT)$(BINDIR) 5.112 + cp ed $(ROOT)$(BINDIR)/ed 5.113 + chmod 755 $(ROOT)$(BINDIR)/ed 5.114 + $(STRIP) $(ROOT)$(BINDIR)/ed 5.115 + mkdir -p $(ROOT)$(MANDIR)/man1 5.116 + cp ed.1 $(ROOT)$(MANDIR)/man1/ed.1 5.117 + chmod 644 $(ROOT)$(MANDIR)/man1/ed.1 5.118 + 5.119 +clean: 5.120 + rm -f ed.o regexpr.o sigset.o sigrelse.o core log *~ 5.121 + 5.122 +mrproper: clean 5.123 + rm -f ed 5.124 +
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/regexp.h Mon Sep 05 16:31:35 2011 +0200 6.3 @@ -0,0 +1,1211 @@ 6.4 +/* 6.5 + * Simple Regular Expression functions. Derived from Unix 7th Edition, 6.6 + * /usr/src/cmd/expr.y 6.7 + * 6.8 + * Modified by Gunnar Ritter, Freiburg i. Br., Germany, February 2002. 6.9 + * 6.10 + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. 6.11 + * 6.12 + * Redistribution and use in source and binary forms, with or without 6.13 + * modification, are permitted provided that the following conditions 6.14 + * are met: 6.15 + * Redistributions of source code and documentation must retain the 6.16 + * above copyright notice, this list of conditions and the following 6.17 + * disclaimer. 6.18 + * Redistributions in binary form must reproduce the above copyright 6.19 + * notice, this list of conditions and the following disclaimer in the 6.20 + * documentation and/or other materials provided with the distribution. 6.21 + * All advertising materials mentioning features or use of this software 6.22 + * must display the following acknowledgement: 6.23 + * This product includes software developed or owned by Caldera 6.24 + * International, Inc. 6.25 + * Neither the name of Caldera International, Inc. nor the names of 6.26 + * other contributors may be used to endorse or promote products 6.27 + * derived from this software without specific prior written permission. 6.28 + * 6.29 + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA 6.30 + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 6.31 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 6.32 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 6.33 + * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE 6.34 + * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR 6.35 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 6.36 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 6.37 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 6.38 + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 6.39 + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 6.40 + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 6.41 + */ 6.42 + 6.43 +#if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4 6.44 +#define REGEXP_H_USED __attribute__ ((used)) 6.45 +#elif defined __GNUC__ 6.46 +#define REGEXP_H_USED __attribute__ ((unused)) 6.47 +#else 6.48 +#define REGEXP_H_USED 6.49 +#endif 6.50 +static const char regexp_h_sccsid[] REGEXP_H_USED = 6.51 + "@(#)regexp.sl 1.56 (gritter) 5/29/05"; 6.52 + 6.53 +#if !defined (REGEXP_H_USED_FROM_VI) && !defined (__dietlibc__) 6.54 +#define REGEXP_H_WCHARS 6.55 +#endif 6.56 + 6.57 +#define CBRA 2 6.58 +#define CCHR 4 6.59 +#define CDOT 8 6.60 +#define CCL 12 6.61 +/* CLNUM 14 used in sed */ 6.62 +/* CEND 16 used in sed */ 6.63 +#define CDOL 20 6.64 +#define CCEOF 22 6.65 +#define CKET 24 6.66 +#define CBACK 36 6.67 +#define CNCL 40 6.68 +#define CBRC 44 6.69 +#define CLET 48 6.70 +#define CCH1 52 6.71 +#define CCH2 56 6.72 +#define CCH3 60 6.73 + 6.74 +#define STAR 01 6.75 +#define RNGE 03 6.76 +#define REGEXP_H_LEAST 0100 6.77 + 6.78 +#ifdef REGEXP_H_WCHARS 6.79 +#define CMB 0200 6.80 +#else /* !REGEXP_H_WCHARS */ 6.81 +#define CMB 0 6.82 +#endif /* !REGEXP_H_WCHARS */ 6.83 + 6.84 +#define NBRA 9 6.85 + 6.86 +#define PLACE(c) ep[c >> 3] |= bittab[c & 07] 6.87 +#define ISTHERE(c) (ep[c >> 3] & bittab[c & 07]) 6.88 + 6.89 +#ifdef REGEXP_H_WCHARS 6.90 +#define REGEXP_H_IS_THERE(ep, c) ((ep)[c >> 3] & bittab[c & 07]) 6.91 +#endif 6.92 + 6.93 +#include <ctype.h> 6.94 +#include <string.h> 6.95 +#include <limits.h> 6.96 +#ifdef REGEXP_H_WCHARS 6.97 +#include <stdlib.h> 6.98 +#include <wchar.h> 6.99 +#include <wctype.h> 6.100 +#endif /* REGEXP_H_WCHARS */ 6.101 + 6.102 +#define regexp_h_uletter(c) (isalpha(c) || (c) == '_') 6.103 +#ifdef REGEXP_H_WCHARS 6.104 +#define regexp_h_wuletter(c) (iswalpha(c) || (c) == L'_') 6.105 + 6.106 +/* 6.107 + * Used to allocate memory for the multibyte star algorithm. 6.108 + */ 6.109 +#ifndef regexp_h_malloc 6.110 +#define regexp_h_malloc(n) malloc(n) 6.111 +#endif 6.112 +#ifndef regexp_h_free 6.113 +#define regexp_h_free(p) free(p) 6.114 +#endif 6.115 + 6.116 +/* 6.117 + * Can be predefined to 'inline' to inline some multibyte functions; 6.118 + * may improve performance for files that contain many multibyte 6.119 + * sequences. 6.120 + */ 6.121 +#ifndef regexp_h_inline 6.122 +#define regexp_h_inline 6.123 +#endif 6.124 + 6.125 +/* 6.126 + * Mask to determine whether the first byte of a sequence possibly 6.127 + * starts a multibyte character. Set to 0377 to force mbtowc() for 6.128 + * any byte sequence (except 0). 6.129 + */ 6.130 +#ifndef REGEXP_H_MASK 6.131 +#define REGEXP_H_MASK 0200 6.132 +#endif 6.133 +#endif /* REGEXP_H_WCHARS */ 6.134 + 6.135 +/* 6.136 + * For regexpr.h. 6.137 + */ 6.138 +#ifndef regexp_h_static 6.139 +#define regexp_h_static 6.140 +#endif 6.141 +#ifndef REGEXP_H_STEP_INIT 6.142 +#define REGEXP_H_STEP_INIT 6.143 +#endif 6.144 +#ifndef REGEXP_H_ADVANCE_INIT 6.145 +#define REGEXP_H_ADVANCE_INIT 6.146 +#endif 6.147 + 6.148 +char *braslist[NBRA]; 6.149 +char *braelist[NBRA]; 6.150 +int nbra; 6.151 +char *loc1, *loc2, *locs; 6.152 +int sed; 6.153 +int nodelim; 6.154 + 6.155 +regexp_h_static int circf; 6.156 +regexp_h_static int low; 6.157 +regexp_h_static int size; 6.158 + 6.159 +regexp_h_static unsigned char bittab[] = { 6.160 + 1, 6.161 + 2, 6.162 + 4, 6.163 + 8, 6.164 + 16, 6.165 + 32, 6.166 + 64, 6.167 + 128 6.168 +}; 6.169 +static int regexp_h_advance(register const char *lp, 6.170 + register const char *ep); 6.171 +static void regexp_h_getrnge(register const char *str, int least); 6.172 + 6.173 +static const char *regexp_h_bol; /* beginning of input line (for \<) */ 6.174 + 6.175 +#ifdef REGEXP_H_WCHARS 6.176 +static int regexp_h_wchars; 6.177 +static int regexp_h_mbcurmax; 6.178 + 6.179 +static const char *regexp_h_firstwc; /* location of first 6.180 + multibyte character 6.181 + on input line */ 6.182 + 6.183 +#define regexp_h_getwc(c) { \ 6.184 + if (regexp_h_wchars) { \ 6.185 + char mbbuf[MB_LEN_MAX + 1], *mbptr; \ 6.186 + wchar_t wcbuf; \ 6.187 + int mb, len; \ 6.188 + mbptr = mbbuf; \ 6.189 + do { \ 6.190 + mb = GETC(); \ 6.191 + *mbptr++ = mb; \ 6.192 + *mbptr = '\0'; \ 6.193 + } while ((len = mbtowc(&wcbuf, mbbuf, regexp_h_mbcurmax)) < 0 \ 6.194 + && mb != eof && mbptr < mbbuf + MB_LEN_MAX); \ 6.195 + if (len == -1) \ 6.196 + ERROR(67); \ 6.197 + c = wcbuf; \ 6.198 + } else { \ 6.199 + c = GETC(); \ 6.200 + } \ 6.201 +} 6.202 + 6.203 +#define regexp_h_store(wc, mb, me) { \ 6.204 + int len; \ 6.205 + if (wc == WEOF) \ 6.206 + ERROR(67); \ 6.207 + if ((len = me - mb) <= regexp_h_mbcurmax) { \ 6.208 + char mt[MB_LEN_MAX]; \ 6.209 + if (wctomb(mt, wc) >= len) \ 6.210 + ERROR(50); \ 6.211 + } \ 6.212 + switch (len = wctomb(mb, wc)) { \ 6.213 + case -1: \ 6.214 + ERROR(67); \ 6.215 + case 0: \ 6.216 + mb++; \ 6.217 + break; \ 6.218 + default: \ 6.219 + mb += len; \ 6.220 + } \ 6.221 +} 6.222 + 6.223 +static regexp_h_inline wint_t 6.224 +regexp_h_fetchwc(const char **mb, int islp) 6.225 +{ 6.226 + wchar_t wc; 6.227 + int len; 6.228 + 6.229 + if ((len = mbtowc(&wc, *mb, regexp_h_mbcurmax)) < 0) { 6.230 + (*mb)++; 6.231 + return WEOF; 6.232 + } 6.233 + if (islp && regexp_h_firstwc == NULL) 6.234 + regexp_h_firstwc = *mb; 6.235 + /*if (len == 0) { 6.236 + (*mb)++; 6.237 + return L'\0'; 6.238 + } handled in singlebyte code */ 6.239 + *mb += len; 6.240 + return wc; 6.241 +} 6.242 + 6.243 +#define regexp_h_fetch(mb, islp) ((*(mb) & REGEXP_H_MASK) == 0 ? \ 6.244 + (*(mb)++&0377): \ 6.245 + regexp_h_fetchwc(&(mb), islp)) 6.246 + 6.247 +static regexp_h_inline wint_t 6.248 +regexp_h_showwc(const char *mb) 6.249 +{ 6.250 + wchar_t wc; 6.251 + 6.252 + if (mbtowc(&wc, mb, regexp_h_mbcurmax) < 0) 6.253 + return WEOF; 6.254 + return wc; 6.255 +} 6.256 + 6.257 +#define regexp_h_show(mb) ((*(mb) & REGEXP_H_MASK) == 0 ? (*(mb)&0377): \ 6.258 + regexp_h_showwc(mb)) 6.259 + 6.260 +/* 6.261 + * Return the character immediately preceding mb. Since no byte is 6.262 + * required to be the first byte of a character, the longest multibyte 6.263 + * character ending at &[mb-1] is searched. 6.264 + */ 6.265 +static regexp_h_inline wint_t 6.266 +regexp_h_previous(const char *mb) 6.267 +{ 6.268 + const char *p = mb; 6.269 + wchar_t wc, lastwc = WEOF; 6.270 + int len, max = 0; 6.271 + 6.272 + if (regexp_h_firstwc == NULL || mb <= regexp_h_firstwc) 6.273 + return (mb > regexp_h_bol ? (mb[-1] & 0377) : WEOF); 6.274 + while (p-- > regexp_h_bol) { 6.275 + mbtowc(NULL, NULL, 0); 6.276 + if ((len = mbtowc(&wc, p, mb - p)) >= 0) { 6.277 + if (len < max || len < mb - p) 6.278 + break; 6.279 + max = len; 6.280 + lastwc = wc; 6.281 + } else if (len < 0 && max > 0) 6.282 + break; 6.283 + } 6.284 + return lastwc; 6.285 +} 6.286 + 6.287 +#define regexp_h_cclass(set, c, af) \ 6.288 + ((c) == 0 || (c) == WEOF ? 0 : ( \ 6.289 + ((c) > 0177) ? \ 6.290 + regexp_h_cclass_wc(set, c, af) : ( \ 6.291 + REGEXP_H_IS_THERE((set)+1, (c)) ? (af) : !(af) \ 6.292 + ) \ 6.293 + ) \ 6.294 + ) 6.295 + 6.296 +static regexp_h_inline int 6.297 +regexp_h_cclass_wc(const char *set, register wint_t c, int af) 6.298 +{ 6.299 + register wint_t wc, wl = WEOF; 6.300 + const char *end; 6.301 + 6.302 + end = &set[18] + set[0] - 1; 6.303 + set += 17; 6.304 + while (set < end) { 6.305 + wc = regexp_h_fetch(set, 0); 6.306 +#ifdef REGEXP_H_VI_BACKSLASH 6.307 + if (wc == '\\' && set < end && 6.308 + (*set == ']' || *set == '-' || 6.309 + *set == '^' || *set == '\\')) { 6.310 + wc = regexp_h_fetch(set, 0); 6.311 + } else 6.312 +#endif /* REGEXP_H_VI_BACKSLASH */ 6.313 + if (wc == '-' && wl != WEOF && set < end) { 6.314 + wc = regexp_h_fetch(set, 0); 6.315 +#ifdef REGEXP_H_VI_BACKSLASH 6.316 + if (wc == '\\' && set < end && 6.317 + (*set == ']' || *set == '-' || 6.318 + *set == '^' || *set == '\\')) { 6.319 + wc = regexp_h_fetch(set, 0); 6.320 + } 6.321 +#endif /* REGEXP_H_VI_BACKSLASH */ 6.322 + if (c > wl && c < wc) 6.323 + return af; 6.324 + } 6.325 + if (c == wc) 6.326 + return af; 6.327 + wl = wc; 6.328 + } 6.329 + return !af; 6.330 +} 6.331 +#else /* !REGEXP_H_WCHARS */ 6.332 +#define regexp_h_wchars 0 6.333 +#define regexp_h_getwc(c) { c = GETC(); } 6.334 +#endif /* !REGEXP_H_WCHARS */ 6.335 + 6.336 +regexp_h_static char * 6.337 +compile(char *instring, char *ep, const char *endbuf, int seof) 6.338 +{ 6.339 + INIT /* Dependent declarations and initializations */ 6.340 + register int c; 6.341 + register int eof = seof; 6.342 + char *lastep = instring; 6.343 + int cclcnt; 6.344 + char bracket[NBRA], *bracketp; 6.345 + int closed; 6.346 + char neg; 6.347 + int lc; 6.348 + int i, cflg; 6.349 + 6.350 +#ifdef REGEXP_H_WCHARS 6.351 + char *eq; 6.352 + regexp_h_mbcurmax = MB_CUR_MAX; 6.353 + regexp_h_wchars = regexp_h_mbcurmax > 1 ? CMB : 0; 6.354 +#endif 6.355 + lastep = 0; 6.356 + bracketp = bracket; 6.357 + if((c = GETC()) == eof || c == '\n') { 6.358 + if (c == '\n') { 6.359 + UNGETC(c); 6.360 + nodelim = 1; 6.361 + } 6.362 + if(*ep == 0 && !sed) 6.363 + ERROR(41); 6.364 + if (bracketp > bracket) 6.365 + ERROR(42); 6.366 + RETURN(ep); 6.367 + } 6.368 + circf = closed = nbra = 0; 6.369 + if (c == '^') 6.370 + circf++; 6.371 + else 6.372 + UNGETC(c); 6.373 + for (;;) { 6.374 + if (ep >= endbuf) 6.375 + ERROR(50); 6.376 + regexp_h_getwc(c); 6.377 + if(c != '*' && ((c != '\\') || (PEEKC() != '{'))) 6.378 + lastep = ep; 6.379 + if (c == eof) { 6.380 + *ep++ = CCEOF; 6.381 + if (bracketp > bracket) 6.382 + ERROR(42); 6.383 + RETURN(ep); 6.384 + } 6.385 + switch (c) { 6.386 + 6.387 + case '.': 6.388 + *ep++ = CDOT|regexp_h_wchars; 6.389 + continue; 6.390 + 6.391 + case '\n': 6.392 + if (sed == 0) { 6.393 + UNGETC(c); 6.394 + *ep++ = CCEOF; 6.395 + nodelim = 1; 6.396 + RETURN(ep); 6.397 + } 6.398 + ERROR(36); 6.399 + case '*': 6.400 + if (lastep==0 || *lastep==CBRA || *lastep==CKET || 6.401 + *lastep==(CBRC|regexp_h_wchars) || 6.402 + *lastep==(CLET|regexp_h_wchars)) 6.403 + goto defchar; 6.404 + *lastep |= STAR; 6.405 + continue; 6.406 + 6.407 + case '$': 6.408 + if(PEEKC() != eof) 6.409 + goto defchar; 6.410 + *ep++ = CDOL; 6.411 + continue; 6.412 + 6.413 + case '[': 6.414 +#ifdef REGEXP_H_WCHARS 6.415 + if (regexp_h_wchars == 0) { 6.416 +#endif 6.417 + if(&ep[33] >= endbuf) 6.418 + ERROR(50); 6.419 + 6.420 + *ep++ = CCL; 6.421 + lc = 0; 6.422 + for(i = 0; i < 32; i++) 6.423 + ep[i] = 0; 6.424 + 6.425 + neg = 0; 6.426 + if((c = GETC()) == '^') { 6.427 + neg = 1; 6.428 + c = GETC(); 6.429 + } 6.430 + 6.431 + do { 6.432 + c &= 0377; 6.433 + if(c == '\0' || c == '\n') 6.434 + ERROR(49); 6.435 +#ifdef REGEXP_H_VI_BACKSLASH 6.436 + if(c == '\\' && ((c = PEEKC()) == ']' || 6.437 + c == '-' || c == '^' || 6.438 + c == '\\')) { 6.439 + c = GETC(); 6.440 + c &= 0377; 6.441 + } else 6.442 +#endif /* REGEXP_H_VI_BACKSLASH */ 6.443 + if(c == '-' && lc != 0) { 6.444 + if ((c = GETC()) == ']') { 6.445 + PLACE('-'); 6.446 + break; 6.447 + } 6.448 +#ifdef REGEXP_H_VI_BACKSLASH 6.449 + if(c == '\\' && 6.450 + ((c = PEEKC()) == ']' || 6.451 + c == '-' || 6.452 + c == '^' || 6.453 + c == '\\')) 6.454 + c = GETC(); 6.455 +#endif /* REGEXP_H_VI_BACKSLASH */ 6.456 + c &= 0377; 6.457 + while(lc < c) { 6.458 + PLACE(lc); 6.459 + lc++; 6.460 + } 6.461 + } 6.462 + lc = c; 6.463 + PLACE(c); 6.464 + } while((c = GETC()) != ']'); 6.465 + if(neg) { 6.466 + for(cclcnt = 0; cclcnt < 32; cclcnt++) 6.467 + ep[cclcnt] ^= 0377; 6.468 + ep[0] &= 0376; 6.469 + } 6.470 + 6.471 + ep += 32; 6.472 +#ifdef REGEXP_H_WCHARS 6.473 + } else { 6.474 + if (&ep[18] >= endbuf) 6.475 + ERROR(50); 6.476 + *ep++ = CCL|CMB; 6.477 + *ep++ = 0; 6.478 + lc = 0; 6.479 + for (i = 0; i < 16; i++) 6.480 + ep[i] = 0; 6.481 + eq = &ep[16]; 6.482 + regexp_h_getwc(c); 6.483 + if (c == L'^') { 6.484 + regexp_h_getwc(c); 6.485 + ep[-2] = CNCL|CMB; 6.486 + } 6.487 + do { 6.488 + if (c == '\0' || c == '\n') 6.489 + ERROR(49); 6.490 +#ifdef REGEXP_H_VI_BACKSLASH 6.491 + if(c == '\\' && ((c = PEEKC()) == ']' || 6.492 + c == '-' || c == '^' || 6.493 + c == '\\')) { 6.494 + regexp_h_store(c, eq, endbuf); 6.495 + regexp_h_getwc(c); 6.496 + } else 6.497 +#endif /* REGEXP_H_VI_BACKSLASH */ 6.498 + if (c == '-' && lc != 0 && lc <= 0177) { 6.499 + regexp_h_store(c, eq, endbuf); 6.500 + regexp_h_getwc(c); 6.501 + if (c == ']') { 6.502 + PLACE('-'); 6.503 + break; 6.504 + } 6.505 +#ifdef REGEXP_H_VI_BACKSLASH 6.506 + if(c == '\\' && 6.507 + ((c = PEEKC()) == ']' || 6.508 + c == '-' || 6.509 + c == '^' || 6.510 + c == '\\')) { 6.511 + regexp_h_store(c, eq, 6.512 + endbuf); 6.513 + regexp_h_getwc(c); 6.514 + } 6.515 +#endif /* REGEXP_H_VI_BACKSLASH */ 6.516 + while (lc < (c & 0177)) { 6.517 + PLACE(lc); 6.518 + lc++; 6.519 + } 6.520 + } 6.521 + lc = c; 6.522 + if (c <= 0177) 6.523 + PLACE(c); 6.524 + regexp_h_store(c, eq, endbuf); 6.525 + regexp_h_getwc(c); 6.526 + } while (c != L']'); 6.527 + if ((i = eq - &ep[16]) > 255) 6.528 + ERROR(50); 6.529 + lastep[1] = i; 6.530 + ep = eq; 6.531 + } 6.532 +#endif /* REGEXP_H_WCHARS */ 6.533 + 6.534 + continue; 6.535 + 6.536 + case '\\': 6.537 + regexp_h_getwc(c); 6.538 + switch(c) { 6.539 + 6.540 + case '(': 6.541 + if(nbra >= NBRA) 6.542 + ERROR(43); 6.543 + *bracketp++ = nbra; 6.544 + *ep++ = CBRA; 6.545 + *ep++ = nbra++; 6.546 + continue; 6.547 + 6.548 + case ')': 6.549 + if(bracketp <= bracket) 6.550 + ERROR(42); 6.551 + *ep++ = CKET; 6.552 + *ep++ = *--bracketp; 6.553 + closed++; 6.554 + continue; 6.555 + 6.556 + case '<': 6.557 + *ep++ = CBRC|regexp_h_wchars; 6.558 + continue; 6.559 + 6.560 + case '>': 6.561 + *ep++ = CLET|regexp_h_wchars; 6.562 + continue; 6.563 + 6.564 + case '{': 6.565 + if(lastep == (char *) (0)) 6.566 + goto defchar; 6.567 + *lastep |= RNGE; 6.568 + cflg = 0; 6.569 + nlim: 6.570 + c = GETC(); 6.571 + i = 0; 6.572 + do { 6.573 + if ('0' <= c && c <= '9') 6.574 + i = 10 * i + c - '0'; 6.575 + else 6.576 + ERROR(16); 6.577 + } while(((c = GETC()) != '\\') && (c != ',')); 6.578 + if (i > 255) 6.579 + ERROR(11); 6.580 + *ep++ = i; 6.581 + if (c == ',') { 6.582 + if(cflg++) 6.583 + ERROR(44); 6.584 + if((c = GETC()) == '\\') { 6.585 + *ep++ = (char)255; 6.586 + *lastep |= REGEXP_H_LEAST; 6.587 + } else { 6.588 + UNGETC(c); 6.589 + goto nlim; /* get 2'nd number */ 6.590 + } 6.591 + } 6.592 + if(GETC() != '}') 6.593 + ERROR(45); 6.594 + if(!cflg) /* one number */ 6.595 + *ep++ = i; 6.596 + else if((ep[-1] & 0377) < (ep[-2] & 0377)) 6.597 + ERROR(46); 6.598 + continue; 6.599 + 6.600 + case '\n': 6.601 + ERROR(36); 6.602 + 6.603 + case 'n': 6.604 + c = '\n'; 6.605 + goto defchar; 6.606 + 6.607 + default: 6.608 + if(c >= '1' && c <= '9') { 6.609 + if((c -= '1') >= closed) 6.610 + ERROR(25); 6.611 + *ep++ = CBACK; 6.612 + *ep++ = c; 6.613 + continue; 6.614 + } 6.615 + } 6.616 + /* Drop through to default to use \ to turn off special chars */ 6.617 + 6.618 + defchar: 6.619 + default: 6.620 + lastep = ep; 6.621 +#ifdef REGEXP_H_WCHARS 6.622 + if (regexp_h_wchars == 0) { 6.623 +#endif 6.624 + *ep++ = CCHR; 6.625 + *ep++ = c; 6.626 +#ifdef REGEXP_H_WCHARS 6.627 + } else { 6.628 + char mbbuf[MB_LEN_MAX]; 6.629 + 6.630 + switch (wctomb(mbbuf, c)) { 6.631 + case 1: *ep++ = CCH1; 6.632 + break; 6.633 + case 2: *ep++ = CCH2; 6.634 + break; 6.635 + case 3: *ep++ = CCH3; 6.636 + break; 6.637 + default: 6.638 + *ep++ = CCHR|CMB; 6.639 + } 6.640 + regexp_h_store(c, ep, endbuf); 6.641 + } 6.642 +#endif /* REGEXP_H_WCHARS */ 6.643 + } 6.644 + } 6.645 +} 6.646 + 6.647 +int 6.648 +step(const char *p1, const char *p2) 6.649 +{ 6.650 + register int c; 6.651 +#ifdef REGEXP_H_WCHARS 6.652 + register int d; 6.653 +#endif /* REGEXP_H_WCHARS */ 6.654 + 6.655 + REGEXP_H_STEP_INIT /* get circf */ 6.656 + regexp_h_bol = p1; 6.657 +#ifdef REGEXP_H_WCHARS 6.658 + regexp_h_firstwc = NULL; 6.659 +#endif /* REGEXP_H_WCHARS */ 6.660 + if (circf) { 6.661 + loc1 = (char *)p1; 6.662 + return(regexp_h_advance(p1, p2)); 6.663 + } 6.664 + /* fast check for first character */ 6.665 + if (*p2==CCHR) { 6.666 + c = p2[1] & 0377; 6.667 + do { 6.668 + if ((*p1 & 0377) != c) 6.669 + continue; 6.670 + if (regexp_h_advance(p1, p2)) { 6.671 + loc1 = (char *)p1; 6.672 + return(1); 6.673 + } 6.674 + } while (*p1++); 6.675 + return(0); 6.676 + } 6.677 +#ifdef REGEXP_H_WCHARS 6.678 + else if (*p2==CCH1) { 6.679 + do { 6.680 + if (p1[0] == p2[1] && regexp_h_advance(p1, p2)) { 6.681 + loc1 = (char *)p1; 6.682 + return(1); 6.683 + } 6.684 + c = regexp_h_fetch(p1, 1); 6.685 + } while (c); 6.686 + return(0); 6.687 + } else if (*p2==CCH2) { 6.688 + do { 6.689 + if (p1[0] == p2[1] && p1[1] == p2[2] && 6.690 + regexp_h_advance(p1, p2)) { 6.691 + loc1 = (char *)p1; 6.692 + return(1); 6.693 + } 6.694 + c = regexp_h_fetch(p1, 1); 6.695 + } while (c); 6.696 + return(0); 6.697 + } else if (*p2==CCH3) { 6.698 + do { 6.699 + if (p1[0] == p2[1] && p1[1] == p2[2] && p1[2] == p2[3]&& 6.700 + regexp_h_advance(p1, p2)) { 6.701 + loc1 = (char *)p1; 6.702 + return(1); 6.703 + } 6.704 + c = regexp_h_fetch(p1, 1); 6.705 + } while (c); 6.706 + return(0); 6.707 + } else if ((*p2&0377)==(CCHR|CMB)) { 6.708 + d = regexp_h_fetch(p2, 0); 6.709 + do { 6.710 + c = regexp_h_fetch(p1, 1); 6.711 + if (c == d && regexp_h_advance(p1, p2)) { 6.712 + loc1 = (char *)p1; 6.713 + return(1); 6.714 + } 6.715 + } while(c); 6.716 + return(0); 6.717 + } 6.718 + /* regular algorithm */ 6.719 + if (regexp_h_wchars) 6.720 + do { 6.721 + if (regexp_h_advance(p1, p2)) { 6.722 + loc1 = (char *)p1; 6.723 + return(1); 6.724 + } 6.725 + c = regexp_h_fetch(p1, 1); 6.726 + } while (c); 6.727 + else 6.728 +#endif /* REGEXP_H_WCHARS */ 6.729 + do { 6.730 + if (regexp_h_advance(p1, p2)) { 6.731 + loc1 = (char *)p1; 6.732 + return(1); 6.733 + } 6.734 + } while (*p1++); 6.735 + return(0); 6.736 +} 6.737 + 6.738 +#ifdef REGEXP_H_WCHARS 6.739 +/* 6.740 + * It is painfully slow to read character-wise backwards in a 6.741 + * multibyte string (see regexp_h_previous() above). For the star 6.742 + * algorithm, we therefore keep track of every character as it is 6.743 + * read in forward direction. 6.744 + * 6.745 + * Don't use alloca() for stack blocks since there is no measurable 6.746 + * speedup and huge amounts of memory are used up for long input 6.747 + * lines. 6.748 + */ 6.749 +#ifndef REGEXP_H_STAKBLOK 6.750 +#define REGEXP_H_STAKBLOK 1000 6.751 +#endif 6.752 + 6.753 +struct regexp_h_stack { 6.754 + struct regexp_h_stack *s_nxt; 6.755 + struct regexp_h_stack *s_prv; 6.756 + const char *s_ptr[REGEXP_H_STAKBLOK]; 6.757 +}; 6.758 + 6.759 +#define regexp_h_push(sb, sp, sc, lp) (regexp_h_wchars ? \ 6.760 + regexp_h_pushwc(sb, sp, sc, lp) : (void)0) 6.761 + 6.762 +static regexp_h_inline void 6.763 +regexp_h_pushwc(struct regexp_h_stack **sb, 6.764 + struct regexp_h_stack **sp, 6.765 + const char ***sc, const char *lp) 6.766 +{ 6.767 + if (regexp_h_firstwc == NULL || lp < regexp_h_firstwc) 6.768 + return; 6.769 + if (*sb == NULL) { 6.770 + if ((*sb = regexp_h_malloc(sizeof **sb)) == NULL) 6.771 + return; 6.772 + (*sb)->s_nxt = (*sb)->s_prv = NULL; 6.773 + *sp = *sb; 6.774 + *sc = &(*sb)->s_ptr[0]; 6.775 + } else if (*sc >= &(*sp)->s_ptr[REGEXP_H_STAKBLOK]) { 6.776 + if ((*sp)->s_nxt == NULL) { 6.777 + struct regexp_h_stack *bq; 6.778 + 6.779 + if ((bq = regexp_h_malloc(sizeof *bq)) == NULL) 6.780 + return; 6.781 + bq->s_nxt = NULL; 6.782 + bq->s_prv = *sp; 6.783 + (*sp)->s_nxt = bq; 6.784 + *sp = bq; 6.785 + } else 6.786 + *sp = (*sp)->s_nxt; 6.787 + *sc = &(*sp)->s_ptr[0]; 6.788 + } 6.789 + *(*sc)++ = lp; 6.790 +} 6.791 + 6.792 +static regexp_h_inline const char * 6.793 +regexp_h_pop(struct regexp_h_stack **sb, struct regexp_h_stack **sp, 6.794 + const char ***sc, const char *lp) 6.795 +{ 6.796 + if (regexp_h_firstwc == NULL || lp <= regexp_h_firstwc) 6.797 + return &lp[-1]; 6.798 + if (*sp == NULL) 6.799 + return regexp_h_firstwc; 6.800 + if (*sc == &(*sp)->s_ptr[0]) { 6.801 + if ((*sp)->s_prv == NULL) { 6.802 + regexp_h_free(*sp); 6.803 + *sp = NULL; 6.804 + *sb = NULL; 6.805 + return regexp_h_firstwc; 6.806 + } 6.807 + *sp = (*sp)->s_prv; 6.808 + regexp_h_free((*sp)->s_nxt); 6.809 + (*sp)->s_nxt = NULL ; 6.810 + *sc = &(*sp)->s_ptr[REGEXP_H_STAKBLOK]; 6.811 + } 6.812 + return *(--(*sc)); 6.813 +} 6.814 + 6.815 +static void 6.816 +regexp_h_zerostak(struct regexp_h_stack **sb, struct regexp_h_stack **sp) 6.817 +{ 6.818 + for (*sp = *sb; *sp && (*sp)->s_nxt; *sp = (*sp)->s_nxt) 6.819 + if ((*sp)->s_prv) 6.820 + regexp_h_free((*sp)->s_prv); 6.821 + if (*sp) { 6.822 + if ((*sp)->s_prv) 6.823 + regexp_h_free((*sp)->s_prv); 6.824 + regexp_h_free(*sp); 6.825 + } 6.826 + *sp = *sb = NULL; 6.827 +} 6.828 +#else /* !REGEXP_H_WCHARS */ 6.829 +#define regexp_h_push(sb, sp, sc, lp) 6.830 +#endif /* !REGEXP_H_WCHARS */ 6.831 + 6.832 +static int 6.833 +regexp_h_advance(const char *lp, const char *ep) 6.834 +{ 6.835 + register const char *curlp; 6.836 + int c, least; 6.837 +#ifdef REGEXP_H_WCHARS 6.838 + int d; 6.839 + struct regexp_h_stack *sb = NULL, *sp = NULL; 6.840 + const char **sc; 6.841 +#endif /* REGEXP_H_WCHARS */ 6.842 + char *bbeg; 6.843 + int ct; 6.844 + 6.845 + for (;;) switch (least = *ep++ & 0377, least & ~REGEXP_H_LEAST) { 6.846 + 6.847 + case CCHR: 6.848 +#ifdef REGEXP_H_WCHARS 6.849 + case CCH1: 6.850 +#endif 6.851 + if (*ep++ == *lp++) 6.852 + continue; 6.853 + return(0); 6.854 + 6.855 +#ifdef REGEXP_H_WCHARS 6.856 + case CCHR|CMB: 6.857 + if (regexp_h_fetch(ep, 0) == regexp_h_fetch(lp, 1)) 6.858 + continue; 6.859 + return(0); 6.860 + 6.861 + case CCH2: 6.862 + if (ep[0] == lp[0] && ep[1] == lp[1]) { 6.863 + ep += 2, lp += 2; 6.864 + continue; 6.865 + } 6.866 + return(0); 6.867 + 6.868 + case CCH3: 6.869 + if (ep[0] == lp[0] && ep[1] == lp[1] && ep[2] == lp[2]) { 6.870 + ep += 3, lp += 3; 6.871 + continue; 6.872 + } 6.873 + return(0); 6.874 +#endif /* REGEXP_H_WCHARS */ 6.875 + 6.876 + case CDOT: 6.877 + if (*lp++) 6.878 + continue; 6.879 + return(0); 6.880 +#ifdef REGEXP_H_WCHARS 6.881 + case CDOT|CMB: 6.882 + if ((c = regexp_h_fetch(lp, 1)) != L'\0' && c != WEOF) 6.883 + continue; 6.884 + return(0); 6.885 +#endif /* REGEXP_H_WCHARS */ 6.886 + 6.887 + case CDOL: 6.888 + if (*lp==0) 6.889 + continue; 6.890 + return(0); 6.891 + 6.892 + case CCEOF: 6.893 + loc2 = (char *)lp; 6.894 + return(1); 6.895 + 6.896 + case CCL: 6.897 + c = *lp++ & 0377; 6.898 + if(ISTHERE(c)) { 6.899 + ep += 32; 6.900 + continue; 6.901 + } 6.902 + return(0); 6.903 + 6.904 +#ifdef REGEXP_H_WCHARS 6.905 + case CCL|CMB: 6.906 + case CNCL|CMB: 6.907 + c = regexp_h_fetch(lp, 1); 6.908 + if (regexp_h_cclass(ep, c, (ep[-1] & 0377) == (CCL|CMB))) { 6.909 + ep += (*ep & 0377) + 17; 6.910 + continue; 6.911 + } 6.912 + return 0; 6.913 +#endif /* REGEXP_H_WCHARS */ 6.914 + 6.915 + case CBRA: 6.916 + braslist[*ep++ & 0377] = (char *)lp; 6.917 + continue; 6.918 + 6.919 + case CKET: 6.920 + braelist[*ep++ & 0377] = (char *)lp; 6.921 + continue; 6.922 + 6.923 + case CBRC: 6.924 + if (lp == regexp_h_bol && locs == NULL) 6.925 + continue; 6.926 + if ((isdigit(lp[0] & 0377) || regexp_h_uletter(lp[0] & 0377)) 6.927 + && !regexp_h_uletter(lp[-1] & 0377) 6.928 + && !isdigit(lp[-1] & 0377)) 6.929 + continue; 6.930 + return(0); 6.931 + 6.932 +#ifdef REGEXP_H_WCHARS 6.933 + case CBRC|CMB: 6.934 + c = regexp_h_show(lp); 6.935 + d = regexp_h_previous(lp); 6.936 + if ((iswdigit(c) || regexp_h_wuletter(c)) 6.937 + && !regexp_h_wuletter(d) 6.938 + && !iswdigit(d)) 6.939 + continue; 6.940 + return(0); 6.941 +#endif /* REGEXP_H_WCHARS */ 6.942 + 6.943 + case CLET: 6.944 + if (!regexp_h_uletter(lp[0] & 0377) && !isdigit(lp[0] & 0377)) 6.945 + continue; 6.946 + return(0); 6.947 + 6.948 +#ifdef REGEXP_H_WCHARS 6.949 + case CLET|CMB: 6.950 + c = regexp_h_show(lp); 6.951 + if (!regexp_h_wuletter(c) && !iswdigit(c)) 6.952 + continue; 6.953 + return(0); 6.954 +#endif /* REGEXP_H_WCHARS */ 6.955 + 6.956 + case CCHR|RNGE: 6.957 + c = *ep++; 6.958 + regexp_h_getrnge(ep, least); 6.959 + while(low--) 6.960 + if(*lp++ != c) 6.961 + return(0); 6.962 + curlp = lp; 6.963 + while(size--) { 6.964 + regexp_h_push(&sb, &sp, &sc, lp); 6.965 + if(*lp++ != c) 6.966 + break; 6.967 + } 6.968 + if(size < 0) { 6.969 + regexp_h_push(&sb, &sp, &sc, lp); 6.970 + lp++; 6.971 + } 6.972 + ep += 2; 6.973 + goto star; 6.974 + 6.975 +#ifdef REGEXP_H_WCHARS 6.976 + case CCHR|RNGE|CMB: 6.977 + case CCH1|RNGE: 6.978 + case CCH2|RNGE: 6.979 + case CCH3|RNGE: 6.980 + c = regexp_h_fetch(ep, 0); 6.981 + regexp_h_getrnge(ep, least); 6.982 + while (low--) 6.983 + if (regexp_h_fetch(lp, 1) != c) 6.984 + return 0; 6.985 + curlp = lp; 6.986 + while (size--) { 6.987 + regexp_h_push(&sb, &sp, &sc, lp); 6.988 + if (regexp_h_fetch(lp, 1) != c) 6.989 + break; 6.990 + } 6.991 + if(size < 0) { 6.992 + regexp_h_push(&sb, &sp, &sc, lp); 6.993 + regexp_h_fetch(lp, 1); 6.994 + } 6.995 + ep += 2; 6.996 + goto star; 6.997 +#endif /* REGEXP_H_WCHARS */ 6.998 + 6.999 + case CDOT|RNGE: 6.1000 + regexp_h_getrnge(ep, least); 6.1001 + while(low--) 6.1002 + if(*lp++ == '\0') 6.1003 + return(0); 6.1004 + curlp = lp; 6.1005 + while(size--) { 6.1006 + regexp_h_push(&sb, &sp, &sc, lp); 6.1007 + if(*lp++ == '\0') 6.1008 + break; 6.1009 + } 6.1010 + if(size < 0) { 6.1011 + regexp_h_push(&sb, &sp, &sc, lp); 6.1012 + lp++; 6.1013 + } 6.1014 + ep += 2; 6.1015 + goto star; 6.1016 + 6.1017 +#ifdef REGEXP_H_WCHARS 6.1018 + case CDOT|RNGE|CMB: 6.1019 + regexp_h_getrnge(ep, least); 6.1020 + while (low--) 6.1021 + if ((c = regexp_h_fetch(lp, 1)) == L'\0' || c == WEOF) 6.1022 + return 0; 6.1023 + curlp = lp; 6.1024 + while (size--) { 6.1025 + regexp_h_push(&sb, &sp, &sc, lp); 6.1026 + if ((c = regexp_h_fetch(lp, 1)) == L'\0' || c == WEOF) 6.1027 + break; 6.1028 + } 6.1029 + if (size < 0) { 6.1030 + regexp_h_push(&sb, &sp, &sc, lp); 6.1031 + regexp_h_fetch(lp, 1); 6.1032 + } 6.1033 + ep += 2; 6.1034 + goto star; 6.1035 +#endif /* REGEXP_H_WCHARS */ 6.1036 + 6.1037 + case CCL|RNGE: 6.1038 + regexp_h_getrnge(ep + 32, least); 6.1039 + while(low--) { 6.1040 + c = *lp++ & 0377; 6.1041 + if(!ISTHERE(c)) 6.1042 + return(0); 6.1043 + } 6.1044 + curlp = lp; 6.1045 + while(size--) { 6.1046 + regexp_h_push(&sb, &sp, &sc, lp); 6.1047 + c = *lp++ & 0377; 6.1048 + if(!ISTHERE(c)) 6.1049 + break; 6.1050 + } 6.1051 + if(size < 0) { 6.1052 + regexp_h_push(&sb, &sp, &sc, lp); 6.1053 + lp++; 6.1054 + } 6.1055 + ep += 34; /* 32 + 2 */ 6.1056 + goto star; 6.1057 + 6.1058 +#ifdef REGEXP_H_WCHARS 6.1059 + case CCL|RNGE|CMB: 6.1060 + case CNCL|RNGE|CMB: 6.1061 + regexp_h_getrnge(ep + (*ep & 0377) + 17, least); 6.1062 + while (low--) { 6.1063 + c = regexp_h_fetch(lp, 1); 6.1064 + if (!regexp_h_cclass(ep, c, 6.1065 + (ep[-1] & 0377 & ~REGEXP_H_LEAST) 6.1066 + == (CCL|RNGE|CMB))) 6.1067 + return 0; 6.1068 + } 6.1069 + curlp = lp; 6.1070 + while (size--) { 6.1071 + regexp_h_push(&sb, &sp, &sc, lp); 6.1072 + c = regexp_h_fetch(lp, 1); 6.1073 + if (!regexp_h_cclass(ep, c, 6.1074 + (ep[-1] & 0377 & ~REGEXP_H_LEAST) 6.1075 + == (CCL|RNGE|CMB))) 6.1076 + break; 6.1077 + } 6.1078 + if (size < 0) { 6.1079 + regexp_h_push(&sb, &sp, &sc, lp); 6.1080 + regexp_h_fetch(lp, 1); 6.1081 + } 6.1082 + ep += (*ep & 0377) + 19; 6.1083 + goto star; 6.1084 +#endif /* REGEXP_H_WCHARS */ 6.1085 + 6.1086 + case CBACK: 6.1087 + bbeg = braslist[*ep & 0377]; 6.1088 + ct = braelist[*ep++ & 0377] - bbeg; 6.1089 + 6.1090 + if(strncmp(bbeg, lp, ct) == 0) { 6.1091 + lp += ct; 6.1092 + continue; 6.1093 + } 6.1094 + return(0); 6.1095 + 6.1096 + case CBACK|STAR: 6.1097 + bbeg = braslist[*ep & 0377]; 6.1098 + ct = braelist[*ep++ & 0377] - bbeg; 6.1099 + curlp = lp; 6.1100 + while(strncmp(bbeg, lp, ct) == 0) 6.1101 + lp += ct; 6.1102 + 6.1103 + while(lp >= curlp) { 6.1104 + if(regexp_h_advance(lp, ep)) return(1); 6.1105 + lp -= ct; 6.1106 + } 6.1107 + return(0); 6.1108 + 6.1109 + 6.1110 + case CDOT|STAR: 6.1111 + curlp = lp; 6.1112 + do 6.1113 + regexp_h_push(&sb, &sp, &sc, lp); 6.1114 + while (*lp++); 6.1115 + goto star; 6.1116 + 6.1117 +#ifdef REGEXP_H_WCHARS 6.1118 + case CDOT|STAR|CMB: 6.1119 + curlp = lp; 6.1120 + do 6.1121 + regexp_h_push(&sb, &sp, &sc, lp); 6.1122 + while ((c = regexp_h_fetch(lp, 1)) != L'\0' && c != WEOF); 6.1123 + goto star; 6.1124 +#endif /* REGEXP_H_WCHARS */ 6.1125 + 6.1126 + case CCHR|STAR: 6.1127 + curlp = lp; 6.1128 + do 6.1129 + regexp_h_push(&sb, &sp, &sc, lp); 6.1130 + while (*lp++ == *ep); 6.1131 + ep++; 6.1132 + goto star; 6.1133 + 6.1134 +#ifdef REGEXP_H_WCHARS 6.1135 + case CCHR|STAR|CMB: 6.1136 + case CCH1|STAR: 6.1137 + case CCH2|STAR: 6.1138 + case CCH3|STAR: 6.1139 + curlp = lp; 6.1140 + d = regexp_h_fetch(ep, 0); 6.1141 + do 6.1142 + regexp_h_push(&sb, &sp, &sc, lp); 6.1143 + while (regexp_h_fetch(lp, 1) == d); 6.1144 + goto star; 6.1145 +#endif /* REGEXP_H_WCHARS */ 6.1146 + 6.1147 + case CCL|STAR: 6.1148 + curlp = lp; 6.1149 + do { 6.1150 + regexp_h_push(&sb, &sp, &sc, lp); 6.1151 + c = *lp++ & 0377; 6.1152 + } while(ISTHERE(c)); 6.1153 + ep += 32; 6.1154 + goto star; 6.1155 + 6.1156 +#ifdef REGEXP_H_WCHARS 6.1157 + case CCL|STAR|CMB: 6.1158 + case CNCL|STAR|CMB: 6.1159 + curlp = lp; 6.1160 + do { 6.1161 + regexp_h_push(&sb, &sp, &sc, lp); 6.1162 + c = regexp_h_fetch(lp, 1); 6.1163 + } while (regexp_h_cclass(ep, c, (ep[-1] & 0377) 6.1164 + == (CCL|STAR|CMB))); 6.1165 + ep += (*ep & 0377) + 17; 6.1166 + goto star; 6.1167 +#endif /* REGEXP_H_WCHARS */ 6.1168 + 6.1169 + star: 6.1170 +#ifdef REGEXP_H_WCHARS 6.1171 + if (regexp_h_wchars == 0) { 6.1172 +#endif 6.1173 + do { 6.1174 + if(--lp == locs) 6.1175 + break; 6.1176 + if (regexp_h_advance(lp, ep)) 6.1177 + return(1); 6.1178 + } while (lp > curlp); 6.1179 +#ifdef REGEXP_H_WCHARS 6.1180 + } else { 6.1181 + do { 6.1182 + lp = regexp_h_pop(&sb, &sp, &sc, lp); 6.1183 + if (lp <= locs) 6.1184 + break; 6.1185 + if (regexp_h_advance(lp, ep)) { 6.1186 + regexp_h_zerostak(&sb, &sp); 6.1187 + return(1); 6.1188 + } 6.1189 + } while (lp > curlp); 6.1190 + regexp_h_zerostak(&sb, &sp); 6.1191 + } 6.1192 +#endif /* REGEXP_H_WCHARS */ 6.1193 + return(0); 6.1194 + 6.1195 + } 6.1196 +} 6.1197 + 6.1198 +static void 6.1199 +regexp_h_getrnge(register const char *str, int least) 6.1200 +{ 6.1201 + low = *str++ & 0377; 6.1202 + size = least & REGEXP_H_LEAST ? /*20000*/INT_MAX : (*str & 0377) - low; 6.1203 +} 6.1204 + 6.1205 +int 6.1206 +advance(const char *lp, const char *ep) 6.1207 +{ 6.1208 + REGEXP_H_ADVANCE_INIT /* skip past circf */ 6.1209 + regexp_h_bol = lp; 6.1210 +#ifdef REGEXP_H_WCHARS 6.1211 + regexp_h_firstwc = NULL; 6.1212 +#endif /* REGEXP_H_WCHARS */ 6.1213 + return regexp_h_advance(lp, ep); 6.1214 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/regexpr.c Mon Sep 05 16:31:35 2011 +0200 7.3 @@ -0,0 +1,90 @@ 7.4 +/* 7.5 + * Simple Regular Expression functions. Derived from Unix 7th Edition, 7.6 + * /usr/src/cmd/expr.y 7.7 + * 7.8 + * Modified by Gunnar Ritter, Freiburg i. Br., Germany, January 2003. 7.9 + * 7.10 + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. 7.11 + * 7.12 + * Redistribution and use in source and binary forms, with or without 7.13 + * modification, are permitted provided that the following conditions 7.14 + * are met: 7.15 + * Redistributions of source code and documentation must retain the 7.16 + * above copyright notice, this list of conditions and the following 7.17 + * disclaimer. 7.18 + * Redistributions in binary form must reproduce the above copyright 7.19 + * notice, this list of conditions and the following disclaimer in the 7.20 + * documentation and/or other materials provided with the distribution. 7.21 + * All advertising materials mentioning features or use of this software 7.22 + * must display the following acknowledgement: 7.23 + * This product includes software developed or owned by Caldera 7.24 + * International, Inc. 7.25 + * Neither the name of Caldera International, Inc. nor the names of 7.26 + * other contributors may be used to endorse or promote products 7.27 + * derived from this software without specific prior written permission. 7.28 + * 7.29 + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA 7.30 + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 7.31 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 7.32 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 7.33 + * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE 7.34 + * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR 7.35 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7.36 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 7.37 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 7.38 + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 7.39 + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 7.40 + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 7.41 + */ 7.42 + 7.43 +/* Sccsid @(#)regexpr.c 1.8 (gritter) 10/13/04 */ 7.44 + 7.45 +#include <stdlib.h> 7.46 +#include "regexpr.h" 7.47 + 7.48 +int regerrno, reglength; 7.49 +static int circf; 7.50 + 7.51 +static char *regexpr_compile(char *, char *, const char *, int); 7.52 + 7.53 +char * 7.54 +compile(const char *instring, char *ep, char *endbuf) 7.55 +{ 7.56 + char *cp; 7.57 + int sz = 0; 7.58 + 7.59 + if (ep == 0) { 7.60 + for (cp = (char *)instring; *cp != '\0'; cp++) 7.61 + if (*cp == '[') 7.62 + sz += 32; 7.63 + sz += 2 * (cp - instring) + 5; 7.64 + if ((ep = malloc(sz)) == 0) { 7.65 + regerrno = 11; 7.66 + return 0; 7.67 + } 7.68 + endbuf = &ep[sz]; 7.69 + ep[1] = '\0'; 7.70 + } 7.71 + if ((cp=regexpr_compile((char *)instring, &ep[1], endbuf, '\0')) == 0) { 7.72 + if (sz) 7.73 + free(ep); 7.74 + return 0; 7.75 + } 7.76 + ep[0] = circf; 7.77 + reglength = cp - ep; 7.78 + return sz ? ep : cp; 7.79 +} 7.80 + 7.81 +#define INIT register char *sp = instring; 7.82 +#define GETC() (*sp++) 7.83 +#define PEEKC() (*sp) 7.84 +#define UNGETC(c) (--sp) 7.85 +#define RETURN(c) return (c); 7.86 +#define ERROR(c) { regerrno = c; return 0; } 7.87 + 7.88 +#define compile(a, b, c, d) regexpr_compile(a, b, c, d) 7.89 +#define regexp_h_static static 7.90 +#define REGEXP_H_STEP_INIT circf = *p2++; 7.91 +#define REGEXP_H_ADVANCE_INIT circf = *ep++; 7.92 + 7.93 +#include "regexp.h"
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/regexpr.h Mon Sep 05 16:31:35 2011 +0200 8.3 @@ -0,0 +1,53 @@ 8.4 +/* 8.5 + * Simple Regular Expression functions. Derived from Unix 7th Edition, 8.6 + * /usr/src/cmd/expr.y 8.7 + * 8.8 + * Modified by Gunnar Ritter, Freiburg i. Br., Germany, January 2003. 8.9 + * 8.10 + * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. 8.11 + * 8.12 + * Redistribution and use in source and binary forms, with or without 8.13 + * modification, are permitted provided that the following conditions 8.14 + * are met: 8.15 + * Redistributions of source code and documentation must retain the 8.16 + * above copyright notice, this list of conditions and the following 8.17 + * disclaimer. 8.18 + * Redistributions in binary form must reproduce the above copyright 8.19 + * notice, this list of conditions and the following disclaimer in the 8.20 + * documentation and/or other materials provided with the distribution. 8.21 + * All advertising materials mentioning features or use of this software 8.22 + * must display the following acknowledgement: 8.23 + * This product includes software developed or owned by Caldera 8.24 + * International, Inc. 8.25 + * Neither the name of Caldera International, Inc. nor the names of 8.26 + * other contributors may be used to endorse or promote products 8.27 + * derived from this software without specific prior written permission. 8.28 + * 8.29 + * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA 8.30 + * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 8.31 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 8.32 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 8.33 + * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE 8.34 + * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR 8.35 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 8.36 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 8.37 + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 8.38 + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 8.39 + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 8.40 + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 8.41 + */ 8.42 + 8.43 +/* Sccsid @(#)regexpr.h 1.2 (gritter) 1/11/03 */ 8.44 + 8.45 +#define NBRA 9 8.46 + 8.47 +extern char *braslist[NBRA]; 8.48 +extern char *braelist[NBRA]; 8.49 +extern int nbra; 8.50 +extern int regerrno, reglength; 8.51 +extern char *loc1, *loc2, *locs; 8.52 +extern int sed; 8.53 + 8.54 +extern char *compile(const char *, char *, char *); 8.55 +extern int step(const char *, const char *); 8.56 +extern int advance(const char *, const char *);
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/sigrelse.c Mon Sep 05 16:31:35 2011 +0200 9.3 @@ -0,0 +1,41 @@ 9.4 +/* 9.5 + * Copyright (c) 2004 Gunnar Ritter 9.6 + * 9.7 + * This software is provided 'as-is', without any express or implied 9.8 + * warranty. In no event will the authors be held liable for any damages 9.9 + * arising from the use of this software. 9.10 + * 9.11 + * Permission is granted to anyone to use this software for any purpose, 9.12 + * including commercial applications, and to alter it and redistribute 9.13 + * it freely, subject to the following restrictions: 9.14 + * 9.15 + * 1. The origin of this software must not be misrepresented; you must not 9.16 + * claim that you wrote the original software. If you use this software 9.17 + * in a product, an acknowledgment in the product documentation would be 9.18 + * appreciated but is not required. 9.19 + * 9.20 + * 2. Altered source versions must be plainly marked as such, and must not be 9.21 + * misrepresented as being the original software. 9.22 + * 9.23 + * 3. This notice may not be removed or altered from any source distribution. 9.24 + */ 9.25 +/* Sccsid @(#)sigrelse.c 1.8 (gritter) 1/22/06 */ 9.26 + 9.27 +#if defined (__FreeBSD__) || defined (__dietlibc__) || defined (__NetBSD__) || \ 9.28 + defined (__OpenBSD__) || defined (__DragonFly__) || defined (__APPLE__) 9.29 +#include <signal.h> 9.30 +#include "sigset.h" 9.31 + 9.32 +int 9.33 +sigrelse(int sig) 9.34 +{ 9.35 + sigset_t set, oset; 9.36 + 9.37 + if (sig <= 0) 9.38 + return -1; 9.39 + sigemptyset(&set); 9.40 + sigaddset(&set, sig); 9.41 + return sigprocmask(SIG_UNBLOCK, &set, &oset); 9.42 +} 9.43 +#endif /* __FreeBSD__ || __dietlibc__ || __NetBSD__ || __OpenBSD__ || 9.44 + __DragonFly__ || __APPLE__ */
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/sigset.c Mon Sep 05 16:31:35 2011 +0200 10.3 @@ -0,0 +1,55 @@ 10.4 +/* 10.5 + * Copyright (c) 2004 Gunnar Ritter 10.6 + * 10.7 + * This software is provided 'as-is', without any express or implied 10.8 + * warranty. In no event will the authors be held liable for any damages 10.9 + * arising from the use of this software. 10.10 + * 10.11 + * Permission is granted to anyone to use this software for any purpose, 10.12 + * including commercial applications, and to alter it and redistribute 10.13 + * it freely, subject to the following restrictions: 10.14 + * 10.15 + * 1. The origin of this software must not be misrepresented; you must not 10.16 + * claim that you wrote the original software. If you use this software 10.17 + * in a product, an acknowledgment in the product documentation would be 10.18 + * appreciated but is not required. 10.19 + * 10.20 + * 2. Altered source versions must be plainly marked as such, and must not be 10.21 + * misrepresented as being the original software. 10.22 + * 10.23 + * 3. This notice may not be removed or altered from any source distribution. 10.24 + */ 10.25 +/* Sccsid @(#)sigset.c 1.7 (gritter) 1/22/06 */ 10.26 + 10.27 +#if defined (__FreeBSD__) || defined (__dietlibc__) || defined (__NetBSD__) || \ 10.28 + defined (__OpenBSD__) || defined (__DragonFly__) || defined (__APPLE__) 10.29 +#include <signal.h> 10.30 +#include "sigset.h" 10.31 + 10.32 +void (*sigset(int sig, void (*func)(int)))(int) 10.33 +{ 10.34 + struct sigaction nact, oact; 10.35 + sigset_t nset, oset; 10.36 + 10.37 + if (sig <= 0) 10.38 + return SIG_ERR; 10.39 + sigemptyset(&nset); 10.40 + sigaddset(&nset, sig); 10.41 + if (sigprocmask(func==SIG_HOLD?SIG_BLOCK:SIG_UNBLOCK, &nset, &oset) < 0) 10.42 + return SIG_ERR; 10.43 + nact.sa_handler = func; 10.44 + nact.sa_flags = 0; 10.45 + if (sig == SIGCHLD && func == SIG_IGN) 10.46 + nact.sa_flags |= SA_NOCLDSTOP|SA_NOCLDWAIT; 10.47 + sigemptyset(&nact.sa_mask); 10.48 + sigaddset(&nact.sa_mask, sig); 10.49 + if (sigaction(sig, func==SIG_HOLD?(struct sigaction *)0:&nact, &oact) 10.50 + == -1) 10.51 + return SIG_ERR; 10.52 + if (sigismember(&oset, sig)) 10.53 + return SIG_HOLD; 10.54 + else 10.55 + return (oact.sa_handler); 10.56 +} 10.57 +#endif /* __FreeBSD__ || __dietlibc__ || __NetBSD__ || __OpenBSD__ || 10.58 + __DragonFly__ || __APPLE__ */
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/sigset.h Mon Sep 05 16:31:35 2011 +0200 11.3 @@ -0,0 +1,38 @@ 11.4 +/* 11.5 + * Copyright (c) 2004 Gunnar Ritter 11.6 + * 11.7 + * This software is provided 'as-is', without any express or implied 11.8 + * warranty. In no event will the authors be held liable for any damages 11.9 + * arising from the use of this software. 11.10 + * 11.11 + * Permission is granted to anyone to use this software for any purpose, 11.12 + * including commercial applications, and to alter it and redistribute 11.13 + * it freely, subject to the following restrictions: 11.14 + * 11.15 + * 1. The origin of this software must not be misrepresented; you must not 11.16 + * claim that you wrote the original software. If you use this software 11.17 + * in a product, an acknowledgment in the product documentation would be 11.18 + * appreciated but is not required. 11.19 + * 11.20 + * 2. Altered source versions must be plainly marked as such, and must not be 11.21 + * misrepresented as being the original software. 11.22 + * 11.23 + * 3. This notice may not be removed or altered from any source distribution. 11.24 + */ 11.25 +/* Sccsid @(#)sigset.h 1.9 (gritter) 1/22/06 */ 11.26 + 11.27 +#if defined (__FreeBSD__) || defined (__dietlibc__) || defined (__NetBSD__) || \ 11.28 + defined (__OpenBSD__) || defined (__DragonFly__) || defined (__APPLE__) 11.29 + 11.30 +#ifndef SIG_HOLD 11.31 +#define SIG_HOLD ((void (*)(int))2) 11.32 +#endif /* !SIG_HOLD */ 11.33 + 11.34 +extern int sighold(int); 11.35 +extern int sigignore(int); 11.36 +extern int sigpause(int); 11.37 +extern int sigrelse(int); 11.38 +extern void (*sigset(int, void (*)(int)))(int); 11.39 +extern void (*signal(int, void (*)(int)))(int); 11.40 +#endif /* __FreeBSD__ || __dietlibc__ || __NetBSD__ || __OpenBSD__ || 11.41 + __DragonFly__ || __APPLE__ */