home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 640a.lha / BumpRev_v1.0 / bumprev.c < prev    next >
C/C++ Source or Header  |  1992-05-14  |  18KB  |  645 lines

  1. /* $Revision Header *** Header built automatically - do not edit! ***********
  2.  *
  3.  *    (C) Copyright 1991 by Torsten Jürgeleit
  4.  *
  5.  *    Name .....: bumprev.c
  6.  *    Created ..: Thursday 18-Dec-91 15:55:48
  7.  *    Revision .: 0
  8.  *
  9.  *    Date        Author                 Comment
  10.  *    =========   ====================   ====================
  11.  *    18-Dec-91   Torsten Jürgeleit      Created this file!
  12.  *
  13.  ****************************************************************************
  14.  *
  15.  *     This program is a completely rewritten version of DoRevision
  16.  *    (Fish 325) from    Olaf Barthel.
  17.  *
  18.  * Differences to DoRevision:
  19.  *
  20.  *    It now can be used for assembler source files too, because BumpRev
  21.  *    examines the file extension ('.c' or '.h' for C sources and '.asm'
  22.  *    or '.i' for assembler sources).
  23.  *    The size of the executable was reduced to 3.7 kb, but now the
  24.  *    program is NOT portable anymore - it uses the ARP library and only
  25.  *    three functions from c.lib (strrchr, strcpy and strlen).
  26.  *    In this version the current day, date and time strings are
  27.  *    generated with the function StampToStr from ARP library and so it
  28.  *    does not require DClock.
  29.  *
  30.  * $Revision Header ********************************************************/
  31.  
  32.     /* Includes */
  33.  
  34. #include <exec/types.h>
  35. #include <exec/memory.h>
  36. #include <libraries/arpbase.h>
  37. #include <functions.h>
  38. #include <string.h>
  39.  
  40.     /* Defines */
  41.  
  42. #define MAX_READ_BUFFER_SIZE    2000
  43. #define MAX_LINE_BUFFER_SIZE    300
  44. #define MAX_FILE_NAME_LEN    108
  45. #define MAX_AUTHOR_NAME_LEN    20
  46. #define MAX_COMPANY_NAME_LEN    20
  47. #define MAX_ARGUMENTS        2
  48.  
  49. #define ARGUMENT_FILE_NAME    0
  50. #define ARGUMENT_COMMENT    1
  51.  
  52. #define TEMP_FILE_NAME        "T:Revision.temp"
  53.  
  54. #define FILE_TYPE_INVALID    0
  55. #define FILE_TYPE_C        1
  56. #define FILE_TYPE_ASM        2
  57.  
  58. #define ENV_DIR_NAME        "ENV:"
  59.  
  60. #define ENV_AUTHOR        "AUTHOR"
  61. #define ENV_COMPANY        "COMPANY"
  62.  
  63. #define DEFAULT_AUTHOR        "- Unknown -"
  64. #define DEFAULT_COMPANY        "???"
  65.  
  66. #define FILE_STATUS_NORMAL    0
  67. #define FILE_STATUS_EOF        1
  68.  
  69. #define FILE_ERROR_LINE_TOO_LONG    -1
  70. #define FILE_ERROR_READ_FAILED        -2
  71. #define FILE_ERROR_WRITE_FAILED        -3
  72.  
  73. #define REVISION_HEADER_ID_START    3
  74. #define REVISION_HEADER_ID        "$Revision Header"
  75. #define REVISION_HEADER_ID_LEN        16
  76.  
  77. #define REVISION_COUNT_START        15
  78.  
  79. #define REVISION_DATE_START        3
  80. #define REVISION_DATE_LEN        9
  81.  
  82. #define DEFAULT_COMMENT        "- Empty log message -"
  83. #define FIRST_COMMENT        "Created this file!"
  84.  
  85. #define LINE_NUM_REVISION_COUNT        7
  86. #define LINE_NUM_LAST_REVISION        11
  87.  
  88.     /* Structures */
  89.  
  90. struct RevisionData {
  91.     BYTE    *rd_Comment;
  92.     LONG    rd_FileProtection;    /* protection bits */
  93.     USHORT    rd_FileType;
  94.     BYTE    rd_FileName[MAX_FILE_NAME_LEN + 1];    /* real file name */
  95.     BYTE    rd_Author[MAX_AUTHOR_NAME_LEN + 1];
  96.     BYTE    rd_Company[MAX_COMPANY_NAME_LEN + 1];
  97.     BYTE    rd_Day[LEN_DATSTRING];        /* needed for StampToStr() */
  98.     BYTE    rd_Date[LEN_DATSTRING];        /* needed for StampToStr() */
  99.     BYTE    rd_Time[LEN_DATSTRING];        /* needed for StampToStr() */
  100. };
  101. struct FileData {
  102.     BPTR    fd_FileHandle;
  103.     BYTE    *fd_ReadBuffer;
  104.     BYTE    *fd_CurrentPtr;
  105.     BYTE    *fd_EndPtr;
  106.     BYTE    *fd_LineBuffer;
  107.     USHORT    fd_LineLen;
  108.     USHORT    fd_LineNum;
  109. };
  110.     /* Externals */
  111.  
  112. IMPORT struct DOSBase   *DOSBase;
  113.  
  114.     /* Globals */
  115.  
  116. struct ArpBase    *ArpBase;
  117.  
  118. BYTE template[]  = "File/a,Comment",
  119.      xtra_help[] = "Usage: BumpRev <file> [comment]\n"
  120.            "\t<file>    = name of source file\n"
  121.            "\t[comment] = comment string for new revision";
  122.  
  123.     /* Static prototypes */
  124.  
  125. BOOL  revise_file(BYTE *name, BYTE *comment);
  126. struct RevisionData  *get_revision_data(BYTE *name, BYTE *comment);
  127. SHORT get_revision_env(BYTE *name, BYTE *buffer, USHORT buffer_size);
  128. struct FileData  *open_file(BYTE *name, LONG mode);
  129. SHORT read_line(struct FileData  *fd);
  130. SHORT fill_read_buffer(struct FileData  *fd);
  131. VOID  close_file(struct FileData  *fd);
  132. BOOL  create_revision_header(struct RevisionData  *rd, BPTR fh);
  133. BOOL  change_revision_header(struct RevisionData  *rd,
  134.                     struct FileData  *rev_fd, BPTR temp_fh);
  135. BOOL  append_rest_of_file(struct FileData  *rev_fd, BPTR temp_fh);
  136. BOOL  copy_file(BPTR src_fh, BPTR dst_fh, BYTE *read_buffer);
  137.  
  138.     /* Static pragmas */
  139.  
  140. #pragma regcall(revise_file(a0,a1))
  141. #pragma regcall(get_revision_data(a0,a1))
  142. #pragma regcall(get_revision_env(a0,a1,d0))
  143. #pragma regcall(open_file(a0,d0))
  144. #pragma regcall(read_line(a0))
  145. #pragma regcall(fill_read_buffer(a0))
  146. #pragma regcall(close_file(a0))
  147. #pragma regcall(create_revision_header(a0,a1))
  148. #pragma regcall(change_revision_header(a0,a1,a2))
  149. #pragma regcall(append_rest_of_file(a0,a1))
  150. #pragma regcall(copy_file(a0,a1,a2))
  151.  
  152.     /* Main routine - no startup code */
  153.  
  154.    LONG
  155. _main(LONG alen, BYTE *aptr)
  156. {
  157.    LONG return_code = RETURN_FAIL;
  158.  
  159.    /* First open ARP library */
  160.    if (!(ArpBase = OpenLibrary(ArpName, ArpVersion))) {
  161.       Write(Output(), "Need ARP library V39+\n", 22L);
  162.    } else {
  163.       BYTE   *argv[MAX_ARGUMENTS];
  164.       LONG   count;
  165.       USHORT i;
  166.  
  167.       /* Clear argument array */
  168.       for (i = 0; i < MAX_ARGUMENTS; i++) {
  169.      argv[i] = NULL;
  170.       }
  171.  
  172.       /* Parse command line arguments */
  173.       if ((count = GADS(aptr, alen, &xtra_help[0], &argv[0],
  174.                                &template[0])) < 0) {
  175.      Puts(argv[0]);
  176.       } else {
  177.      if (!count) {
  178.         Puts(&xtra_help[0]);
  179.      } else {
  180.  
  181.         /* Call revise function with file name and comment */
  182.         if (revise_file(argv[ARGUMENT_FILE_NAME],
  183.                       argv[ARGUMENT_COMMENT]) == TRUE) {
  184.            return_code = RETURN_OK;
  185.         }
  186.      }
  187.       }
  188.       CloseLibrary(ArpBase);
  189.    }
  190.  
  191.    /* MANX crt0.asm forget to close DOS library, so we have to do it */
  192.    CloseLibrary(DOSBase);
  193.    return(return_code);
  194. }
  195.     /* Revise given file */
  196.  
  197.    BOOL
  198. revise_file(BYTE *name, BYTE *comment)
  199. {
  200.    struct RevisionData  *rd;
  201.    struct FileData      *rev_fd;
  202.    BPTR temp_fh;
  203.    BOOL success = FALSE;
  204.  
  205.    /* If no comment then use default one */
  206.    if (!comment) {
  207.       comment = DEFAULT_COMMENT;
  208.    }
  209.  
  210.    /* Get data needed for revision change and open files */
  211.    if (rd = get_revision_data(name, comment)) {
  212.       if (rev_fd = open_file(name, (LONG)MODE_READWRITE)) {
  213.      if (temp_fh = Open(TEMP_FILE_NAME, (LONG)MODE_NEWFILE)) {
  214.  
  215.         /* Read first line of file and check for revision header */
  216.         if (read_line(rev_fd) == FILE_STATUS_NORMAL) {
  217.            if (rev_fd->fd_LineLen > REVISION_HEADER_ID_START &&
  218.            Strncmp(rev_fd->fd_LineBuffer + REVISION_HEADER_ID_START,
  219.             REVISION_HEADER_ID, (LONG)REVISION_HEADER_ID_LEN)) {
  220.           if ((success = create_revision_header(rd, temp_fh)) ==
  221.                                      TRUE) {
  222.              /* Append line already read */
  223.              if (FPrintf(temp_fh, "%s\n", rev_fd->fd_LineBuffer) <
  224.                                     0) {
  225.             success = FALSE;
  226.              }
  227.           }
  228.            } else {
  229.           success = change_revision_header(rd, rev_fd, temp_fh);
  230.            }
  231.            if (success == TRUE) {
  232.  
  233.           /* Copy rest of revision file to temp file */
  234.           if ((success = append_rest_of_file(rev_fd, temp_fh)) ==
  235.                                      TRUE) {
  236.              BPTR rev_fh = rev_fd->fd_FileHandle;
  237.  
  238.              /* Copy revised temp file over original file */
  239.              if (Seek(rev_fh, 0L, (LONG)OFFSET_BEGINNING) == -1L ||
  240.              Seek(temp_fh, 0L, (LONG)OFFSET_BEGINNING) == -1L) {
  241.             success = FALSE;
  242.              } else {
  243.             success = copy_file(temp_fh, rev_fh,
  244.                              rev_fd->fd_ReadBuffer);
  245.              }
  246.           }
  247.            }
  248.         }
  249.         Close(temp_fh);
  250.         DeleteFile(TEMP_FILE_NAME);
  251.      }
  252.      close_file(rev_fd);
  253.      if (success == TRUE) {
  254.  
  255.         /* Set archive bit to mark file as revised */
  256.         SetProtection(name, rd->rd_FileProtection | FIBF_ARCHIVE);
  257.      }
  258.       }
  259.       FreeMem(rd, (LONG)sizeof(struct RevisionData));
  260.    }
  261.    return(success);
  262. }
  263.     /* Prepare structure with data needed for revision change */
  264.  
  265.    struct RevisionData  *
  266. get_revision_data(BYTE *name, BYTE *comment)
  267. {
  268.    struct RevisionData  *rd = NULL;
  269.    BYTE   *ptr;
  270.    USHORT type;
  271.  
  272.    /* First get type of given file */
  273.    if (ptr = strrchr(name, '.')) {
  274.       if (!Strcmp(ptr, ".c") || !Strcmp(ptr, ".h")) {
  275.      type = FILE_TYPE_C;
  276.       } else {
  277.      if (!Strcmp(ptr, ".asm") || !Strcmp(ptr, ".i")) {
  278.         type = FILE_TYPE_ASM;
  279.      } else {
  280.         type = FILE_TYPE_INVALID;
  281.      }
  282.       }
  283.       if (type != FILE_TYPE_INVALID) {
  284.      struct FileInfoBlock  *fib;
  285.      struct DateTime       dat;
  286.      struct DateStamp      *ds = &dat.dat_Stamp;
  287.      BPTR lock;
  288.  
  289.      /* Get actual date and time into DateStamp and make range check */
  290.      DateStamp(ds);
  291.      if (ds->ds_Days <= 36500 && ds->ds_Minute <= 60 * 24 &&
  292.                            ds->ds_Tick <= 50 * 60) {
  293.         /* Try to lock and examine selected file */
  294.         if (lock = Lock (name, (LONG)SHARED_LOCK)) {
  295.            if (fib = AllocMem((LONG)sizeof(struct FileInfoBlock),
  296.                                (LONG)MEMF_PUBLIC)) {
  297.           if (Examine(lock, fib) != DOSFALSE) {
  298.              if (rd = AllocMem((LONG)sizeof(struct RevisionData),
  299.                       (LONG)MEMF_PUBLIC | MEMF_CLEAR)) {
  300.             /* Init revision data */
  301.             rd->rd_Comment        = comment;
  302.             rd->rd_FileProtection = fib->fib_Protection;
  303.             rd->rd_FileType       = type;
  304.             strcpy(&rd->rd_FileName[0], &fib->fib_FileName[0]);
  305.  
  306.             /* Get author and company name from environment variables */
  307.             if (get_revision_env(ENV_AUTHOR, &rd->rd_Author[0],
  308.                          MAX_AUTHOR_NAME_LEN) < 0) {
  309.                strcpy(&rd->rd_Author[0], DEFAULT_AUTHOR);
  310.             }
  311.             if (get_revision_env(ENV_COMPANY, &rd->rd_Company[0],
  312.                         MAX_COMPANY_NAME_LEN) < 0) {
  313.                strcpy(&rd->rd_Company[0], DEFAULT_COMPANY);
  314.             }
  315.  
  316.             /* Convert DateStamp to strings in revision data */
  317.             dat.dat_Format  = FORMAT_DOS;
  318.             dat.dat_Flags   = 0;
  319.             dat.dat_StrDay  = &rd->rd_Day[0];
  320.             dat.dat_StrDate = &rd->rd_Date[0];
  321.             dat.dat_StrTime = &rd->rd_Time[0];
  322.             rd->rd_Time[8]  = '\0';   /* NULL terminate time string */
  323.             StamptoStr(&dat);
  324.              }
  325.           }
  326.           FreeMem(fib, (LONG)sizeof(struct FileInfoBlock));
  327.            }
  328.            UnLock(lock);
  329.         }
  330.      }
  331.       }
  332.    }
  333.    return(rd);
  334. }
  335.     /* Copy value of environment variable to given buffer */
  336.  
  337.    SHORT
  338. get_revision_env(BYTE *name, BYTE *buffer, USHORT buffer_size)
  339. {
  340.    BPTR  lock, fh;
  341.    SHORT len = -1;
  342.  
  343.    /* Change current directory to 'ENV:' */
  344.    if (lock = Lock(ENV_DIR_NAME, (LONG)SHARED_LOCK)) {
  345.       lock = CurrentDir(lock);
  346.  
  347.       /* Open and read env file */
  348.       if (fh = Open(name, (LONG)MODE_OLDFILE)) {
  349.      if ((len = Read(fh, buffer, (LONG)buffer_size)) >= 0) {
  350.         *(buffer + len) = '\0';
  351.      }
  352.      Close(fh);
  353.       }
  354.       lock = CurrentDir(lock);
  355.       UnLock(lock);
  356.    }
  357.    return(len);
  358. }
  359.     /* Open text file for buffered input */
  360.  
  361.    struct FileData *
  362. open_file(BYTE *name, LONG mode)
  363. {
  364.    struct FileData  *fd = NULL;
  365.    BPTR fh;
  366.  
  367.    if (fh = Open(name, mode)) {
  368.       if (!(fd = AllocMem((LONG)(sizeof(struct FileData) +
  369.                MAX_READ_BUFFER_SIZE + MAX_LINE_BUFFER_SIZE + 1),
  370.                               (LONG)MEMF_PUBLIC))) {
  371.      Close(fh);
  372.       } else {
  373.  
  374.      /* Init file data */
  375.      fd->fd_FileHandle = fh;
  376.      fd->fd_ReadBuffer = (BYTE *)(fd + 1);
  377.      fd->fd_CurrentPtr = NULL;
  378.      fd->fd_LineBuffer = fd->fd_ReadBuffer + MAX_READ_BUFFER_SIZE;
  379.      fd->fd_LineLen    = 0;
  380.      fd->fd_LineNum    = 0;
  381.       }
  382.    }
  383.    return(fd);
  384. }
  385.     /* Read line from read buffer */
  386.  
  387.    SHORT
  388. read_line(struct FileData  *fd)
  389. {
  390.    BYTE   c, *ptr, *line = fd->fd_LineBuffer;
  391.    USHORT len = 0;
  392.    SHORT  status = FILE_STATUS_NORMAL;
  393.  
  394.    /* Fill read buffer if necessary */
  395.    if (!(ptr = fd->fd_CurrentPtr) || ptr >= fd->fd_EndPtr) {
  396.       if ((status = fill_read_buffer(fd)) == FILE_STATUS_NORMAL) {
  397.      ptr = fd->fd_CurrentPtr;
  398.       }
  399.    }
  400.    if (status == FILE_STATUS_NORMAL) {
  401.  
  402.       /* Copy line to buffer */
  403.       while ((c = *ptr) != '\n') {
  404.  
  405.      /* Write char to line buffer */
  406.      if (len >= MAX_LINE_BUFFER_SIZE) {
  407.         status = FILE_ERROR_LINE_TOO_LONG;
  408.         break;
  409.      } else {
  410.         *line++ = c;
  411.         len++;
  412.  
  413.         /* Increment ptr and fill read buffer if neccessary */
  414.         if (++ptr == fd->fd_EndPtr) {
  415.            if ((status = fill_read_buffer(fd)) != FILE_STATUS_NORMAL) {
  416.           break;
  417.            } else {
  418.           ptr = fd->fd_CurrentPtr;
  419.            }
  420.         }
  421.      }
  422.       }
  423.       if (status == FILE_STATUS_NORMAL) {
  424.  
  425.      /* Mark end of string */
  426.      *line             = '\0';
  427.      fd->fd_CurrentPtr = ptr + 1;   /* skip trailing '\n' */
  428.      fd->fd_LineLen    = len;
  429.      fd->fd_LineNum++;
  430.       }
  431.    }
  432.    return(status);
  433. }
  434.     /* Fill read buffer from text file */
  435.  
  436.    SHORT
  437. fill_read_buffer(struct FileData  *fd)
  438. {
  439.    LONG  len;
  440.    SHORT status;
  441.  
  442.    if ((len = Read(fd->fd_FileHandle, fd->fd_ReadBuffer,
  443.                       (LONG)MAX_READ_BUFFER_SIZE)) == -1L) {
  444.       status = FILE_ERROR_READ_FAILED;
  445.    } else {
  446.       if (!len) {
  447.      status = FILE_STATUS_EOF;
  448.       } else {
  449.      fd->fd_CurrentPtr = fd->fd_ReadBuffer;
  450.      fd->fd_EndPtr     = fd->fd_ReadBuffer + len;
  451.      status            = FILE_STATUS_NORMAL;
  452.       }
  453.    }
  454.    return(status);
  455. }
  456.     /* Close text file and free read buffer */
  457.  
  458.    VOID
  459. close_file(struct FileData  *fd)
  460. {
  461.    Close(fd->fd_FileHandle);
  462.    FreeMem(fd, (LONG)(sizeof(struct FileData) + MAX_READ_BUFFER_SIZE +
  463.                          MAX_LINE_BUFFER_SIZE + 1));
  464. }
  465.     /* Create new revision header */
  466.  
  467.    BOOL
  468. create_revision_header(struct RevisionData  *rd, BPTR fh)
  469. {
  470.    BYTE c;
  471.    BOOL success = FALSE;
  472.  
  473.    /* Get comment indicator depending on file type */
  474.    if (rd->rd_FileType == FILE_TYPE_C) {
  475.       c = '/';
  476.    } else {
  477.       c = ' ';
  478.    }
  479.  
  480.    /* Insert revision header */
  481.    if (FPrintf(fh, "%c* $Revision Header *** Header built automatically -"
  482.                     " do not edit! ***********\n", c) > 0 &&
  483.     FPrintf(fh, " *\n *\t(C) Copyright 19%s by %s\n *\n",
  484.                  &rd->rd_Date[7], &rd->rd_Company[0]) > 0 &&
  485.     FPrintf(fh, " *\tName .....: %s\n", &rd->rd_FileName[0]) > 0 &&
  486.     FPrintf(fh, " *\tCreated ..: %s %s %s\n", &rd->rd_Day[0],
  487.                     &rd->rd_Date[0], &rd->rd_Time[0]) > 0 &&
  488.     FPrintf(fh, " *\tRevision .: 0\n *\n") > 0 &&
  489.     FPrintf(fh, " *\tDate        Author                 "
  490.                              "Comment\n") > 0 &&
  491.     FPrintf(fh, " *\t=========   ===================="
  492.                      "   ====================\n") > 0 &&
  493.     FPrintf(fh, " *\t%s   %-20s   %s\n *\n", &rd->rd_Date[0],
  494.                     &rd->rd_Author[0], FIRST_COMMENT) > 0 &&
  495.     FPrintf(fh, " * $Revision Header **********************************"
  496.                         "**********************") > 0) {
  497.       /* Append comment end char and define or equate with revision num */
  498.       if (rd->rd_FileType == FILE_TYPE_C) {
  499.      if (FPrintf(fh, "/\n#define REVISION\t0\n\n") > 0) {
  500.         success = TRUE;
  501.      }
  502.       } else {
  503.      if (FPrintf(fh, "\nREVISION\tEQU\t0\n\n") > 0) {
  504.         success = TRUE;
  505.      }
  506.       }
  507.    }
  508.    return(success);
  509. }
  510.     /* Change existing revision header */
  511.  
  512.    BOOL
  513. change_revision_header(struct RevisionData  *rd, struct FileData  *rev_fd,
  514.                                    BPTR temp_fh)
  515. {
  516.    BYTE  *line = rev_fd->fd_LineBuffer;
  517.    LONG  revision;
  518.    SHORT status;
  519.    BOOL  leave = FALSE, end = FALSE, success = TRUE;
  520.  
  521.    /* First write line read before */
  522.    if (FPrintf(temp_fh, "%s\n", line) < 0) {
  523.       status = FILE_ERROR_WRITE_FAILED;
  524.    } else {
  525.  
  526.       /* Copy rest of header lines */
  527.       while (leave == FALSE && (status = read_line(rev_fd)) ==
  528.                                FILE_STATUS_NORMAL) {
  529.      USHORT len = rev_fd->fd_LineLen, num = rev_fd->fd_LineNum;
  530.  
  531.      switch (num) {
  532.         case LINE_NUM_REVISION_COUNT :
  533.  
  534.            /* Increment revision count */
  535.            revision = Atol(line + REVISION_COUNT_START) + 1;
  536.            if (IoErr()) {
  537.           leave = TRUE;
  538.            } else {
  539.           SPrintf(line + REVISION_COUNT_START, "%ld", revision);
  540.            }
  541.            break;
  542.  
  543.         case LINE_NUM_LAST_REVISION :
  544.  
  545.            /* Check date of last revision and leave if it was today */
  546.            if (len > REVISION_DATE_START && !Strncmp(line +
  547.                        REVISION_DATE_START, &rd->rd_Date[0],
  548.             (LONG)REVISION_DATE_LEN) && (rd->rd_FileProtection &
  549.                                 FIBF_ARCHIVE)) {
  550.           leave = TRUE;
  551.            } else {
  552.  
  553.           /* Insert new revision comment line */
  554.           if (FPrintf(temp_fh, " *\t%s   %-20s   %s\n",
  555.                      &rd->rd_Date[0], &rd->rd_Author[0],
  556.                               rd->rd_Comment) < 0) {
  557.              leave = TRUE;
  558.           }
  559.            }
  560.            break;
  561.  
  562.         default :
  563.  
  564.            /* If end of revision header reached then leave */
  565.            if (end == TRUE) {
  566.           BYTE *text;
  567.  
  568.           /* Check for line with define or equate */
  569.           if (rd->rd_FileType == FILE_TYPE_C) {
  570.              text = "#define REVISION\t";
  571.           } else {
  572.              text = "REVISION\tEQU\t";
  573.           }
  574.  
  575.           /* If define or equate found then change revision */
  576.           if (!Strncmp(line, text, (LONG)strlen(text))) {
  577.              SPrintf(line, "%s%ld", text, revision);
  578.           }
  579.           status = FILE_STATUS_EOF;
  580.           leave  = TRUE;
  581.            } else {
  582.  
  583.           /* Check for end of revision header */
  584.           if (len > REVISION_HEADER_ID_START && !Strncmp(line +
  585.                    REVISION_HEADER_ID_START, REVISION_HEADER_ID,
  586.                         (LONG)REVISION_HEADER_ID_LEN)) {
  587.              end = TRUE;
  588.           }
  589.            }
  590.            break;
  591.      }
  592.      if (leave == FALSE || end == TRUE) {
  593.  
  594.         /* Write line to temp file */
  595.         if (FPrintf(temp_fh, "%s\n", line) < 0) {
  596.            status = FILE_ERROR_WRITE_FAILED;
  597.            leave  = TRUE;
  598.         }
  599.      }
  600.       }
  601.    }
  602.    if (status != FILE_STATUS_EOF) {
  603.       success = FALSE;
  604.    }
  605.    return(success);
  606. }
  607.     /* Copy file including rest from read buffer */
  608.  
  609.    BOOL
  610. append_rest_of_file(struct FileData  *rev_fd, BPTR temp_fh)
  611. {
  612.    LONG len;
  613.    BOOL success = TRUE;
  614.  
  615.    /* First copy contents of read buffer */
  616.    if (len = rev_fd->fd_EndPtr - rev_fd->fd_CurrentPtr) {
  617.       if (Write(temp_fh, rev_fd->fd_CurrentPtr, len) != len) {
  618.      success = FALSE;
  619.       }
  620.    }
  621.    if (success == TRUE) {
  622.  
  623.       /* Copy rest of file */
  624.       success = copy_file(rev_fd->fd_FileHandle, temp_fh,
  625.                              rev_fd->fd_ReadBuffer);
  626.    }
  627.    return(success);
  628. }
  629.     /* Copy file */
  630.  
  631.    BOOL
  632. copy_file(BPTR src_fh, BPTR dst_fh, BYTE *read_buffer)
  633. {
  634.    LONG len;
  635.    BOOL success = TRUE;
  636.  
  637.    while ((len = Read(src_fh, read_buffer, (LONG)MAX_READ_BUFFER_SIZE)) > 0) {
  638.       if (Write(dst_fh, read_buffer, len) != len) {
  639.      success = FALSE;
  640.      break;
  641.       }
  642.    }
  643.    return(success);
  644. }
  645.