|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.