blob: 26833b26290b9458ed02addb57949d591ffc0e25 [file] [log] [blame]
%{
/*
* libiio - Library for interfacing industrial I/O (IIO) devices
*
* Copyright (C) 2014 Analog Devices, Inc.
* Author: Paul Cercueil <paul.cercueil@analog.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* */
#include "ops.h"
#include "parser.h"
#include <errno.h>
#include <string.h>
void yyerror(yyscan_t scanner, const char *msg);
%}
%code requires {
#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void *yyscan_t;
#endif
#include "../iio-config.h"
#include "../debug.h"
#include <stdbool.h>
#include <sys/socket.h>
int yylex();
int yylex_init_extra(void *d, yyscan_t *scanner);
int yylex_destroy(yyscan_t yyscanner);
void * yyget_extra(yyscan_t scanner);
ssize_t yy_input(yyscan_t scanner, char *buf, size_t max_size);
#define ECHO do { \
struct parser_pdata *pdata = yyget_extra(yyscanner); \
write_all(pdata, yytext, yyleng); \
} while (0)
#define YY_INPUT(buf,result,max_size) do { \
ssize_t res = yy_input(yyscanner, buf, max_size); \
result = res <= 0 ? YY_NULL : (size_t) res; \
} while (0)
}
%define api.pure
%lex-param { yyscan_t scanner }
%parse-param { yyscan_t scanner }
%union {
char *word;
struct iio_device *dev;
struct iio_channel *chn;
long value;
}
%token SPACE
%token END
%token VERSION
%token EXIT
%token REQUEST_CLIENT_ID
%token REGISTER_CLIENT_ID
%token HELP
%token OPEN
%token CLOSE
%token PRINT
%token READ
%token READBUF
%token WRITEBUF
%token WRITE
%token SETTRIG
%token GETTRIG
%token TIMEOUT
%token DEBUG_ATTR
%token BUFFER_ATTR
%token IN_OUT
%token CYCLIC
%token SET
%token BUFFERS_COUNT
%token <word> WORD
%token <dev> DEVICE
%token <chn> CHANNEL
%token <value> VALUE;
%destructor { DEBUG("Freeing token \"%s\"\n", $$); free($$); } <word>
%start Line
%%
Line:
END {
YYACCEPT;
}
| EXIT END {
struct parser_pdata *pdata = yyget_extra(scanner);
pdata->stop = true;
YYACCEPT;
}
| HELP END {
struct parser_pdata *pdata = yyget_extra(scanner);
output(pdata, "Available commands:\n\n"
"\tHELP\n"
"\t\tPrint this help message\n"
"\tEXIT\n"
"\t\tClose the current session\n"
"\tREQUEST_CLIENT_ID\n"
"\t\tA new client requesting a unique client id\n"
"\tREGISTER_CLIENT_ID <client_id>\n"
"\t\tA subchannel of a client registering the fd with the client id\n"
"\tPRINT\n"
"\t\tDisplays a XML string corresponding to the current IIO context\n"
"\tVERSION\n"
"\t\tGet the version of libiio in use\n"
"\tTIMEOUT <timeout_ms>\n"
"\t\tSet the timeout (in ms) for I/O operations\n"
"\tOPEN <device> <samples_count> <mask> [CYCLIC]\n"
"\t\tOpen the specified device with the given mask of channels\n"
"\tCLOSE <device>\n"
"\t\tClose the specified device\n"
"\tREAD <device> DEBUG|BUFFER|[INPUT|OUTPUT <channel>] [<attribute>]\n"
"\t\tRead the value of an attribute\n"
"\tWRITE <device> DEBUG|BUFFER|[INPUT|OUTPUT <channel>] [<attribute>] <bytes_count>\n"
"\t\tSet the value of an attribute\n"
"\tREADBUF <device> <bytes_count>\n"
"\t\tRead raw data from the specified device\n"
"\tWRITEBUF <device> <bytes_count>\n"
"\t\tWrite raw data to the specified device\n"
"\tGETTRIG <device>\n"
"\t\tGet the name of the trigger used by the specified device\n"
"\tSETTRIG <device> [<trigger>]\n"
"\t\tSet the trigger to use for the specified device\n"
"\tSET <device> BUFFERS_COUNT <count>\n"
"\t\tSet the number of kernel buffers for the specified device\n");
YYACCEPT;
}
| REQUEST_CLIENT_ID END {
struct parser_pdata *pdata = yyget_extra(scanner);
// Don't care if it's unique or not
output(pdata, "0\n");
YYACCEPT;
}
| REGISTER_CLIENT_ID SPACE VALUE END {
struct parser_pdata *pdata = yyget_extra(scanner);
// Always success
output(pdata, "0\n");
YYACCEPT;
}
| VERSION END {
struct parser_pdata *pdata = yyget_extra(scanner);
char buf[128];
snprintf(buf, sizeof(buf), "%u.%u.%-7.7s\n", LIBIIO_VERSION_MAJOR,
LIBIIO_VERSION_MINOR, LIBIIO_VERSION_GIT);
output(pdata, buf);
YYACCEPT;
}
| PRINT END {
struct parser_pdata *pdata = yyget_extra(scanner);
const char *xml = iio_context_get_xml(pdata->ctx);
if (!pdata->verbose) {
char buf[128];
sprintf(buf, "%lu\n", (unsigned long) strlen(xml));
output(pdata, buf);
}
output(pdata, xml);
output(pdata, "\n");
YYACCEPT;
}
| TIMEOUT SPACE WORD END {
char *word = $3;
struct parser_pdata *pdata = yyget_extra(scanner);
unsigned int timeout = (unsigned int) atoi(word);
int ret = set_timeout(pdata, timeout);
free(word);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| OPEN SPACE DEVICE SPACE WORD SPACE WORD SPACE CYCLIC END {
char *nb = $5, *mask = $7;
struct parser_pdata *pdata = yyget_extra(scanner);
unsigned long samples_count = atol(nb);
int ret = open_dev(pdata, $3, samples_count, mask, true);
free(nb);
free(mask);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| OPEN SPACE DEVICE SPACE WORD SPACE WORD END {
char *nb = $5, *mask = $7;
struct parser_pdata *pdata = yyget_extra(scanner);
unsigned long samples_count = atol(nb);
int ret = open_dev(pdata, $3, samples_count, mask, false);
free(nb);
free(mask);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| CLOSE SPACE DEVICE END {
struct parser_pdata *pdata = yyget_extra(scanner);
int ret = close_dev(pdata, $3);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| READ SPACE DEVICE END {
struct parser_pdata *pdata = yyget_extra(scanner);
if (read_dev_attr(pdata, $3, NULL, IIO_ATTR_TYPE_DEVICE) < 0)
YYABORT;
else
YYACCEPT;
}
| READ SPACE DEVICE SPACE WORD END {
char *attr = $5;
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = read_dev_attr(pdata, $3, attr, IIO_ATTR_TYPE_DEVICE);
free(attr);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| READ SPACE DEVICE SPACE DEBUG_ATTR END {
struct parser_pdata *pdata = yyget_extra(scanner);
if (read_dev_attr(pdata, $3, NULL, IIO_ATTR_TYPE_DEBUG) < 0)
YYABORT;
else
YYACCEPT;
}
| READ SPACE DEVICE SPACE DEBUG_ATTR SPACE WORD END {
char *attr = $7;
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = read_dev_attr(pdata, $3, attr, IIO_ATTR_TYPE_DEBUG);
free(attr);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| READ SPACE DEVICE SPACE BUFFER_ATTR END {
struct parser_pdata *pdata = yyget_extra(scanner);
if (read_dev_attr(pdata, $3, NULL, IIO_ATTR_TYPE_BUFFER) < 0)
YYABORT;
else
YYACCEPT;
}
| READ SPACE DEVICE SPACE BUFFER_ATTR SPACE WORD END {
char *attr = $7;
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = read_dev_attr(pdata, $3, attr, IIO_ATTR_TYPE_BUFFER);
free(attr);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| READ SPACE DEVICE SPACE IN_OUT SPACE CHANNEL END {
struct parser_pdata *pdata = yyget_extra(scanner);
if (read_chn_attr(pdata, $7, NULL) < 0)
YYABORT;
else
YYACCEPT;
}
| READ SPACE DEVICE SPACE IN_OUT SPACE CHANNEL SPACE WORD END {
char *attr = $9;
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = read_chn_attr(pdata, $7, attr);
free(attr);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| READBUF SPACE DEVICE SPACE WORD END {
char *len = $5;
unsigned long nb = atol(len);
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = rw_dev(pdata, $3, nb, false);
free(len);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| WRITEBUF SPACE DEVICE SPACE WORD END {
char *len = $5;
unsigned long nb = atol(len);
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = rw_dev(pdata, $3, nb, true);
/* Discard additional data */
yyclearin;
free(len);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| WRITE SPACE DEVICE SPACE WORD END {
char *len = $5;
unsigned long nb = atol(len);
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = write_dev_attr(pdata, $3, NULL, nb, IIO_ATTR_TYPE_DEVICE);
free(len);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| WRITE SPACE DEVICE SPACE WORD SPACE WORD END {
char *attr = $5, *len = $7;
unsigned long nb = atol(len);
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = write_dev_attr(pdata, $3, attr, nb, IIO_ATTR_TYPE_DEVICE);
free(attr);
free(len);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| WRITE SPACE DEVICE SPACE DEBUG_ATTR SPACE WORD END {
char *len = $7;
unsigned long nb = atol(len);
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = write_dev_attr(pdata, $3, NULL, nb, IIO_ATTR_TYPE_DEBUG);
free(len);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| WRITE SPACE DEVICE SPACE DEBUG_ATTR SPACE WORD SPACE WORD END {
char *attr = $7, *len = $9;
unsigned long nb = atol(len);
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = write_dev_attr(pdata, $3, attr, nb, IIO_ATTR_TYPE_DEBUG);
free(attr);
free(len);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| WRITE SPACE DEVICE SPACE BUFFER_ATTR SPACE WORD END {
char *len = $7;
unsigned long nb = atol(len);
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = write_dev_attr(pdata, $3, NULL, nb, IIO_ATTR_TYPE_BUFFER);
free(len);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| WRITE SPACE DEVICE SPACE BUFFER_ATTR SPACE WORD SPACE WORD END {
char *attr = $7, *len = $9;
unsigned long nb = atol(len);
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = write_dev_attr(pdata, $3, attr, nb, IIO_ATTR_TYPE_BUFFER);
free(attr);
free(len);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| WRITE SPACE DEVICE SPACE IN_OUT SPACE CHANNEL SPACE WORD END {
char *len = $9;
unsigned long nb = atol(len);
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = write_chn_attr(pdata, $7, NULL, nb);
free(len);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| WRITE SPACE DEVICE SPACE IN_OUT SPACE CHANNEL SPACE WORD SPACE WORD END {
char *attr = $9, *len = $11;
unsigned long nb = atol(len);
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = write_chn_attr(pdata, $7, attr, nb);
free(attr);
free(len);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| SETTRIG SPACE DEVICE SPACE WORD END {
char *trig = $5;
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret = set_trigger(pdata, $3, trig);
free(trig);
if (ret < 0)
YYABORT;
else
YYACCEPT;
}
| SETTRIG SPACE DEVICE END {
struct parser_pdata *pdata = yyget_extra(scanner);
if (set_trigger(pdata, $3, NULL) < 0)
YYABORT;
else
YYACCEPT;
}
| GETTRIG SPACE DEVICE END {
struct parser_pdata *pdata = yyget_extra(scanner);
if (get_trigger(pdata, $3) < 0)
YYABORT;
else
YYACCEPT;
}
| SET SPACE DEVICE SPACE BUFFERS_COUNT SPACE VALUE END {
struct parser_pdata *pdata = yyget_extra(scanner);
if (set_buffers_count(pdata, $3, $7) < 0)
YYABORT;
else
YYACCEPT;
}
| error END {
yyclearin;
yyerrok;
YYACCEPT;
}
;
%%
void yyerror(yyscan_t scanner, const char *msg)
{
struct parser_pdata *pdata = yyget_extra(scanner);
if (pdata->verbose) {
output(pdata, "ERROR: ");
output(pdata, msg);
output(pdata, "\n");
} else {
char buf[128];
sprintf(buf, "%i\n", -EINVAL);
output(pdata, buf);
}
}
ssize_t yy_input(yyscan_t scanner, char *buf, size_t max_size)
{
struct parser_pdata *pdata = yyget_extra(scanner);
ssize_t ret;
ret = read_line(pdata, buf, max_size);
if (ret < 0)
return ret;
if (ret == 0)
return -EIO;
if ((size_t) ret == max_size)
buf[max_size - 1] = '\0';
return ret;
}