Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include        "mk.h"

static  int     bquote(Biobuf*, Bufblock*);

/*
 *      Assemble a line skipping blank lines, comments, and eliding
 *      escaped newlines
 */
int
assline(Biobuf *bp, Bufblock *buf)
{
        int c;
        int lastc;

        buf->current=buf->start;
        while ((c = nextrune(bp, 1)) >= 0){
                switch(c)
                {
                case '\r':              /* consumes CRs for Win95 */
                        continue;
                case '\n':
                        if (buf->current != buf->start) {
                                insert(buf, 0);
                                return 1;
                        }
                        break;          /* skip empty lines */
                case '\\':
                case '\'':
                case '"':
                        rinsert(buf, c);
                        if (escapetoken(bp, buf, 1, c) == 0)
                                Exit();
                        break;
                case '`':
                        if (bquote(bp, buf) == 0)
                                Exit();
                        break;
                case '#':
                        lastc = '#';
                        while ((c = Bgetc(bp)) != '\n') {
                                if (c < 0)
                                        goto eof;
                                if(c != '\r')
                                        lastc = c;
                        }
                        mkinline++;
                        if (lastc == '\\')
                                break;          /* propagate escaped newlines??*/
                        if (buf->current != buf->start) {
                                insert(buf, 0);
                                return 1;
                        }
                        break;
                default:
                        rinsert(buf, c);
                        break;
                }
        }
eof:
        insert(buf, 0);
        return *buf->start != 0;
}

/*
 *      assemble a back-quoted shell command into a buffer
 */
static int
bquote(Biobuf *bp, Bufblock *buf)
{
        int c, line, term;
        int start;

        line = mkinline;
        while((c = Bgetrune(bp)) == ' ' || c == '\t')
                        ;
        if(c == '{'){
                term = '}';             /* rc style */
                while((c = Bgetrune(bp)) == ' ' || c == '\t')
                        ;
        } else
                term = '`';             /* sh style */

        start = buf->current-buf->start;
        for(;c > 0; c = nextrune(bp, 0)){
                if(c == term){
                        insert(buf, '\n');
                        insert(buf,0);
                        buf->current = buf->start+start;
                        execinit();
                        execsh(0, buf->current, buf, envy);
                        return 1;
                }
                if(c == '\n')
                        break;
                if(c == '\'' || c == '"' || c == '\\'){
                        insert(buf, c);
                        if(!escapetoken(bp, buf, 1, c))
                                return 0;
                        continue;
                }
                rinsert(buf, c);
        }
        SYNERR(line);
        fprint(2, "missing closing %c after `\n", term);
        return 0;
}

/*
 *      get next character stripping escaped newlines
 *      the flag specifies whether escaped newlines are to be elided or
 *      replaced with a blank.
 */
int
nextrune(Biobuf *bp, int elide)
{
        int c;

        for (;;) {
                c = Bgetrune(bp);
                if (c == '\\') {
                        if (Bgetrune(bp) == '\n') {
                                mkinline++;
                                if (elide)
                                        continue;
                                return ' ';
                        }
                        Bungetrune(bp);
                }
                if (c == '\n')
                        mkinline++;
                return c;
        }
}