1 0 stevel /* 2 2182 chin * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3 0 stevel * Use is subject to license terms. 4 0 stevel */ 5 0 stevel 6 0 stevel /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7 0 stevel /* All Rights Reserved */ 8 0 stevel 9 0 stevel /* 10 0 stevel * Copyright (c) 1980 Regents of the University of California. 11 0 stevel * All rights reserved. The Berkeley Software License Agreement 12 0 stevel * specifies the terms and conditions for redistribution. 13 0 stevel */ 14 0 stevel 15 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 16 0 stevel 17 0 stevel #include <unistd.h> /* for lseek prototype */ 18 0 stevel #include "sh.h" 19 0 stevel #include "sh.tconst.h" 20 0 stevel #include <sys/filio.h> 21 0 stevel #include <sys/ttold.h> 22 559 nakanon #define RAW O_RAW 23 0 stevel /* 24 0 stevel * C shell 25 0 stevel */ 26 0 stevel 27 0 stevel /* 28 0 stevel * These lexical routines read input and form lists of words. 29 0 stevel * There is some involved processing here, because of the complications 30 0 stevel * of input buffering, and especially because of history substitution. 31 0 stevel */ 32 0 stevel 33 356 muffin tchar *word(void); 34 356 muffin tchar getC1(int); 35 356 muffin tchar *subword(tchar *, int, bool *); 36 356 muffin void getdol(void); 37 356 muffin void addla(tchar *); 38 356 muffin void getexcl(tchar); 39 356 muffin void noev(tchar *); 40 356 muffin void setexclp(tchar *); 41 356 muffin void unreadc(tchar); 42 356 muffin int readc(bool); 43 356 muffin struct wordent *dosub(int, struct wordent *, bool); 44 356 muffin struct Hist *findev(tchar *, bool); 45 356 muffin struct wordent *gethent(int); 46 356 muffin struct wordent *getsub(struct wordent *); 47 0 stevel 48 0 stevel /* 49 0 stevel * Peekc is a peek characer for getC, peekread for readc. 50 0 stevel * There is a subtlety here in many places... history routines 51 0 stevel * will read ahead and then insert stuff into the input stream. 52 0 stevel * If they push back a character then they must push it behind 53 0 stevel * the text substituted by the history substitution. On the other 54 0 stevel * hand in several places we need 2 peek characters. To make this 55 0 stevel * all work, the history routines read with getC, and make use both 56 0 stevel * of ungetC and unreadc. The key observation is that the state 57 0 stevel * of getC at the call of a history reference is such that calls 58 0 stevel * to getC from the history routines will always yield calls of 59 0 stevel * readc, unless this peeking is involved. That is to say that during 60 0 stevel * getexcl the variables lap, exclp, and exclnxt are all zero. 61 0 stevel * 62 0 stevel * Getdol invokes history substitution, hence the extra peek, peekd, 63 0 stevel * which it can ungetD to be before history substitutions. 64 0 stevel */ 65 0 stevel tchar peekc, peekd; 66 0 stevel tchar peekread; 67 0 stevel 68 0 stevel tchar *exclp; /* (Tail of) current word from ! subst */ 69 0 stevel struct wordent *exclnxt; /* The rest of the ! subst words */ 70 0 stevel int exclc; /* Count of remainig words in ! subst */ 71 0 stevel tchar *alvecp; /* "Globp" for alias resubstitution */ 72 0 stevel 73 0 stevel /* 74 0 stevel * Lex returns to its caller not only a wordlist (as a "var" parameter) 75 0 stevel * but also whether a history substitution occurred. This is used in 76 0 stevel * the main (process) routine to determine whether to echo, and also 77 0 stevel * when called by the alias routine to determine whether to keep the 78 0 stevel * argument list. 79 0 stevel */ 80 0 stevel bool hadhist; 81 0 stevel 82 0 stevel tchar getCtmp; 83 559 nakanon #define getC(f) ((getCtmp = peekc) ? (peekc = 0, getCtmp) : getC1(f)) 84 0 stevel #define ungetC(c) peekc = c 85 0 stevel #define ungetD(c) peekd = c 86 0 stevel 87 356 muffin bool 88 356 muffin lex(struct wordent *hp) 89 0 stevel { 90 356 muffin struct wordent *wdp; 91 0 stevel int c; 92 0 stevel 93 0 stevel #ifdef TRACE 94 0 stevel tprintf("TRACE- lex()\n"); 95 0 stevel #endif 96 0 stevel lineloc = btell(); 97 0 stevel hp->next = hp->prev = hp; 98 559 nakanon hp->word = S_ /* "" */; 99 0 stevel alvecp = 0, hadhist = 0; 100 0 stevel do 101 0 stevel c = readc(0); 102 0 stevel while (issp(c)); 103 0 stevel /* make sure history is enabled */ 104 0 stevel if (HIST && c == HISTSUB && intty) 105 0 stevel /* ^lef^rit from tty is short !:s^lef^rit */ 106 0 stevel getexcl(c); 107 0 stevel else 108 0 stevel unreadc(c); 109 0 stevel wdp = hp; 110 0 stevel /* 111 0 stevel * The following loop is written so that the links needed 112 0 stevel * by freelex will be ready and rarin to go even if it is 113 0 stevel * interrupted. 114 0 stevel */ 115 0 stevel do { 116 559 nakanon struct wordent *new = (struct wordent *)xalloc(sizeof *wdp); 117 0 stevel 118 0 stevel new->word = 0; 119 0 stevel new->prev = wdp; 120 0 stevel new->next = hp; 121 0 stevel wdp->next = new; 122 0 stevel wdp = new; 123 0 stevel wdp->word = word(); 124 0 stevel } while (wdp->word[0] != '\n'); 125 0 stevel #ifdef TRACE 126 0 stevel tprintf("Exiting lex()\n"); 127 0 stevel #endif 128 0 stevel hp->prev = wdp; 129 0 stevel return (hadhist); 130 0 stevel } 131 0 stevel 132 356 muffin void 133 356 muffin prlex(struct wordent *sp0) 134 0 stevel { 135 356 muffin struct wordent *sp = sp0->next; 136 0 stevel 137 0 stevel #ifdef TRACE 138 0 stevel tprintf("TRACE- prlex()\n"); 139 0 stevel #endif 140 0 stevel for (;;) { 141 0 stevel printf("%t", sp->word); 142 0 stevel sp = sp->next; 143 0 stevel if (sp == sp0) 144 0 stevel break; 145 0 stevel if (sp->word[0] != '\n') 146 0 stevel Putchar(' '); 147 0 stevel } 148 0 stevel } 149 0 stevel 150 356 muffin void 151 356 muffin copylex(struct wordent *hp, struct wordent *fp) 152 0 stevel { 153 356 muffin struct wordent *wdp; 154 0 stevel 155 0 stevel #ifdef TRACE 156 0 stevel tprintf("TRACE- copylex()\n"); 157 0 stevel #endif 158 0 stevel wdp = hp; 159 0 stevel fp = fp->next; 160 0 stevel do { 161 559 nakanon struct wordent *new = (struct wordent *)xalloc(sizeof *wdp); 162 0 stevel 163 0 stevel new->prev = wdp; 164 0 stevel new->next = hp; 165 0 stevel wdp->next = new; 166 0 stevel wdp = new; 167 0 stevel wdp->word = savestr(fp->word); 168 0 stevel fp = fp->next; 169 0 stevel } while (wdp->word[0] != '\n'); 170 0 stevel hp->prev = wdp; 171 0 stevel } 172 0 stevel 173 356 muffin void 174 356 muffin freelex(struct wordent *vp) 175 0 stevel { 176 356 muffin struct wordent *fp; 177 0 stevel 178 0 stevel #ifdef TRACE 179 0 stevel tprintf("TRACE- freelex()\n"); 180 0 stevel #endif 181 0 stevel while (vp->next != vp) { 182 0 stevel fp = vp->next; 183 0 stevel vp->next = fp->next; 184 559 nakanon xfree(fp->word); 185 559 nakanon xfree(fp); 186 0 stevel } 187 0 stevel vp->prev = vp; 188 0 stevel } 189 0 stevel 190 0 stevel tchar * 191 356 muffin word(void) 192 0 stevel { 193 356 muffin tchar c, c1; 194 356 muffin tchar *wp; 195 0 stevel tchar wbuf[BUFSIZ]; 196 356 muffin bool dolflg; 197 356 muffin int i; 198 0 stevel 199 0 stevel #ifdef TRACE 200 0 stevel tprintf("TRACE- word()\n"); 201 0 stevel #endif 202 0 stevel wp = wbuf; 203 0 stevel i = BUFSIZ - 4; 204 0 stevel loop: 205 0 stevel while (issp(c = getC(DOALL))) 206 0 stevel ; 207 0 stevel if (cmap(c, _META|_ESC)||isauxsp(c)) 208 0 stevel switch (c) { 209 0 stevel case '&': 210 0 stevel case '|': 211 0 stevel case '<': 212 0 stevel case '>': 213 0 stevel *wp++ = c; 214 0 stevel c1 = getC(DOALL); 215 0 stevel if (c1 == c) 216 0 stevel *wp++ = c1; 217 0 stevel else 218 0 stevel ungetC(c1); 219 0 stevel goto ret; 220 0 stevel 221 0 stevel case '#': 222 0 stevel if (intty) 223 0 stevel break; 224 0 stevel c = 0; 225 0 stevel do { 226 0 stevel c1 = c; 227 0 stevel c = getC(0); 228 0 stevel } while (c != '\n'); 229 0 stevel if (c1 == '\\') 230 0 stevel goto loop; 231 0 stevel /* fall into ... */ 232 0 stevel 233 0 stevel case ';': 234 0 stevel case '(': 235 0 stevel case ')': 236 0 stevel case '\n': 237 0 stevel *wp++ = c; 238 0 stevel goto ret; 239 0 stevel 240 0 stevel case '\\': 241 0 stevel c = getC(0); 242 0 stevel if (c == '\n') { 243 0 stevel if (onelflg == 1) 244 0 stevel onelflg = 2; 245 0 stevel goto loop; 246 0 stevel } 247 0 stevel if (c != HIST) 248 0 stevel *wp++ = '\\', --i; 249 0 stevel c |= QUOTE; 250 0 stevel } 251 0 stevel c1 = 0; 252 0 stevel dolflg = DOALL; 253 0 stevel for (;;) { 254 0 stevel if (c1) { 255 0 stevel if (c == c1) { 256 0 stevel c1 = 0; 257 0 stevel dolflg = DOALL; 258 0 stevel } else if (c == '\\') { 259 0 stevel c = getC(0); 260 0 stevel if (c == HIST) 261 0 stevel c |= QUOTE; 262 0 stevel else { 263 0 stevel if (c == '\n') 264 559 nakanon #if 0 265 0 stevel if (c1 == '`') 266 0 stevel c = ' '; 267 0 stevel else 268 559 nakanon #endif 269 0 stevel c |= QUOTE; 270 0 stevel ungetC(c); 271 0 stevel c = '\\'; 272 0 stevel } 273 0 stevel } else if (c == '\n') { 274 0 stevel seterrc(gettext("Unmatched "), c1); 275 0 stevel ungetC(c); 276 0 stevel break; 277 0 stevel } 278 0 stevel } else if (cmap(c, _META|_Q|_Q1|_ESC)||isauxsp(c)) { 279 0 stevel if (c == '\\') { 280 0 stevel c = getC(0); 281 0 stevel if (c == '\n') { 282 0 stevel if (onelflg == 1) 283 0 stevel onelflg = 2; 284 0 stevel break; 285 0 stevel } 286 0 stevel if (c != HIST) 287 0 stevel *wp++ = '\\', --i; 288 0 stevel c |= QUOTE; 289 0 stevel } else if (cmap(c, _Q|_Q1)) { /* '"` */ 290 0 stevel c1 = c; 291 0 stevel dolflg = c == '"' ? DOALL : DOEXCL; 292 0 stevel } else if (c != '#' || !intty) { 293 0 stevel ungetC(c); 294 0 stevel break; 295 0 stevel } 296 0 stevel } 297 0 stevel if (--i > 0) { 298 0 stevel *wp++ = c; 299 0 stevel c = getC(dolflg); 300 0 stevel } else { 301 0 stevel seterr("Word too long"); 302 0 stevel wp = &wbuf[1]; 303 0 stevel break; 304 0 stevel } 305 0 stevel } 306 0 stevel ret: 307 0 stevel *wp = 0; 308 0 stevel #ifdef TRACE 309 0 stevel tprintf("word() returning:%t\n", wbuf); 310 0 stevel #endif 311 0 stevel return (savestr(wbuf)); 312 0 stevel } 313 0 stevel 314 356 muffin tchar 315 356 muffin getC1(int flag) 316 0 stevel { 317 356 muffin tchar c; 318 0 stevel 319 0 stevel top: 320 0 stevel if (c = peekc) { 321 0 stevel peekc = 0; 322 0 stevel return (c); 323 0 stevel } 324 0 stevel if (lap) { 325 0 stevel if ((c = *lap++) == 0) 326 0 stevel lap = 0; 327 0 stevel else { 328 0 stevel /* 329 559 nakanon * don't quote things if there was an error (err!=0) 330 559 nakanon * the input is original, not from a substitution and 331 559 nakanon * therefore should not be quoted 332 0 stevel */ 333 0 stevel if (!err && cmap(c, _META|_Q|_Q1)||isauxsp(c)) 334 0 stevel c |= QUOTE; 335 0 stevel return (c); 336 0 stevel } 337 0 stevel } 338 0 stevel if (c = peekd) { 339 0 stevel peekd = 0; 340 0 stevel return (c); 341 0 stevel } 342 0 stevel if (exclp) { 343 0 stevel if (c = *exclp++) 344 0 stevel return (c); 345 0 stevel if (exclnxt && --exclc >= 0) { 346 0 stevel exclnxt = exclnxt->next; 347 0 stevel setexclp(exclnxt->word); 348 0 stevel return (' '); 349 0 stevel } 350 0 stevel exclp = 0; 351 0 stevel exclnxt = 0; 352 0 stevel } 353 0 stevel if (exclnxt) { 354 0 stevel exclnxt = exclnxt->next; 355 0 stevel if (--exclc < 0) 356 0 stevel exclnxt = 0; 357 0 stevel else 358 0 stevel setexclp(exclnxt->word); 359 0 stevel goto top; 360 0 stevel } 361 0 stevel c = readc(0); 362 0 stevel if (c == '$' && (flag & DODOL)) { 363 0 stevel getdol(); 364 0 stevel goto top; 365 0 stevel } 366 0 stevel if (c == HIST && (flag & DOEXCL)) { 367 0 stevel getexcl(0); 368 0 stevel goto top; 369 0 stevel } 370 0 stevel return (c); 371 0 stevel } 372 0 stevel 373 356 muffin void 374 356 muffin getdol(void) 375 0 stevel { 376 356 muffin tchar *np, *p; 377 0 stevel tchar name[MAX_VREF_LEN]; 378 356 muffin int c; 379 0 stevel int sc; 380 0 stevel bool special = 0; 381 0 stevel 382 0 stevel #ifdef TRACE 383 0 stevel tprintf("TRACE- getdol()\n"); 384 0 stevel #endif 385 0 stevel np = name, *np++ = '$'; 386 0 stevel c = sc = getC(DOEXCL); 387 0 stevel if (isspnl(c)) { 388 0 stevel ungetD(c); 389 0 stevel ungetC('$' | QUOTE); 390 0 stevel return; 391 0 stevel } 392 0 stevel if (c == '{') 393 0 stevel *np++ = c, c = getC(DOEXCL); 394 0 stevel if (c == '#' || c == '?') 395 0 stevel special++, *np++ = c, c = getC(DOEXCL); 396 0 stevel *np++ = c; 397 0 stevel switch (c) { 398 559 nakanon 399 0 stevel case '<': 400 0 stevel case '$': 401 0 stevel case '*': 402 0 stevel if (special) 403 0 stevel goto vsyn; 404 0 stevel goto ret; 405 0 stevel 406 0 stevel case '\n': 407 0 stevel ungetD(c); 408 0 stevel np--; 409 0 stevel goto vsyn; 410 0 stevel 411 0 stevel default: 412 0 stevel p = np; 413 0 stevel if (digit(c)) { 414 0 stevel /* make sure the variable names are MAX_VAR_LEN chars or less */ 415 559 nakanon while (digit(c = getC(DOEXCL)) && (np - p) < MAX_VAR_LEN) { 416 0 stevel *np++ = c; 417 0 stevel } 418 0 stevel } else if (letter(c)) { 419 0 stevel while ((letter(c = getC(DOEXCL)) || digit(c)) && 420 559 nakanon (np - p) < MAX_VAR_LEN) { 421 0 stevel *np++ = c; 422 0 stevel } 423 0 stevel } 424 0 stevel else 425 0 stevel goto vsyn; 426 0 stevel 427 559 nakanon if ((np - p) > MAX_VAR_LEN) 428 0 stevel { 429 0 stevel seterr("Variable name too long"); 430 0 stevel goto ret; 431 0 stevel } 432 0 stevel } 433 0 stevel if (c == '[') { 434 0 stevel *np++ = c; 435 0 stevel do { 436 0 stevel c = getC(DOEXCL); 437 0 stevel if (c == '\n') { 438 0 stevel ungetD(c); 439 0 stevel np--; 440 0 stevel goto vsyn; 441 0 stevel } 442 0 stevel /* need to leave space for possible modifiers */ 443 0 stevel if (np >= &name[MAX_VREF_LEN - 8]) 444 0 stevel { 445 0 stevel seterr("Variable reference too long"); 446 0 stevel goto ret; 447 0 stevel } 448 0 stevel *np++ = c; 449 0 stevel } while (c != ']'); 450 0 stevel c = getC(DOEXCL); 451 0 stevel } 452 0 stevel if (c == ':') { 453 0 stevel *np++ = c, c = getC(DOEXCL); 454 0 stevel if (c == 'g') 455 0 stevel *np++ = c, c = getC(DOEXCL); 456 0 stevel *np++ = c; 457 0 stevel if (!any(c, S_htrqxe)) 458 0 stevel goto vsyn; 459 0 stevel } else 460 0 stevel ungetD(c); 461 0 stevel if (sc == '{') { 462 0 stevel c = getC(DOEXCL); 463 0 stevel if (c != '}') { 464 0 stevel ungetC(c); 465 0 stevel goto vsyn; 466 0 stevel } 467 0 stevel *np++ = c; 468 0 stevel } 469 0 stevel ret: 470 0 stevel *np = 0; 471 0 stevel addla(name); 472 0 stevel return; 473 0 stevel 474 0 stevel vsyn: 475 0 stevel seterr("Variable syntax"); 476 0 stevel goto ret; 477 0 stevel } 478 0 stevel 479 356 muffin void 480 356 muffin addla(tchar *cp) 481 0 stevel { 482 0 stevel tchar *buf; 483 0 stevel int len = 0; 484 0 stevel 485 0 stevel #ifdef TRACE 486 0 stevel tprintf("TRACE- addla()\n"); 487 0 stevel #endif 488 0 stevel if (lap) { 489 0 stevel len = strlen_(lap); 490 0 stevel buf = xalloc((len+1) * sizeof (tchar)); 491 0 stevel (void) strcpy_(buf, lap); 492 0 stevel } 493 0 stevel len += strlen_(cp); 494 0 stevel 495 0 stevel /* len+5 is allow 4 additional charecters just to be safe */ 496 0 stevel labuf = xrealloc(labuf, (len+5) * sizeof (tchar)); 497 0 stevel (void) strcpy_(labuf, cp); 498 0 stevel if (lap) { 499 0 stevel (void) strcat_(labuf, buf); 500 559 nakanon xfree(buf); 501 0 stevel } 502 0 stevel lap = labuf; 503 0 stevel } 504 0 stevel 505 2182 chin tchar lhsb[256]; 506 2182 chin tchar slhs[256]; 507 2182 chin tchar rhsb[512]; 508 0 stevel int quesarg; 509 0 stevel 510 356 muffin void 511 356 muffin getexcl(tchar sc) 512 0 stevel { 513 356 muffin struct wordent *hp, *ip; 514 0 stevel int left, right, dol; 515 356 muffin int c; 516 0 stevel 517 0 stevel #ifdef TRACE 518 0 stevel tprintf("TRACE- getexcl()\n"); 519 0 stevel #endif 520 0 stevel if (sc == 0) { 521 0 stevel sc = getC(0); 522 0 stevel if (sc != '{') { 523 0 stevel ungetC(sc); 524 0 stevel sc = 0; 525 0 stevel } 526 0 stevel } 527 0 stevel quesarg = -1; 528 0 stevel lastev = eventno; 529 0 stevel hp = gethent(sc); 530 0 stevel if (hp == 0) 531 0 stevel return; 532 0 stevel hadhist = 1; 533 0 stevel dol = 0; 534 0 stevel if (hp == alhistp) 535 0 stevel for (ip = hp->next->next; ip != alhistt; ip = ip->next) 536 0 stevel dol++; 537 0 stevel else 538 0 stevel for (ip = hp->next->next; ip != hp->prev; ip = ip->next) 539 0 stevel dol++; 540 0 stevel left = 0, right = dol; 541 0 stevel if (sc == HISTSUB) { 542 0 stevel ungetC('s'), unreadc(HISTSUB), c = ':'; 543 0 stevel goto subst; 544 0 stevel } 545 0 stevel c = getC(0); 546 559 nakanon /* if (!any(c, ":^$*-%")) */ /* change needed for char -> tchar */ 547 0 stevel if (! (c == ':' || c == '^' || c == '$' || c == '*' || 548 559 nakanon c == '-' || c == '%')) 549 0 stevel goto subst; 550 0 stevel left = right = -1; 551 0 stevel if (c == ':') { 552 0 stevel c = getC(0); 553 0 stevel unreadc(c); 554 0 stevel if (letter(c) || c == '&') { 555 0 stevel c = ':'; 556 0 stevel left = 0, right = dol; 557 0 stevel goto subst; 558 0 stevel } 559 0 stevel } else 560 0 stevel ungetC(c); 561 0 stevel if (!getsel(&left, &right, dol)) 562 0 stevel return; 563 0 stevel c = getC(0); 564 0 stevel if (c == '*') 565 0 stevel ungetC(c), c = '-'; 566 0 stevel if (c == '-') { 567 0 stevel if (!getsel(&left, &right, dol)) 568 0 stevel return; 569 0 stevel c = getC(0); 570 0 stevel } 571 0 stevel subst: 572 0 stevel exclc = right - left + 1; 573 0 stevel while (--left >= 0) 574 0 stevel hp = hp->next; 575 0 stevel if (sc == HISTSUB || c == ':') { 576 0 stevel do { 577 0 stevel hp = getsub(hp); 578 0 stevel c = getC(0); 579 0 stevel } while (c == ':'); 580 0 stevel } 581 0 stevel unreadc(c); 582 0 stevel if (sc == '{') { 583 0 stevel c = getC(0); 584 0 stevel if (c != '}') 585 0 stevel seterr("Bad ! form"); 586 0 stevel } 587 0 stevel exclnxt = hp; 588 0 stevel } 589 0 stevel 590 0 stevel struct wordent * 591 356 muffin getsub(struct wordent *en) 592 0 stevel { 593 356 muffin tchar *cp; 594 0 stevel int delim; 595 356 muffin int c; 596 0 stevel int sc; 597 0 stevel bool global = 0; 598 0 stevel tchar orhsb[(sizeof rhsb)/(sizeof rhsb[0])]; 599 0 stevel 600 0 stevel #ifdef TRACE 601 0 stevel tprintf("TRACE- getsub()\n"); 602 0 stevel #endif 603 0 stevel exclnxt = 0; 604 0 stevel sc = c = getC(0); 605 0 stevel if (c == 'g') 606 0 stevel global++, c = getC(0); 607 0 stevel switch (c) { 608 0 stevel 609 0 stevel case 'p': 610 0 stevel justpr++; 611 0 stevel goto ret; 612 0 stevel 613 0 stevel case 'x': 614 0 stevel case 'q': 615 0 stevel global++; 616 0 stevel /* fall into ... */ 617 0 stevel 618 0 stevel case 'h': 619 0 stevel case 'r': 620 0 stevel case 't': 621 0 stevel case 'e': 622 0 stevel break; 623 0 stevel 624 0 stevel case '&': 625 0 stevel if (slhs[0] == 0) { 626 0 stevel seterr("No prev sub"); 627 0 stevel goto ret; 628 0 stevel } 629 0 stevel (void) strcpy_(lhsb, slhs); 630 0 stevel break; 631 0 stevel 632 559 nakanon #if 0 633 0 stevel case '~': 634 0 stevel if (lhsb[0] == 0) 635 0 stevel goto badlhs; 636 0 stevel break; 637 559 nakanon #endif 638 0 stevel 639 0 stevel case 's': 640 0 stevel delim = getC(0); 641 559 nakanon if (alnum(delim) || isspnl(delim)) { 642 0 stevel unreadc(delim); 643 0 stevel bads: 644 0 stevel lhsb[0] = 0; 645 0 stevel seterr("Bad substitute"); 646 0 stevel goto ret; 647 0 stevel } 648 0 stevel cp = lhsb; 649 0 stevel for (;;) { 650 0 stevel c = getC(0); 651 0 stevel if (c == '\n') { 652 0 stevel unreadc(c); 653 0 stevel break; 654 0 stevel } 655 0 stevel if (c == delim) 656 0 stevel break; 657 0 stevel if (cp > &lhsb[(sizeof lhsb)/(sizeof lhsb[0]) - 2]) 658 0 stevel goto bads; 659 0 stevel if (c == '\\') { 660 0 stevel c = getC(0); 661 0 stevel if (c != delim && c != '\\') 662 0 stevel *cp++ = '\\'; 663 0 stevel } 664 0 stevel *cp++ = c; 665 0 stevel } 666 0 stevel if (cp != lhsb) 667 0 stevel *cp++ = 0; 668 0 stevel else if (lhsb[0] == 0) { 669 559 nakanon /* badlhs: */ 670 0 stevel seterr("No prev lhs"); 671 0 stevel goto ret; 672 0 stevel } 673 0 stevel cp = rhsb; 674 0 stevel (void) strcpy_(orhsb, cp); 675 0 stevel for (;;) { 676 0 stevel c = getC(0); 677 0 stevel if (c == '\n') { 678 0 stevel unreadc(c); 679 0 stevel break; 680 0 stevel } 681 0 stevel if (c == delim) 682 0 stevel break; 683 559 nakanon #if 0 684 0 stevel if (c == '~') { 685 559 nakanon if (&cp[strlen_(orhsb)] 686 0 stevel > &rhsb[(sizeof rhsb)/(sizeof rhsb[0]) - 2]) 687 0 stevel goto toorhs; 688 0 stevel (void) strcpy_(cp, orhsb); 689 0 stevel cp = strend(cp); 690 0 stevel continue; 691 0 stevel } 692 559 nakanon #endif 693 0 stevel if (cp > &rhsb[(sizeof rhsb)/(sizeof rhsb[0]) - 2]) { 694 559 nakanon /* toorhs: */ 695 0 stevel seterr("Rhs too long"); 696 0 stevel goto ret; 697 0 stevel } 698 0 stevel if (c == '\\') { 699 0 stevel c = getC(0); 700 0 stevel if (c != delim /* && c != '~' */) 701 0 stevel *cp++ = '\\'; 702 0 stevel } 703 0 stevel *cp++ = c; 704 0 stevel } 705 0 stevel *cp++ = 0; 706 0 stevel break; 707 0 stevel 708 0 stevel default: 709 0 stevel if (c == '\n') 710 0 stevel unreadc(c); 711 0 stevel seterrc(gettext("Bad ! modifier: "), c); 712 0 stevel goto ret; 713 0 stevel } 714 0 stevel (void) strcpy_(slhs, lhsb); 715 0 stevel if (exclc) 716 0 stevel en = dosub(sc, en, global); 717 0 stevel ret: 718 0 stevel return (en); 719 0 stevel } 720 0 stevel 721 0 stevel struct wordent * 722 356 muffin dosub(int sc, struct wordent *en, bool global) 723 0 stevel { 724 0 stevel struct wordent lex; 725 0 stevel bool didsub = 0; 726 0 stevel struct wordent *hp = &lex; 727 356 muffin struct wordent *wdp; 728 356 muffin int i = exclc; 729 0 stevel 730 0 stevel #ifdef TRACE 731 0 stevel tprintf("TRACE- dosub()\n"); 732 0 stevel #endif 733 0 stevel wdp = hp; 734 0 stevel while (--i >= 0) { 735 559 nakanon struct wordent *new = (struct wordent *)xcalloc(1, sizeof *wdp); 736 0 stevel 737 0 stevel new->prev = wdp; 738 0 stevel new->next = hp; 739 0 stevel wdp->next = new; 740 0 stevel wdp = new; 741 0 stevel en = en->next; 742 0 stevel wdp->word = global || didsub == 0 ? 743 0 stevel subword(en->word, sc, &didsub) : savestr(en->word); 744 0 stevel } 745 0 stevel if (didsub == 0) 746 0 stevel seterr("Modifier failed"); 747 0 stevel hp->prev = wdp; 748 0 stevel return (&enthist(-1000, &lex, 0)->Hlex); 749 0 stevel } 750 0 stevel 751 0 stevel tchar * 752 356 muffin subword(tchar *cp, int type, bool *adid) 753 0 stevel { 754 0 stevel tchar wbuf[BUFSIZ]; 755 356 muffin tchar *wp, *mp, *np; 756 356 muffin int i; 757 0 stevel 758 0 stevel #ifdef TRACE 759 0 stevel tprintf("TRACE- subword()\n"); 760 0 stevel #endif 761 0 stevel switch (type) { 762 0 stevel 763 0 stevel case 'r': 764 0 stevel case 'e': 765 0 stevel case 'h': 766 0 stevel case 't': 767 0 stevel case 'q': 768 0 stevel case 'x': 769 0 stevel wp = domod(cp, type); 770 0 stevel if (wp == 0) 771 0 stevel return (savestr(cp)); 772 0 stevel *adid = 1; 773 0 stevel return (wp); 774 0 stevel 775 0 stevel default: 776 0 stevel wp = wbuf; 777 0 stevel i = BUFSIZ - 4; 778 0 stevel for (mp = cp; *mp; mp++) 779 0 stevel if (matchs(mp, lhsb)) { 780 559 nakanon for (np = cp; np < mp; ) 781 0 stevel *wp++ = *np++, --i; 782 0 stevel for (np = rhsb; *np; np++) switch (*np) { 783 0 stevel 784 0 stevel case '\\': 785 0 stevel if (np[1] == '&') 786 0 stevel np++; 787 0 stevel /* fall into ... */ 788 0 stevel 789 0 stevel default: 790 0 stevel if (--i < 0) 791 0 stevel goto ovflo; 792 0 stevel *wp++ = *np; 793 0 stevel continue; 794 0 stevel 795 0 stevel case '&': 796 0 stevel i -= strlen_(lhsb); 797 0 stevel if (i < 0) 798 0 stevel goto ovflo; 799 0 stevel *wp = 0; 800 0 stevel (void) strcat_(wp, lhsb); 801 0 stevel wp = strend(wp); 802 0 stevel continue; 803 0 stevel } 804 0 stevel mp += strlen_(lhsb); 805 0 stevel i -= strlen_(mp); 806 0 stevel if (i < 0) { 807 0 stevel ovflo: 808 0 stevel seterr("Subst buf ovflo"); 809 559 nakanon return (S_ /* "" */); 810 0 stevel } 811 0 stevel *wp = 0; 812 0 stevel (void) strcat_(wp, mp); 813 0 stevel *adid = 1; 814 0 stevel return (savestr(wbuf)); 815 0 stevel } 816 0 stevel return (savestr(cp)); 817 0 stevel } 818 0 stevel } 819 0 stevel 820 0 stevel tchar * 821 356 muffin domod(tchar *cp, int type) 822 0 stevel { 823 356 muffin tchar *wp, *xp; 824 356 muffin int c; 825 0 stevel 826 0 stevel #ifdef TRACE 827 0 stevel tprintf("TRACE- domod()\n"); 828 0 stevel #endif 829 0 stevel switch (type) { 830 0 stevel 831 0 stevel case 'x': 832 0 stevel case 'q': 833 0 stevel wp = savestr(cp); 834 0 stevel for (xp = wp; c = *xp; xp++) 835 0 stevel if (!issp(c) || type == 'q') 836 0 stevel *xp |= QUOTE; 837 0 stevel return (wp); 838 0 stevel 839 0 stevel case 'h': 840 0 stevel case 't': 841 0 stevel if (!any('/', cp)) 842 0 stevel return (type == 't' ? savestr(cp) : 0); 843 0 stevel wp = strend(cp); 844 0 stevel while (*--wp != '/') 845 0 stevel continue; 846 0 stevel if (type == 'h') 847 0 stevel xp = savestr(cp), xp[wp - cp] = 0; 848 0 stevel else 849 0 stevel xp = savestr(wp + 1); 850 0 stevel return (xp); 851 0 stevel 852 0 stevel case 'e': 853 0 stevel case 'r': 854 0 stevel wp = strend(cp); 855 0 stevel for (wp--; wp >= cp && *wp != '/'; wp--) 856 0 stevel if (*wp == '.') { 857 0 stevel if (type == 'e') 858 0 stevel xp = savestr(wp + 1); 859 0 stevel else 860 0 stevel xp = savestr(cp), xp[wp - cp] = 0; 861 0 stevel return (xp); 862 0 stevel } 863 559 nakanon return (savestr(type == 'e' ? S_ /* "" */ : cp)); 864 0 stevel } 865 0 stevel return (0); 866 0 stevel } 867 0 stevel 868 356 muffin int 869 356 muffin matchs(tchar *str, tchar *pat) 870 0 stevel { 871 0 stevel 872 0 stevel #ifdef TRACE 873 0 stevel tprintf("TRACE- matchs()\n"); 874 0 stevel #endif 875 0 stevel while (*str && *pat && *str == *pat) 876 0 stevel str++, pat++; 877 0 stevel return (*pat == 0); 878 0 stevel } 879 0 stevel 880 356 muffin int 881 356 muffin getsel(int *al, int *ar, int dol) 882 0 stevel { 883 356 muffin int c = getC(0); 884 356 muffin int i; 885 0 stevel bool first = *al < 0; 886 0 stevel 887 0 stevel #ifdef TRACE 888 0 stevel tprintf("TRACE- getsel()\n"); 889 0 stevel #endif 890 0 stevel switch (c) { 891 0 stevel 892 0 stevel case '%': 893 0 stevel if (quesarg == -1) 894 0 stevel goto bad; 895 0 stevel if (*al < 0) 896 0 stevel *al = quesarg; 897 0 stevel *ar = quesarg; 898 0 stevel break; 899 0 stevel 900 0 stevel case '-': 901 0 stevel if (*al < 0) { 902 0 stevel *al = 0; 903 0 stevel *ar = dol - 1; 904 0 stevel unreadc(c); 905 0 stevel } 906 0 stevel return (1); 907 0 stevel 908 0 stevel case '^': 909 0 stevel if (*al < 0) 910 0 stevel *al = 1; 911 0 stevel *ar = 1; 912 0 stevel break; 913 0 stevel 914 0 stevel case '$': 915 0 stevel if (*al < 0) 916 0 stevel *al = dol; 917 0 stevel *ar = dol; 918 0 stevel break; 919 0 stevel 920 0 stevel case '*': 921 0 stevel if (*al < 0) 922 0 stevel *al = 1; 923 0 stevel *ar = dol; 924 0 stevel if (*ar < *al) { 925 0 stevel *ar = 0; 926 0 stevel *al = 1; 927 0 stevel return (1); 928 0 stevel } 929 0 stevel break; 930 0 stevel 931 0 stevel default: 932 0 stevel if (digit(c)) { 933 0 stevel i = 0; 934 0 stevel while (digit(c)) { 935 0 stevel i = i * 10 + c - '0'; 936 0 stevel c = getC(0); 937 0 stevel } 938 0 stevel if (i < 0) 939 0 stevel i = dol + 1; 940 0 stevel if (*al < 0) 941 0 stevel *al = i; 942 0 stevel *ar = i; 943 0 stevel } else 944 0 stevel if (*al < 0) 945 0 stevel *al = 0, *ar = dol; 946 0 stevel else 947 0 stevel *ar = dol - 1; 948 0 stevel unreadc(c); 949 0 stevel break; 950 0 stevel } 951 0 stevel if (first) { 952 0 stevel c = getC(0); 953 0 stevel unreadc(c); 954 0 stevel /* if (any(c, "-$*")) */ /* char -> tchar */ 955 0 stevel if (c == '-' || c == '$' || c == '*') 956 0 stevel return (1); 957 0 stevel } 958 0 stevel if (*al > *ar || *ar > dol) { 959 0 stevel bad: 960 0 stevel seterr("Bad ! arg selector"); 961 0 stevel return (0); 962 0 stevel } 963 0 stevel return (1); 964 0 stevel 965 0 stevel } 966 0 stevel 967 0 stevel struct wordent * 968 356 muffin gethent(int sc) 969 0 stevel { 970 356 muffin struct Hist *hp; 971 356 muffin tchar *np; 972 356 muffin int c; 973 0 stevel int event; 974 0 stevel bool back = 0; 975 0 stevel 976 0 stevel #ifdef TRACE 977 0 stevel tprintf("TRACE- gethent()\n"); 978 0 stevel #endif 979 0 stevel c = sc == HISTSUB ? HIST : getC(0); 980 0 stevel if (c == HIST) { 981 0 stevel if (alhistp) 982 0 stevel return (alhistp); 983 0 stevel event = eventno; 984 0 stevel goto skip; 985 0 stevel } 986 0 stevel switch (c) { 987 0 stevel 988 0 stevel case ':': 989 0 stevel case '^': 990 0 stevel case '$': 991 0 stevel case '*': 992 0 stevel case '%': 993 0 stevel ungetC(c); 994 0 stevel if (lastev == eventno && alhistp) 995 0 stevel return (alhistp); 996 0 stevel event = lastev; 997 0 stevel break; 998 0 stevel 999 0 stevel case '-': 1000 0 stevel back = 1; 1001 0 stevel c = getC(0); 1002 0 stevel goto number; 1003 0 stevel 1004 0 stevel case '#': /* !# is command being typed in (mrh) */ 1005 559 nakanon return (¶ml); 1006 0 stevel 1007 0 stevel default: 1008 559 nakanon /* if (any(c, "(=~")) { */ 1009 0 stevel if (c == '(' || c == '=' || c == '~') { 1010 0 stevel unreadc(c); 1011 0 stevel ungetC(HIST); 1012 0 stevel return (0); 1013 0 stevel } 1014 0 stevel if (digit(c)) 1015 0 stevel goto number; 1016 0 stevel np = lhsb; 1017 0 stevel /* while (!any(c, ": \t\\\n}")) { */ 1018 0 stevel while (! (c == ':' || c == '\\' || isspnl(c) || c == '}')) { 1019 0 stevel if (np < &lhsb[(sizeof lhsb)/(sizeof lhsb[0]) - 2]) 1020 0 stevel *np++ = c; 1021 0 stevel c = getC(0); 1022 0 stevel } 1023 0 stevel unreadc(c); 1024 0 stevel if (np == lhsb) { 1025 0 stevel ungetC(HIST); 1026 0 stevel return (0); 1027 0 stevel } 1028 0 stevel *np++ = 0; 1029 0 stevel hp = findev(lhsb, 0); 1030 0 stevel if (hp) 1031 0 stevel lastev = hp->Hnum; 1032 0 stevel return (&hp->Hlex); 1033 0 stevel 1034 0 stevel case '?': 1035 0 stevel np = lhsb; 1036 0 stevel for (;;) { 1037 0 stevel c = getC(0); 1038 0 stevel if (c == '\n') { 1039 0 stevel unreadc(c); 1040 0 stevel break; 1041 0 stevel } 1042 0 stevel if (c == '?') 1043 0 stevel break; 1044 0 stevel if (np < &lhsb[(sizeof lhsb)/(sizeof lhsb[0]) - 2]) 1045 0 stevel *np++ = c; 1046 0 stevel } 1047 0 stevel if (np == lhsb) { 1048 0 stevel if (lhsb[0] == 0) { 1049 0 stevel seterr("No prev search"); 1050 0 stevel return (0); 1051 0 stevel } 1052 0 stevel } else 1053 0 stevel *np++ = 0; 1054 0 stevel hp = findev(lhsb, 1); 1055 0 stevel if (hp) 1056 0 stevel lastev = hp->Hnum; 1057 0 stevel return (&hp->Hlex); 1058 0 stevel 1059 0 stevel number: 1060 0 stevel event = 0; 1061 0 stevel while (digit(c)) { 1062 0 stevel event = event * 10 + c - '0'; 1063 0 stevel c = getC(0); 1064 0 stevel } 1065 0 stevel if (back) 1066 0 stevel event = eventno + (alhistp == 0) - (event ? event : 0); 1067 0 stevel unreadc(c); 1068 0 stevel break; 1069 0 stevel } 1070 0 stevel skip: 1071 0 stevel for (hp = Histlist.Hnext; hp; hp = hp->Hnext) 1072 0 stevel if (hp->Hnum == event) { 1073 0 stevel hp->Href = eventno; 1074 0 stevel lastev = hp->Hnum; 1075 0 stevel return (&hp->Hlex); 1076 0 stevel } 1077 0 stevel np = putn(event); 1078 0 stevel noev(np); 1079 0 stevel return (0); 1080 0 stevel } 1081 0 stevel 1082 0 stevel struct Hist * 1083 356 muffin findev(tchar *cp, bool anyarg) 1084 0 stevel { 1085 356 muffin struct Hist *hp; 1086 0 stevel 1087 0 stevel #ifdef TRACE 1088 0 stevel tprintf("TRACE- findev()\n"); 1089 0 stevel #endif 1090 0 stevel for (hp = Histlist.Hnext; hp; hp = hp->Hnext) { 1091 356 muffin tchar *dp; 1092 356 muffin tchar *p, *q; 1093 356 muffin struct wordent *lp = hp->Hlex.next; 1094 0 stevel int argno = 0; 1095 0 stevel 1096 0 stevel if (lp->word[0] == '\n') 1097 0 stevel continue; 1098 0 stevel if (!anyarg) { 1099 0 stevel p = cp; 1100 0 stevel q = lp->word; 1101 0 stevel do 1102 0 stevel if (!*p) 1103 0 stevel return (hp); 1104 0 stevel while (*p++ == *q++); 1105 0 stevel continue; 1106 0 stevel } 1107 0 stevel do { 1108 0 stevel for (dp = lp->word; *dp; dp++) { 1109 0 stevel p = cp; 1110 0 stevel q = dp; 1111 0 stevel do 1112 0 stevel if (!*p) { 1113 0 stevel quesarg = argno; 1114 0 stevel return (hp); 1115 0 stevel } 1116 0 stevel while (*p++ == *q++); 1117 0 stevel } 1118 0 stevel lp = lp->next; 1119 0 stevel argno++; 1120 0 stevel } while (lp->word[0] != '\n'); 1121 0 stevel } 1122 0 stevel noev(cp); 1123 0 stevel return (0); 1124 0 stevel } 1125 0 stevel 1126 356 muffin void 1127 356 muffin noev(tchar *cp) 1128 0 stevel { 1129 0 stevel 1130 0 stevel #ifdef TRACE 1131 0 stevel tprintf("TRACE- noev()\n"); 1132 0 stevel #endif 1133 0 stevel seterr2(cp, ": Event not found"); 1134 0 stevel } 1135 0 stevel 1136 356 muffin void 1137 356 muffin setexclp(tchar *cp) 1138 0 stevel { 1139 0 stevel 1140 0 stevel #ifdef TRACE 1141 0 stevel tprintf("TRACE- setexclp()\n"); 1142 0 stevel #endif 1143 0 stevel if (cp && cp[0] == '\n') 1144 0 stevel return; 1145 0 stevel exclp = cp; 1146 0 stevel } 1147 0 stevel 1148 356 muffin void 1149 356 muffin unreadc(tchar c) 1150 0 stevel { 1151 0 stevel 1152 0 stevel peekread = c; 1153 0 stevel } 1154 0 stevel 1155 356 muffin int 1156 356 muffin readc(bool wanteof) 1157 0 stevel { 1158 356 muffin int c; 1159 356 muffin static int sincereal; 1160 0 stevel 1161 0 stevel if (c = peekread) { 1162 0 stevel peekread = 0; 1163 0 stevel return (c); 1164 0 stevel } 1165 0 stevel top: 1166 0 stevel if (alvecp) { 1167 0 stevel if (c = *alvecp++) 1168 0 stevel return (c); 1169 0 stevel if (*alvec) { 1170 0 stevel alvecp = *alvec++; 1171 0 stevel return (' '); 1172 0 stevel } 1173 0 stevel } 1174 0 stevel if (alvec) { 1175 0 stevel if (alvecp = *alvec) { 1176 0 stevel alvec++; 1177 0 stevel goto top; 1178 0 stevel } 1179 0 stevel /* Infinite source! */ 1180 0 stevel return ('\n'); 1181 0 stevel } 1182 0 stevel if (evalp) { 1183 0 stevel if (c = *evalp++) 1184 0 stevel return (c); 1185 0 stevel if (*evalvec) { 1186 0 stevel evalp = *evalvec++; 1187 0 stevel return (' '); 1188 0 stevel } 1189 0 stevel evalp = 0; 1190 0 stevel } 1191 0 stevel if (evalvec) { 1192 0 stevel if (evalvec == (tchar **)1) { 1193 0 stevel doneinp = 1; 1194 0 stevel reset(); 1195 0 stevel } 1196 0 stevel if (evalp = *evalvec) { 1197 0 stevel evalvec++; 1198 0 stevel goto top; 1199 0 stevel } 1200 0 stevel evalvec = (tchar **)1; 1201 0 stevel return ('\n'); 1202 0 stevel } 1203 0 stevel do { 1204 0 stevel if (arginp == (tchar *) 1 || onelflg == 1) { 1205 0 stevel if (wanteof) 1206 0 stevel return (-1); 1207 0 stevel exitstat(); 1208 0 stevel } 1209 0 stevel if (arginp) { 1210 0 stevel if ((c = *arginp++) == 0) { 1211 0 stevel arginp = (tchar *) 1; 1212 0 stevel return ('\n'); 1213 0 stevel } 1214 0 stevel return (c); 1215 0 stevel } 1216 0 stevel reread: 1217 0 stevel c = bgetc(); 1218 0 stevel if (c < 0) { 1219 0 stevel struct sgttyb tty; 1220 0 stevel 1221 0 stevel if (wanteof) 1222 0 stevel return (-1); 1223 0 stevel /* was isatty but raw with ignoreeof yields problems */ 1224 0 stevel if (ioctl(SHIN, TIOCGETP, (char *)&tty) == 0 && 1225 0 stevel (tty.sg_flags & RAW) == 0) { 1226 0 stevel /* was 'short' for FILEC */ 1227 0 stevel int ctpgrp; 1228 0 stevel 1229 0 stevel if (++sincereal > 25) 1230 0 stevel goto oops; 1231 0 stevel if (tpgrp != -1 && 1232 559 nakanon ioctl(FSHTTY, TIOCGPGRP, (char *)&ctpgrp) == 0 && 1233 0 stevel tpgrp != ctpgrp) { 1234 0 stevel (void) ioctl(FSHTTY, TIOCSPGRP, 1235 559 nakanon (char *)&tpgrp); 1236 0 stevel (void) killpg(ctpgrp, SIGHUP); 1237 0 stevel printf("Reset tty pgrp from %d to %d\n", ctpgrp, tpgrp); 1238 0 stevel goto reread; 1239 0 stevel } 1240 559 nakanon if (adrof(S_ignoreeof /* "ignoreeof" */)) { 1241 0 stevel if (loginsh) 1242 559 nakanon printf("\nUse \"logout\" to logout.\n"); 1243 0 stevel else 1244 559 nakanon printf("\nUse \"exit\" to leave csh.\n"); 1245 0 stevel reset(); 1246 0 stevel } 1247 0 stevel if (chkstop == 0) { 1248 0 stevel panystop(1); 1249 0 stevel } 1250 0 stevel } 1251 0 stevel oops: 1252 0 stevel doneinp = 1; 1253 0 stevel reset(); 1254 0 stevel } 1255 0 stevel sincereal = 0; 1256 0 stevel if (c == '\n' && onelflg) 1257 0 stevel onelflg--; 1258 0 stevel } while (c == 0); 1259 0 stevel return (c); 1260 0 stevel } 1261 0 stevel 1262 559 nakanon static void 1263 559 nakanon expand_fbuf(void) 1264 559 nakanon { 1265 559 nakanon tchar **nfbuf = 1266 559 nakanon (tchar **)xcalloc((unsigned)(fblocks + 2), sizeof (tchar **)); 1267 559 nakanon 1268 559 nakanon if (fbuf) { 1269 559 nakanon (void) blkcpy(nfbuf, fbuf); 1270 559 nakanon xfree((char *)fbuf); 1271 559 nakanon } 1272 559 nakanon fbuf = nfbuf; 1273 559 nakanon fbuf[fblocks] = (tchar *)xcalloc(BUFSIZ + MB_LEN_MAX, 1274 559 nakanon sizeof (tchar)); 1275 559 nakanon fblocks++; 1276 559 nakanon } 1277 559 nakanon 1278 356 muffin int 1279 356 muffin bgetc(void) 1280 0 stevel { 1281 356 muffin int buf, off, c; 1282 0 stevel #ifdef FILEC 1283 559 nakanon tchar ttyline[BUFSIZ + MB_LEN_MAX]; /* read_() can return extra bytes */ 1284 559 nakanon int roomleft; 1285 0 stevel #endif 1286 0 stevel 1287 0 stevel #ifdef TELL 1288 0 stevel if (cantell) { 1289 0 stevel if (fseekp < fbobp || fseekp > feobp) { 1290 0 stevel fbobp = feobp = fseekp; 1291 0 stevel (void) lseek(SHIN, fseekp, 0); 1292 0 stevel } 1293 0 stevel if (fseekp == feobp) { 1294 0 stevel fbobp = feobp; 1295 0 stevel do 1296 0 stevel c = read_(SHIN, fbuf[0], BUFSIZ); 1297 0 stevel while (c < 0 && errno == EINTR); 1298 0 stevel if (c <= 0) 1299 0 stevel return (-1); 1300 0 stevel feobp += c; 1301 0 stevel } 1302 0 stevel c = fbuf[0][fseekp - fbobp]; 1303 0 stevel fseekp++; 1304 0 stevel return (c); 1305 0 stevel } 1306 0 stevel #endif 1307 0 stevel again: 1308 559 nakanon buf = (int)fseekp / BUFSIZ; 1309 0 stevel if (buf >= fblocks) { 1310 559 nakanon expand_fbuf(); 1311 0 stevel goto again; 1312 0 stevel } 1313 0 stevel if (fseekp >= feobp) { 1314 559 nakanon buf = (int)feobp / BUFSIZ; 1315 559 nakanon off = (int)feobp % BUFSIZ; 1316 0 stevel #ifndef FILEC 1317 0 stevel for (;;) { 1318 0 stevel c = read_(SHIN, fbuf[buf] + off, BUFSIZ - off); 1319 0 stevel #else 1320 0 stevel roomleft = BUFSIZ - off; 1321 0 stevel for (;;) { 1322 0 stevel if (filec && intty) { 1323 559 nakanon c = tenex(ttyline, BUFSIZ); 1324 0 stevel if (c > roomleft) { 1325 559 nakanon expand_fbuf(); 1326 559 nakanon copy(fbuf[buf] + off, ttyline, 1327 559 nakanon roomleft * sizeof (tchar)); 1328 559 nakanon copy(fbuf[buf + 1], ttyline + roomleft, 1329 559 nakanon (c - roomleft) * sizeof (tchar)); 1330 559 nakanon } else if (c > 0) { 1331 559 nakanon copy(fbuf[buf] + off, ttyline, 1332 559 nakanon c * sizeof (tchar)); 1333 0 stevel } 1334 559 nakanon } else { 1335 0 stevel c = read_(SHIN, fbuf[buf] + off, roomleft); 1336 559 nakanon if (c > roomleft) { 1337 559 nakanon expand_fbuf(); 1338 559 nakanon copy(fbuf[buf + 1], 1339 559 nakanon fbuf[buf] + off + roomleft, 1340 559 nakanon (c - roomleft) * sizeof (tchar)); 1341 559 nakanon } 1342 559 nakanon } 1343 0 stevel #endif 1344 0 stevel if (c >= 0) 1345 0 stevel break; 1346 0 stevel if (errno == EWOULDBLOCK) { 1347 0 stevel int off = 0; 1348 0 stevel 1349 0 stevel (void) ioctl(SHIN, FIONBIO, (char *)&off); 1350 0 stevel } else if (errno != EINTR) 1351 0 stevel break; 1352 0 stevel } 1353 0 stevel if (c <= 0) 1354 0 stevel return (-1); 1355 0 stevel feobp += c; 1356 0 stevel #ifndef FILEC 1357 0 stevel goto again; 1358 0 stevel #else 1359 0 stevel if (filec && !intty) 1360 0 stevel goto again; 1361 0 stevel #endif 1362 0 stevel } 1363 559 nakanon c = fbuf[buf][(int)fseekp % BUFSIZ]; 1364 0 stevel fseekp++; 1365 0 stevel return (c); 1366 0 stevel } 1367 0 stevel 1368 559 nakanon void 1369 356 muffin bfree(void) 1370 0 stevel { 1371 356 muffin int sb, i; 1372 0 stevel 1373 0 stevel #ifdef TELL 1374 0 stevel if (cantell) 1375 0 stevel return; 1376 0 stevel #endif 1377 0 stevel if (whyles) 1378 0 stevel return; 1379 559 nakanon sb = (int)(fseekp - 1) / BUFSIZ; 1380 0 stevel if (sb > 0) { 1381 0 stevel for (i = 0; i < sb; i++) 1382 0 stevel xfree(fbuf[i]); 1383 0 stevel (void) blkcpy(fbuf, &fbuf[sb]); 1384 0 stevel fseekp -= BUFSIZ * sb; 1385 0 stevel feobp -= BUFSIZ * sb; 1386 0 stevel fblocks -= sb; 1387 0 stevel } 1388 0 stevel } 1389 0 stevel 1390 356 muffin void 1391 356 muffin bseek(off_t l) 1392 0 stevel { 1393 356 muffin struct whyle *wp; 1394 0 stevel 1395 0 stevel fseekp = l; 1396 0 stevel #ifdef TELL 1397 0 stevel if (!cantell) { 1398 0 stevel #endif 1399 0 stevel if (!whyles) 1400 0 stevel return; 1401 0 stevel for (wp = whyles; wp->w_next; wp = wp->w_next) 1402 0 stevel continue; 1403 0 stevel if (wp->w_start > l) 1404 0 stevel l = wp->w_start; 1405 0 stevel #ifdef TELL 1406 0 stevel } 1407 0 stevel #endif 1408 0 stevel } 1409 0 stevel 1410 0 stevel /* any similarity to bell telephone is purely accidental */ 1411 0 stevel #ifndef btell 1412 0 stevel off_t 1413 356 muffin btell(void) 1414 0 stevel { 1415 0 stevel 1416 0 stevel return (fseekp); 1417 0 stevel } 1418 0 stevel #endif 1419 0 stevel 1420 356 muffin void 1421 356 muffin btoeof(void) 1422 0 stevel { 1423 0 stevel 1424 0 stevel (void) lseek(SHIN, (off_t)0, 2); 1425 0 stevel fseekp = feobp; 1426 0 stevel wfree(); 1427 0 stevel bfree(); 1428 0 stevel } 1429 0 stevel 1430 0 stevel #ifdef TELL 1431 356 muffin void 1432 356 muffin settell(void) 1433 0 stevel { 1434 0 stevel 1435 0 stevel cantell = 0; 1436 0 stevel if (arginp || onelflg || intty) 1437 0 stevel return; 1438 0 stevel if (lseek(SHIN, (off_t)0, 1) < 0 || errno == ESPIPE) 1439 0 stevel return; 1440 559 nakanon fbuf = (tchar **)xcalloc(2, sizeof (tchar **)); 1441 0 stevel fblocks = 1; 1442 559 nakanon fbuf[0] = (tchar *)xcalloc(BUFSIZ + MB_LEN_MAX, sizeof (tchar)); 1443 0 stevel fseekp = fbobp = feobp = lseek(SHIN, (off_t)0, 1); 1444 0 stevel cantell = 1; 1445 0 stevel } 1446 0 stevel #endif 1447