/*-=-=-=-=-=-=-=-=-=-=-=- RCCL/RCI Notice of Copyright -=-=-=-=-=-=-=-=-=-=-*
 *									    *
 *	Copyright (C) 1987, 1991 by John E. Lloyd.			    *
 *									    *
 *	Information on copyright permissions, as well as a complete	    *
 *	disclaimer of warranty, is given in the file COPYRIGHT.		    *
 *									    *
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*---------------------------------------------------------------------------
 *		
 * MODULE NAME:	robotFile
 *
 * DESCRIPTION:	Routines to read the 'robots' file, which contains
 *		configuration information (like I/O device addresses)
 *		for each of the robots available to the system.
 * 
 * CAVEATS:	This interface will probably be replaced by a more
 *		general database package in development.
 *
 * AUTHOR/DATE:	John Lloyd, Fall 1987
 *
 * MODIFICATION HISTORY:
 *
 *--------------------------------------------------------------------------*/

#ifndef VXWORKS_CFG
#include <stdio.h>
#else
#include <vxWorks.h>
#include <stdioLib.h>
#endif

#include <ctype.h>

#include "../h/cdefs.h"
#include "../h/IOdevice.h"
#include "../h/errorCodes.h"

#include "../rci/robotDefs.h"
#include "../rci/link.h"

/* ----- Error Messages. Defined externally to save space ----- */

static char *outOfMemoryMsg	= "%s -- out of memory\n";
static char *parseErrMsg	= "%s %s, line %d\n";
static char *cantOpenFileMsg	= "%s -- can't open file %s\n";
static char *badKeywordMsg 	= "%s illegal keyword %s, line %d\n";

extern char *copyofstr();

#define IBUFSIZE 256
#define PARSE_ERROR(m)	errorMsg(EBadObj, parseErrMsg, fxnName, \
				 (m), lineNumber()); \
			fclose (fp); return (-1);

readRobotFile(fileName, robotDefList)
char *fileName;
ROBOT_DEFS *robotDefList;
{
	char *fxnName = "readRobotFile()";
	ROBOT_DEFS *rdefs;
	int k;

	char ibuf[IBUFSIZE];
	FILE *fp;

	enum keytype {
	  	Device,
	  	Address,
	  	Interrupt,
		Arg,
		Intraddr,
		Vector,
		Ipl
	  } keyword;
	int argnum = UNDEF;

	robotDefList->prev = robotDefList->next = robotDefList;

	if ((fp = fopen (fileName, "r")) == NULL)
	 { errorMsg (EBadAccess, cantOpenFileMsg, fxnName, fileName);
	   return (-1);
	 }

	readInit (fp, "=");
	if (!readIdentifier (ibuf, IBUFSIZE) ||
	    strcmp (ibuf, "robot") != 0)
	 { if (!endOfInput())
	    { PARSE_ERROR ("'robot' keyword expected");
	    }
	 }
	while (!endOfInput())
	 { if (readCharacter() != '=')
	    { PARSE_ERROR ("'=' expected");
	    }
	   if (!readIdentifier (ibuf, IBUFSIZE))
	    { PARSE_ERROR ("robot name expected");
	    }
	   if ((rdefs = ALLOC(ROBOT_DEFS)) == NULL)
	    { errorMsg (EMemory, outOfMemoryMsg, fxnName);
	      fclose(fp); return(-1);
	    }
	   bzero (rdefs, sizeof(ROBOT_DEFS));
	   rdefs->device = NULL;
	   rdefs->name = copyofstr(ibuf);
	   for (k=0; k<MAX_DEVARGS; k++)
	    { rdefs->args[k] = UNDEF;
	    }

	   while (1)
	    { if (!readIdentifier (ibuf, IBUFSIZE))
	       { if (endOfInput())
		  { break;
		  }
		 else
		  { PARSE_ERROR ("keyword expected");
		  }
	       }

	      argnum = UNDEF;
	      if (strncmp (ibuf, "arg", strlen("arg")) == 0)
	       { char *cp = ibuf + strlen("arg");
		 int num;
		 
		 if (isdigit(*cp))
		  { num = atoi(cp);
		    while (isdigit(*cp))
		     { cp++;
		     }
		    if (*cp == '\0' && num < MAX_DEVARGS)
		     { argnum = num;
		     }
		  }
	       }
	      
	      if (strcmp (ibuf, "device") == 0)
	       { keyword = Device;
	       }
	      else if (strcmp (ibuf, "address") == 0)
	       { keyword = Address;
	       }
	      else if (strcmp (ibuf, "interrupt") == 0)
	       { keyword = Interrupt;
	       }
	      else if (strcmp (ibuf, "intraddr") == 0)
	       { keyword = Intraddr;
	       }
	      else if (strcmp (ibuf, "vector") == 0)
	       { keyword = Vector;
	       }
	      else if (strcmp (ibuf, "ipl") == 0)
	       { keyword = Ipl;
	       }
	      else if (argnum != UNDEF)
	       { keyword = Arg;
	       }
	      else if (strcmp (ibuf, "robot") == 0)
	       { break;
	       }
	      else
	       { errorMsg(EBadObj, badKeywordMsg, fxnName,ibuf,lineNumber());
		 fclose(fp); return (-1);
	       }
	      if (readCharacter() != '=')
	       { PARSE_ERROR ("'=' expected");
	       }
	      switch (keyword)
	       { case Address:
		  { if (!readInteger(&rdefs->address))
		     { PARSE_ERROR ("integer expected after 'address ='");
		     }
		    rdefs->addressSet = 1;
		    break;
		  }
		 case Arg:
		  { if (!readInteger(&rdefs->args[argnum]))
		     { PARSE_ERROR ("integer expected after 'arg<n> ='");
		     }
		    break;
		  }
		 case Device:
		  { if (!readIdentifier(ibuf, IBUFSIZE))
		     { PARSE_ERROR ("identifier expected after 'device ='");
		     }
		    rdefs->device = copyofstr (ibuf);
		    break;
		  }
		 case Interrupt:
		  { if (!readString(ibuf, IBUFSIZE))
		     { PARSE_ERROR ("string expected after 'interrupt ='");
		     }
		    rdefs->interrupt = copyofstr (ibuf);
		    break;
		  }
		 case Intraddr:
		  { if (!readInteger(&rdefs->intraddr))
		     { PARSE_ERROR ("integer expected after 'intraddr ='");
		     }
		    rdefs->intraddrSet = 1;
		    break;
		  }
		 case Vector:
		  { if (!readInteger(&rdefs->vector))
		     { PARSE_ERROR ("integer expected after 'vector ='");
		     }
		    rdefs->vectorSet = 1;
		    break;
		  }
		 case Ipl:
		  { if (!readInteger(&rdefs->ipl))
		     { PARSE_ERROR ("integer expected after 'ipl ='");
		     }
		    rdefs->iplSet = 1;
		    break;
		  }
	       }
	    }
	   LINK (rdefs, robotDefList);
	 }
	fclose (fp);
	return (1);
}
