~ubuntu-branches/ubuntu/natty/9base/natty

« back to all changes in this revision

Viewing changes to ed/ed.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2010-06-04 17:22:03 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20100604172203-ei85j0da495sr8ut
Tags: 1:6-1
* Adding Kai as co-maintainer.
* Merging upstream version 6.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Editor
 
3
 */
 
4
#include <u.h>
 
5
#include <libc.h>
 
6
#include <bio.h>
 
7
#include <regexp.h>
 
8
 
 
9
#undef EOF      /* stdio? */
 
10
 
 
11
enum
 
12
{
 
13
        FNSIZE  = 128,          /* file name */
 
14
        LBSIZE  = 4096,         /* max line size */
 
15
        BLKSIZE = 4096,         /* block size in temp file */
 
16
        NBLK    = 8191,         /* max size of temp file */
 
17
        ESIZE   = 256,          /* max size of reg exp */
 
18
        GBSIZE  = 256,          /* max size of global command */
 
19
        MAXSUB  = 9,            /* max number of sub reg exp */
 
20
        ESCFLG  = 0xFFFF,       /* escape Rune - user defined code */
 
21
        EOF     = -1
 
22
};
 
23
 
 
24
void    (*oldhup)(int);
 
25
void    (*oldquit)(int);
 
26
int*    addr1;
 
27
int*    addr2;
 
28
int     anymarks;
 
29
int     col;
 
30
long    count;
 
31
int*    dol;
 
32
int*    dot;
 
33
int     fchange;
 
34
char    file[FNSIZE];
 
35
Rune    genbuf[LBSIZE];
 
36
int     given;
 
37
Rune*   globp;
 
38
int     iblock;
 
39
int     ichanged;
 
40
int     io;
 
41
Biobuf  iobuf;
 
42
int     lastc;
 
43
char    line[70];
 
44
Rune*   linebp;
 
45
Rune    linebuf[LBSIZE];
 
46
int     listf;
 
47
int     listn;
 
48
Rune*   loc1;
 
49
Rune*   loc2;
 
50
int     names[26];
 
51
int     nleft;
 
52
int     oblock;
 
53
int     oflag;
 
54
Reprog  *pattern;
 
55
int     peekc;
 
56
int     pflag;
 
57
int     rescuing;
 
58
Rune    rhsbuf[LBSIZE/sizeof(Rune)];
 
59
char    savedfile[FNSIZE];
 
60
jmp_buf savej;
 
61
int     subnewa;
 
62
int     subolda;
 
63
Resub   subexp[MAXSUB];
 
64
char*   tfname;
 
65
int     tline;
 
66
int     waiting;
 
67
int     wrapp;
 
68
int*    zero;
 
69
 
 
70
char    Q[]     = "";
 
71
char    T[]     = "TMP";
 
72
char    WRERR[] = "WRITE ERROR";
 
73
int     bpagesize = 20;
 
74
char    hex[]   = "0123456789abcdef";
 
75
char*   linp    = line;
 
76
ulong   nlall = 128;
 
77
int     tfile   = -1;
 
78
int     vflag   = 1;
 
79
 
 
80
void    add(int);
 
81
int*    address(void);
 
82
int     append(int(*)(void), int*);
 
83
void    browse(void);
 
84
void    callunix(void);
 
85
void    commands(void);
 
86
void    compile(int);
 
87
int     compsub(void);
 
88
void    dosub(void);
 
89
void    error(char*);
 
90
int     match(int*);
 
91
void    exfile(int);
 
92
void    filename(int);
 
93
Rune*   getblock(int, int);
 
94
int     getchr(void);
 
95
int     getcopy(void);
 
96
int     getfile(void);
 
97
Rune*   getline(int);
 
98
int     getnum(void);
 
99
int     getsub(void);
 
100
int     gettty(void);
 
101
void    global(int);
 
102
void    init(void);
 
103
void    join(void);
 
104
void    move(int);
 
105
void    newline(void);
 
106
void    nonzero(void);
 
107
void    notifyf(void*, char*);
 
108
Rune*   place(Rune*, Rune*, Rune*);
 
109
void    printcom(void);
 
110
void    putchr(int);
 
111
void    putd(void);
 
112
void    putfile(void);
 
113
int     putline(void);
 
114
void    putshst(Rune*);
 
115
void    putst(char*);
 
116
void    quit(void);
 
117
void    rdelete(int*, int*);
 
118
void    regerror(char *);
 
119
void    reverse(int*, int*);
 
120
void    setnoaddr(void);
 
121
void    setwide(void);
 
122
void    squeeze(int);
 
123
void    substitute(int);
 
124
char*   _mktemp(char *as);
 
125
 
 
126
Rune La[] = { 'a', 0 };
 
127
Rune Lr[] = { 'r', 0 };
 
128
 
 
129
char tmp[] = "/var/tmp/eXXXXX";
 
130
 
 
131
void
 
132
main(int argc, char *argv[])
 
133
{
 
134
        char *p1, *p2;
 
135
 
 
136
        notify(notifyf);
 
137
        ARGBEGIN {
 
138
        case 'o':
 
139
                oflag = 1;
 
140
                vflag = 0;
 
141
                break;
 
142
        } ARGEND
 
143
 
 
144
        USED(argc);
 
145
        if(*argv && (strcmp(*argv, "-") == 0)) {
 
146
                argv++;
 
147
                vflag = 0;
 
148
        }
 
149
        if(oflag) {
 
150
                p1 = "/dev/stdout";
 
151
                p2 = savedfile;
 
152
                while(*p2++ = *p1++)
 
153
                        ;
 
154
                globp = La;
 
155
        } else
 
156
        if(*argv) {
 
157
                p1 = *argv;
 
158
                p2 = savedfile;
 
159
                while(*p2++ = *p1++)
 
160
                        if(p2 >= &savedfile[sizeof(savedfile)])
 
161
                                p2--;
 
162
                globp = Lr;
 
163
        }
 
164
        zero = malloc((nlall+5)*sizeof(int*));
 
165
        tfname = _mktemp(tmp);
 
166
        init();
 
167
        setjmp(savej);
 
168
        commands();
 
169
        quit();
 
170
}
 
171
 
 
172
void
 
173
commands(void)
 
174
{
 
175
        int *a1, c, temp;
 
176
        char lastsep;
 
177
        Dir *d;
 
178
 
 
179
        for(;;) {
 
180
                if(pflag) {
 
181
                        pflag = 0;
 
182
                        addr1 = addr2 = dot;
 
183
                        printcom();
 
184
                }
 
185
                c = '\n';
 
186
                for(addr1 = 0;;) {
 
187
                        lastsep = c;
 
188
                        a1 = address();
 
189
                        c = getchr();
 
190
                        if(c != ',' && c != ';')
 
191
                                break;
 
192
                        if(lastsep == ',')
 
193
                                error(Q);
 
194
                        if(a1 == 0) {
 
195
                                a1 = zero+1;
 
196
                                if(a1 > dol)
 
197
                                        a1--;
 
198
                        }
 
199
                        addr1 = a1;
 
200
                        if(c == ';')
 
201
                                dot = a1;
 
202
                }
 
203
                if(lastsep != '\n' && a1 == 0)
 
204
                        a1 = dol;
 
205
                if((addr2=a1) == 0) {
 
206
                        given = 0;
 
207
                        addr2 = dot;    
 
208
                } else
 
209
                        given = 1;
 
210
                if(addr1 == 0)
 
211
                        addr1 = addr2;
 
212
                switch(c) {
 
213
 
 
214
                case 'a':
 
215
                        add(0);
 
216
                        continue;
 
217
 
 
218
                case 'b':
 
219
                        nonzero();
 
220
                        browse();
 
221
                        continue;
 
222
 
 
223
                case 'c':
 
224
                        nonzero();
 
225
                        newline();
 
226
                        rdelete(addr1, addr2);
 
227
                        append(gettty, addr1-1);
 
228
                        continue;
 
229
 
 
230
                case 'd':
 
231
                        nonzero();
 
232
                        newline();
 
233
                        rdelete(addr1, addr2);
 
234
                        continue;
 
235
 
 
236
                case 'E':
 
237
                        fchange = 0;
 
238
                        c = 'e';
 
239
                case 'e':
 
240
                        setnoaddr();
 
241
                        if(vflag && fchange) {
 
242
                                fchange = 0;
 
243
                                error(Q);
 
244
                        }
 
245
                        filename(c);
 
246
                        init();
 
247
                        addr2 = zero;
 
248
                        goto caseread;
 
249
 
 
250
                case 'f':
 
251
                        setnoaddr();
 
252
                        filename(c);
 
253
                        putst(savedfile);
 
254
                        continue;
 
255
 
 
256
                case 'g':
 
257
                        global(1);
 
258
                        continue;
 
259
 
 
260
                case 'i':
 
261
                        add(-1);
 
262
                        continue;
 
263
 
 
264
 
 
265
                case 'j':
 
266
                        if(!given)
 
267
                                addr2++;
 
268
                        newline();
 
269
                        join();
 
270
                        continue;
 
271
 
 
272
                case 'k':
 
273
                        nonzero();
 
274
                        c = getchr();
 
275
                        if(c < 'a' || c > 'z')
 
276
                                error(Q);
 
277
                        newline();
 
278
                        names[c-'a'] = *addr2 & ~01;
 
279
                        anymarks |= 01;
 
280
                        continue;
 
281
 
 
282
                case 'm':
 
283
                        move(0);
 
284
                        continue;
 
285
 
 
286
                case 'n':
 
287
                        listn++;
 
288
                        newline();
 
289
                        printcom();
 
290
                        continue;
 
291
 
 
292
                case '\n':
 
293
                        if(a1==0) {
 
294
                                a1 = dot+1;
 
295
                                addr2 = a1;
 
296
                                addr1 = a1;
 
297
                        }
 
298
                        if(lastsep==';')
 
299
                                addr1 = a1;
 
300
                        printcom();
 
301
                        continue;
 
302
 
 
303
                case 'l':
 
304
                        listf++;
 
305
                case 'p':
 
306
                case 'P':
 
307
                        newline();
 
308
                        printcom();
 
309
                        continue;
 
310
 
 
311
                case 'Q':
 
312
                        fchange = 0;
 
313
                case 'q':
 
314
                        setnoaddr();
 
315
                        newline();
 
316
                        quit();
 
317
 
 
318
                case 'r':
 
319
                        filename(c);
 
320
                caseread:
 
321
                        if((io=open(file, OREAD)) < 0) {
 
322
                                lastc = '\n';
 
323
                                error(file);
 
324
                        }
 
325
                        if((d = dirfstat(io)) != nil){
 
326
                                if(d->mode & DMAPPEND)
 
327
                                        print("warning: %s is append only\n", file);
 
328
                                free(d);
 
329
                        }
 
330
                        Binit(&iobuf, io, OREAD);
 
331
                        setwide();
 
332
                        squeeze(0);
 
333
                        c = zero != dol;
 
334
                        append(getfile, addr2);
 
335
                        exfile(OREAD);
 
336
 
 
337
                        fchange = c;
 
338
                        continue;
 
339
 
 
340
                case 's':
 
341
                        nonzero();
 
342
                        substitute(globp != 0);
 
343
                        continue;
 
344
 
 
345
                case 't':
 
346
                        move(1);
 
347
                        continue;
 
348
 
 
349
                case 'u':
 
350
                        nonzero();
 
351
                        newline();
 
352
                        if((*addr2&~01) != subnewa)
 
353
                                error(Q);
 
354
                        *addr2 = subolda;
 
355
                        dot = addr2;
 
356
                        continue;
 
357
 
 
358
                case 'v':
 
359
                        global(0);
 
360
                        continue;
 
361
 
 
362
                case 'W':
 
363
                        wrapp++;
 
364
                case 'w':
 
365
                        setwide();
 
366
                        squeeze(dol>zero);
 
367
                        temp = getchr();
 
368
                        if(temp != 'q' && temp != 'Q') {
 
369
                                peekc = temp;
 
370
                                temp = 0;
 
371
                        }
 
372
                        filename(c);
 
373
                        if(!wrapp ||
 
374
                          ((io = open(file, OWRITE)) == -1) ||
 
375
                          ((seek(io, 0L, 2)) == -1))
 
376
                                if((io = create(file, OWRITE, 0666)) < 0)
 
377
                                        error(file);
 
378
                        Binit(&iobuf, io, OWRITE);
 
379
                        wrapp = 0;
 
380
                        if(dol > zero)
 
381
                                putfile();
 
382
                        exfile(OWRITE);
 
383
                        if(addr1<=zero+1 && addr2==dol)
 
384
                                fchange = 0;
 
385
                        if(temp == 'Q')
 
386
                                fchange = 0;
 
387
                        if(temp)
 
388
                                quit();
 
389
                        continue;
 
390
 
 
391
                case '=':
 
392
                        setwide();
 
393
                        squeeze(0);
 
394
                        newline();
 
395
                        count = addr2 - zero;
 
396
                        putd();
 
397
                        putchr('\n');
 
398
                        continue;
 
399
 
 
400
                case '!':
 
401
                        callunix();
 
402
                        continue;
 
403
 
 
404
                case EOF:
 
405
                        return;
 
406
 
 
407
                }
 
408
                error(Q);
 
409
        }
 
410
}
 
411
 
 
412
void
 
413
printcom(void)
 
414
{
 
415
        int *a1;
 
416
 
 
417
        nonzero();
 
418
        a1 = addr1;
 
419
        do {
 
420
                if(listn) {
 
421
                        count = a1-zero;
 
422
                        putd();
 
423
                        putchr('\t');
 
424
                }
 
425
                putshst(getline(*a1++));
 
426
        } while(a1 <= addr2);
 
427
        dot = addr2;
 
428
        listf = 0;
 
429
        listn = 0;
 
430
        pflag = 0;
 
431
}
 
432
 
 
433
int*
 
434
address(void)
 
435
{
 
436
        int sign, *a, opcnt, nextopand, *b, c;
 
437
 
 
438
        nextopand = -1;
 
439
        sign = 1;
 
440
        opcnt = 0;
 
441
        a = dot;
 
442
        do {
 
443
                do {
 
444
                        c = getchr();
 
445
                } while(c == ' ' || c == '\t');
 
446
                if(c >= '0' && c <= '9') {
 
447
                        peekc = c;
 
448
                        if(!opcnt)
 
449
                                a = zero;
 
450
                        a += sign*getnum();
 
451
                } else
 
452
                switch(c) {
 
453
                case '$':
 
454
                        a = dol;
 
455
                case '.':
 
456
                        if(opcnt)
 
457
                                error(Q);
 
458
                        break;
 
459
                case '\'':
 
460
                        c = getchr();
 
461
                        if(opcnt || c < 'a' || c > 'z')
 
462
                                error(Q);
 
463
                        a = zero;
 
464
                        do {
 
465
                                a++;
 
466
                        } while(a <= dol && names[c-'a'] != (*a & ~01));
 
467
                        break;
 
468
                case '?':
 
469
                        sign = -sign;
 
470
                case '/':
 
471
                        compile(c);
 
472
                        b = a;
 
473
                        for(;;) {
 
474
                                a += sign;
 
475
                                if(a <= zero)
 
476
                                        a = dol;
 
477
                                if(a > dol)
 
478
                                        a = zero;
 
479
                                if(match(a))
 
480
                                        break;
 
481
                                if(a == b)
 
482
                                        error(Q);
 
483
                        }
 
484
                        break;
 
485
                default:
 
486
                        if(nextopand == opcnt) {
 
487
                                a += sign;
 
488
                                if(a < zero || dol < a)
 
489
                                        continue;       /* error(Q); */
 
490
                        }
 
491
                        if(c != '+' && c != '-' && c != '^') {
 
492
                                peekc = c;
 
493
                                if(opcnt == 0)
 
494
                                        a = 0;
 
495
                                return a;
 
496
                        }
 
497
                        sign = 1;
 
498
                        if(c != '+')
 
499
                                sign = -sign;
 
500
                        nextopand = ++opcnt;
 
501
                        continue;
 
502
                }
 
503
                sign = 1;
 
504
                opcnt++;
 
505
        } while(zero <= a && a <= dol);
 
506
        error(Q);
 
507
        return 0;
 
508
}
 
509
 
 
510
int
 
511
getnum(void)
 
512
{
 
513
        int r, c;
 
514
 
 
515
        r = 0;
 
516
        for(;;) {
 
517
                c = getchr();
 
518
                if(c < '0' || c > '9')
 
519
                        break;
 
520
                r = r*10 + (c-'0');
 
521
        }
 
522
        peekc = c;
 
523
        return r;
 
524
}
 
525
 
 
526
void
 
527
setwide(void)
 
528
{
 
529
        if(!given) {
 
530
                addr1 = zero + (dol>zero);
 
531
                addr2 = dol;
 
532
        }
 
533
}
 
534
 
 
535
void
 
536
setnoaddr(void)
 
537
{
 
538
        if(given)
 
539
                error(Q);
 
540
}
 
541
 
 
542
void
 
543
nonzero(void)
 
544
{
 
545
        squeeze(1);
 
546
}
 
547
 
 
548
void
 
549
squeeze(int i)
 
550
{
 
551
        if(addr1 < zero+i || addr2 > dol || addr1 > addr2)
 
552
                error(Q);
 
553
}
 
554
 
 
555
void
 
556
newline(void)
 
557
{
 
558
        int c;
 
559
 
 
560
        c = getchr();
 
561
        if(c == '\n' || c == EOF)
 
562
                return;
 
563
        if(c == 'p' || c == 'l' || c == 'n') {
 
564
                pflag++;
 
565
                if(c == 'l')
 
566
                        listf++;
 
567
                else
 
568
                if(c == 'n')
 
569
                        listn++;
 
570
                c = getchr();
 
571
                if(c == '\n')
 
572
                        return;
 
573
        }
 
574
        error(Q);
 
575
}
 
576
 
 
577
void
 
578
filename(int comm)
 
579
{
 
580
        char *p1, *p2;
 
581
        Rune rune;
 
582
        int c;
 
583
 
 
584
        count = 0;
 
585
        c = getchr();
 
586
        if(c == '\n' || c == EOF) {
 
587
                p1 = savedfile;
 
588
                if(*p1 == 0 && comm != 'f')
 
589
                        error(Q);
 
590
                p2 = file;
 
591
                while(*p2++ = *p1++)
 
592
                        ;
 
593
                return;
 
594
        }
 
595
        if(c != ' ')
 
596
                error(Q);
 
597
        while((c=getchr()) == ' ')
 
598
                ;
 
599
        if(c == '\n')
 
600
                error(Q);
 
601
        p1 = file;
 
602
        do {
 
603
                if(p1 >= &file[sizeof(file)-6] || c == ' ' || c == EOF)
 
604
                        error(Q);
 
605
                rune = c;
 
606
                p1 += runetochar(p1, &rune);
 
607
        } while((c=getchr()) != '\n');
 
608
        *p1 = 0;
 
609
        if(savedfile[0] == 0 || comm == 'e' || comm == 'f') {
 
610
                p1 = savedfile;
 
611
                p2 = file;
 
612
                while(*p1++ = *p2++)
 
613
                        ;
 
614
        }
 
615
}
 
616
 
 
617
void
 
618
exfile(int om)
 
619
{
 
620
 
 
621
        if(om == OWRITE)
 
622
                if(Bflush(&iobuf) < 0)
 
623
                        error(Q);
 
624
        close(io);
 
625
        io = -1;
 
626
        if(vflag) {
 
627
                putd();
 
628
                putchr('\n');
 
629
        }
 
630
}
 
631
 
 
632
void
 
633
error1(char *s)
 
634
{
 
635
        int c;
 
636
 
 
637
        wrapp = 0;
 
638
        listf = 0;
 
639
        listn = 0;
 
640
        count = 0;
 
641
        seek(0, 0, 2);
 
642
        pflag = 0;
 
643
        if(globp)
 
644
                lastc = '\n';
 
645
        globp = 0;
 
646
        peekc = lastc;
 
647
        if(lastc)
 
648
                for(;;) {
 
649
                        c = getchr();
 
650
                        if(c == '\n' || c == EOF)
 
651
                                break;
 
652
                }
 
653
        if(io > 0) {
 
654
                close(io);
 
655
                io = -1;
 
656
        }
 
657
        putchr('?');
 
658
        putst(s);
 
659
}
 
660
 
 
661
void
 
662
error(char *s)
 
663
{
 
664
        error1(s);
 
665
        longjmp(savej, 1);
 
666
}
 
667
 
 
668
void
 
669
rescue(void)
 
670
{
 
671
        rescuing = 1;
 
672
        if(dol > zero) {
 
673
                addr1 = zero+1;
 
674
                addr2 = dol;
 
675
                io = create("ed.hup", OWRITE, 0666);
 
676
                if(io > 0){
 
677
                        Binit(&iobuf, io, OWRITE);
 
678
                        putfile();
 
679
                }
 
680
        }
 
681
        fchange = 0;
 
682
        quit();
 
683
}
 
684
 
 
685
void
 
686
notifyf(void *a, char *s)
 
687
{
 
688
        if(strcmp(s, "interrupt") == 0){
 
689
                if(rescuing || waiting)
 
690
                        noted(NCONT);
 
691
                putchr('\n');
 
692
                lastc = '\n';
 
693
                error1(Q);
 
694
                notejmp(a, savej, 0);
 
695
        }
 
696
        if(strcmp(s, "hangup") == 0 || strcmp(s, "kill") == 0){
 
697
                if(rescuing)
 
698
                        noted(NDFLT);
 
699
                rescue();
 
700
        }
 
701
        if(strstr(s, "child"))
 
702
                noted(NCONT);
 
703
        fprint(2, "ed: note: %s\n", s);
 
704
        abort();
 
705
}
 
706
 
 
707
int
 
708
getchr(void)
 
709
{
 
710
        char s[UTFmax];
 
711
        int i;
 
712
        Rune r;
 
713
 
 
714
        if(lastc = peekc) {
 
715
                peekc = 0;
 
716
                return lastc;
 
717
        }
 
718
        if(globp) {
 
719
                if((lastc=*globp++) != 0)
 
720
                        return lastc;
 
721
                globp = 0;
 
722
                return EOF;
 
723
        }
 
724
        for(i=0;;) {
 
725
                if(read(0, s+i, 1) <= 0)
 
726
                        return lastc = EOF;
 
727
                i++;
 
728
                if(fullrune(s, i))
 
729
                        break;
 
730
                
 
731
        }
 
732
        chartorune(&r, s);
 
733
        lastc = r;
 
734
        return lastc;
 
735
}
 
736
 
 
737
int
 
738
gety(void)
 
739
{
 
740
        int c;
 
741
        Rune *gf, *p;
 
742
 
 
743
        p = linebuf;
 
744
        gf = globp;
 
745
        for(;;) {
 
746
                c = getchr();
 
747
                if(c == '\n') {
 
748
                        *p = 0;
 
749
                        return 0;
 
750
                }
 
751
                if(c == EOF) {
 
752
                        if(gf)
 
753
                                peekc = c;
 
754
                        return c;
 
755
                }
 
756
                if(c == 0)
 
757
                        continue;
 
758
                *p++ = c;
 
759
                if(p >= &linebuf[LBSIZE-2])
 
760
                        error(Q);
 
761
        }
 
762
}
 
763
 
 
764
int
 
765
gettty(void)
 
766
{
 
767
        int rc;
 
768
 
 
769
        rc = gety();
 
770
        if(rc)
 
771
                return rc;
 
772
        if(linebuf[0] == '.' && linebuf[1] == 0)
 
773
                return EOF;
 
774
        return 0;
 
775
}
 
776
 
 
777
int
 
778
getfile(void)
 
779
{
 
780
        int c;
 
781
        Rune *lp;
 
782
 
 
783
        lp = linebuf;
 
784
        do {
 
785
                c = Bgetrune(&iobuf);
 
786
                if(c < 0) {
 
787
                        if(lp > linebuf) {
 
788
                                putst("'\\n' appended");
 
789
                                c = '\n';
 
790
                        } else
 
791
                                return EOF;
 
792
                }
 
793
                if(lp >= &linebuf[LBSIZE]) {
 
794
                        lastc = '\n';
 
795
                        error(Q);
 
796
                }
 
797
                *lp++ = c;
 
798
                count++;
 
799
        } while(c != '\n');
 
800
        lp[-1] = 0;
 
801
        return 0;
 
802
}
 
803
 
 
804
void
 
805
putfile(void)
 
806
{
 
807
        int *a1;
 
808
        Rune *lp;
 
809
        long c;
 
810
 
 
811
        a1 = addr1;
 
812
        do {
 
813
                lp = getline(*a1++);
 
814
                for(;;) {
 
815
                        count++;
 
816
                        c = *lp++;
 
817
                        if(c == 0) {
 
818
                                if(Bputrune(&iobuf, '\n') < 0)
 
819
                                        error(Q);
 
820
                                break;
 
821
                        }
 
822
                        if(Bputrune(&iobuf, c) < 0)
 
823
                                error(Q);
 
824
                }
 
825
        } while(a1 <= addr2);
 
826
        if(Bflush(&iobuf) < 0)
 
827
                error(Q);
 
828
}
 
829
 
 
830
int
 
831
append(int (*f)(void), int *a)
 
832
{
 
833
        int *a1, *a2, *rdot, nline, d;
 
834
 
 
835
        nline = 0;
 
836
        dot = a;
 
837
        while((*f)() == 0) {
 
838
                if((dol-zero) >= nlall) {
 
839
                        nlall += 512;
 
840
                        a1 = realloc(zero, (nlall+50)*sizeof(int*));
 
841
                        if(a1 == 0) {
 
842
                                error("MEM?");
 
843
                                rescue();
 
844
                        }
 
845
                        /* relocate pointers; avoid wraparound if sizeof(int) < sizeof(int*) */
 
846
                        d = addr1 - zero;
 
847
                        addr1 = a1 + d;
 
848
                        d = addr2 - zero;
 
849
                        addr2 = a1 + d;
 
850
                        d = dol - zero;
 
851
                        dol = a1 + d;
 
852
                        d = dot - zero;
 
853
                        dot = a1 + d;
 
854
                        zero = a1;
 
855
                }
 
856
                d = putline();
 
857
                nline++;
 
858
                a1 = ++dol;
 
859
                a2 = a1+1;
 
860
                rdot = ++dot;
 
861
                while(a1 > rdot)
 
862
                        *--a2 = *--a1;
 
863
                *rdot = d;
 
864
        }
 
865
        return nline;
 
866
}
 
867
 
 
868
void
 
869
add(int i)
 
870
{
 
871
        if(i && (given || dol > zero)) {
 
872
                addr1--;
 
873
                addr2--;
 
874
        }
 
875
        squeeze(0);
 
876
        newline();
 
877
        append(gettty, addr2);
 
878
}
 
879
 
 
880
void
 
881
browse(void)
 
882
{
 
883
        int forward, n;
 
884
        static int bformat, bnum; /* 0 */
 
885
 
 
886
        forward = 1;
 
887
        peekc = getchr();
 
888
        if(peekc != '\n'){
 
889
                if(peekc == '-' || peekc == '+') {
 
890
                        if(peekc == '-')
 
891
                                forward = 0;
 
892
                        getchr();
 
893
                }
 
894
                n = getnum();
 
895
                if(n > 0)
 
896
                        bpagesize = n;
 
897
        }
 
898
        newline();
 
899
        if(pflag) {
 
900
                bformat = listf;
 
901
                bnum = listn;
 
902
        } else {
 
903
                listf = bformat;
 
904
                listn = bnum;
 
905
        }
 
906
        if(forward) {
 
907
                addr1 = addr2;
 
908
                addr2 += bpagesize;
 
909
                if(addr2 > dol)
 
910
                        addr2 = dol;
 
911
        } else {
 
912
                addr1 = addr2-bpagesize;
 
913
                if(addr1 <= zero)
 
914
                        addr1 = zero+1;
 
915
        }
 
916
        printcom();
 
917
}
 
918
 
 
919
void
 
920
callunix(void)
 
921
{
 
922
        int c, pid;
 
923
        Rune rune;
 
924
        char buf[512];
 
925
        char *p;
 
926
 
 
927
        setnoaddr();
 
928
        p = buf;
 
929
        while((c=getchr()) != EOF && c != '\n')
 
930
                if(p < &buf[sizeof(buf) - 6]) {
 
931
                        rune = c;
 
932
                        p += runetochar(p, &rune);
 
933
                }
 
934
        *p = 0;
 
935
        pid = fork();
 
936
        if(pid == 0) {
 
937
                execlp("rc", "rc", "-c", buf, (char*)0);
 
938
                sysfatal("exec failed: %r");
 
939
                exits("execl failed");
 
940
        }
 
941
        waiting = 1;
 
942
        while(waitpid() != pid)
 
943
                ;
 
944
        waiting = 0;
 
945
        if(vflag)
 
946
                putst("!");
 
947
}
 
948
 
 
949
void
 
950
quit(void)
 
951
{
 
952
        if(vflag && fchange && dol!=zero) {
 
953
                fchange = 0;
 
954
                error(Q);
 
955
        }
 
956
        remove(tfname);
 
957
        exits(0);
 
958
}
 
959
 
 
960
void
 
961
onquit(int sig)
 
962
{
 
963
        USED(sig);
 
964
        quit();
 
965
}
 
966
 
 
967
void
 
968
rdelete(int *ad1, int *ad2)
 
969
{
 
970
        int *a1, *a2, *a3;
 
971
 
 
972
        a1 = ad1;
 
973
        a2 = ad2+1;
 
974
        a3 = dol;
 
975
        dol -= a2 - a1;
 
976
        do {
 
977
                *a1++ = *a2++;
 
978
        } while(a2 <= a3);
 
979
        a1 = ad1;
 
980
        if(a1 > dol)
 
981
                a1 = dol;
 
982
        dot = a1;
 
983
        fchange = 1;
 
984
}
 
985
 
 
986
void
 
987
gdelete(void)
 
988
{
 
989
        int *a1, *a2, *a3;
 
990
 
 
991
        a3 = dol;
 
992
        for(a1=zero; (*a1&01)==0; a1++)
 
993
                if(a1>=a3)
 
994
                        return;
 
995
        for(a2=a1+1; a2<=a3;) {
 
996
                if(*a2 & 01) {
 
997
                        a2++;
 
998
                        dot = a1;
 
999
                } else
 
1000
                        *a1++ = *a2++;
 
1001
        }
 
1002
        dol = a1-1;
 
1003
        if(dot > dol)
 
1004
                dot = dol;
 
1005
        fchange = 1;
 
1006
}
 
1007
 
 
1008
Rune*
 
1009
getline(int tl)
 
1010
{
 
1011
        Rune *lp, *bp;
 
1012
        int nl;
 
1013
 
 
1014
        lp = linebuf;
 
1015
        bp = getblock(tl, OREAD);
 
1016
        nl = nleft;
 
1017
        tl &= ~((BLKSIZE/sizeof(Rune)) - 1);
 
1018
        while(*lp++ = *bp++) {
 
1019
                nl -= sizeof(Rune);
 
1020
                if(nl == 0) {
 
1021
                        bp = getblock(tl += BLKSIZE/sizeof(Rune), OREAD);
 
1022
                        nl = nleft;
 
1023
                }
 
1024
        }
 
1025
        return linebuf;
 
1026
}
 
1027
 
 
1028
int
 
1029
putline(void)
 
1030
{
 
1031
        Rune *lp, *bp;
 
1032
        int nl, tl;
 
1033
 
 
1034
        fchange = 1;
 
1035
        lp = linebuf;
 
1036
        tl = tline;
 
1037
        bp = getblock(tl, OWRITE);
 
1038
        nl = nleft;
 
1039
        tl &= ~((BLKSIZE/sizeof(Rune))-1);
 
1040
        while(*bp = *lp++) {
 
1041
                if(*bp++ == '\n') {
 
1042
                        bp[-1] = 0;
 
1043
                        linebp = lp;
 
1044
                        break;
 
1045
                }
 
1046
                nl -= sizeof(Rune);
 
1047
                if(nl == 0) {
 
1048
                        tl += BLKSIZE/sizeof(Rune);
 
1049
                        bp = getblock(tl, OWRITE);
 
1050
                        nl = nleft;
 
1051
                }
 
1052
        }
 
1053
        nl = tline;
 
1054
        tline += ((lp-linebuf) + 03) & 077776;
 
1055
        return nl;
 
1056
}
 
1057
 
 
1058
void
 
1059
blkio(int b, uchar *buf, int isread)
 
1060
{
 
1061
        int n;
 
1062
 
 
1063
        seek(tfile, b*BLKSIZE, 0);
 
1064
        if(isread)
 
1065
                n = read(tfile, buf, BLKSIZE);
 
1066
        else
 
1067
                n = write(tfile, buf, BLKSIZE);
 
1068
        if(n != BLKSIZE)
 
1069
                error(T);
 
1070
}
 
1071
 
 
1072
Rune*
 
1073
getblock(int atl, int iof)
 
1074
{
 
1075
        int bno, off;
 
1076
        
 
1077
        static uchar ibuff[BLKSIZE];
 
1078
        static uchar obuff[BLKSIZE];
 
1079
 
 
1080
        bno = atl / (BLKSIZE/sizeof(Rune));
 
1081
        off = (atl*sizeof(Rune)) & (BLKSIZE-1) & ~03;
 
1082
        if(bno >= NBLK) {
 
1083
                lastc = '\n';
 
1084
                error(T);
 
1085
        }
 
1086
        nleft = BLKSIZE - off;
 
1087
        if(bno == iblock) {
 
1088
                ichanged |= iof;
 
1089
                return (Rune*)(ibuff+off);
 
1090
        }
 
1091
        if(bno == oblock)
 
1092
                return (Rune*)(obuff+off);
 
1093
        if(iof == OREAD) {
 
1094
                if(ichanged)
 
1095
                        blkio(iblock, ibuff, 0);
 
1096
                ichanged = 0;
 
1097
                iblock = bno;
 
1098
                blkio(bno, ibuff, 1);
 
1099
                return (Rune*)(ibuff+off);
 
1100
        }
 
1101
        if(oblock >= 0)
 
1102
                blkio(oblock, obuff, 0);
 
1103
        oblock = bno;
 
1104
        return (Rune*)(obuff+off);
 
1105
}
 
1106
 
 
1107
void
 
1108
init(void)
 
1109
{
 
1110
        int *markp;
 
1111
 
 
1112
        close(tfile);
 
1113
        tline = 2;
 
1114
        for(markp = names; markp < &names[26]; )
 
1115
                *markp++ = 0;
 
1116
        subnewa = 0;
 
1117
        anymarks = 0;
 
1118
        iblock = -1;
 
1119
        oblock = -1;
 
1120
        ichanged = 0;
 
1121
        if((tfile = create(tfname, ORDWR, 0600)) < 0){
 
1122
                error1(T);
 
1123
                exits(0);
 
1124
        }
 
1125
        dot = dol = zero;
 
1126
}
 
1127
 
 
1128
void
 
1129
global(int k)
 
1130
{
 
1131
        Rune *gp, globuf[GBSIZE];
 
1132
        int c, *a1;
 
1133
 
 
1134
        if(globp)
 
1135
                error(Q);
 
1136
        setwide();
 
1137
        squeeze(dol > zero);
 
1138
        c = getchr();
 
1139
        if(c == '\n')
 
1140
                error(Q);
 
1141
        compile(c);
 
1142
        gp = globuf;
 
1143
        while((c=getchr()) != '\n') {
 
1144
                if(c == EOF)
 
1145
                        error(Q);
 
1146
                if(c == '\\') {
 
1147
                        c = getchr();
 
1148
                        if(c != '\n')
 
1149
                                *gp++ = '\\';
 
1150
                }
 
1151
                *gp++ = c;
 
1152
                if(gp >= &globuf[GBSIZE-2])
 
1153
                        error(Q);
 
1154
        }
 
1155
        if(gp == globuf)
 
1156
                *gp++ = 'p';
 
1157
        *gp++ = '\n';
 
1158
        *gp = 0;
 
1159
        for(a1=zero; a1<=dol; a1++) {
 
1160
                *a1 &= ~01;
 
1161
                if(a1 >= addr1 && a1 <= addr2 && match(a1) == k)
 
1162
                        *a1 |= 01;
 
1163
        }
 
1164
 
 
1165
        /*
 
1166
         * Special case: g/.../d (avoid n^2 algorithm)
 
1167
         */
 
1168
        if(globuf[0] == 'd' && globuf[1] == '\n' && globuf[2] == 0) {
 
1169
                gdelete();
 
1170
                return;
 
1171
        }
 
1172
        for(a1=zero; a1<=dol; a1++) {
 
1173
                if(*a1 & 01) {
 
1174
                        *a1 &= ~01;
 
1175
                        dot = a1;
 
1176
                        globp = globuf;
 
1177
                        commands();
 
1178
                        a1 = zero;
 
1179
                }
 
1180
        }
 
1181
}
 
1182
 
 
1183
void
 
1184
join(void)
 
1185
{
 
1186
        Rune *gp, *lp;
 
1187
        int *a1;
 
1188
 
 
1189
        nonzero();
 
1190
        gp = genbuf;
 
1191
        for(a1=addr1; a1<=addr2; a1++) {
 
1192
                lp = getline(*a1);
 
1193
                while(*gp = *lp++)
 
1194
                        if(gp++ >= &genbuf[LBSIZE-2])
 
1195
                                error(Q);
 
1196
        }
 
1197
        lp = linebuf;
 
1198
        gp = genbuf;
 
1199
        while(*lp++ = *gp++)
 
1200
                ;
 
1201
        *addr1 = putline();
 
1202
        if(addr1 < addr2)
 
1203
                rdelete(addr1+1, addr2);
 
1204
        dot = addr1;
 
1205
}
 
1206
 
 
1207
void
 
1208
substitute(int inglob)
 
1209
{
 
1210
        int *mp, *a1, nl, gsubf, n;
 
1211
 
 
1212
        n = getnum();   /* OK even if n==0 */
 
1213
        gsubf = compsub();
 
1214
        for(a1 = addr1; a1 <= addr2; a1++) {
 
1215
                if(match(a1)){
 
1216
                        int *ozero;
 
1217
                        int m = n;
 
1218
 
 
1219
                        do {
 
1220
                                int span = loc2-loc1;
 
1221
 
 
1222
                                if(--m <= 0) {
 
1223
                                        dosub();
 
1224
                                        if(!gsubf)
 
1225
                                                break;
 
1226
                                        if(span == 0) { /* null RE match */
 
1227
                                                if(*loc2 == 0)
 
1228
                                                        break;
 
1229
                                                loc2++;
 
1230
                                        }
 
1231
                                }
 
1232
                        } while(match(0));
 
1233
                        if(m <= 0) {
 
1234
                                inglob |= 01;
 
1235
                                subnewa = putline();
 
1236
                                *a1 &= ~01;
 
1237
                                if(anymarks) {
 
1238
                                        for(mp=names; mp<&names[26]; mp++)
 
1239
                                                if(*mp == *a1)
 
1240
                                                        *mp = subnewa;
 
1241
                                }
 
1242
                                subolda = *a1;
 
1243
                                *a1 = subnewa;
 
1244
                                ozero = zero;
 
1245
                                nl = append(getsub, a1);
 
1246
                                addr2 += nl;
 
1247
                                nl += zero-ozero;
 
1248
                                a1 += nl;
 
1249
                        }
 
1250
                }
 
1251
        }
 
1252
        if(inglob == 0)
 
1253
                error(Q);
 
1254
}
 
1255
 
 
1256
int
 
1257
compsub(void)
 
1258
{
 
1259
        int seof, c;
 
1260
        Rune *p;
 
1261
 
 
1262
        seof = getchr();
 
1263
        if(seof == '\n' || seof == ' ')
 
1264
                error(Q);
 
1265
        compile(seof);
 
1266
        p = rhsbuf;
 
1267
        for(;;) {
 
1268
                c = getchr();
 
1269
                if(c == '\\') {
 
1270
                        c = getchr();
 
1271
                        *p++ = ESCFLG;
 
1272
                        if(p >= &rhsbuf[LBSIZE/sizeof(Rune)])
 
1273
                                error(Q);
 
1274
                } else
 
1275
                if(c == '\n' && (!globp || !globp[0])) {
 
1276
                        peekc = c;
 
1277
                        pflag++;
 
1278
                        break;
 
1279
                } else
 
1280
                if(c == seof)
 
1281
                        break;
 
1282
                *p++ = c;
 
1283
                if(p >= &rhsbuf[LBSIZE/sizeof(Rune)])
 
1284
                        error(Q);
 
1285
        }
 
1286
        *p = 0;
 
1287
        peekc = getchr();
 
1288
        if(peekc == 'g') {
 
1289
                peekc = 0;
 
1290
                newline();
 
1291
                return 1;
 
1292
        }
 
1293
        newline();
 
1294
        return 0;
 
1295
}
 
1296
 
 
1297
int
 
1298
getsub(void)
 
1299
{
 
1300
        Rune *p1, *p2;
 
1301
 
 
1302
        p1 = linebuf;
 
1303
        if((p2 = linebp) == 0)
 
1304
                return EOF;
 
1305
        while(*p1++ = *p2++)
 
1306
                ;
 
1307
        linebp = 0;
 
1308
        return 0;
 
1309
}
 
1310
 
 
1311
void
 
1312
dosub(void)
 
1313
{
 
1314
        Rune *lp, *sp, *rp;
 
1315
        int c, n;
 
1316
 
 
1317
        lp = linebuf;
 
1318
        sp = genbuf;
 
1319
        rp = rhsbuf;
 
1320
        while(lp < loc1)
 
1321
                *sp++ = *lp++;
 
1322
        while(c = *rp++) {
 
1323
                if(c == '&'){
 
1324
                        sp = place(sp, loc1, loc2);
 
1325
                        continue;
 
1326
                }
 
1327
                if(c == ESCFLG && (c = *rp++) >= '1' && c < MAXSUB+'0') {
 
1328
                        n = c-'0';
 
1329
                        if(subexp[n].s.rsp && subexp[n].e.rep) {
 
1330
                                sp = place(sp, subexp[n].s.rsp, subexp[n].e.rep);
 
1331
                                continue;
 
1332
                        }
 
1333
                        error(Q);
 
1334
                }
 
1335
                *sp++ = c;
 
1336
                if(sp >= &genbuf[LBSIZE])
 
1337
                        error(Q);
 
1338
        }
 
1339
        lp = loc2;
 
1340
        loc2 = sp - genbuf + linebuf;
 
1341
        while(*sp++ = *lp++)
 
1342
                if(sp >= &genbuf[LBSIZE])
 
1343
                        error(Q);
 
1344
        lp = linebuf;
 
1345
        sp = genbuf;
 
1346
        while(*lp++ = *sp++)
 
1347
                ;
 
1348
}
 
1349
 
 
1350
Rune*
 
1351
place(Rune *sp, Rune *l1, Rune *l2)
 
1352
{
 
1353
 
 
1354
        while(l1 < l2) {
 
1355
                *sp++ = *l1++;
 
1356
                if(sp >= &genbuf[LBSIZE])
 
1357
                        error(Q);
 
1358
        }
 
1359
        return sp;
 
1360
}
 
1361
 
 
1362
void
 
1363
move(int cflag)
 
1364
{
 
1365
        int *adt, *ad1, *ad2;
 
1366
 
 
1367
        nonzero();
 
1368
        if((adt = address())==0)        /* address() guarantees addr is in range */
 
1369
                error(Q);
 
1370
        newline();
 
1371
        if(cflag) {
 
1372
                int *ozero, delta;
 
1373
                ad1 = dol;
 
1374
                ozero = zero;
 
1375
                append(getcopy, ad1++);
 
1376
                ad2 = dol;
 
1377
                delta = zero - ozero;
 
1378
                ad1 += delta;
 
1379
                adt += delta;
 
1380
        } else {
 
1381
                ad2 = addr2;
 
1382
                for(ad1 = addr1; ad1 <= ad2;)
 
1383
                        *ad1++ &= ~01;
 
1384
                ad1 = addr1;
 
1385
        }
 
1386
        ad2++;
 
1387
        if(adt<ad1) {
 
1388
                dot = adt + (ad2-ad1);
 
1389
                if((++adt)==ad1)
 
1390
                        return;
 
1391
                reverse(adt, ad1);
 
1392
                reverse(ad1, ad2);
 
1393
                reverse(adt, ad2);
 
1394
        } else
 
1395
        if(adt >= ad2) {
 
1396
                dot = adt++;
 
1397
                reverse(ad1, ad2);
 
1398
                reverse(ad2, adt);
 
1399
                reverse(ad1, adt);
 
1400
        } else
 
1401
                error(Q);
 
1402
        fchange = 1;
 
1403
}
 
1404
 
 
1405
void
 
1406
reverse(int *a1, int *a2)
 
1407
{
 
1408
        int t;
 
1409
 
 
1410
        for(;;) {
 
1411
                t = *--a2;
 
1412
                if(a2 <= a1)
 
1413
                        return;
 
1414
                *a2 = *a1;
 
1415
                *a1++ = t;
 
1416
        }
 
1417
}
 
1418
 
 
1419
int
 
1420
getcopy(void)
 
1421
{
 
1422
        if(addr1 > addr2)
 
1423
                return EOF;
 
1424
        getline(*addr1++);
 
1425
        return 0;
 
1426
}
 
1427
 
 
1428
void
 
1429
compile(int eof)
 
1430
{
 
1431
        Rune c;
 
1432
        char *ep;
 
1433
        char expbuf[ESIZE];
 
1434
 
 
1435
        if((c = getchr()) == '\n') {
 
1436
                peekc = c;
 
1437
                c = eof;
 
1438
        }
 
1439
        if(c == eof) {
 
1440
                if(!pattern)
 
1441
                        error(Q);
 
1442
                return;
 
1443
        }
 
1444
        if(pattern) {
 
1445
                free(pattern);
 
1446
                pattern = 0;
 
1447
        }
 
1448
        ep = expbuf;
 
1449
        do {
 
1450
                if(c == '\\') {
 
1451
                        if(ep >= expbuf+sizeof(expbuf)) {
 
1452
                                error(Q);
 
1453
                                return;
 
1454
                        }
 
1455
                        ep += runetochar(ep, &c);
 
1456
                        if((c = getchr()) == '\n') {
 
1457
                                error(Q);
 
1458
                                return;
 
1459
                        }
 
1460
                }
 
1461
                if(ep >= expbuf+sizeof(expbuf)) {
 
1462
                        error(Q);
 
1463
                        return;
 
1464
                }
 
1465
                ep += runetochar(ep, &c);
 
1466
        } while((c = getchr()) != eof && c != '\n');
 
1467
        if(c == '\n')
 
1468
                peekc = c;
 
1469
        *ep = 0;
 
1470
        pattern = regcomp(expbuf);
 
1471
}
 
1472
 
 
1473
int
 
1474
match(int *addr)
 
1475
{
 
1476
        if(!pattern)
 
1477
                return 0;
 
1478
        if(addr){
 
1479
                if(addr == zero)
 
1480
                        return 0;
 
1481
                subexp[0].s.rsp = getline(*addr);
 
1482
        } else
 
1483
                subexp[0].s.rsp = loc2;
 
1484
        subexp[0].e.rep = 0;
 
1485
        if(rregexec(pattern, linebuf, subexp, MAXSUB)) {
 
1486
                loc1 = subexp[0].s.rsp;
 
1487
                loc2 = subexp[0].e.rep;
 
1488
                return 1;
 
1489
        }
 
1490
        loc1 = loc2 = 0;
 
1491
        return 0;
 
1492
        
 
1493
}
 
1494
 
 
1495
void
 
1496
putd(void)
 
1497
{
 
1498
        int r;
 
1499
 
 
1500
        r = count%10;
 
1501
        count /= 10;
 
1502
        if(count)
 
1503
                putd();
 
1504
        putchr(r + '0');
 
1505
}
 
1506
 
 
1507
void
 
1508
putst(char *sp)
 
1509
{
 
1510
        Rune r;
 
1511
 
 
1512
        col = 0;
 
1513
        for(;;) {
 
1514
                sp += chartorune(&r, sp);
 
1515
                if(r == 0)
 
1516
                        break;
 
1517
                putchr(r);
 
1518
        }
 
1519
        putchr('\n');
 
1520
}
 
1521
 
 
1522
void
 
1523
putshst(Rune *sp)
 
1524
{
 
1525
        col = 0;
 
1526
        while(*sp)
 
1527
                putchr(*sp++);
 
1528
        putchr('\n');
 
1529
}
 
1530
 
 
1531
void
 
1532
putchr(int ac)
 
1533
{
 
1534
        char *lp;
 
1535
        int c;
 
1536
        Rune rune;
 
1537
 
 
1538
        lp = linp;
 
1539
        c = ac;
 
1540
        if(listf) {
 
1541
                if(c == '\n') {
 
1542
                        if(linp != line && linp[-1] == ' ') {
 
1543
                                *lp++ = '\\';
 
1544
                                *lp++ = 'n';
 
1545
                        }
 
1546
                } else {
 
1547
                        if(col > (72-6-2)) {
 
1548
                                col = 8;
 
1549
                                *lp++ = '\\';
 
1550
                                *lp++ = '\n';
 
1551
                                *lp++ = '\t';
 
1552
                        }
 
1553
                        col++;
 
1554
                        if(c=='\b' || c=='\t' || c=='\\') {
 
1555
                                *lp++ = '\\';
 
1556
                                if(c == '\b')
 
1557
                                        c = 'b';
 
1558
                                else
 
1559
                                if(c == '\t')
 
1560
                                        c = 't';
 
1561
                                col++;
 
1562
                        } else
 
1563
                        if(c<' ' || c>='\177') {
 
1564
                                *lp++ = '\\';
 
1565
                                *lp++ = 'x';
 
1566
                                *lp++ =  hex[c>>12];
 
1567
                                *lp++ =  hex[c>>8&0xF];
 
1568
                                *lp++ =  hex[c>>4&0xF];
 
1569
                                c     =  hex[c&0xF];
 
1570
                                col += 5;
 
1571
                        }
 
1572
                }
 
1573
        }
 
1574
 
 
1575
        rune = c;
 
1576
        lp += runetochar(lp, &rune);
 
1577
 
 
1578
        if(c == '\n' || lp >= &line[sizeof(line)-5]) {
 
1579
                linp = line;
 
1580
                write(oflag? 2: 1, line, lp-line);
 
1581
                return;
 
1582
        }
 
1583
        linp = lp;
 
1584
}
 
1585
 
 
1586
char*
 
1587
_mktemp(char *as)
 
1588
{
 
1589
        char *s;
 
1590
        unsigned pid;
 
1591
        int i;
 
1592
 
 
1593
        pid = getpid();
 
1594
        s = as;
 
1595
        while(*s++)
 
1596
                ;
 
1597
        s--;
 
1598
        while(*--s == 'X') {
 
1599
                *s = pid % 10 + '0';
 
1600
                pid /= 10;
 
1601
        }
 
1602
        s++;
 
1603
        i = 'a';
 
1604
        while(access(as, 0) != -1) {
 
1605
                if(i == 'z')
 
1606
                        return "/";
 
1607
                *s = i++;
 
1608
        }
 
1609
        return as;
 
1610
}
 
1611
 
 
1612
void
 
1613
regerror(char *s)
 
1614
{
 
1615
        USED(s);
 
1616
        error(Q);
 
1617
}