/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "lint.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include "libc.h"
#include "gettext.h"
#include "plural_parser.h"
/*
* 31 28 24 20 16 12 8 4 0
* +-----+-----+-----+-----+-----+-----+-----+-----+
* |opnum| priority | operator |
* +-----+-----+-----+-----+-----+-----+-----+-----+
*/
static const unsigned int operator[] = {
0x00000000, /* NULL */
0x00000001, /* INIT */
0x00100002, /* EXP */
0x00200003, /* NUM */
0x00300004, /* VAR */
0x30400005, /* CONDC */
0x30500006, /* CONDQ */
0x20600007, /* OR */
0x20700008, /* AND */
0x20800009, /* EQ */
0x2080000a, /* NEQ */
0x2090000b, /* GT */
0x2090000c, /* LT */
0x2090000d, /* GE */
0x2090000e, /* LE */
0x20a0000f, /* ADD */
0x20a00010, /* SUB */
0x20b00011, /* MUL */
0x20b00012, /* DIV */
0x20b00013, /* MOD */
0x10c00014, /* NOT */
0x00d00015, /* LPAR */
0x00e00016, /* RPAR */
0x00000017 /* ERR */
};
#define STACKFREE \
{ \
}
#ifdef PARSE_DEBUG
static const char *type_name[] = {
"T_NULL",
"T_INIT", "T_EXP", "T_NUM", "T_VAR", "T_CONDC", "T_CONDQ",
"T_LOR", "T_LAND", "T_EQ", "T_NEQ", "T_GT", "T_LT", "T_GE", "T_LE",
"T_ADD", "T_SUB", "T_MUL", "T_DIV", "T_MOD", "T_LNOT", "T_LPAR",
"T_RPAR", "T_ERR"
};
#endif
static struct expr *
{
#ifdef PARSE_DEBUG
printf("--- stack_push ---\n");
printf("------------------\n");
#endif
/* overflow */
return (NULL);
}
return (exp);
}
static struct expr *
{
/* no item */
if (exp_a)
if (exp_b)
return (NULL);
}
#ifdef PARSE_DEBUG
printf("--- stack_pop ---\n");
printf(" type: %s\n",
printf(" flag: %s\n",
printf("-----------------\n");
#endif
}
static void
{
#ifdef PARSE_DEBUG
printf("--- freeexpr ---\n");
printf("----------------\n");
#endif
case TRINARY:
if (e->nodes[2])
/* FALLTHROUGH */
case BINARY:
if (e->nodes[1])
/* FALLTHROUGH */
case UNARY:
if (e->nodes[0])
/* FALLTHROUGH */
default:
break;
}
free(e);
}
static struct expr *
{
unsigned int type;
#ifdef PARSE_DEBUG
printf("---setop1---\n");
printf("-----------\n");
#endif
if (!newitem) {
return (NULL);
}
return (newitem);
}
static struct expr *
{
#ifdef PARSE_DEBUG
unsigned int type;
printf("---setop_reduce---\n");
printf(" n: %d\n", n);
switch (n) {
case TRINARY:
printf(" exp3 type: %s\n",
case BINARY:
printf(" exp2 type: %s\n",
case UNARY:
printf(" exp1 type: %s\n",
case NARY:
break;
}
printf("-----------\n");
#endif
if (!newitem) {
if (exp1)
if (exp2)
if (exp3)
return (NULL);
}
switch (n) {
case TRINARY:
/* FALLTHROUGH */
case BINARY:
/* FALLTHROUGH */
case UNARY:
/* FALLTHROUGH */
case NARY:
break;
}
return (newitem);
}
static int
{
unsigned int tmp_flag;
unsigned int oop;
#ifdef PARSE_DEBUG
printf("---reduce---\n");
printf(" n: %d\n", n);
printf("-----------\n");
#endif
switch (n) {
case UNARY:
/* unary operator */
if (!exp_op)
return (1);
if (!*nexp)
return (-1);
return (0);
case BINARY:
/* binary operator */
if (!exp_op)
return (1);
if (!exp1)
return (1);
if (!*nexp)
return (-1);
return (0);
case TRINARY:
/* trinary operator: conditional */
if (!exp_op)
return (1);
if (!exp2)
return (1);
if (!exp_op)
return (1);
/* parse failed */
return (1);
}
if (!exp1)
return (1);
if (!*nexp)
return (-1);
return (0);
}
/* NOTREACHED */
return (0); /* keep gcc happy */
}
static unsigned int
{
unsigned int n;
unsigned int ret;
sp++;
if (!*sp) {
return (T_NULL);
}
n = *sp - '0';
sp++;
n *= 10;
n += *sp - '0';
sp++;
}
*num = n;
} else if (*sp == 'n') {
sp++;
} else if (*sp == '(') {
sp++;
} else if (*sp == ')') {
sp++;
} else if (*sp == '!') {
sp++;
if (*sp == '=') {
sp++;
} else {
}
} else if (*sp == '*') {
sp++;
} else if (*sp == '/') {
sp++;
} else if (*sp == '%') {
sp++;
} else if (*sp == '+') {
sp++;
} else if (*sp == '-') {
sp++;
} else if (*sp == '<') {
sp++;
if (*sp == '=') {
sp++;
} else {
}
} else if (*sp == '>') {
sp++;
if (*sp == '=') {
sp++;
} else {
}
} else if (*sp == '=') {
sp++;
if (*sp == '=') {
sp++;
} else {
}
} else if (*sp == '&') {
sp++;
if (*sp == '&') {
sp++;
} else {
}
} else if (*sp == '|') {
sp++;
if (*sp == '|') {
sp++;
} else {
}
} else if (*sp == '?') {
sp++;
} else if (*sp == ':') {
sp++;
} else {
}
}
/*
* plural_expr
*
* INPUT
* str: string to parse
*
* OUTPUT
* e: parsed expression
*
* RETURN
* -1: Error happend (malloc failed)
* 1: Parse failed (invalid expression)
* 0: Parse succeeded
*/
int
{
sizeof (struct expr *) * MAX_STACK_SIZE);
/* malloc failed */
return (-1);
}
par = 0;
#ifdef PARSE_DEBUG
printf("***********\n");
#endif
/* parse failed */
return (1);
}
/* binary operation */
/* parse failed */
#ifdef PARSE_DEBUG
printf("ERR: T_EXP is not followed by %s\n",
#endif
return (1);
}
if (!exp)
return (-1);
if (!ret)
return (1);
continue; /* while-loop */
}
/* conditional operation: '?' */
/* parse failed */
#ifdef PARSE_DEBUG
printf("ERR: T_EXP is not followed by %s\n",
#endif
return (1);
}
if (!exp)
return (-1);
if (!ret)
return (1);
continue; /* while-loop */
}
/* conditional operation: ':' */
/* parse failed */
#ifdef PARSE_DEBUG
printf("ERR: T_EXP is not followed by %s\n",
#endif
return (1);
}
if (!exp)
return (-1);
if (!ret)
return (1);
continue; /* while-loop */
}
/* left parenthesis */
/* parse failed */
#ifdef PARSE_DEBUG
printf("ERR: T_EXP is followed by %s\n",
#endif
return (1);
}
if (!exp)
return (-1);
if (!ret)
return (1);
par++;
continue; /* while-loop */
}
/* right parenthesis */
/* parse failed */
#ifdef PARSE_DEBUG
printf("ERR: T_EXP is not followed by %s\n",
#endif
return (1);
}
par--;
if (par < 0) {
/* parse failed */
#ifdef PARSE_DEBUG
printf("ERR: too much T_RPAR\n");
#endif
return (1);
}
if (!exp)
return (1);
#ifdef PARSE_DEBUG
printf("======================== RPAR for loop in\n");
#endif
for (; ; ) {
#ifdef PARSE_DEBUG
printf("=========== exp->flag: %s\n",
#endif
if (!exp_op)
return (1);
break; /* break from for-loop */
}
if (result)
return (result);
continue; /* for-loop */
}
/* parse failed */
return (1);
} /* for-loop */
#ifdef PARSE_DEBUG
printf("========================= RPAR for loop out\n");
#endif
/*
* Needs to check if exp can be reduced or not
*/
goto exp_check;
}
/* parse failed */
#ifdef PARSE_DEBUG
printf("ERR: T_EXP is followed by %s\n",
#endif
return (1);
}
if (!exp)
return (-1);
if (!ret)
return (1);
continue; /* while-loop */
}
if (!exp)
return (-1);
/*
* just push this
*/
if (!ret)
return (1);
continue; /* while-loop */
}
/*
* parse failed
* T_EXP
*/
return (1);
}
} else {
nprio = 0;
}
#ifdef PARSE_DEBUG
#endif
for (; ; ) {
#ifdef PARSE_DEBUG
printf("========= flag: %s\n",
#endif
if (!ret)
return (1);
break; /* exit from for-loop */
}
/* LNOT is the strongest */
if (result)
return (result);
continue; /* for-loop */
}
/*
* binary operation
* T_MUL, T_ADD, T_CMP,
* T_EQ, T_LAND, T_LOR
*/
/* reduce */
if (result)
return (result);
continue; /* for-loop */
}
/* shift */
if (!ret)
return (1);
break; /* exit from for loop */
}
/*
* CONDQ is the weakest
* always shift
*/
if (!ret)
return (1);
break; /* exit from for loop */
}
/* reduce */
if (result)
return (result);
continue; /* for-loop */
}
/* shift */
if (!ret)
return (1);
break; /* exit from for-loop */
}
/* parse failed */
return (1);
}
#ifdef PARSE_DEBUG
#endif
continue; /* while-loop */
}
/* parse failed */
return (1);
} /* while-loop */
/* parse failed */
#ifdef PARSE_DEBUG
printf("XXXX ERROR: flag is not T_INIT\n");
#endif
return (1);
} else {
if (!exp)
return (1);
/* parse failed */
#ifdef PARSE_DEBUG
printf("ERR: flag for the result is not T_INIT\n");
printf(" %s observed\n",
#endif
return (1);
}
/*
* exp still remains in stack.
* parse failed
*/
return (1);
}
/* parse succeeded */
*e = exp;
return (0);
}
}
unsigned int
{
#ifdef GETTEXT_DEBUG
(void) printf("*************** plural_eval(%p, %d)\n",
exp, n);
#endif
switch (opnum) {
case NARY:
return (n);
}
break;
case UNARY:
/* T_LNOT */
return (!e1);
case BINARY:
/* optimization for T_LOR and T_LAND */
}
switch (type) {
case T_EQ:
case T_NEQ:
case T_GT:
case T_LT:
case T_GE:
case T_LE:
case T_ADD:
case T_SUB:
case T_MUL:
case T_DIV:
if (e2 != 0)
break;
case T_MOD:
if (e2 != 0)
break;
}
break;
case TRINARY:
/* T_CONDQ */
if (e1) {
} else {
}
}
/* should not be here */
return (0);
}