windows上使用sed:将中间文本用base64解码得可执行文件,文末附源码

功能介绍

`

1. 基本文本替换

例:将hello替换为hi
echo "hello world" | sed -e 's/hello/hi/'
输出: hi world

全局替换(所有出现的地方)
echo "hello hello world" | sed -e 's/hello/hi/g'
输出: hi hi world

2. 删除操作

删除空行
echo -e "line1\n\nline2" | sed -e '/^$/d'
输出: line1\nline2

删除包含pattern的行
echo -e "keep\nremove this\keep too" | sed -e '/remove this/d'

3. 打印特定行

bash
只打印第一行(配合-n选项)
echo -e "line1\nline2\nline3" | sed -n -e '1p'
输出: line1

打印匹配的行
echo -e "apple\nbanana\napple" | sed -n -e '/apple/p'
输出: apple\napple

4. 行号操作

例:显示行号
echo -e "first\nsecond\nthird" | sed -e '='
输出:
1
first
2
second
3
third

5. 插入和追加文本

例:在第一行前插入文本
echo -e "line1\nline2" | sed -e '1i\Header line'
输出: Header line\nline1\nline2

例:在最后一行后追加文本
echo -e "line1\nline2" | sed -e '$a\Footer line'

6. 使用脚本文件

创建脚本文件 script.sed
cat > script.sed << EOF
s/foo/bar/g
/pattern/d
1,5p
EOF

使用脚本文件处理输入
sed -f script.sed input.txt

7. 字符转换

例:转换字符(类似tr命令)
echo "hello" | sed -e 'y/abcdef/ABCDEF/'
输出: hEllo

8. 多命令执行

例:多个命令用分号分隔
echo -e "test line\nanother test" | sed -e 's/test/TEST/; s/line/LINE/'
输出: TEST LINE\nanother TEST

或者使用多个-e选项
echo "sample text" | sed -e 's/sample/SAMPLE/' -e 's/text/TEXT/'

9. 地址范围操作

例:对第2到第4行执行替换
echo -e "1\n2\n3\n4\n5" | sed -e '2,4s/.*/changed/'
输出: 1\nchanged\nchanged\nchanged\n5

从匹配开始到文件结尾
echo -e "start\nmiddle\nend" | sed -e '/middle/,$s/.*/modified/'

10. 写入文件

例:将匹配的行写入文件
echo -e "save this\nignore this\nsave this too" | sed -e '/save/w output.txt'
`

可执行文件下载

将以下整段字符串下载保存到文件,然后用base64解码。推荐打开cmd,使用命令certutil -decode input output来完成。
-----BEGIN CERTIFICATE-----
TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5v
dCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAABQRQAATAEHAOFoC2kAAAAA
AAAAAOAADwMLAQIXAEYAAABeAAAAagAA4BQAAAAQAAAAYAAAAABAAAAQAAAAAgAA
BAAAAAEAAAAEAAAAAAAAAAAgAQAABAAAzdYAAAMAAAAAACAAABAAAAAAEAAAEAAA
AAAAABAAAAAAAAAAAAAAAADwAACABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAEAGAAAAAAAAAAAAAAA
AAAAAAAAAAAw8QAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC50ZXh0AAAA
hEUAAAAQAAAARgAAAAQAAAAAAAAAAAAAAAAAAGAAUGAuZGF0YQAAACgDAAAAYAAA
AAQAAABKAAAAAAAAAAAAAAAAAABAAGDALnJkYXRhAAAQBgAAAHAAAAAIAAAATgAA
AAAAAAAAAAAAAAAAQABgQC5ic3MAAAAAJGkAAACAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAIAAYMAuaWRhdGEAAIAGAAAA8AAAAAgAAABWAAAAAAAAAAAAAAAAAABAADDA
LkNSVAAAAAA0AAAAAAABAAACAAAAXgAAAAAAAAAAAAAAAAAAQAAwwC50bHMAAAAA
IAAAAAAQAQAAAgAAAGAAAAAAAAAAAAAAAAAAAEAAMMAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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
IGdhcmJsZWQgYWRkcmVzcyAlcwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
c2VkOiBmaXJzdCBSRSBtdXN0IGJlIG5vbi1udWxsCgBzZWQ6IG5vIHN1Y2ggY29t
bWFuZCBhcyAlcwoAAAAAAHNlZDogdG9vIG1hbnkgY29tbWFuZHMsIGxhc3Qgd2Fz
ICVzCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzZWQ6IGNvbW1hbmQgIiVz
IiBoYXMgdHJhaWxpbmcgZ2FyYmFnZQoAc2VkOiB0b28gbWFueSBsaW5lIG51bWJl
cnMKAHNlZDogUkUgdG9vIGxvbmc6ICVzCgBzZWQ6IGdhcmJsZWQgY29tbWFuZCAl
cwoAAAAAAAAAAAAAAAAAAHNlZDogbm8gYWRkcmVzc2VzIGFsbG93ZWQgZm9yICVz
CgBzZWQ6IHRvbyBtYW55IH0ncwoAAAAAAAAAAAAAAABzZWQ6IG9ubHkgb25lIGFk
ZHJlc3MgYWxsb3dlZCBmb3IgJXMKAAAALLhAAHNlZDogZHVwbGljYXRlIGxhYmVs
ICVzCgBzZWQ6IHRvbyBtYW55IGxhYmVsczogJXMKAAABAAAAc2VkOiB0b28gbWFu
eSB3IGZpbGVzCgBzZWQ6IGNhbm5vdCBjcmVhdGUgJXMKAHNlZDogdW5kZWZpbmVk
IGxhYmVsICVzCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////wAAAP//////////
gFVAAAIAAAD/////TuZAu7EZv0QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
X3NldF9pbnZhbGlkX3BhcmFtZXRlcl9oYW5kbGVyAABsaWJnY2otMTMuZGxsAF9K
dl9SZWdpc3RlckNsYXNzZXMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
c2VkOiBSRSBlcnJvciwgJW8KAAB6FUAAehVAAMMVQADiFUAAUBZAAGgWQACAFkAA
sBZAAOAWQAB6FUAA4BZAAHoVQADwFkAAehVAAAYXQAB6FUAAIBdAAGAXQAB6FUAA
ehVAAHoVQAB6FUAAsBVAAHIAc2VkOiBjYW4ndCBvcGVuICVzCgB3ADcqQABtI0AA
bSNAAGApQABtI0AAbSNAAG0jQABtI0AAbSNAAG0jQABUKUAAbSNAAG0jQABtI0AA
bSNAAG0jQABtI0AAbSNAANMmQABtI0AAbSNAAG0jQABtI0AAbSNAAG0jQABtI0AA
BSlAAG0jQABtI0AA6CZAAG0jQABtI0AAbSNAAG0jQABtI0AAbSNAAG0jQABtI0AA
bSNAAFMmQAAFKUAAXiZAAG0jQABtI0AAbSNAAG0jQABtI0AAUyZAAG0jQABtI0AA
0yZAAG0jQABtI0AAbSNAAG0jQABgKUAAUyZAAJIpQAAFKUAAbSNAAG0jQADoJkAA
bSNAAJEoQABtI0AASihAAG0jQAAcKEAAaG9sZCBzcGFjZQBsaW5lICVEAHNlZDog
ACB0cnVuY2F0ZWQgdG8gJWQgY2hhcmFjdGVycwoAAABzZWQ6IHRvbyBtYW55IGFw
cGVuZHMgYWZ0ZXIgbGluZSAlRAoAJUQKACUwMngAAABzZWQ6IHRvbyBtYW55IHJl
YWRzIGFmdGVyIGxpbmUgJUQKACVzCgAATTFAAAU2QADaNUAAPzNAAFQzQADGNUAA
OzRAAJg1QACYNEAAajRAANs2QAByM0AArDpAAKQ5QACGOEAAbzhAAJAzQAA/N0AA
PzhAAGg3QAAhM0AAITNAAP80QADoM0AAJTVAAKU2QABNMUAATTFAAE0xQABNMUAA
TTFAAE0xQAAxNkAA1jtAAL07QACkO0AASztAAEs7QACLO0AASztAAEs7QABLO0AA
SztAAEs7QABLO0AASztAAEs7QABLO0AASztAAEs7QABLO0AASztAAHI7QAAAAAAA
AACAAACBAAAAAAAAhgAACAoAAACgAA4AEAAAAJUAAJcAAAAAAAAAAACCg4QFAAAH
CYsAAIwADQAPkZKTlAAAlhiZAIMAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
QEBAAFVua25vd24gZXJyb3IAAABfbWF0aGVycigpOiAlcyBpbiAlcyglZywgJWcp
ICAocmV0dmFsPSVnKQoAAEFyZ3VtZW50IGRvbWFpbiBlcnJvciAoRE9NQUlOKQBB
cmd1bWVudCBzaW5ndWxhcml0eSAoU0lHTikAAE92ZXJmbG93IHJhbmdlIGVycm9y
IChPVkVSRkxPVykAVGhlIHJlc3VsdCBpcyB0b28gc21hbGwgdG8gYmUgcmVwcmVz
ZW50ZWQgKFVOREVSRkxPVykAAABUb3RhbCBsb3NzIG9mIHNpZ25pZmljYW5jZSAo
VExPU1MpAABQYXJ0aWFsIGxvc3Mgb2Ygc2lnbmlmaWNhbmNlIChQTE9TUykAAAAA
AHRAAB90QAA8dEAAXHRAAJR0QAC4dEAATWluZ3ctdzY0IHJ1bnRpbWUgZmFpbHVy
ZToKAEFkZHJlc3MgJXAgaGFzIG5vIGltYWdlLXNlY3Rpb24AICBWaXJ0dWFsUXVl
cnkgZmFpbGVkIGZvciAlZCBieXRlcyBhdCBhZGRyZXNzICVwAAAAACAgVmlydHVh
bFByb3RlY3QgZmFpbGVkIHdpdGggY29kZSAweCV4AAAgIFVua25vd24gcHNldWRv
IHJlbG9jYXRpb24gcHJvdG9jb2wgdmVyc2lvbiAlZC4KAAAAICBVbmtub3duIHBz
ZXVkbyByZWxvY2F0aW9uIGJpdCBzaXplICVkLgoAAABtAHMAdgBjAHIAdAAuAGQA
bABsAAAAAACgvkAAwLtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA88AAAAAAAAAAAAADQ9QAA
MPEAAJjwAAAAAAAAAAAAAHT2AACM8QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAk8gAA
PPIAAFTyAABo8gAAfvIAAJTyAACk8gAAuPIAAMryAADc8gAA9vIAAAbzAAAi8wAA
OvMAAErzAABk8wAAgvMAAIrzAACe8wAArPMAAMjzAADa8wAAAAAAAOrzAAD48wAA
CPQAABT0AAAk9AAANvQAAEr0AABU9AAAYvQAAGz0AAB29AAAgvQAAIr0AACS9AAA
nPQAAKb0AACu9AAAuPQAAMD0AADK9AAA0vQAANz0AADk9AAA7vQAAPj0AAAA9QAA
CvUAABT1AAAe9QAAKPUAADL1AAA69QAAQvUAAEz1AABW9QAAYPUAAGr1AAAAAAAA
JPIAADzyAABU8gAAaPIAAH7yAACU8gAApPIAALjyAADK8gAA3PIAAPbyAAAG8wAA
IvMAADrzAABK8wAAZPMAAILzAACK8wAAnvMAAKzzAADI8wAA2vMAAAAAAADq8wAA
+PMAAAj0AAAU9AAAJPQAADb0AABK9AAAVPQAAGL0AABs9AAAdvQAAIL0AACK9AAA
kvQAAJz0AACm9AAArvQAALj0AADA9AAAyvQAANL0AADc9AAA5PQAAO70AAD49AAA
APUAAAr1AAAU9QAAHvUAACj1AAAy9QAAOvUAAEL1AABM9QAAVvUAAGD1AABq9QAA
AAAAAMQARGVsZXRlQ3JpdGljYWxTZWN0aW9uAN8ARW50ZXJDcml0aWNhbFNlY3Rp
b24AALEBR2V0Q3VycmVudFByb2Nlc3MAsgFHZXRDdXJyZW50UHJvY2Vzc0lkALUB
R2V0Q3VycmVudFRocmVhZElkAADuAUdldExhc3RFcnJvcgAA/gFHZXRNb2R1bGVI
YW5kbGVBAAApAkdldFByb2NBZGRyZXNzAABEAkdldFN0YXJ0dXBJbmZvQQBbAkdl
dFN5c3RlbVRpbWVBc0ZpbGVUaW1lAHMCR2V0VGlja0NvdW50AADGAkluaXRpYWxp
emVDcml0aWNhbFNlY3Rpb24AAQNMZWF2ZUNyaXRpY2FsU2VjdGlvbgAABgNMb2Fk
TGlicmFyeVcAAGcDUXVlcnlQZXJmb3JtYW5jZUNvdW50ZXIAMQRTZXRVbmhhbmRs
ZWRFeGNlcHRpb25GaWx0ZXIAPQRTbGVlcABJBFRlcm1pbmF0ZVByb2Nlc3MAAFAE
VGxzR2V0VmFsdWUAXQRVbmhhbmRsZWRFeGNlcHRpb25GaWx0ZXIAAH0EVmlydHVh
bFByb3RlY3QAAIAEVmlydHVhbFF1ZXJ5AAA4AF9fZGxsb25leGl0ADsAX19nZXRt
YWluYXJncwA8AF9faW5pdGVudgBFAF9fbGNvbnZfaW5pdAAAaQBfX3NldF9hcHBf
dHlwZQAAbABfX3NldHVzZXJtYXRoZXJyAAB6AF9hY21kbG4AjwBfYW1zZ19leGl0
AACgAF9jZXhpdAAA/ABfZm1vZGUAAD0BX2luaXR0ZXJtAEEBX2lvYgAApQFfbG9j
awBHAl9vbmV4aXQA9QJfdW5sb2NrAL0DYWJvcnQAywNjYWxsb2MAANUDZXhpdAAA
2ANmY2xvc2UAAOMDZm9wZW4A5QNmcHJpbnRmAOwDZnJlZQAA7QNmcmVvcGVuAPcD
ZndyaXRlAAD6A2dldGMAAPsDZ2V0Y2hhcgAKBGlzcHJpbnQAJARtYWxsb2MAACsE
bWVtY21wAAAsBG1lbWNweQAANgRwdXRjAAA4BHB1dHMAAEkEc2lnbmFsAABVBHN0
cmNtcAAAXQRzdHJsZW4AAGAEc3RybmNtcACABHZmcHJpbnRmAAAAAADwAAAA8AAA
APAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAA
APAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAABLRVJORUwzMi5kbGwAAAAA
FPAAABTwAAAU8AAAFPAAABTwAAAU8AAAFPAAABTwAAAU8AAAFPAAABTwAAAU8AAA
FPAAABTwAAAU8AAAFPAAABTwAAAU8AAAFPAAABTwAAAU8AAAFPAAABTwAAAU8AAA
FPAAABTwAAAU8AAAFPAAABTwAAAU8AAAFPAAABTwAAAU8AAAFPAAABTwAAAU8AAA
FPAAAG1zdmNydC5kbGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAQEEAAAAAAAAAAAABgEEAA0EBAAAAAAAAAAAAA
QEBAAPA/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
GBBBABwQQQCQu0AAIABBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
-----END CERTIFICATE-----

源码

#include <stdio.h>
#include <ctype.h>


/* data area sizes used by both modules */
#define MAXBUF 4000      /* current line buffer size */
#define MAXAPPENDS 20 /* maximum number of appends */
#define MAXTAGS 9      /* tagged patterns are \1 to \9 */

/* constants for compiled-command representation */
#define EQCMD 0x01 /* = -- print current line number    */
#define ACMD 0x02  /* a -- append text after current line    */
#define BCMD 0x03  /* b -- branch to label            */
#define CCMD 0x04  /* c -- change current line        */
#define DCMD 0x05  /* d -- delete all of pattern space        */
#define CDCMD 0x06 /* D -- delete first line of pattern space    */
#define GCMD 0x07  /* g -- copy hold space to pattern space    */
#define CGCMD 0x08 /* G -- append hold space to pattern space    */
#define HCMD 0x09  /* h -- copy pattern space to hold space    */
#define CHCMD 0x0A /* H -- append pattern space to hold space    */
#define ICMD 0x0B  /* i -- insert text before current line        */
#define LCMD 0x0C  /* l -- print pattern space in escaped form    */
#define NCMD 0x0D  /* n -- get next line into pattern space    */
#define CNCMD 0x0E /* N -- append next line to pattern space    */
#define PCMD 0x0F  /* p -- print pattern space to output        */
#define CPCMD 0x10 /* P -- print first line of pattern space    */
#define QCMD 0x11  /* q -- exit the stream editor            */
#define RCMD 0x12  /* r -- read in a file after current line    */
#define SCMD 0x13  /* s -- regular-expression substitute        */
#define TCMD 0x14  /* t -- branch on any substitute successful    */
#define CTCMD 0x15 /* T -- branch on any substitute failed        */
#define WCMD 0x16  /* w -- write pattern space to file        */
#define CWCMD 0x17 /* W -- write first line of pattern space    */
#define XCMD 0x18  /* x -- exhange pattern and hold spaces        */
#define YCMD 0x19  /* y -- transliterate text            */
#define CLCMD 0x20 /* L -- hexdump                    */

struct cmd_t /* compiled-command representation */
{
    char *addr1; /* first address for command */
    char *addr2; /* second address for command */
    union
    {
        char *lhs;            /* s command lhs */
        struct cmd_t *link; /* label link */
    } u;
    char command; /* command code */
    char *rhs;      /* s command replacement string */
    FILE *fout;      /* associated output file descriptor */
    struct
    {
        char allbut;  /* was negation specified? */
        char global;  /* was g postfix specified? */
        char print;      /* was p postfix specified? */
        char inrange; /* in an address range? */
    } flags;
};
typedef struct cmd_t sedcmd; /* use this name for declarations */

#define BAD ((char *)-1) /* guaranteed not a string ptr */

/* address and regular expression compiled-form markers */
#define STAR 1     /* marker for Kleene star */
#define CCHR 2     /* non-newline character to be matched follows */
#define CDOT 4     /* dot wild-card marker */
#define CCL 6     /* character class follows */
#define CNL 8     /* match line start */
#define CDOL 10     /* match line end */
#define CBRA 12     /* tagged pattern start marker */
#define CKET 14     /* tagged pattern end marker */
#define CBACK 16 /* backslash-digit pair marker */
#define CLNUM 18 /* numeric-address index follows */
#define CEND 20     /* symbol for end-of-source */
#define CEOF 22     /* end-of-field mark */

/* sed.h ends here */

#define CMASK 0xFF /* some char type should have been unsigned char? */

/* #include <stdio.h>        /* uses getc, fprintf, fopen, fclose */
extern FILE *fopen(); /* should this be in stdio.h? */
/* #include "sed.h"        /* command type struct and name defines */

/* imported functions */
extern int strcmp();   /* test strings for equality */
extern void execute(); /* execute compiled command */

/***** public stuff ******/

#define MAXCMDS 200     /* maximum number of compiled commands */
#define MAXLINES 256 /* max # numeric addresses to compile */

/* main data areas */
char linebuf[MAXBUF + 1]; /* current-line buffer */
sedcmd cmds[MAXCMDS + 1]; /* hold compiled commands */
long linenum[MAXLINES];      /* numeric-addresses table */

/* miscellaneous shared variables */
int nflag;      /* -n option flag */
int eargc;      /* scratch copy of argument count */
char **eargv; /* scratch copy of argument list */
char bits[] = {1, 2, 4, 8, 16, 32, 64, 128};

/***** module common stuff *****/

#define POOLSIZE 6000 /* size of string-pool space */
#define WFILES 10      /* max # w output files that can be compiled */
#define RELIMIT 256      /* max chars in compiled RE */
#define MAXDEPTH 20      /* maximum {}-nesting level */
#define MAXLABS 50      /* max # of labels that can be handled */

#define SKIPWS(pc)                        \
    while ((*pc == ' ') || (*pc == '\t')) \
    pc++
#define ABORT(msg) (fprintf(stderr, msg, linebuf), quit(2))
#define IFEQ(x, v) \
    if (*x == v)   \
    x++, /* do expression */

/* error messages */
static char AGMSG[] = "sed: garbled address %s\n";
static char CGMSG[] = "sed: garbled command %s\n";
static char TMTXT[] = "sed: too much text: %s\n";
static char AD1NG[] = "sed: no addresses allowed for %s\n";
static char AD2NG[] = "sed: only one address allowed for %s\n";
static char TMCDS[] = "sed: too many commands, last was %s\n";
static char COCFI[] = "sed: cannot open command-file %s\n";
static char UFLAG[] = "sed: unknown flag %c\n";
static char CCOFI[] = "sed: cannot create %s\n";
static char ULABL[] = "sed: undefined label %s\n";
static char TMLBR[] = "sed: too many {'s\n";
static char FRENL[] = "sed: first RE must be non-null\n";
static char NSCAX[] = "sed: no such command as %s\n";
static char TMRBR[] = "sed: too many }'s\n";
static char DLABL[] = "sed: duplicate label %s\n";
static char TMLAB[] = "sed: too many labels: %s\n";
static char TMWFI[] = "sed: too many w files\n";
static char REITL[] = "sed: RE too long: %s\n";
static char TMLNR[] = "sed: too many line numbers\n";
static char TRAIL[] = "sed: command \"%s\" has trailing garbage\n";

typedef struct /* represent a command label */
{
    char *name;         /* the label name */
    sedcmd *last;     /* it's on the label search list */
    sedcmd *address; /* pointer to the cmd it labels */
} label;

/* label handling */
static label labels[MAXLABS];    /* here's the label table */
static label *lab = labels + 1; /* pointer to current label */
static label *lablst = labels;    /* header for search list */

/* string pool for regular expressions, append text, etc. etc. */
static char pool[POOLSIZE];                /* the pool */
static char *fp = pool;                    /* current pool pointer */
static char *poolend = pool + POOLSIZE; /* pointer past pool end */

/* compilation state */
static FILE *cmdf = NULL;    /* current command source */
static char *cp = linebuf;    /* compile pointer */
static sedcmd *cmdp = cmds; /* current compiled-cmd ptr */
static char *lastre = NULL; /* old RE pointer */
static int bdepth = 0;        /* current {}-nesting level */
static int bcount = 0;        /* # tagged patterns in current RE */

/* compilation flags */
static int eflag; /* -e option flag */
static int gflag; /* -g option flag */

#define H 0x80      /* 128 bit, on if there's really code for command */
#define LOWCMD 56 /* = '8', lowest char indexed in cmdmask */

/* indirect through this to get command internal code, if it exists */
static char cmdmask[] =
{
    0, 0, H, 0, 0, H+EQCMD,0, 0,
    0, 0, 0, 0, H+CDCMD,0, 0, CGCMD,
    CHCMD, 0, 0, 0, H+CLCMD,0, CNCMD, 0,
    CPCMD, 0, 0, 0, H+CTCMD,0, 0, H+CWCMD,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, H+ACMD, H+BCMD, H+CCMD, DCMD, 0, 0, GCMD,
    HCMD, H+ICMD, 0, 0, H+LCMD, 0, NCMD, 0,
    PCMD, H+QCMD, H+RCMD, H+SCMD, H+TCMD, 0, 0, H+WCMD,
    XCMD, H+YCMD, 0, H+BCMD, 0, H, 0, 0,
};

static char *rhscomp(rhsp, delim) /* uses bcount */
/* generate replacement string for substitute command right hand side */
register char *rhsp; /* place to compile expression to */
register char delim; /* regular-expression end-mark to look for */
{
    register char *p = cp; /* strictly for speed */

    for (;;)
        if ((*rhsp = *p++) == '\\') /* copy; if it's a \, */
        {
            *rhsp = *p++; /* copy escaped char */
            /* check validity of pattern tag */
            if (*rhsp > bcount + '0' && *rhsp <= '9')
                return (BAD);
            *rhsp++ |= 0x80; /* mark the good ones */
            continue;
        }
        else if (*rhsp == delim) /* found RE end, hooray... */
        {
            *rhsp++ = '\0'; /* cap the expression string */
            cp = p;
            return (rhsp); /* pt at 1 past the RE */
        }
        else if (*rhsp++ == '\0') /* last ch not RE end, help! */
            return (BAD);
}

static char *recomp(expbuf, redelim) /* uses cp, bcount */
/* compile a regular expression to internal form */
char *expbuf; /* place to compile it to */
char redelim; /* RE end-marker to look for */
{
    register char *ep = expbuf; /* current-compiled-char pointer */
    register char *sp = cp;        /* source-character ptr */
    register int c;                /* current-character pointer */
    char negclass;                /* all-but flag */
    char *lastep;                /* ptr to last expr compiled */
    char *svclass;                /* start of current char class */
    char brnest[MAXTAGS];        /* bracket-nesting array */
    char *brnestp;                /* ptr to current bracket-nest */
    char *pp;                    /* scratch pointer */
    int classct;                /* class element count */
    int tags;                    /* # of closed tags */

    if (*cp == redelim)           /* if first char is RE endmarker */
        return (cp++, expbuf); /* leave existing RE unchanged */

    lastep = NULL;       /* there's no previous RE */
    brnestp = brnest;  /* initialize ptr to brnest array */
    tags = bcount = 0; /* initialize counters */

    if (*ep++ = (*sp == '^')) /* check for start-of-line syntax */
        sp++;

    for (;;)
    {
        if (ep >= expbuf + RELIMIT) /* match is too large */
            return (cp = sp, BAD);
        if ((c = *sp++) == redelim) /* found the end of the RE */
        {
            cp = sp;
            if (brnestp != brnest) /* \(, \) unbalanced */
                return (BAD);
            *ep++ = CEOF; /* write end-of-pattern mark */
            return (ep);  /* return ptr to compiled RE */
        }
        if (c != '*')     /* if we're a postfix op */
            lastep = ep; /*   get ready to match last */

        switch (c)
        {
        case '\\':
            if ((c = *sp++) == '(') /* start tagged section */
            {
                if (bcount >= MAXTAGS)
                    return (cp = sp, BAD);
                *brnestp++ = bcount; /* update tag stack */
                *ep++ = CBRA;         /* enter tag-start */
                *ep++ = bcount++;     /* bump tag count */
                continue;
            }
            else if (c == ')') /* end tagged section */
            {
                if (brnestp <= brnest) /* extra \) */
                    return (cp = sp, BAD);
                *ep++ = CKET;        /* enter end-of-tag */
                *ep++ = *--brnestp; /* pop tag stack */
                tags++;                /* count closed tags */
                continue;
            }
            else if (c >= '1' && c <= '9') /* tag use */
            {
                if ((c -= '1') >= tags) /* too few */
                    return (BAD);
                *ep++ = CBACK; /* enter tag mark */
                *ep++ = c;       /* and the number */
                continue;
            }
            else if (c == '\n') /* escaped newline no good */
                return (cp = sp, BAD);
            else if (c == 'n') /* match a newline */
                c = '\n';
            else if (c == 't') /* match a tab */
                c = '\t';
            else if (c == 'r') /* match a return */
                c = '\r';
            goto defchar;

        case '\0': /* ignore nuls */
            continue;

        case '\n': /* trailing pattern delimiter is missing */
            return (cp = sp, BAD);

        case '.': /* match any char except newline */
            *ep++ = CDOT;
            continue;
        case '*':                 /* 0..n repeats of previous pattern */
            if (lastep == NULL)     /* if * isn't first on line */
                goto defchar;     /*   match a literal * */
            if (*lastep == CKET) /* can't iterate a tag */
                return (cp = sp, BAD);
            *lastep |= STAR; /* flag previous pattern */
            continue;

        case '$':                /* match only end-of-line */
            if (*sp != redelim) /* if we're not at end of RE */
                goto defchar;    /*   match a literal $ */
            *ep++ = CDOL;        /* insert end-symbol mark */
            continue;

        case '[': /* begin character set pattern */
            if (ep + 17 >= expbuf + RELIMIT)
                ABORT(REITL);
            *ep++ = CCL; /* insert class mark */
            if (negclass = ((c = *sp++) == '^'))
                c = *sp++;
            svclass = sp; /* save ptr to class start */
            do
            {
                if (c == '\0')
                    ABORT(CGMSG);

                /* handle character ranges */
                if (c == '-' && sp > svclass && *sp != ']')
                    for (c = sp[-2]; c < *sp; c++)
                        ep[c >> 3] |= bits[c & 7];

                /* handle escape sequences in sets */
                if (c == '\\')
                    if ((c = *sp++) == 'n')
                        c = '\n';
                    else if (c == 't')
                        c = '\t';
                    else if (c == 'r')
                        c = '\r';

                /* enter (possibly translated) char in set */
                ep[c >> 3] |= bits[c & 7];
            } while ((c = *sp++) != ']');

            /* invert the bitmask if all-but was specified */
            if (negclass)
                for (classct = 0; classct < 16; classct++)
                    ep[classct] ^= 0xFF;
            ep[0] &= 0xFE; /* never match ASCII 0 */
            ep += 16;       /* advance ep past set mask */
            continue;

        defchar:          /* match literal character */
        default:          /* which is what we'd do by default */
            *ep++ = CCHR; /* insert character mark */
            *ep++ = c;
        }
    }
}

static label *search(ptr) /* uses global lablst */
/* find the label matching *ptr, return NULL if none */
register label *ptr;
{
    register label *rp;
    for (rp = lablst; rp < ptr; rp++)
        if ((rp->name != NULL) && (strcmp(rp->name, ptr->name) == 0))
            return (rp);
    return (NULL);
}

static char *ycomp(ep, delim)
/* compile a y (transliterate) command */
register char *ep; /* where to compile to */
char delim;           /* end delimiter to look for */
{
    register char *tp, *sp;
    register int c;

    /* scan the 'from' section for invalid chars */
    for (sp = tp = cp; *tp != delim; tp++)
    {
        if (*tp == '\\')
            tp++;
        if ((*tp == '\n') || (*tp == '\0'))
            return (BAD);
    }
    tp++; /* tp now points at first char of 'to' section */

    /* now rescan the 'from' section */
    while ((c = *sp++ & 0x7F) != delim)
    {
        if (c == '\\' && *sp == 'n')
        {
            sp++;
            c = '\n';
        }
        if ((ep[c] = *tp++) == '\\' && *tp == 'n')
        {
            ep[c] = '\n';
            tp++;
        }
        if ((ep[c] == delim) || (ep[c] == '\0'))
            return (BAD);
    }

    if (*tp != delim) /* 'to', 'from' parts have unequal lengths */
        return (BAD);

    cp = ++tp; /* point compile ptr past translit */

    for (c = 0; c < 128; c++) /* fill in self-map entries in table */
        if (ep[c] == 0)
            ep[c] = c;

    return (ep + 0x80); /* return first free location past table end */
}

static char *gettext(txp) /* uses global cp */
/* accept multiline input from *cp..., discarding leading whitespace */
register char *txp; /* where to put the text */
{
    register char *p = cp; /* this is for speed */

    SKIPWS(p); /* discard whitespace */
    do
    {
        if ((*txp = *p++) == '\\') /* handle escapes */
            *txp = *p++;
        if (*txp == '\0') /* we're at end of input */
            return (cp = --p, ++txp);
        else if (*txp == '\n') /* also SKIPWS after newline */
            SKIPWS(p);
    } while (txp++); /* keep going till we find that nul */
    return (txp);
}

static int cmdcomp(cchar)
/* compile a single command */
register char cchar; /* character name of command */
{
    static sedcmd **cmpstk[MAXDEPTH]; /* current cmd stack for {} */
    static char *fname[WFILES];          /* w file name pointers */
    static FILE *fout[WFILES];          /* w file file ptrs */
    static int nwfiles = 1;              /* count of open w files */
    int i;                              /* indexing dummy used in w */
    sedcmd *sp1, *sp2;                  /* temps for label searches */
    label *lpt, *search();              /* ditto, and the searcher */
    char redelim;                      /* current RE delimiter */

    fout[0] = stdout;
    switch (cchar)
    {
    case '{': /* start command group */
        cmdp->flags.allbut = !cmdp->flags.allbut;
        cmpstk[bdepth++] = &(cmdp->u.link);
        if (++cmdp >= cmds + MAXCMDS)
            ABORT(TMCDS);
        return (1);

    case '}': /* end command group */
        if (cmdp->addr1)
            ABORT(AD1NG); /* no addresses allowed */
        if (--bdepth < 0)
            ABORT(TMRBR);        /* too many right braces */
        *cmpstk[bdepth] = cmdp; /* set the jump address */
        return (1);

    case '=': /* print current source line number */
    case 'q': /* exit the stream editor */
        if (cmdp->addr2)
            ABORT(AD2NG);
        break;

    case ':': /* label declaration */
        if (cmdp->addr1)
            ABORT(AD1NG);              /* no addresses allowed */
        fp = gettext(lab->name = fp); /* get the label name */
        if (lpt = search(lab))          /* does it have a double? */
        {
            if (lpt->address)
                ABORT(DLABL); /* yes, abort */
        }
        else /* check that it doesn't overflow label table */
        {
            lab->last = NULL;
            lpt = lab;
            if (++lab >= labels + MAXLABS)
                ABORT(TMLAB);
        }
        lpt->address = cmdp;
        return (1);

    case 'b': /* branch command */
    case 't': /* branch-on-succeed command */
    case 'T': /* branch-on-fail command */
        SKIPWS(cp);
        if (*cp == '\0') /* if branch is to start of cmds... */
        {
            /* add current command to end of label last */
            if (sp1 = lablst->last)
            {
                while (sp2 = sp1->u.link)
                    sp1 = sp2;
                sp1->u.link = cmdp;
            }
            else /* lablst->last == NULL */
                lablst->last = cmdp;
            break;
        }
        fp = gettext(lab->name = fp); /* else get label into pool */
        if (lpt = search(lab))          /* enter branch to it */
        {
            if (lpt->address)
                cmdp->u.link = lpt->address;
            else
            {
                sp1 = lpt->last;
                while (sp2 = sp1->u.link)
                    sp1 = sp2;
                sp1->u.link = cmdp;
            }
        }
        else /* matching named label not found */
        {
            lab->last = cmdp;               /* add the new label */
            lab->address = NULL;           /* it's forward of here */
            if (++lab >= labels + MAXLABS) /* overflow if last */
                ABORT(TMLAB);
        }
        break;

    case 'a': /* append text */
    case 'i': /* insert text */
    case 'r': /* read file into stream */
        if (cmdp->addr2)
            ABORT(AD2NG);
    case 'c': /* change text */
        if ((*cp == '\\') && (*++cp == '\n'))
            cp++;
        fp = gettext(cmdp->u.lhs = fp);
        break;

    case 'D': /* delete current line in hold space */
        cmdp->u.link = cmds;
        break;

    case 's':             /* substitute regular expression */
        redelim = *cp++; /* get delimiter from 1st ch */
        if ((fp = recomp(cmdp->u.lhs = fp, redelim)) == BAD)
            ABORT(CGMSG);
        if (fp == cmdp->u.lhs)      /* if compiled RE zero len */
            cmdp->u.lhs = lastre; /*   use the previous one */
        else                      /* otherwise */
            lastre = cmdp->u.lhs; /*   save the one just found */
        if ((cmdp->rhs = fp) > poolend)
            ABORT(TMTXT);
        if ((fp = rhscomp(cmdp->rhs, redelim)) == BAD)
            ABORT(CGMSG);
        if (gflag)
            cmdp->flags.global++;
        while (*cp == 'g' || *cp == 'p' || *cp == 'P')
        {
            IFEQ(cp, 'g')
            cmdp->flags.global++;
            IFEQ(cp, 'p')
            cmdp->flags.print = 1;
            IFEQ(cp, 'P')
            cmdp->flags.print = 2;
        }

    case 'l': /* list pattern space */
    case 'L': /* dump pattern space */
        if (*cp == 'w')
            cp++; /* and execute a w command! */
        else
            break; /* s or L or l is done */

    case 'w': /* write-pattern-space command */
    case 'W': /* write-first-line command */
        if (nwfiles >= WFILES)
            ABORT(TMWFI);
        fp = gettext(fname[nwfiles] = fp); /* filename will be in pool */
        for (i = nwfiles - 1; i >= 0; i--) /* match it in table */
            if ((fname[i] != NULL) &&
                (strcmp(fname[nwfiles], fname[i]) == 0))
            {
                cmdp->fout = fout[i];
                return (0);
            }
        /* if didn't find one, open new out file */
        if ((cmdp->fout = fopen(fname[nwfiles], "w")) == NULL)
        {
            fprintf(stderr, CCOFI, fname[nwfiles]);
            quit(2);
        }
        fout[nwfiles++] = cmdp->fout;
        break;

    case 'y':                                 /* transliterate text */
        fp = ycomp(cmdp->u.lhs = fp, *cp++); /* compile translit */
        if (fp == BAD)
            ABORT(CGMSG); /* fail on bad form */
        if (fp > poolend)
            ABORT(TMTXT); /* fail on overflow */
        break;
    }
    return (0); /* succeeded in interpreting one command */
}

static int cmdline(cbuf) /* uses eflag, eargc, cmdf */
/* read next command from -e argument or command file */
register char *cbuf;
{
    register int inc; /* not char because must hold EOF */

    cbuf--; /* so pre-increment points us at cbuf */

    /* e command flag is on */
    if (eflag)
    {
        register char *p;    /* ptr to current -e argument */
        static char *savep; /* saves previous value of p */

        if (eflag > 0) /* there are pending -e arguments */
        {
            eflag = -1;
            if (eargc-- <= 0)
                quit(2); /* if no arguments, barf */

            /* else transcribe next e argument into cbuf */
            p = *++eargv;
            while (*++cbuf = *p++)
                if (*cbuf == '\\')
                {
                    if ((*++cbuf = *p++) == '\0')
                        return (savep = NULL, -1);
                    else
                        continue;
                }
                else if (*cbuf == '\n') /* end of 1 cmd line */
                {
                    *cbuf = '\0';
                    return (savep = p, 1);
                    /* we'll be back for the rest... */
                }

            /* found end-of-string; can advance to next argument */
            return (savep = NULL, 1);
        }

        if ((p = savep) == NULL)
            return (-1);

        while (*++cbuf = *p++)
            if (*cbuf == '\\')
            {
                if ((*++cbuf = *p++) == '0')
                    return (savep = NULL, -1);
                else
                    continue;
            }
            else if (*cbuf == '\n')
            {
                *cbuf = '\0';
                return (savep = p, 1);
            }

        return (savep = NULL, 1);
    }

    /* if no -e flag read from command file descriptor */
    while ((inc = getc(cmdf)) != EOF)    /* get next char */
        if ((*++cbuf = inc) == '\\')    /* if it's escape */
            *++cbuf = inc = getc(cmdf); /* get next char */
        else if (*cbuf == '\n')            /* end on newline */
            return (*cbuf = '\0', 1);    /* cap the string */

    return (*++cbuf = '\0', -1); /* end-of-file, no more chars */
}

static char *address(expbuf) /* uses cp, linenum */
/* expand an address at *cp... into expbuf, return ptr at following char */
register char *expbuf;
{
    static int numl = 0; /* current ind in addr-number table */
    register char *rcp;     /* temp compile ptr for forwd look */
    long lno;             /* computed value of numeric address */

    if (*cp == '$') /* end-of-source address */
    {
        *expbuf++ = CEND; /* write symbolic end address */
        *expbuf++ = CEOF; /* and the end-of-address mark (!) */
        cp++;              /* go to next source character */
        return (expbuf);  /* we're done */
    }
    if (*cp == '/')                        /* start of regular-expression match */
        return (recomp(expbuf, *cp++)); /* compile the RE */

    rcp = cp;
    lno = 0;                           /* now handle a numeric address */
    while (*rcp >= '0' && *rcp <= '9') /* collect digits */
        lno = lno * 10 + *rcp++ - '0'; /*  compute their value */

    if (rcp > cp) /* if we caught a number... */
    {
        *expbuf++ = CLNUM;       /* put a numeric-address marker */
        *expbuf++ = numl;       /* and the address table index */
        linenum[numl++] = lno; /* and set the table entry */
        if (numl >= MAXLINES)  /* oh-oh, address table overflow */
            ABORT(TMLNR);       /*   abort with error message */
        *expbuf++ = CEOF;       /* write the end-of-address marker */
        cp = rcp;               /* point compile past the address */
        return (expbuf);       /* we're done */
    }

    return (NULL); /* no legal address was found */
}

static void compile()
/* precompile sed commands out of a file */
{
    char ccode;

    for (;;) /* main compilation loop */
    {
        if (*cp == '\0') /* get a new command line */
            if (cmdline(cp = linebuf) < 0)
                break;
        SKIPWS(cp);
        if (*cp == '\0') /* empty */
            continue;
        if (*cp == '#') /* comment */
        {
            while (*cp)
                ++cp;
            continue;
        }
        if (*cp == ';') /* ; separates cmds */
        {
            cp++;
            continue;
        }

        /* compile first address */
        if (fp > poolend)
            ABORT(TMTXT);
        else if ((fp = address(cmdp->addr1 = fp)) == BAD)
            ABORT(AGMSG);

        if (fp == cmdp->addr1) /* if empty RE was found */
        {
            if (lastre)                  /* if there was previous RE */
                cmdp->addr1 = lastre; /* use it */
            else
                ABORT(FRENL);
        }
        else if (fp == NULL) /* if fp was NULL */
        {
            fp = cmdp->addr1; /* use current pool location */
            cmdp->addr1 = NULL;
        }
        else
        {
            lastre = cmdp->addr1;
            if (*cp == ',' || *cp == ';') /* there's 2nd addr */
            {
                cp++;
                if (fp > poolend)
                    ABORT(TMTXT);
                fp = address(cmdp->addr2 = fp);
                if (fp == BAD || fp == NULL)
                    ABORT(AGMSG);
                if (fp == cmdp->addr2)
                    cmdp->addr2 = lastre;
                else
                    lastre = cmdp->addr2;
            }
            else
                cmdp->addr2 = NULL; /* no 2nd address */
        }
        if (fp > poolend)
            ABORT(TMTXT);

        SKIPWS(cp); /* discard whitespace after address */
        IFEQ(cp, '!')
        cmdp->flags.allbut = 1;

        SKIPWS(cp); /* get cmd char, range-check it */
        if ((*cp < LOWCMD) || (*cp > '~') || ((ccode = cmdmask[*cp - LOWCMD]) == 0))
            ABORT(NSCAX);

        cmdp->command = ccode & ~H; /* fill in command value */
        if ((ccode & H) == 0)        /* if no compile-time code */
            cp++;                    /* discard command char */
        else if (cmdcomp(*cp++))    /* execute it; if ret = 1 */
            continue;                /* skip next line read */

        if (++cmdp >= cmds + MAXCMDS)
            ABORT(TMCDS);

        SKIPWS(cp); /* look for trailing stuff */
        if (*cp != '\0' && *cp != ';' && *cp != '#')
            ABORT(TRAIL);
    }
}

static void resolve() /* uses global lablst */
/* write label links into the compiled-command space */
{
    register label *lptr;
    register sedcmd *rptr, *trptr;

    /* loop through the label table */
    for (lptr = lablst; lptr < lab; lptr++)
        if (lptr->address == NULL) /* barf if not defined */
        {
            fprintf(stderr, ULABL, lptr->name);
            quit(2);
        }
        else if (lptr->last) /* if last is non-null */
        {
            rptr = lptr->last;             /* chase it */
            while (trptr = rptr->u.link) /* resolve refs */
            {
                rptr->u.link = lptr->address;
                rptr = trptr;
            }
            rptr->u.link = lptr->address;
        }
}

quit(n) int n;
{
    /* Flush buffers and exit. */
    //_cleanup();
    exit(n);
}

/***** shared variables imported from the main ******/

/* main data areas */
extern char linebuf[]; /* current-line buffer */
extern sedcmd cmds[];  /* hold compiled commands */
extern long linenum[]; /* numeric-addresses table */

/* miscellaneous shared variables */
extern int nflag;     /* -n option flag */
extern int eargc;     /* scratch copy of argument count */
extern char **eargv; /* scratch copy of argument list */
extern char bits[];     /* the bits table */

/***** end of imported stuff *****/

#define MAXHOLD MAXBUF /* size of the hold space */
#define GENSIZ MAXBUF  /* maximum genbuf size */

#define TRUE 1
#define FALSE 0

static char LTLMSG[] = "sed: line too long\n";

static char *spend;       /* current end-of-line-buffer pointer */
static long lnum = 0L; /* current source line number */

/* append buffer maintenance */
static sedcmd *appends[MAXAPPENDS]; /* array of ptrs to a,i,c commands */
static sedcmd **aptr = appends;        /* ptr to current append */

/* genbuf and its pointers */
static char genbuf[GENSIZ];
static char *loc1;
static char *loc2;
static char *locs;

/* command-logic flags */
static int lastline; /* do-line flag */
static int jump;     /* jump to cmd's link address if set */
static int delete;     /* delete command flag */

/* tagged-pattern tracking */
static char *bracend[MAXTAGS];    /* tagged pattern start pointers */
static char *brastart[MAXTAGS]; /* tagged pattern end pointers */

static int anysub; /* true if any s on current line succeeded */
static int c;       /* Will be the next char to read, a kind of lookahead */

static void truncated(h) int h;
{
    static long last = 0L;

    if (lnum == last)
        return;
    last = lnum;

    fprintf(stderr, "sed: ");
    fprintf(stderr, h ? "hold space" : "line %D", lnum);
    fprintf(stderr, " truncated to %d characters\n", MAXBUF);
}

static void openfile(file) char *file;
/* Replace stdin by given file */
{
    if (freopen(file, "r", stdin) == NULL)
    {
        fprintf(stderr, "sed: can't open %s\n", file);
        quit(1);
    }
}

static void get()
/* Read next character into c treating all argument files as run through cat */
{
    while ((c = getchar()) == EOF && --eargc >= 0)
        openfile(*eargv++);
}

static char *getline(buf)
/* get next line of text to be edited, return pointer to end */
register char *buf; /* where to send the input */
{
    if (c == EOF)
        return BAD;

    lnum++; /* we can read a new line */

    do
    {
        if (c == '\n')
        {
            get();
            break;
        }
        if (buf <= linebuf + MAXBUF)
            *buf++ = c;
        get();
    } while (c != EOF);

    if (c == EOF)
        lastline = TRUE;

    if (buf > linebuf + MAXBUF)
    {
        truncated();
        --buf;
    }

    *buf = 0;
    return buf;
}

static int advance(lp, ep)
/* attempt to advance match pointer by one pattern element */
register char *lp; /* source (linebuf) ptr */
register char *ep; /* regular expression element ptr */
{
    register char *curlp; /* save ptr for closures */
    char c;                  /* scratch character holder */
    char *bbeg;
    int ct;

    for (;;)
        switch (*ep++)
        {
        case CCHR:                /* literal character */
            if (*ep++ == *lp++) /* if chars are equal */
                continue;        /* matched */
            return (FALSE);        /* else return false */

        case CDOT:            /* anything but newline */
            if (*lp++)        /* first NUL is at EOL */
                continue;    /* keep going if didn't find */
            return (FALSE); /* else return false */

        case CNL:            /* start-of-line */
        case CDOL:            /* end-of-line */
            if (*lp == 0)    /* found that first NUL? */
                continue;    /* yes, keep going */
            return (FALSE); /* else return false */

        case CEOF:           /* end-of-address mark */
            loc2 = lp;       /* set second loc */
            return (TRUE); /* return true */

        case CCL: /* a closure */
            c = *lp++ & 0177;
            if (ep[c >> 3] & bits[c & 07]) /* is char in set? */
            {
                ep += 16; /* then skip rest of bitmask */
                continue; /*   and keep going */
            }
            return (FALSE); /* else return false */

        case CBRA:                  /* start of tagged pattern */
            brastart[*ep++] = lp; /* mark it */
            continue;              /* and go */

        case CKET:                 /* end of tagged pattern */
            bracend[*ep++] = lp; /* mark it */
            continue;             /* and go */

        case CBACK:
            bbeg = brastart[*ep];
            ct = bracend[*ep++] - bbeg;

            if (memcmp(bbeg, lp, ct))
            {
                lp += ct;
                continue;
            }
            return (FALSE);

        case CBACK | STAR:
            bbeg = brastart[*ep];
            ct = bracend[*ep++] - bbeg;
            curlp = lp;
            while (memcmp(bbeg, lp, ct))
                lp += ct;

            while (lp >= curlp)
            {
                if (advance(lp, ep))
                    return (TRUE);
                lp -= ct;
            }
            return (FALSE);

        case CDOT | STAR: /* match .* */
            curlp = lp;      /* save closure start loc */
            while (*lp++)
                ;       /* match anything */
            goto star; /* now look for followers */

        case CCHR | STAR: /* match <literal char>* */
            curlp = lp;      /* save closure start loc */
            while (*lp++ == *ep)
                ;       /* match many of that char */
            ep++;       /* to start of next element */
            goto star; /* match it and followers */

        case CCL | STAR: /* match [...]* */
            curlp = lp;     /* save closure start loc */
            do
            {
                c = *lp++ & 0x7F; /* match any in set */
            } while (ep[c >> 3] & bits[c & 07]);
            ep += 16;  /* skip past the set */
            goto star; /* match followers */

        star:                   /* the recursion part of a * or + match */
            if (--lp == curlp) /* 0 matches */
                continue;

            if (*ep == CCHR)
            {
                c = ep[1];
                do
                {
                    if (*lp != c)
                        continue;
                    if (advance(lp, ep))
                        return (TRUE);
                } while (lp-- > curlp);
                return (FALSE);
            }

            if (*ep == CBACK)
            {
                c = *(brastart[ep[1]]);
                do
                {
                    if (*lp != c)
                        continue;
                    if (advance(lp, ep))
                        return (TRUE);
                } while (lp-- > curlp);
                return (FALSE);
            }

            do
            {
                if (lp == locs)
                    break;
                if (advance(lp, ep))
                    return (TRUE);
            } while (lp-- > curlp);
            return (FALSE);

        default:
            fprintf(stderr, "sed: RE error, %o\n", *--ep);
        }
}

static int match(expbuf, gf) /* uses genbuf */
/* match RE at expbuf against linebuf; if gf set, copy linebuf from genbuf */
char *expbuf;
{
    register char *p1, *p2, c;

    if (gf)
    {
        if (*expbuf)
            return (FALSE);
        p1 = linebuf;
        p2 = genbuf;
        while (*p1++ = *p2++)
            ;
        locs = p1 = loc2;
    }
    else
    {
        p1 = linebuf;
        locs = FALSE;
    }

    p2 = expbuf;
    if (*p2++)
    {
        loc1 = p1;
        if (*p2 == CCHR && p2[1] != *p1) /* 1st char is wrong */
            return (FALSE);                 /*   so fail */
        return (advance(p1, p2));         /* else try to match rest */
    }

    /* quick check for 1st character if it's literal */
    if (*p2 == CCHR)
    {
        c = p2[1]; /* pull out character to search for */
        do
        {
            if (*p1 != c)
                continue;         /* scan the source string */
            if (advance(p1, p2)) /* found it, match the rest */
                return (loc1 = p1, 1);
        } while (*p1++);
        return (FALSE); /* didn't find that first char */
    }

    /* else try for unanchored match of the pattern */
    do
    {
        if (advance(p1, p2))
            return (loc1 = p1, 1);
    } while (*p1++);

    /* if got here, didn't match either way */
    return (FALSE);
}

static char *place(asp, al1, al2) /* uses genbuf */
/* place chars at *al1...*(al1 - 1) at asp... in genbuf[] */
register char *asp, *al1, *al2;
{
    while (al1 < al2)
    {
        *asp++ = *al1++;
        if (asp >= genbuf + MAXBUF)
            fprintf(stderr, LTLMSG);
    }
    return (asp);
}

static void dosub(rhsbuf) /* uses linebuf, genbuf, spend */
    /* generate substituted right-hand side (of s command) */
    char *rhsbuf; /* where to put the result */
{
    register char *lp, *sp, *rp;
    int c;
    char *place();

    /* copy linebuf to genbuf up to location  1 */
    lp = linebuf;
    sp = genbuf;
    while (lp < loc1)
        *sp++ = *lp++;

    for (rp = rhsbuf; c = *rp++;)
    {
        if (c == '&')
        {
            sp = place(sp, loc1, loc2);
            continue;
        }
        else if (c & 0200 && (c &= 0177) >= '1' && c < MAXTAGS + '1')
        {
            sp = place(sp, brastart[c - '1'], bracend[c - '1']);
            continue;
        }
        *sp++ = c & 0177;
        if (sp >= genbuf + MAXBUF)
            fprintf(stderr, LTLMSG);
    }
    lp = loc2;
    loc2 = sp - genbuf + linebuf;
    while (*sp++ = *lp++)
        if (sp >= genbuf + MAXBUF)
            fprintf(stderr, LTLMSG);
    lp = linebuf;
    sp = genbuf;
    while (*lp++ = *sp++)
        ;
    spend = lp - 1;
}

static int substitute(ipc)
/* perform s command */
sedcmd *ipc; /* ptr to s command struct */
{
    void dosub(); /* for if we find a match */

    if (match(ipc->u.lhs, 0)) /* if no match */
        dosub(ipc->rhs);      /* perform it once */
    else
        return (FALSE); /* command fails */

    if (ipc->flags.global)              /* if global flag enabled */
        while (*loc2)                  /* cycle through possibles */
            if (match(ipc->u.lhs, 1)) /* found another */
                dosub(ipc->rhs);      /* so substitute */
            else                      /* otherwise, */
                break;                  /* we're done */
    return (TRUE);                      /* we succeeded */
}

static void listto(p1, fp)
    /* write a hex dump expansion of *p1... to fp */
    register char *p1; /* the source */
FILE *fp;               /* output stream to write to */
{
    p1--;
    for (; *p1++; p1 < spend)
        if (isprint(*p1))
            putc(*p1, fp); /* pass it through */
        else
        {
            putc('\\', fp); /* emit a backslash */
            switch (*p1)
            {
            case '\b':
                putc('b', fp);
                break; /* BS */
            case '\t':
                putc('t', fp);
                break; /* TAB */
            case '\n':
                putc('n', fp);
                break; /* NL */
            case '\r':
                putc('r', fp);
                break; /* CR */
            case '\33':
                putc('e', fp);
                break; /* ESC */
            default:
                fprintf(fp, "%02x", *p1 & 0xFF);
            }
        }
    putc('\n', fp);
}

static void dumpto(p1, fp)
    /* write a hex dump expansion of *p1... to fp */
    register char *p1; /* source */
FILE *fp;               /* output */
{
    p1--;
    while (*p1++, p1 < spend)
        fprintf(fp, "%02x", *p1 & 0xFF);
    fprintf(fp, "%02x", '\n' & 0xFF);
    putc('\n', fp);
}

static void readout()
/* write file indicated by r command to output */
{
    register int t; /* hold input char or EOF */
    FILE *fi;        /* ptr to file to be read */

    aptr = appends - 1; /* arrange for pre-increment to work right */
    while (*++aptr)
        if ((*aptr)->command == ACMD) /* process "a" cmd */
            printf("%s\n", (*aptr)->u.lhs);
        else /* process "r" cmd */
        {
            if ((fi = fopen((*aptr)->u.lhs, "r")) == NULL)
            {
                fprintf(stderr, "sed: can't open %s\n",
                        (*aptr)->u.lhs);
                continue;
            }
            while ((t = getc(fi)) != EOF)
                putc((char)t, stdout);
            fclose(fi);
        }
    aptr = appends; /* reset the append ptr */
    *aptr = 0;
}

static void command(ipc)
    /* execute compiled command pointed at by ipc */
    sedcmd *ipc;
{
    static char holdsp[MAXHOLD + 1]; /* the hold space */
    static char *hspend = holdsp;     /* hold space end pointer */
    register char *p1, *p2;
    char *execp;
    int didsub; /* true if last s succeeded */

    switch (ipc->command)
    {
    case ACMD: /* append */
        *aptr++ = ipc;
        if (aptr >= appends + MAXAPPENDS)
            fprintf(stderr,
                    "sed: too many appends after line %D\n",
                    lnum);
        *aptr = 0;
        break;

    case CCMD: /* change pattern space */
        delete = TRUE;
        if (!ipc->flags.inrange || lastline)
            printf("%s\n", ipc->u.lhs);
        break;

    case DCMD: /* delete pattern space */
        delete++;
        break;

    case CDCMD: /* delete a line in hold space */
        p1 = p2 = linebuf;
        while (*p1 != '\n')
            if (delete = (*p1++ == 0))
                return;
        p1++;
        while (*p2++ = *p1++)
            continue;
        spend = p2 - 1;
        jump++;
        break;

    case EQCMD: /* show current line number */
        fprintf(stdout, "%D\n", lnum);
        break;

    case GCMD: /* copy hold space to pattern space */
        p1 = linebuf;
        p2 = holdsp;
        while (*p1++ = *p2++)
            ;
        spend = p1 - 1;
        break;

    case CGCMD: /* append hold space to pattern space */
        *spend++ = '\n';
        p1 = spend;
        p2 = holdsp;
        do
            if (p1 > linebuf + MAXBUF)
            {
                truncated();
                p1[-1] = 0;
                break;
            }
        while (*p1++ = *p2++);

        spend = p1 - 1;
        break;

    case HCMD: /* copy pattern space to hold space */
        p1 = holdsp;
        p2 = linebuf;
        while (*p1++ = *p2++)
            ;
        hspend = p1 - 1;
        break;

    case CHCMD: /* append pattern space to hold space */
        *hspend++ = '\n';
        p1 = hspend;
        p2 = linebuf;
        do
            if (p1 > holdsp + MAXBUF)
            {
                truncated();
                p1[-1] = 0;
                break;
            }
        while (*p1++ = *p2++);

        hspend = p1 - 1;
        break;

    case ICMD: /* insert text */
        printf("%s\n", ipc->u.lhs);
        break;

    case BCMD: /* branch to label */
        jump = TRUE;
        break;

    case LCMD: /* list text */
        listto(linebuf, (ipc->fout != NULL) ? ipc->fout : stdout);
        break;

    case CLCMD: /* dump text */
        dumpto(linebuf, (ipc->fout != NULL) ? ipc->fout : stdout);
        break;

    case NCMD: /* read next line into pattern space */
        if (!nflag)
            puts(linebuf); /* flush out the current line */
        if (aptr > appends)
            readout(); /* do pending a, r commands */
        if ((execp = getline(linebuf)) == BAD)
        {
            delete = TRUE;
            break;
        }
        spend = execp;
        anysub = FALSE;
        break;

    case CNCMD: /* append next line to pattern space */
        if (aptr > appends)
            readout();
        *spend++ = '\n';
        if ((execp = getline(spend)) == BAD)
        {
            *--spend = 0;
            break;
        }
        spend = execp;
        anysub = FALSE;
        break;

    case PCMD: /* print pattern space */
        puts(linebuf);
        break;

    case CPCMD: /* print one line from pattern space */
    cpcom:        /* so s command can jump here */
        for (p1 = linebuf; *p1 != '\n' && *p1 != '\0';)
            putc(*p1++, stdout);
        putc('\n', stdout);
        break;

    case QCMD: /* quit the stream editor */
        if (!nflag)
            puts(linebuf); /* flush out the current line */
        if (aptr > appends)
            readout(); /* do any pending a and r commands */
        quit(0);

    case RCMD: /* read a file into the stream */
        *aptr++ = ipc;
        if (aptr >= appends + MAXAPPENDS)
            fprintf(stderr,
                    "sed: too many reads after line %D\n",
                    lnum);
        *aptr = 0;
        break;

    case SCMD: /* substitute RE */
        didsub = substitute(ipc);
        if (didsub)
            anysub = TRUE;
        if (ipc->flags.print && didsub)
            if (ipc->flags.print == TRUE)
                puts(linebuf);
            else
                goto cpcom;
        if (didsub && ipc->fout)
            fprintf(ipc->fout, "%s\n", linebuf);
        break;

    case TCMD:    /* branch on any s successful */
    case CTCMD: /* branch on any s failed */
        if (anysub == (ipc->command == CTCMD))
            break; /* no branch if any s failed, else */
        anysub = FALSE;
        jump = TRUE; /*    set up to jump to assoc'd label */
        break;

    case CWCMD: /* write one line from pattern space */
        for (p1 = linebuf; *p1 != '\n' && *p1 != '\0';)
            putc(*p1++, ipc->fout);
        putc('\n', ipc->fout);
        break;

    case WCMD: /* write pattern space to file */
        fprintf(ipc->fout, "%s\n", linebuf);
        break;

    case XCMD: /* exchange pattern and hold spaces */
        p1 = linebuf;
        p2 = genbuf;
        while (*p2++ = *p1++)
            continue;
        p1 = holdsp;
        p2 = linebuf;
        while (*p2++ = *p1++)
            continue;
        spend = p2 - 1;
        p1 = genbuf;
        p2 = holdsp;
        while (*p2++ = *p1++)
            continue;
        hspend = p2 - 1;
        break;

    case YCMD:
        p1 = linebuf;
        p2 = ipc->u.lhs;
        while (*p1 = p2[*p1])
            p1++;
        break;
    }
}

static void initget()
/* Initialise character input */
{
    if (--eargc >= 0)
        openfile(*eargv++); /* else input == stdin */
    get();
}

static int selected(ipc)
/* is current command selected */
sedcmd *ipc;
{
    register char *p1 = ipc->addr1; /* point p1 at first address */
    register char *p2 = ipc->addr2; /*   and p2 at second */
    char c;

    if (ipc->flags.inrange)
    {
        if (*p2 == CEND)
            p1 = NULL;
        else if (*p2 == CLNUM)
        {
            c = p2[1];
            if (lnum > linenum[c])
            {
                ipc->flags.inrange = FALSE;
                if (ipc->flags.allbut)
                    return (TRUE);
                ipc++;
                return (FALSE);
            }
            if (lnum == linenum[c])
                ipc->flags.inrange = FALSE;
        }
        else if (match(p2, 0))
            ipc->flags.inrange = FALSE;
    }
    else if (*p1 == CEND)
    {
        if (!lastline)
        {
            if (ipc->flags.allbut)
                return (TRUE);
            ipc++;
            return (FALSE);
        }
    }
    else if (*p1 == CLNUM)
    {
        c = p1[1];
        if (lnum != linenum[c])
        {
            if (ipc->flags.allbut)
                return (TRUE);
            ipc++;
            return (FALSE);
        }
        if (p2)
            ipc->flags.inrange = TRUE;
    }
    else if (match(p1, 0))
    {
        if (p2)
            ipc->flags.inrange = TRUE;
    }
    else
    {
        if (ipc->flags.allbut)
            return (TRUE);
        ipc++;
        return (FALSE);
    }
}

void execute()
/* execute the compiled commands in cmds[] */
{
    register char *p1;      /* dummy copy ptrs */
    register sedcmd *ipc; /* ptr to current command */
    char *execp;          /* ptr to source */
    char *getline();      /* input-getting functions */

    initget();

    /* here's the main command-execution loop */
    for (;;)
    {

        /* get next line to filter */
        if ((execp = getline(linebuf)) == BAD)
            return;
        spend = execp;
        anysub = FALSE;

        /* loop through compiled commands, executing them */
        for (ipc = cmds; ipc->command;)
        {
            if (!selected(ipc))
            {
                ipc++;
                continue;
            }
            command(ipc); /* execute the command pointed at */

            if (delete) /* if delete flag is set */
                break;    /* don't exec rest of compiled cmds */

            if (jump) /* if jump set, follow cmd's link */
            {
                jump = FALSE;
                if ((ipc = ipc->u.link) == 0)
                {
                    ipc = cmds;
                    break;
                }
            }
            else /* normal goto next command */
                ipc++;
        }
        /* we've now done all modification commands on the line */

        /* here's where the transformed line is output */
        if (!nflag && !delete)
        {
            for (p1 = linebuf; p1 < spend; p1++)
                putc(*p1, stdout);
            putc('\n', stdout);
        }

        /* if we've been set up for append, emit the text from it */
        if (aptr > appends)
            readout();

        delete = FALSE; /* clear delete flag; about to get next cmd */
    }
}

/* return TRUE if *a... == *b... for count chars, FALSE otherwise */
static int memcmp(a, b, count)
register char *a, *b;
{
    while (count--)            /* look at count characters */
        if (*a++ != *b++)    /* if any are nonequal     */
            return (FALSE); /*    return FALSE for false */
    return (TRUE);            /* compare succeeded */
}

main(argc, argv)
    /* main sequence of the stream editor */
    int argc;
char *argv[];
{
    void compile(), resolve();

    eargc = argc;        /* set local copy of argument count */
    eargv = argv;        /* set local copy of argument list */
    cmdp->addr1 = pool; /* 1st addr expand will be at pool start */
    if (eargc == 1)
        quit(0); /* exit immediately if no arguments */
    /* scan through the arguments, interpreting each one */
    while ((--eargc > 0) && (**++eargv == '-'))
        switch (eargv[0][1])
        {
        case 'e':
            eflag++;
            compile(); /* compile with e flag on */
            eflag = 0;
            continue; /* get another argument */
        case 'f':
            if (eargc-- <= 0) /* barf if no -f file */
                quit(2);
            if ((cmdf = fopen(*++eargv, "r")) == NULL)
            {
                fprintf(stderr, COCFI, *eargv);
                quit(2);
            }
            compile(); /* file is O.K., compile it */
            fclose(cmdf);
            continue; /* go back for another argument */
        case 'g':
            gflag++; /* set global flag on all s cmds */
            continue;
        case 'n':
            nflag++; /* no print except on p flag or w */
            continue;
        default:
            fprintf(stdout, UFLAG, eargv[0][1]);
            continue;
        }

    if (cmdp == cmds) /* no commands have been compiled */
    {
        eargv--;
        eargc++;
        eflag++;
        compile();
        eflag = 0;
        eargv++;
        eargc--;
    }

    if (bdepth) /* we have unbalanced squigglies */
        ABORT(TMLBR);

    lablst->address = cmdp; /* set up header of label linked list */
    resolve();                /* resolve label table indirections */
    execute();                /* execute commands */
    quit(0);                /* everything was O.K. if we got here */
}
posted @ 2025-11-05 10:52  肉肉的男朋友  阅读(4)  评论(0)    收藏  举报