home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / CMDS / rcs4.lha / rcsedit.c < prev    next >
Text File  |  1993-03-03  |  18KB  |  481 lines

  1. /*
  2.  *                     RCS stream editor
  3.  */
  4. #ifndef lint
  5. static char rcsid[]= "$Id: rcsedit.c,v 4.5 87/12/18 11:38:46 narten Exp $ Purdue CS";
  6. #endif
  7. /**********************************************************************************
  8.  *                       edits the input file according to a
  9.  *                       script from stdin, generated by diff -n
  10.  *                       performs keyword expansion
  11.  **********************************************************************************
  12.  *
  13.  * Copyright (C) 1982 by Walter F. Tichy
  14.  *                       Purdue University
  15.  *                       Computer Science Department
  16.  *                       West Lafayette, IN 47907
  17.  *
  18.  * All rights reserved. No part of this software may be sold or distributed
  19.  * in any form or by any means without the prior written permission of the
  20.  * author.
  21.  * Report problems and direct all inquiries to Tichy@purdue (ARPA net).
  22.  */
  23.  
  24.  
  25. /* $Log:    rcsedit.c,v $
  26.  * Revision 4.5  87/12/18  11:38:46  narten
  27.  * Changes from the 43. version. Don't know the significance of the
  28.  * first change involving "rewind". Also, additional "lint" cleanup.
  29.  * (Guy Harris)
  30.  * 
  31.  * Revision 4.4  87/10/18  10:32:21  narten
  32.  * Updating version numbers. Changes relative to version 1.1 actually
  33.  * relative to 4.1
  34.  * 
  35.  * Revision 1.4  87/09/24  13:59:29  narten
  36.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  37.  * warnings)
  38.  * 
  39.  * Revision 1.3  87/09/15  16:39:39  shepler
  40.  * added an initializatin of the variables editline and linecorr
  41.  * this will be done each time a file is processed.
  42.  * (there was an obscure bug where if co was used to retrieve multiple files
  43.  *  it would dump)
  44.  * fix attributed to  Roy Morris @FileNet Corp ...!felix!roy
  45.  * 
  46.  * Revision 1.2  87/03/27  14:22:17  jenkins
  47.  * Port to suns
  48.  * 
  49.  * Revision 1.1  84/01/23  14:50:20  kcs
  50.  * Initial revision
  51.  * 
  52.  * Revision 4.1  83/05/12  13:10:30  wft
  53.  * Added new markers Id and RCSfile; added locker to Header and Id.
  54.  * Overhauled expandline completely() (problem with $01234567890123456789@).
  55.  * Moved trymatch() and marker table to rcskeys.c.
  56.  * 
  57.  * Revision 3.7  83/05/12  13:04:39  wft
  58.  * Added retry to expandline to resume after failed match which ended in $.
  59.  * Fixed truncation problem for $19chars followed by@@.
  60.  * Log no longer expands full path of RCS file.
  61.  * 
  62.  * Revision 3.6  83/05/11  16:06:30  wft
  63.  * added retry to expandline to resume after failed match which ended in $.
  64.  * Fixed truncation problem for $19chars followed by@@.
  65.  * 
  66.  * Revision 3.5  82/12/04  13:20:56  wft
  67.  * Added expansion of keyword Locker.
  68.  *
  69.  * Revision 3.4  82/12/03  12:26:54  wft
  70.  * Added line number correction in case editing does not start at the
  71.  * beginning of the file.
  72.  * Changed keyword expansion to always print a space before closing KDELIM;
  73.  * Expansion for Header shortened.
  74.  *
  75.  * Revision 3.3  82/11/14  14:49:30  wft
  76.  * removed Suffix from keyword expansion. Replaced fclose with ffclose.
  77.  * keyreplace() gets log message from delta, not from curlogmsg.
  78.  * fixed expression overflow in while(c=putc(GETC....
  79.  * checked nil printing.
  80.  *
  81.  * Revision 3.2  82/10/18  21:13:39  wft
  82.  * I added checks for write errors during the co process, and renamed
  83.  * expandstring() to xpandstring().
  84.  *
  85.  * Revision 3.1  82/10/13  15:52:55  wft
  86.  * changed type of result of getc() from char to int.
  87.  * made keyword expansion loop in expandline() portable to machines
  88.  * without sign-extension.
  89.  */
  90.  
  91.  
  92. #include "rcsbase.h"
  93.  
  94.  
  95. extern FILE * fopen();
  96. extern char * mktempfile();
  97. extern char * bindex();
  98. extern FILE * finptr, * frewrite;
  99. extern int rewriteflag;
  100. extern int nextc;
  101. extern char * RCSfilename, * workfilename;
  102. extern char * bindex();
  103. extern char * getfullRCSname();
  104. extern enum markers trymatch();
  105.  
  106.  
  107. FILE  * fcopy,  * fedit; /* result and edit file descriptors                */
  108. char  *resultfile = nil; /* result file name                                */
  109. char  * editfile  = nil; /* edit   file name                                */
  110. int editline;  /*line counter in fedit; starts with 1, is always #lines+1   */
  111. int linecorr;  /*contains #adds - #deletes in each edit run.                */
  112.                /*used to correct editline in case file is not rewound after */
  113.                /* applying one delta                                        */
  114.  
  115. initeditfiles(dir)
  116. char * dir;
  117. /* Function: Initializes resultfile and editfile with temporary filenames
  118.  * in directory dir. Opens resultfile for reading and writing, with fcopy
  119.  * as file descriptor. fedit is set to nil.
  120.  */
  121. {
  122.     editline = linecorr = 0;    /* make sure we start from the beginning*/
  123.         resultfile=mktempfile(dir,TMPFILE1);
  124.         editfile  =mktempfile(dir,TMPFILE2);
  125.         fedit=nil;
  126.         if ((fcopy=fopen(resultfile,"w+"))==NULL) {
  127.                 faterror("Can't open working file %s",resultfile);
  128.         }
  129. }
  130.  
  131.  
  132. swapeditfiles(tostdout)
  133. /* Function: swaps resultfile and editfile, assigns fedit=fcopy,
  134.  * rewinds fedit for reading, and opens resultfile for reading and
  135.  * writing, using fcopy. If tostdout, fcopy is set to stdout.
  136.  */
  137. {       char * tmpptr;
  138.         if(ferror(fcopy))
  139.                 faterror("write failed on %s -- file system full?",resultfile);
  140.         fedit=fcopy;
  141.         rewind(fedit);
  142.         editline = 1; linecorr=0;
  143.         tmpptr=editfile; editfile=resultfile; resultfile=tmpptr;
  144.         if (tostdout)
  145.                 fcopy=stdout;
  146.         elsif ((fcopy=fopen(resultfile,"w+"))==NULL) {
  147.                 faterror("Can't open working file %s",resultfile);
  148.         }
  149. }
  150.  
  151.  
  152. finishedit(delta)
  153. struct hshentry * delta;
  154. /* copy the rest of the edit file and close it (if it exists).
  155.  * if delta!=nil, perform keyword substitution at the same time.
  156.  */
  157. {
  158.         register int c;
  159.         if (fedit!=nil) {
  160.                 if (delta!=nil) {
  161.                         while (expandline(fedit,fcopy,delta,false,false)) editline++;
  162.                 } else {
  163.                         while((c=getc(fedit))!=EOF) {
  164.                                 VOID putc(c,fcopy);
  165.                                 if (c=='\n') editline++;
  166.                         }
  167.                 }
  168.                 ffclose(fedit);
  169.         }
  170. }
  171.  
  172.  
  173. copylines(line,delta)
  174. register int line; struct hshentry * delta;
  175. /* Function: copies input lines editline..line-1 from fedit to fcopy.
  176.  * If delta != nil, keyword expansion is done simultaneously.
  177.  * editline is updated. Rewinds a file only if necessary.
  178.  */
  179. {
  180.  
  181.         if (editline>line) {
  182.                 /* swap files */
  183.                 finishedit((struct hshentry *)nil); swapeditfiles(false);
  184.                 /* assumes edit only during last pass, from the beginning*/
  185.         }
  186.         while (editline<line) {
  187.                 /*copy another line*/
  188.                 if (delta)
  189.                         VOID expandline(fedit,fcopy,delta,false,false);
  190.                 else
  191.                         while (putc(getc(fedit),fcopy)!='\n');
  192.                 editline++;
  193.         }
  194. }
  195.  
  196.  
  197.  
  198. xpandstring(delta)
  199. struct hshentry * delta;
  200. /* Function: Reads a string terminated by SDELIM from finptr and writes it
  201.  * to fcopy. Double SDELIM is replaced with single SDELIM.
  202.  * Keyword expansion is performed with data from delta.
  203.  * If rewriteflag==true, the string is also copied unchanged to frewrite.
  204.  * editline is updated.
  205.  */
  206. {
  207.         editline=1;
  208.         while (expandline(finptr,fcopy,delta,true,rewriteflag)) editline++;
  209.         nextc='\n';
  210. }
  211.  
  212.  
  213. copystring()
  214. /* Function: copies a string terminated with a single SDELIM from finptr to
  215.  * fcopy, replacing all double SDELIM with a single SDELIM.
  216.  * If rewriteflag==true, the string also copied unchanged to frewrite.
  217.  * editline is set to (number of lines copied)+1.
  218.  * Assumption: next character read is first string character.
  219.  */
  220. {       register c, write;
  221.         write=rewriteflag;
  222.         editline=1;
  223.         while ((c=GETC(finptr,frewrite,write)) != EOF) {
  224.                 if ((c==SDELIM)&&((c=GETC(finptr,frewrite,write)) != SDELIM)){
  225.                         /* end of string */
  226.                         nextc = c;
  227.                         return;
  228.                 }
  229.                 VOID putc(c,fcopy);
  230.                 if (c=='\n') editline++;
  231.         }
  232.         nextc = c;
  233.         serror("Unterminated string");
  234.         return;
  235. }
  236.  
  237.  
  238.  
  239.  
  240. editstring(delta)
  241. struct hshentry * delta;
  242. /* Function: reads an edit script from finptr and applies it to
  243.  * file fedit; the result is written to fcopy.
  244.  * If delta!=nil, keyword expansion is performed simultaneously.
  245.  * If frewrite==true, the edit script is also copied verbatim to frewrite.
  246.  * Assumes that all these files are open.
  247.  * If running out of lines in fedit, fedit and fcopy are swapped.
  248.  * resultfile and editfile are the names of the files that go with fcopy
  249.  * and fedit, respectively.
  250.  * Assumes the next input character from finptr is the first character of
  251.  * the edit script. Resets nextc on exit.
  252.  */
  253. {
  254.         int ed; /* editor command */
  255.         register int c;
  256.         register int write, i;
  257.         int line, length;
  258.  
  259.         editline += linecorr; linecorr=0; /*correct line number*/
  260.         write=rewriteflag;
  261.         for (;;) {
  262.                 /* read next command and decode */
  263.                 /* assume next non-white character is command name*/
  264.                 while((ed=GETC(finptr,frewrite,write))=='\n'||
  265.                         ed==' ' || ed=='\t');
  266.                 if (ed==SDELIM) break;
  267.                 /* now attempt to read numbers. */
  268.                 /* fscanf causes trouble because of the required echoing */
  269.                 while ((c=GETC(finptr,frewrite,write))==' ');  /*skip spaces*/
  270.                 if (!('0'<=c && c<='9')) {
  271.                         faterror("missing line number in edit script");
  272.                         break;
  273.                 }
  274.                 line= c -'0';
  275.                 while ('0'<=(c=GETC(finptr,frewrite,write)) && c<='9') {
  276.                         line = line*10 + c-'0';
  277.                 }
  278.                 while (c==' ') c=GETC(finptr,frewrite,write);
  279.                 if (!('0'<=c && c<='9')) {
  280.                         faterror("incorrect range in edit script");
  281.                         break;
  282.                 }
  283.                 length= c -'0';
  284.                 while ('0'<=(c=GETC(finptr,frewrite,write)) && c<='9') {
  285.                         length = length*10 + c-'0';
  286.                 }
  287.                 while(c!='\n'&&c!=EOF) c=GETC(finptr,frewrite,write); /* skip to end of line */
  288.  
  289.                 switch (ed) {
  290.                 case 'd':
  291.                         copylines(line,delta);
  292.                         /* skip over unwanted lines */
  293.                         for (i=length;i>0;i--) {
  294.                                 /*skip next line*/
  295.                                 while ((c=getc(fedit))!='\n');
  296.                     if (c==EOF)
  297.                         faterror("EOF during edit");
  298.                                 editline++;
  299.                         }
  300.                         linecorr -= length;
  301.                         break;
  302.                 case 'a':
  303.                         copylines(line+1,delta); /*copy only; no delete*/
  304.                         for (i=length;i>0;i--) {
  305.                                 /*copy next line from script*/
  306.                                 if (delta!=nil)
  307.                                        VOID expandline(finptr,fcopy,delta,true,write);
  308.                                 else {
  309.                                        c = GETC(finptr,frewrite,write);
  310.                                        while (putc(c,fcopy)!='\n'){
  311.                                                if ((c==SDELIM)&&((c=GETC(finptr,frewrite,write))!=SDELIM)){
  312.                                                        serror("Missing string delimiter in edit script");
  313.                                                        VOID putc(c,fcopy);
  314.                                                }
  315.                                                c = GETC(finptr,frewrite,write);
  316.                                        }
  317.                                 }
  318.                         }
  319.                         linecorr += length;
  320.                         break;
  321.                 default:
  322.                         faterror("unknown command in edit script: %c", ed);
  323.                         break;
  324.                 }
  325.         }
  326.         nextc=GETC(finptr,frewrite,write);
  327. }
  328.  
  329.  
  330.  
  331. /* The rest if for keyword expansion */
  332.  
  333.  
  334.  
  335. expandline(in, out, delta,delimstuffed,write)
  336. FILE * in, * out; struct hshentry * delta;
  337. register int delimstuffed, write;
  338. /* Function: Reads a line from in and writes it to out.
  339.  * If delimstuffed==true, double SDELIM is replaced with single SDELIM.
  340.  * Keyword expansion is performed with data from delta.
  341.  * If write==true, the string is also copied unchanged to frewrite.
  342.  * Returns false if end-of-string or end-of-line is detected, true otherwise.
  343.  */
  344. {
  345.     register c;
  346.     register char * tp;
  347.     char keystring[keylength+2];
  348.     char keyval[keyvallength+2];
  349.         enum markers matchresult;
  350.  
  351.     c=GETC(in,frewrite,write);
  352.         for (;;) {
  353.                 if (c==EOF) {
  354.                         if(delimstuffed) {
  355.                                 error("unterminated string");
  356.                                 nextc=c;
  357.                         }
  358.                         return(false);
  359.                 }
  360.  
  361.                 if (c==SDELIM && delimstuffed) {
  362.                         if ((c=GETC(in,frewrite,write))!=SDELIM) {
  363.                                 /* end of string */
  364.                                 nextc=c;
  365.                                 return false;
  366.                         }
  367.                 }
  368.                 VOID putc(c,out);
  369.  
  370.                 if (c=='\n') return true; /* end of line */
  371.  
  372.         if (c==KDELIM) {
  373.                         /* check for keyword */
  374.                         /* first, copy a long enough string into keystring */
  375.             tp=keystring;
  376.             while (((c=GETC(in,frewrite,write))!=EOF) && (tp<keystring+keylength) && (c!='\n')
  377.                    && (c!=SDELIM) && (c!=KDELIM) && (c!=VDELIM)) {
  378.                               VOID putc(c,out);
  379.                   *tp++ = c;
  380.                         }
  381.             *tp++ = c; *tp = '\0';
  382.             matchresult=trymatch(keystring,false);
  383.             if (matchresult==Nomatch) continue;
  384.             /* last c will be dealt with properly by continue*/
  385.  
  386.             /* Now we have a keyword terminated with a K/VDELIM */
  387.             if (c==VDELIM) {
  388.                   /* try to find closing KDELIM, and replace value */
  389.                   tp=keyval;
  390.                   while (((c=GETC(in,frewrite,write)) != EOF)
  391.                      && (c!='\n') && (c!=KDELIM) && (tp<keyval+keyvallength)) {
  392.                       *tp++ =c;
  393.                       if (c==SDELIM && delimstuffed) { /*skip next SDELIM */
  394.                         c=GETC(in,frewrite,write);
  395.                         /* Can't be at end of string.
  396.                         /* always a \n before closing SDELIM */
  397.                       }
  398.                   }
  399.                   if (c!=KDELIM) {
  400.                     /* couldn't find closing KDELIM -- give up */
  401.                     VOID putc(VDELIM,out); *tp='\0';
  402.                     VOID fputs(keyval,out);
  403.                     continue;   /* last c handled properly */
  404.                   }
  405.             }
  406.             /* now put out the new keyword value */
  407.             keyreplace(matchresult,delta,out);
  408.                 }
  409.                 c=GETC(in,frewrite,write);
  410.         } /* end for */
  411. }
  412.  
  413.  
  414.  
  415. keyreplace(marker,delta,out)
  416. enum markers marker; struct hshentry * delta; FILE * out;
  417. /* function: ouputs the keyword value(s) corresponding to marker.
  418.  * Attributes are derived from delta.
  419.  */
  420. {
  421.         char * date;
  422.         register char * sp;
  423.  
  424.         date= delta->date;
  425.  
  426.         switch (marker) {
  427.         case Author:
  428.                 VOID fprintf(out,"%c %s %c",VDELIM,delta->author,KDELIM);
  429.                 break;
  430.         case Date:
  431.                 VOID putc(VDELIM,out);VOID putc(' ',out);
  432.                 VOID PRINTDATE(out,date);VOID putc(' ',out);
  433.                 VOID PRINTTIME(out,date);VOID putc(' ',out);VOID putc(KDELIM,out);
  434.                 break;
  435.         case Id:
  436.     case Header:
  437.         VOID putc(VDELIM,out); VOID putc(' ',out);
  438.         if (marker==Id)
  439.              VOID fputs(bindex(RCSfilename,'/'),out);
  440.         else     VOID fputs(getfullRCSname(),out);
  441.         VOID fprintf(out," %s ", delta->num);
  442.                 VOID PRINTDATE(out,date);VOID putc(' ',out);VOID PRINTTIME(out,date);
  443.         VOID fprintf(out, " %s %s ",delta->author,delta->state);
  444.         if (delta->lockedby!=nil)
  445.              VOID fprintf(out,"Locker: %s ",delta->lockedby);
  446.         VOID putc(KDELIM,out);
  447.                 break;
  448.         case Locker:
  449.                 VOID fprintf(out,"%c %s %c", VDELIM,
  450.                         delta->lockedby==nil?"":delta->lockedby,KDELIM);
  451.                 break;
  452.         case Log:
  453.                 VOID fprintf(out, "%c\t%s %c\n%sRevision %s  ",
  454.                         VDELIM, bindex(RCSfilename,'/'), KDELIM, Comment, delta->num);
  455.                 VOID PRINTDATE(out,date);VOID fputs("  ",out);VOID PRINTTIME(out,date);
  456.                 VOID fprintf(out, "  %s\n%s",delta->author,Comment);
  457.                 /* do not include state here because it may change and is not updated*/
  458.                 sp = delta->log;
  459.                 while (*sp) if (putc(*sp++,out)=='\n') VOID fputs(Comment,out);
  460.                 /* Comment is the comment leader */
  461.                 break;
  462.         case RCSfile:
  463.                 VOID fprintf(out,"%c %s %c",VDELIM,bindex(RCSfilename,'/'),KDELIM);
  464.                 break;
  465.         case Revision:
  466.                 VOID fprintf(out,"%c %s %c",VDELIM,delta->num,KDELIM);
  467.                 break;
  468.         case Source:
  469.                 VOID fprintf(out,"%c %s %c",VDELIM,getfullRCSname(),KDELIM);
  470.                 break;
  471.         case State:
  472.                 VOID fprintf(out,"%c %s %c",VDELIM,delta->state,KDELIM);
  473.                 break;
  474.         case Nomatch:
  475.                 VOID putc(KDELIM,out);
  476.                 break;
  477.         }
  478. }
  479.  
  480.  
  481.