Commit | Line | Data |
---|---|---|
eb594574 | 1 | /* macro.c 4.2 83/02/09 */ |
121105ee KM |
2 | |
3 | # | |
4 | /* | |
5 | * UNIX shell | |
6 | * | |
7 | * S. R. Bourne | |
8 | * Bell Telephone Laboratories | |
9 | * | |
10 | */ | |
11 | ||
12 | #include "defs.h" | |
13 | #include "sym.h" | |
14 | ||
15 | LOCAL CHAR quote; /* used locally */ | |
16 | LOCAL CHAR quoted; /* used locally */ | |
17 | ||
18 | ||
19 | ||
20 | LOCAL STRING copyto(endch) | |
21 | REG CHAR endch; | |
22 | { | |
23 | REG CHAR c; | |
24 | ||
25 | WHILE (c=getch(endch))!=endch ANDF c | |
26 | DO pushstak(c|quote) OD | |
27 | zerostak(); | |
28 | IF c!=endch THEN error(badsub) FI | |
29 | } | |
30 | ||
31 | LOCAL skipto(endch) | |
32 | REG CHAR endch; | |
33 | { | |
34 | /* skip chars up to } */ | |
35 | REG CHAR c; | |
36 | WHILE (c=readc()) ANDF c!=endch | |
37 | DO SWITCH c IN | |
38 | ||
39 | case SQUOTE: skipto(SQUOTE); break; | |
40 | ||
41 | case DQUOTE: skipto(DQUOTE); break; | |
42 | ||
43 | case DOLLAR: IF readc()==BRACE | |
44 | THEN skipto('}'); | |
45 | FI | |
46 | ENDSW | |
47 | OD | |
48 | IF c!=endch THEN error(badsub) FI | |
49 | } | |
50 | ||
51 | LOCAL getch(endch) | |
52 | CHAR endch; | |
53 | { | |
54 | REG CHAR d; | |
55 | ||
56 | retry: | |
57 | d=readc(); | |
58 | IF !subchar(d) | |
59 | THEN return(d); | |
60 | FI | |
61 | IF d==DOLLAR | |
62 | THEN REG INT c; | |
63 | IF (c=readc(), dolchar(c)) | |
64 | THEN NAMPTR n=NIL; | |
65 | INT dolg=0; | |
66 | BOOL bra; | |
67 | REG STRING argp, v; | |
68 | CHAR idb[2]; | |
69 | STRING id=idb; | |
70 | ||
71 | IF bra=(c==BRACE) THEN c=readc() FI | |
72 | IF letter(c) | |
73 | THEN argp=relstak(); | |
74 | WHILE alphanum(c) DO pushstak(c); c=readc() OD | |
75 | zerostak(); | |
76 | n=lookup(absstak(argp)); setstak(argp); | |
77 | v = n->namval; id = n->namid; | |
78 | peekc = c|MARK;; | |
79 | ELIF digchar(c) | |
80 | THEN *id=c; idb[1]=0; | |
81 | IF astchar(c) | |
82 | THEN dolg=1; c='1'; | |
83 | FI | |
84 | c -= '0'; | |
85 | v=((c==0) ? cmdadr : (c<=dolc) ? dolv[c] : (dolg=0)); | |
86 | ELIF c=='$' | |
87 | THEN v=pidadr; | |
88 | ELIF c=='!' | |
89 | THEN v=pcsadr; | |
90 | ELIF c=='#' | |
91 | THEN v=dolladr; | |
92 | ELIF c=='?' | |
93 | THEN v=exitadr; | |
94 | ELIF c=='-' | |
95 | THEN v=flagadr; | |
96 | ELIF bra THEN error(badsub); | |
97 | ELSE goto retry; | |
98 | FI | |
99 | c = readc(); | |
100 | IF !defchar(c) ANDF bra | |
101 | THEN error(badsub); | |
102 | FI | |
103 | argp=0; | |
104 | IF bra | |
105 | THEN IF c!='}' | |
106 | THEN argp=relstak(); | |
107 | IF (v==0)NEQ(setchar(c)) | |
108 | THEN copyto('}'); | |
109 | ELSE skipto('}'); | |
110 | FI | |
111 | argp=absstak(argp); | |
112 | FI | |
113 | ELSE peekc = c|MARK; c = 0; | |
114 | FI | |
115 | IF v | |
116 | THEN IF c!='+' | |
117 | THEN LOOP WHILE c = *v++ | |
118 | DO pushstak(c|quote); OD | |
119 | IF dolg==0 ORF (++dolg>dolc) | |
120 | THEN break; | |
121 | ELSE v=dolv[dolg]; pushstak(SP|(*id=='*' ? quote : 0)); | |
122 | FI | |
123 | POOL | |
124 | FI | |
125 | ELIF argp | |
126 | THEN IF c=='?' | |
127 | THEN failed(id,*argp?argp:badparam); | |
128 | ELIF c=='=' | |
129 | THEN IF n | |
130 | THEN assign(n,argp); | |
131 | ELSE error(badsub); | |
132 | FI | |
133 | FI | |
134 | ELIF flags&setflg | |
135 | THEN failed(id,badparam); | |
136 | FI | |
137 | goto retry; | |
138 | ELSE peekc=c|MARK; | |
139 | FI | |
140 | ELIF d==endch | |
141 | THEN return(d); | |
142 | ELIF d==SQUOTE | |
143 | THEN comsubst(); goto retry; | |
144 | ELIF d==DQUOTE | |
145 | THEN quoted++; quote^=QUOTE; goto retry; | |
146 | FI | |
147 | return(d); | |
148 | } | |
149 | ||
150 | STRING macro(as) | |
151 | STRING as; | |
152 | { | |
153 | /* Strip "" and do $ substitution | |
154 | * Leaves result on top of stack | |
155 | */ | |
156 | REG BOOL savqu =quoted; | |
157 | REG CHAR savq = quote; | |
158 | FILEHDR fb; | |
159 | ||
160 | push(&fb); estabf(as); | |
161 | usestak(); | |
162 | quote=0; quoted=0; | |
163 | copyto(0); | |
164 | pop(); | |
165 | IF quoted ANDF (stakbot==staktop) THEN pushstak(QUOTE) FI | |
166 | quote=savq; quoted=savqu; | |
167 | return(fixstak()); | |
168 | } | |
169 | ||
170 | LOCAL comsubst() | |
171 | { | |
172 | /* command substn */ | |
173 | FILEBLK cb; | |
174 | REG CHAR d; | |
175 | REG STKPTR savptr = fixstak(); | |
176 | ||
177 | usestak(); | |
178 | WHILE (d=readc())!=SQUOTE ANDF d | |
179 | DO pushstak(d) OD | |
180 | ||
181 | BEGIN | |
182 | REG STRING argc; | |
183 | trim(argc=fixstak()); | |
184 | push(&cb); estabf(argc); | |
185 | END | |
186 | BEGIN | |
187 | REG TREPTR t = makefork(FPOU,cmd(EOFSYM,MTFLG|NLFLG)); | |
188 | INT pv[2]; | |
189 | ||
190 | /* this is done like this so that the pipe | |
191 | * is open only when needed | |
192 | */ | |
193 | chkpipe(pv); | |
194 | initf(pv[INPIPE]); | |
195 | execute(t, 0, 0, pv); | |
196 | close(pv[OTPIPE]); | |
197 | END | |
198 | tdystak(savptr); staktop=movstr(savptr,stakbot); | |
eb594574 | 199 | WHILE d=readc() DO locstak(); pushstak(d|quote) OD |
121105ee KM |
200 | await(0); |
201 | WHILE stakbot!=staktop | |
202 | DO IF (*--staktop&STRIP)!=NL | |
203 | THEN ++staktop; break; | |
204 | FI | |
205 | OD | |
206 | pop(); | |
207 | } | |
208 | ||
209 | #define CPYSIZ 512 | |
210 | ||
211 | subst(in,ot) | |
212 | INT in, ot; | |
213 | { | |
214 | REG CHAR c; | |
215 | FILEBLK fb; | |
216 | REG INT count=CPYSIZ; | |
217 | ||
218 | push(&fb); initf(in); | |
219 | /* DQUOTE used to stop it from quoting */ | |
220 | WHILE c=(getch(DQUOTE)&STRIP) | |
221 | DO pushstak(c); | |
222 | IF --count == 0 | |
223 | THEN flush(ot); count=CPYSIZ; | |
224 | FI | |
225 | OD | |
226 | flush(ot); | |
227 | pop(); | |
228 | } | |
229 | ||
230 | LOCAL flush(ot) | |
231 | { | |
232 | write(ot,stakbot,staktop-stakbot); | |
233 | IF flags&execpr THEN write(output,stakbot,staktop-stakbot) FI | |
234 | staktop=stakbot; | |
235 | } |