ref: a57a6e511f15c02b4fd2690197b6f1333b171193
dir: /sys/src/cmd/mk/lex.c/
#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, depth; 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 */ depth = 1; start = buf->current-buf->start; for(;c > 0; c = nextrune(bp, 0)){ if(c == '{' && term == '}') depth++; if(c == term && --depth == 0){ 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; } }