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
|
||||
.ld lld-link
|
||||
|
||||
# Shell block
|
||||
CFLAGS ::
|
||||
-Iinclude/
|
||||
-mgeneral-regs-only
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "common/ptrbox.h"
|
||||
#include "common/trace.h"
|
||||
|
||||
#define SHELL_BLOCK_TERMINATE '~'
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
lexer_scan(struct quip_state *state, struct token *tokres)
|
||||
{
|
||||
@@ -274,17 +339,12 @@ lexer_scan(struct quip_state *state, struct token *tokres)
|
||||
case ':':
|
||||
tokres->c = c;
|
||||
if ((c = lexer_consume(state, false)) == ':') {
|
||||
tokres->type = TT_COLONDUB;
|
||||
return 0;
|
||||
return lexer_scan_shellblock(state, tokres);
|
||||
}
|
||||
|
||||
lexer_putback(state, c);
|
||||
tokres->type = TT_COLON;
|
||||
return 0;
|
||||
case '~':
|
||||
tokres->type = TT_TILDE;
|
||||
tokres->c = c;
|
||||
return 0;
|
||||
default:
|
||||
if (lexer_scan_name(state, c, tokres) == 0) {
|
||||
return 0;
|
||||
|
||||
@@ -37,11 +37,10 @@ static const char *toktab[] = {
|
||||
[TT_NONE] = symtok("none"),
|
||||
[TT_NAME] = symtok("name"),
|
||||
[TT_NEWLINE] = symtok("newline"),
|
||||
[TT_SHELLBLOCK] = symtok("shellblock"),
|
||||
[TT_CC] = qtok(".cc"),
|
||||
[TT_LD] = qtok(".ld"),
|
||||
[TT_COLON] = qtok(":"),
|
||||
[TT_TILDE] = qtok("~"),
|
||||
[TT_COLONDUB] = qtok("::")
|
||||
[TT_COLON] = qtok(":")
|
||||
};
|
||||
|
||||
int
|
||||
|
||||
@@ -18,11 +18,10 @@ typedef enum {
|
||||
TT_NONE, /* [none] */
|
||||
TT_NAME, /* [name] */
|
||||
TT_NEWLINE, /* [newline] */
|
||||
TT_SHELLBLOCK, /* [shellblock] */
|
||||
TT_CC, /* '.cc' */
|
||||
TT_LD, /* '.ld' */
|
||||
TT_COLON, /* ':' */
|
||||
TT_TILDE, /* '~' */
|
||||
TT_COLONDUB, /* '::' */
|
||||
} tt_t;
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user