%{
/* isp.y - Internal Signaling Protocol test generator language */

/* Written 1997 by Werner Almesberger, EPFL-ICA */


#include <stdlib.h>
#include <string.h>
#include <atm.h>
#include <linux/atmsvc.h>

#include "isp.h"


static struct atmsvc_msg msg;

%}

%union {
    char *str;
    enum atmsvc_msg_type type;
};


%token		TOK_SEND TOK_WAIT TOK_VCC TOK_LISTEN TOK_REPLY TOK_PVC
%token		TOK_LOCAL TOK_QOS TOK_SVC TOK_BIND TOK_CONNECT TOK_ACCEPT
%token		TOK_REJECT TOK_LISTEN TOK_OKAY TOK_ERROR TOK_INDICATE
%token		TOK_CLOSE TOK_ITF_NOTIFY TOK_MODIFY TOK_SAP TOK_EOL
%token		TOK_IDENTIFY
%token	<str>	TOK_VALUE

%type	<type>	type

%%

all:
    | command all
    ;

command:
    TOK_SEND type
	{
	    memset(&msg,0,sizeof(msg));
	    msg.type = $2;
	}
      values TOK_EOL
	{
	    send_msg(&msg);
	}
    | TOK_WAIT TOK_EOL
	{
	    recv_msg(&msg);
	    dump_msg(&msg);
	}
    | TOK_EOL
    ;

type:
    TOK_BIND
	{
	    $$ = as_bind;
	}
    | TOK_CONNECT
	{
	    $$ = as_connect;
	}
    | TOK_ACCEPT
	{
	    $$ = as_accept;
	}
    | TOK_REJECT
	{
	    $$ = as_reject;
	}
    | TOK_LISTEN
	{
	    $$ = as_listen;
	}
    | TOK_OKAY
	{
	    $$ = as_okay;
	}
    | TOK_ERROR
	{
	    $$ = as_error;
	}
    | TOK_INDICATE
	{
	    $$ = as_indicate;
	}
    | TOK_CLOSE
	{
	    $$ = as_close;
	}
    | TOK_ITF_NOTIFY
	{
	    $$ = as_itf_notify;
	}
    | TOK_MODIFY
	{
	    $$ = as_modify;
	}
    | TOK_IDENTIFY
	{
	    $$ = as_identify;
	}
    ;

values:
    | value values
    ;

value:
    TOK_VCC TOK_VALUE
	{
	    char *end;

	    msg.vcc = strtoul($2,&end,0);
	    if (*end) yyerror("invalid VCC id");
	    free($2);
	}
    | TOK_LISTEN TOK_VALUE
	{
	    char *end;

	    msg.listen_vcc = strtoul($2,&end,0);
	    if (*end) yyerror("invalid VCC id");
	    free($2);
	}
    | TOK_REPLY TOK_VALUE
	{
	    char *end;

	    msg.reply = strtol($2,&end,0);
	    if (*end) {
		int code;

		code = str2errno(*$2 == '-' ? $2+1 : $2);
		if (!code) yyerror("invalid error code");
		msg.reply = *$2 == '-' ? -code : code;
	    }
	    free($2);
	}
    | TOK_PVC TOK_VALUE
	{
	    if (text2atm($2,(struct sockaddr *) &msg.pvc,sizeof(msg.pvc),
	      T2A_PVC | T2A_NNI | T2A_NAME) < 0)
		yyerror("invalid PVC address");
	    free($2);
	}
    | TOK_LOCAL TOK_VALUE
	{
	    if (text2atm($2,(struct sockaddr *) &msg.local,sizeof(msg.local),
	      T2A_SVC | T2A_NAME) < 0)
		yyerror("invalid SVC address");
	    free($2);
	}
    | TOK_QOS TOK_VALUE
	{
	    if (text2qos($2,&msg.qos,0) < 0)
		yyerror("invalid QOS");
	    free($2);
	}
    | TOK_SVC TOK_VALUE
	{
	    if (text2atm($2,(struct sockaddr *) &msg.svc,sizeof(msg.svc),
	      T2A_SVC | T2A_NAME) < 0)
		yyerror("invalid SVC address");
	    free($2);
	}
    | TOK_SAP TOK_VALUE
	{
	    if (text2sap($2,&msg.sap,T2S_NAME) < 0)
		yyerror("invalid SAP address");
	    free($2);
	}
    ;
