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