frontend: Add parsing of shell blocks
Signed-off-by: Ian Moffett <ian@mirocom.org>
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
.cc clang
|
.cc clang
|
||||||
.ld lld-link
|
.ld lld-link
|
||||||
|
|
||||||
|
# Shell block
|
||||||
CFLAGS ::
|
CFLAGS ::
|
||||||
-Iinclude/
|
-Iinclude/
|
||||||
-mgeneral-regs-only
|
-mgeneral-regs-only
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
#include "common/ptrbox.h"
|
#include "common/ptrbox.h"
|
||||||
#include "common/trace.h"
|
#include "common/trace.h"
|
||||||
|
|
||||||
|
#define SHELL_BLOCK_TERMINATE '~'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test if a given character counts as a whitespace character
|
* Test if a given character counts as a whitespace character
|
||||||
*
|
*
|
||||||
@@ -247,6 +249,69 @@ lexer_scan_directive(struct quip_state *state, struct token *tokres)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scan a shell block
|
||||||
|
*
|
||||||
|
* @state: Quip state
|
||||||
|
* @tokres: Token result is written here
|
||||||
|
*
|
||||||
|
* Returns zero on success
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
lexer_scan_shellblock(struct quip_state *state, struct token *tokres)
|
||||||
|
{
|
||||||
|
char c, *buf;
|
||||||
|
size_t bufsz, bufcap;
|
||||||
|
bool is_leading = true;
|
||||||
|
|
||||||
|
bufsz = 0;
|
||||||
|
bufcap = 8;
|
||||||
|
if ((buf = malloc(bufcap)) == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if ((c = lexer_consume(state, false)) == '\0') {
|
||||||
|
trace_error(state, "unexpected end of file within shellblock\n");
|
||||||
|
free(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle overflow if needed */
|
||||||
|
if (bufsz > bufcap - 1) {
|
||||||
|
bufcap += 8;
|
||||||
|
buf = realloc(buf, bufcap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle newlines */
|
||||||
|
if (c == '\n') {
|
||||||
|
buf[bufsz++] = ' ';
|
||||||
|
is_leading = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == SHELL_BLOCK_TERMINATE) {
|
||||||
|
buf[bufsz] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_leading && lexer_is_ws(c)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_leading = false;
|
||||||
|
buf[bufsz++] = c;
|
||||||
|
if (buf == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tokres->type = TT_SHELLBLOCK;
|
||||||
|
tokres->s = ptrbox_strdup(&state->ptrbox, buf);
|
||||||
|
free(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
lexer_scan(struct quip_state *state, struct token *tokres)
|
lexer_scan(struct quip_state *state, struct token *tokres)
|
||||||
{
|
{
|
||||||
@@ -274,17 +339,12 @@ lexer_scan(struct quip_state *state, struct token *tokres)
|
|||||||
case ':':
|
case ':':
|
||||||
tokres->c = c;
|
tokres->c = c;
|
||||||
if ((c = lexer_consume(state, false)) == ':') {
|
if ((c = lexer_consume(state, false)) == ':') {
|
||||||
tokres->type = TT_COLONDUB;
|
return lexer_scan_shellblock(state, tokres);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lexer_putback(state, c);
|
lexer_putback(state, c);
|
||||||
tokres->type = TT_COLON;
|
tokres->type = TT_COLON;
|
||||||
return 0;
|
return 0;
|
||||||
case '~':
|
|
||||||
tokres->type = TT_TILDE;
|
|
||||||
tokres->c = c;
|
|
||||||
return 0;
|
|
||||||
default:
|
default:
|
||||||
if (lexer_scan_name(state, c, tokres) == 0) {
|
if (lexer_scan_name(state, c, tokres) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -37,11 +37,10 @@ static const char *toktab[] = {
|
|||||||
[TT_NONE] = symtok("none"),
|
[TT_NONE] = symtok("none"),
|
||||||
[TT_NAME] = symtok("name"),
|
[TT_NAME] = symtok("name"),
|
||||||
[TT_NEWLINE] = symtok("newline"),
|
[TT_NEWLINE] = symtok("newline"),
|
||||||
|
[TT_SHELLBLOCK] = symtok("shellblock"),
|
||||||
[TT_CC] = qtok(".cc"),
|
[TT_CC] = qtok(".cc"),
|
||||||
[TT_LD] = qtok(".ld"),
|
[TT_LD] = qtok(".ld"),
|
||||||
[TT_COLON] = qtok(":"),
|
[TT_COLON] = qtok(":")
|
||||||
[TT_TILDE] = qtok("~"),
|
|
||||||
[TT_COLONDUB] = qtok("::")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|||||||
@@ -18,11 +18,10 @@ typedef enum {
|
|||||||
TT_NONE, /* [none] */
|
TT_NONE, /* [none] */
|
||||||
TT_NAME, /* [name] */
|
TT_NAME, /* [name] */
|
||||||
TT_NEWLINE, /* [newline] */
|
TT_NEWLINE, /* [newline] */
|
||||||
|
TT_SHELLBLOCK, /* [shellblock] */
|
||||||
TT_CC, /* '.cc' */
|
TT_CC, /* '.cc' */
|
||||||
TT_LD, /* '.ld' */
|
TT_LD, /* '.ld' */
|
||||||
TT_COLON, /* ':' */
|
TT_COLON, /* ':' */
|
||||||
TT_TILDE, /* '~' */
|
|
||||||
TT_COLONDUB, /* '::' */
|
|
||||||
} tt_t;
|
} tt_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Reference in New Issue
Block a user