bc: Unwind the stack in every return - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 98923f69a1bb852d7fcbf2146dec4a084874bf80
 (DIR) parent 6edcf9948848793f67f04458a72c7825fe9e4138
 (HTM) Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
       Date:   Fri, 28 Nov 2025 12:34:55 +0100
       
       bc: Unwind the stack in every return
       
       When we return from a function we have to unwind the stack and
       pop all the locals of that function. That requires to create
       a string with all the pop information to be used in every return.
       
       Diffstat:
         M bc.y                                |      73 ++++++++++++++++++++++---------
       
       1 file changed, 52 insertions(+), 21 deletions(-)
       ---
 (DIR) diff --git a/bc.y b/bc.y
       @@ -49,7 +49,7 @@ static char *var(char *);
        static char *ary(char *);
        static void writeout(char *);
        
       -static char *yytext, *buff;
       +static char *yytext, *buff, *unwind;
        static char *filename;
        static FILE *filep;
        static int lineno, nerr, flowid;
       @@ -158,29 +158,29 @@ for     : FOR                   {$$ = macro(LOOP);}
        def     : DEF ID                {$$ = macro(DEF);}
                ;
        
       -parlst  : '(' ')'               {$$ = code("%%s");}
       +parlst  : '(' ')'               {$$ = code("");}
                | '(' params ')'        {$$ = $2;}
                ;
        
       -params  : param
       -        | params ',' param      {$$ = code($1, $3); free($1);}
       +params  : param                 {$$ = param(NULL, $1);}
       +        | params ',' param      {$$ = param($1, $3);}
                ;
        
       -param   : ID                    {$$ = code("S%s%%sL%ss.", var($1), var($1));}
       -        | ID '[' ']'            {$$ = code("S%s%%sL%ss.", ary($1), ary($1));}
       +param   : ID                    {$$ = var($1);}
       +        | ID '[' ']'            {$$ = ary($1);}
                ;
        
       -autolst :                       {$$ = code("%%s");}
       +autolst :                       {$$ = code("");}
                | AUTO locals '\n'      {$$ = $2;}
                | AUTO locals ';'       {$$ = $2;}
                ;
        
       -locals  : local
       -        | locals ',' local      {$$ = code($1, $3); free($1);}
       +locals  : local                 {$$ = local(NULL, $1);}
       +        | locals ',' local      {$$ = local($1, $3);}
                ;
        
       -local   : ID                    {$$ = code("0S%s%%sL%ss.", var($1), var($1));}
       -        | ID '[' ']'            {$$ = code("0S%s%%sL%ss.", ary($1), ary($1));}
       +local   : ID                    {$$ = var($1);}
       +        | ID '[' ']'            {$$ = ary($1);}
                ;
        
        arglst  : expr
       @@ -379,19 +379,50 @@ macro(int op)
        }
        
        static char *
       -funcode(Macro *d, char *params, char *vars, char *body)
       +param(char *list, char *id)
       +{
       +        char *i1, *i2;
       +
       +        i1 = estrdup(id);
       +        i2 = estrdup(id);
       +        free(id);
       +
       +        unwind = code(unwind ? "L%ss.%s" : "L%ss.", i1, unwind);
       +
       +        return code(list ? "S%s%s" : "S%s" , i2, list);
       +}
       +
       +static char *
       +local(char *list, char *id)
        {
       -        char *s, *t1, *t2;
       +        char *i1, *i2;
        
       -        t1 = code(vars, params);
       -        t2 = code(t1, body);
       +        i1 = estrdup(id);
       +        i2 = estrdup(id);
       +        free(id);
        
       +        unwind = code(unwind ? "L%ss.%s" : "L%ss.", i1, unwind);
       +
       +        return code(list ? "0S%s%s" : "0S%s" , i2, list);
       +}
       +
       +static char *
       +funcode(Macro *d, char *params, char *vars, char *body)
       +{
       +        char *s;
       +
       +        s = code("[%s%s%s%s]s%c",
       +                 vars, params,
       +                 body,
       +                 retcode(code(" 0")),
       +                 d->id);
       +        free(unwind);
       +        unwind = NULL;
                nested--;
                inhome = 0;
       -        free(vars);
       -        free(t1);
        
       -        return code("[%s 0 1Q]s%c", t2, d->id);
       +
       +        return s;
        }
        
        static char *
       @@ -415,7 +446,7 @@ forcode(Macro *d, char *init, char *cmp, char *inc, char *body)
                         body,
                         inc,
                         estrdup(cmp),
       -                 d->flowid, d->id);
       +                 d->id, d->id);
                writeout(s);
        
                s = code("%ss.%s%c", init, cmp, d->id);
       @@ -432,7 +463,7 @@ whilecode(Macro *d, char *cmp, char *body)
                s = code("[%ss.%s%c]s%c",
                         body,
                         estrdup(cmp),
       -                 d->flowid, d->id);
       +                 d->id, d->id);
                writeout(s);
        
                s = code("%s%c", cmp, d->id);
       @@ -462,7 +493,7 @@ retcode(char *expr)
        
                if (nested < 2 || macros[1].op != DEF)
                        yyerror("return must be in a function");
       -        return code("%s %dQ", expr, nested - 1);
       +        return code("%s %s %dQ", estrdup(unwind), expr, nested - 1);
        }
        
        static char *