From patchwork Thu Oct 4 01:47:33 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Troy Kisky X-Patchwork-Id: 189007 X-Patchwork-Delegate: sbabic@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id B18E62C0336 for ; Thu, 4 Oct 2012 11:57:55 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 58DAF282FD; Thu, 4 Oct 2012 03:57:47 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ImIu38U4zFDS; Thu, 4 Oct 2012 03:57:47 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 5F58A28308; Thu, 4 Oct 2012 03:57:26 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 4D658282F0 for ; Thu, 4 Oct 2012 03:57:23 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id M-2uDtrdJRPx for ; Thu, 4 Oct 2012 03:57:21 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-da0-f44.google.com (mail-da0-f44.google.com [209.85.210.44]) by theia.denx.de (Postfix) with ESMTPS id 293882823B for ; Thu, 4 Oct 2012 03:57:18 +0200 (CEST) Received: by mail-da0-f44.google.com with SMTP id h15so2687833dan.3 for ; Wed, 03 Oct 2012 18:57:18 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=LXHPmAALYJ5IHrPFQYs8UR1eaNGhPHyeIiOCVzUcC64=; b=n69z04nrAE8UJQBvHy9hJRMKDjfu0tCXzvHJar6REnwsaW3xU9hPyO0oCqgjvugY8G 97tirKOF/V2kuPlwX45sl6cxkko24sPf4W8BajNlPjUWHDSWnWB5F/fH76P4IoJ0V7Kz q3Hos2B1kh9x8CDUmGNYwe0HpcU2v8RRCtMVrvAPv/Nb/r5Cw4YkcweCIb3e1b1g7Kn2 P+8skq7s0OSTXO3N68NtoGz0Ijs2TjQAuS23VtPu0DyLkSX/q/JC5k7Zt+E2P34KpCEJ MtHrmezLqVRRX+38JtqducgkiFmm2aNobNLjXQYMzvKZ9kvF4sXEg3aOb+1buabIa/0P bZIA== Received: by 10.68.213.138 with SMTP id ns10mr17452385pbc.157.1349315838585; Wed, 03 Oct 2012 18:57:18 -0700 (PDT) Received: from officeserver-2 ([70.96.116.236]) by mx.google.com with ESMTPS id gk5sm3482383pbc.21.2012.10.03.18.57.17 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 03 Oct 2012 18:57:18 -0700 (PDT) Received: from tkisky by officeserver-2 with local (Exim 4.76) (envelope-from ) id 1TJaXe-0005Xa-QQ; Wed, 03 Oct 2012 18:47:58 -0700 From: Troy Kisky To: sbabic@denx.de Date: Wed, 3 Oct 2012 18:47:33 -0700 Message-Id: <1349315254-21151-32-git-send-email-troy.kisky@boundarydevices.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1349315254-21151-1-git-send-email-troy.kisky@boundarydevices.com> References: <1348281558-19520-1-git-send-email-troy.kisky@boundarydevices.com> <1349315254-21151-1-git-send-email-troy.kisky@boundarydevices.com> X-Gm-Message-State: ALoCoQlNQD/6/dubivFkn7eh69TCjzMBtosWN3MQmvDRiFYmoedW+rg6dnR8+l481G0S2ZL6xHO3 Cc: u-boot@lists.denx.de Subject: [U-Boot] [PATCH V3 31/32] parse_helper: add expression evaluation X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Basic expressions with order precedence is now supported. ie. (----3 + ((1+2*3)/--2 + --5 *(8/4))) is 16. Signed-off-by: Troy Kisky --- tools/parse_helper.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 162 insertions(+), 10 deletions(-) diff --git a/tools/parse_helper.c b/tools/parse_helper.c index 0a5c5f6..50be832 100644 --- a/tools/parse_helper.c +++ b/tools/parse_helper.c @@ -97,20 +97,172 @@ int ph_skip_comma(struct parse_helper *ph) } } +static const char precedence[] = { + /* ( + - * / & ^ | ) */ + 0, 2, 2, 1, 1, 3, 4, 5, 6 +}; +static const char unary_operations[] = "(+-"; +static const char binary_operations[] = " +-*/&^|)"; + +static uint32_t do_func(uint32_t val1, uint32_t val2, int op) +{ + switch (op) { + case 1: + return val1 + val2; + case 2: + return val1 - val2; + case 3: + return val1 * val2; + case 4: + return val1 / val2; + case 5: + return val1 & val2; + case 6: + return val1 ^ val2; + case 7: + return val1 | val2; + } + fprintf(stderr, "Error: in func %s: val1=%d val2=%d op = %d\n", + __func__, val1, val2, op); + exit(EXIT_FAILURE); +} + +static int find_op(char c, const char *p) +{ + int i; + for (i = 0; ; i++) { + if (c == p[i]) + return i; + if (!p[i]) + break; + } + return -1; +} + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + int ph_get_value(struct parse_helper *ph, uint32_t *pval) { char *endptr; - uint32_t value; + int op_i = 0; + int val_i = 0; + unsigned char op[16]; + uint32_t val[16]; + int unary = 1; + char *p; - if (ph_skip_separators(ph)) - return -1; - errno = 0; - value = strtoul(ph->p, &endptr, 16); - if (errno || (ph->p == endptr)) - return -1; - *pval = value; - ph->p = endptr; - return 0; + p = ph->p; + for (;;) { + char c; + int i, j; + const char *ops = unary ? unary_operations : binary_operations; + + if (unary) { + ph->p = p; + if (ph_skip_separators(ph)) + return -1; + p = ph->p; + c = *p; + } else { + for (;;) { + c = *p; + if ((c != ' ') && (c != '\t')) + break; + p++; + } + } + i = find_op(c, ops); + debug("%d,%c,%d:%s\n", i, c, unary, p); + if ((i < 0) && unary) { + if (val_i >= ARRAY_SIZE(val)) + return -1; + errno = 0; + val[val_i++] = strtoul(p, &endptr, 16); + if (errno || (p == endptr)) { + ph->p = p; + return -1; + } + p = endptr; + unary = 0; + debug("val[%d]=%x,%d,%d\n", val_i - 1, val[val_i - 1], + op_i, val_i); +do_unary: + while (op_i) { + j = op[op_i - 1]; + if (!(j & 0x80)) + break; + op_i--; + val[val_i - 1] = do_func(0, + val[val_i - 1], j & 0x7f); + debug("un:%d,%x,%d,%d\n", val[val_i - 1], j, + op_i, val_i); + } + continue; + } + if (i < 0) { + c = 0; + i = 8; + } else { + p++; + } + if (c == '(') { + if (op_i >= ARRAY_SIZE(op)) + return -1; + op[op_i++] = i; + debug("op[%d]=%x,%d,%d\n", op_i - 1, op[op_i - 1], + op_i, val_i); + unary = 1; + continue; + } + for (;;) { + if (!op_i || unary) + break; + j = op[op_i - 1]; + if (j == 0) { + if (c == ')') { + op_i--; + goto do_unary; + } + break; + } + if ((j & 0x80)) { + op_i--; + val[val_i - 1] = do_func(0, + val[val_i - 1], j & 0x7f); + debug("unary:%d,%x\n", val[val_i - 1], j); + continue; + } + if (precedence[i] < precedence[j]) + break; + if (val_i < 2) + return -1; + op_i--; + val[val_i - 2] = do_func(val[val_i - 2], + val[val_i - 1], j); + val_i--; + debug("binary:%d,%x,%d,%d\n", val[val_i - 1], j, + op_i, val_i); + } + if (c == ')') { + fprintf(stderr, "Error: unmatched parenthesis\n"); + return -1; + } + if (i == 8) { + if ((op_i != 0) || (val_i != 1)) { + fprintf(stderr, "Error: syntax %d %d\n", + op_i, val_i); + return -1; + } + ph->p = p; + *pval = val[0]; + return 0; + } + if (op_i >= ARRAY_SIZE(op)) + return -1; + op[op_i++] = i | (unary << 7); + debug("op[%d]=%x,%d,%d\n", op_i - 1, op[op_i - 1], op_i, val_i); + unary = 1; + } } /*