changeset 4:4bb09e405eab

Added new files for 0.8
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 03 Jun 2003 11:03:04 +0000
parents 279b1e12df2b
children 5b7009eef767
files src/xs_length.c src/xs_length.h src/xs_md5.c src/xs_md5.h src/xs_support.c src/xs_support.h
diffstat 6 files changed, 783 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/xs_length.c	Tue Jun 03 11:03:04 2003 +0000
@@ -0,0 +1,262 @@
+/*  
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   Get song length (from database or by other means)
+   
+   Written by Matti "ccr" Hamalainen <ccr@tnsp.org>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "xmms-sid.h"
+#include "xs_length.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+/*
+ * Pointer to database in memory
+ */
+static t_xs_dbentry	*xs_database = NULL;
+
+
+/*
+ * Parses a time-entry in SLDB format
+ */
+long int xs_gettime(char *pcStr, int *piPos)
+{
+ long int iResult;
+ int iTemp;
+ char chTempBuf[16];
+
+ /* Check if it starts with a digit */ 
+ if (isdigit(pcStr[*piPos]))
+	{
+	/* Get minutes-field */
+	iTemp = *piPos;
+	xs_findnum(pcStr, piPos);
+ 
+	strncpy(chTempBuf, &pcStr[iTemp], (*piPos - iTemp));
+	chTempBuf[*piPos - iTemp] = 0;
+ 
+	iResult = (atol(chTempBuf) * 60);
+
+	/* Check the field separator char */
+	if (pcStr[*piPos] == ':')
+		{
+		/* Get seconds-field */
+		(*piPos)++;
+		iTemp = *piPos;
+		xs_findnum(pcStr, piPos);
+
+		strncpy(chTempBuf, &pcStr[iTemp], (*piPos - iTemp));
+		chTempBuf[*piPos - iTemp] = 0;
+ 
+		iResult += atol(chTempBuf);
+		
+		} else
+		iResult = -2;
+	} else
+	iResult = -1;
+
+ /* Ignore and skip the possible attributes */
+ while (!isspace(pcStr[*piPos])) (*piPos)++;
+ 
+ return iResult;
+}
+
+
+/*
+ * Initialize, read database to memory
+ */
+gint xs_db_initialize(gchar *pcFilename)
+{
+ FILE *inFile;
+ char inLine[256];
+ int lineNum, linePos, i, j, k;
+ t_xs_hash tmpHash;
+
+   
+ /* Try to open the file */
+ if ((inFile = fopen(pcFilename, "r")) == NULL)
+ 	{
+ 	fprintf(stderr, "hv!\n");
+ 	return -1;
+ 	}
+ 
+
+ /* Read and parse the data */
+ lineNum = 0;
+
+ while (!feof(inFile))
+ {
+ fgets(inLine, sizeof(inLine), inFile);
+ linePos = 0;
+  
+ if (strlen(inLine) > 1)
+ {
+ /* Find first character */
+ xs_findnext(inLine, &linePos);
+
+ /* Check if it is a hash-line */ 
+ if (isxdigit(inLine[linePos]))
+ 	{
+ 	i = linePos;
+ 	while (isxdigit(inLine[linePos])) linePos++;
+
+	if ((linePos - i) != XS_HASH_LENGTH_CH)
+		{
+		XSERR("Invalid hash/syntax error in SongLengthDB file '%s' line #%d!\n",
+		pcFilename, lineNum);
+		} else {
+		/* Get hashcode value */
+		for (j = 0; j < XS_HASH_LENGTH; j++)
+			{
+			
+			}
+
+		/* Get playtimes */
+		xs_findnext(line, &linePos);
+
+		if (line[linePos] != '=')
+			{
+			XSERR("Warning: '=' expected in line #%d in SongLengthDB file '%s'\n",
+			lineNum, pcFilename);
+			} else {
+			linePos++;
+
+			while (linePos < strlen(inLine))
+				{
+				xs_findnext(line, &linePos);
+				printf("[%lis]", xs_gettime(inLine, &linePos));
+				}
+		
+
+			/* Add an entry to db in memory */
+			}
+		}
+ 	}
+ 	else
+ if ((line[linePos] != ';') && (line[linePos] != '['))
+ 	{
+	XSERR("Invalid line #%d in SongLengthDB file '%s'\n", lineNum, pcFilename);
+	}
+ 
+ } /* strlen(line) > 1 */
+ 
+ lineNum++;
+ }
+  
+ fclose(inFile);
+ 
+ return 0;
+}
+
+
+/*
+ *
+ */
+gint xs_db_delete(void)
+{
+ /* Free the memory allocated for database */
+
+ return 0;
+}
+
+
+/*
+ *
+ */
+int xs_comparehashes(t_xs_hash *testHash1, t_xs_hash *testHash2)
+{
+ int iIndex, iOK;
+
+ iOK = 1;
+ iIndex = 0;
+ while ((iIndex < 16) && (iOK))
+ 	{
+ 	if (testHash1[iIndex] != testHash2[iIndex])
+ 		iOK = 0;
+ 		else
+ 		iIndex++;
+	}
+
+ return iOK;
+}
+
+
+
+
+/*
+ * Get song length from database
+ */
+t_xs_dbentry * xs_db_get(gchar *pcFilename)
+{
+
+ return NULL;
+}
+
+
+gint32 xs_get_length(gchar *pcFilename, gint iSubTune)
+{
+ gint32 iResult;
+ t_xs_dbentry *dbEntry;
+ t_xs_hash dbHash;
+
+ iResult = -1;
+
+ switch (xs_cfg.playMethod) {
+
+  case XMMS_SID_PMETHOD_DATABASE:
+  		
+	iResult = xs_db_get(pcFilename, &dbHash);
+	if (iResult >= 0)
+		{
+		}
+		
+	if (dbEntry)
+		{
+		if ((iSubTune >= 0) && (iSubTune < dbEntry->nlengths))
+			iResult = dbEntry->lengths[iSubTune];
+			else
+			iResult = -1;
+  		}
+  	break;
+
+  case XMMS_SID_PMETHOD_MAXSILENCE:
+  case XMMS_SID_PMETHOD_NONE:
+	iResult = -1;
+	break;
+
+  default:
+	XSERR("Invalid play-method! (%d, unknown)\n", xs_cfg.playMethod);
+	break;
+ }
+
+ /* Check for max playtime */
+ if (iResult == -1)
+ 	{
+	if (xs_cfg.playUseMaxTime)
+		iResult = xs_cfg.playMaxTime;
+		else
+		iResult = -1;
+ 	}
+ 
+ XSDEBUG("fname='%s', sub=%i, res=%li\n", pcFilename, iSubTune, iResult);
+  
+ return iResult;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/xs_length.h	Tue Jun 03 11:03:04 2003 +0000
@@ -0,0 +1,34 @@
+#ifndef XS_LENGTH_H
+#define XS_LENGTH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ * Defines and typedefs
+ */
+#define XS_HASH_LENGTH		(16)
+#define XS_HASH_LENGTH_CH	(XS_HASH_LENGTH * 2)
+
+typedef guint8 t_xs_hash[XS_HASH_LENGTH];
+
+typedef struct {
+	t_xs_hash	hashcode;	/* 128-bit MD5 hash-digest */
+	gint		nlengths;	/* Number of lengths */
+	long int	lengths[XMMS_SID_STIL_MAXENTRY];	
+					/* Lengths in seconds */
+} t_xs_dbentry;
+
+
+/*
+ * Functions
+ */
+gint32	xs_get_length(gchar *, gint);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* XS_LENGTH_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/xs_md5.c	Tue Jun 03 11:03:04 2003 +0000
@@ -0,0 +1,325 @@
+/*
+  Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321.
+  It is derived directly from the text of the RFC and not from the
+  reference implementation.
+
+  The original and principal author of md5.c is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-08-25 ccr Edited for integration in XMMS-SID. Removed unnecessary stuff.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+  1999-05-03 lpd Original version.
+ */
+
+#include <glib.h>
+#include <string.h>
+#include "xs_md5.h"
+
+#define T1 0xd76aa478
+#define T2 0xe8c7b756
+#define T3 0x242070db
+#define T4 0xc1bdceee
+#define T5 0xf57c0faf
+#define T6 0x4787c62a
+#define T7 0xa8304613
+#define T8 0xfd469501
+#define T9 0x698098d8
+#define T10 0x8b44f7af
+#define T11 0xffff5bb1
+#define T12 0x895cd7be
+#define T13 0x6b901122
+#define T14 0xfd987193
+#define T15 0xa679438e
+#define T16 0x49b40821
+#define T17 0xf61e2562
+#define T18 0xc040b340
+#define T19 0x265e5a51
+#define T20 0xe9b6c7aa
+#define T21 0xd62f105d
+#define T22 0x02441453
+#define T23 0xd8a1e681
+#define T24 0xe7d3fbc8
+#define T25 0x21e1cde6
+#define T26 0xc33707d6
+#define T27 0xf4d50d87
+#define T28 0x455a14ed
+#define T29 0xa9e3e905
+#define T30 0xfcefa3f8
+#define T31 0x676f02d9
+#define T32 0x8d2a4c8a
+#define T33 0xfffa3942
+#define T34 0x8771f681
+#define T35 0x6d9d6122
+#define T36 0xfde5380c
+#define T37 0xa4beea44
+#define T38 0x4bdecfa9
+#define T39 0xf6bb4b60
+#define T40 0xbebfbc70
+#define T41 0x289b7ec6
+#define T42 0xeaa127fa
+#define T43 0xd4ef3085
+#define T44 0x04881d05
+#define T45 0xd9d4d039
+#define T46 0xe6db99e5
+#define T47 0x1fa27cf8
+#define T48 0xc4ac5665
+#define T49 0xf4292244
+#define T50 0x432aff97
+#define T51 0xab9423a7
+#define T52 0xfc93a039
+#define T53 0x655b59c3
+#define T54 0x8f0ccc92
+#define T55 0xffeff47d
+#define T56 0x85845dd1
+#define T57 0x6fa87e4f
+#define T58 0xfe2ce6e0
+#define T59 0xa3014314
+#define T60 0x4e0811a1
+#define T61 0xf7537e82
+#define T62 0xbd3af235
+#define T63 0x2ad7d2bb
+#define T64 0xeb86d391
+
+
+static void xs_md5_process(t_xs_md5state * pms, const guint8 * data)
+{
+ guint32 a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3];
+ guint32 t;
+ guint32 X[16];
+ const guint8 *xp = data;
+ int i;
+
+ for (i = 0; i < 16; ++i, xp += 4)
+	X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+
+
+ /*
+  * Round 1. Let [abcd k s i] denote the operation
+  * a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s).
+  */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + F(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 7, T1);
+ SET(d, a, b, c, 1, 12, T2);
+ SET(c, d, a, b, 2, 17, T3);
+ SET(b, c, d, a, 3, 22, T4);
+ SET(a, b, c, d, 4, 7, T5);
+ SET(d, a, b, c, 5, 12, T6);
+ SET(c, d, a, b, 6, 17, T7);
+ SET(b, c, d, a, 7, 22, T8);
+ SET(a, b, c, d, 8, 7, T9);
+ SET(d, a, b, c, 9, 12, T10);
+ SET(c, d, a, b, 10, 17, T11);
+ SET(b, c, d, a, 11, 22, T12);
+ SET(a, b, c, d, 12, 7, T13);
+ SET(d, a, b, c, 13, 12, T14);
+ SET(c, d, a, b, 14, 17, T15);
+ SET(b, c, d, a, 15, 22, T16);
+
+#undef SET
+
+ /*
+  * Round 2. Let [abcd k s i] denote the operation
+  * a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s).
+  */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + G(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 1, 5, T17);
+ SET(d, a, b, c, 6, 9, T18);
+ SET(c, d, a, b, 11, 14, T19);
+ SET(b, c, d, a, 0, 20, T20);
+ SET(a, b, c, d, 5, 5, T21);
+ SET(d, a, b, c, 10, 9, T22);
+ SET(c, d, a, b, 15, 14, T23);
+ SET(b, c, d, a, 4, 20, T24);
+ SET(a, b, c, d, 9, 5, T25);
+ SET(d, a, b, c, 14, 9, T26);
+ SET(c, d, a, b, 3, 14, T27);
+ SET(b, c, d, a, 8, 20, T28);
+ SET(a, b, c, d, 13, 5, T29);
+ SET(d, a, b, c, 2, 9, T30);
+ SET(c, d, a, b, 7, 14, T31);
+ SET(b, c, d, a, 12, 20, T32);
+
+#undef SET
+
+ /*
+  * Round 3. Let [abcd k s t] denote the operation
+  * a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s).
+  */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + H(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 5, 4, T33);
+ SET(d, a, b, c, 8, 11, T34);
+ SET(c, d, a, b, 11, 16, T35);
+ SET(b, c, d, a, 14, 23, T36);
+ SET(a, b, c, d, 1, 4, T37);
+ SET(d, a, b, c, 4, 11, T38);
+ SET(c, d, a, b, 7, 16, T39);
+ SET(b, c, d, a, 10, 23, T40);
+ SET(a, b, c, d, 13, 4, T41);
+ SET(d, a, b, c, 0, 11, T42);
+ SET(c, d, a, b, 3, 16, T43);
+ SET(b, c, d, a, 6, 23, T44);
+ SET(a, b, c, d, 9, 4, T45);
+ SET(d, a, b, c, 12, 11, T46);
+ SET(c, d, a, b, 15, 16, T47);
+ SET(b, c, d, a, 2, 23, T48);
+
+#undef SET
+
+ /*
+  * Round 4. Let [abcd k s t] denote the operation
+  * a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s).
+  */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + I(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 6, T49);
+ SET(d, a, b, c, 7, 10, T50);
+ SET(c, d, a, b, 14, 15, T51);
+ SET(b, c, d, a, 5, 21, T52);
+ SET(a, b, c, d, 12, 6, T53);
+ SET(d, a, b, c, 3, 10, T54);
+ SET(c, d, a, b, 10, 15, T55);
+ SET(b, c, d, a, 1, 21, T56);
+ SET(a, b, c, d, 8, 6, T57);
+ SET(d, a, b, c, 15, 10, T58);
+ SET(c, d, a, b, 6, 15, T59);
+ SET(b, c, d, a, 13, 21, T60);
+ SET(a, b, c, d, 4, 6, T61);
+ SET(d, a, b, c, 11, 10, T62);
+ SET(c, d, a, b, 2, 15, T63);
+ SET(b, c, d, a, 9, 21, T64);
+
+#undef SET
+
+ /*
+  * Then perform the following additions. (That is increment each
+  * of the four registers by the value it had before this block was started.)
+  */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
+}
+
+
+void xs_md5_init(t_xs_md5state * pms)
+{
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = 0xefcdab89;
+ pms->abcd[2] = 0x98badcfe;
+ pms->abcd[3] = 0x10325476;
+}
+
+
+void xs_md5_append(t_xs_md5state * pms, const guint8 * data, int nbytes)
+{
+ const guint8 *p = data;
+ int left = nbytes;
+ int offset = (pms->count[0] >> 3) & 63;
+ guint32 nbits = (guint32) (nbytes << 3);
+
+ if (nbytes <= 0)
+	return;
+
+ /* Update the message length. */
+ pms->count[1] += nbytes >> 29;
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+	pms->count[1]++;
+
+ /* Process an initial partial block. */
+ if (offset)
+ 	{
+	int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+	memcpy(pms->buf + offset, p, copy);
+
+	if (offset + copy < 64)
+		return;
+
+	p += copy;
+	left -= copy;
+	xs_md5_process(pms, pms->buf);
+	}
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+	xs_md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+	memcpy(pms->buf, p, left);
+}
+
+
+void xs_md5_finish(t_xs_md5state * pms, t_xs_md5hash digest)
+{
+ static const guint8 pad[64] = {
+	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ guint8 data[8];
+ gint i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+	data[i] = (guint8) (pms->count[i >> 2] >> ((i & 3) << 3));
+
+ /* Pad to 56 bytes mod 64. */
+ xs_md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+
+ /* Append the length. */
+ xs_md5_append(pms, data, 8);
+ for (i = 0; i < XS_MD5HASH_LENGTH; ++i)
+	digest[i] = (guint8) (pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/xs_md5.h	Tue Jun 03 11:03:04 2003 +0000
@@ -0,0 +1,31 @@
+#ifndef XS_MD5_H
+#define XS_MD5_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "xs_length.h"
+
+/*
+ * Typedefs
+ */
+typedef struct md5_state_s {
+    guint32 count[2];	/* message length in bits, lsw first */
+    guint32 abcd[4];	/* digest buffer */
+    guint8 buf[64];	/* accumulate block */
+} t_xs_md5state;
+
+
+/*
+ * Functions
+ */
+void xs_md5_init(t_xs_md5state *pms);
+void xs_md5_append(t_xs_md5state *pms, const guint8 *data, int nbytes);
+void xs_md5_finish(t_xs_md5state *pms, t_xs_md5hash digest);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* XS_MD5_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/xs_support.c	Tue Jun 03 11:03:04 2003 +0000
@@ -0,0 +1,108 @@
+/*  
+   XMMS-SID - SIDPlay input plugin for X MultiMedia System (XMMS)
+
+   Miscellaneous support functions
+   
+   Written by Matti "ccr" Hamalainen <ccr@tnsp.org>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "xmms-sid.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+/*
+ * Utility routines
+ */
+int xs_strcalloc(gchar **result, const gchar *str)
+{
+	/* Check the string pointers */
+	if ((result == NULL) || (str == NULL))
+		return -1;
+
+	/* Allocate memory for destination */
+	*result = (gchar *) g_realloc(*result, strlen(str) + 1);
+
+	if (*result == NULL) return -2;
+
+	/* Copy to the destination */
+	strcpy(*result, str);
+	
+	return 0;
+}
+
+
+int xs_strcat(gchar **ppcResult, const gchar *pcStr)
+{
+	int ilen;
+
+	/* Check the pcString pointers */
+	if ((ppcResult == NULL) || (pcStr == NULL))
+		return -1;
+
+	/* Get length of the pcString to be catted */
+	ilen = strlen(pcStr);
+
+	/* Re-allocate memory for destination */
+	*ppcResult = (gchar *) g_realloc(*ppcResult, strlen(*ppcResult) + ilen + 1);
+
+	if (*ppcResult == NULL) return -2;
+
+	/* Cat to the destination */
+	strcat(*ppcResult, pcStr);
+
+	return 0;
+}
+
+
+int xs_strcpy(gchar **ppcResult, gint *j, const gchar *pcStr)
+{
+	int ilen;
+
+	/* Check the pcString pointers */
+	if ((ppcResult == NULL) || (pcStr == NULL) || (j == NULL))
+		return -1;
+
+	/* Get length of the pcString to be catted */
+	(*j) += ilen = strlen(pcStr);
+
+	/* Re-allocate memory for destination */
+	*ppcResult = (gchar *) g_realloc(*ppcResult, strlen(*ppcResult) + ilen + 1);
+
+	if (*ppcResult == NULL) return -2;
+
+	/* Cat to the destination */
+	strcat(*ppcResult, pcStr);
+
+	return 0;
+}
+
+
+inline void xs_findnext(gchar *pcStr, gint *piPos)
+{
+ /* Terminating NULL-character is not whitespace! */
+ while (isspace(pcStr[*piPos])) (*piPos)++;
+}
+
+
+inline void xs_findnum(gchar *pcStr, gint *piPos)
+{
+ /* Terminating NULL-character is not digit! */
+ while (isdigit(pcStr[*piPos])) (*piPos)++;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/xs_support.h	Tue Jun 03 11:03:04 2003 +0000
@@ -0,0 +1,23 @@
+#ifndef XS_SUPPORT_H
+#define XS_SUPPORT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <glib.h>
+
+/*
+ * Functions
+ */
+int	xs_strcalloc(gchar **, const gchar *);
+int	xs_strcat(gchar **, const gchar *);
+int	xs_strcpy(gchar **, gint *, const gchar *);
+inline 	void xs_findnext(gchar *, gint *);
+inline	void xs_findnum(gchar *, gint *);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* XS_SUPPORT_H */