Index: /issm/trunk/src/c/Makefile.am
===================================================================
--- /issm/trunk/src/c/Makefile.am	(revision 8205)
+++ /issm/trunk/src/c/Makefile.am	(revision 8206)
@@ -111,4 +111,6 @@
 					./objects/KML/KML_SubStyle.cpp\
 					./objects/KML/KML_SubStyle.h\
+					./objects/KML/KMLFileReadUtils.cpp\
+					./objects/KML/KMLFileReadUtils.h\
 					./objects/Options/Option.cpp\
 					./objects/Options/Option.h\
@@ -754,4 +756,6 @@
 					./objects/KML/KML_SubStyle.cpp\
 					./objects/KML/KML_SubStyle.h\
+					./objects/KML/KMLFileReadUtils.cpp\
+					./objects/KML/KMLFileReadUtils.h\
 					./objects/Options/Option.cpp\
 					./objects/Options/Option.h\
Index: /issm/trunk/src/c/objects/KML/KMLFileReadUtils.cpp
===================================================================
--- /issm/trunk/src/c/objects/KML/KMLFileReadUtils.cpp	(revision 8206)
+++ /issm/trunk/src/c/objects/KML/KMLFileReadUtils.cpp	(revision 8206)
@@ -0,0 +1,426 @@
+/*!\file KMLFileUtils.cpp
+ * \brief: utilities for kml file reading.
+ */
+
+/*Headers:*/
+/*{{{1*/
+#ifdef HAVE_CONFIG_H
+	#include "config.h"
+#else
+#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
+#endif
+
+#include "stdio.h"
+#include <string.h>
+#include "../objects.h"
+#include "../../shared/shared.h"
+#include "../../Container/Container.h"
+#include "../../include/include.h"
+/*}}}*/
+
+/*FUNCTION  KMLFileToken(FILE* fid) {{{1*/
+char* KMLFileToken(FILE* fid){
+
+	bool    inew=1,itag=0,ifield=0;
+	int     c;
+	int     ibuf=0,buflen=1024,bufblk=1024;
+	char*   buffer=NULL;
+
+	buffer=(char *) xmalloc(buflen*sizeof(char));
+	buffer[0]='\0';
+
+/*  read kml file  */
+
+//  note that fgets includes newline
+//	fgets(buffer,buflen,fid);
+
+	while ((c=getc(fid)) != EOF) {
+		/*  ignore leading blanks  */
+		if (inew && isspace(c))
+			continue;
+
+		/*  distinguish between tag or field  */
+		if (!itag && !ifield) {
+			if (c == '<')
+				itag=1;
+			else
+				ifield=1;
+			inew=0;
+			KMLFileTokenBuffer(&buffer,&ibuf,&buflen,
+							   c,
+							   bufblk);
+		}
+
+		/*  accumulate tag, not including newlines  */
+		else if (itag) {
+			if (c != '\n') {
+				inew=0;
+				KMLFileTokenBuffer(&buffer,&ibuf,&buflen,
+								   c,
+								   bufblk);
+				if (c == '>')
+					break;
+			}
+			else
+				inew=1;
+		}
+
+		/*  accumulate field, including newlines  */
+		else if (ifield) {
+			if (c == '<') {
+				ungetc(c,fid);
+				break;
+			}
+			else {
+				inew=0;
+				KMLFileTokenBuffer(&buffer,&ibuf,&buflen,
+								   c,
+								   bufblk);
+				if (c == '\n')
+					inew=1;
+			}
+		}
+
+	}
+
+/*  remove trailing blanks or newline  */
+
+	while (ibuf > 0)
+		if (isspace(buffer[ibuf-1]))
+			ibuf--;
+		else {
+			buffer[ibuf]='\0';
+			break;
+		}
+
+	if      (itag)
+		_printf_(true,"tag buffer (length=%d):\n",ibuf);
+	else if (ifield)
+		_printf_(true,"field buffer (length=%d):\n",ibuf);
+	_printf_(true,"%s\n",buffer);
+
+	if (!ibuf)
+		xfree((void**)&buffer);
+
+	return(buffer);
+}
+/*}}}*/
+
+/*FUNCTION  KMLFileTokenBuffer {{{1*/
+void KMLFileTokenBuffer(char** pbuffer,int* pibuf,int* pbuflen,
+						int c,
+						int bufblk){
+
+	char*   buffer=NULL;
+
+/*  check buffer length and realloc if necessary  */
+
+	if (*pibuf+2 > *pbuflen) {
+		*pbuflen+=bufblk;
+		*pbuffer=(char *) xrealloc(*pbuffer,*pbuflen*sizeof(char));
+	}
+
+/*  add character and terminator  */
+
+	(*pbuffer)[(*pibuf)++]=c;
+	(*pbuffer)[ *pibuf   ]='\0';
+
+	return;
+}
+/*}}}*/
+
+/*FUNCTION  KMLFileTagAttrib {{{1*/
+char* KMLFileTagAttrib(char* pstr,int *m,int maxlen,
+					   char* ktag,
+					   char* att){
+
+	char*   ktagi;
+	char*   ktok;
+	char    quote[]={'\"','\0'};
+	char*   pstro=NULL;
+
+	if (pstr)
+		(pstr)[0]='\0';
+
+/*  ktok modifies ktag, so work on copy  */
+
+	ktagi=(char *) xmalloc((strlen(ktag)+1)*sizeof(char));
+	strcpy(ktagi,ktag);
+
+/*  loop through tag to find all attributes  */
+
+	ktok=strtok(ktagi," ");
+	while (ktok=strtok(NULL," =?>")) {
+		_printf_(true,"KMLFileTagAttrib -- attribute %s",ktok);
+
+/*  check if it's the specified attribute  */
+
+		if (!strcmp(ktok,att)) {
+			ktok=strtok(NULL,quote);
+			_printf_(true,"=\"%s\" found.\n",ktok);
+
+			if (!pstr) {
+				pstr=(char *) xmalloc((strlen(ktok)+1)*sizeof(char));
+				pstro=pstr;
+			}
+
+			if (maxlen && (maxlen < strlen(ktok))) {
+				_printf_(true,"KMLFileTagAttrib -- string field too short for attribute \"%s\".\n",att);
+				_printf_(true,"KMLFileTagAttrib -- \"%s\" truncated to %d characters.\n",ktok,maxlen);
+				strncpy(pstr,ktok,maxlen);
+			}
+			else
+				strcpy(pstr,ktok);
+		}
+		else {
+			ktok=strtok(NULL,quote);
+			_printf_(true,"=\"%s\" skipped.\n",ktok);
+		}
+	}
+
+	xfree((void**)&ktagi);
+
+	if (pstr && m)
+		*m=strlen(pstr);
+
+	if (pstr)
+		_printf_(true,"KMLFileTagAttrib -- attribute %s=\"%s\".\n",att,pstr);
+	else
+		_printf_(true,"KMLFileTagAttrib -- attribute \"%s\" not found.\n",att);
+
+	return(pstro);
+}
+/*}}}*/
+
+/*FUNCTION  KMLFileTokenParse {{{1*/
+int KMLFileTokenParse(int* pival,
+					  char* ktag,
+					  FILE* fid){
+
+	char*   kstr;
+
+/*  get next token and convert to appropriate format  */
+
+	if (!(kstr=KMLFileToken(fid)) ||
+		(kstr[0] == '<'))
+		_error_("KMLFileTokenParse -- Missing integer field for %s.\n",ktag);
+
+	sscanf(kstr,"%d",pival);
+	xfree((void**)&kstr);
+
+/*  get additional token and compare to closing tag  */
+
+	if (ktag)
+		if (!(kstr=KMLFileToken(fid)) ||
+			(kstr[0] != '<') ||
+			(kstr[1] != '/') ||
+			(strncmp(&(kstr[2]),&(ktag[1]),strlen(ktag)-1)))
+			_error_("KMLFileTokenParse -- Missing closing tag for %s.\n",ktag);
+		else
+			xfree((void**)&kstr);
+
+	_printf_(true,"KMLFileTokenParse -- %s=%d.\n",ktag,*pival);
+
+	return(0);
+}
+/*}}}*/
+
+/*FUNCTION  KMLFileTokenParse {{{1*/
+int KMLFileTokenParse(bool* pbval,
+					  char* ktag,
+					  FILE* fid){
+
+	int     ival;
+	char*   kstr;
+
+/*  get next token and convert to appropriate format  */
+
+	if (!(kstr=KMLFileToken(fid)) ||
+		(kstr[0] == '<'))
+		_error_("KMLFileTokenParse -- Missing bool field for %s.\n",ktag);
+
+	sscanf(kstr,"%d",&ival);
+	*pbval=(bool)ival;
+	xfree((void**)&kstr);
+
+/*  get additional token and compare to closing tag  */
+
+	if (ktag)
+		if (!(kstr=KMLFileToken(fid)) ||
+			(kstr[0] != '<') ||
+			(kstr[1] != '/') ||
+			(strncmp(&(kstr[2]),&(ktag[1]),strlen(ktag)-1)))
+			_error_("KMLFileTokenParse -- Missing closing tag for %s.\n",ktag);
+		else
+			xfree((void**)&kstr);
+
+	_printf_(true,"KMLFileTokenParse -- %s=%s.\n",ktag,(*pbval ? "true" : "false"));
+
+	return(0);
+}
+/*}}}*/
+
+/*FUNCTION  KMLFileTokenParse {{{1*/
+char* KMLFileTokenParse(char* pstr,int *m,int maxlen,
+						char* ktag,
+						FILE* fid){
+
+	char*   kstr;
+	char*   pstro=NULL;
+
+/*  get next token and allocate if necessary  */
+
+	if (!(kstr=KMLFileToken(fid)) ||
+		(kstr[0] == '<'))
+		_error_("KMLFileTokenParse -- Missing string field for %s.\n",ktag);
+
+	if (!pstr) {
+		if (maxlen)
+			pstr=(char *) xmalloc((maxlen      +1)*sizeof(char));
+		else
+			pstr=(char *) xmalloc((strlen(kstr)+1)*sizeof(char));
+		pstro=pstr;
+	}
+
+	if (maxlen && (maxlen < strlen(kstr))) {
+		_printf_(true,"KMLFileTokenParse -- string field too short for %s.\n",ktag);
+		_printf_(true,"KMLFileTokenParse -- \"%s\" truncated to %d characters.\n",kstr,maxlen);
+		strncpy(pstr,kstr,maxlen);
+	}
+	else
+		strcpy(pstr,kstr);
+	xfree((void**)&kstr);
+
+	if (m)
+		*m=strlen(pstr);
+
+/*  get additional token and compare to closing tag  */
+
+	if (ktag)
+		if (!(kstr=KMLFileToken(fid)) ||
+			(kstr[0] != '<') ||
+			(kstr[1] != '/') ||
+			(strncmp(&(kstr[2]),&(ktag[1]),strlen(ktag)-1)))
+			_error_("KMLFileTokenParse -- Missing closing tag for %s.\n",ktag);
+		else
+			xfree((void**)&kstr);
+
+	_printf_(true,"KMLFileTokenParse -- %s=\"%s\".\n",ktag,pstr);
+
+	return(pstro);
+}
+/*}}}*/
+
+/*FUNCTION  KMLFileTokenParse {{{1*/
+int KMLFileTokenParse(double (**pdval3)[3],int* m,int maxlen,
+					  char* ktag,
+					  FILE* fid){
+
+	int     i=0,j=-1;
+	char*   kstr;
+	char*   ktok;
+	char    delim[]={' ',',','\f','\n','\r','\t','\v','\0'};
+
+/*  get next token and allocate if necessary  */
+
+	if (!(kstr=KMLFileToken(fid)) ||
+		(kstr[0] == '<'))
+		_error_("KMLFileTokenParse -- Missing double [m x 3] field for %s.\n",ktag);
+
+	if (!*pdval3)
+		if (maxlen)
+			*pdval3=(double (*)[3]) xmalloc((maxlen*3)          *sizeof(double));
+		else
+			*pdval3=(double (*)[3]) xmalloc(((strlen(kstr)+1)/2)*sizeof(double));
+
+/*  loop through string to get all values  */
+
+	ktok=strtok(kstr,delim);
+	while (ktok) {
+		j++;
+		if (j == 3) {
+			i++;
+			j=0;
+			if (maxlen && (maxlen < i+1))
+				_error_("KMLFileTokenParse -- Double [m x 3] field too short for %s.\n",ktag);
+		}
+		sscanf(ktok,"%lg",&((*pdval3)[i][j]));
+		ktok=strtok(NULL,delim);
+	}
+	xfree((void**)&kstr);
+
+	if (!maxlen)
+		*pdval3=(double (*)[3]) xrealloc(*pdval3,((i+1)*3)*sizeof(double));
+
+	if (m)
+		*m=i+1;
+
+	if (j != 2)
+		_printf_(true,"KMLFileTokenParse -- Double [m x 3] field for %s does not have multiple of 3 values.\n",ktag);
+
+/*  get additional token and compare to closing tag  */
+
+	if (ktag)
+		if (!(kstr=KMLFileToken(fid)) ||
+			(kstr[0] != '<') ||
+			(kstr[1] != '/') ||
+			(strncmp(&(kstr[2]),&(ktag[1]),strlen(ktag)-1)))
+			_error_("KMLFileTokenParse -- Missing closing tag for %s.\n",ktag);
+		else
+			xfree((void**)&kstr);
+
+	_printf_(true,"KMLFileTokenParse -- %s=...\n",ktag);
+	for (j=0; j<=i; j++)
+		_printf_(true,"   [%d][0-2]: %g,%g,%g\n",j,(*pdval3)[j][0],(*pdval3)[j][1],(*pdval3)[j][2]);
+
+	return(0);
+}
+/*}}}*/
+
+/*FUNCTION  KMLFileTagSkip {{{1*/
+int KMLFileTagSkip(char* ktag,
+				   FILE* fid){
+
+	char*   kstr;
+
+/*  note that tags of the same type can be nested inside each other, so for each
+	opening tag, must find corresponding closing tag  */
+
+	_printf_(true,"KMLFileTagSkip -- input tag %s.\n",ktag);
+
+/*  if next token is a closing tag, compare to input  */
+
+	while (kstr=KMLFileToken(fid)) {
+		if      ((kstr[0] == '<') &&
+				 (kstr[1] == '/') &&
+				 (!strncmp(&(kstr[2]),&(ktag[1]),(strcspn(ktag," >")-1)/sizeof(char)))) {
+			_printf_(true,"KMLFileTagSkip -- closing tag %s.\n",kstr);
+			xfree((void**)&kstr);
+			return(0);
+		}
+
+/*  if next token is an opening tag, call recursively  */
+
+		else if ((kstr[0] == '<') &&
+				 (kstr[1] != '/')) {
+			_printf_(true,"KMLFileTagSkip -- opening tag %s.\n",kstr);
+			KMLFileTagSkip(kstr,
+						   fid);
+		}
+
+/*  if next token is a closing tag, error out  */
+
+		else if ((kstr[0] == '<') &&
+				 (kstr[1] == '/')) {
+			_error_("KMLFileTagSkip -- Unexpected closing tag %s.\n",kstr);
+		}
+
+		xfree((void**)&kstr);
+	}
+
+	_error_("KMLFileTokenParse -- Corresponding closing tag for %s not found.\n",ktag);
+
+	return(0);
+}
+/*}}}*/
+
Index: /issm/trunk/src/c/objects/KML/KMLFileReadUtils.h
===================================================================
--- /issm/trunk/src/c/objects/KML/KMLFileReadUtils.h	(revision 8206)
+++ /issm/trunk/src/c/objects/KML/KMLFileReadUtils.h	(revision 8206)
@@ -0,0 +1,40 @@
+/*!\file:  KMLFileReadUtils.h
+ * \brief: header file for kml file reading utilities.
+ */ 
+
+#ifndef _KMLFILEREADUTILS_H
+#define _KMLFILEREADUTILS_H
+
+/*Headers:{{{1*/
+#include "../../include/include.h"
+#include "../../shared/Exceptions/exceptions.h"
+#include "../../EnumDefinitions/EnumDefinitions.h"
+
+#include "../Object.h"
+/*}}}*/
+
+/* local prototypes: */
+char* KMLFileToken(FILE* fid);
+void KMLFileTokenBuffer(char** pbuffer,int* pibuf,int* pbuflen,
+						int c,
+						int bufblk);
+char* KMLFileTagAttrib(char* pstr,int *m,int maxlen,
+					   char* ktag,
+					   char* att);
+int KMLFileTokenParse(int* pint,
+					  char* ktag,
+					  FILE* fid);
+int KMLFileTokenParse(bool* pbool,
+					  char* ktag,
+					  FILE* fid);
+char* KMLFileTokenParse(char* pstr,int *m,int maxlen,
+					  char* ktag,
+					  FILE* fid);
+int KMLFileTokenParse(double (**pdoub3)[3],int* m,int maxlen,
+					  char* ktag,
+					  FILE* fid);
+int KMLFileTagSkip(char* ktag,
+				   FILE* fid);
+
+#endif  /* _KMLFILEREADUTILS_H */
+
Index: /issm/trunk/src/c/objects/objects.h
===================================================================
--- /issm/trunk/src/c/objects/objects.h	(revision 8205)
+++ /issm/trunk/src/c/objects/objects.h	(revision 8206)
@@ -62,4 +62,5 @@
 #include "./KML/KML_StyleSelector.h"
 #include "./KML/KML_SubStyle.h"
+#include "./KML/KMLFileReadUtils.h"
 
 /*Option parsing objects: */
