home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / RCS_SRC.ZIP / RCSGEN.C < prev    next >
C/C++ Source or Header  |  1991-01-15  |  13KB  |  330 lines

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