| lex.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
| git clone git://git.suckless.org/9base | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| 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 escap… | |
| 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, shell… | |
| 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 } |