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