Motr  M0
lex.c
Go to the documentation of this file.
1 /* -*- C -*- */
2 /*
3  * Copyright (c) 2011-2020 Seagate Technology LLC and/or its Affiliates
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * For any questions about this software or licensing,
18  * please email opensource@seagate.com or cortx-questions@seagate.com.
19  *
20  */
21 
22 
29 #include <string.h> /* strchr, strlen */
30 #include <stdbool.h> /* bool */
31 #include <stdio.h> /* snprintf */
32 #include <errno.h>
33 #include <assert.h>
34 #include <err.h>
35 
36 #include "xcode/ff2c/lex.h"
37 
38 static const struct keyword {
39  const char *k_name;
41 } keywords[] = {
42  { "void", FTT_VOID },
43  { "require", FTT_REQUIRE },
44  { "u8", FTT_U8 },
45  { "u32", FTT_U32 },
46  { "u64", FTT_U64 },
47  { "record", FTT_RECORD },
48  { "union", FTT_UNION },
49  { "sequence", FTT_SEQUENCE },
50  { "array", FTT_ARRAY },
51  { "{", FTT_OPEN },
52  { "}", FTT_CLOSE },
53  { ";", FTT_SEMICOLON },
54  { NULL, 0 }
55 };
56 
57 static void ctx_move(struct ff2c_context *ctx, size_t nob)
58 {
59  assert(nob <= ctx->fc_remain);
60 
61  for (; nob > 0; --nob, --ctx->fc_remain, ++ctx->fc_pt) {
62  if (*ctx->fc_pt == '\n') {
63  ctx->fc_line++;
64  ctx->fc_col = 0;
65  } else
66  ctx->fc_col++;
67  }
68 }
69 
70 static void ctx_step(struct ff2c_context *ctx)
71 {
72  ctx_move(ctx, 1);
73 }
74 
75 #define SAFE(ctx, cond) ((ctx)->fc_remain > 0 && (cond))
76 
77 static bool at(struct ff2c_context *ctx, char c)
78 {
79  return SAFE(ctx, *ctx->fc_pt == c);
80 }
81 
82 static bool at_string(struct ff2c_context *ctx, const char *s, size_t n)
83 {
84  return ctx->fc_remain >= n && memcmp(ctx->fc_pt, s, n) == 0;
85 }
86 
87 static bool is_start(char c)
88 {
89  return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '_';
90 }
91 
92 static bool is_middle(char c)
93 {
94  return ('0' <= c && c <= '9') || is_start(c);
95 }
96 
97 static void tok_end(struct ff2c_context *ctx, struct ff2c_token *tok)
98 {
99  tok->ft_len = ctx->fc_pt - tok->ft_val;
100 }
101 
102 static void skip_space(struct ff2c_context *ctx)
103 {
104  static const char space[] = " \t\v\n\r";
105  const char *start;
106 
107  do {
108  start = ctx->fc_pt;
109  while (SAFE(ctx, strchr(space, *ctx->fc_pt)))
110  ctx_step(ctx);
111  if (at_string(ctx, "/*", 2)) {
112  ctx_step(ctx);
113  do {
114  ctx_step(ctx);
115  if (ctx->fc_remain < 2)
116  errx(2, "Unterminated comment");
117  } while (!at_string(ctx, "*/", 2));
118  ctx_move(ctx, 2);
119  }
120  } while (start != ctx->fc_pt);
121 }
122 
123 static bool get_literal(struct ff2c_context *ctx, struct ff2c_token *tok)
124 {
125  ctx_step(ctx);
126  skip_space(ctx);
127  tok->ft_val = ctx->fc_pt;
128  while (SAFE(ctx, is_middle(*ctx->fc_pt)))
129  ctx_step(ctx);
130  tok_end(ctx, tok);
131  return tok->ft_len > 0;
132 }
133 
134 int ff2c_token_get(struct ff2c_context *ctx, struct ff2c_token *tok)
135 {
136  const struct keyword *kw;
137 
138  /*
139  * Majority of token types are constant keywords, detected by iterating
140  * over keywords[] array.
141  *
142  * Others are (not entirely coincidentally) identifiable by their first
143  * character, which makes analyzing very simple.
144  */
145 
146  if (ctx->fc_depth > 0) {
147  *tok = ctx->fc_stack[--ctx->fc_depth];
148  return +1;
149  }
150 
151  skip_space(ctx);
152  if (ctx->fc_remain == 0)
153  return 0;
154  for (kw = &keywords[0]; kw->k_name != NULL; ++kw) {
155  size_t len = strlen(kw->k_name);
156  const char *pt = ctx->fc_pt;
157 
158  if (ctx->fc_remain >= len && !memcmp(pt, kw->k_name, len)) {
159  tok->ft_type = kw->k_type;
160  tok->ft_val = pt;
161  tok->ft_len = len;
162  ctx_move(ctx, len);
163  return +1;
164  }
165  }
166 
167  if (at(ctx, ':')) {
168  if (get_literal(ctx, tok)) {
169  tok->ft_type = FTT_TAG;
170  return +1;
171  } else {
172  warnx("\":\" must be followed by a tag");
173  return -EINVAL;
174  }
175  } else if (at(ctx, '[')) {
176  if (get_literal(ctx, tok)) {
177  skip_space(ctx);
178  if (at(ctx, ']')) {
179  ctx_step(ctx);
180  tok->ft_type = FTT_ESCAPE;
181  return +1;
182  }
183  }
184  warnx("\"[\" must be followed by an escape and \"]\"");
185  return -EINVAL;
186  } else if (at(ctx, '*')) {
187  if (get_literal(ctx, tok)) {
188  tok->ft_type = FTT_OPAQUE;
189  return +1;
190  } else {
191  warnx("\"*\" must be followed by a type name");
192  return -EINVAL;
193  }
194  } else if (at(ctx, '"')) {
195  tok->ft_val = ctx->fc_pt;
196  tok->ft_type = FTT_STRING;
197  do
198  ctx_step(ctx);
199  while (SAFE(ctx, *ctx->fc_pt != '"'));
200  if (at(ctx, '"')) {
201  ctx_step(ctx);
202  tok_end(ctx, tok);
203  return +1;
204  }
205  } else if (SAFE(ctx, is_start(*ctx->fc_pt))) {
206  tok->ft_val = ctx->fc_pt;
207  tok->ft_type = FTT_IDENTIFIER;
208  do
209  ctx_step(ctx);
210  while (SAFE(ctx, is_middle(*ctx->fc_pt)));
211  tok_end(ctx, tok);
212  return +1;
213  }
214  return -ENOENT;
215 }
216 
217 void ff2c_token_put(struct ff2c_context *ctx, struct ff2c_token *tok)
218 {
219  assert(ctx->fc_depth < FF2C_CTX_STACK_MAX);
220 
221  ctx->fc_stack[ctx->fc_depth++] = *tok;
222 }
223 
224 void ff2c_context_init(struct ff2c_context *ctx, const char *buf, size_t size)
225 {
226  ctx->fc_remain = ctx->fc_size = size;
227  ctx->fc_origin = ctx->fc_pt = buf;
228 }
229 
231 {
232 }
233 
234 int ff2c_context_loc(struct ff2c_context *ctx, int nr, char *buf)
235 {
236  return snprintf(buf, nr, "[%i:%i] %zu/%zu: '%c'",
237  ctx->fc_line, ctx->fc_col, ctx->fc_pt - ctx->fc_origin,
238  ctx->fc_size, *ctx->fc_pt);
239 }
240 
241 const char *ff2c_token_type_name[] = {
242  [FTT_IDENTIFIER] = "IDENTIFIER",
243  [FTT_REQUIRE] = "REQUIRE",
244  [FTT_STRING] = "STRING",
245  [FTT_VOID] = "VOID",
246  [FTT_U8] = "U8",
247  [FTT_U32] = "U32",
248  [FTT_U64] = "U64",
249  [FTT_OPAQUE] = "OPAQUE",
250  [FTT_RECORD] = "RECORD",
251  [FTT_UNION] = "UNION",
252  [FTT_SEQUENCE] = "SEQUENCE",
253  [FTT_ARRAY] = "ARRAY",
254  [FTT_OPEN] = "OPEN",
255  [FTT_CLOSE] = "CLOSE",
256  [FTT_SEMICOLON] = "SEMICOLON",
257  [FTT_TAG] = "TAG",
258  [FTT_ESCAPE] = "ESCAPE"
259 };
260 
263 /*
264  * Local variables:
265  * c-indentation-style: "K&R"
266  * c-basic-offset: 8
267  * tab-width: 8
268  * fill-column: 80
269  * scroll-step: 1
270  * End:
271  */
ff2c_token_type
Definition: lex.h:53
static size_t nr
Definition: dump.c:1505
Definition: lex.h:63
#define NULL
Definition: misc.h:38
static void ctx_step(struct ff2c_context *ctx)
Definition: lex.c:70
Definition: lex.h:81
Definition: lex.h:65
void ff2c_context_fini(struct ff2c_context *ctx)
Definition: lex.c:230
static void skip_space(struct ff2c_context *ctx)
Definition: lex.c:102
void ff2c_token_put(struct ff2c_context *ctx, struct ff2c_token *tok)
Definition: lex.c:217
int ff2c_token_get(struct ff2c_context *ctx, struct ff2c_token *tok)
Definition: lex.c:134
static int void * buf
Definition: dir.c:1019
static void tok_end(struct ff2c_context *ctx, struct ff2c_token *tok)
Definition: lex.c:97
Definition: sock.c:887
size_t ft_len
Definition: lex.h:99
#define SAFE(ctx, cond)
Definition: lex.c:75
Definition: lex.h:87
static bool is_start(char c)
Definition: lex.c:87
enum ff2c_token_type ft_type
Definition: lex.h:95
static bool at_string(struct ff2c_context *ctx, const char *s, size_t n)
Definition: lex.c:82
Definition: lex.h:73
const char * ff2c_token_type_name[]
Definition: lex.c:241
static struct m0_addb2_callback c
Definition: consumer.c:41
const char * k_name
Definition: lex.c:39
Definition: lex.h:59
Definition: lex.c:38
int ff2c_context_loc(struct ff2c_context *ctx, int nr, char *buf)
Definition: lex.c:234
static const struct keyword keywords[]
static bool is_middle(char c)
Definition: lex.c:92
static void ctx_move(struct ff2c_context *ctx, size_t nob)
Definition: lex.c:57
static bool at(struct ff2c_context *ctx, char c)
Definition: lex.c:77
uint64_t n
Definition: fops.h:107
Definition: lex.h:67
static bool get_literal(struct ff2c_context *ctx, struct ff2c_token *tok)
Definition: lex.c:123
Definition: lex.h:94
m0_bcount_t size
Definition: di.c:39
static int start(struct m0_fom *fom)
Definition: trigger_fom.c:321
Definition: lex.h:85
Definition: lex.h:61
Definition: lex.h:79
Definition: lex.h:77
Definition: nucleus.c:42
enum ff2c_token_type k_type
Definition: lex.c:40
const char * ft_val
Definition: lex.h:97
static struct m0_addb2_source * s
Definition: consumer.c:39
Definition: lex.h:71
void ff2c_context_init(struct ff2c_context *ctx, const char *buf, size_t size)
Definition: lex.c:224
Definition: lex.h:69