home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 270_01 / apply.c < prev    next >
Text File  |  1979-12-31  |  6KB  |  343 lines

  1. /**
  2.  
  3.     APPLY.C
  4.     
  5.     Apply a delta script to a text file.
  6.     
  7. **/
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <ctype.h>
  12. #include <malloc.h>
  13. #include <string.h>
  14. #include "apply.h"
  15.  
  16. /* Static data */
  17. static char szBuffer[MAXLINE] ;
  18.  
  19. /**
  20.  
  21.     AddNode()
  22.     
  23.     Add a linked list node after specified node.
  24.     This routine actually does the memory allocation to create
  25.     the node in memory.
  26.     
  27.     Returns:
  28.         Pointer to the new node if successful
  29.         NULL if out of memory
  30.         
  31. **/
  32.  
  33. static ELINE *AddNode( pNode, szText, nLine )
  34. ELINE *pNode ;
  35. char *szText ;
  36. int nLine ;
  37. {
  38.     ELINE *pTmp ;
  39.     
  40.     if ( (pTmp = (ELINE *)calloc(1,sizeof(ELINE))) != NULL )
  41.     {
  42.         if ( (pTmp->text = malloc(strlen(szText)+1) ) == NULL )
  43.             return FALSE ;
  44.             
  45.         pTmp->linenum = nLine ;
  46.         strcpy( pTmp->text, szText ) ;
  47.             
  48.         /* fix all the list links */
  49.  
  50.         if ( pNode != NULL )
  51.             pTmp->next = pNode->next ;
  52.         else
  53.             pTmp->next = NULL ;
  54.  
  55.         pTmp->prev = pNode ;
  56.         if ( pTmp->next != NULL )
  57.             pTmp->next->prev = pTmp ;
  58.         if ( pTmp->prev != NULL )
  59.             pTmp->prev->next = pTmp ;
  60.     }
  61.     return pTmp ;
  62. }
  63.  
  64. /**
  65.  
  66.     DeleteNode()
  67.     
  68.     Remove a node from the list
  69.     
  70.     Returns:
  71.         Pointer to the next node in the list.
  72.     
  73. **/
  74.  
  75. static ELINE *DeleteNode( pNode )
  76. ELINE *pNode ;
  77. {
  78.     ELINE *pRetval ;
  79.     
  80.     pRetval = pNode->next ;
  81.     
  82.     if ( pNode->next != NULL )
  83.         pNode->next->prev = pNode->prev ;
  84.     if ( pNode->prev != NULL )
  85.         pNode->prev->next = pNode->next ;
  86.     
  87.     free( pNode->text ) ;
  88.     free( pNode ) ;
  89.     
  90.     return pRetval ;
  91. }
  92.  
  93. /**
  94.  
  95.     ReadFile()
  96.     
  97.     Read a file into a linked list of ELINEs
  98.     
  99.     Returns:
  100.         TRUE if file read properly
  101.         FALSE if out of memory
  102.     
  103. **/
  104.  
  105. BOOL ReadFile( pFile, pHead, pTail )
  106. FILE *pFile ;
  107. ELINE **pHead, **pTail;
  108. {
  109.     int nLine = 0 ;
  110.     
  111.     *pHead = *pTail = NULL ;
  112.     
  113.     while ( ! feof(pFile) )
  114.     {
  115.         if ( fgets( szBuffer, MAXLINE, pFile ) )
  116.         {
  117.             ++nLine ;
  118.         
  119.             if ( (*pTail = AddNode(*pTail, szBuffer, nLine)) == NULL )
  120.                 return FALSE ;
  121.             
  122.             if ( *pHead == NULL )
  123.                 *pHead = *pTail ;
  124.         }
  125.     }
  126.     return TRUE ;
  127. }
  128.  
  129. /**
  130.  
  131.     DoDelete()
  132.     
  133.     Do a deletion of a range of lines
  134.  
  135. **/
  136.  
  137. void DoDelete( nStart, nEnd, pHead, pTail ) 
  138. int nStart, nEnd ;
  139. ELINE **pHead, **pTail ;
  140. {
  141.     /* back up to start of range to delete */
  142.     while ( (*pTail)->linenum != nStart && (*pTail)->linenum > 0 )
  143.         *pTail = (*pTail)->prev ;
  144.         
  145.     if ( (*pTail)->linenum > 0 )
  146.     {
  147.         while ( *pTail != NULL && (*pTail)->linenum <= nEnd )
  148.         {
  149.             if ( *pTail == *pHead ) 
  150.                 *pHead = (*pHead)->next ;
  151.  
  152.             *pTail = DeleteNode( *pTail ) ;
  153.         }
  154.     }
  155. }
  156.  
  157. /**
  158.  
  159.     DoAdd()
  160.     
  161.     Do an add of a range of lines
  162.  
  163. **/
  164.  
  165. void DoAdd( nAfter, pHead, pTail, pNode )
  166. int nAfter ;
  167. ELINE **pHead, **pTail, **pNode ;
  168. {
  169.     ELINE *pTmp, *pNext ;
  170.     
  171.     if ( nAfter == 0 )        /* insert at head */
  172.         *pTail = *pHead ;
  173.     else                /* back up to insertion point */
  174.         while ( (*pTail)->linenum != nAfter && (*pTail)->linenum > 0 )
  175.             *pTail = (*pTail)->prev ;
  176.         
  177.     if ( (*pTail)->linenum > 0 )
  178.     {
  179.         pTmp = (*pTail)->next ;    /* save end link */
  180.         
  181.         (*pTail)->next = *pNode ;
  182.         (*pNode)->prev = *pTail ;
  183.         
  184.         while ( *pNode != NULL && strcmp((*pNode)->text, ".\n") )
  185.             *pNode = (*pNode)->next ;
  186.             
  187.         if ( *pNode != NULL )
  188.         {
  189.             pNext = (*pNode)->next ;
  190.             (*pNode)->prev->next = pTmp ;
  191.             if ( pTmp != NULL )
  192.                 pTmp->prev = (*pNode)->prev ;
  193.             *pNode = pNext ;
  194.         }
  195.     }
  196. }            
  197.  
  198. /**
  199.  
  200.     DoChange()
  201.     
  202.     Do a change on a range of lines
  203.  
  204. **/
  205.  
  206. void DoChange( nStart, nEnd, pHead, pTail, pNode )
  207. int nStart, nEnd ;
  208. ELINE **pHead, **pTail, **pNode ;
  209. {
  210.     DoDelete( nStart, nEnd, pHead, pTail ) ;
  211.     DoAdd( nStart-1, pHead, pTail, pNode ) ;
  212. }
  213.  
  214. /**
  215.  
  216.     ParseDelta()
  217.     
  218.     Process the commands in the delta file
  219.  
  220. **/
  221.  
  222. void ParseDelta( pDHead, pFHead, pFTail ) 
  223. ELINE **pDHead ;        /* head of delta list */
  224. ELINE **pFHead, **pFTail ;    /* head, tail of file list */
  225. {
  226.     char *szStart, *szEnd, *szType ;
  227.     int nStart, nEnd ;
  228.     
  229.     while ( *pDHead != NULL )
  230.     {
  231.         szStart = (*pDHead)->text ;
  232.         szEnd = szStart ;
  233.  
  234.         /* get the range of numbers from string */
  235.         nStart = atoi( szStart ) ;
  236.         while ( isdigit(*szEnd) )
  237.             ++szEnd ;
  238.         if ( *szEnd == ',' )
  239.         {
  240.             szType = ++szEnd ;
  241.             while ( isdigit(*szType) )
  242.                 ++szType ;
  243.             nEnd = atoi( szEnd ) ;
  244.         }
  245.         else
  246.         {
  247.             nEnd = nStart ;
  248.             szType = szEnd ;
  249.         }
  250.         
  251.         *pDHead = (*pDHead)->next ;
  252.         
  253.         switch( *szType )
  254.         {
  255.         case 'c':        /* change */
  256.             DoChange( nStart, nEnd, pFHead, pFTail, pDHead ) ;
  257.             break ;
  258.         case 'd':        /* delete */
  259.             DoDelete( nStart, nEnd, pFHead, pFTail ) ;
  260.             break ;
  261.         case 'a':        /* add */
  262.             DoAdd( nStart, pFHead, pFTail, pDHead ) ;
  263.             break ;
  264.         }
  265.     }
  266. }
  267.  
  268. /**
  269.  
  270.     Banner()
  271.     
  272.     Print a startup banner
  273.     
  274. **/
  275.  
  276. static void banner()
  277. {
  278.     fprintf( stderr, "APPLY - Delta File Applicator\n" ) ;
  279.     fprintf( stderr, "By Ralph E. Brendler\n\n" ) ;
  280. }
  281.     
  282.  
  283. /**
  284.  
  285.     MAIN ROUTINE
  286.     
  287. **/
  288.  
  289. void main( argc, argv )
  290. int argc ;
  291. char *argv[] ;
  292. {
  293.     FILE *pFile1, *pFile2 ;
  294.     ELINE *pDHead, *pDTail, *pFHead, *pFTail;
  295.     
  296.     pDHead = pDTail = pFHead = pFTail = NULL ;
  297.  
  298.     if ( argc != 3 )
  299.     {
  300.         fprintf( stderr, "Usage: APPLY file delta\n" ) ;
  301.         exit(1) ;
  302.     }
  303.     
  304.     banner() ;        /* print startup banner */
  305.  
  306.     if ( (pFile1 = fopen(argv[1],"rt")) == NULL )
  307.     {
  308.         fprintf( stderr, "Unable to open %s\n", argv[1] ) ;
  309.         exit(1) ;
  310.     }
  311.  
  312.     if ( (pFile2 = fopen(argv[2],"rt")) == NULL )
  313.     {
  314.         fprintf( stderr, "Unable to open %s\n", argv[2] ) ;
  315.         exit(1) ;
  316.     }
  317.  
  318.     if ( ReadFile(pFile1, &pFHead, &pFTail) == FALSE )
  319.     {
  320.         fprintf( stderr, "Out of memory\n" ) ;
  321.         exit(1) ;
  322.     }
  323.  
  324.     if ( ReadFile(pFile2, &pDHead, &pDTail) == FALSE )
  325.     {
  326.         fprintf( stderr, "Out of memory\n" ) ;
  327.         exit(1) ;
  328.     }
  329.  
  330.     ParseDelta( &pDHead, &pFHead, &pFTail ) ;
  331.     
  332.     fclose( pFile1 ) ;
  333.     fclose( pFile2 ) ;
  334.     
  335.     while ( pFHead != NULL )
  336.     {
  337.         printf( "%s", pFHead->text ) ;
  338.         pFHead = pFHead->next ;
  339.     }
  340. }
  341.  
  342.  
  343.