1316958Sdchagin/* $Header: /p/tcsh/cvsroot/tcsh/sh.set.c,v 3.89 2015/09/08 15:49:53 christos Exp $ */ 259243Sobrien/* 359243Sobrien * sh.set.c: Setting and Clearing of variables 459243Sobrien */ 559243Sobrien/*- 659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California. 759243Sobrien * All rights reserved. 859243Sobrien * 959243Sobrien * Redistribution and use in source and binary forms, with or without 1059243Sobrien * modification, are permitted provided that the following conditions 1159243Sobrien * are met: 1259243Sobrien * 1. Redistributions of source code must retain the above copyright 1359243Sobrien * notice, this list of conditions and the following disclaimer. 1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1559243Sobrien * notice, this list of conditions and the following disclaimer in the 1659243Sobrien * documentation and/or other materials provided with the distribution. 17100616Smp * 3. Neither the name of the University nor the names of its contributors 1859243Sobrien * may be used to endorse or promote products derived from this software 1959243Sobrien * without specific prior written permission. 2059243Sobrien * 2159243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2459243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3159243Sobrien * SUCH DAMAGE. 3259243Sobrien */ 3359243Sobrien#include "sh.h" 3459243Sobrien 35316958SdchaginRCSID("$tcsh: sh.set.c,v 3.89 2015/09/08 15:49:53 christos Exp $") 3659243Sobrien 3759243Sobrien#include "ed.h" 3859243Sobrien#include "tw.h" 3959243Sobrien 40145479Smp#ifdef HAVE_NL_LANGINFO 41145479Smp#include <langinfo.h> 42145479Smp#endif 43145479Smp 44145479Smpextern int GotTermCaps; 45131962Smpint numeof = 0; 4659243Sobrien 47167465Smpstatic void update_vars (Char *); 48167465Smpstatic Char *getinx (Char *, int *); 49167465Smpstatic void asx (Char *, int, Char *); 50167465Smpstatic struct varent *getvx (Char *, int); 51167465Smpstatic Char *xset (Char *, Char ***); 52167465Smpstatic Char *operate (int, Char *, Char *); 53231990Smpstatic void putn1 (tcsh_number_t); 54167465Smpstatic struct varent *madrof (Char *, struct varent *); 55167465Smpstatic void unsetv1 (struct varent *); 56167465Smpstatic void exportpath (Char **); 57167465Smpstatic void balance (struct varent *, int, int); 58316958Sdchaginstatic int set_noclobber (Char **); 5959243Sobrien 6059243Sobrien/* 6159243Sobrien * C Shell 6259243Sobrien */ 6359243Sobrien 6459243Sobrienstatic void 65167465Smpupdate_vars(Char *vp) 6659243Sobrien{ 6759243Sobrien if (eq(vp, STRpath)) { 68167465Smp struct varent *p = adrof(STRpath); 69167465Smp if (p == NULL) 70167465Smp stderror(ERR_NAME | ERR_UNDVAR); 71167465Smp else { 72167465Smp exportpath(p->vec); 73167465Smp dohash(NULL, NULL); 74167465Smp } 7559243Sobrien } 76316958Sdchagin else if (eq(vp, STRnoclobber)) { 77316958Sdchagin struct varent *p = adrof(STRnoclobber); 78316958Sdchagin if (p == NULL) 79316958Sdchagin stderror(ERR_NAME | ERR_UNDVAR); 80316958Sdchagin else 81316958Sdchagin no_clobber = set_noclobber(p->vec); 82316958Sdchagin } 8359243Sobrien else if (eq(vp, STRhistchars)) { 84145479Smp Char *pn = varval(vp); 8559243Sobrien 8659243Sobrien HIST = *pn++; 87231990Smp if (HIST) 88231990Smp HISTSUB = *pn; 89231990Smp else 90231990Smp HISTSUB = HIST; 9159243Sobrien } 9259243Sobrien else if (eq(vp, STRpromptchars)) { 93145479Smp Char *pn = varval(vp); 9459243Sobrien 9559243Sobrien PRCH = *pn++; 96231990Smp if (PRCH) 97231990Smp PRCHROOT = *pn; 98231990Smp else 99231990Smp PRCHROOT = PRCH; 10059243Sobrien } 10159243Sobrien else if (eq(vp, STRhistlit)) { 10259243Sobrien HistLit = 1; 10359243Sobrien } 10459243Sobrien else if (eq(vp, STRuser)) { 10559243Sobrien tsetenv(STRKUSER, varval(vp)); 10659243Sobrien tsetenv(STRLOGNAME, varval(vp)); 10759243Sobrien } 10859243Sobrien else if (eq(vp, STRgroup)) { 10959243Sobrien tsetenv(STRKGROUP, varval(vp)); 11059243Sobrien } 11159243Sobrien else if (eq(vp, STRwordchars)) { 11259243Sobrien word_chars = varval(vp); 11359243Sobrien } 11459243Sobrien else if (eq(vp, STRloginsh)) { 11559243Sobrien loginsh = 1; 11659243Sobrien } 117231990Smp else if (eq(vp, STRanyerror)) { 118231990Smp anyerror = 1; 119231990Smp } 12059243Sobrien else if (eq(vp, STRsymlinks)) { 121145479Smp Char *pn = varval(vp); 12259243Sobrien 12359243Sobrien if (eq(pn, STRignore)) 12459243Sobrien symlinks = SYM_IGNORE; 12559243Sobrien else if (eq(pn, STRexpand)) 12659243Sobrien symlinks = SYM_EXPAND; 12759243Sobrien else if (eq(pn, STRchase)) 12859243Sobrien symlinks = SYM_CHASE; 12959243Sobrien else 13059243Sobrien symlinks = 0; 13159243Sobrien } 13259243Sobrien else if (eq(vp, STRterm)) { 13359243Sobrien Char *cp = varval(vp); 13459243Sobrien tsetenv(STRKTERM, cp); 13559243Sobrien#ifdef DOESNT_WORK_RIGHT 13659243Sobrien cp = getenv("TERMCAP"); 13759243Sobrien if (cp && (*cp != '/')) /* if TERMCAP and not a path */ 13859243Sobrien Unsetenv(STRTERMCAP); 13959243Sobrien#endif /* DOESNT_WORK_RIGHT */ 14059243Sobrien GotTermCaps = 0; 14159243Sobrien if (noediting && Strcmp(cp, STRnetwork) != 0 && 14259243Sobrien Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) { 14359243Sobrien editing = 1; 14459243Sobrien noediting = 0; 145167465Smp setNS(STRedit); 14659243Sobrien } 14759243Sobrien ed_Init(); /* reset the editor */ 14859243Sobrien } 14959243Sobrien else if (eq(vp, STRhome)) { 150167465Smp Char *cp, *canon; 15159243Sobrien 15259243Sobrien cp = Strsave(varval(vp)); /* get the old value back */ 153167465Smp cleanup_push(cp, xfree); 15459243Sobrien 15559243Sobrien /* 15659243Sobrien * convert to cononical pathname (possibly resolving symlinks) 15759243Sobrien */ 158167465Smp canon = dcanon(cp, cp); 159167465Smp cleanup_ignore(cp); 160167465Smp cleanup_until(cp); 161167465Smp cleanup_push(canon, xfree); 16259243Sobrien 163167465Smp setcopy(vp, canon, VAR_READWRITE); /* have to save the new val */ 16459243Sobrien 16559243Sobrien /* and now mirror home with HOME */ 166167465Smp tsetenv(STRKHOME, canon); 16759243Sobrien /* fix directory stack for new tilde home */ 16859243Sobrien dtilde(); 169167465Smp cleanup_until(canon); 17059243Sobrien } 17159243Sobrien else if (eq(vp, STRedit)) { 17259243Sobrien editing = 1; 17359243Sobrien noediting = 0; 17459243Sobrien /* PWP: add more stuff in here later */ 17559243Sobrien } 176316958Sdchagin else if (eq(vp, STRvimode)) { 177316958Sdchagin VImode = 1; 178316958Sdchagin update_wordchars(); 179316958Sdchagin } 18059243Sobrien else if (eq(vp, STRshlvl)) { 18159243Sobrien tsetenv(STRKSHLVL, varval(vp)); 18259243Sobrien } 183131962Smp else if (eq(vp, STRignoreeof)) { 184131962Smp Char *cp; 185131962Smp numeof = 0; 186131962Smp for ((cp = varval(STRignoreeof)); cp && *cp; cp++) { 187131962Smp if (!Isdigit(*cp)) { 188131962Smp numeof = 0; 189131962Smp break; 190131962Smp } 191131962Smp numeof = numeof * 10 + *cp - '0'; 192131962Smp } 193131962Smp if (numeof <= 0) numeof = 26; /* Sanity check */ 194131962Smp } 19559243Sobrien else if (eq(vp, STRbackslash_quote)) { 19659243Sobrien bslash_quote = 1; 19759243Sobrien } 198195609Smp else if (eq(vp, STRcompat_expr)) { 199195609Smp compat_expr = 1; 200195609Smp } 20159243Sobrien else if (eq(vp, STRdirstack)) { 20259243Sobrien dsetstack(); 20359243Sobrien } 20459243Sobrien else if (eq(vp, STRrecognize_only_executables)) { 20559243Sobrien tw_cmd_free(); 20659243Sobrien } 20783098Smp else if (eq(vp, STRkillring)) { 208231990Smp SetKillRing((int)getn(varval(vp))); 20983098Smp } 210316958Sdchagin else if (eq(vp, STRhistory)) { 211316958Sdchagin sethistory((int)getn(varval(vp))); 212316958Sdchagin } 21359243Sobrien#ifndef HAVENOUTMP 21459243Sobrien else if (eq(vp, STRwatch)) { 21559243Sobrien resetwatch(); 21659243Sobrien } 21759243Sobrien#endif /* HAVENOUTMP */ 21859243Sobrien else if (eq(vp, STRimplicitcd)) { 21959243Sobrien implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1); 22059243Sobrien } 221316958Sdchagin else if (eq(vp, STRcdtohome)) { 222316958Sdchagin cdtohome = 1; 223316958Sdchagin } 22459243Sobrien#ifdef COLOR_LS_F 22559243Sobrien else if (eq(vp, STRcolor)) { 22659243Sobrien set_color_context(); 22759243Sobrien } 22859243Sobrien#endif /* COLOR_LS_F */ 22959243Sobrien#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) 23059243Sobrien else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) { 23159243Sobrien update_dspmbyte_vars(); 23259243Sobrien } 23359243Sobrien#endif 23469408Sache#ifdef NLS_CATALOGS 23569408Sache else if (eq(vp, STRcatalog)) { 236145479Smp nlsclose(); 23769408Sache nlsinit(); 23869408Sache } 239100616Smp#if defined(FILEC) && defined(TIOCSTI) 240100616Smp else if (eq(vp, STRfilec)) 241100616Smp filec = 1; 242100616Smp#endif 24369408Sache#endif /* NLS_CATALOGS */ 24459243Sobrien} 24559243Sobrien 24659243Sobrien 24759243Sobrien/*ARGSUSED*/ 24859243Sobrienvoid 249167465Smpdoset(Char **v, struct command *c) 25059243Sobrien{ 251145479Smp Char *p; 252231990Smp Char *vp; 25359243Sobrien Char **vecp; 254145479Smp int hadsub; 25559243Sobrien int subscr; 25659243Sobrien int flags = VAR_READWRITE; 257145479Smp int first_match = 0; 258145479Smp int last_match = 0; 259145479Smp int changed = 0; 26059243Sobrien 26159243Sobrien USE(c); 26259243Sobrien v++; 26359243Sobrien do { 26459243Sobrien changed = 0; 26559243Sobrien /* 26659243Sobrien * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov> 26759243Sobrien */ 26859243Sobrien if (*v && eq(*v, STRmr)) { 26959243Sobrien flags = VAR_READONLY; 27059243Sobrien v++; 27159243Sobrien changed = 1; 27259243Sobrien } 27359243Sobrien if (*v && eq(*v, STRmf) && !last_match) { 27459243Sobrien first_match = 1; 27559243Sobrien v++; 27659243Sobrien changed = 1; 27759243Sobrien } 27859243Sobrien if (*v && eq(*v, STRml) && !first_match) { 27959243Sobrien last_match = 1; 28059243Sobrien v++; 28159243Sobrien changed = 1; 28259243Sobrien } 28359243Sobrien } while(changed); 28459243Sobrien p = *v++; 28559243Sobrien if (p == 0) { 28659243Sobrien plist(&shvhed, flags); 28759243Sobrien return; 28859243Sobrien } 28959243Sobrien do { 29059243Sobrien hadsub = 0; 29159243Sobrien vp = p; 292231990Smp if (!letter(*p)) 29359243Sobrien stderror(ERR_NAME | ERR_VARBEGIN); 294231990Smp do { 295231990Smp p++; 296231990Smp } while (alnum(*p)); 29759243Sobrien if (*p == '[') { 29859243Sobrien hadsub++; 29959243Sobrien p = getinx(p, &subscr); 30059243Sobrien } 301231990Smp if (*p != '\0' && *p != '=') 302231990Smp stderror(ERR_NAME | ERR_VARALNUM); 303231990Smp if (*p == '=') { 304231990Smp *p++ = '\0'; 305231990Smp if (*p == '\0' && *v != NULL && **v == '(') 30659243Sobrien p = *v++; 30759243Sobrien } 30859243Sobrien else if (*v && eq(*v, STRequal)) { 309231990Smp if (*++v != NULL) 31059243Sobrien p = *v++; 31159243Sobrien } 31259243Sobrien if (eq(p, STRLparen)) { 313145479Smp Char **e = v; 31459243Sobrien 31559243Sobrien if (hadsub) 31659243Sobrien stderror(ERR_NAME | ERR_SYNTAX); 31759243Sobrien for (;;) { 31859243Sobrien if (!*e) 31959243Sobrien stderror(ERR_NAME | ERR_MISSING, ')'); 32059243Sobrien if (**e == ')') 32159243Sobrien break; 32259243Sobrien e++; 32359243Sobrien } 32459243Sobrien p = *e; 32559243Sobrien *e = 0; 32659243Sobrien vecp = saveblk(v); 32759243Sobrien if (first_match) 32859243Sobrien flags |= VAR_FIRST; 32959243Sobrien else if (last_match) 33059243Sobrien flags |= VAR_LAST; 33159243Sobrien 33259243Sobrien set1(vp, vecp, &shvhed, flags); 33359243Sobrien *e = p; 33459243Sobrien v = e + 1; 33559243Sobrien } 336167465Smp else if (hadsub) { 337167465Smp Char *copy; 338167465Smp 339167465Smp copy = Strsave(p); 340167465Smp cleanup_push(copy, xfree); 341167465Smp asx(vp, subscr, copy); 342167465Smp cleanup_ignore(copy); 343167465Smp cleanup_until(copy); 344167465Smp } 34559243Sobrien else 346167465Smp setv(vp, Strsave(p), flags); 34759243Sobrien update_vars(vp); 34859243Sobrien } while ((p = *v++) != NULL); 34959243Sobrien} 35059243Sobrien 35159243Sobrienstatic Char * 352167465Smpgetinx(Char *cp, int *ip) 35359243Sobrien{ 35459243Sobrien *ip = 0; 35559243Sobrien *cp++ = 0; 35659243Sobrien while (*cp && Isdigit(*cp)) 35759243Sobrien *ip = *ip * 10 + *cp++ - '0'; 35859243Sobrien if (*cp++ != ']') 35959243Sobrien stderror(ERR_NAME | ERR_SUBSCRIPT); 36059243Sobrien return (cp); 36159243Sobrien} 36259243Sobrien 36359243Sobrienstatic void 364167465Smpasx(Char *vp, int subscr, Char *p) 36559243Sobrien{ 366145479Smp struct varent *v = getvx(vp, subscr); 367167465Smp Char *prev; 36859243Sobrien 36959243Sobrien if (v->v_flags & VAR_READONLY) 37059243Sobrien stderror(ERR_READONLY|ERR_NAME, v->v_name); 371167465Smp prev = v->vec[subscr - 1]; 372167465Smp cleanup_push(prev, xfree); 37359243Sobrien v->vec[subscr - 1] = globone(p, G_APPEND); 374167465Smp cleanup_until(prev); 37559243Sobrien} 37659243Sobrien 37759243Sobrienstatic struct varent * 378167465Smpgetvx(Char *vp, int subscr) 37959243Sobrien{ 380145479Smp struct varent *v = adrof(vp); 38159243Sobrien 38259243Sobrien if (v == 0) 38359243Sobrien udvar(vp); 38459243Sobrien if (subscr < 1 || subscr > blklen(v->vec)) 38559243Sobrien stderror(ERR_NAME | ERR_RANGE); 38659243Sobrien return (v); 38759243Sobrien} 38859243Sobrien 38959243Sobrien/*ARGSUSED*/ 39059243Sobrienvoid 391167465Smpdolet(Char **v, struct command *dummy) 39259243Sobrien{ 393145479Smp Char *p; 39459243Sobrien Char *vp, c, op; 395145479Smp int hadsub; 39659243Sobrien int subscr; 39759243Sobrien 39859243Sobrien USE(dummy); 39959243Sobrien v++; 40059243Sobrien p = *v++; 40159243Sobrien if (p == 0) { 40259243Sobrien prvars(); 40359243Sobrien return; 40459243Sobrien } 40559243Sobrien do { 40659243Sobrien hadsub = 0; 40759243Sobrien vp = p; 40859243Sobrien if (letter(*p)) 40959243Sobrien for (; alnum(*p); p++) 41059243Sobrien continue; 41159243Sobrien if (vp == p || !letter(*vp)) 41259243Sobrien stderror(ERR_NAME | ERR_VARBEGIN); 41359243Sobrien if (*p == '[') { 41459243Sobrien hadsub++; 41559243Sobrien p = getinx(p, &subscr); 41659243Sobrien } 41759243Sobrien if (*p == 0 && *v) 41859243Sobrien p = *v++; 41959243Sobrien if ((op = *p) != 0) 42059243Sobrien *p++ = 0; 42159243Sobrien else 42259243Sobrien stderror(ERR_NAME | ERR_ASSIGN); 42359243Sobrien 42459243Sobrien /* 42559243Sobrien * if there is no expression after the '=' then print a "Syntax Error" 42659243Sobrien * message - strike 42759243Sobrien */ 42859243Sobrien if (*p == '\0' && *v == NULL) 42959243Sobrien stderror(ERR_NAME | ERR_ASSIGN); 43059243Sobrien 43159243Sobrien vp = Strsave(vp); 432167465Smp cleanup_push(vp, xfree); 43359243Sobrien if (op == '=') { 43459243Sobrien c = '='; 43559243Sobrien p = xset(p, &v); 43659243Sobrien } 43759243Sobrien else { 43859243Sobrien c = *p++; 43959243Sobrien if (any("+-", c)) { 44059243Sobrien if (c != op || *p) 44159243Sobrien stderror(ERR_NAME | ERR_UNKNOWNOP); 44259243Sobrien p = Strsave(STR1); 44359243Sobrien } 44459243Sobrien else { 44559243Sobrien if (any("<>", op)) { 44659243Sobrien if (c != op) 44759243Sobrien stderror(ERR_NAME | ERR_UNKNOWNOP); 44859243Sobrien stderror(ERR_NAME | ERR_SYNTAX); 44959243Sobrien } 45059243Sobrien if (c != '=') 45159243Sobrien stderror(ERR_NAME | ERR_UNKNOWNOP); 45259243Sobrien p = xset(p, &v); 45359243Sobrien } 45459243Sobrien } 455167465Smp cleanup_push(p, xfree); 45659243Sobrien if (op == '=') { 45759243Sobrien if (hadsub) 45859243Sobrien asx(vp, subscr, p); 45959243Sobrien else 460167465Smp setv(vp, p, VAR_READWRITE); 461167465Smp cleanup_ignore(p); 46259243Sobrien } 46359243Sobrien else if (hadsub) { 46459243Sobrien struct varent *gv = getvx(vp, subscr); 465167465Smp Char *val; 46659243Sobrien 467167465Smp val = operate(op, gv->vec[subscr - 1], p); 468167465Smp cleanup_push(val, xfree); 469167465Smp asx(vp, subscr, val); 470167465Smp cleanup_ignore(val); 471167465Smp cleanup_until(val); 47259243Sobrien } 473167465Smp else { 474167465Smp Char *val; 475167465Smp 476167465Smp val = operate(op, varval(vp), p); 477167465Smp cleanup_push(val, xfree); 478167465Smp setv(vp, val, VAR_READWRITE); 479167465Smp cleanup_ignore(val); 480167465Smp cleanup_until(val); 481167465Smp } 48259243Sobrien update_vars(vp); 483167465Smp cleanup_until(vp); 48459243Sobrien } while ((p = *v++) != NULL); 48559243Sobrien} 48659243Sobrien 48759243Sobrienstatic Char * 488167465Smpxset(Char *cp, Char ***vp) 48959243Sobrien{ 490145479Smp Char *dp; 49159243Sobrien 49259243Sobrien if (*cp) { 49359243Sobrien dp = Strsave(cp); 49459243Sobrien --(*vp); 495167465Smp xfree(** vp); 49659243Sobrien **vp = dp; 49759243Sobrien } 49859243Sobrien return (putn(expr(vp))); 49959243Sobrien} 50059243Sobrien 50159243Sobrienstatic Char * 502167465Smpoperate(int op, Char *vp, Char *p) 50359243Sobrien{ 50459243Sobrien Char opr[2]; 50559243Sobrien Char *vec[5]; 506145479Smp Char **v = vec; 50759243Sobrien Char **vecp = v; 508231990Smp tcsh_number_t i; 50959243Sobrien 51059243Sobrien if (op != '=') { 51159243Sobrien if (*vp) 51259243Sobrien *v++ = vp; 513167465Smp opr[0] = op; 51459243Sobrien opr[1] = 0; 51559243Sobrien *v++ = opr; 51659243Sobrien if (op == '<' || op == '>') 51759243Sobrien *v++ = opr; 51859243Sobrien } 51959243Sobrien *v++ = p; 52059243Sobrien *v++ = 0; 52159243Sobrien i = expr(&vecp); 52259243Sobrien if (*vecp) 52359243Sobrien stderror(ERR_NAME | ERR_EXPRESSION); 52459243Sobrien return (putn(i)); 52559243Sobrien} 52659243Sobrien 527167465Smpstatic Char *putp; 52859243Sobrien 529231990SmpChar * 530231990Smpputn(tcsh_number_t n) 53159243Sobrien{ 532231990Smp Char nbuf[1024]; /* Enough even for octal */ 53359243Sobrien 53459243Sobrien putp = nbuf; 53559243Sobrien if (n < 0) { 53659243Sobrien n = -n; 53759243Sobrien *putp++ = '-'; 53859243Sobrien } 53959243Sobrien putn1(n); 54059243Sobrien *putp = 0; 54159243Sobrien return (Strsave(nbuf)); 54259243Sobrien} 54359243Sobrien 54459243Sobrienstatic void 545231990Smpputn1(tcsh_number_t n) 54659243Sobrien{ 54759243Sobrien if (n > 9) 54859243Sobrien putn1(n / 10); 549231990Smp *putp++ = (Char)(n % 10 + '0'); 55059243Sobrien} 55159243Sobrien 552231990Smptcsh_number_t 553231990Smpgetn(const Char *cp) 55459243Sobrien{ 555231990Smp tcsh_number_t n; 55659243Sobrien int sign; 557195609Smp int base; 55859243Sobrien 55959243Sobrien if (!cp) /* PWP: extra error checking */ 56059243Sobrien stderror(ERR_NAME | ERR_BADNUM); 56159243Sobrien 56259243Sobrien sign = 0; 56359243Sobrien if (cp[0] == '+' && cp[1]) 56459243Sobrien cp++; 56559243Sobrien if (*cp == '-') { 56659243Sobrien sign++; 56759243Sobrien cp++; 56859243Sobrien if (!Isdigit(*cp)) 56959243Sobrien stderror(ERR_NAME | ERR_BADNUM); 57059243Sobrien } 571195609Smp 572231990Smp if (cp[0] == '0' && cp[1] && is_set(STRparseoctal)) 573195609Smp base = 8; 574195609Smp else 575195609Smp base = 10; 576195609Smp 57759243Sobrien n = 0; 57859243Sobrien while (Isdigit(*cp)) 579195609Smp { 580195609Smp if (base == 8 && *cp >= '8') 581195609Smp stderror(ERR_NAME | ERR_BADNUM); 582195609Smp n = n * base + *cp++ - '0'; 583195609Smp } 58459243Sobrien if (*cp) 58559243Sobrien stderror(ERR_NAME | ERR_BADNUM); 58659243Sobrien return (sign ? -n : n); 58759243Sobrien} 58859243Sobrien 58959243SobrienChar * 590167465Smpvalue1(Char *var, struct varent *head) 59159243Sobrien{ 592145479Smp struct varent *vp; 59359243Sobrien 59459243Sobrien if (!var || !head) /* PWP: extra error checking */ 59559243Sobrien return (STRNULL); 59659243Sobrien 59759243Sobrien vp = adrof1(var, head); 598100616Smp return ((vp == NULL || vp->vec == NULL || vp->vec[0] == NULL) ? 599100616Smp STRNULL : vp->vec[0]); 60059243Sobrien} 60159243Sobrien 60259243Sobrienstatic struct varent * 603167465Smpmadrof(Char *pat, struct varent *vp) 60459243Sobrien{ 605145479Smp struct varent *vp1; 60659243Sobrien 60759243Sobrien for (vp = vp->v_left; vp; vp = vp->v_right) { 60859243Sobrien if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL) 60959243Sobrien return vp1; 61059243Sobrien if (Gmatch(vp->v_name, pat)) 61159243Sobrien return vp; 61259243Sobrien } 61359243Sobrien return vp; 61459243Sobrien} 61559243Sobrien 61659243Sobrienstruct varent * 617167465Smpadrof1(const Char *name, struct varent *v) 61859243Sobrien{ 61959243Sobrien int cmp; 62059243Sobrien 62159243Sobrien v = v->v_left; 62259243Sobrien while (v && ((cmp = *name - *v->v_name) != 0 || 62359243Sobrien (cmp = Strcmp(name, v->v_name)) != 0)) 62459243Sobrien if (cmp < 0) 62559243Sobrien v = v->v_left; 62659243Sobrien else 62759243Sobrien v = v->v_right; 62859243Sobrien return v; 62959243Sobrien} 63059243Sobrien 631167465Smpvoid 632167465Smpsetcopy(const Char *var, const Char *val, int flags) 633167465Smp{ 634167465Smp Char *copy; 635167465Smp 636167465Smp copy = Strsave(val); 637167465Smp cleanup_push(copy, xfree); 638167465Smp setv(var, copy, flags); 639167465Smp cleanup_ignore(copy); 640167465Smp cleanup_until(copy); 641167465Smp} 642167465Smp 64359243Sobrien/* 64459243Sobrien * The caller is responsible for putting value in a safe place 64559243Sobrien */ 64659243Sobrienvoid 647167465Smpsetv(const Char *var, Char *val, int flags) 64859243Sobrien{ 649167465Smp Char **vec = xmalloc(2 * sizeof(Char **)); 65059243Sobrien 65159243Sobrien vec[0] = val; 65259243Sobrien vec[1] = 0; 65359243Sobrien set1(var, vec, &shvhed, flags); 65459243Sobrien} 65559243Sobrien 65659243Sobrienvoid 657167465Smpset1(const Char *var, Char **vec, struct varent *head, int flags) 65859243Sobrien{ 659145479Smp Char **oldv = vec; 66059243Sobrien 66159243Sobrien if ((flags & VAR_NOGLOB) == 0) { 662167465Smp int gflag; 663167465Smp 664167465Smp gflag = tglob(oldv); 66559243Sobrien if (gflag) { 666167465Smp vec = globall(oldv, gflag); 66759243Sobrien if (vec == 0) { 66859243Sobrien blkfree(oldv); 66959243Sobrien stderror(ERR_NAME | ERR_NOMATCH); 67059243Sobrien } 67159243Sobrien blkfree(oldv); 67259243Sobrien } 67359243Sobrien } 67459243Sobrien /* 67559243Sobrien * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com> 67659243Sobrien */ 67759243Sobrien if ( flags & (VAR_FIRST | VAR_LAST) ) { 67859243Sobrien /* 67959243Sobrien * Code for -f (VAR_FIRST) and -l (VAR_LAST) options. 68059243Sobrien * Method: 68159243Sobrien * Delete all duplicate words leaving "holes" in the word array (vec). 68259243Sobrien * Then remove the "holes", keeping the order of the words unchanged. 68359243Sobrien */ 68459243Sobrien if (vec && vec[0] && vec[1]) { /* more than one word ? */ 68559243Sobrien int i, j; 68659243Sobrien int num_items; 68759243Sobrien 68859243Sobrien for (num_items = 0; vec[num_items]; num_items++) 68959243Sobrien continue; 69059243Sobrien if (flags & VAR_FIRST) { 69159243Sobrien /* delete duplications, keeping first occurance */ 69259243Sobrien for (i = 1; i < num_items; i++) 69359243Sobrien for (j = 0; j < i; j++) 69459243Sobrien /* If have earlier identical item, remove i'th item */ 69559243Sobrien if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) { 696167465Smp xfree(vec[i]); 69759243Sobrien vec[i] = NULL; 69859243Sobrien break; 69959243Sobrien } 70059243Sobrien } else if (flags & VAR_LAST) { 70159243Sobrien /* delete duplications, keeping last occurance */ 70259243Sobrien for (i = 0; i < num_items - 1; i++) 70359243Sobrien for (j = i + 1; j < num_items; j++) 70459243Sobrien /* If have later identical item, remove i'th item */ 70559243Sobrien if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) { 70659243Sobrien /* remove identical item (the first) */ 707167465Smp xfree(vec[i]); 70859243Sobrien vec[i] = NULL; 70959243Sobrien } 71059243Sobrien } 71159243Sobrien /* Compress items - remove empty items */ 71259243Sobrien for (j = i = 0; i < num_items; i++) 71359243Sobrien if (vec[i]) 71459243Sobrien vec[j++] = vec[i]; 71559243Sobrien 71659243Sobrien /* NULL-fy remaining items */ 71759243Sobrien for (; j < num_items; j++) 71859243Sobrien vec[j] = NULL; 71959243Sobrien } 72059243Sobrien /* don't let the attribute propagate */ 72159243Sobrien flags &= ~(VAR_FIRST|VAR_LAST); 72259243Sobrien } 72359243Sobrien setq(var, vec, head, flags); 72459243Sobrien} 72559243Sobrien 72659243Sobrien 72759243Sobrienvoid 728167465Smpsetq(const Char *name, Char **vec, struct varent *p, int flags) 72959243Sobrien{ 730145479Smp struct varent *c; 731145479Smp int f; 73259243Sobrien 73359243Sobrien f = 0; /* tree hangs off the header's left link */ 73459243Sobrien while ((c = p->v_link[f]) != 0) { 73559243Sobrien if ((f = *name - *c->v_name) == 0 && 73659243Sobrien (f = Strcmp(name, c->v_name)) == 0) { 73759243Sobrien if (c->v_flags & VAR_READONLY) 73859243Sobrien stderror(ERR_READONLY|ERR_NAME, c->v_name); 73959243Sobrien blkfree(c->vec); 74059243Sobrien c->v_flags = flags; 74159243Sobrien trim(c->vec = vec); 74259243Sobrien return; 74359243Sobrien } 74459243Sobrien p = c; 74559243Sobrien f = f > 0; 74659243Sobrien } 747167465Smp p->v_link[f] = c = xmalloc(sizeof(struct varent)); 74859243Sobrien c->v_name = Strsave(name); 74959243Sobrien c->v_flags = flags; 75059243Sobrien c->v_bal = 0; 75159243Sobrien c->v_left = c->v_right = 0; 75259243Sobrien c->v_parent = p; 75359243Sobrien balance(p, f, 0); 75459243Sobrien trim(c->vec = vec); 75559243Sobrien} 75659243Sobrien 75759243Sobrien/*ARGSUSED*/ 75859243Sobrienvoid 759167465Smpunset(Char **v, struct command *c) 76059243Sobrien{ 761145479Smp int did_roe, did_edit; 76259243Sobrien 76359243Sobrien USE(c); 76459243Sobrien did_roe = adrof(STRrecognize_only_executables) != NULL; 76559243Sobrien did_edit = adrof(STRedit) != NULL; 76659243Sobrien unset1(v, &shvhed); 767100616Smp 768100616Smp#if defined(FILEC) && defined(TIOCSTI) 769100616Smp if (adrof(STRfilec) == 0) 770100616Smp filec = 0; 771100616Smp#endif /* FILEC && TIOCSTI */ 772100616Smp 77359243Sobrien if (adrof(STRhistchars) == 0) { 77459243Sobrien HIST = '!'; 77559243Sobrien HISTSUB = '^'; 77659243Sobrien } 777131962Smp if (adrof(STRignoreeof) == 0) 778131962Smp numeof = 0; 77959243Sobrien if (adrof(STRpromptchars) == 0) { 780231990Smp PRCH = tcsh ? '>' : '%'; 78159243Sobrien PRCHROOT = '#'; 78259243Sobrien } 783316958Sdchagin if (adrof(STRnoclobber) == 0) 784316958Sdchagin no_clobber = 0; 78559243Sobrien if (adrof(STRhistlit) == 0) 78659243Sobrien HistLit = 0; 78759243Sobrien if (adrof(STRloginsh) == 0) 78859243Sobrien loginsh = 0; 789231990Smp if (adrof(STRanyerror) == 0) 790231990Smp anyerror = 0; 79159243Sobrien if (adrof(STRwordchars) == 0) 79259243Sobrien word_chars = STR_WORD_CHARS; 79359243Sobrien if (adrof(STRedit) == 0) 79459243Sobrien editing = 0; 79559243Sobrien if (adrof(STRbackslash_quote) == 0) 79659243Sobrien bslash_quote = 0; 797195609Smp if (adrof(STRcompat_expr) == 0) 798195609Smp compat_expr = 0; 79959243Sobrien if (adrof(STRsymlinks) == 0) 80059243Sobrien symlinks = 0; 80159243Sobrien if (adrof(STRimplicitcd) == 0) 80259243Sobrien implicit_cd = 0; 803316958Sdchagin if (adrof(STRcdtohome) == 0) 804316958Sdchagin cdtohome = 0; 80583098Smp if (adrof(STRkillring) == 0) 80683098Smp SetKillRing(0); 80759243Sobrien if (did_edit && noediting && adrof(STRedit) == 0) 80859243Sobrien noediting = 0; 809316958Sdchagin if (adrof(STRvimode) == 0) 810316958Sdchagin VImode = 0; 81159243Sobrien if (did_roe && adrof(STRrecognize_only_executables) == 0) 81259243Sobrien tw_cmd_free(); 813316958Sdchagin if (adrof(STRhistory) == 0) 814316958Sdchagin sethistory(0); 81559243Sobrien#ifdef COLOR_LS_F 81659243Sobrien if (adrof(STRcolor) == 0) 81759243Sobrien set_color_context(); 81859243Sobrien#endif /* COLOR_LS_F */ 81959243Sobrien#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) 82059243Sobrien update_dspmbyte_vars(); 82159243Sobrien#endif 822316958Sdchagin update_wordchars(); 82369408Sache#ifdef NLS_CATALOGS 824145479Smp nlsclose(); 82569408Sache nlsinit(); 82669408Sache#endif /* NLS_CATALOGS */ 82759243Sobrien} 82859243Sobrien 82959243Sobrienvoid 830167465Smpunset1(Char *v[], struct varent *head) 83159243Sobrien{ 832145479Smp struct varent *vp; 833145479Smp int cnt; 83459243Sobrien 83559243Sobrien while (*++v) { 83659243Sobrien cnt = 0; 83759243Sobrien while ((vp = madrof(*v, head)) != NULL) 83859243Sobrien if (vp->v_flags & VAR_READONLY) 83959243Sobrien stderror(ERR_READONLY|ERR_NAME, vp->v_name); 84059243Sobrien else 84159243Sobrien unsetv1(vp), cnt++; 84259243Sobrien if (cnt == 0) 84359243Sobrien setname(short2str(*v)); 84459243Sobrien } 84559243Sobrien} 84659243Sobrien 84759243Sobrienvoid 848167465Smpunsetv(Char *var) 84959243Sobrien{ 850145479Smp struct varent *vp; 85159243Sobrien 85259243Sobrien if ((vp = adrof1(var, &shvhed)) == 0) 85359243Sobrien udvar(var); 85459243Sobrien unsetv1(vp); 85559243Sobrien} 85659243Sobrien 85759243Sobrienstatic void 858167465Smpunsetv1(struct varent *p) 85959243Sobrien{ 860145479Smp struct varent *c, *pp; 861145479Smp int f; 86259243Sobrien 86359243Sobrien /* 86459243Sobrien * Free associated memory first to avoid complications. 86559243Sobrien */ 86659243Sobrien blkfree(p->vec); 867167465Smp xfree(p->v_name); 86859243Sobrien /* 86959243Sobrien * If p is missing one child, then we can move the other into where p is. 87059243Sobrien * Otherwise, we find the predecessor of p, which is guaranteed to have no 87159243Sobrien * right child, copy it into p, and move it's left child into it. 87259243Sobrien */ 87359243Sobrien if (p->v_right == 0) 87459243Sobrien c = p->v_left; 87559243Sobrien else if (p->v_left == 0) 87659243Sobrien c = p->v_right; 87759243Sobrien else { 87859243Sobrien for (c = p->v_left; c->v_right; c = c->v_right) 87959243Sobrien continue; 88059243Sobrien p->v_name = c->v_name; 88159243Sobrien p->v_flags = c->v_flags; 88259243Sobrien p->vec = c->vec; 88359243Sobrien p = c; 88459243Sobrien c = p->v_left; 88559243Sobrien } 88659243Sobrien 88759243Sobrien /* 88859243Sobrien * Move c into where p is. 88959243Sobrien */ 89059243Sobrien pp = p->v_parent; 89159243Sobrien f = pp->v_right == p; 89259243Sobrien if ((pp->v_link[f] = c) != 0) 89359243Sobrien c->v_parent = pp; 89459243Sobrien /* 89559243Sobrien * Free the deleted node, and rebalance. 89659243Sobrien */ 897167465Smp xfree(p); 89859243Sobrien balance(pp, f, 1); 89959243Sobrien} 90059243Sobrien 901231990Smp/* Set variable name to NULL. */ 90259243Sobrienvoid 903231990SmpsetNS(const Char *varName) 90459243Sobrien{ 905231990Smp setcopy(varName, STRNULL, VAR_READWRITE); 90659243Sobrien} 90759243Sobrien 90859243Sobrien/*ARGSUSED*/ 90959243Sobrienvoid 910167465Smpshift(Char **v, struct command *c) 91159243Sobrien{ 912145479Smp struct varent *argv; 913145479Smp Char *name; 91459243Sobrien 91559243Sobrien USE(c); 91659243Sobrien v++; 91759243Sobrien name = *v; 91859243Sobrien if (name == 0) 91959243Sobrien name = STRargv; 92059243Sobrien else 92159243Sobrien (void) strip(name); 92259243Sobrien argv = adrof(name); 923100616Smp if (argv == NULL || argv->vec == NULL) 92459243Sobrien udvar(name); 92559243Sobrien if (argv->vec[0] == 0) 92659243Sobrien stderror(ERR_NAME | ERR_NOMORE); 92759243Sobrien lshift(argv->vec, 1); 92859243Sobrien update_vars(name); 92959243Sobrien} 93059243Sobrien 93159243Sobrienstatic void 932167465Smpexportpath(Char **val) 93359243Sobrien{ 934167465Smp struct Strbuf buf = Strbuf_INIT; 935167465Smp Char *exppath; 93659243Sobrien 93759243Sobrien if (val) 93859243Sobrien while (*val) { 939167465Smp Strbuf_append(&buf, *val++); 940167465Smp if (*val == 0 || eq(*val, STRRparen)) 94159243Sobrien break; 942167465Smp Strbuf_append1(&buf, PATHSEP); 943167465Smp } 944167465Smp exppath = Strbuf_finish(&buf); 945167465Smp cleanup_push(exppath, xfree); 946167465Smp tsetenv(STRKPATH, exppath); 947167465Smp cleanup_until(exppath); 94859243Sobrien} 94959243Sobrien 950316958Sdchaginstatic int 951316958Sdchaginset_noclobber(Char **val) 952316958Sdchagin{ 953316958Sdchagin Char *option; 954316958Sdchagin int nc = NOCLOBBER_DEFAULT; 955316958Sdchagin 956316958Sdchagin if (val == NULL) 957316958Sdchagin return nc; 958316958Sdchagin while (*val) { 959316958Sdchagin if (*val == 0 || eq(*val, STRRparen)) 960316958Sdchagin return nc; 961316958Sdchagin 962316958Sdchagin option = *val++; 963316958Sdchagin 964316958Sdchagin if (eq(option, STRnotempty)) 965316958Sdchagin nc |= NOCLOBBER_NOTEMPTY; 966316958Sdchagin else if (eq(option, STRask)) 967316958Sdchagin nc |= NOCLOBBER_ASK; 968316958Sdchagin } 969316958Sdchagin return nc; 970316958Sdchagin} 971316958Sdchagin 97259243Sobrien#ifndef lint 97359243Sobrien /* 97459243Sobrien * Lint thinks these have null effect 97559243Sobrien */ 97659243Sobrien /* macros to do single rotations on node p */ 97759243Sobrien# define rright(p) (\ 97859243Sobrien t = (p)->v_left,\ 97959243Sobrien (t)->v_parent = (p)->v_parent,\ 98059243Sobrien (((p)->v_left = t->v_right) != NULL) ?\ 98159243Sobrien (t->v_right->v_parent = (p)) : 0,\ 98259243Sobrien (t->v_right = (p))->v_parent = t,\ 98359243Sobrien (p) = t) 98459243Sobrien# define rleft(p) (\ 98559243Sobrien t = (p)->v_right,\ 98659243Sobrien ((t)->v_parent = (p)->v_parent,\ 98759243Sobrien ((p)->v_right = t->v_left) != NULL) ? \ 98859243Sobrien (t->v_left->v_parent = (p)) : 0,\ 98959243Sobrien (t->v_left = (p))->v_parent = t,\ 99059243Sobrien (p) = t) 99159243Sobrien#else 99259243Sobrienstatic struct varent * 993167465Smprleft(struct varent *p) 99459243Sobrien{ 99559243Sobrien return (p); 99659243Sobrien} 99759243Sobrienstatic struct varent * 998167465Smprright(struct varent *p) 99959243Sobrien{ 100059243Sobrien return (p); 100159243Sobrien} 100259243Sobrien 100359243Sobrien#endif /* ! lint */ 100459243Sobrien 100559243Sobrien 100659243Sobrien/* 100759243Sobrien * Rebalance a tree, starting at p and up. 100859243Sobrien * F == 0 means we've come from p's left child. 100959243Sobrien * D == 1 means we've just done a delete, otherwise an insert. 101059243Sobrien */ 101159243Sobrienstatic void 1012167465Smpbalance(struct varent *p, int f, int d) 101359243Sobrien{ 1014145479Smp struct varent *pp; 101559243Sobrien 101659243Sobrien#ifndef lint 1017145479Smp struct varent *t; /* used by the rotate macros */ 101859243Sobrien#endif /* !lint */ 1019145479Smp int ff; 102059243Sobrien#ifdef lint 102159243Sobrien ff = 0; /* Sun's lint is dumb! */ 102259243Sobrien#endif 102359243Sobrien 102459243Sobrien /* 102559243Sobrien * Ok, from here on, p is the node we're operating on; pp is it's parent; f 102659243Sobrien * is the branch of p from which we have come; ff is the branch of pp which 102759243Sobrien * is p. 102859243Sobrien */ 102959243Sobrien for (; (pp = p->v_parent) != 0; p = pp, f = ff) { 103059243Sobrien ff = pp->v_right == p; 103159243Sobrien if (f ^ d) { /* right heavy */ 103259243Sobrien switch (p->v_bal) { 103359243Sobrien case -1: /* was left heavy */ 103459243Sobrien p->v_bal = 0; 103559243Sobrien break; 103659243Sobrien case 0: /* was balanced */ 103759243Sobrien p->v_bal = 1; 103859243Sobrien break; 103959243Sobrien case 1: /* was already right heavy */ 104059243Sobrien switch (p->v_right->v_bal) { 1041167465Smp case 1: /* single rotate */ 104259243Sobrien pp->v_link[ff] = rleft(p); 104359243Sobrien p->v_left->v_bal = 0; 104459243Sobrien p->v_bal = 0; 104559243Sobrien break; 104659243Sobrien case 0: /* single rotate */ 104759243Sobrien pp->v_link[ff] = rleft(p); 104859243Sobrien p->v_left->v_bal = 1; 104959243Sobrien p->v_bal = -1; 105059243Sobrien break; 105159243Sobrien case -1: /* double rotate */ 105259243Sobrien (void) rright(p->v_right); 105359243Sobrien pp->v_link[ff] = rleft(p); 105459243Sobrien p->v_left->v_bal = 105559243Sobrien p->v_bal < 1 ? 0 : -1; 105659243Sobrien p->v_right->v_bal = 105759243Sobrien p->v_bal > -1 ? 0 : 1; 105859243Sobrien p->v_bal = 0; 105959243Sobrien break; 106059243Sobrien default: 106159243Sobrien break; 106259243Sobrien } 106359243Sobrien break; 106459243Sobrien default: 106559243Sobrien break; 106659243Sobrien } 106759243Sobrien } 106859243Sobrien else { /* left heavy */ 106959243Sobrien switch (p->v_bal) { 107059243Sobrien case 1: /* was right heavy */ 107159243Sobrien p->v_bal = 0; 107259243Sobrien break; 107359243Sobrien case 0: /* was balanced */ 107459243Sobrien p->v_bal = -1; 107559243Sobrien break; 107659243Sobrien case -1: /* was already left heavy */ 107759243Sobrien switch (p->v_left->v_bal) { 107859243Sobrien case -1: /* single rotate */ 107959243Sobrien pp->v_link[ff] = rright(p); 108059243Sobrien p->v_right->v_bal = 0; 108159243Sobrien p->v_bal = 0; 108259243Sobrien break; 1083167465Smp case 0: /* single rotate */ 108459243Sobrien pp->v_link[ff] = rright(p); 108559243Sobrien p->v_right->v_bal = -1; 108659243Sobrien p->v_bal = 1; 108759243Sobrien break; 108859243Sobrien case 1: /* double rotate */ 108959243Sobrien (void) rleft(p->v_left); 109059243Sobrien pp->v_link[ff] = rright(p); 109159243Sobrien p->v_left->v_bal = 109259243Sobrien p->v_bal < 1 ? 0 : -1; 109359243Sobrien p->v_right->v_bal = 109459243Sobrien p->v_bal > -1 ? 0 : 1; 109559243Sobrien p->v_bal = 0; 109659243Sobrien break; 109759243Sobrien default: 109859243Sobrien break; 109959243Sobrien } 110059243Sobrien break; 110159243Sobrien default: 110259243Sobrien break; 110359243Sobrien } 110459243Sobrien } 110559243Sobrien /* 110659243Sobrien * If from insert, then we terminate when p is balanced. If from 110759243Sobrien * delete, then we terminate when p is unbalanced. 110859243Sobrien */ 110959243Sobrien if ((p->v_bal == 0) ^ d) 111059243Sobrien break; 111159243Sobrien } 111259243Sobrien} 111359243Sobrien 111459243Sobrienvoid 1115167465Smpplist(struct varent *p, int what) 111659243Sobrien{ 1117145479Smp struct varent *c; 1118145479Smp int len; 111959243Sobrien 112059243Sobrien for (;;) { 112159243Sobrien while (p->v_left) 112259243Sobrien p = p->v_left; 112359243Sobrienx: 112459243Sobrien if (p->v_parent == 0) /* is it the header? */ 1125167465Smp break; 112659243Sobrien if ((p->v_flags & what) != 0) { 1127167465Smp if (setintr) { 1128167465Smp int old_pintr_disabled; 1129167465Smp 1130167465Smp pintr_push_enable(&old_pintr_disabled); 1131167465Smp cleanup_until(&old_pintr_disabled); 1132167465Smp } 113359243Sobrien len = blklen(p->vec); 113459243Sobrien xprintf("%S\t", p->v_name); 113559243Sobrien if (len != 1) 113659243Sobrien xputchar('('); 113759243Sobrien blkpr(p->vec); 113859243Sobrien if (len != 1) 113959243Sobrien xputchar(')'); 114059243Sobrien xputchar('\n'); 114159243Sobrien } 114259243Sobrien if (p->v_right) { 114359243Sobrien p = p->v_right; 114459243Sobrien continue; 114559243Sobrien } 114659243Sobrien do { 114759243Sobrien c = p; 114859243Sobrien p = p->v_parent; 114959243Sobrien } while (p->v_right == c); 115059243Sobrien goto x; 115159243Sobrien } 115259243Sobrien} 115359243Sobrien 1154231990Smp#if defined(KANJI) 1155231990Smp# if defined(SHORT_STRINGS) && defined(DSPMBYTE) 1156145479Smpextern int dspmbyte_ls; 115759243Sobrien 115859243Sobrienvoid 1159167465Smpupdate_dspmbyte_vars(void) 116059243Sobrien{ 116159243Sobrien int lp, iskcode; 116259243Sobrien Char *dstr1; 116359243Sobrien struct varent *vp; 116459243Sobrien 116559243Sobrien /* if variable "nokanji" is set, multi-byte display is disabled */ 116659243Sobrien if ((vp = adrof(CHECK_MBYTEVAR)) && !adrof(STRnokanji)) { 116759243Sobrien _enable_mbdisp = 1; 116859243Sobrien dstr1 = vp->vec[0]; 1169145479Smp if(eq (dstr1, STRsjis)) 117059243Sobrien iskcode = 1; 1171145479Smp else if (eq(dstr1, STReuc)) 117259243Sobrien iskcode = 2; 1173145479Smp else if (eq(dstr1, STRbig5)) 117483098Smp iskcode = 3; 1175145479Smp else if (eq(dstr1, STRutf8)) 1176100616Smp iskcode = 4; 117759243Sobrien else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) { 117859243Sobrien iskcode = 0; 117959243Sobrien } 118059243Sobrien else { 118159243Sobrien xprintf(CGETS(18, 2, 118259243Sobrien "Warning: unknown multibyte display; using default(euc(JP))\n")); 118359243Sobrien iskcode = 2; 118459243Sobrien } 118559243Sobrien if (dstr1 && vp->vec[1] && eq(vp->vec[1], STRls)) 118659243Sobrien dspmbyte_ls = 1; 118759243Sobrien else 118859243Sobrien dspmbyte_ls = 0; 118959243Sobrien for (lp = 0; lp < 256 && iskcode > 0; lp++) { 119059243Sobrien switch (iskcode) { 119159243Sobrien case 1: 119259243Sobrien /* Shift-JIS */ 119359243Sobrien _cmap[lp] = _cmap_mbyte[lp]; 119459243Sobrien _mbmap[lp] = _mbmap_sjis[lp]; 119559243Sobrien break; 119659243Sobrien case 2: 119759243Sobrien /* 2 ... euc */ 119859243Sobrien _cmap[lp] = _cmap_mbyte[lp]; 119959243Sobrien _mbmap[lp] = _mbmap_euc[lp]; 120059243Sobrien break; 120183098Smp case 3: 120283098Smp /* 3 ... big5 */ 120383098Smp _cmap[lp] = _cmap_mbyte[lp]; 120483098Smp _mbmap[lp] = _mbmap_big5[lp]; 120583098Smp break; 1206100616Smp case 4: 1207100616Smp /* 4 ... utf8 */ 1208100616Smp _cmap[lp] = _cmap_mbyte[lp]; 1209100616Smp _mbmap[lp] = _mbmap_utf8[lp]; 1210100616Smp break; 121159243Sobrien default: 121259243Sobrien xprintf(CGETS(18, 3, 121359243Sobrien "Warning: unknown multibyte code %d; multibyte disabled\n"), 121459243Sobrien iskcode); 121559243Sobrien _cmap[lp] = _cmap_c[lp]; 121659243Sobrien _mbmap[lp] = 0; /* Default map all 0 */ 121759243Sobrien _enable_mbdisp = 0; 121859243Sobrien break; 121959243Sobrien } 122059243Sobrien } 122159243Sobrien if (iskcode == 0) { 122259243Sobrien /* check original table */ 122359243Sobrien if (Strlen(dstr1) != 256) { 122459243Sobrien xprintf(CGETS(18, 4, 122559243Sobrien "Warning: Invalid multibyte table length (%d); multibyte disabled\n"), 122659243Sobrien Strlen(dstr1)); 122759243Sobrien _enable_mbdisp = 0; 122859243Sobrien } 122959243Sobrien for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) { 123059243Sobrien if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) { 123159243Sobrien xprintf(CGETS(18, 4, 123259243Sobrien "Warning: bad multibyte code at offset +%d; multibyte diabled\n"), 123359243Sobrien lp); 123459243Sobrien _enable_mbdisp = 0; 123559243Sobrien break; 123659243Sobrien } 123759243Sobrien } 123859243Sobrien /* set original table */ 123959243Sobrien for (lp = 0; lp < 256; lp++) { 124059243Sobrien if (_enable_mbdisp == 1) { 124159243Sobrien _cmap[lp] = _cmap_mbyte[lp]; 124259243Sobrien _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f); 124359243Sobrien } 124459243Sobrien else { 124559243Sobrien _cmap[lp] = _cmap_c[lp]; 124659243Sobrien _mbmap[lp] = 0; /* Default map all 0 */ 124759243Sobrien } 124859243Sobrien } 124959243Sobrien } 125059243Sobrien } 125159243Sobrien else { 125259243Sobrien for (lp = 0; lp < 256; lp++) { 125359243Sobrien _cmap[lp] = _cmap_c[lp]; 125459243Sobrien _mbmap[lp] = 0; /* Default map all 0 */ 125559243Sobrien } 125659243Sobrien _enable_mbdisp = 0; 125759243Sobrien dspmbyte_ls = 0; 125859243Sobrien } 125959243Sobrien#ifdef MBYTEDEBUG /* Sorry, use for beta testing */ 126059243Sobrien { 126159243Sobrien Char mbmapstr[300]; 1262167465Smp for (lp = 0; lp < 256; lp++) 126359243Sobrien mbmapstr[lp] = _mbmap[lp] + '0'; 1264167465Smp mbmapstr[lp] = 0; 1265167465Smp setcopy(STRmbytemap, mbmapstr, VAR_READWRITE); 126659243Sobrien } 126759243Sobrien#endif /* MBYTEMAP */ 126859243Sobrien} 126959243Sobrien 127059243Sobrien/* dspkanji/dspmbyte autosetting */ 127159243Sobrien/* PATCH IDEA FROM Issei.Suzuki VERY THANKS */ 127259243Sobrienvoid 1273167465Smpautoset_dspmbyte(const Char *pcp) 127459243Sobrien{ 127559243Sobrien int i; 1276167465Smp static const struct dspm_autoset_Table { 127759243Sobrien Char *n; 127859243Sobrien Char *v; 127959243Sobrien } dspmt[] = { 1280145479Smp { STRLANGEUCJP, STReuc }, 1281145479Smp { STRLANGEUCKR, STReuc }, 1282145479Smp { STRLANGEUCZH, STReuc }, 1283145479Smp { STRLANGEUCJPB, STReuc }, 1284145479Smp { STRLANGEUCKRB, STReuc }, 1285145479Smp { STRLANGEUCZHB, STReuc }, 1286231990Smp#ifdef __linux__ 1287145479Smp { STRLANGEUCJPC, STReuc }, 1288131962Smp#endif 1289145479Smp { STRLANGSJIS, STRsjis }, 1290145479Smp { STRLANGSJISB, STRsjis }, 1291145479Smp { STRLANGBIG5, STRbig5 }, 1292145479Smp { STRstarutfstar8, STRutf8 }, 129359243Sobrien { NULL, NULL } 129459243Sobrien }; 1295167465Smp#if defined(HAVE_NL_LANGINFO) && defined(CODESET) 1296167465Smp static const struct dspm_autoset_Table dspmc[] = { 1297145479Smp { STRstarutfstar8, STRutf8 }, 1298145479Smp { STReuc, STReuc }, 1299145479Smp { STRGB2312, STReuc }, 1300145479Smp { STRLANGBIG5, STRbig5 }, 1301145479Smp { NULL, NULL } 1302145479Smp }; 1303145479Smp Char *codeset; 130459243Sobrien 1305145479Smp codeset = str2short(nl_langinfo(CODESET)); 1306145479Smp if (*codeset != '\0') { 1307145479Smp for (i = 0; dspmc[i].n; i++) { 1308167465Smp const Char *estr; 1309145479Smp if (dspmc[i].n[0] && t_pmatch(pcp, dspmc[i].n, &estr, 0) > 0) { 1310167465Smp setcopy(CHECK_MBYTEVAR, dspmc[i].v, VAR_READWRITE); 1311145479Smp update_dspmbyte_vars(); 1312145479Smp return; 1313145479Smp } 1314145479Smp } 1315145479Smp } 1316145479Smp#endif 1317145479Smp 131859243Sobrien if (*pcp == '\0') 131959243Sobrien return; 132059243Sobrien 132159243Sobrien for (i = 0; dspmt[i].n; i++) { 1322167465Smp const Char *estr; 1323145479Smp if (dspmt[i].n[0] && t_pmatch(pcp, dspmt[i].n, &estr, 0) > 0) { 1324167465Smp setcopy(CHECK_MBYTEVAR, dspmt[i].v, VAR_READWRITE); 132559243Sobrien update_dspmbyte_vars(); 132659243Sobrien break; 132759243Sobrien } 132859243Sobrien } 132959243Sobrien} 1330231990Smp# elif defined(AUTOSET_KANJI) 1331231990Smpvoid 1332231990Smpautoset_kanji(void) 1333231990Smp{ 1334231990Smp char *codeset = nl_langinfo(CODESET); 1335231990Smp 1336231990Smp if (*codeset == '\0') { 1337231990Smp if (adrof(STRnokanji) == NULL) 1338231990Smp setNS(STRnokanji); 1339231990Smp return; 1340231990Smp } 1341231990Smp 1342231990Smp if (strcasestr(codeset, "SHIFT_JIS") == (char*)0) { 1343231990Smp if (adrof(STRnokanji) == NULL) 1344231990Smp setNS(STRnokanji); 1345231990Smp return; 1346231990Smp } 1347231990Smp 1348231990Smp if (adrof(STRnokanji) != NULL) 1349231990Smp unsetv(STRnokanji); 1350231990Smp} 135159243Sobrien#endif 1352231990Smp#endif 1353316958Sdchagin 1354316958Sdchaginvoid 1355316958Sdchaginupdate_wordchars(void) 1356316958Sdchagin{ 1357316958Sdchagin if ((word_chars == STR_WORD_CHARS) || (word_chars == STR_WORD_CHARS_VI)) { 1358316958Sdchagin word_chars = (VImode ? STR_WORD_CHARS_VI : STR_WORD_CHARS); 1359316958Sdchagin } 1360316958Sdchagin} 1361