|
|
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.