lex.c (2505B)
1 #include "mk.h" 2 3 static int bquote(Biobuf*, Bufblock*); 4 5 /* 6 * Assemble a line skipping blank lines, comments, and eliding 7 * escaped newlines 8 */ 9 int 10 assline(Biobuf *bp, Bufblock *buf) 11 { 12 int c; 13 int lastc; 14 15 buf->current=buf->start; 16 while ((c = nextrune(bp, 1)) >= 0){ 17 switch(c) 18 { 19 case '\r': /* consumes CRs for Win95 */ 20 continue; 21 case '\n': 22 if (buf->current != buf->start) { 23 insert(buf, 0); 24 return 1; 25 } 26 break; /* skip empty lines */ 27 case '\\': 28 case '\'': 29 case '"': 30 rinsert(buf, c); 31 if (shellt->escapetoken(bp, buf, 1, c) == 0) 32 Exit(); 33 break; 34 case '`': 35 if (bquote(bp, buf) == 0) 36 Exit(); 37 break; 38 case '#': 39 lastc = '#'; 40 while ((c = Bgetc(bp)) != '\n') { 41 if (c < 0) 42 goto eof; 43 if(c != '\r') 44 lastc = c; 45 } 46 mkinline++; 47 if (lastc == '\\') 48 break; /* propagate escaped newlines??*/ 49 if (buf->current != buf->start) { 50 insert(buf, 0); 51 return 1; 52 } 53 break; 54 default: 55 rinsert(buf, c); 56 break; 57 } 58 } 59 eof: 60 insert(buf, 0); 61 return *buf->start != 0; 62 } 63 64 /* 65 * assemble a back-quoted shell command into a buffer 66 */ 67 static int 68 bquote(Biobuf *bp, Bufblock *buf) 69 { 70 int c, line, term; 71 int start; 72 73 line = mkinline; 74 while((c = Bgetrune(bp)) == ' ' || c == '\t') 75 ; 76 if(c == '{'){ 77 term = '}'; /* rc style */ 78 while((c = Bgetrune(bp)) == ' ' || c == '\t') 79 ; 80 } else 81 term = '`'; /* sh style */ 82 83 start = buf->current-buf->start; 84 for(;c > 0; c = nextrune(bp, 0)){ 85 if(c == term){ 86 insert(buf, '\n'); 87 insert(buf,0); 88 buf->current = buf->start+start; 89 execinit(); 90 execsh(0, buf->current, buf, envy, shellt, shellcmd); 91 return 1; 92 } 93 if(c == '\n') 94 break; 95 if(c == '\'' || c == '"' || c == '\\'){ 96 insert(buf, c); 97 if(!shellt->escapetoken(bp, buf, 1, c)) 98 return 0; 99 continue; 100 } 101 rinsert(buf, c); 102 } 103 SYNERR(line); 104 fprint(2, "missing closing %c after `\n", term); 105 return 0; 106 } 107 108 /* 109 * get next character stripping escaped newlines 110 * the flag specifies whether escaped newlines are to be elided or 111 * replaced with a blank. 112 */ 113 int 114 nextrune(Biobuf *bp, int elide) 115 { 116 int c, c2; 117 static int savec; 118 119 if(savec){ 120 c = savec; 121 savec = 0; 122 return c; 123 } 124 125 for (;;) { 126 c = Bgetrune(bp); 127 if (c == '\\') { 128 c2 = Bgetrune(bp); 129 if(c2 == '\r'){ 130 savec = c2; 131 c2 = Bgetrune(bp); 132 } 133 if (c2 == '\n') { 134 savec = 0; 135 mkinline++; 136 if (elide) 137 continue; 138 return ' '; 139 } 140 Bungetrune(bp); 141 } 142 if (c == '\n') 143 mkinline++; 144 return c; 145 } 146 }