tlex.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
tlex.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 } |