Annotation of researchv9/jtools/src/sam/sam.c, revision 1.1.1.1

1.1       root        1: #include "sam.h"
                      2: #include <setjmp.h>
                      3: #include <signal.h>
                      4: 
                      5: typedef struct Patlist{
                      6:        int     nalloc;
                      7:        int     nused;
                      8:        String  **ptr;
                      9: }Patlist;
                     10: 
                     11: uchar  genbuf[BLOCKSIZE];
                     12: char   *home;
                     13: int    io;
                     14: int    panicking;
                     15: int    rescuing;
                     16: Mod    modnum;
                     17: String genstr;
                     18: String rhs;
                     19: String wd;
                     20: String cmdstr;
                     21: int    intr();
                     22: int    rescue();
                     23: char   *getenv();
                     24: File   *current();
                     25: File   *tofile();
                     26: File   *getfile();
                     27: File   *curfile;
                     28: File   *flist;
                     29: File   *cmd;
                     30: jmp_buf        mainloop;
                     31: Filelist tempfile;
                     32: int    quitok=TRUE;
                     33: Patlist        globstr;
                     34: Patlist        pattern;
                     35: int    downloaded;
                     36: int    dflag;
                     37: int    Rflag;
                     38: int    zflag;
                     39: char   *machine;
                     40: int    dounlock;
                     41: 
                     42: main(argc, argv)
                     43:        uchar *argv[];
                     44: {
                     45:        register i;
                     46:        int (*onintr)();
                     47:        while(argc>1 && argv[1][0]=='-'){
                     48:                switch(argv[1][1]){
                     49:                case 'd':
                     50:                        dflag++;
                     51:                        break;
                     52:                case 'r':
                     53:                        --argc, argv++;
                     54:                        if(argc==1){
                     55:                                dprint("usage: sam [-d] -r machine\n");
                     56:                                return 1;
                     57:                        }
                     58:                        machine=(char *)argv[1];
                     59:                        break;
                     60:                case 'z':
                     61:                        zflag++;
                     62:                        break;
                     63:                case 'R':
                     64:                        Rflag++;
                     65:                        break;
                     66: #ifdef SUN
                     67:                case 't':
                     68:                case 'x':
                     69:                case '=':
                     70:                case 'W':
                     71:                        sunarg(&argv, &argc);
                     72:                        break;
                     73: #endif
                     74:                default:
                     75:                        dprint("sam: unknown flag %c\n", argv[1][1]);
                     76:                        return 1;
                     77:                }
                     78:                --argc, argv++;
                     79:        }
                     80:        allocinit();
                     81:        Fstart();
                     82:        strinit(&cmdstr);
                     83:        strinit(&lastpat);
                     84:        strinit(&lastregexp);
                     85:        strinit(&genstr);
                     86:        strinit(&rhs);
                     87:        strinit(&wd);
                     88:        gcnew(tempfile.ptr, 0);
                     89:        strinit(&unixcmd);
                     90:        straddc(&unixcmd, '\0');
                     91:        home=getenv("HOME");
                     92:        if(home==0)
                     93:                home="/tmp";
                     94:        if(!dflag){
                     95:                if(machine)
                     96: #ifdef SUN
                     97:                        connectboot(machine,zflag); /* doesn't return */
                     98: #else
                     99:                        connectto(machine);
                    100: #endif
                    101:                if(!Rflag){
                    102:                        if(!bootterm(zflag))
                    103:                                return 1;
                    104:                }
                    105:                rawmode(1);
                    106:                if(machine)
                    107:                        join();
                    108:                downloaded=1;
                    109:        }
                    110:        if(argc>1){
                    111:                for(i=1; i<argc; i++)
                    112:                        if(!setjmp(mainloop)){
                    113:                                strdup(&genstr, argv[i]);
                    114:                                Fsetname(newfile());
                    115:                        }
                    116:        }else if(!downloaded)
                    117:                newfile()->state=Clean;
                    118:        modnum++;
                    119:        onintr=signal(SIGINT, intr);
                    120:        if(onintr)
                    121:                signal(SIGINT, onintr);
                    122:        onintr=signal(SIGHUP, rescue);
                    123:        if(onintr)
                    124:                signal(SIGHUP, onintr);
                    125:        if(file.nused)
                    126:                current(file.ptr[0]);
                    127:        (void)setjmp(mainloop);
                    128:        cmdloop();
                    129:        trytoquit();    /* if we already q'ed, quitok will be TRUE */
                    130:        if(downloaded)
                    131:                rawmode(0);
                    132:        return 0;
                    133: }
                    134: panic(s)
                    135:        char *s;
                    136: {
                    137:        if(!panicking++ && !setjmp(mainloop)){
                    138:                dprint("sam: panic: %s\n", s);
                    139:                rescue();
                    140:        }
                    141:        abort();
                    142: }
                    143: rescue(){
                    144:        register i, nblank=0;
                    145:        register File *f;
                    146:        uchar buf[128];
                    147:        signal(SIGHUP, SIG_IGN);
                    148:        if(rescuing++)
                    149:                exit(1);
                    150:        io= -1;
                    151:        for(i=0; i<file.nused; i++){
                    152:                f=file.ptr[i];
                    153:                if(f==cmd || f->nbytes==0 || f->state!=Dirty)
                    154:                        continue;
                    155:                if(io==-1){
                    156:                        strcpy(buf, (uchar *)home);
                    157:                        strcpy(buf+strlen(buf), (uchar *)"/sam.save");
                    158:                        io=creat((char *)buf, 0777);
                    159:                        if(io<0)
                    160:                                return;
                    161:                }
                    162:                strcpy(buf, f->name.s);
                    163:                if(buf[0]==0)
                    164:                        sprint(buf, "nameless.%d", nblank++);
                    165:                fprint(io, "/usr/jerq/lib/samsave '%s' $* <<'---%s'\n",
                    166:                        (char *)buf, (char *)buf);
                    167:                addr.r.p1=0, addr.r.p2=f->nbytes;
                    168:                writeio(f);
                    169:                fprint(io, "\n---%s\n", (char *)buf);
                    170:        }
                    171:        if(panicking)
                    172:                abort();
                    173:        exit(0);
                    174: }
                    175: hiccough(s)
                    176:        char *s;
                    177: {
                    178:        if(rescuing)
                    179:                exit(1);
                    180:        if(s)
                    181:                dprint("%s\n", s);
                    182:        resetcmd();
                    183:        resetxec();
                    184:        compactok();
                    185:        if(io>0)
                    186:                close(io);
                    187:        if(undobuf->nbytes)
                    188:                Bdelete(undobuf, (Posn)0, undobuf->nbytes);
                    189:        update();
                    190:        if(curfile && curfile->state==Unread)
                    191:                curfile->state=Clean;
                    192:        dounlock=TRUE;
                    193:        if(downloaded && curfile && curfile->state!=Unread)
                    194:                outTs(Hcurrent, curfile->tag);
                    195:        longjmp(mainloop, 1);
                    196: }
                    197: intr(){
                    198:        signal(SIGINT, intr);
                    199:        error(Eintr);
                    200: }
                    201: trytoclose(f)
                    202:        register File *f;
                    203: {
                    204:        if(f==cmd)      /* possible? */
                    205:                return;
                    206:        if(f->state==Dirty && !f->closeok){
                    207:                f->closeok=TRUE;
                    208:                error_s(Emodified,
                    209:                    f->name.s[0]?(char *)f->name.s : "nameless file");
                    210:        }
                    211:        if(downloaded && f->rasp)
                    212:                outTs(Hclose, f->tag);
                    213:        delfile(f);
                    214:        if(f==curfile)
                    215:                current((File *)0);
                    216: }
                    217: trytoquit(){
                    218:        register c;
                    219:        register File *f;
                    220:        extern int eof;
                    221:        if(!quitok)
                    222:                for(c=0; c<file.nused; c++){
                    223:                        f=file.ptr[c];
                    224:                        if(f!=cmd && f->state==Dirty){
                    225:                                quitok=TRUE;
                    226:                                eof=FALSE;
                    227:                                error(Echanges);
                    228:                        }
                    229:                }
                    230: }
                    231: load(f)
                    232:        register File *f;
                    233: {
                    234:        Address saveaddr;
                    235:        strdupstr(&genstr, &f->name);
                    236:        filename(f);
                    237:        if(f->name.s[0]){
                    238:                saveaddr=addr;
                    239:                edit(f, 'I');
                    240:                addr=saveaddr;
                    241:        }else
                    242:                f->state=Clean;
                    243:        Fupdate(f, FALSE, TRUE);
                    244: }
                    245: update(){
                    246:        register i, anymod;
                    247:        register File *f;
                    248:        settempfile();
                    249:        for(anymod=i=0; i<tempfile.nused; i++){
                    250:                f=tempfile.ptr[i];
                    251:                if(f==cmd)      /* cmd gets done in main() */
                    252:                        continue;
                    253:                if(f->mod==modnum && Fupdate(f, FALSE, downloaded))
                    254:                        anymod++;
                    255:                if(f->rasp)
                    256:                        telldot(f);
                    257:        }
                    258:        if(anymod)
                    259:                modnum++;
                    260: }
                    261: File *
                    262: current(f)
                    263:        register File *f;
                    264: {
                    265:        return curfile=f;
                    266: }
                    267: edit(f, cmd)
                    268:        register File *f;
                    269: {
                    270:        register empty=TRUE;
                    271:        Posn p;
                    272:        int nonascii;
                    273:        if(cmd=='r')
                    274:                Fdelete(f, addr.r.p1, addr.r.p2);
                    275:        if(cmd=='e' || cmd=='I'){
                    276:                Fdelete(f, (Posn)0, f->nbytes);
                    277:                addr.r.p2=f->nbytes;
                    278:        }else if(f->nbytes!=0 || (f->name.s[0] && strcmp(genstr.s, f->name.s)!=0))
                    279:                empty=FALSE;
                    280:        if((io=open((char *)genstr.s, 0))<0)
                    281:                error_s(Eopen, (char *)genstr.s);
                    282:        p=readio(f, &nonascii, empty);
                    283:        closeio((cmd=='e' || cmd=='I')? -1 : p);
                    284:        if(cmd=='r')
                    285:                f->dot.r.p1=addr.r.p2, f->dot.r.p2=addr.r.p2+p;
                    286:        else
                    287:                f->dot.r.p1=f->dot.r.p2=0;
                    288:        quitok=f->closeok=empty;
                    289:        state(f, empty && !nonascii? Clean : Dirty);
                    290:        if(cmd=='e')
                    291:                filename(f);
                    292: }
                    293: getname(f, s, save)
                    294:        register File *f;
                    295:        register String *s;
                    296: {
                    297:        register c, i;
                    298:        strzero(&genstr);
                    299:        if(s==0 || (c=s->s[0])==0){             /* no name provided */
                    300:                if(f)
                    301:                        strdupstr(&genstr, &f->name);
                    302:                else
                    303:                        straddc(&genstr, '\0');
                    304:                goto Return;
                    305:        }
                    306:        if(c!=' ' && c!='\t')
                    307:                error(Eblank);
                    308:        for(i=0; (c=s->s[i])==' ' || c=='\t'; i++)
                    309:                ;
                    310:        while(s->s[i]>' ')
                    311:                straddc(&genstr, s->s[i++]);
                    312:        if(s->s[i])
                    313:                error(Enewline);
                    314:        straddc(&genstr, '\0');
                    315:        if(f && (save || f->name.s[0]==0)){
                    316:                Fsetname(f);
                    317:                if(strcmp(f->name.s, genstr.s)){
                    318:                        quitok=f->closeok=FALSE;
                    319:                        f->inumber=0;
                    320:                        f->date=0;
                    321:                        state(f, Dirty); /* if it's 'e', fix later */
                    322:                }
                    323:        }
                    324:     Return:
                    325:        return genstr.n-1;      /* strlen(name) */
                    326: }
                    327: filename(f)
                    328:        register File *f;
                    329: {
                    330:        dprint("%c%c%c %s\n", " '"[f->state==Dirty],
                    331:                "-+"[f->rasp!=0], " ."[f==curfile], genstr.s);
                    332: }
                    333: undo()
                    334: {
                    335:        register File *f;
                    336:        register i;
                    337:        Mod max;
                    338:        if((max=curfile->mod)==0)
                    339:                return;
                    340:        settempfile();
                    341:        for(i=0; i<tempfile.nused; i++){
                    342:                f=tempfile.ptr[i];
                    343:                if(f!=cmd && f->mod==max)
                    344:                        undostep(f);
                    345:        }
                    346: }
                    347: undostep(f)
                    348:        register File *f;
                    349: {
                    350:        register Buffer *t;
                    351:        register changes;
                    352:        Mark mark;
                    353:        t=f->transcript;
                    354:        changes=Fupdate(f, TRUE, TRUE);
                    355:        Bread(t, (uchar *)&mark, sizeof mark, f->markp);
                    356:        Bdelete(t, f->markp, t->nbytes);
                    357:        f->markp=mark.p;
                    358:        f->dot.r=mark.dot;
                    359:        f->mark=mark.mark;
                    360:        f->mod=mark.m;
                    361:        f->closeok=mark.s1!=Dirty;
                    362:        if(mark.s1==Dirty)
                    363:                quitok=FALSE;
                    364:        if(f->state==Clean && mark.s1==Clean && changes)
                    365:                state(f, Dirty);
                    366:        else
                    367:                state(f, mark.s1);
                    368: }
                    369: cd(str)
                    370:        String *str;
                    371: {
                    372:        register i;
                    373:        register File *f;
                    374:        readcmd(tempstr((uchar *)"/bin/pwd", 9));
                    375:        strdupstr(&wd, &genstr);
                    376:        if(wd.s[0]==0){
                    377:                wd.n=0;
                    378:                warn(Wpwd);
                    379:        }else if(wd.s[wd.n-2]=='\n'){
                    380:                --wd.n;
                    381:                wd.s[wd.n-1]='/';
                    382:        }
                    383:        if(chdir(getname((File *)0, str, FALSE)? (char *)genstr.s : home))
                    384:                syserror("chdir");
                    385:        settempfile();
                    386:        for(i=0; i<tempfile.nused; i++){
                    387:                f=tempfile.ptr[i];
                    388:                if(f!=cmd && f->name.s[0]!='/' && f->name.s[0]!=0){
                    389:                        strinsert(&f->name, &wd, (Posn)0);
                    390:                        sortname(f);
                    391:                }
                    392:        }
                    393: }
                    394: readcmd(s)
                    395:        String *s;
                    396: {
                    397:        if(flist==0)
                    398:                (flist=Fopen())->state=Clean;
                    399:        addr.r.p1=0, addr.r.p2=flist->nbytes;
                    400:        Unix(flist, '<', s, FALSE);
                    401:        Fupdate(flist, FALSE, FALSE);
                    402:        flist->mod=0;
                    403:        strzero(&genstr);
                    404:        strinsure(&genstr, flist->nbytes);
                    405:        Fchars(flist, genstr.s, (Posn)0, flist->nbytes);
                    406:        genstr.n=flist->nbytes;
                    407:        straddc(&genstr, '\0');
                    408: }
                    409: loadflist(s)
                    410:        register String *s;
                    411: {
                    412:        register c, i;
                    413:        c=s->s[0];
                    414:        for(i=0; s->s[i]==' ' || s->s[i]=='\t'; i++)
                    415:                ;
                    416:        if((c==' ' || c=='\t') && s->s[i]!='\n'){
                    417:                if(s->s[i]=='<'){
                    418:                        strdelete(s, 0L, (long)i+1);
                    419:                        readcmd(s);
                    420:                }else{
                    421:                        strzero(&genstr);
                    422:                        while((c=s->s[i++]) && c!='\n')
                    423:                                straddc(&genstr, c);
                    424:                        straddc(&genstr, '\0');
                    425:                }
                    426:        }else{
                    427:                if(c!='\n')
                    428:                        error(Eblank);
                    429:                strdup(&genstr, (uchar *)"");
                    430:        }
                    431:        return genstr.s[0];
                    432: }
                    433: File *
                    434: readflist(readall, delete)
                    435: {
                    436:        register Posn i;
                    437:        register c;
                    438:        register File *f;
                    439:        for(i=0,f=0; f==0 || readall || delete; ){
                    440:                strdelete(&genstr, (Posn)0, i);
                    441:                for(i=0; (c=genstr.s[i])==' ' || c=='\t' || c=='\n'; i++)
                    442:                        ;
                    443:                if(i>=genstr.n)
                    444:                        break;
                    445:                strdelete(&genstr, (Posn)0, i);
                    446:                for(i=0; (c=genstr.s[i]) && c!=' ' && c!='\t' && c!='\n'; i++)
                    447:                        ;
                    448:                if(i==0)
                    449:                        break;
                    450:                genstr.s[i++]=0;
                    451:                f=lookfile();
                    452:                if(delete){
                    453:                        if(f==0)
                    454:                                warn_s(Wfile, (char *)genstr.s);
                    455:                        else
                    456:                                trytoclose(f);
                    457:                }else if(f==0 && readall)
                    458:                        Fsetname(f=newfile());
                    459:        }
                    460:        return f;
                    461: }
                    462: File *
                    463: tofile(s)
                    464:        String *s;
                    465: {
                    466:        register File *f;
                    467:        if(s->s[0]!=' ')
                    468:                error(Eblank);
                    469:        if(loadflist(s)==0)
                    470:                f=lookfile();   /* empty string ==> nameless file */
                    471:        else if((f=readflist(FALSE, FALSE))==0)
                    472:                error_s(Emenu, (char *)genstr.s);
                    473:        return current(f);
                    474: }
                    475: File *
                    476: getfile(s)
                    477:        String *s;
                    478: {
                    479:        register File *f;
                    480:        if(loadflist(s)==0)
                    481:                Fsetname(f=newfile());
                    482:        else if((f=readflist(TRUE, FALSE))==0)
                    483:                error(Eblank);
                    484:        return current(f);
                    485: }
                    486: closefiles(f, s)
                    487:        File *f;
                    488:        register String *s;
                    489: {
                    490:        if(s->s[0]==0){
                    491:                if(f==0)
                    492:                        error(Enofile);
                    493:                trytoclose(f);
                    494:                return;
                    495:        }
                    496:        if(s->s[0]!=' ')
                    497:                error(Eblank);
                    498:        if(loadflist(s)==0)
                    499:                error(Enewline);
                    500:        readflist(FALSE, TRUE);
                    501: }
                    502: move(f, addr2)
                    503:        register File *f;
                    504:        Address addr2;
                    505: {
                    506:        if(addr.r.p2<=addr2.r.p2){
                    507:                Fdelete(f, addr.r.p1, addr.r.p2);
                    508:                copy(f, addr2);
                    509:        }else if(addr.r.p1>=addr2.r.p2){
                    510:                copy(f, addr2);
                    511:                Fdelete(f, addr.r.p1, addr.r.p2);
                    512:        }else
                    513:                error(Eoverlap);
                    514: }
                    515: copy(f, addr2)
                    516:        register File *f;
                    517:        Address addr2;
                    518: {
                    519:        register Posn p;
                    520:        register ni;
                    521:        for(p=addr.r.p1; p<addr.r.p2; p+=ni){
                    522:                ni=addr.r.p2-p;
                    523:                if(ni>BLOCKSIZE)
                    524:                        ni=BLOCKSIZE;
                    525:                Fchars(f, genbuf, p, p+ni);
                    526:                Finsert(addr2.f, tempstr(genbuf, ni), addr2.r.p2);
                    527:        }
                    528:        addr2.f->dot.r.p2=addr2.r.p2+(f->dot.r.p2-f->dot.r.p1);
                    529:        addr2.f->dot.r.p1=addr2.r.p2;
                    530: }
                    531: Posn
                    532: nlcount(f, p0, p1)
                    533:        register File *f;
                    534:        register Posn p0, p1;
                    535: {
                    536:        register Posn nl=0;
                    537:        Fgetcset(f, p0);
                    538:        while(p0++<p1)
                    539:                if(Fgetc(f)=='\n')
                    540:                        nl++;
                    541:        return nl;
                    542: }
                    543: printposn(f, charsonly)
                    544:        register File *f;
                    545: {
                    546:        register Posn l1, l2;
                    547:        if(!charsonly){
                    548:                l1=1+nlcount(f, (Posn)0, addr.r.p1);
                    549:                l2=l1+nlcount(f, addr.r.p1, addr.r.p2);
                    550:                /* check if addr ends with '\n' */
                    551:                if(addr.r.p2>0 && addr.r.p2>addr.r.p1 && (Fgetcset(f, addr.r.p2-1),Fgetc(f)=='\n'))
                    552:                        --l2;
                    553:                dprint("%lud", l1);
                    554:                if(l2!=l1)
                    555:                        dprint(",%lud", l2);
                    556:                dprint("; ");
                    557:        }
                    558:        dprint("#%lud", addr.r.p1);
                    559:        if(addr.r.p2!=addr.r.p1)
                    560:                dprint(",#%lud", addr.r.p2);
                    561:        dprint("\n");
                    562: }
                    563: settempfile(){
                    564:        if(tempfile.nalloc<file.nused){
                    565:                gcfree((uchar *)tempfile.ptr);
                    566:                gcnew(tempfile.ptr, file.nused);
                    567:                tempfile.nalloc=file.nused;
                    568:        }
                    569:        tempfile.nused=file.nused;
                    570:        bcopy((uchar *)&file.ptr[0], (uchar *)&file.ptr[file.nused],
                    571:                (uchar *)&tempfile.ptr[0], 1);
                    572: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.