12152Seric # include "../hdr/defines.h"
22152Seric # include "../hdr/had.h"
32152Seric
4*33423Sbostic static char Sccsid[] = "@(#)snull.c 4.5 02/02/88";
52152Seric USXALLOC();
62152Seric
730499Slepreau int Debug = 0;
82152Seric struct packet gpkt;
92152Seric struct sid sid;
102152Seric int num_files;
112152Seric char had[26];
122152Seric FILE *Xiop;
132152Seric int Xcreate;
142152Seric struct deltalist {
152152Seric struct deltalist *ds_olderdel;
162152Seric struct deltalist *ds_youngerdel;
172152Seric struct sid ds_sid;
182152Seric int ds_origser;
192152Seric int ds_ser;
202152Seric int ds_pred;
212152Seric long ds_datetime;
226174Seric char ds_pgmr[SZLNAM];
232152Seric char ds_type;
242152Seric struct stats ds_stats;
252152Seric int ds_insnull;
262152Seric };
272152Seric struct deltalist *Dhead;
282152Seric struct deltalist *Dtail;
292152Seric char line[512];
302152Seric int *New_ser_ptr;
312152Seric int Max_old_ser;
322152Seric
main(argc,argv)332152Seric main(argc,argv)
342152Seric int argc;
352152Seric register char *argv[];
362152Seric {
372152Seric register int i;
382152Seric register char *p;
392152Seric char c;
402152Seric extern snull();
412152Seric extern int Fcnt;
422152Seric
432152Seric /*
442152Seric Flags for 'fatal'.
452152Seric */
462152Seric Fflags = FTLEXIT | FTLMSG | FTLCLN;
472152Seric
482152Seric /*
492152Seric Process arguments.
502152Seric */
512152Seric for (i = 1; i < argc; i++)
522152Seric if (argv[i][0] == '-' && (c = argv[i][1])) {
532152Seric p = &argv[i][2];
542152Seric switch (c) {
552152Seric default:
562152Seric fatal("unknown key letter (cm1)");
572152Seric }
582152Seric if (had[c - 'a']++)
592152Seric fatal("key letter twice (cm2)");
602152Seric argv[i] = 0;
612152Seric }
622152Seric else num_files++;
632152Seric
642152Seric if(num_files == 0)
652152Seric fatal("missing file arg (cm3)");
662152Seric
672152Seric setsig();
682152Seric /*
692152Seric Reset flags for 'fatal' so that it will return to 'main'
702152Seric rather than exiting.
712152Seric */
7230499Slepreau Fflags &= ~FTLEXIT;
7330499Slepreau Fflags |= FTLJMP;
742152Seric
752152Seric /*
762152Seric Invoke 'snull' for each file argument.
772152Seric */
782152Seric for (i = 1; i < argc; i++)
792152Seric if (p = argv[i])
802152Seric do_file(p,snull);
812152Seric
822152Seric exit(Fcnt ? 1 : 0);
832152Seric }
842152Seric
852152Seric
snull(file)862152Seric snull(file)
872152Seric {
882152Seric register char *p;
892152Seric register int ser;
902152Seric extern char had_dir, had_standinp;
912152Seric extern char *Sflags[];
922152Seric struct stats stats;
932152Seric int newser;
942152Seric
952152Seric /*
962152Seric Set up to return to caller ('main') from 'fatal'.
972152Seric */
982152Seric if (setjmp(Fjmp))
992152Seric return;
1002152Seric
1012152Seric sinit(&gpkt,file,1); /* init packet and open file */
1022152Seric
1032152Seric if (exists(auxf(gpkt.p_file,'p')))
1042152Seric fatal("p-file exists (sn3)");
1052152Seric
1062152Seric if (lockit(auxf(gpkt.p_file,'z'),2,getpid()))
1072152Seric fatal("cannot create lock file (cm4)");
1082152Seric
1092152Seric /*
1102152Seric Indicate that file is to be re-opened (from beginning)
1112152Seric after it reaches EOF.
1122152Seric The file is read once to get the delta table
1132152Seric (without copying to x-file) and then again to make
1142152Seric required modifications to it (using x-file).
1152152Seric */
1162152Seric gpkt.p_reopen = 1;
1172152Seric
1182152Seric dodeltbl(&gpkt); /* get delta table */
1192152Seric flushto(&gpkt,EUSERNAM,1);
1202152Seric doflags(&gpkt); /* get flags */
1212152Seric
1222152Seric /*
1232152Seric Indicate to 'getline' that EOF is allowable.
1242152Seric */
1252152Seric gpkt.p_chkeof = 1;
1262152Seric
1272152Seric /*
1282152Seric Flush through rest of file.
1292152Seric This checks for corruptions.
1302152Seric */
1312152Seric while (getline(&gpkt))
1322152Seric ;
1332152Seric
1342152Seric if (num_files > 1 || had_dir || had_standinp)
1352152Seric printf("\n%s:\n",gpkt.p_file);
1362152Seric
1372152Seric /*
1382152Seric Here, file has already been re-opened (by 'getline').
1392152Seric Indicate that x-file is to be used.
1402152Seric */
1412152Seric gpkt.p_upd = 1;
1422152Seric
1432152Seric gpkt.p_wrttn = 1;
1442152Seric getline(&gpkt); /* skip over old */
1452152Seric gpkt.p_wrttn = 1; /* header record */
1462152Seric
1472152Seric /*
1482152Seric Write new header.
1492152Seric */
150*33423Sbostic sprintf(line,"%c%c00000\n",CTLCHAR,HEAD);
151*33423Sbostic putline(&gpkt,line);
1522152Seric mkdelt(); /* insert 'null' deltas */
1532152Seric wrtdeltbl(&gpkt); /* write out new delta table */
1542152Seric
1552152Seric flushto(&gpkt,EUSERNAM,0);
1562152Seric /*
1572152Seric If file does not have the 'n' flag, put one in.
1582152Seric */
159*33423Sbostic if (!Sflags[NULLFLAG - 'a']) {
160*33423Sbostic sprintf(line,"%c%c %c\n",CTLCHAR,FLAG,NULLFLAG);
161*33423Sbostic putline(&gpkt,line);
162*33423Sbostic }
1632152Seric
1642152Seric flushto(&gpkt,EUSERTXT,0);
1652152Seric
1662152Seric /*
1672152Seric Process body, changing control-line serial numbers
1682152Seric appropriately.
1692152Seric */
1702152Seric fixbody(&gpkt);
1712152Seric
1722152Seric flushline(&gpkt,0); /* flush buffer, fix header, and close */
1732152Seric rename(auxf(gpkt.p_file,'x'),gpkt.p_file);
1742152Seric clean_up(0);
1752152Seric }
1762152Seric
1772152Seric
dodeltbl(pkt)1782152Seric dodeltbl(pkt)
1792152Seric register struct packet *pkt;
1802152Seric {
1812152Seric struct deltab dt;
1822152Seric struct stats stats;
1832152Seric struct deltalist *newp;
1842152Seric int n;
1852152Seric
1862152Seric Dhead = Dtail = newp = 0;
1872152Seric
1882152Seric /*
1892152Seric Read entire delta table.
1902152Seric */
1912152Seric while (getstats(pkt,&stats)) {
1922152Seric if (getadel(pkt,&dt) != BDELTAB)
1932152Seric fmterr(pkt);
1942152Seric newp = alloc(n = sizeof(*Dhead));
19519944Ssam bzero(newp,n);
1962152Seric if (!Dhead) {
1972152Seric Dhead = newp;
1982152Seric New_ser_ptr = alloc(n = 2 * (dt.d_serial + 1));
19919944Ssam bzero(New_ser_ptr,n);
2002152Seric Max_old_ser = dt.d_serial;
2012152Seric }
2022152Seric else {
2032152Seric Dtail->ds_olderdel = newp;
2042152Seric newp->ds_youngerdel = Dtail;
2052152Seric }
2062152Seric newp->ds_sid.s_rel = dt.d_sid.s_rel;
2072152Seric newp->ds_sid.s_lev = dt.d_sid.s_lev;
2082152Seric newp->ds_sid.s_br = dt.d_sid.s_br;
2092152Seric newp->ds_sid.s_seq = dt.d_sid.s_seq;
2102152Seric newp->ds_origser = dt.d_serial;
2112152Seric newp->ds_ser = dt.d_serial;
2122152Seric newp->ds_pred = dt.d_pred;
2132152Seric newp->ds_datetime = dt.d_datetime;
21419944Ssam bcopy(&dt.d_pgmr,newp->ds_pgmr,sizeof(dt.d_pgmr));
2152152Seric newp->ds_type = dt.d_type;
2162152Seric newp->ds_stats.s_ins = stats.s_ins;
2172152Seric newp->ds_stats.s_del = stats.s_del;
2182152Seric newp->ds_stats.s_unc = stats.s_unc;
2192152Seric Dtail = newp;
2202152Seric
2212152Seric /*
2222152Seric Skip over rest of delta entry.
2232152Seric */
2242152Seric while ((n = getline(pkt)) != NULL)
2252152Seric if (pkt->p_line[0] != CTLCHAR)
2262152Seric break;
2272152Seric else {
2282152Seric switch (pkt->p_line[1]) {
2292152Seric case EDELTAB:
2302152Seric break;
2312152Seric case INCLUDE:
2322152Seric case EXCLUDE:
2332152Seric case IGNORE:
2342152Seric case MRNUM:
2352152Seric case COMMENTS:
2362152Seric continue;
2372152Seric default:
2382152Seric fmterr(pkt);
2392152Seric }
2402152Seric break;
2412152Seric }
2422152Seric if (n == NULL || pkt->p_line[0] != CTLCHAR)
2432152Seric fmterr(pkt);
2442152Seric }
2452152Seric }
2462152Seric
2472152Seric
getadel(pkt,dt)2482152Seric getadel(pkt,dt)
2492152Seric register struct packet *pkt;
2502152Seric register struct deltab *dt;
2512152Seric {
2522152Seric if (getline(pkt) == NULL)
2532152Seric fmterr(pkt);
2542152Seric return(del_ab(pkt->p_line,dt,pkt));
2552152Seric }
2562152Seric
2572152Seric
getstats(pkt,statp)2582152Seric getstats(pkt,statp)
2592152Seric register struct packet *pkt;
2602152Seric register struct stats *statp;
2612152Seric {
2622152Seric register char *p;
2632152Seric
2642152Seric p = pkt->p_line;
2652152Seric if (getline(pkt) == NULL || *p++ != CTLCHAR || *p++ != STATS)
2662152Seric return(0);
2672152Seric NONBLANK(p);
2682152Seric p = satoi(p,&statp->s_ins);
2692152Seric p = satoi(++p,&statp->s_del);
2702152Seric satoi(++p,&statp->s_unc);
2712152Seric return(1);
2722152Seric }
2732152Seric
2742152Seric
mkdelt()2752152Seric mkdelt()
2762152Seric {
2772152Seric struct deltalist *ptr;
2782152Seric struct deltalist *nulldel;
2792152Seric struct deltalist *oldp;
2802152Seric struct deltalist *ptrtemp;
2812152Seric int n;
2822152Seric int currel;
2832152Seric int reldiff, numnull;
2842152Seric int serhold;
2852152Seric
2862152Seric /*
2872152Seric Set current release to that of oldest (first) delta.
2882152Seric */
2892152Seric currel = Dtail->ds_sid.s_rel;
2902152Seric
2912152Seric /*
2922152Seric The following loop processes each delta, starting with the
2932152Seric oldest one in the file (the last one read).
2942152Seric */
2952152Seric ptr = Dtail;
2962152Seric while (ptr) {
2972152Seric reldiff = ptr->ds_sid.s_rel - currel;
2982152Seric
2992152Seric /*
3002152Seric Skip removed deltas, branch deltas, or any delta whose
3012152Seric release number is the same as the current release number.
3022152Seric */
3032152Seric if (ptr->ds_type == 'R' || ptr->ds_sid.s_br ||
3042152Seric ptr->ds_sid.s_seq || reldiff == 0) {
3052152Seric ptr = ptr->ds_youngerdel;
3062152Seric continue;
3072152Seric }
3082152Seric
3092152Seric /*
3102152Seric Check if delta is the next trunk delta in sequence, and if so
3112152Seric bump up current release number and continue.
3122152Seric */
3132152Seric if (reldiff == 1) {
3142152Seric currel++;
3152152Seric ptr = ptr->ds_youngerdel;
3162152Seric continue;
3172152Seric }
3182152Seric
3192152Seric /*
3202152Seric Here, a trunk delta has been found, and its release
3212152Seric number is greater (by at least 2) than the current
3222152Seric release number.
3232152Seric This requires insertion of 'null' deltas.
3242152Seric First, check that this trunk delta's release
3252152Seric number is greater than currel.
3262152Seric (This catches deltas whose SIDs have been changed
3272152Seric by the user to make them look like trunk deltas.)
3282152Seric */
3292152Seric if (reldiff < 0)
3302152Seric fatal("file has invalid trunk delta (sn1)");
3312152Seric
33230499Slepreau currel += reldiff; /* update currel */
3332152Seric
3342152Seric /*
3352152Seric Find pointer to ancestor delta.
3362152Seric */
3372152Seric oldp = ser_to_ptr(ptr->ds_pred);
3382152Seric
3392152Seric /*
3402152Seric Retain serial number for later use in fixing
3412152Seric other deltas' serial numbers.
3422152Seric */
3432152Seric serhold = ptr->ds_ser;
3442152Seric
3452152Seric ptrtemp = ptr;
3462152Seric numnull = reldiff; /* number of null deltas needed */
3472152Seric while (--numnull) { /* insert null deltas */
3482152Seric nulldel = alloc(n = sizeof(*Dhead));
34919944Ssam bzero(nulldel,n);
3502152Seric nulldel->ds_youngerdel = ptrtemp;
3512152Seric nulldel->ds_olderdel = ptrtemp->ds_olderdel;
3522152Seric ptrtemp->ds_olderdel = nulldel;
3532152Seric (nulldel->ds_olderdel)->ds_youngerdel = nulldel;
3542152Seric nulldel->ds_sid.s_rel = ptrtemp->ds_sid.s_rel - 1;
3552152Seric nulldel->ds_sid.s_lev = 1;
3562152Seric nulldel->ds_sid.s_br = 0;
3572152Seric nulldel->ds_sid.s_seq = 0;
3582152Seric nulldel->ds_ser = serhold + numnull - 1;
3592152Seric if (numnull != 1)
3602152Seric nulldel->ds_pred = nulldel->ds_ser - 1;
3612152Seric else
3622152Seric nulldel->ds_pred = oldp->ds_ser;
3632152Seric nulldel->ds_datetime = ptr->ds_datetime;
3646174Seric substr(logname(),nulldel->ds_pgmr,0,LNLNAM);
3652152Seric nulldel->ds_type = 'D';
3662152Seric nulldel->ds_stats.s_ins = 0;
3672152Seric nulldel->ds_stats.s_del = 0;
3682152Seric nulldel->ds_stats.s_unc = oldp->ds_stats.s_unc +
3692152Seric oldp->ds_stats.s_ins;
3702152Seric nulldel->ds_insnull = 1; /* null delta indicator */
3712152Seric ptrtemp = nulldel;
3722152Seric }
3732152Seric
3742152Seric /*
3752152Seric Fix up sequence and predecessor numbers of those deltas
3762152Seric which are younger than the ones just processed.
3772152Seric */
3782152Seric ptrtemp = ptr;
3792152Seric reldiff--;
3802152Seric while (ptrtemp) {
3812152Seric if (ptrtemp->ds_ser >= serhold)
38230499Slepreau ptrtemp->ds_ser += reldiff;
3832152Seric if (ptrtemp->ds_pred >= serhold)
38430499Slepreau ptrtemp->ds_pred += reldiff;
3852152Seric
3862152Seric ptrtemp = ptrtemp->ds_youngerdel;
3872152Seric }
3882152Seric
3892152Seric /*
3902152Seric Fix predecessor of current delta.
3912152Seric */
3922152Seric ptr->ds_pred = serhold + reldiff - 1;
3932152Seric
3942152Seric /*
3952152Seric Point to next (non-null) delta.
3962152Seric */
3972152Seric ptr = ptr->ds_youngerdel;
3982152Seric }
3992152Seric
4002152Seric /*
4012152Seric Create array of original values of serial numbers of
4022152Seric the original deltas.
4032152Seric */
4042152Seric ptr = Dtail;
4052152Seric while (ptr) {
4062152Seric if (ptr->ds_insnull != 1)
4072152Seric New_ser_ptr[ptr->ds_origser] = ptr->ds_ser;
4082152Seric ptr = ptr->ds_youngerdel;
4092152Seric }
4102152Seric }
4112152Seric
4122152Seric
ser_to_ptr(ser)4132152Seric ser_to_ptr(ser)
4142152Seric int ser;
4152152Seric {
4162152Seric struct deltalist *ptr;
4172152Seric
4182152Seric ptr = Dtail;
4192152Seric while (ptr) {
4202152Seric if (ptr->ds_ser == ser)
4212152Seric return(ptr);
4222152Seric ptr = ptr->ds_youngerdel;
4232152Seric }
4242152Seric fatal("internal error -- ser_to_ptr (sn2)");
4252152Seric }
4262152Seric
4272152Seric
wrtdeltbl(pkt)4282152Seric wrtdeltbl(pkt)
4292152Seric register struct packet *pkt;
4302152Seric {
4312152Seric struct deltalist *ptr;
4322152Seric char *p;
4332152Seric int ser;
4342152Seric
4352152Seric /*
4362152Seric The following loop writes out the new delta table.
4372152Seric */
4382152Seric ptr = Dhead;
4392152Seric while (ptr) {
4402152Seric if (ptr->ds_insnull) { /* 'null' delta */
4412152Seric /*
4422152Seric Write out statistics line.
4432152Seric */
444*33423Sbostic sprintf(line,"%c%c %05u/%05u/%05u\n",CTLCHAR,STATS,ptr->ds_stats.s_ins,ptr->ds_stats.s_del,ptr->ds_stats.s_unc);
445*33423Sbostic putline(pkt,line);
4462152Seric
4472152Seric /*
4482152Seric Write 'delta' line, taken from
4492152Seric in-core list.
4502152Seric */
4512152Seric putdel(pkt,ptr);
4522152Seric
453*33423Sbostic sprintf(line,"%c%c %s\n",CTLCHAR,COMMENTS,"INSERTED BY SNULL");
454*33423Sbostic putline(pkt,line);
455*33423Sbostic sprintf(line,CTLSTR,CTLCHAR,EDELTAB);
456*33423Sbostic putline(pkt,line);
4572152Seric }
4582152Seric else {
4592152Seric getline(pkt); /* statistics line */
4602152Seric getline(pkt); /* 'delta' line */
4612152Seric
4622152Seric /*
4632152Seric Indicate not to output previously read line.
4642152Seric */
4652152Seric pkt->p_wrttn = 1;
4662152Seric
4672152Seric /*
4682152Seric Write 'delta' line from in-core list.
4692152Seric */
4702152Seric putdel(pkt,ptr);
4712152Seric
4722152Seric /*
4732152Seric Process rest of entry, changeing serial
4742152Seric numbers of deltas included, excluded,
4752152Seric or ignored.
4762152Seric */
4772152Seric while (getline(pkt))
4782152Seric if (pkt->p_line[0] != CTLCHAR)
4792152Seric break;
4802152Seric else {
4812152Seric switch (*(p = &pkt->p_line[1])) {
4822152Seric case EDELTAB:
4832152Seric putline(pkt,0);
4842152Seric break;
4852152Seric case INCLUDE:
4862152Seric case EXCLUDE:
4872152Seric case IGNORE:
4882152Seric pkt->p_wrttn = 1;
489*33423Sbostic sprintf(line,"%c%c",CTLCHAR,*p++);
490*33423Sbostic putline(pkt,line);
4912152Seric NONBLANK(p);
4922152Seric while (numeric(*p)) {
4932152Seric p = satoi(p,&ser);
4942152Seric
4952152Seric if (!(ser > 0 &&
4962152Seric ser <= Max_old_ser))
4972152Seric fmterr(pkt);
4982152Seric
499*33423Sbostic sprintf(line," %u",New_ser_ptr[ser]);
500*33423Sbostic putline(pkt,line);
5012152Seric
5022152Seric NONBLANK(p);
5032152Seric }
5042152Seric putline(pkt,"\n");
5052152Seric continue;
5062152Seric default:
5072152Seric putline(pkt,0);
5082152Seric continue;
5092152Seric }
5102152Seric break;
5112152Seric }
5122152Seric }
5132152Seric
5142152Seric /*
5152152Seric Point to next delta to be output.
5162152Seric */
5172152Seric ptr = ptr->ds_olderdel;
5182152Seric }
5192152Seric }
5202152Seric
5212152Seric
5222152Seric putdel(pkt,ptr)
5232152Seric struct packet *pkt;
5242152Seric struct deltalist *ptr;
5252152Seric {
5262152Seric struct deltab dt;
5272152Seric
52819944Ssam bcopy(&ptr->ds_sid,&dt.d_sid,sizeof(dt.d_sid));
5292152Seric dt.d_serial = ptr->ds_ser;
5302152Seric dt.d_pred = ptr->ds_pred;
5312152Seric dt.d_datetime = ptr->ds_datetime;
53219944Ssam bcopy(ptr->ds_pgmr,&dt.d_pgmr,sizeof(dt.d_pgmr));
5332152Seric dt.d_type = ptr->ds_type;
5342152Seric
5352152Seric del_ba(&dt,line);
5362152Seric putline(pkt,line);
5372152Seric }
5382152Seric
5392152Seric
fixbody(pkt)5402152Seric fixbody(pkt)
5412152Seric register struct packet *pkt;
5422152Seric {
5432152Seric int ser;
5442152Seric char *p, type;
5452152Seric
5462152Seric while (getline(pkt)) {
5472152Seric p = pkt->p_line;
5482152Seric
5492152Seric if (*p++ == CTLCHAR) {
5502152Seric if (!((type = *p++) == INS || type == DEL ||
5512152Seric type == END))
5522152Seric fmterr(pkt);
5532152Seric NONBLANK(p);
5542152Seric satoi(p,&ser);
5552152Seric if (!(ser > 0 && ser <= Max_old_ser))
5562152Seric fmterr(pkt);
5572152Seric
5582152Seric /*
5592152Seric Indicate not to output line just read.
5602152Seric */
5612152Seric pkt->p_wrttn = 1;
5622152Seric
5632152Seric /*
5642152Seric Output new value of sequence number.
5652152Seric */
566*33423Sbostic sprintf(line,"%c%c %u\n",CTLCHAR,type,New_ser_ptr[ser]);
567*33423Sbostic putline(pkt,line);
5682152Seric }
5692152Seric }
5702152Seric }
5712152Seric
5722152Seric
clean_up(n)5732152Seric clean_up(n)
5742152Seric {
5752152Seric if (gpkt.p_file[0])
5762152Seric unlockit(auxf(gpkt.p_file,'z'),getpid());
5772152Seric if (gpkt.p_iop)
5782152Seric fclose(gpkt.p_iop);
5792152Seric xrm(&gpkt);
5802152Seric xfreeall();
5812152Seric }
582