|
|
1.1 root 1: /* @(#)macro.c 1.5 */
2: /*
3: * UNIX shell
4: *
5: * Bell Telephone Laboratories
6: *
7: */
8:
9: #include "defs.h"
10: #include "sym.h"
11:
12: static char quote; /* used locally */
13: static char quoted; /* used locally */
14:
15:
16:
17: static char *
18: copyto(endch)
19: register char endch;
20: {
21: register char c;
22:
23: while ((c = getch(endch)) != endch && c)
24: pushstak(c | quote);
25: zerostak();
26: if (c != endch)
27: error(badsub);
28: }
29:
30: static
31: skipto(endch)
32: register char endch;
33: {
34: /*
35: * skip chars up to }
36: */
37: register char c;
38:
39: while ((c = readc()) && c != endch)
40: {
41: switch (c)
42: {
43: case SQUOTE:
44: skipto(SQUOTE);
45: break;
46:
47: case DQUOTE:
48: skipto(DQUOTE);
49: break;
50:
51: case DOLLAR:
52: if (readc() == BRACE)
53: skipto('}');
54: }
55: }
56: if (c != endch)
57: error(badsub);
58: }
59:
60: static
61: getch(endch)
62: char endch;
63: {
64: register char d;
65:
66: retry:
67: d = readc();
68: if (!subchar(d))
69: return(d);
70: if (d == DOLLAR)
71: {
72: register int c;
73:
74: if ((c = readc(), dolchar(c)))
75: {
76: struct namnod *n = (struct namnod *)NIL;
77: int dolg = 0;
78: BOOL bra;
79: BOOL nulflg;
80: register char *argp, *v;
81: char idb[2];
82: char *id = idb;
83:
84: if (bra = (c == BRACE))
85: c = readc();
86: if (letter(c))
87: {
88: argp = (char *)relstak();
89: while (alphanum(c))
90: {
91: pushstak(c);
92: c = readc();
93: }
94: zerostak();
95: n = lookup(absstak(argp));
96: setstak(argp);
97: if (n->namval.flg & N_FUNCTN)
98: error(badsub);
99: v = n->namval.val;
100: id = n->namid;
101: peekc = c | MARK;
102: }
103: else if (digchar(c))
104: {
105: *id = c;
106: idb[1] = 0;
107: if (astchar(c))
108: {
109: dolg = 1;
110: c = '1';
111: }
112: c -= '0';
113: v = ((c == 0) ? cmdadr : (c <= dolc) ? dolv[c] : (char *)(dolg = 0));
114: }
115: else if (c == '$')
116: v = pidadr;
117: else if (c == '!')
118: v = pcsadr;
119: else if (c == '#')
120: {
121: itos(dolc);
122: v = numbuf;
123: }
124: else if (c == '?')
125: {
126: itos(retval);
127: v = numbuf;
128: }
129: else if (c == '-')
130: v = flagadr;
131: else if (bra)
132: error(badsub);
133: else
134: goto retry;
135: c = readc();
136: if (c == ':' && bra) /* null and unset fix */
137: {
138: nulflg = 1;
139: c = readc();
140: }
141: else
142: nulflg = 0;
143: if (!defchar(c) && bra)
144: error(badsub);
145: argp = 0;
146: if (bra)
147: {
148: if (c != '}')
149: {
150: argp = (char *)relstak();
151: if ((v == 0 || (nulflg && *v == 0)) ^ (setchar(c)))
152: copyto('}');
153: else
154: skipto('}');
155: argp = absstak(argp);
156: }
157: }
158: else
159: {
160: peekc = c | MARK;
161: c = 0;
162: }
163: if (v && (!nulflg || *v))
164: {
165: char tmp = (*id == '*' ? SP | quote : SP);
166:
167: if (c != '+')
168: {
169: for (;;)
170: {
171: if (*v == 0 && quote)
172: pushstak(QUOTE);
173: else
174: {
175: while (c = *v++)
176: pushstak(c | quote);
177: }
178:
179: if (dolg == 0 || (++dolg > dolc))
180: break;
181: else
182: {
183: v = dolv[dolg];
184: pushstak(tmp);
185: }
186: }
187: }
188: }
189: else if (*id == '@' && quoted)
190: quoted = -1; /* swallow the quote later */
191: else if (argp)
192: {
193: if (c == '?')
194: failed(id, *argp ? argp : badparam);
195: else if (c == '=')
196: {
197: if (n)
198: {
199: trim(argp);
200: assign(n, argp);
201: }
202: else
203: error(badsub);
204: }
205: }
206: else if (flags & setflg)
207: failed(id, unset);
208: goto retry;
209: }
210: else
211: peekc = c | MARK;
212: }
213: else if (d == endch)
214: return(d);
215: else if (d == SQUOTE)
216: {
217: comsubst();
218: goto retry;
219: }
220: else if (d == DQUOTE)
221: {
222: quoted++;
223: quote ^= QUOTE;
224: goto retry;
225: }
226: return(d);
227: }
228:
229: char *
230: macro(as)
231: char *as;
232: {
233: /*
234: * Strip "" and do $ substitution
235: * Leaves result on top of stack
236: */
237: register BOOL savqu = quoted;
238: register char savq = quote;
239: struct filehdr fb;
240:
241: push(&fb);
242: estabf(as);
243: usestak();
244: quote = 0;
245: quoted = 0;
246: copyto(0);
247: pop();
248: if (quoted && (stakbot == staktop))
249: pushstak(QUOTE);
250: /*
251: * above is the fix for *'.c' bug
252: */
253: quote = savq;
254: quoted = savqu;
255: return(fixstak());
256: }
257:
258: static
259: comsubst()
260: {
261: /*
262: * command substn
263: */
264: struct fileblk cb;
265: register char d;
266: register char *savptr = fixstak();
267:
268: usestak();
269: while ((d = readc()) != SQUOTE && d)
270: pushstak(d);
271: {
272: register char *argc;
273:
274: trim(argc = fixstak());
275: push(&cb);
276: estabf(argc);
277: }
278: {
279: register struct trenod *t = makefork(FPOU, cmd(EOFSYM, MTFLG | NLFLG));
280: int pv[2];
281:
282: /*
283: * this is done like this so that the pipe
284: * is open only when needed
285: */
286: chkpipe(pv);
287: initf(pv[INPIPE]);
288: execute(t, 0, (int)(flags & errflg), 0, pv);
289: close(pv[OTPIPE]);
290: }
291: tdystak(savptr);
292: staktop = movstr(savptr, stakbot);
293: while (d = readc())
294: pushstak(d | quote);
295: await(0, 0);
296: while (stakbot != staktop)
297: {
298: if ((*--staktop & STRIP) != NL)
299: {
300: ++staktop;
301: break;
302: }
303: }
304: pop();
305: }
306:
307: #define CPYSIZ 512
308:
309: subst(in, ot)
310: int in, ot;
311: {
312: register char c;
313: struct fileblk fb;
314: register int count = CPYSIZ;
315:
316: push(&fb);
317: initf(in);
318: /*
319: * DQUOTE used to stop it from quoting
320: */
321: while (c = (getch(DQUOTE) & STRIP))
322: {
323: pushstak(c);
324: if (--count == 0)
325: {
326: flush(ot);
327: count = CPYSIZ;
328: }
329: }
330: flush(ot);
331: pop();
332: }
333:
334: static
335: flush(ot)
336: {
337: write(ot, stakbot, staktop - stakbot);
338: if (flags & execpr)
339: write(output, stakbot, staktop - stakbot);
340: staktop = stakbot;
341: }
342:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.