1: /*
   2:  *                     RCS revision generation
   3:  */
   4: #ifndef lint
   5: static char rcsid[]= "$Id: rcsgen.c,v 3.6 88/04/24 17:32:22 bostic Exp $ Purdue CS";
   6: #endif
   7: /*********************************************************************************
   8:  *********************************************************************************
   9:  *
  10:  * Copyright (C) 1982 by Walter F. Tichy
  11:  *                       Purdue University
  12:  *                       Computer Science Department
  13:  *                       West Lafayette, IN 47907
  14:  *
  15:  * All rights reserved. No part of this software may be sold or distributed
  16:  * in any form or by any means without the prior written permission of the
  17:  * author.
  18:  * Report problems and direct all inquiries to Tichy@purdue (ARPA net).
  19:  */
  20: 
  21: 
  22: /* $Log:	rcsgen.c,v $
  23:  * Revision 3.6  88/04/24  17:32:22  bostic
  24:  * fix for ANSI C
  25:  *
  26:  * Revision 3.5  88/02/18  11:58:44  bostic
  27:  * replaced with version 4
  28:  *
  29:  * Revision 4.5  87/12/18  11:43:25  narten
  30:  * additional lint cleanups, and a bug fix from the 4.3BSD version that
  31:  * keeps "ci" from sticking a '\377' into the description if you run it
  32:  * with a zero-length file as the description. (Guy Harris)
  33:  *
  34:  * Revision 4.4  87/10/18  10:35:10  narten
  35:  * Updating version numbers. Changes relative to 1.1 actually relative to
  36:  * 4.2
  37:  *
  38:  * Revision 1.3  87/09/24  13:59:51  narten
  39:  * Sources now pass through lint (if you ignore printf/sprintf/fprintf
  40:  * warnings)
  41:  *
  42:  * Revision 1.2  87/03/27  14:22:27  jenkins
  43:  * Port to suns
  44:  *
  45:  * Revision 1.1  84/01/23  14:50:28  kcs
  46:  * Initial revision
  47:  *
  48:  * Revision 4.2  83/12/02  23:01:39  wft
  49:  * merged 4.1 and 3.3.1.1 (clearerr(stdin)).
  50:  *
  51:  * Revision 4.1  83/05/10  16:03:33  wft
  52:  * Changed putamin() to abort if trying to reread redirected stdin.
  53:  * Fixed getdesc() to output a prompt on initial newline.
  54:  *
  55:  * Revision 3.3.1.1  83/10/19  04:21:51  lepreau
  56:  * Added clearerr(stdin) for re-reading description from stdin.
  57:  *
  58:  * Revision 3.3  82/11/28  21:36:49  wft
  59:  * 4.2 prerelease
  60:  *
  61:  * Revision 3.3  82/11/28  21:36:49  wft
  62:  * Replaced ferror() followed by fclose() with ffclose().
  63:  * Putdesc() now suppresses the prompts if stdin
  64:  * is not a terminal. A pointer to the current log message is now
  65:  * inserted into the corresponding delta, rather than leaving it in a
  66:  * global variable.
  67:  *
  68:  * Revision 3.2  82/10/18  21:11:26  wft
  69:  * I added checks for write errors during editing, and improved
  70:  * the prompt on putdesc().
  71:  *
  72:  * Revision 3.1  82/10/13  15:55:09  wft
  73:  * corrected type of variables assigned to by getc (char --> int)
  74:  */
  75: 
  76: 
  77: 
  78: 
  79: #include "rcsbase.h"
  80: 
  81: extern struct hshentry * getnum();
  82: extern char * mktemp();
  83: extern FILE * fopen();
  84: extern savestring();
  85: extern struct hshentry * genrevs();
  86: extern editstring();
  87: 
  88: extern int nextc;          /* next character from lexical analyzer          */
  89: extern char * RCSfilename, * workfilename;
  90: extern struct hshentry * targetdelta; /* delta to be generated              */
  91: extern char * Ktext;       /* keywords from syntax analyzer                 */
  92: extern char * Klog;        /* Keyword "log"                                 */
  93: extern char * Kdesc;       /* Keyword for description                       */
  94: extern FILE * finptr;      /* RCS input file                                */
  95: extern FILE * frewrite;    /* new RCS file                                  */
  96: extern FILE * fcopy;       /* result file during editing                    */
  97: extern FILE * fedit;       /* edit file                                     */
  98: extern char * resultfile, *editfile;/* file names for fcopy and fedit       */
  99: extern int    rewriteflag; /* indicates whether to rewrite the input file   */
 100: 
 101: 
 102: char    curlogmsg[logsize];/* buffer for current log message                */
 103: 
 104: enum stringwork {copy, edit, expand, edit_expand };
 105: /* parameter to scandeltatext() */
 106: 
 107: 
 108: 
 109: 
 110: char * buildrevision(deltas, target, dir, expandflag)
 111: struct hshentry ** deltas, * target;
 112: char * dir; int expandflag;
 113: /* Function: Generates the revision given by target
 114:  * by retrieving all deltas given by parameter deltas and combining them.
 115:  * If dir==nil, the revision is printed on the standard output,
 116:  * otherwise written into a temporary file in directory dir.
 117:  * if expandflag==true, keyword expansion is performed.
 118:  * returns false on errors, the name of the file with the revision otherwise.
 119:  *
 120:  * Algorithm: Copy inital revision unchanged. Then edit all revisions but
 121:  * the last one into it, alternating input and output files (resultfile and
 122:  * editfile). The last revision is then edited in, performing simultaneous
 123:  * keyword substitution (this saves one extra pass).
 124:  * All this simplifies if only one revision needs to be generated,
 125:  * or no keyword expansion is necessary, or if output goes to stdout.
 126:  */
 127: {
 128:         int i;
 129: 
 130:         if (deltas[0]==target) {
 131:                 /* only latest revision to generate */
 132:                 if (dir==nil) {/* print directly to stdout */
 133:                         fcopy=stdout;
 134:                         scandeltatext(target,expand);
 135:                         return(char *) true;
 136:                 } else {
 137:                         initeditfiles(dir);
 138:                         scandeltatext(target,expandflag?expand:copy);
 139:                         ffclose(fcopy);
 140:                         return(resultfile);
 141:                 }
 142:         } else {
 143:                 /* several revisions to generate */
 144:                 initeditfiles(dir?dir:"/tmp/");
 145:                 /* write initial revision into fcopy, no keyword expansion */
 146:                 scandeltatext(deltas[0],copy);
 147:                 i = 1;
 148:                 while (deltas[i+1] != nil) {
 149:                         /* do all deltas except last one */
 150:                         scandeltatext(deltas[i++],edit);
 151:                 }
 152:                 if (!expandflag) {
 153:                         /* no keyword expansion; only invoked from ci */
 154:                         scandeltatext(deltas[i],edit);
 155:                         finishedit((struct hshentry *)nil);
 156:                         ffclose(fcopy);
 157:                 } else {
 158:                         /* perform keyword expansion*/
 159:                         /* first, get to beginning of file*/
 160:                         finishedit((struct hshentry *)nil); swapeditfiles(dir==nil);
 161:                         scandeltatext(deltas[i],edit_expand);
 162:                         finishedit(deltas[i]);
 163:                         if (dir!=nil) ffclose(fcopy);
 164:                 }
 165:                 return(resultfile); /*doesn't matter for dir==nil*/
 166:         }
 167: }
 168: 
 169: 
 170: 
 171: scandeltatext(delta,func)
 172: struct hshentry * delta; enum stringwork func;
 173: /* Function: Scans delta text nodes up to and including the one given
 174:  * by delta. For the one given by delta, the log message is saved into
 175:  * curlogmsg and the text is processed according to parameter func.
 176:  * Assumes the initial lexeme must be read in first.
 177:  * Does not advance nexttok after it is finished.
 178:  */
 179: {       struct hshentry * nextdelta;
 180: 
 181:         do {
 182:                 nextlex();
 183:                 if (!(nextdelta=getnum())) {
 184:                         fatserror("Can't find delta for revision %s", delta->num);
 185:                 }
 186:                 if (!getkey(Klog) || nexttok!=STRING)
 187:                         serror("Missing log entry");
 188:                 elsif (delta==nextdelta) {
 189:                         VOID savestring(curlogmsg,logsize);
 190:                         delta->log=curlogmsg;
 191:                 } else {readstring();
 192:                         delta->log= "";
 193:                 }
 194:                 nextlex();
 195:                 if (!getkey(Ktext) || nexttok!=STRING)
 196:                         fatserror("Missing delta text");
 197: 
 198:                 if(delta==nextdelta)
 199:                         /* got the one we're looking for */
 200:                         switch (func) {
 201:                         case copy:      copystring();
 202:                                         break;
 203:                         case expand:    xpandstring(delta);
 204:                                         break;
 205:                         case edit:      editstring((struct hshentry *)nil);
 206:                                         break;
 207:                         case edit_expand: editstring(delta);
 208:                                         break;
 209:                         }
 210:                 else    readstring(); /* skip over it */
 211: 
 212:         } while (delta!=nextdelta);
 213: }
 214: 
 215: 
 216: int stdinread = 0; /* stdinread>0 if redirected stdin has been read once */
 217: 
 218: int putdesc(initflag,textflag,textfile,quietflag)
 219: int initflag,textflag; char * textfile; int quietflag;
 220: /* Function: puts the descriptive text into file frewrite.
 221:  * if !initflag && !textflag, the text is simply copied from finptr.
 222:  * Otherwise, if the textfile!=nil, the text is read from that
 223:  * file, or from stdin, if textfile==nil.
 224:  * Increments stdinread if text is read from redirected stdin.
 225:  * if initflag&&quietflag&&!textflag, an empty text is inserted.
 226:  * if !initflag, the old descriptive text is discarded.
 227:  * Returns true is successful, false otherwise.
 228:  */
 229: {       FILE * txt; register int c, old1, old2;
 230: #ifdef lint
 231:     if (quietflag ==  0) initflag = quietflag; /* silencelint */
 232: #endif
 233:         if (!initflag && !textflag) {
 234:                 /* copy old description */
 235:                 VOID fprintf(frewrite,"\n\n%s%c",Kdesc,nextc);
 236:                 rewriteflag=true; getdesc(false);
 237:                 return true;
 238:         } else {
 239:                 /* get new description */
 240:                if (!initflag) {
 241:                         /*skip old description*/
 242:                         rewriteflag=false; getdesc(false);
 243:                 }
 244:                 VOID fprintf(frewrite,"\n\n%s\n%c",Kdesc,SDELIM);
 245:                 if (textfile) {
 246:                         old1='\n';
 247:                         /* copy textfile */
 248:                         if ((txt=fopen(textfile,"r"))!=NULL) {
 249:                                 while ((c=getc(txt))!=EOF) {
 250:                                         if (c==SDELIM) VOID putc(c,frewrite); /*double up*/
 251:                                         VOID putc(c,frewrite);
 252:                                         old1=c;
 253:                                 }
 254:                                 if (old1!='\n') VOID putc('\n',frewrite);
 255:                                 VOID fclose(txt);
 256:                                 VOID putc(SDELIM,frewrite);
 257:                 VOID fputs("\n\n", frewrite);
 258:                                 return true;
 259:                         } else {
 260:                                 error("Can't open file %s with description",textfile);
 261:                                 if (!isatty(fileno(stdin))) return false;
 262:                                 /* otherwise, get description from terminal */
 263:                         }
 264:                 }
 265:                 /* read text from stdin */
 266:                 if (isatty(fileno(stdin))) {
 267:                     VOID fputs("enter description, terminated with ^D or '.':\n",stderr);
 268:                     VOID fputs("NOTE: This is NOT the log message!\n>> ",stderr);
 269:             if (feof(stdin))
 270:                     clearerr(stdin);
 271:                 } else {  /* redirected stdin */
 272:                     if (stdinread>0)
 273:                         faterror("Can't reread redirected stdin for description; use -t<file>");
 274:                     stdinread++;
 275:                 }
 276:                 c = '\0'; old2= '\n';
 277:                 if ((old1=getchar())==EOF) {
 278:                         if (isatty(fileno(stdin))) {
 279:                              VOID putc('\n',stderr);
 280:                              clearerr(stdin);
 281:             }
 282:         } else {
 283:              if (old1=='\n' && isatty(fileno(stdin)))
 284:              VOID fputs(">> ",stderr);
 285:              for (;;) {
 286:                             c=getchar();
 287:                             if (c==EOF) {
 288:                                     if (isatty(fileno(stdin))) {
 289:                                             VOID putc('\n',stderr);
 290:                                             clearerr(stdin);
 291:                     }
 292:                                     VOID putc(old1,frewrite);
 293:                                     if (old1!='\n') VOID putc('\n',frewrite);
 294:                                     break;
 295:                             }
 296:                             if (c=='\n' && old1=='.' && old2=='\n') {
 297:                                     break;
 298:                             }
 299:                             if (c=='\n' && isatty(fileno(stdin))) VOID fputs(">> ",stderr);
 300:                             if(old1==SDELIM) VOID putc(old1,frewrite); /* double up*/
 301:                             VOID putc(old1,frewrite);
 302:                             old2=old1;
 303:                             old1=c;
 304:                     } /* end for */
 305:         }
 306:                 VOID putc(SDELIM,frewrite);VOID fputs("\n\n",frewrite);
 307:                 return true;
 308:         }
 309: }

Defined functions

buildrevision defined in line 110; used 5 times
putdesc defined in line 218; used 2 times
scandeltatext defined in line 171; used 6 times

Defined variables

curlogmsg defined in line 102; used 6 times
rcsid defined in line 5; never used
stdinread defined in line 216; used 4 times

Defined enum's

stringwork defined in line 104; used 2 times
  • in line 172(2)
Last modified: 1988-04-25
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2665
Valid CSS Valid XHTML 1.0 Strict