|  | #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 (shellt->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, shellt, shellcmd); | 
|  | return 1; | 
|  | } | 
|  | if(c == '\n') | 
|  | break; | 
|  | if(c == '\'' || c == '"' || c == '\\'){ | 
|  | insert(buf, c); | 
|  | if(!shellt->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, c2; | 
|  | static int savec; | 
|  |  | 
|  | if(savec){ | 
|  | c = savec; | 
|  | savec = 0; | 
|  | return c; | 
|  | } | 
|  |  | 
|  | for (;;) { | 
|  | c = Bgetrune(bp); | 
|  | if (c == '\\') { | 
|  | c2 = Bgetrune(bp); | 
|  | if(c2 == '\r'){ | 
|  | savec = c2; | 
|  | c2 = Bgetrune(bp); | 
|  | } | 
|  | if (c2 == '\n') { | 
|  | savec = 0; | 
|  | mkinline++; | 
|  | if (elide) | 
|  | continue; | 
|  | return ' '; | 
|  | } | 
|  | Bungetrune(bp); | 
|  | } | 
|  | if (c == '\n') | 
|  | mkinline++; | 
|  | return c; | 
|  | } | 
|  | } |