Add support for "ifdef <attribute>" blocks. It goes like this:

ifdef <attr> / ifndef <attr>
elifdef <attr>
elifndef <attr>
else
endif

No indentation is possible for now, it will come later.
This commit is contained in:
cube 2007-11-09 23:41:08 +00:00
parent 26515bc536
commit 656cdcc8fb
3 changed files with 173 additions and 6 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: config.5,v 1.11 2007/09/10 10:54:20 cube Exp $
.\" $NetBSD: config.5,v 1.12 2007/11/09 23:41:08 cube Exp $
.\"
.\" Copyright (c) 2006, 2007 The NetBSD Foundation.
.\" All rights reserved.
@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd January 9, 2007
.Dd November 9, 2007
.Dt CONFIG 5
.Os
.Sh NAME
@ -268,6 +268,19 @@ The
.Ar path
argument is either absolute or relative to the current defined prefix, which
defaults to the top of ther kernel source tree.
.It Ic ifdef Ar attribute
.It Ic ifndef Ar attribute
.It Ic elifdef Ar attribute
.It Ic elifndef Ar attribute
.It Ic else
.It Ic endif
Conditionally interprets portions of the current file.
Those statements depend on whether or not the given
.Ar attribute
has been previously defined, through
.Ic define
or any other statement that implicitely defines attributes such as
.Ic device .
.El
.Ss PREAMBLE
In addition to

View File

@ -1,4 +1,4 @@
/* $NetBSD: defs.h,v 1.20 2007/01/13 23:47:36 christos Exp $ */
/* $NetBSD: defs.h,v 1.21 2007/11/09 23:41:08 cube Exp $ */
/*
* Copyright (c) 1992, 1993
@ -98,7 +98,7 @@ extern const char *progname;
* The next two lines define the current version of the config(1) binary,
* and the minimum version of the configuration files it supports.
*/
#define CONFIG_VERSION 20070109
#define CONFIG_VERSION 20071109
#define CONFIG_MINVERSION 0
/*

View File

@ -1,5 +1,5 @@
%{
/* $NetBSD: scan.l,v 1.8 2007/11/09 05:06:08 cube Exp $ */
/* $NetBSD: scan.l,v 1.9 2007/11/09 23:41:08 cube Exp $ */
/*
* Copyright (c) 1992, 1993
@ -59,6 +59,34 @@ int yyline;
const char *yyfile;
const char *lastfile;
char curinclpath[PATH_MAX];
int ifdefstate = -1;
int st;
#define IDS_PARENT_DISABLED \
((ifdefstate > 6) && ((((ifdefstate/6)-1) & 1) == 1))
#define IDS_MAX_DEPTH 362797056 /* 6^11 */
/* States for ifdefstate:
0 -> matched ifdef
1 -> unmatched ifdef
2 -> matched elifdef
3 -> unmatched elifdef
4 -> matched else
5 -> unmatched else
Upon "ifdef", add one and multiply by 6.
Upon "endif", divide by 6, remove 1.
ifdef -> MATCH => continue
MISMATCH => set to 1
elifdef -> if (!1) -> MISMATCH
MATCH => set to 2
MISMATCH => if (2 || 3) set to 3, else set to 1
else -> if (1) -> MATCH
MATCH => set to 4
MISMATCH => set to 5
in each case, if parent & 1 == 1, MISMATCH
*/
/*
* Data for returning to previous files from include files.
@ -70,10 +98,12 @@ struct incl {
int in_lineno; /* previous line number */
int in_ateof; /* token to insert at EOF */
int in_interesting; /* previous value for "interesting" */
int in_ifdefstate; /* conditional level */
};
static struct incl *incl;
static int endinclude(void);
static int getincludepath(void);
static int getcurifdef(void);
#define yywrap() 1
@ -85,6 +115,8 @@ WORD [A-Za-z_][-A-Za-z_0-9]*
FILENAME ({PATH}|\"{QCHARS}\")
RESTOFLINE [ \t]*(#[^\n]*)?\n
%x IGNORED
%%
/* Local variables for yylex() */
int tok;
@ -135,6 +167,107 @@ with return WITH;
\+= return PLUSEQ;
:= return COLONEQ;
<*>ifdef[ \t]+{WORD}{RESTOFLINE} {
ifdefstate = (ifdefstate + 1) * 6;
if (ifdefstate >= IDS_MAX_DEPTH) {
yyerror("too many levels of conditional");
}
if (!IDS_PARENT_DISABLED && getcurifdef()) {
BEGIN(INITIAL);
} else {
ifdefstate++;
BEGIN(IGNORED);
}
yyline++;
}
<*>ifndef[ \t]+{WORD}{RESTOFLINE} {
ifdefstate = (ifdefstate + 1) * 6;
if (ifdefstate >= IDS_MAX_DEPTH) {
yyerror("too many levels of conditional");
}
if (!IDS_PARENT_DISABLED && !getcurifdef()) {
BEGIN(INITIAL);
} else {
ifdefstate++;
BEGIN(IGNORED);
}
yyline++;
}
<*>elifdef[ \t]+{WORD}{RESTOFLINE} {
st = ifdefstate % 6;
if (ifdefstate < 0 || st > 3) {
yyerror("mismatched elifdef");
}
if (IDS_PARENT_DISABLED ||
st != 1 || !getcurifdef()) {
if (st == 2 || st == 3) {
ifdefstate += 3 - st;
} else {
ifdefstate += 1 - st;
}
BEGIN(IGNORED);
} else {
ifdefstate++;
BEGIN(INITIAL);
}
yyline++;
}
<*>elifndef[ \t]+{WORD}{RESTOFLINE} {
st = ifdefstate % 6;
if (ifdefstate < 0 || st > 3) {
yyerror("mismatched elifndef");
}
if (IDS_PARENT_DISABLED ||
st != 1 || getcurifdef()) {
if (st == 2 || st == 3) {
ifdefstate += 3 - st;
} else {
ifdefstate += 1 - st;
}
BEGIN(IGNORED);
} else {
ifdefstate++;
BEGIN(INITIAL);
}
yyline++;
}
<*>else{RESTOFLINE} {
st = ifdefstate % 6;
if (ifdefstate < 0 || st > 3) {
yyerror("mismatched else");
}
if (!IDS_PARENT_DISABLED && (st == 1)) {
ifdefstate += 3;
BEGIN(INITIAL);
} else {
ifdefstate += 5 - st;
BEGIN(IGNORED);
}
yyline++;
}
<*>endif{RESTOFLINE} {
if (ifdefstate < 0) {
yyerror("mismatched endif");
}
if (!IDS_PARENT_DISABLED) {
BEGIN(INITIAL);
}
ifdefstate = (ifdefstate/6) - 1;
yyline++;
}
<IGNORED>\n {
yyline++;
}
<IGNORED>. /* ignore */
include[ \t]+{FILENAME}{RESTOFLINE} {
yyline++;
if (getincludepath()) {
@ -224,7 +357,10 @@ package[ \t]+{FILENAME}{RESTOFLINE} {
#.* { /* ignored (comment) */; }
[ \t]+ { /* ignored (white space) */; }
. { return yytext[0]; }
<<EOF>> {
<*><<EOF>> {
if (ifdefstate > (incl == NULL ? -1 : incl->in_ifdefstate)) {
yyerror("reached EOF while looking for endif");
}
if (incl == NULL)
return YY_NULL;
tok = endinclude();
@ -380,6 +516,7 @@ include(const char *fname, int ateof, int conditional, int direct)
in->in_lineno = yyline;
in->in_ateof = ateof;
in->in_interesting = interesting;
in->in_ifdefstate = ifdefstate;
interesting = direct & interesting;
if (interesting)
logconfig_include(fp, fname);
@ -465,3 +602,20 @@ currentline(void)
return (yyline - (yychar == '\n'));
}
static int
getcurifdef(void)
{
char *p = yytext, *q;
while (*p && isascii((unsigned int)*p) && !isspace((unsigned int)*p))
p++;
while (*p && isascii((unsigned int)*p) && isspace((unsigned int)*p))
p++;
q = p;
while (*q && isascii((unsigned int)*q) && !isspace((unsigned int)*q))
q++;
*q = '\0';
return ht_lookup(attrtab, intern(p)) != NULL;
}