/*
 * Revision control info:
 * $Id: bump.c 1.14 1995/12/06 21:33:50 JöG Exp JöG $
 *
 * Bump - Bump AmigaDOS version string
 *
 * SAS/C 6.55 code - beware when porting:
 * autoinitalization of library bases
 * __oslibversion
 *
 *
 * Jörgen Grahn
 * Wetterlinsgatan 13E
 * S-521 34 Falköping
 * Sverige
 *
 */

/*
 * Here comes that funny part again;
 * using features in a program which you
 * really would need the program for.
 * The hen or the egg. Oh well.
 *
 */
#define VERS "Bump 1.2 (06.12.95)"

/*
 * $Log: bump.c $
 * Revision 1.14  1995/12/06  21:33:50  JöG
 * manually bumped version to 1.2
 * added lost log message
 *
 * Revision 1.13  1995/12/06  21:29:48  JöG
 * bug fix: now accepts names with dots (but not spaces)
 *
 * revision 1.12
 * date: 1995/12/06 21:25:21;  author: JöG;  state: Exp;  lines: +9 -3
 * fix: now keeps leading zeros in date string
 * 
 * Revision 1.11  1995/11/21  18:49:23  JöG
 * changed format of extra output (RELEASE_x.y)
 * to conform with RCS symbolic revision names
 * (can't have '.' in them)
 * bumped AmigaDOS revision
 *
 * Revision 1.10  1995/10/23  13:31:42  JöG
 * more security for false markers
 *
 * Revision 1.9  1995/10/23  13:10:54  JöG
 * better handling of revision 9->10
 *
 * Revision 1.8  1995/10/23  12:00:09  JöG
 * added forgotten '\n's
 *
 * Revision 1.7  1995/10/23  11:53:13  JöG
 * added check for line limit
 *
 * Revision 1.6  1995/10/23  09:27:56  JöG
 * final, somewhat cleaned up version
 * added MARKER keyword
 *
 * Revision 1.5  1995/10/23  09:10:32  JöG
 * first functional version
 * the format of the file can still confuse the program
 * horribly
 *
 * Revision 1.4  1995/10/23  00:02:05  JöG
 * almost semi-working version
 *
 * Revision 1.3  1995/10/22  23:36:37  JöG
 * file copying working
 *
 * Earlier log messages lost.
 *
 */



#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/rdargs.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/utility.h>

#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>



int __oslibversion = 37;

static const char verstag[] = "$" "VER: " VERS " Jörgen Grahn";
static const char rcsid[] = "$Id: bump.c 1.14 1995/12/06 21:33:50 JöG Exp JöG $";


static void internalsprintf(char *, char *, ...);


#define STORAGEMAX	512


int main(void)
{
	int				  result;
	WORD			  i;
	BPTR			  file;
	char			* argarray[2];
	struct RDArgs	* rdargs;

	static char		  buffer[512+1];
	static char		  outbuf[20];
	static char		* storage[STORAGEMAX];
	WORD			  storagelen;


	result = 0;

	argarray[0] = NULL;
	argarray[1] = "VER: ";

	rdargs = ReadArgs("FILE/A,MARKER", (LONG *)argarray, NULL);
	if(!rdargs)
	{
		PrintFault(IoErr(), "Bump");
		result = RETURN_ERROR;
		goto nordargs;
	}

	file = Open(argarray[0], MODE_OLDFILE);
	if(!file)
	{
		PrintFault(IoErr(), "Bump");
		result = RETURN_WARN;
		goto noread;
	}

	storagelen = 0;

	while(FGets(file, buffer, 512))
	{
		if(storagelen==STORAGEMAX)
		{
			PutStr("Bump: line limit exceeded\n");
			result = RETURN_WARN;
			goto rowlimit;
		}

		storage[storagelen] = AllocVec((ULONG)strlen(buffer)+1+1, MEMF_CLEAR);
		if(!storage[storagelen])
		{	break;							/* ### */
		}

		strcpy(storage[storagelen], buffer);

		storagelen++;
	}

	Close(file);

	/*
	 * ...and bump revision and date.
	 * Look for VER: _without_ the dollar
	 * for HWGRCS compability.
	 *
	 */

	{
		char	* pos,
				* verpos,
				* revpos,
				* datepos;
		int		  ver,
				  rev;
		char	  revbuf[5],
				  datebuf[11];

		struct DateStamp	datestamp;
		struct ClockData	clockdata;


		for(i=0; i<storagelen; i++)
		{
			pos = strstr(storage[i], argarray[1]);
			if(pos)
			{	/*
				 * Here we _must_ find
				 * <name> version.revision (dd.mm.yy) <something>
				 * or we may fail horribly.
				 *
				 */
				pos += strlen(argarray[1]);
				pos = strstr(pos, " ");
				if(!pos)
				{	continue;
				}
				pos = strstr(pos, ".");
				if(!pos)
				{	continue;
				}

				revpos = pos+1;

				/* backwards to start of version */
				while(isdigit(*(pos-1)))
				{	pos--;
				}
				verpos = pos;

				ver = atoi(pos);

				rev = atoi(revpos);
				internalsprintf(revbuf, "%ld", rev+1);
				if(rev==9 || rev==99 || rev==999 || rev==9999)
				{	/* revision text will grow */
					memmove(revpos+1, revpos,
						strlen(storage[i]) + 1 - (revpos - storage[i]));
				}
				memcpy(revpos, revbuf, strlen(revbuf));

				datepos = strstr(revpos, "(");
				if(!datepos)
				{	continue;
				}

				DateStamp(&datestamp);
				/* add an extra second for good measure */
				Amiga2Date(datestamp.ds_Days*24*60*60 + 1, &clockdata);
				internalsprintf(datebuf, "(%02ld.%02ld.%02ld)", clockdata.mday,
					clockdata.month, clockdata.year%100);
				memcpy(datepos, datebuf, strlen("(dd.mm.yy)"));

				internalsprintf(outbuf, "RELEASE_%ld_%ld\n", ver, rev+1);
			}
		}
	}

	file = Open(argarray[0], MODE_NEWFILE);
	if(!file)
	{
		PrintFault(IoErr(), "Bump");
		result = RETURN_ERROR;
		goto nowrite;
	}

	for(i=0; i<storagelen; i++)
	{
		if(FPuts(file, storage[i]))
		{	break;
		}
	}

	/* Print a certain string to standard output */
	PutStr(outbuf);
rowlimit:
	Close(file);
nowrite:
	/* free storage */	
	for(i=0; i<storagelen; i++)
	{
		FreeVec(storage[i]);
	}
noread:
	FreeArgs(rdargs);
nordargs:
	exit(result);
}



/*
 * The following RawDoFmt-sprintf code
 * comes from Doug Walker. Minor changes.
 *
 */
static void internalsprintf(char * buf, char * fmt, ...)
{
   va_list args;

   va_start(args, fmt);

   /*********************************************************/
   /* NOTE: The string below is actually CODE that copies a */
   /*       value from d0 to A3 and increments A3:          */
   /*                                                       */
   /*          move.b d0,(a3)+                              */
   /*          rts                                          */
   /*                                                       */
   /*       It is essentially the callback routine needed   */
   /*       by RawDoFmt.                                    */
   /*********************************************************/

   RawDoFmt(fmt, args, (void (*))"\x16\xc0\x4e\x75", buf);

   va_end(args);
}
