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