summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Elder <elder@linaro.org>2021-10-01 18:23:35 -0500
committerBjorn Andersson <bjorn.andersson@linaro.org>2021-10-04 14:18:03 -0500
commitfae755df216617dd132bb72645e1287167726c72 (patch)
treec9c6768b6f17a2bb773c248fedaa1696c5c0d2f0
parentb793b576ffe27001ec2087dcffa0510da9d7734e (diff)
parser: introduce qmi_identifier_parse()
Pull the code that extracts an identifier from the input stream out of yylex() and into a new helper function. Create qmi_number_parse() to do a similar thing for numbers. Signed-off-by: Alex Elder <elder@linaro.org> Message-Id: <20211001232338.769309-32-elder@linaro.org> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
-rw-r--r--parser.c103
1 files changed, 62 insertions, 41 deletions
diff --git a/parser.c b/parser.c
index 4edbf2f..ffd8249 100644
--- a/parser.c
+++ b/parser.c
@@ -205,20 +205,78 @@ static bool skip(char ch)
return in_comment;
}
+/* Extract an identifier from input into the given buffer */
+static struct symbol *qmi_identifier_parse(char *buf, size_t size, char ch)
+{
+ char *p = buf;
+
+ /* First character is known to be alphabetic */
+ *p++ = ch;
+ while ((ch = input()) && (isalnum(ch) || ch == '_')) {
+ if (p - buf == size) {
+ buf[TOKEN_BUF_MIN] = '\0';
+ yyerror("token too long: \"%s...\"", buf);
+ }
+ *p++ = ch;
+ }
+ unput(ch);
+ *p = '\0';
+
+ return symbol_find(buf);
+}
+
/* Used for parsing octal numbers */
static int isodigit(int c)
{
return isdigit(c) && c < '9';
}
+/* Extract a number from input into the given buffer; return base */
+static unsigned qmi_number_parse(char *buf, size_t size, char ch)
+{
+ int (*isvalid)(int);
+ char *p = buf;
+ unsigned base;
+
+ /* First character is a digit; determine base and valid character set */
+ if (ch == '0') {
+ *p++ = ch;
+ ch = input();
+ if (ch == 'x' || ch == 'X') {
+ *p++ = ch;
+ ch = input();
+ isvalid = isxdigit;
+ base = 16;
+ } else {
+ isvalid = isodigit;
+ base = 8;
+ }
+ } else {
+ isvalid = isdigit;
+ base = 10;
+ }
+
+ /* First character is known to be a digit 0-9 */
+ *p++ = ch;
+ while ((ch = input()) && isvalid(ch)) {
+ if (p - buf == size) {
+ buf[TOKEN_BUF_MIN] = '\0';
+ yyerror("number too long: \"%s...\"", buf);
+ }
+ *p++ = ch;
+ }
+ unput(ch);
+ *p = '\0';
+
+ return base;
+}
+
static struct token yylex()
{
struct symbol *sym;
struct token token = {};
unsigned long long num;
- int (*isvalid)(int);
char buf[TOKEN_BUF_SIZE];
- char *p = buf;
int base;
char ch;
@@ -226,22 +284,12 @@ static struct token yylex()
;
if (isalpha(ch)) {
- *p++ = ch;
- while ((ch = input()) && (isalnum(ch) || ch == '_')) {
- if (p - buf == sizeof(buf)) {
- buf[TOKEN_BUF_MIN] = '\0';
- yyerror("token too long: \"%s...\"", buf);
- }
- *p++ = ch;
- }
- unput(ch);
- *p = '\0';
+ sym = qmi_identifier_parse(buf, sizeof(buf), ch);
token.str = strdup(buf);
if (!token.str)
yyerror("strdup() failed in %s(), line %d\n",
__func__, __LINE__);
- sym = symbol_find(token.str);
if (sym) {
token.id = sym->token_id;
switch (token.id) {
@@ -261,34 +309,7 @@ static struct token yylex()
return token;
} else if (isdigit(ch)) {
- /* Determine base and valid character set */
- if (ch == '0') {
- *p++ = ch;
- ch = input();
- if (ch == 'x' || ch == 'X') {
- *p++ = ch;
- ch = input();
- isvalid = isxdigit;
- base = 16;
- } else {
- isvalid = isodigit;
- base = 8;
- }
- } else {
- isvalid = isdigit;
- base = 10;
- }
-
- *p++ = ch;
- while ((ch = input()) && isvalid(ch)) {
- if (p - buf == sizeof(buf)) {
- buf[TOKEN_BUF_MIN] = '\0';
- yyerror("number too long: \"%s...\"", buf);
- }
- *p++ = ch;
- }
- unput(ch);
- *p = '\0';
+ base = qmi_number_parse(buf, sizeof(buf), ch);
errno = 0;
num = strtoull(buf, NULL, base);