blob: f4e940ce4e69323b40deb1866211215e645f6736 [file] [log] [blame]
%{
/* ----------------------------------------------------------------------- *
*
* master_tok.l - master map tokenizer.
*
* Copyright 2006 Ian Kent <raven@themaw.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
* USA; either version 2 of the License, or (at your option) any later
* version.
*
* This program 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 General Public License for more details.
*
* ----------------------------------------------------------------------- */
#ifdef ECHO
# undef ECHO
#endif /* ECHO */
static void master_echo(void); /* forward definition */
#define ECHO master_echo()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "master_parse.tab.h"
/*
* There are some things that need to be defined only if useing GNU flex.
* These must not be defined if using standard lex
*/
#ifdef FLEX_SCANNER
int master_lineno;
#endif
int master_lex(void);
int master_wrap(void);
/* no need for yywrap() */
#define YY_SKIP_YYWRAP
#ifndef YY_STACK_USED
#define YY_STACK_USED 0
#endif
#ifndef YY_ALWAYS_INTERACTIVE
#define YY_ALWAYS_INTERACTIVE 0
#endif
#ifndef YY_NEVER_INTERACTIVE
#define YY_NEVER_INTERACTIVE 0
#endif
#ifndef YY_MAIN
#define YY_MAIN 0
#endif
void master_set_scan_buffer(const char *);
const char *line = NULL;
#ifdef FLEX_SCANNER
const char *line_pos = NULL;
const char *line_lim = NULL;
int my_yyinput(char *, int);
#undef YY_INPUT
#define YY_INPUT(b, r, ms) (r = my_yyinput(b, ms))
#else
#undef input
#undef unput
#define input() (*(char *) line++)
#define unput(c) (*(char *) --line = c)
#endif
#define BUFF_LEN 1024
char buff[BUFF_LEN];
char *bptr;
char *optr = buff;
unsigned int tlen;
%}
%option nounput
%x PATHSTR MAPSTR DNSTR OPTSTR OCTAL
WS [[:blank:]]+
OPTWS [[:blank:]]*
NL \r?\n
CONT \\\n{OPTWS}
OPTIONSTR ([\-]?([[:alpha:]_]([[:alnum:]_\-])*(=(\"?([[:alnum:]_\-\:\.])+\"?))?)+)
MACROSTR (-D{OPTWS}([[:alpha:]_]([[:alnum:]_\-\.])*)=([[:alnum:]_\-\.])+)
SLASHIFYSTR (--(no-)?slashify-colons)
NUMBER [0-9]+
OCTALNUMBER [0-7]+
DNSERVSTR1 ([[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?:)
DNSERVSTR2 (\[([[:xdigit:]]:.)+\](:[0-9]+)?:)
DNSERVSTR3 (\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/)
DNSERVSTR4 (\/\/\[([[:xdigit:]]:.)+\](:[0-9]+)?\/)
DNSERVSTR5 (([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:)
DNSERVSTR6 (\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/)
DNSERVERSTR ({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4}|{DNSERVSTR5}|{DNSERVSTR6})
AT_CN ([cC][[nN])
AT_NMN ([nN][iI][sS][Mm][aA][pP][Nn][aA][mM][eE])
AT_AMN ([aA][uU][tT][oO][mM][oO][uU][nN][tT][Mm][aA][pP][Nn][aA][mM][eE])
AT_OU ([oO][[uU])
AT_DC ([dD][[cC])
AT_O ([oO])
AT_C ([cC])
AT_L ([lL])
DNATTRSTR ({AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C}|{AT_L})
DNNAMESTR1 ([[:alnum:]_.\- ]+)
DNNAMESTR2 ([[:alnum:]_.\-]+)
INTMAP (-hosts|-null)
MULTI ((multi)(,(sun|hesiod))?(:{OPTWS}|{WS}))
MULTISEP ([\-]{2}[[:blank:]]+)
MTYPE ((file|program|exec|sss|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod|amd))?(:{OPTWS}|{WS}))
OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS})
OPTNTOUT (-n{OPTWS}|-n{OPTWS}={OPTWS}|--negative-timeout{OPTWS}|--negative-timeout{OPTWS}={OPTWS})
MODE (--mode{OPTWS}|--mode{OPTWS}={OPTWS})
%%
<INITIAL>{
{NL} |
\x00 {
if (optr != buff) {
*optr = '\0';
strcpy(master_lval.strtype, buff);
return NILL;
}
}
#.* { return COMMENT; }
"/" {
if (optr != buff) {
*optr = '\0';
strcpy(master_lval.strtype, buff);
return NILL;
}
BEGIN(PATHSTR);
bptr = buff;
yyless(0);
}
. { *optr++ = *master_text; }
}
<PATHSTR>{
\x00 {
BEGIN(INITIAL);
*bptr++ = *master_text;
strcpy(master_lval.strtype, buff);
return NILL;
}
\\. { *bptr++ = *(master_text + 1); }
\" {
BEGIN(INITIAL);
*bptr++ = *master_text;
*bptr = '\0';
strcpy(master_lval.strtype, buff);
return QUOTE;
}
{WS} {
BEGIN(MAPSTR);
*bptr = '\0';
strcpy(master_lval.strtype, buff);
bptr = buff;
memset(buff, 0, BUFF_LEN);
return(PATH);
}
<<EOF>> {
BEGIN(INITIAL);
*bptr = '\0';
strcpy(master_lval.strtype, buff);
return(PATH);
}
{NL} {
BEGIN(INITIAL);
*bptr = '\0';
strcpy(master_lval.strtype, buff);
return PATH;
}
. { *bptr++ = *master_text; }
}
<MAPSTR>{
{OPTWS}\\\n{OPTWS} {}
{MULTI} {
tlen = master_leng - 1;
if (bptr != buff && isblank(master_text[tlen])) {
/*
* We can't handle unescaped white space in map names
* so just eat the white space. We always have the
* "multi" at the beginning of the string so the while
* will not fall off the end.
*/
while (isblank(master_text[tlen - 1]))
tlen--;
strncat(buff, master_text, tlen);
bptr += tlen;
yyless(tlen);
} else {
strcpy(master_lval.strtype, master_text);
return(MULTITYPE);
}
}
{MTYPE} |
{MTYPE}/{DNSERVERSTR}{DNATTRSTR}= |
{MTYPE}/{DNATTRSTR}= {
tlen = master_leng - 1;
if (bptr != buff && isblank(master_text[tlen])) {
/*
* We can't handle unescaped white space in map names
* so just eat the white space. We always have the
* maptype keyword at the beginning of the string so
* the while will not fall off the end.
*/
while (isblank(master_text[tlen - 1]))
tlen--;
strncat(buff, master_text, tlen);
bptr += tlen;
yyless(tlen);
} else {
strcpy(master_lval.strtype, master_text);
return(MAPTYPE);
}
}
{MULTISEP} { return(DDASH); }
":" { return(COLON); }
"-hosts" {
BEGIN(OPTSTR);
strcpy(master_lval.strtype, master_text);
return MAPHOSTS;
}
"-null" {
BEGIN(OPTSTR);
strcpy(master_lval.strtype, master_text);
return MAPNULL;
}
"-xfn" {
/*
* The X/Open Federated Naming service isn't supported
* and the parser will call YYABORT() when it sees the
* MAPXFN token so we must set the start state to the
* INITIAL state here for the next yylex() call.
*/
BEGIN(INITIAL);
strcpy(master_lval.strtype, master_text);
return MAPXFN;
}
"//" {
BEGIN(DNSTR);
yyless(0);
}
{DNSERVERSTR}{DNATTRSTR}= {
BEGIN(DNSTR);
yyless(0);
}
{DNATTRSTR}= {
BEGIN(DNSTR);
yyless(0);
}
{OPTWS}/{NL} {
BEGIN(INITIAL);
*bptr = '\0';
strcpy(master_lval.strtype, buff);
bptr = buff;
return(MAPNAME);
}
\\. { *bptr++ = *(master_text + 1); }
{WS} {
BEGIN(OPTSTR);
*bptr = '\0';
strcpy(master_lval.strtype, buff);
bptr = buff;
return(MAPNAME);
}
{NL} |
\x00 {
BEGIN(INITIAL);
*bptr = '\0';
strcpy(master_lval.strtype, buff);
return(MAPNAME);
}
<<EOF>> {
BEGIN(INITIAL);
*bptr = '\0';
strcpy(master_lval.strtype, buff);
return(MAPNAME);
}
. { *bptr++ = *master_text; }
}
<DNSTR>{
{OPTWS}\\\n{OPTWS} {}
{DNSERVERSTR} {
strcpy(master_lval.strtype, master_text);
return DNSERVER;
}
{DNATTRSTR}/"=" {
strcpy(master_lval.strtype, master_text);
return DNATTR;
}
"=" {
return EQUAL;
}
{DNNAMESTR1}/","{DNATTRSTR}"=" {
strcpy(master_lval.strtype, master_text);
return DNNAME;
}
{DNNAMESTR2} {
strcpy(master_lval.strtype, master_text);
return DNNAME;
}
{OPTWS}","{OPTWS} {
return COMMA;
}
{WS}"=" |
"="{WS} {
BEGIN(INITIAL);
strcpy(master_lval.strtype, master_text);
return SPACE;
}
{WS} { BEGIN(OPTSTR); }
{NL} |
\x00 { BEGIN(INITIAL); }
<<EOF>> { BEGIN(INITIAL); }
}
<OPTSTR>{
{OPTWS}\\\n{OPTWS} {}
{MULTISEP} {
BEGIN(MAPSTR);
return(DDASH);
}
{OPTTOUT}/{NUMBER} { return(OPT_TIMEOUT); }
{OPTNTOUT}/{NUMBER} { return(OPT_NTIMEOUT); }
{NUMBER} {
master_lval.longtype = atol(master_text);
return(NUMBER);
}
-?symlink { return(OPT_SYMLINK); }
-?nobind { return(OPT_NOBIND); }
-?nobrowse { return(OPT_NOGHOST); }
-?slave { return(OPT_SLAVE); }
-?private { return(OPT_PRIVATE); }
-g|--ghost|-?browse { return(OPT_GHOST); }
-v|--verbose { return(OPT_VERBOSE); }
-d|--debug { return(OPT_DEBUG); }
-w|--use-weight-only { return(OPT_USE_WEIGHT); }
-r|--random-multimount-selection { return(OPT_RANDOM); }
{MODE}/{OCTALNUMBER} {
BEGIN(OCTAL);
return(OPT_MODE);
}
{OPTWS}","{OPTWS} { return(COMMA); }
{OPTWS} {}
{SLASHIFYSTR} {
strcpy(master_lval.strtype, master_text);
return(OPTION);
}
{MACROSTR} {
strcpy(master_lval.strtype, master_text);
return(OPTION);
}
{OPTIONSTR} {
strcpy(master_lval.strtype, master_text);
return(OPTION);
}
"=" {
strcpy(master_lval.strtype, master_text);
return(EQUAL);
}
{WS} {}
{NL} |
\x00 { BEGIN(INITIAL); }
<<EOF>> { BEGIN(INITIAL); }
}
<OCTAL>{
{OCTALNUMBER} {
master_lval.longtype = strtoul(master_text, NULL, 8);
return(OCTALNUMBER);
}
. { BEGIN(OPTSTR); yyless(0); }
}
%%
#include "automount.h"
int master_wrap(void)
{
return 1;
}
static void master_echo(void)
{
logmsg("%s", master_text);
return;
}
#ifdef FLEX_SCANNER
void master_set_scan_buffer(const char *buffer)
{
memset(buff, 0, sizeof(buff));
optr = buff;
YY_FLUSH_BUFFER;
line = buffer;
line_pos = &line[0];
/*
* Ensure buffer is 1 greater than string and is zeroed before
* the parse so we can fit the extra NULL which allows us to
* explicitly match an end of line within the buffer (ie. the
* need for 2 NULLS when parsing in memeory buffers).
*/
line_lim = line + strlen(buffer) + 1;
}
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
int my_yyinput(char *buffer, int max_size)
{
int n = min(max_size, line_lim - line_pos);
if (n > 0) {
memcpy(buffer, line_pos, n);
line_pos += n;
}
return n;
}
#else
void master_set_scan_buffer(const char *buffer)
{
line = buffer;
}
#endif