From 435cdb0b7f3df965e9583dfcb1d37094871a87d4 Mon Sep 17 00:00:00 2001 From: Olaf Seibert Date: Fri, 22 May 2015 16:36:16 +0200 Subject: [PATCH] Separate out the string parsing for .include/.library file names and macro arguments. They behave observably different from generic string parsing and trying to account for them generically just gets in the way. .rept is treated the same as a macro. --- assemble.c | 4 +-- macros.c | 83 +++++++++++++++++++++++++++++++++++++++-------------- macros.h | 5 ++-- parse.c | 52 +++++++++++++++++++++++++++------ parse.h | 3 ++ rept_irpc.c | 3 +- 6 files changed, 114 insertions(+), 36 deletions(-) diff --git a/assemble.c b/assemble.c index 07d457e..1073e5a 100644 --- a/assemble.c +++ b/assemble.c @@ -459,7 +459,7 @@ static int assemble( case P_INCLUDE: { - char *name = getstring(cp, &cp); + char *name = getstring_fn(cp, &cp); STREAM *incl; if (name == NULL) { @@ -525,7 +525,7 @@ static int assemble( case P_LIBRARY: if (pass == 0) { char hitfile[FILENAME_MAX]; - char *name = getstring(cp, &cp); + char *name = getstring_fn(cp, &cp); my_searchenv(name, "MCALL", hitfile, sizeof(hitfile)); diff --git a/macros.c b/macros.c index 44179c1..fdec89f 100644 --- a/macros.c +++ b/macros.c @@ -371,32 +371,75 @@ BUFFER *subst_args( return gb; /* Done. */ } -/* eval_arg - the language allows an argument expression to be given +/* eval_str - the language allows an argument expression to be given as "\expression" which means, evaluate the expression and substitute the numeric value in the current radix. */ -void eval_arg( +char *eval_str( STREAM *refstr, - ARG *arg) + char *arg) { - /* Check for value substitution */ + EX_TREE *value = parse_expr(arg, 0); + unsigned word = 0; + char temp[10]; - if (arg->value[0] == '\\') { - EX_TREE *value = parse_expr(arg->value + 1, 0); - unsigned word = 0; - char temp[10]; + if (value->type != EX_LIT) { + report(refstr, "Constant value required\n"); + } else + word = value->data.lit; - if (value->type != EX_LIT) { - report(refstr, "Constant value required\n"); - } else - word = value->data.lit; + free_tree(value); - free_tree(value); + /* printf can't do base 2. */ + my_ultoa(word & 0177777, temp, radix); + free(arg); + arg = memcheck(strdup(temp)); + return arg; +} - /* printf can't do base 2. */ - my_ultoa(word & 0177777, temp, radix); - free(arg->value); - arg->value = memcheck(strdup(temp)); +/* getstring_macarg - parse a string that possibly starts with a backslash. + * If so, performs expression evaluation. + * + * The current implementation over-accepts some input. + * + * MACRO V05.05: + + .list me + .macro test x + .blkb x + .endm + + size = 10 + foo = 2 + + ; likes: + + test size + test \size + test \ + test \ + test ^/size + foo/ + + ; dislikes: + + test <\size> ; arg is \size which could be ok in other cases + test size + foo ; gets split at the space + test /size + foo/ ; gets split at the space + test \/size + foo/ + test \^/size + foo/ ; * accepted by this version + + */ + +char *getstring_macarg( + STREAM *refstr, + char *cp, + char **endp) +{ + if (cp[0] == '\\') { + char *str = getstring(cp + 1, endp); + return eval_str(refstr, str); /* Perform expression evaluation */ + } else { + return getstring(cp, endp); } } @@ -440,7 +483,7 @@ STREAM *expandmacro( arg = new_arg(); arg->label = label; nextcp = skipwhite(nextcp + 1); - arg->value = getstring(nextcp, &nextcp); + arg->value = getstring_macarg(refstr, nextcp, &nextcp); } else { if (label) free(label); @@ -457,15 +500,13 @@ STREAM *expandmacro( arg = new_arg(); arg->label = memcheck(strdup(macarg->label)); /* Copy the name */ - arg->value = getstring(cp, &nextcp); + arg->value = getstring_macarg(refstr, cp, &nextcp); nargs++; /* Count nonkeyword arguments only. */ } arg->next = args; args = arg; - eval_arg(refstr, arg); /* Check for expression evaluation */ - /* If there is a trailing comma, there is an empty last argument */ cp = skipdelim_comma(nextcp, &onemore); } diff --git a/macros.h b/macros.h index 3d15988..212ecc7 100644 --- a/macros.h +++ b/macros.h @@ -59,9 +59,10 @@ void read_body( BUFFER *gb, char *name, int called); -void eval_arg( +char *getstring_macarg( STREAM *refstr, - ARG *arg); + char *cp, + char **endp); BUFFER *subst_args( BUFFER *text, ARG *args); diff --git a/parse.c b/parse.c index 5f0630e..0218516 100644 --- a/parse.c +++ b/parse.c @@ -77,6 +77,49 @@ char *getstring( return str; } +/* Parses a string from the input stream for .include and .library. + * These have a special kind of delimiters. It likes + * .include /name/ ?name? \name\ "name" + * but not + * .include ^/name/ name =name= :name: + * .include :name: seems to be silently ignored. + */ +char *getstring_fn( + char *cp, + char **endp) +{ + char endstr[4]; + int len; + char *str; + + switch (*cp) { + case '<': + case '=': + case ':': + return NULL; + } + + if (!ispunct(*cp)) { + return NULL; + } + + endstr[0] = *cp; + endstr[1] = '\n'; + endstr[2] = '\0'; + cp++; + + len = strcspn(cp, endstr); + + if (endp) + *endp = cp + len + 1; + + str = memcheck(malloc(len + 1)); + memcpy(str, cp, len); + str[len] = 0; + + return str; +} + /* Get what would be the operation code from the line. */ /* Used to find the ends of streams without evaluating them, like finding the closing .ENDM on a macro definition */ @@ -584,15 +627,6 @@ int brackrange( endlen = 1; *start = 1; break; - case '/': /* seen on page 6-52 */ - case '?': /* seen on page 6-52 */ - case '\\': /* seen on page 6-52 */ - case '"': /* seen in Kermit-11 source for RT11 */ - endstr[0] = cp[0]; - strcpy(endstr + 1, "\n"); - *start = 1; - endlen = 1; - break; default: return FALSE; } diff --git a/parse.h b/parse.h index b1a415b..84f50d9 100644 --- a/parse.h +++ b/parse.h @@ -26,6 +26,9 @@ SYMBOL *get_op( char *getstring( char *cp, char **endp); +char *getstring_fn( + char *cp, + char **endp); char *get_symbol( char *cp, char **endp, diff --git a/rept_irpc.c b/rept_irpc.c index 42685d5..5ba5fb4 100644 --- a/rept_irpc.c +++ b/rept_irpc.c @@ -151,11 +151,10 @@ char *irp_stream_gets( arg->next = NULL; arg->locsym = 0; arg->label = istr->label; - arg->value = getstring(cp, &cp); + arg->value = getstring_macarg(str, cp, &cp); cp = skipdelim(cp); istr->offset = (int) (cp - istr->items); - eval_arg(str, arg); buf = subst_args(istr->body, arg); free(arg->value);