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