/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1997-1999 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "xlator.h"
#include "util.h"
#include "bucket.h"
#include "errlog.h"
/* Types: */
#define FALSE 0
typedef enum {
} RELATION;
/* Statics: */
/* The parser is a dfa, driven by the following: */
static const char *Filename;
static int Line;
static int Errors;
/* The grammar is: */
static int arch(void);
static int comment(void);
static int arch_name(void);
static int set_list(void);
static int set(void);
/* The supporting code is: */
static int accept_token(char *);
static void skip_to(char *);
/* And the tokenizer is: */
static char *tokenize(char *);
static char *currtok(void);
static char *nexttok(void);
static char *skipb(char *);
static char *skipover(char *);
static int set_parents(void);
static void init_tables(void);
static void add_valid_arch(char *);
static void add_valid_version(char *vers_name);
(c) == '-' || (c) == ';' || (c) == ':' || (c) == ',' || \
(c) == '[' || (c) == ']')
/*
* parse_versions -- parse the file whose name is passed, return
* the number of (fatal) errors encountered. Currently only
* knows about reading set files and writing vers files.
*/
int
{
/* Prime the set-file parser dfa: */
fileName);
return (1);
}
Line = 0;
/* Run the dfa. */
while (arch())
continue;
/* print_all_buckets(); */
return (Errors);
}
/*
* The parser. This implements the grammar:
* setfile::= (arch())+ <EOF>
* | <EOF>
* arch::= <ARCHITECTURE> "{" (set_list())* "}"
* set_list::= (set())+ ";"
* set::= <IDENTIFIER> ["[" "WEAK" "]"] ":" "{" (ancestors) "}" ";"
* ancestors::= <IDENTIFIER> | <ancestors> "," <IDENTIFIER>
* where <ARCHITECTURE> and <IDENTIFIER> are tokens.
*/
static int
arch(void)
{
int olderrors;
if (comment()) {
return (TRUE);
}
return (FALSE);
}
return (FALSE);
}
return (FALSE);
}
}
return (TRUE);
}
static int
comment(void)
{
return (FALSE);
} else {
/* Swallow token. */
return (TRUE);
}
}
static int
arch_name(void)
{
return (FALSE);
} else if (in_specials(*token)) {
/* It's not an architecture */
/* Report a syntax error: TBD */
"while looking for an architecture name",
*token);
Errors++;
return (FALSE);
/* It's an architecture ... */
(void) nexttok();
/* ... but the the wrong one. */
return (TRUE);
} else {
/* Found the right architecture. */
(void) nexttok();
return (TRUE);
}
}
static int
set_list(void)
{
int olderrors;
return (FALSE);
}
while (set()) {
continue;
}
return (FALSE);
}
return (TRUE);
}
static int
set(void)
{
int has_parent = 0;
if (in_specials(*token)) {
"Version name expected", token);
Errors++;
return (FALSE);
}
*Previous = '\0';
if (Selected) {
"from the set file");
Errors++;
return (FALSE);
}
}
switch (*token) {
case ':':
(void) accept_token(":");
if (set_parents() == FALSE) {
return (FALSE);
}
return (FALSE);
}
break;
case ';':
(void) accept_token(";");
break;
case '[':
(void) accept_token("[");
return (FALSE);
}
return (FALSE);
}
(void) accept_token(":");
has_parent = 1;
(void) accept_token(";");
} else {
"Unexpected token \"%s\" found. ':'"
"or ';' expected.", token);
Errors++;
return (FALSE);
}
if (Selected)
if (has_parent) {
if (set_parents() == FALSE) {
return (FALSE);
}
return (FALSE);
}
}
break;
default:
/* CSTYLED */
"Unexpected token \"%s\" found. ';' expected.",
token);
Errors++;
return (FALSE);
}
(void) accept_token("}");
return (FALSE);
}
return (TRUE);
}
static int
set_parents(void)
{
int uncle;
token);
Errors++;
return (FALSE);
}
if (in_specials(*token)) {
"found. Version token expected", *token);
Errors++;
return (FALSE);
}
uncle = 0;
if (Selected) {
if (uncle)
else
}
if (*token == ',') {
/* following identifiers are all uncles */
uncle = 1;
continue;
}
if (*token == '}') {
return (FALSE);
}
return (TRUE);
}
"set_parents(): Unexpected token \"%s\" "
"found. ',' or '}' were expected", token);
Errors++;
return (FALSE);
}
return (TRUE);
}
/*
* parser support routines
*/
/*
* accept_token -- get a specified token or complain loudly.
*/
static int
{
/* We're at EOF */
return (TRUE);
}
(void) nexttok();
return (TRUE);
} else {
"accept_token, found %s while looking for %s",
++Errors;
return (FALSE);
}
}
static void
{
}
}
/*
* tokenizer -- below the grammar lives this, like a troll
* under a bridge.
*/
/*
* skipb -- skip over blanks (whitespace, actually), stopping
* on first non-blank.
*/
static char *
skipb(char *p)
{
while (*p && isspace(*p))
++p;
return (p);
}
/*
* skipover -- skip over non-separators (alnum, . and _, actually),
* stopping on first separator.
*/
static char *
skipover(char *p)
{
++p;
return (p);
}
/*
*/
static char *
currtok(void)
{
(void) nexttok();
}
return (CurrTok);
}
static char *
nexttok(void)
{
char *p;
/* We're at an end of line. */
do {
/* Which is also end of file. */
return (NULL);
}
++Line;
}
CurrTok = p;
return (p);
}
/*
* tokenize -- a version of the standard strtok with specific behavior.
*/
static char *
{
static char *p = NULL;
static char saved = 0;
char *q;
/* It's the very first time */
return (NULL);
/* Initialize with a new line */
} else {
/* Restore previous line. */
*p = saved;
q = skipb(p);
}
/* q is at the beginning of a token or at EOL, p is irrelevant. */
if (*q == '\0') {
/* It's at EOL. */
p = q;
} else if (in_specials(*q)) {
/* We have a special-character token. */
p = q + 1;
} else if (*q == '#') {
/* The whole rest of the line is a comment token. */
return (NULL);
} else {
/* We have a word token. */
p = skipover(q);
}
saved = *p;
*p = '\0';
if (p == q) {
/* End of line */
return (NULL);
} else {
return (q);
}
}
/*
* valid_version -- see if a version string was mentioned in the set file.
*/
int
{
init_tables();
}
}
/*
* valid_arch -- see if the arch was mentioned in the set file.
*/
int
{
init_tables();
}
}
/*
* add_valid_version and _arch -- add a name to the table.
*/
static void
{
init_tables();
}
}
static void
{
init_tables();
}
}
/*
* init_tables -- creat them when first used.
*/
static void
init_tables(void)
{
}