Annotation of researchv10no/cmd/join/join.c, revision 1.1

1.1     ! root        1: /*     join F1 F2 on stuff */
        !             2: 
        !             3: #include       <stdio.h>
        !             4: #include       <string.h>
        !             5: #include       <stdlib.h>
        !             6: #include       <ctype.h>
        !             7: 
        !             8: enum { F1, F2, FX, F0 };
        !             9: #define        NFLD    100     /* max field per line */
        !            10: #define comp() strcmp(ppi[F1][j1],ppi[F2][j2])
        !            11: 
        !            12: FILE *f[2];
        !            13: char buf[2][BUFSIZ];   /*input lines */
        !            14: char *ppi[2][NFLD+1];  /* pointers to fields in lines */
        !            15: int    j1      = 1;    /* join on this field in file 1 */
        !            16: int    j2      = 1;    /* join on this field in file 2 */
        !            17: int    olist[2*NFLD];  /* output these fields */
        !            18: int    olistf[2*NFLD]; /* from these files */
        !            19: int    no;             /* number of entries in olist */
        !            20: int    sep1    = ' ';  /* default field separator */
        !            21: int    sep2    = '\t';
        !            22: int    discard;        /* count of truncated lines */
        !            23: char*  null    = "";
        !            24: int    a1;
        !            25: int    a2;
        !            26: int    vflg;
        !            27: 
        !            28: char*  jcom    = "join: -j is archaic, replaced by -1 and -2\n";
        !            29: char*  ocom    = "join: archaic -o; commas are preferred\n";
        !            30: char*  usage   = "usage: join [-1 n] [-2 n] [-o m.n,m.n,...]"
        !            31:                  " [-t c] [-e s] [-a m] [-v m] file1 file2";
        !            32: 
        !            33: int getopt(int, char**, char*);
        !            34: extern char *optarg;
        !            35: extern int optind;
        !            36: 
        !            37: int onelet(char*);
        !            38: int xatoi(char*);
        !            39: void optiono(int, char**);
        !            40: void output(int, int);
        !            41: int input(int);
        !            42: void oparse(char*);
        !            43: void error(char*, char*);
        !            44: void seek1(void), seek2(void);
        !            45: 
        !            46: int
        !            47: main(int argc, char **argv)
        !            48: {
        !            49:        int i;
        !            50: 
        !            51:        for(;;) {
        !            52:                switch(getopt(argc, argv, "1:2:a:e:j:o:t:v:")) {
        !            53:                case -1:
        !            54:                        break;
        !            55:                case '?':
        !            56:                        error(usage, "");
        !            57:                case 'v':
        !            58:                        vflg++;
        !            59:                case 'a':
        !            60:                        switch(onelet(optarg)) {
        !            61:                        case '1':
        !            62:                                a1++;
        !            63:                                continue;
        !            64:                        case '2':
        !            65:                                a2++;
        !            66:                                continue;
        !            67:                        }
        !            68:                        error(usage, "");
        !            69:                case 'e':
        !            70:                        null = optarg;
        !            71:                        continue;
        !            72:                case 't':
        !            73:                        sep1 = sep2 = onelet(optarg);
        !            74:                        continue;
        !            75:                case '1':
        !            76:                        j1 = xatoi(optarg);
        !            77:                        continue;
        !            78:                case '2':
        !            79:                        j2 = xatoi(optarg);
        !            80:                        continue;
        !            81:                case 'j':
        !            82:                        fprintf(stderr, jcom);
        !            83:                        if(optarg[-1] != 'j') {
        !            84:                                j1 = j2 = xatoi(optarg);
        !            85:                                continue;
        !            86:                        }
        !            87:                        switch(onelet(optarg)) {
        !            88:                        case '1':
        !            89:                                j1 = xatoi(argv[optind++]);
        !            90:                                continue;
        !            91:                        case '2':
        !            92:                                j2 = xatoi(argv[optind++]);
        !            93:                                continue;
        !            94:                        }
        !            95:                        error("improper -j", "");
        !            96:                case 'o':
        !            97:                        optiono(argc, argv);
        !            98:                        continue;
        !            99:                }
        !           100:                break;
        !           101:        }
        !           102: proceed:
        !           103:        if (argc-optind != 2)
        !           104:                error(usage,"");
        !           105:        for (i = 0; i < no; i++)
        !           106:                if (--olist[i] >= NFLD) /* 0 origin */
        !           107:                        error("field number too big in -o","");
        !           108:        if(--j1<0 || --j2<0)
        !           109:                error("join field number not positive", "");
        !           110:        if(j1>=NFLD || j2>=NFLD)
        !           111:                error("join field number too big", "");
        !           112:        if (strcmp(argv[optind], "-") == 0)
        !           113:                f[F1] = stdin;
        !           114:        else if ((f[F1] = fopen(argv[optind], "r")) == 0)
        !           115:                error("can't open %s", argv[optind]);
        !           116:        if(strcmp(argv[optind+1], "-") == 0) {
        !           117:                f[F2] = stdin;
        !           118:        } else if ((f[F2] = fopen(argv[optind+1], "r")) == 0)
        !           119:                error("can't open %s", argv[optind+1]);
        !           120: 
        !           121:        if(ftell(f[F2]) >= 0)
        !           122:                seek2();
        !           123:        else if(ftell(f[F1]) >= 0)
        !           124:                seek1();
        !           125:        else
        !           126:                error("sorry, need one random-access file","");
        !           127:        if (discard)
        !           128:                error("some input line was truncated", "");
        !           129:        return 0;
        !           130: }
        !           131: 
        !           132: /* lazy.  there ought to be a clean way to combine seek1 & seek2 */
        !           133: #define get1() n1=input(F1)
        !           134: #define get2() n2=input(F2)
        !           135: void
        !           136: seek2()
        !           137: {
        !           138:        int n1, n2;     /* number of fields in each record */
        !           139:        long top2;
        !           140:        long bot2 = ftell(f[F2]);
        !           141:        get1();
        !           142:        get2();
        !           143:        while(n1>0 && n2>0 || (a1||a2) && n1+n2>0) {
        !           144:                if(n1>0 && n2>0 && comp()>0 || n1==0) {
        !           145:                        if(a2) output(0, n2);
        !           146:                        bot2 = ftell(f[F2]);
        !           147:                        get2();
        !           148:                } else if(n1>0 && n2>0 && comp()<0 || n2==0) {
        !           149:                        if(a1) output(n1, 0);
        !           150:                        get1();
        !           151:                } else /*(n1>0 && n2>0 && comp()==0)*/ {
        !           152:                        while(n2>0 && comp()==0) {
        !           153:                                if(!vflg) output(n1, n2);
        !           154:                                top2 = ftell(f[F2]);
        !           155:                                get2();
        !           156:                        }
        !           157:                        fseek(f[F2], bot2, 0);
        !           158:                        get2();
        !           159:                        get1();
        !           160:                        for(;;) {
        !           161:                                if(n1>0 && n2>0 && comp()==0) {
        !           162:                                        if(!vflg) output(n1, n2);
        !           163:                                        get2();
        !           164:                                } else if(n1>0 && n2>0 && comp()<0 || n2==0) {
        !           165:                                        fseek(f[F2], bot2, 0);
        !           166:                                        get2();
        !           167:                                        get1();
        !           168:                                } else /*(n1>0 && n2>0 && comp()>0 || n1==0)*/{
        !           169:                                        fseek(f[F2], top2, 0);
        !           170:                                        bot2 = top2;
        !           171:                                        get2();
        !           172:                                        break;
        !           173:                                }
        !           174:                        }
        !           175:                }
        !           176:        }
        !           177: }
        !           178: void
        !           179: seek1()
        !           180: {
        !           181:        int n1, n2;     /* number of fields in each record */
        !           182:        long top1;
        !           183:        long bot1 = ftell(f[F1]);
        !           184:        get1();
        !           185:        get2();
        !           186:        while(n1>0 && n2>0 || (a1||a2) && n1+n2>0) {
        !           187:                if(n1>0 && n2>0 && comp()>0 || n1==0) {
        !           188:                        if(a2) output(0, n2);
        !           189:                        get2();
        !           190:                } else if(n1>0 && n2>0 && comp()<0 || n2==0) {
        !           191:                        if(a1) output(n1, 0);
        !           192:                        bot1 = ftell(f[F1]);
        !           193:                        get1();
        !           194:                } else /*(n1>0 && n2>0 && comp()==0)*/ {
        !           195:                        while(n2>0 && comp()==0) {
        !           196:                                if(!vflg) output(n1, n2);
        !           197:                                top1 = ftell(f[F1]);
        !           198:                                get1();
        !           199:                        }
        !           200:                        fseek(f[F1], bot1, 0);
        !           201:                        get2();
        !           202:                        get1();
        !           203:                        for(;;) {
        !           204:                                if(n1>0 && n2>0 && comp()==0) {
        !           205:                                        if(!vflg) output(n1, n2);
        !           206:                                        get1();
        !           207:                                } else if(n1>0 && n2>0 && comp()>0 || n1==0) {
        !           208:                                        fseek(f[F1], bot1, 0);
        !           209:                                        get2();
        !           210:                                        get1();
        !           211:                                } else /*(n1>0 && n2>0 && comp()<0 || n2==0)*/{
        !           212:                                        fseek(f[F1], top1, 0);
        !           213:                                        bot1 = top1;
        !           214:                                        get1();
        !           215:                                        break;
        !           216:                                }
        !           217:                        }
        !           218:                }
        !           219:        }
        !           220: }
        !           221: 
        !           222: int
        !           223: input(int n)           /* get line, split, return field count */
        !           224: {
        !           225:        register int i, c;
        !           226:        char *bp;
        !           227:        char **pp;
        !           228: 
        !           229:        bp = buf[n];
        !           230:        pp = ppi[n];
        !           231:        pp[j1] = pp[j2] = "";   /* for absent join field */
        !           232:        if (fgets(bp, BUFSIZ, f[n]) == 0)
        !           233:                return(0);
        !           234:        i = 0;
        !           235:        do {
        !           236:                i++;
        !           237:                if (sep1 == ' ')        /* strip multiples */
        !           238:                        while ((c = *bp) == sep1 || c == sep2)
        !           239:                                bp++;   /* skip blanks */
        !           240:                else
        !           241:                        c = *bp;
        !           242:                *pp++ = bp;     /* record beginning */
        !           243:                while ((c = *bp) != sep1 && c != '\n' && c != sep2 && c != '\0')
        !           244:                        bp++;
        !           245:                *bp++ = '\0';   /* mark end by overwriting blank */
        !           246:        } while (c != '\n' && c != '\0' && i < NFLD-1);
        !           247:        if (c != '\n')
        !           248:                discard++;
        !           249:        return(i);
        !           250: }
        !           251: 
        !           252: void
        !           253: output(int on1, int on2)       /* print items from olist */
        !           254: {
        !           255:        int i;
        !           256:        char *temp;
        !           257: 
        !           258:        if (no <= 0) {  /* default case */
        !           259:                printf("%s", j1<on1? ppi[F1][j1]:
        !           260:                             j2<on2? ppi[F2][j2]: null);
        !           261:                for (i = 0; i < on1; i++)
        !           262:                        if (i != j1)
        !           263:                                printf("%c%s", sep1, ppi[F1][i]);
        !           264:                for (i = 0; i < on2; i++)
        !           265:                        if (i != j2)
        !           266:                                printf("%c%s", sep1, ppi[F2][i]);
        !           267:                printf("\n");
        !           268:        } else {
        !           269:                for (i = 0; i < no; i++) {
        !           270:                        temp = null;
        !           271:                        switch(olistf[i]) {
        !           272:                        case F0:
        !           273:                                if(j1 < on1)
        !           274:                                        temp = ppi[F1][j1];
        !           275:                                else if(j2 < on2)
        !           276:                                        temp = ppi[F2][j2];
        !           277:                                break;
        !           278:                        case F1:
        !           279:                                if(olist[i] < on1)
        !           280:                                        temp = ppi[F1][olist[i]];
        !           281:                                break;
        !           282:                        case F2:
        !           283:                                if(olist[i] < on2)
        !           284:                                        temp = ppi[F2][olist[i]];
        !           285:                                break;
        !           286:                        }
        !           287:                        printf("%s", temp);
        !           288:                        if (i == no - 1)
        !           289:                                printf("\n");
        !           290:                        else
        !           291:                                printf("%c", sep1);
        !           292:                }
        !           293:        }
        !           294: }
        !           295: 
        !           296: void
        !           297: error(char *s1, char *s2)
        !           298: {
        !           299:        fprintf(stderr, "join: ");
        !           300:        fprintf(stderr, s1, s2);
        !           301:        fprintf(stderr, "\n");
        !           302:        exit(1);
        !           303: }
        !           304: 
        !           305: char *
        !           306: getoptarg(int *argcp, char ***argvp)
        !           307: {
        !           308:        int argc = *argcp;
        !           309:        char **argv = *argvp;
        !           310:        if(argv[1][2] != 0)
        !           311:                return &argv[1][2];
        !           312:        if(argc<=2 || argv[2][0]=='-')
        !           313:                error("incomplete option %s", argv[1]);
        !           314:        *argcp = --argc;
        !           315:        *argvp = ++argv;
        !           316:        return argv[1];
        !           317: }
        !           318: 
        !           319: void
        !           320: oparse(char *s)
        !           321: {
        !           322:        for (no = 0; no<2*NFLD && *s; no++, s++) {
        !           323:                switch(*s) {
        !           324:                case 0:
        !           325:                        return;
        !           326:                case '0':
        !           327:                        olistf[no] = F0;
        !           328:                        break;
        !           329:                case '1':
        !           330:                case '2':
        !           331:                        if(s[1] == '.' && isdigit(s[2])) {
        !           332:                                olistf[no] = *s=='1'? F1: F2;
        !           333:                                olist[no] = xatoi(s += 2);
        !           334:                                break;
        !           335:                        } /* fall thru */
        !           336:                default:
        !           337:                        error("invalid -o list", "");
        !           338:                }
        !           339:                if(s[1] == ',')
        !           340:                        s++;
        !           341:        }
        !           342: }
        !           343: 
        !           344: int
        !           345: xatoi(char *s)
        !           346: {
        !           347:        if(!isdigit(*s))
        !           348:                error("numeric argument expected", "");
        !           349:        return atoi(s);
        !           350: }
        !           351: 
        !           352: int
        !           353: onelet(char *s)
        !           354: {
        !           355:        if(s[0] == 0 || s[1] != 0)
        !           356:                error(usage, "");
        !           357:        return s[0];
        !           358: }      
        !           359: 
        !           360: void
        !           361: optiono(int argc, char **argv)
        !           362: {
        !           363:        static multi;
        !           364:        int f;
        !           365:        for (no=0; *optarg; no++) {
        !           366:                if(no >= 2*NFLD)
        !           367:                        error("too many output fields", "");
        !           368:                f = *optarg++;
        !           369:                f = f=='0'? F0: f=='1'? F1: f=='2'? F2: FX;
        !           370:                if(f == FX)
        !           371:                        error("improper -o", "");
        !           372:                olistf[no] = f;
        !           373:                if(f != F0) {
        !           374:                        if(*optarg++ != '.')
        !           375:                                error("improper -o", "");
        !           376:                        olist[no] = xatoi(optarg);
        !           377:                        while(isdigit(*optarg))
        !           378:                                optarg++;
        !           379:                }
        !           380:                if(*optarg==',' || *optarg==' ')
        !           381:                        optarg++;
        !           382:                else if(*optarg==0 &&
        !           383:                        (multi || no==0) &&
        !           384:                        optind<argc-2 &&
        !           385:                        isdigit(*argv[optind])) {
        !           386:                                optarg = argv[optind++];
        !           387:                                if(multi++ == 0)
        !           388:                                        fprintf(stderr, ocom);
        !           389:                        }
        !           390:        }
        !           391: }

unix.superglobalmegacorp.com

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