Annotation of 43BSDReno/contrib/rcs/src/rcsedit.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *                     RCS stream editor
                      3:  */
                      4: #ifndef lint
                      5: static char rcsid[]= "$Id: rcsedit.c,v 3.11 89/08/15 21:37:31 bostic Exp $ Purdue CS";
                      6: #endif
                      7: /**********************************************************************************
                      8:  *                       edits the input file according to a
                      9:  *                       script from stdin, generated by diff -n
                     10:  *                       performs keyword expansion
                     11:  **********************************************************************************
                     12:  */
                     13: 
                     14: /* Copyright (C) 1982, 1988, 1989 Walter Tichy
                     15:  * All rights reserved.
                     16:  *
                     17:  * Redistribution and use in source and binary forms are permitted
                     18:  * provided that the above copyright notice and this paragraph are
                     19:  * duplicated in all such forms and that any documentation,
                     20:  * advertising materials, and other materials related to such
                     21:  * distribution and use acknowledge that the software was developed
                     22:  * by Walter Tichy.
                     23:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     26:  *
                     27:  * Report all problems and direct all questions to:
                     28:  *   [email protected]
                     29:  * 
                     30: 
                     31: 
                     32: 
                     33: 
                     34: 
                     35: 
                     36: 
                     37: */
                     38: 
                     39: 
                     40: /* $Log:       rcsedit.c,v $
                     41:  * Revision 3.11  89/08/15  21:37:31  bostic
                     42:  * Version 4 from Tom Narten at Purdue
                     43:  * 
                     44:  * Revision 4.8  89/05/01  15:12:35  narten
                     45:  * changed copyright header to reflect current distribution rules
                     46:  * 
                     47:  * Revision 4.7  88/11/08  13:54:14  narten
                     48:  * misplaced semicolon caused infinite loop
                     49:  * 
                     50:  * Revision 4.6  88/11/08  12:01:41  narten
                     51:  * changes from  [email protected] (Paul Eggert)
                     52:  * 
                     53:  * Revision 4.6  88/08/09  19:12:45  eggert
                     54:  * Shrink stdio code size; allow cc -R.
                     55:  * 
                     56:  * Revision 4.5  87/12/18  11:38:46  narten
                     57:  * Changes from the 43. version. Don't know the significance of the
                     58:  * first change involving "rewind". Also, additional "lint" cleanup.
                     59:  * (Guy Harris)
                     60:  * 
                     61:  * Revision 4.4  87/10/18  10:32:21  narten
                     62:  * Updating version numbers. Changes relative to version 1.1 actually
                     63:  * relative to 4.1
                     64:  * 
                     65:  * Revision 1.4  87/09/24  13:59:29  narten
                     66:  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
                     67:  * warnings)
                     68:  * 
                     69:  * Revision 1.3  87/09/15  16:39:39  shepler
                     70:  * added an initializatin of the variables editline and linecorr
                     71:  * this will be done each time a file is processed.
                     72:  * (there was an obscure bug where if co was used to retrieve multiple files
                     73:  *  it would dump)
                     74:  * fix attributed to  Roy Morris @FileNet Corp ...!felix!roy
                     75:  * 
                     76:  * Revision 1.2  87/03/27  14:22:17  jenkins
                     77:  * Port to suns
                     78:  * 
                     79:  * Revision 1.1  84/01/23  14:50:20  kcs
                     80:  * Initial revision
                     81:  * 
                     82:  * Revision 4.1  83/05/12  13:10:30  wft
                     83:  * Added new markers Id and RCSfile; added locker to Header and Id.
                     84:  * Overhauled expandline completely() (problem with $01234567890123456789@).
                     85:  * Moved trymatch() and marker table to rcskeys.c.
                     86:  * 
                     87:  * Revision 3.7  83/05/12  13:04:39  wft
                     88:  * Added retry to expandline to resume after failed match which ended in $.
                     89:  * Fixed truncation problem for $19chars followed by@@.
                     90:  * Log no longer expands full path of RCS file.
                     91:  * 
                     92:  * Revision 3.6  83/05/11  16:06:30  wft
                     93:  * added retry to expandline to resume after failed match which ended in $.
                     94:  * Fixed truncation problem for $19chars followed by@@.
                     95:  * 
                     96:  * Revision 3.5  82/12/04  13:20:56  wft
                     97:  * Added expansion of keyword Locker.
                     98:  *
                     99:  * Revision 3.4  82/12/03  12:26:54  wft
                    100:  * Added line number correction in case editing does not start at the
                    101:  * beginning of the file.
                    102:  * Changed keyword expansion to always print a space before closing KDELIM;
                    103:  * Expansion for Header shortened.
                    104:  *
                    105:  * Revision 3.3  82/11/14  14:49:30  wft
                    106:  * removed Suffix from keyword expansion. Replaced fclose with ffclose.
                    107:  * keyreplace() gets log message from delta, not from curlogmsg.
                    108:  * fixed expression overflow in while(c=putc(GETC....
                    109:  * checked nil printing.
                    110:  *
                    111:  * Revision 3.2  82/10/18  21:13:39  wft
                    112:  * I added checks for write errors during the co process, and renamed
                    113:  * expandstring() to xpandstring().
                    114:  *
                    115:  * Revision 3.1  82/10/13  15:52:55  wft
                    116:  * changed type of result of getc() from char to int.
                    117:  * made keyword expansion loop in expandline() portable to machines
                    118:  * without sign-extension.
                    119:  */
                    120: 
                    121: 
                    122: #include "rcsbase.h"
                    123: 
                    124: 
                    125: extern FILE * fopen();
                    126: extern char * mktempfile();
                    127: extern char * bindex();
                    128: extern FILE * finptr, * frewrite;
                    129: extern int rewriteflag;
                    130: extern int nextc;
                    131: extern char * RCSfilename, * workfilename;
                    132: extern char * bindex();
                    133: extern char * getfullRCSname();
                    134: extern enum markers trymatch();
                    135: 
                    136: 
                    137: FILE  * fcopy,  * fedit; /* result and edit file descriptors                */
                    138: char  *resultfile;       /* result file name                                */
                    139: char  * editfile;        /* edit   file name                                */
                    140: int editline;  /*line counter in fedit; starts with 1, is always #lines+1   */
                    141: int linecorr;  /*contains #adds - #deletes in each edit run.                */
                    142:                /*used to correct editline in case file is not rewound after */
                    143:                /* applying one delta                                        */
                    144: 
                    145: initeditfiles(dir)
                    146: char * dir;
                    147: /* Function: Initializes resultfile and editfile with temporary filenames
                    148:  * in directory dir. Opens resultfile for reading and writing, with fcopy
                    149:  * as file descriptor. fedit is set to nil.
                    150:  */
                    151: {
                    152:        editline = linecorr = 0;    /* make sure we start from the beginning*/
                    153:         resultfile=mktempfile(dir,TMPFILE1);
                    154:         editfile  =mktempfile(dir,TMPFILE2);
                    155:         fedit=nil;
                    156:         if ((fcopy=fopen(resultfile,"w+"))==NULL) {
                    157:                 faterror("Can't open working file %s",resultfile);
                    158:         }
                    159: }
                    160: 
                    161: 
                    162: swapeditfiles(tostdout)
                    163: /* Function: swaps resultfile and editfile, assigns fedit=fcopy,
                    164:  * rewinds fedit for reading, and opens resultfile for reading and
                    165:  * writing, using fcopy. If tostdout, fcopy is set to stdout.
                    166:  */
                    167: {       char * tmpptr;
                    168:         if(ferror(fcopy))
                    169:                 faterror("write failed on %s -- file system full?",resultfile);
                    170:         fedit=fcopy;
                    171:         rewind(fedit);
                    172:         editline = 1; linecorr=0;
                    173:         tmpptr=editfile; editfile=resultfile; resultfile=tmpptr;
                    174:         if (tostdout)
                    175:                 fcopy=stdout;
                    176:         elsif ((fcopy=fopen(resultfile,"w+"))==NULL) {
                    177:                 faterror("Can't open working file %s",resultfile);
                    178:         }
                    179: }
                    180: 
                    181: 
                    182: finishedit(delta)
                    183: struct hshentry * delta;
                    184: /* copy the rest of the edit file and close it (if it exists).
                    185:  * if delta!=nil, perform keyword substitution at the same time.
                    186:  */
                    187: {
                    188:         register int c;
                    189:         if (fedit!=nil) {
                    190:                 if (delta!=nil) {
                    191:                         while (expandline(fedit,fcopy,delta,false,false)) editline++;
                    192:                 } else {
                    193:                         while((c=getc(fedit))!=EOF) {
                    194:                                 VOID putc(c,fcopy);
                    195:                                 if (c=='\n') editline++;
                    196:                         }
                    197:                 }
                    198:                 ffclose(fedit);
                    199:         }
                    200: }
                    201: 
                    202: 
                    203: copylines(line,delta)
                    204: register int line; struct hshentry * delta;
                    205: /* Function: copies input lines editline..line-1 from fedit to fcopy.
                    206:  * If delta != nil, keyword expansion is done simultaneously.
                    207:  * editline is updated. Rewinds a file only if necessary.
                    208:  */
                    209: {
                    210: 
                    211:         if (editline>line) {
                    212:                 /* swap files */
                    213:                 finishedit((struct hshentry *)nil); swapeditfiles(false);
                    214:                 /* assumes edit only during last pass, from the beginning*/
                    215:         }
                    216:         while (editline<line) {
                    217:                 /*copy another line*/
                    218:                 if (delta)
                    219:                         VOID expandline(fedit,fcopy,delta,false,false);
                    220:                 else
                    221:                         while (putc(getc(fedit),fcopy)!='\n');
                    222:                 editline++;
                    223:         }
                    224: }
                    225: 
                    226: 
                    227: 
                    228: xpandstring(delta)
                    229: struct hshentry * delta;
                    230: /* Function: Reads a string terminated by SDELIM from finptr and writes it
                    231:  * to fcopy. Double SDELIM is replaced with single SDELIM.
                    232:  * Keyword expansion is performed with data from delta.
                    233:  * If rewriteflag==true, the string is also copied unchanged to frewrite.
                    234:  * editline is updated.
                    235:  */
                    236: {
                    237:         editline=1;
                    238:         while (expandline(finptr,fcopy,delta,true,rewriteflag)) editline++;
                    239:         nextc='\n';
                    240: }
                    241: 
                    242: 
                    243: copystring()
                    244: /* Function: copies a string terminated with a single SDELIM from finptr to
                    245:  * fcopy, replacing all double SDELIM with a single SDELIM.
                    246:  * If rewriteflag==true, the string also copied unchanged to frewrite.
                    247:  * editline is set to (number of lines copied)+1.
                    248:  * Assumption: next character read is first string character.
                    249:  */
                    250: {      register c;
                    251:        register FILE *fin, *frew, *fcop;
                    252:        register write;
                    253: 
                    254:        fin=finptr; frew=frewrite; fcop=fcopy;
                    255:         write=rewriteflag;
                    256:         editline=1;
                    257:         while ((c=GETC(fin,frew,write)) != EOF) {
                    258:                 if ((c==SDELIM)&&((c=GETC(fin,frew,write)) != SDELIM)){
                    259:                         /* end of string */
                    260:                         nextc = c;
                    261:                         return;
                    262:                 }
                    263:                 VOID putc(c,fcop);
                    264:                 if (c=='\n') editline++;
                    265:         }
                    266:         nextc = c;
                    267:         serror("Unterminated string");
                    268:         return;
                    269: }
                    270: 
                    271: 
                    272: 
                    273: 
                    274: editstring(delta)
                    275: struct hshentry * delta;
                    276: /* Function: reads an edit script from finptr and applies it to
                    277:  * file fedit; the result is written to fcopy.
                    278:  * If delta!=nil, keyword expansion is performed simultaneously.
                    279:  * If frewrite==true, the edit script is also copied verbatim to frewrite.
                    280:  * Assumes that all these files are open.
                    281:  * If running out of lines in fedit, fedit and fcopy are swapped.
                    282:  * resultfile and editfile are the names of the files that go with fcopy
                    283:  * and fedit, respectively.
                    284:  * Assumes the next input character from finptr is the first character of
                    285:  * the edit script. Resets nextc on exit.
                    286:  */
                    287: {
                    288:         int ed; /* editor command */
                    289:         register int c;
                    290:        register FILE *fin, *frew;
                    291:         register int write, i;
                    292:         int line, length;
                    293: 
                    294:        fin=finptr;  frew=frewrite;
                    295:         editline += linecorr; linecorr=0; /*correct line number*/
                    296:         write=rewriteflag;
                    297:         for (;;) {
                    298:                 /* read next command and decode */
                    299:                 /* assume next non-white character is command name*/
                    300:                 while((ed=GETC(fin,frew,write))=='\n'||
                    301:                         ed==' ' || ed=='\t');
                    302:                 if (ed==SDELIM) break;
                    303:                 /* now attempt to read numbers. */
                    304:                 /* fscanf causes trouble because of the required echoing */
                    305:                 while ((c=GETC(fin,frew,write))==' ');  /*skip spaces*/
                    306:                 if (!('0'<=c && c<='9')) {
                    307:                         faterror("missing line number in edit script");
                    308:                         break;
                    309:                 }
                    310:                 line= c -'0';
                    311:                 while ('0'<=(c=GETC(fin,frew,write)) && c<='9') {
                    312:                         line = line*10 + c-'0';
                    313:                 }
                    314:                 while (c==' ') c=GETC(fin,frew,write);
                    315:                 if (!('0'<=c && c<='9')) {
                    316:                         faterror("incorrect range in edit script");
                    317:                         break;
                    318:                 }
                    319:                 length= c -'0';
                    320:                 while ('0'<=(c=GETC(fin,frew,write)) && c<='9') {
                    321:                         length = length*10 + c-'0';
                    322:                 }
                    323:                 while(c!='\n'&&c!=EOF) c=GETC(fin,frew,write); /* skip to end of line */
                    324: 
                    325:                 switch (ed) {
                    326:                 case 'd':
                    327:                         copylines(line,delta);
                    328:                         /* skip over unwanted lines */
                    329:                         for (i=length;i>0;i--) {
                    330:                                 /*skip next line*/
                    331:                                 while ((c=getc(fedit))!='\n')
                    332:                                        if (c==EOF)
                    333:                                                faterror("EOF during edit");
                    334:                                 editline++;
                    335:                         }
                    336:                         linecorr -= length;
                    337:                         break;
                    338:                 case 'a':
                    339:                         copylines(line+1,delta); /*copy only; no delete*/
                    340:                         for (i=length;i>0;i--) {
                    341:                                 /*copy next line from script*/
                    342:                                 if (delta!=nil)
                    343:                                        VOID expandline(fin,fcopy,delta,true,write);
                    344:                                 else {
                    345:                                        c = GETC(fin,frew,write);
                    346:                                        while (putc(c,fcopy)!='\n'){
                    347:                                                if ((c==SDELIM)&&((c=GETC(fin,frew,write))!=SDELIM)){
                    348:                                                        serror("Missing string delimiter in edit script");
                    349:                                                        VOID putc(c,fcopy);
                    350:                                                }
                    351:                                                c = GETC(fin,frew,write);
                    352:                                        }
                    353:                                 }
                    354:                         }
                    355:                         linecorr += length;
                    356:                         break;
                    357:                 default:
                    358:                         faterror("unknown command in edit script: %c", ed);
                    359:                         break;
                    360:                 }
                    361:         }
                    362:         nextc=GETC(fin,frew,write);
                    363: }
                    364: 
                    365: 
                    366: 
                    367: /* The rest is for keyword expansion */
                    368: 
                    369: 
                    370: 
                    371: expandline(in, out, delta,delimstuffed,write)
                    372: register FILE * in, * out; struct hshentry * delta;
                    373: int delimstuffed, write;
                    374: /* Function: Reads a line from in and writes it to out.
                    375:  * If delimstuffed==true, double SDELIM is replaced with single SDELIM.
                    376:  * Keyword expansion is performed with data from delta.
                    377:  * If write==true, the string is also copied unchanged to frewrite.
                    378:  * Returns false if end-of-string or end-of-line is detected, true otherwise.
                    379:  */
                    380: {
                    381:        register c;
                    382:        register FILE * frew;
                    383:        register w, ds;
                    384:        register char * tp;
                    385:        char keystring[keylength+2];
                    386:        char keyval[keyvallength+2];
                    387:         enum markers matchresult;
                    388: 
                    389:        frew = frewrite;
                    390:        w = write;
                    391:        ds = delimstuffed;
                    392:        c=GETC(in,frew,w);
                    393:         for (;;) {
                    394:                 if (c==EOF) {
                    395:                         if(ds) {
                    396:                                 error("unterminated string");
                    397:                                 nextc=c;
                    398:                         }
                    399:                         return(false);
                    400:                 }
                    401: 
                    402:                 if (c==SDELIM && ds) {
                    403:                         if ((c=GETC(in,frew,w))!=SDELIM) {
                    404:                                 /* end of string */
                    405:                                 nextc=c;
                    406:                                 return false;
                    407:                         }
                    408:                 }
                    409:                 VOID putc(c,out);
                    410: 
                    411:                 if (c=='\n') return true; /* end of line */
                    412: 
                    413:                if (c==KDELIM) {
                    414:                         /* check for keyword */
                    415:                         /* first, copy a long enough string into keystring */
                    416:                        tp=keystring;
                    417:                        while (((c=GETC(in,frew,w))!=EOF) && (tp<keystring+keylength) && (c!='\n')
                    418:                               && (c!=SDELIM) && (c!=KDELIM) && (c!=VDELIM)) {
                    419:                               VOID putc(c,out);
                    420:                              *tp++ = c;
                    421:                         }
                    422:                        *tp++ = c; *tp = '\0';
                    423:                        matchresult=trymatch(keystring,false);
                    424:                        if (matchresult==Nomatch) continue;
                    425:                        /* last c will be dealt with properly by continue*/
                    426: 
                    427:                        /* Now we have a keyword terminated with a K/VDELIM */
                    428:                        if (c==VDELIM) {
                    429:                              /* try to find closing KDELIM, and replace value */
                    430:                              tp=keyval;
                    431:                              while (((c=GETC(in,frew,w)) != EOF)
                    432:                                     && (c!='\n') && (c!=KDELIM) && (tp<keyval+keyvallength)) {
                    433:                                      *tp++ =c;
                    434:                                      if (c==SDELIM && ds) { /*skip next SDELIM */
                    435:                                                c=GETC(in,frew,w);
                    436:                                                /* Can't be at end of string.
                    437:                                                /* always a \n before closing SDELIM */
                    438:                                      }
                    439:                              }
                    440:                              if (c!=KDELIM) {
                    441:                                    /* couldn't find closing KDELIM -- give up */
                    442:                                    VOID putc(VDELIM,out); *tp='\0';
                    443:                                    VOID fputs(keyval,out);
                    444:                                    continue;   /* last c handled properly */
                    445:                              }
                    446:                        }
                    447:                        /* now put out the new keyword value */
                    448:                        keyreplace(matchresult,delta,out);
                    449:                 }
                    450:                 c=GETC(in,frew,w);
                    451:         } /* end for */
                    452: }
                    453: 
                    454: 
                    455: 
                    456: keyreplace(marker,delta,out)
                    457: enum markers marker; struct hshentry * delta; register FILE * out;
                    458: /* function: ouputs the keyword value(s) corresponding to marker.
                    459:  * Attributes are derived from delta.
                    460:  */
                    461: {
                    462:         char * date;
                    463:         register char * sp;
                    464: 
                    465:         date= delta->date;
                    466: 
                    467:         switch (marker) {
                    468:         case Author:
                    469:                 VOID fprintf(out,"%c %s %c",VDELIM,delta->author,KDELIM);
                    470:                 break;
                    471:         case Date:
                    472:                 VOID putc(VDELIM,out);VOID putc(' ',out);
                    473:                 VOID PRINTDATE(out,date);VOID putc(' ',out);
                    474:                 VOID PRINTTIME(out,date);VOID putc(' ',out);VOID putc(KDELIM,out);
                    475:                 break;
                    476:         case Id:
                    477:        case Header:
                    478:                VOID putc(VDELIM,out); VOID putc(' ',out);
                    479:                if (marker==Id)
                    480:                         VOID fputs(bindex(RCSfilename,'/'),out);
                    481:                else     VOID fputs(getfullRCSname(),out);
                    482:                VOID fprintf(out," %s ", delta->num);
                    483:                 VOID PRINTDATE(out,date);VOID putc(' ',out);VOID PRINTTIME(out,date);
                    484:                VOID fprintf(out, " %s %s ",delta->author,delta->state);
                    485:                if (delta->lockedby!=nil)
                    486:                         VOID fprintf(out,"Locker: %s ",delta->lockedby);
                    487:                VOID putc(KDELIM,out);
                    488:                 break;
                    489:         case Locker:
                    490:                 VOID fprintf(out,"%c %s %c", VDELIM,
                    491:                         delta->lockedby==nil?"":delta->lockedby,KDELIM);
                    492:                 break;
                    493:         case Log:
                    494:                 VOID fprintf(out, "%c\t%s %c\n%sRevision %s  ",
                    495:                         VDELIM, bindex(RCSfilename,'/'), KDELIM, Comment, delta->num);
                    496:                 VOID PRINTDATE(out,date);VOID fputs("  ",out);VOID PRINTTIME(out,date);
                    497:                 VOID fprintf(out, "  %s\n%s",delta->author,Comment);
                    498:                 /* do not include state here because it may change and is not updated*/
                    499:                 sp = delta->log;
                    500:                 while (*sp) if (putc(*sp++,out)=='\n') VOID fputs(Comment,out);
                    501:                 /* Comment is the comment leader */
                    502:                 break;
                    503:         case RCSfile:
                    504:                 VOID fprintf(out,"%c %s %c",VDELIM,bindex(RCSfilename,'/'),KDELIM);
                    505:                 break;
                    506:         case Revision:
                    507:                 VOID fprintf(out,"%c %s %c",VDELIM,delta->num,KDELIM);
                    508:                 break;
                    509:         case Source:
                    510:                 VOID fprintf(out,"%c %s %c",VDELIM,getfullRCSname(),KDELIM);
                    511:                 break;
                    512:         case State:
                    513:                 VOID fprintf(out,"%c %s %c",VDELIM,delta->state,KDELIM);
                    514:                 break;
                    515:         case Nomatch:
                    516:                 VOID putc(KDELIM,out);
                    517:                 break;
                    518:         }
                    519: }
                    520: 
                    521: 

unix.superglobalmegacorp.com

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