%{
/*************************************************************************
**
** interp.y - the following yacc code is used to parse the configuration
**		files.
**
*************************************************************************/

/*
 * $Log: interp.y,v $
 * Revision 1.6  1991/10/22  18:55:18  jplevyak
 * Allow comma in arguments.
 *
 * Revision 1.5  1991/10/17  12:28:42  jplevyak
 * Fixed bug with malloc of 1 to few bytes.
 *
 * Revision 1.4  1991/10/16  17:04:19  jplevyak
 * Added support of . in filenames.
 *
 * Revision 1.3  1991/10/16  16:22:46  jplevyak
 * Put ; after last entry in union decl (sgi requires it).
 *
 * Revision 1.2  1991/10/14  22:18:19  jefft
 * Fixed problem with path definition with AGENT statements
 *
 * Revision 1.1  1991/10/11  23:16:01  jefft
 * Initial revision
 *
 */


#include	<stdio.h>
#include	<string.h>


static char **add_list(list, cptr)
  char	**list, *cptr;
{
  int	i = 0;

  /* create the list if neccessary */
  if (list == NULL)
    if ((list = (char **)malloc(16 * sizeof (char*))) == NULL)  {
      fprintf(stderr, "Error: out of memory.\n");
      exit(-1);
      }
    else
      *list = NULL;

  /* add pointer to beginning of list */
  for(i=0; i<16; i+=1)
    if (*(list+i) == NULL)  {
      *(list+i) = cptr;
      *(list+i+1) = NULL;
      break;
      }

  return list;
}

%}
%union { int y_int; char *y_str; char **y_ptr;}

%token <y_str> NAME
%token <y_int> AOP IOP COP
%token <y_int> CSYM
%token <y_int> PORTSEP
%token <y_str> Sconstant

%type <y_str> se args path port name arg_se
%type <y_ptr> plist dstlist

%start buffer

%%

buffer	: /* empty */
	| stmts
			;

stmts	: Astmt
	| Istmt
	| Cstmt
			;

/* handle agent declarations */
Astmt	: AOP se '(' plist PORTSEP plist ')' path args	
			{ agentStatement($2, $4, $6, $8, $9); }
	| AOP se '(' PORTSEP plist ')' path args
			{ agentStatement($2, NULL, $5, $7, $8); }
	| AOP se '(' plist PORTSEP ')' path args
			{ agentStatement($2, $4, NULL, $7, $8); }

plist	: se
			{ $$ = add_list(NULL, $1); }
	| plist ',' se
			{ $$ = add_list($$, $3); }


path	: name 
	| name ':' name 
			{ $$ = (char*)malloc(strlen($1) + strlen($3) + 2);
			  strcat(strcat(strcpy($$, $1), ":"), $3);
			  free($1); free($3);
			}

name	: se
	| name '.' se
			{ $$ = (char*)malloc(strlen($1) + strlen($3) + 2);
			  strcat(strcat(strcpy($$, $1), "."), $3);
			  free($1); free($3);
			}

args	: arg_se
	| args arg_se
			{ $$ = (char*)malloc(strlen($1) + strlen($2) + 2);
			  strcat(strcat(strcpy($$, $1), " "), $2);
			  free($1); free($2);
			}


/* invoke processes */
Istmt	: IOP se '(' se ')' 
			{ invokeStatement($2, $4, -1, -1); }
	| IOP se '(' se ',' se ',' se ')'
			{ invokeStatement($2, $4, atoi($6), atoi($8)); }

/* connect ports */
Cstmt	: COP port CSYM dstlist
			{ connectStatement($2, $4); }

dstlist	: port
			{ $$ = add_list(NULL, $1); }
	| dstlist ',' port
			{ $$ = add_list($$, $3); }

port	: se '.' se
			{ $$ = (char*)malloc(strlen($1) + strlen($3) + 2);
			  strcat(strcat(strcpy($$, $1), "."), $3);
			  free($1); free($3);
			}


se	: Sconstant

arg_se	: Sconstant 
		| arg_se ',' Sconstant
			{ $$ = (char*)malloc(strlen($1) + strlen($3) + 2);
			  strcat(strcat(strcpy($$, $1), ","), $3);
			  free($1); free($3);
			}


%%


yyerror(s)
	register char	*s;
{

	fprintf(stderr, "'%s'\n", s);
}

#ifdef DEBUG
main()
{
	char	buf[256];

	while	(gets(buf))
           lexi_buf(buf), yyparse();

	return 0;
}
#endif
