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);