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