159243Sobrien/* 259243Sobrien * sh.set.c: Setting and Clearing of variables 359243Sobrien */ 459243Sobrien/*- 559243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California. 659243Sobrien * All rights reserved. 759243Sobrien * 859243Sobrien * Redistribution and use in source and binary forms, with or without 959243Sobrien * modification, are permitted provided that the following conditions 1059243Sobrien * are met: 1159243Sobrien * 1. Redistributions of source code must retain the above copyright 1259243Sobrien * notice, this list of conditions and the following disclaimer. 1359243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1459243Sobrien * notice, this list of conditions and the following disclaimer in the 1559243Sobrien * documentation and/or other materials provided with the distribution. 16100616Smp * 3. Neither the name of the University nor the names of its contributors 1759243Sobrien * may be used to endorse or promote products derived from this software 1859243Sobrien * without specific prior written permission. 1959243Sobrien * 2059243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2159243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2259243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2359243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2459243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2559243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2659243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2759243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2859243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2959243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3059243Sobrien * SUCH DAMAGE. 3159243Sobrien */ 3259243Sobrien#include "sh.h" 3359243Sobrien#include "ed.h" 3459243Sobrien#include "tw.h" 3559243Sobrien 36145479Smp#ifdef HAVE_NL_LANGINFO 37145479Smp#include <langinfo.h> 38145479Smp#endif 39145479Smp 40145479Smpextern int GotTermCaps; 41131962Smpint numeof = 0; 4259243Sobrien 43167465Smpstatic void update_vars (Char *); 44167465Smpstatic Char *getinx (Char *, int *); 45167465Smpstatic void asx (Char *, int, Char *); 46167465Smpstatic struct varent *getvx (Char *, int); 47167465Smpstatic Char *xset (Char *, Char ***); 48167465Smpstatic Char *operate (int, Char *, Char *); 49231990Smpstatic void putn1 (tcsh_number_t); 50167465Smpstatic struct varent *madrof (Char *, struct varent *); 51167465Smpstatic void unsetv1 (struct varent *); 52167465Smpstatic void exportpath (Char **); 53167465Smpstatic void balance (struct varent *, int, int); 54316957Sdchaginstatic int set_noclobber (Char **); 5559243Sobrien 5659243Sobrien/* 5759243Sobrien * C Shell 5859243Sobrien */ 5959243Sobrien 6059243Sobrienstatic void 61167465Smpupdate_vars(Char *vp) 6259243Sobrien{ 6359243Sobrien if (eq(vp, STRpath)) { 64167465Smp struct varent *p = adrof(STRpath); 65167465Smp if (p == NULL) 66167465Smp stderror(ERR_NAME | ERR_UNDVAR); 67167465Smp else { 68167465Smp exportpath(p->vec); 69167465Smp dohash(NULL, NULL); 70167465Smp } 7159243Sobrien } 72316957Sdchagin else if (eq(vp, STRnoclobber)) { 73316957Sdchagin struct varent *p = adrof(STRnoclobber); 74316957Sdchagin if (p == NULL) 75316957Sdchagin stderror(ERR_NAME | ERR_UNDVAR); 76316957Sdchagin else 77316957Sdchagin no_clobber = set_noclobber(p->vec); 78316957Sdchagin } 7959243Sobrien else if (eq(vp, STRhistchars)) { 80145479Smp Char *pn = varval(vp); 8159243Sobrien 8259243Sobrien HIST = *pn++; 83231990Smp if (HIST) 84231990Smp HISTSUB = *pn; 85231990Smp else 86231990Smp HISTSUB = HIST; 8759243Sobrien } 8859243Sobrien else if (eq(vp, STRpromptchars)) { 89145479Smp Char *pn = varval(vp); 9059243Sobrien 9159243Sobrien PRCH = *pn++; 92231990Smp if (PRCH) 93231990Smp PRCHROOT = *pn; 94231990Smp else 95231990Smp PRCHROOT = PRCH; 9659243Sobrien } 9759243Sobrien else if (eq(vp, STRhistlit)) { 9859243Sobrien HistLit = 1; 9959243Sobrien } 10059243Sobrien else if (eq(vp, STRuser)) { 10159243Sobrien tsetenv(STRKUSER, varval(vp)); 10259243Sobrien tsetenv(STRLOGNAME, varval(vp)); 10359243Sobrien } 10459243Sobrien else if (eq(vp, STRgroup)) { 10559243Sobrien tsetenv(STRKGROUP, varval(vp)); 10659243Sobrien } 10759243Sobrien else if (eq(vp, STRwordchars)) { 10859243Sobrien word_chars = varval(vp); 10959243Sobrien } 11059243Sobrien else if (eq(vp, STRloginsh)) { 11159243Sobrien loginsh = 1; 11259243Sobrien } 113231990Smp else if (eq(vp, STRanyerror)) { 114231990Smp anyerror = 1; 115231990Smp } 11659243Sobrien else if (eq(vp, STRsymlinks)) { 117145479Smp Char *pn = varval(vp); 11859243Sobrien 11959243Sobrien if (eq(pn, STRignore)) 12059243Sobrien symlinks = SYM_IGNORE; 12159243Sobrien else if (eq(pn, STRexpand)) 12259243Sobrien symlinks = SYM_EXPAND; 12359243Sobrien else if (eq(pn, STRchase)) 12459243Sobrien symlinks = SYM_CHASE; 12559243Sobrien else 12659243Sobrien symlinks = 0; 12759243Sobrien } 12859243Sobrien else if (eq(vp, STRterm)) { 12959243Sobrien Char *cp = varval(vp); 13059243Sobrien tsetenv(STRKTERM, cp); 13159243Sobrien#ifdef DOESNT_WORK_RIGHT 13259243Sobrien cp = getenv("TERMCAP"); 13359243Sobrien if (cp && (*cp != '/')) /* if TERMCAP and not a path */ 13459243Sobrien Unsetenv(STRTERMCAP); 13559243Sobrien#endif /* DOESNT_WORK_RIGHT */ 13659243Sobrien GotTermCaps = 0; 13759243Sobrien if (noediting && Strcmp(cp, STRnetwork) != 0 && 13859243Sobrien Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) { 13959243Sobrien editing = 1; 14059243Sobrien noediting = 0; 141167465Smp setNS(STRedit); 14259243Sobrien } 14359243Sobrien ed_Init(); /* reset the editor */ 14459243Sobrien } 14559243Sobrien else if (eq(vp, STRhome)) { 146167465Smp Char *cp, *canon; 14759243Sobrien 14859243Sobrien cp = Strsave(varval(vp)); /* get the old value back */ 149167465Smp cleanup_push(cp, xfree); 15059243Sobrien 15159243Sobrien /* 15259243Sobrien * convert to cononical pathname (possibly resolving symlinks) 15359243Sobrien */ 154167465Smp canon = dcanon(cp, cp); 155167465Smp cleanup_ignore(cp); 156167465Smp cleanup_until(cp); 157167465Smp cleanup_push(canon, xfree); 15859243Sobrien 159167465Smp setcopy(vp, canon, VAR_READWRITE); /* have to save the new val */ 16059243Sobrien 16159243Sobrien /* and now mirror home with HOME */ 162167465Smp tsetenv(STRKHOME, canon); 16359243Sobrien /* fix directory stack for new tilde home */ 16459243Sobrien dtilde(); 165167465Smp cleanup_until(canon); 16659243Sobrien } 16759243Sobrien else if (eq(vp, STRedit)) { 16859243Sobrien editing = 1; 16959243Sobrien noediting = 0; 17059243Sobrien /* PWP: add more stuff in here later */ 17159243Sobrien } 172316957Sdchagin else if (eq(vp, STRvimode)) { 173316957Sdchagin VImode = 1; 174316957Sdchagin update_wordchars(); 175316957Sdchagin } 17659243Sobrien else if (eq(vp, STRshlvl)) { 17759243Sobrien tsetenv(STRKSHLVL, varval(vp)); 17859243Sobrien } 179131962Smp else if (eq(vp, STRignoreeof)) { 180131962Smp Char *cp; 181131962Smp numeof = 0; 182131962Smp for ((cp = varval(STRignoreeof)); cp && *cp; cp++) { 183131962Smp if (!Isdigit(*cp)) { 184131962Smp numeof = 0; 185131962Smp break; 186131962Smp } 187131962Smp numeof = numeof * 10 + *cp - '0'; 188131962Smp } 189131962Smp if (numeof <= 0) numeof = 26; /* Sanity check */ 190131962Smp } 19159243Sobrien else if (eq(vp, STRbackslash_quote)) { 19259243Sobrien bslash_quote = 1; 19359243Sobrien } 194195609Smp else if (eq(vp, STRcompat_expr)) { 195195609Smp compat_expr = 1; 196195609Smp } 19759243Sobrien else if (eq(vp, STRdirstack)) { 19859243Sobrien dsetstack(); 19959243Sobrien } 20059243Sobrien else if (eq(vp, STRrecognize_only_executables)) { 20159243Sobrien tw_cmd_free(); 20259243Sobrien } 20383098Smp else if (eq(vp, STRkillring)) { 204231990Smp SetKillRing((int)getn(varval(vp))); 20583098Smp } 206316957Sdchagin else if (eq(vp, STRhistory)) { 207316957Sdchagin sethistory((int)getn(varval(vp))); 208316957Sdchagin } 20959243Sobrien#ifndef HAVENOUTMP 21059243Sobrien else if (eq(vp, STRwatch)) { 21159243Sobrien resetwatch(); 21259243Sobrien } 21359243Sobrien#endif /* HAVENOUTMP */ 21459243Sobrien else if (eq(vp, STRimplicitcd)) { 21559243Sobrien implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1); 21659243Sobrien } 217316957Sdchagin else if (eq(vp, STRcdtohome)) { 218316957Sdchagin cdtohome = 1; 219316957Sdchagin } 22059243Sobrien#ifdef COLOR_LS_F 22159243Sobrien else if (eq(vp, STRcolor)) { 22259243Sobrien set_color_context(); 22359243Sobrien } 22459243Sobrien#endif /* COLOR_LS_F */ 22559243Sobrien#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) 22659243Sobrien else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) { 22759243Sobrien update_dspmbyte_vars(); 22859243Sobrien } 22959243Sobrien#endif 23069408Sache#ifdef NLS_CATALOGS 23169408Sache else if (eq(vp, STRcatalog)) { 232145479Smp nlsclose(); 23369408Sache nlsinit(); 23469408Sache } 235100616Smp#if defined(FILEC) && defined(TIOCSTI) 236100616Smp else if (eq(vp, STRfilec)) 237100616Smp filec = 1; 238100616Smp#endif 23969408Sache#endif /* NLS_CATALOGS */ 24059243Sobrien} 24159243Sobrien 24259243Sobrien 24359243Sobrien/*ARGSUSED*/ 24459243Sobrienvoid 245167465Smpdoset(Char **v, struct command *c) 24659243Sobrien{ 247145479Smp Char *p; 248231990Smp Char *vp; 24959243Sobrien Char **vecp; 250145479Smp int hadsub; 25159243Sobrien int subscr; 25259243Sobrien int flags = VAR_READWRITE; 253145479Smp int first_match = 0; 254145479Smp int last_match = 0; 255145479Smp int changed = 0; 25659243Sobrien 25759243Sobrien USE(c); 25859243Sobrien v++; 25959243Sobrien do { 26059243Sobrien changed = 0; 26159243Sobrien /* 26259243Sobrien * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov> 26359243Sobrien */ 26459243Sobrien if (*v && eq(*v, STRmr)) { 26559243Sobrien flags = VAR_READONLY; 26659243Sobrien v++; 26759243Sobrien changed = 1; 26859243Sobrien } 26959243Sobrien if (*v && eq(*v, STRmf) && !last_match) { 27059243Sobrien first_match = 1; 27159243Sobrien v++; 27259243Sobrien changed = 1; 27359243Sobrien } 27459243Sobrien if (*v && eq(*v, STRml) && !first_match) { 27559243Sobrien last_match = 1; 27659243Sobrien v++; 27759243Sobrien changed = 1; 27859243Sobrien } 27959243Sobrien } while(changed); 28059243Sobrien p = *v++; 28159243Sobrien if (p == 0) { 28259243Sobrien plist(&shvhed, flags); 28359243Sobrien return; 28459243Sobrien } 28559243Sobrien do { 28659243Sobrien hadsub = 0; 28759243Sobrien vp = p; 288231990Smp if (!letter(*p)) 28959243Sobrien stderror(ERR_NAME | ERR_VARBEGIN); 290231990Smp do { 291231990Smp p++; 292231990Smp } while (alnum(*p)); 29359243Sobrien if (*p == '[') { 29459243Sobrien hadsub++; 29559243Sobrien p = getinx(p, &subscr); 29659243Sobrien } 297231990Smp if (*p != '\0' && *p != '=') 298231990Smp stderror(ERR_NAME | ERR_VARALNUM); 299231990Smp if (*p == '=') { 300231990Smp *p++ = '\0'; 301231990Smp if (*p == '\0' && *v != NULL && **v == '(') 30259243Sobrien p = *v++; 30359243Sobrien } 30459243Sobrien else if (*v && eq(*v, STRequal)) { 305231990Smp if (*++v != NULL) 30659243Sobrien p = *v++; 30759243Sobrien } 30859243Sobrien if (eq(p, STRLparen)) { 309145479Smp Char **e = v; 31059243Sobrien 31159243Sobrien if (hadsub) 31259243Sobrien stderror(ERR_NAME | ERR_SYNTAX); 31359243Sobrien for (;;) { 31459243Sobrien if (!*e) 31559243Sobrien stderror(ERR_NAME | ERR_MISSING, ')'); 31659243Sobrien if (**e == ')') 31759243Sobrien break; 31859243Sobrien e++; 31959243Sobrien } 32059243Sobrien p = *e; 32159243Sobrien *e = 0; 32259243Sobrien vecp = saveblk(v); 32359243Sobrien if (first_match) 32459243Sobrien flags |= VAR_FIRST; 32559243Sobrien else if (last_match) 32659243Sobrien flags |= VAR_LAST; 32759243Sobrien 32859243Sobrien set1(vp, vecp, &shvhed, flags); 32959243Sobrien *e = p; 33059243Sobrien v = e + 1; 33159243Sobrien } 332167465Smp else if (hadsub) { 333167465Smp Char *copy; 334167465Smp 335167465Smp copy = Strsave(p); 336167465Smp cleanup_push(copy, xfree); 337167465Smp asx(vp, subscr, copy); 338167465Smp cleanup_ignore(copy); 339167465Smp cleanup_until(copy); 340167465Smp } 34159243Sobrien else 342167465Smp setv(vp, Strsave(p), flags); 34359243Sobrien update_vars(vp); 34459243Sobrien } while ((p = *v++) != NULL); 34559243Sobrien} 34659243Sobrien 34759243Sobrienstatic Char * 348167465Smpgetinx(Char *cp, int *ip) 34959243Sobrien{ 35059243Sobrien *ip = 0; 35159243Sobrien *cp++ = 0; 35259243Sobrien while (*cp && Isdigit(*cp)) 35359243Sobrien *ip = *ip * 10 + *cp++ - '0'; 35459243Sobrien if (*cp++ != ']') 35559243Sobrien stderror(ERR_NAME | ERR_SUBSCRIPT); 35659243Sobrien return (cp); 35759243Sobrien} 35859243Sobrien 35959243Sobrienstatic void 360167465Smpasx(Char *vp, int subscr, Char *p) 36159243Sobrien{ 362145479Smp struct varent *v = getvx(vp, subscr); 363167465Smp Char *prev; 36459243Sobrien 36559243Sobrien if (v->v_flags & VAR_READONLY) 36659243Sobrien stderror(ERR_READONLY|ERR_NAME, v->v_name); 367167465Smp prev = v->vec[subscr - 1]; 368167465Smp cleanup_push(prev, xfree); 36959243Sobrien v->vec[subscr - 1] = globone(p, G_APPEND); 370167465Smp cleanup_until(prev); 37159243Sobrien} 37259243Sobrien 37359243Sobrienstatic struct varent * 374167465Smpgetvx(Char *vp, int subscr) 37559243Sobrien{ 376145479Smp struct varent *v = adrof(vp); 37759243Sobrien 37859243Sobrien if (v == 0) 37959243Sobrien udvar(vp); 38059243Sobrien if (subscr < 1 || subscr > blklen(v->vec)) 38159243Sobrien stderror(ERR_NAME | ERR_RANGE); 38259243Sobrien return (v); 38359243Sobrien} 38459243Sobrien 38559243Sobrien/*ARGSUSED*/ 38659243Sobrienvoid 387167465Smpdolet(Char **v, struct command *dummy) 38859243Sobrien{ 389145479Smp Char *p; 39059243Sobrien Char *vp, c, op; 391145479Smp int hadsub; 39259243Sobrien int subscr; 39359243Sobrien 39459243Sobrien USE(dummy); 39559243Sobrien v++; 39659243Sobrien p = *v++; 39759243Sobrien if (p == 0) { 39859243Sobrien prvars(); 39959243Sobrien return; 40059243Sobrien } 40159243Sobrien do { 40259243Sobrien hadsub = 0; 40359243Sobrien vp = p; 40459243Sobrien if (letter(*p)) 40559243Sobrien for (; alnum(*p); p++) 40659243Sobrien continue; 40759243Sobrien if (vp == p || !letter(*vp)) 40859243Sobrien stderror(ERR_NAME | ERR_VARBEGIN); 40959243Sobrien if (*p == '[') { 41059243Sobrien hadsub++; 41159243Sobrien p = getinx(p, &subscr); 41259243Sobrien } 41359243Sobrien if (*p == 0 && *v) 41459243Sobrien p = *v++; 41559243Sobrien if ((op = *p) != 0) 41659243Sobrien *p++ = 0; 41759243Sobrien else 41859243Sobrien stderror(ERR_NAME | ERR_ASSIGN); 41959243Sobrien 42059243Sobrien /* 42159243Sobrien * if there is no expression after the '=' then print a "Syntax Error" 42259243Sobrien * message - strike 42359243Sobrien */ 42459243Sobrien if (*p == '\0' && *v == NULL) 42559243Sobrien stderror(ERR_NAME | ERR_ASSIGN); 42659243Sobrien 42759243Sobrien vp = Strsave(vp); 428167465Smp cleanup_push(vp, xfree); 42959243Sobrien if (op == '=') { 43059243Sobrien c = '='; 43159243Sobrien p = xset(p, &v); 43259243Sobrien } 43359243Sobrien else { 43459243Sobrien c = *p++; 43559243Sobrien if (any("+-", c)) { 43659243Sobrien if (c != op || *p) 43759243Sobrien stderror(ERR_NAME | ERR_UNKNOWNOP); 43859243Sobrien p = Strsave(STR1); 43959243Sobrien } 44059243Sobrien else { 44159243Sobrien if (any("<>", op)) { 44259243Sobrien if (c != op) 44359243Sobrien stderror(ERR_NAME | ERR_UNKNOWNOP); 44459243Sobrien stderror(ERR_NAME | ERR_SYNTAX); 44559243Sobrien } 44659243Sobrien if (c != '=') 44759243Sobrien stderror(ERR_NAME | ERR_UNKNOWNOP); 44859243Sobrien p = xset(p, &v); 44959243Sobrien } 45059243Sobrien } 451167465Smp cleanup_push(p, xfree); 45259243Sobrien if (op == '=') { 45359243Sobrien if (hadsub) 45459243Sobrien asx(vp, subscr, p); 45559243Sobrien else 456167465Smp setv(vp, p, VAR_READWRITE); 457167465Smp cleanup_ignore(p); 45859243Sobrien } 45959243Sobrien else if (hadsub) { 46059243Sobrien struct varent *gv = getvx(vp, subscr); 461167465Smp Char *val; 46259243Sobrien 463167465Smp val = operate(op, gv->vec[subscr - 1], p); 464167465Smp cleanup_push(val, xfree); 465167465Smp asx(vp, subscr, val); 466167465Smp cleanup_ignore(val); 467167465Smp cleanup_until(val); 46859243Sobrien } 469167465Smp else { 470167465Smp Char *val; 471167465Smp 472167465Smp val = operate(op, varval(vp), p); 473167465Smp cleanup_push(val, xfree); 474167465Smp setv(vp, val, VAR_READWRITE); 475167465Smp cleanup_ignore(val); 476167465Smp cleanup_until(val); 477167465Smp } 47859243Sobrien update_vars(vp); 479167465Smp cleanup_until(vp); 48059243Sobrien } while ((p = *v++) != NULL); 48159243Sobrien} 48259243Sobrien 48359243Sobrienstatic Char * 484167465Smpxset(Char *cp, Char ***vp) 48559243Sobrien{ 486145479Smp Char *dp; 48759243Sobrien 48859243Sobrien if (*cp) { 48959243Sobrien dp = Strsave(cp); 49059243Sobrien --(*vp); 491167465Smp xfree(** vp); 49259243Sobrien **vp = dp; 49359243Sobrien } 49459243Sobrien return (putn(expr(vp))); 49559243Sobrien} 49659243Sobrien 49759243Sobrienstatic Char * 498167465Smpoperate(int op, Char *vp, Char *p) 49959243Sobrien{ 50059243Sobrien Char opr[2]; 50159243Sobrien Char *vec[5]; 502145479Smp Char **v = vec; 50359243Sobrien Char **vecp = v; 504231990Smp tcsh_number_t i; 50559243Sobrien 50659243Sobrien if (op != '=') { 50759243Sobrien if (*vp) 50859243Sobrien *v++ = vp; 509167465Smp opr[0] = op; 51059243Sobrien opr[1] = 0; 51159243Sobrien *v++ = opr; 51259243Sobrien if (op == '<' || op == '>') 51359243Sobrien *v++ = opr; 51459243Sobrien } 51559243Sobrien *v++ = p; 51659243Sobrien *v++ = 0; 51759243Sobrien i = expr(&vecp); 51859243Sobrien if (*vecp) 51959243Sobrien stderror(ERR_NAME | ERR_EXPRESSION); 52059243Sobrien return (putn(i)); 52159243Sobrien} 52259243Sobrien 523167465Smpstatic Char *putp; 52459243Sobrien 525231990SmpChar * 526231990Smpputn(tcsh_number_t n) 52759243Sobrien{ 528231990Smp Char nbuf[1024]; /* Enough even for octal */ 52959243Sobrien 53059243Sobrien putp = nbuf; 53159243Sobrien if (n < 0) { 53259243Sobrien n = -n; 53359243Sobrien *putp++ = '-'; 53459243Sobrien } 53559243Sobrien putn1(n); 53659243Sobrien *putp = 0; 53759243Sobrien return (Strsave(nbuf)); 53859243Sobrien} 53959243Sobrien 54059243Sobrienstatic void 541231990Smpputn1(tcsh_number_t n) 54259243Sobrien{ 54359243Sobrien if (n > 9) 54459243Sobrien putn1(n / 10); 545231990Smp *putp++ = (Char)(n % 10 + '0'); 54659243Sobrien} 54759243Sobrien 548231990Smptcsh_number_t 549231990Smpgetn(const Char *cp) 55059243Sobrien{ 551231990Smp tcsh_number_t n; 55259243Sobrien int sign; 553195609Smp int base; 55459243Sobrien 55559243Sobrien if (!cp) /* PWP: extra error checking */ 55659243Sobrien stderror(ERR_NAME | ERR_BADNUM); 55759243Sobrien 55859243Sobrien sign = 0; 55959243Sobrien if (cp[0] == '+' && cp[1]) 56059243Sobrien cp++; 56159243Sobrien if (*cp == '-') { 56259243Sobrien sign++; 56359243Sobrien cp++; 56459243Sobrien if (!Isdigit(*cp)) 56559243Sobrien stderror(ERR_NAME | ERR_BADNUM); 56659243Sobrien } 567195609Smp 568231990Smp if (cp[0] == '0' && cp[1] && is_set(STRparseoctal)) 569195609Smp base = 8; 570195609Smp else 571195609Smp base = 10; 572195609Smp 57359243Sobrien n = 0; 57459243Sobrien while (Isdigit(*cp)) 575195609Smp { 576195609Smp if (base == 8 && *cp >= '8') 577195609Smp stderror(ERR_NAME | ERR_BADNUM); 578195609Smp n = n * base + *cp++ - '0'; 579195609Smp } 58059243Sobrien if (*cp) 58159243Sobrien stderror(ERR_NAME | ERR_BADNUM); 58259243Sobrien return (sign ? -n : n); 58359243Sobrien} 58459243Sobrien 58559243SobrienChar * 586167465Smpvalue1(Char *var, struct varent *head) 58759243Sobrien{ 588145479Smp struct varent *vp; 58959243Sobrien 59059243Sobrien if (!var || !head) /* PWP: extra error checking */ 59159243Sobrien return (STRNULL); 59259243Sobrien 59359243Sobrien vp = adrof1(var, head); 594100616Smp return ((vp == NULL || vp->vec == NULL || vp->vec[0] == NULL) ? 595100616Smp STRNULL : vp->vec[0]); 59659243Sobrien} 59759243Sobrien 59859243Sobrienstatic struct varent * 599167465Smpmadrof(Char *pat, struct varent *vp) 60059243Sobrien{ 601145479Smp struct varent *vp1; 60259243Sobrien 60359243Sobrien for (vp = vp->v_left; vp; vp = vp->v_right) { 60459243Sobrien if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL) 60559243Sobrien return vp1; 60659243Sobrien if (Gmatch(vp->v_name, pat)) 60759243Sobrien return vp; 60859243Sobrien } 60959243Sobrien return vp; 61059243Sobrien} 61159243Sobrien 61259243Sobrienstruct varent * 613167465Smpadrof1(const Char *name, struct varent *v) 61459243Sobrien{ 61559243Sobrien int cmp; 61659243Sobrien 61759243Sobrien v = v->v_left; 61859243Sobrien while (v && ((cmp = *name - *v->v_name) != 0 || 61959243Sobrien (cmp = Strcmp(name, v->v_name)) != 0)) 62059243Sobrien if (cmp < 0) 62159243Sobrien v = v->v_left; 62259243Sobrien else 62359243Sobrien v = v->v_right; 62459243Sobrien return v; 62559243Sobrien} 62659243Sobrien 627167465Smpvoid 628167465Smpsetcopy(const Char *var, const Char *val, int flags) 629167465Smp{ 630167465Smp Char *copy; 631167465Smp 632167465Smp copy = Strsave(val); 633167465Smp cleanup_push(copy, xfree); 634167465Smp setv(var, copy, flags); 635167465Smp cleanup_ignore(copy); 636167465Smp cleanup_until(copy); 637167465Smp} 638167465Smp 63959243Sobrien/* 64059243Sobrien * The caller is responsible for putting value in a safe place 64159243Sobrien */ 64259243Sobrienvoid 643167465Smpsetv(const Char *var, Char *val, int flags) 64459243Sobrien{ 645167465Smp Char **vec = xmalloc(2 * sizeof(Char **)); 64659243Sobrien 64759243Sobrien vec[0] = val; 64859243Sobrien vec[1] = 0; 64959243Sobrien set1(var, vec, &shvhed, flags); 65059243Sobrien} 65159243Sobrien 65259243Sobrienvoid 653167465Smpset1(const Char *var, Char **vec, struct varent *head, int flags) 65459243Sobrien{ 655145479Smp Char **oldv = vec; 65659243Sobrien 65759243Sobrien if ((flags & VAR_NOGLOB) == 0) { 658167465Smp int gflag; 659167465Smp 660167465Smp gflag = tglob(oldv); 66159243Sobrien if (gflag) { 662167465Smp vec = globall(oldv, gflag); 66359243Sobrien if (vec == 0) { 66459243Sobrien blkfree(oldv); 66559243Sobrien stderror(ERR_NAME | ERR_NOMATCH); 66659243Sobrien } 66759243Sobrien blkfree(oldv); 66859243Sobrien } 66959243Sobrien } 67059243Sobrien /* 67159243Sobrien * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com> 67259243Sobrien */ 67359243Sobrien if ( flags & (VAR_FIRST | VAR_LAST) ) { 67459243Sobrien /* 67559243Sobrien * Code for -f (VAR_FIRST) and -l (VAR_LAST) options. 67659243Sobrien * Method: 67759243Sobrien * Delete all duplicate words leaving "holes" in the word array (vec). 67859243Sobrien * Then remove the "holes", keeping the order of the words unchanged. 67959243Sobrien */ 68059243Sobrien if (vec && vec[0] && vec[1]) { /* more than one word ? */ 68159243Sobrien int i, j; 68259243Sobrien int num_items; 68359243Sobrien 68459243Sobrien for (num_items = 0; vec[num_items]; num_items++) 68559243Sobrien continue; 68659243Sobrien if (flags & VAR_FIRST) { 68759243Sobrien /* delete duplications, keeping first occurance */ 68859243Sobrien for (i = 1; i < num_items; i++) 68959243Sobrien for (j = 0; j < i; j++) 69059243Sobrien /* If have earlier identical item, remove i'th item */ 69159243Sobrien if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) { 692167465Smp xfree(vec[i]); 69359243Sobrien vec[i] = NULL; 69459243Sobrien break; 69559243Sobrien } 69659243Sobrien } else if (flags & VAR_LAST) { 69759243Sobrien /* delete duplications, keeping last occurance */ 69859243Sobrien for (i = 0; i < num_items - 1; i++) 69959243Sobrien for (j = i + 1; j < num_items; j++) 70059243Sobrien /* If have later identical item, remove i'th item */ 70159243Sobrien if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) { 70259243Sobrien /* remove identical item (the first) */ 703167465Smp xfree(vec[i]); 70459243Sobrien vec[i] = NULL; 70559243Sobrien } 70659243Sobrien } 70759243Sobrien /* Compress items - remove empty items */ 70859243Sobrien for (j = i = 0; i < num_items; i++) 70959243Sobrien if (vec[i]) 71059243Sobrien vec[j++] = vec[i]; 71159243Sobrien 71259243Sobrien /* NULL-fy remaining items */ 71359243Sobrien for (; j < num_items; j++) 71459243Sobrien vec[j] = NULL; 71559243Sobrien } 71659243Sobrien /* don't let the attribute propagate */ 71759243Sobrien flags &= ~(VAR_FIRST|VAR_LAST); 71859243Sobrien } 71959243Sobrien setq(var, vec, head, flags); 72059243Sobrien} 72159243Sobrien 72259243Sobrien 72359243Sobrienvoid 724167465Smpsetq(const Char *name, Char **vec, struct varent *p, int flags) 72559243Sobrien{ 726145479Smp struct varent *c; 727145479Smp int f; 72859243Sobrien 72959243Sobrien f = 0; /* tree hangs off the header's left link */ 73059243Sobrien while ((c = p->v_link[f]) != 0) { 73159243Sobrien if ((f = *name - *c->v_name) == 0 && 73259243Sobrien (f = Strcmp(name, c->v_name)) == 0) { 73359243Sobrien if (c->v_flags & VAR_READONLY) 73459243Sobrien stderror(ERR_READONLY|ERR_NAME, c->v_name); 73559243Sobrien blkfree(c->vec); 73659243Sobrien c->v_flags = flags; 73759243Sobrien trim(c->vec = vec); 73859243Sobrien return; 73959243Sobrien } 74059243Sobrien p = c; 74159243Sobrien f = f > 0; 74259243Sobrien } 743167465Smp p->v_link[f] = c = xmalloc(sizeof(struct varent)); 74459243Sobrien c->v_name = Strsave(name); 74559243Sobrien c->v_flags = flags; 74659243Sobrien c->v_bal = 0; 74759243Sobrien c->v_left = c->v_right = 0; 74859243Sobrien c->v_parent = p; 74959243Sobrien balance(p, f, 0); 75059243Sobrien trim(c->vec = vec); 75159243Sobrien} 75259243Sobrien 75359243Sobrien/*ARGSUSED*/ 75459243Sobrienvoid 755167465Smpunset(Char **v, struct command *c) 75659243Sobrien{ 757145479Smp int did_roe, did_edit; 75859243Sobrien 75959243Sobrien USE(c); 76059243Sobrien did_roe = adrof(STRrecognize_only_executables) != NULL; 76159243Sobrien did_edit = adrof(STRedit) != NULL; 76259243Sobrien unset1(v, &shvhed); 763100616Smp 764100616Smp#if defined(FILEC) && defined(TIOCSTI) 765100616Smp if (adrof(STRfilec) == 0) 766100616Smp filec = 0; 767100616Smp#endif /* FILEC && TIOCSTI */ 768100616Smp 76959243Sobrien if (adrof(STRhistchars) == 0) { 77059243Sobrien HIST = '!'; 77159243Sobrien HISTSUB = '^'; 77259243Sobrien } 773131962Smp if (adrof(STRignoreeof) == 0) 774131962Smp numeof = 0; 77559243Sobrien if (adrof(STRpromptchars) == 0) { 776231990Smp PRCH = tcsh ? '>' : '%'; 77759243Sobrien PRCHROOT = '#'; 77859243Sobrien } 779316957Sdchagin if (adrof(STRnoclobber) == 0) 780316957Sdchagin no_clobber = 0; 78159243Sobrien if (adrof(STRhistlit) == 0) 78259243Sobrien HistLit = 0; 78359243Sobrien if (adrof(STRloginsh) == 0) 78459243Sobrien loginsh = 0; 785231990Smp if (adrof(STRanyerror) == 0) 786231990Smp anyerror = 0; 78759243Sobrien if (adrof(STRwordchars) == 0) 78859243Sobrien word_chars = STR_WORD_CHARS; 78959243Sobrien if (adrof(STRedit) == 0) 79059243Sobrien editing = 0; 79159243Sobrien if (adrof(STRbackslash_quote) == 0) 79259243Sobrien bslash_quote = 0; 793195609Smp if (adrof(STRcompat_expr) == 0) 794195609Smp compat_expr = 0; 79559243Sobrien if (adrof(STRsymlinks) == 0) 79659243Sobrien symlinks = 0; 79759243Sobrien if (adrof(STRimplicitcd) == 0) 79859243Sobrien implicit_cd = 0; 799316957Sdchagin if (adrof(STRcdtohome) == 0) 800316957Sdchagin cdtohome = 0; 80183098Smp if (adrof(STRkillring) == 0) 80283098Smp SetKillRing(0); 80359243Sobrien if (did_edit && noediting && adrof(STRedit) == 0) 80459243Sobrien noediting = 0; 805316957Sdchagin if (adrof(STRvimode) == 0) 806316957Sdchagin VImode = 0; 80759243Sobrien if (did_roe && adrof(STRrecognize_only_executables) == 0) 80859243Sobrien tw_cmd_free(); 809316957Sdchagin if (adrof(STRhistory) == 0) 810316957Sdchagin sethistory(0); 81159243Sobrien#ifdef COLOR_LS_F 81259243Sobrien if (adrof(STRcolor) == 0) 81359243Sobrien set_color_context(); 81459243Sobrien#endif /* COLOR_LS_F */ 81559243Sobrien#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) 81659243Sobrien update_dspmbyte_vars(); 81759243Sobrien#endif 818316957Sdchagin update_wordchars(); 81969408Sache#ifdef NLS_CATALOGS 820145479Smp nlsclose(); 82169408Sache nlsinit(); 82269408Sache#endif /* NLS_CATALOGS */ 82359243Sobrien} 82459243Sobrien 82559243Sobrienvoid 826167465Smpunset1(Char *v[], struct varent *head) 82759243Sobrien{ 828145479Smp struct varent *vp; 829145479Smp int cnt; 83059243Sobrien 83159243Sobrien while (*++v) { 83259243Sobrien cnt = 0; 83359243Sobrien while ((vp = madrof(*v, head)) != NULL) 83459243Sobrien if (vp->v_flags & VAR_READONLY) 83559243Sobrien stderror(ERR_READONLY|ERR_NAME, vp->v_name); 83659243Sobrien else 83759243Sobrien unsetv1(vp), cnt++; 83859243Sobrien if (cnt == 0) 83959243Sobrien setname(short2str(*v)); 84059243Sobrien } 84159243Sobrien} 84259243Sobrien 84359243Sobrienvoid 844167465Smpunsetv(Char *var) 84559243Sobrien{ 846145479Smp struct varent *vp; 84759243Sobrien 84859243Sobrien if ((vp = adrof1(var, &shvhed)) == 0) 84959243Sobrien udvar(var); 85059243Sobrien unsetv1(vp); 85159243Sobrien} 85259243Sobrien 85359243Sobrienstatic void 854167465Smpunsetv1(struct varent *p) 85559243Sobrien{ 856145479Smp struct varent *c, *pp; 857145479Smp int f; 85859243Sobrien 85959243Sobrien /* 86059243Sobrien * Free associated memory first to avoid complications. 86159243Sobrien */ 86259243Sobrien blkfree(p->vec); 863167465Smp xfree(p->v_name); 86459243Sobrien /* 86559243Sobrien * If p is missing one child, then we can move the other into where p is. 86659243Sobrien * Otherwise, we find the predecessor of p, which is guaranteed to have no 86759243Sobrien * right child, copy it into p, and move it's left child into it. 86859243Sobrien */ 86959243Sobrien if (p->v_right == 0) 87059243Sobrien c = p->v_left; 87159243Sobrien else if (p->v_left == 0) 87259243Sobrien c = p->v_right; 87359243Sobrien else { 87459243Sobrien for (c = p->v_left; c->v_right; c = c->v_right) 87559243Sobrien continue; 87659243Sobrien p->v_name = c->v_name; 87759243Sobrien p->v_flags = c->v_flags; 87859243Sobrien p->vec = c->vec; 87959243Sobrien p = c; 88059243Sobrien c = p->v_left; 88159243Sobrien } 88259243Sobrien 88359243Sobrien /* 88459243Sobrien * Move c into where p is. 88559243Sobrien */ 88659243Sobrien pp = p->v_parent; 88759243Sobrien f = pp->v_right == p; 88859243Sobrien if ((pp->v_link[f] = c) != 0) 88959243Sobrien c->v_parent = pp; 89059243Sobrien /* 89159243Sobrien * Free the deleted node, and rebalance. 89259243Sobrien */ 893167465Smp xfree(p); 89459243Sobrien balance(pp, f, 1); 89559243Sobrien} 89659243Sobrien 897231990Smp/* Set variable name to NULL. */ 89859243Sobrienvoid 899231990SmpsetNS(const Char *varName) 90059243Sobrien{ 901231990Smp setcopy(varName, STRNULL, VAR_READWRITE); 90259243Sobrien} 90359243Sobrien 90459243Sobrien/*ARGSUSED*/ 90559243Sobrienvoid 906167465Smpshift(Char **v, struct command *c) 90759243Sobrien{ 908145479Smp struct varent *argv; 909145479Smp Char *name; 91059243Sobrien 91159243Sobrien USE(c); 91259243Sobrien v++; 91359243Sobrien name = *v; 91459243Sobrien if (name == 0) 91559243Sobrien name = STRargv; 91659243Sobrien else 91759243Sobrien (void) strip(name); 91859243Sobrien argv = adrof(name); 919100616Smp if (argv == NULL || argv->vec == NULL) 92059243Sobrien udvar(name); 92159243Sobrien if (argv->vec[0] == 0) 92259243Sobrien stderror(ERR_NAME | ERR_NOMORE); 92359243Sobrien lshift(argv->vec, 1); 92459243Sobrien update_vars(name); 92559243Sobrien} 92659243Sobrien 92759243Sobrienstatic void 928167465Smpexportpath(Char **val) 92959243Sobrien{ 930167465Smp struct Strbuf buf = Strbuf_INIT; 931167465Smp Char *exppath; 93259243Sobrien 93359243Sobrien if (val) 93459243Sobrien while (*val) { 935167465Smp Strbuf_append(&buf, *val++); 936167465Smp if (*val == 0 || eq(*val, STRRparen)) 93759243Sobrien break; 938167465Smp Strbuf_append1(&buf, PATHSEP); 939167465Smp } 940167465Smp exppath = Strbuf_finish(&buf); 941167465Smp cleanup_push(exppath, xfree); 942167465Smp tsetenv(STRKPATH, exppath); 943167465Smp cleanup_until(exppath); 94459243Sobrien} 94559243Sobrien 946316957Sdchaginstatic int 947316957Sdchaginset_noclobber(Char **val) 948316957Sdchagin{ 949316957Sdchagin Char *option; 950316957Sdchagin int nc = NOCLOBBER_DEFAULT; 951316957Sdchagin 952316957Sdchagin if (val == NULL) 953316957Sdchagin return nc; 954316957Sdchagin while (*val) { 955316957Sdchagin if (*val == 0 || eq(*val, STRRparen)) 956316957Sdchagin return nc; 957316957Sdchagin 958316957Sdchagin option = *val++; 959316957Sdchagin 960316957Sdchagin if (eq(option, STRnotempty)) 961316957Sdchagin nc |= NOCLOBBER_NOTEMPTY; 962316957Sdchagin else if (eq(option, STRask)) 963316957Sdchagin nc |= NOCLOBBER_ASK; 964316957Sdchagin } 965316957Sdchagin return nc; 966316957Sdchagin} 967316957Sdchagin 96859243Sobrien#ifndef lint 96959243Sobrien /* 97059243Sobrien * Lint thinks these have null effect 97159243Sobrien */ 97259243Sobrien /* macros to do single rotations on node p */ 97359243Sobrien# define rright(p) (\ 97459243Sobrien t = (p)->v_left,\ 97559243Sobrien (t)->v_parent = (p)->v_parent,\ 97659243Sobrien (((p)->v_left = t->v_right) != NULL) ?\ 97759243Sobrien (t->v_right->v_parent = (p)) : 0,\ 97859243Sobrien (t->v_right = (p))->v_parent = t,\ 97959243Sobrien (p) = t) 98059243Sobrien# define rleft(p) (\ 98159243Sobrien t = (p)->v_right,\ 98259243Sobrien ((t)->v_parent = (p)->v_parent,\ 98359243Sobrien ((p)->v_right = t->v_left) != NULL) ? \ 98459243Sobrien (t->v_left->v_parent = (p)) : 0,\ 98559243Sobrien (t->v_left = (p))->v_parent = t,\ 98659243Sobrien (p) = t) 98759243Sobrien#else 98859243Sobrienstatic struct varent * 989167465Smprleft(struct varent *p) 99059243Sobrien{ 99159243Sobrien return (p); 99259243Sobrien} 99359243Sobrienstatic struct varent * 994167465Smprright(struct varent *p) 99559243Sobrien{ 99659243Sobrien return (p); 99759243Sobrien} 99859243Sobrien 99959243Sobrien#endif /* ! lint */ 100059243Sobrien 100159243Sobrien 100259243Sobrien/* 100359243Sobrien * Rebalance a tree, starting at p and up. 100459243Sobrien * F == 0 means we've come from p's left child. 100559243Sobrien * D == 1 means we've just done a delete, otherwise an insert. 100659243Sobrien */ 100759243Sobrienstatic void 1008167465Smpbalance(struct varent *p, int f, int d) 100959243Sobrien{ 1010145479Smp struct varent *pp; 101159243Sobrien 101259243Sobrien#ifndef lint 1013145479Smp struct varent *t; /* used by the rotate macros */ 101459243Sobrien#endif /* !lint */ 1015145479Smp int ff; 101659243Sobrien#ifdef lint 101759243Sobrien ff = 0; /* Sun's lint is dumb! */ 101859243Sobrien#endif 101959243Sobrien 102059243Sobrien /* 102159243Sobrien * Ok, from here on, p is the node we're operating on; pp is it's parent; f 102259243Sobrien * is the branch of p from which we have come; ff is the branch of pp which 102359243Sobrien * is p. 102459243Sobrien */ 102559243Sobrien for (; (pp = p->v_parent) != 0; p = pp, f = ff) { 102659243Sobrien ff = pp->v_right == p; 102759243Sobrien if (f ^ d) { /* right heavy */ 102859243Sobrien switch (p->v_bal) { 102959243Sobrien case -1: /* was left heavy */ 103059243Sobrien p->v_bal = 0; 103159243Sobrien break; 103259243Sobrien case 0: /* was balanced */ 103359243Sobrien p->v_bal = 1; 103459243Sobrien break; 103559243Sobrien case 1: /* was already right heavy */ 103659243Sobrien switch (p->v_right->v_bal) { 1037167465Smp case 1: /* single rotate */ 103859243Sobrien pp->v_link[ff] = rleft(p); 103959243Sobrien p->v_left->v_bal = 0; 104059243Sobrien p->v_bal = 0; 104159243Sobrien break; 104259243Sobrien case 0: /* single rotate */ 104359243Sobrien pp->v_link[ff] = rleft(p); 104459243Sobrien p->v_left->v_bal = 1; 104559243Sobrien p->v_bal = -1; 104659243Sobrien break; 104759243Sobrien case -1: /* double rotate */ 104859243Sobrien (void) rright(p->v_right); 104959243Sobrien pp->v_link[ff] = rleft(p); 105059243Sobrien p->v_left->v_bal = 105159243Sobrien p->v_bal < 1 ? 0 : -1; 105259243Sobrien p->v_right->v_bal = 105359243Sobrien p->v_bal > -1 ? 0 : 1; 105459243Sobrien p->v_bal = 0; 105559243Sobrien break; 105659243Sobrien default: 105759243Sobrien break; 105859243Sobrien } 105959243Sobrien break; 106059243Sobrien default: 106159243Sobrien break; 106259243Sobrien } 106359243Sobrien } 106459243Sobrien else { /* left heavy */ 106559243Sobrien switch (p->v_bal) { 106659243Sobrien case 1: /* was right heavy */ 106759243Sobrien p->v_bal = 0; 106859243Sobrien break; 106959243Sobrien case 0: /* was balanced */ 107059243Sobrien p->v_bal = -1; 107159243Sobrien break; 107259243Sobrien case -1: /* was already left heavy */ 107359243Sobrien switch (p->v_left->v_bal) { 107459243Sobrien case -1: /* single rotate */ 107559243Sobrien pp->v_link[ff] = rright(p); 107659243Sobrien p->v_right->v_bal = 0; 107759243Sobrien p->v_bal = 0; 107859243Sobrien break; 1079167465Smp case 0: /* single rotate */ 108059243Sobrien pp->v_link[ff] = rright(p); 108159243Sobrien p->v_right->v_bal = -1; 108259243Sobrien p->v_bal = 1; 108359243Sobrien break; 108459243Sobrien case 1: /* double rotate */ 108559243Sobrien (void) rleft(p->v_left); 108659243Sobrien pp->v_link[ff] = rright(p); 108759243Sobrien p->v_left->v_bal = 108859243Sobrien p->v_bal < 1 ? 0 : -1; 108959243Sobrien p->v_right->v_bal = 109059243Sobrien p->v_bal > -1 ? 0 : 1; 109159243Sobrien p->v_bal = 0; 109259243Sobrien break; 109359243Sobrien default: 109459243Sobrien break; 109559243Sobrien } 109659243Sobrien break; 109759243Sobrien default: 109859243Sobrien break; 109959243Sobrien } 110059243Sobrien } 110159243Sobrien /* 110259243Sobrien * If from insert, then we terminate when p is balanced. If from 110359243Sobrien * delete, then we terminate when p is unbalanced. 110459243Sobrien */ 110559243Sobrien if ((p->v_bal == 0) ^ d) 110659243Sobrien break; 110759243Sobrien } 110859243Sobrien} 110959243Sobrien 111059243Sobrienvoid 1111167465Smpplist(struct varent *p, int what) 111259243Sobrien{ 1113145479Smp struct varent *c; 1114145479Smp int len; 111559243Sobrien 111659243Sobrien for (;;) { 111759243Sobrien while (p->v_left) 111859243Sobrien p = p->v_left; 111959243Sobrienx: 112059243Sobrien if (p->v_parent == 0) /* is it the header? */ 1121167465Smp break; 112259243Sobrien if ((p->v_flags & what) != 0) { 1123167465Smp if (setintr) { 1124167465Smp int old_pintr_disabled; 1125167465Smp 1126167465Smp pintr_push_enable(&old_pintr_disabled); 1127167465Smp cleanup_until(&old_pintr_disabled); 1128167465Smp } 112959243Sobrien len = blklen(p->vec); 113059243Sobrien xprintf("%S\t", p->v_name); 113159243Sobrien if (len != 1) 113259243Sobrien xputchar('('); 113359243Sobrien blkpr(p->vec); 113459243Sobrien if (len != 1) 113559243Sobrien xputchar(')'); 113659243Sobrien xputchar('\n'); 113759243Sobrien } 113859243Sobrien if (p->v_right) { 113959243Sobrien p = p->v_right; 114059243Sobrien continue; 114159243Sobrien } 114259243Sobrien do { 114359243Sobrien c = p; 114459243Sobrien p = p->v_parent; 114559243Sobrien } while (p->v_right == c); 114659243Sobrien goto x; 114759243Sobrien } 114859243Sobrien} 114959243Sobrien 1150231990Smp#if defined(KANJI) 1151231990Smp# if defined(SHORT_STRINGS) && defined(DSPMBYTE) 1152145479Smpextern int dspmbyte_ls; 115359243Sobrien 115459243Sobrienvoid 1155167465Smpupdate_dspmbyte_vars(void) 115659243Sobrien{ 115759243Sobrien int lp, iskcode; 115859243Sobrien Char *dstr1; 115959243Sobrien struct varent *vp; 116059243Sobrien 116159243Sobrien /* if variable "nokanji" is set, multi-byte display is disabled */ 116259243Sobrien if ((vp = adrof(CHECK_MBYTEVAR)) && !adrof(STRnokanji)) { 116359243Sobrien _enable_mbdisp = 1; 116459243Sobrien dstr1 = vp->vec[0]; 1165145479Smp if(eq (dstr1, STRsjis)) 116659243Sobrien iskcode = 1; 1167145479Smp else if (eq(dstr1, STReuc)) 116859243Sobrien iskcode = 2; 1169145479Smp else if (eq(dstr1, STRbig5)) 117083098Smp iskcode = 3; 1171145479Smp else if (eq(dstr1, STRutf8)) 1172100616Smp iskcode = 4; 117359243Sobrien else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) { 117459243Sobrien iskcode = 0; 117559243Sobrien } 117659243Sobrien else { 117759243Sobrien xprintf(CGETS(18, 2, 117859243Sobrien "Warning: unknown multibyte display; using default(euc(JP))\n")); 117959243Sobrien iskcode = 2; 118059243Sobrien } 118159243Sobrien if (dstr1 && vp->vec[1] && eq(vp->vec[1], STRls)) 118259243Sobrien dspmbyte_ls = 1; 118359243Sobrien else 118459243Sobrien dspmbyte_ls = 0; 118559243Sobrien for (lp = 0; lp < 256 && iskcode > 0; lp++) { 118659243Sobrien switch (iskcode) { 118759243Sobrien case 1: 118859243Sobrien /* Shift-JIS */ 118959243Sobrien _cmap[lp] = _cmap_mbyte[lp]; 119059243Sobrien _mbmap[lp] = _mbmap_sjis[lp]; 119159243Sobrien break; 119259243Sobrien case 2: 119359243Sobrien /* 2 ... euc */ 119459243Sobrien _cmap[lp] = _cmap_mbyte[lp]; 119559243Sobrien _mbmap[lp] = _mbmap_euc[lp]; 119659243Sobrien break; 119783098Smp case 3: 119883098Smp /* 3 ... big5 */ 119983098Smp _cmap[lp] = _cmap_mbyte[lp]; 120083098Smp _mbmap[lp] = _mbmap_big5[lp]; 120183098Smp break; 1202100616Smp case 4: 1203100616Smp /* 4 ... utf8 */ 1204100616Smp _cmap[lp] = _cmap_mbyte[lp]; 1205100616Smp _mbmap[lp] = _mbmap_utf8[lp]; 1206100616Smp break; 120759243Sobrien default: 120859243Sobrien xprintf(CGETS(18, 3, 120959243Sobrien "Warning: unknown multibyte code %d; multibyte disabled\n"), 121059243Sobrien iskcode); 121159243Sobrien _cmap[lp] = _cmap_c[lp]; 121259243Sobrien _mbmap[lp] = 0; /* Default map all 0 */ 121359243Sobrien _enable_mbdisp = 0; 121459243Sobrien break; 121559243Sobrien } 121659243Sobrien } 121759243Sobrien if (iskcode == 0) { 121859243Sobrien /* check original table */ 121959243Sobrien if (Strlen(dstr1) != 256) { 122059243Sobrien xprintf(CGETS(18, 4, 122159243Sobrien "Warning: Invalid multibyte table length (%d); multibyte disabled\n"), 122259243Sobrien Strlen(dstr1)); 122359243Sobrien _enable_mbdisp = 0; 122459243Sobrien } 122559243Sobrien for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) { 122659243Sobrien if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) { 122759243Sobrien xprintf(CGETS(18, 4, 122859243Sobrien "Warning: bad multibyte code at offset +%d; multibyte diabled\n"), 122959243Sobrien lp); 123059243Sobrien _enable_mbdisp = 0; 123159243Sobrien break; 123259243Sobrien } 123359243Sobrien } 123459243Sobrien /* set original table */ 123559243Sobrien for (lp = 0; lp < 256; lp++) { 123659243Sobrien if (_enable_mbdisp == 1) { 123759243Sobrien _cmap[lp] = _cmap_mbyte[lp]; 123859243Sobrien _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f); 123959243Sobrien } 124059243Sobrien else { 124159243Sobrien _cmap[lp] = _cmap_c[lp]; 124259243Sobrien _mbmap[lp] = 0; /* Default map all 0 */ 124359243Sobrien } 124459243Sobrien } 124559243Sobrien } 124659243Sobrien } 124759243Sobrien else { 124859243Sobrien for (lp = 0; lp < 256; lp++) { 124959243Sobrien _cmap[lp] = _cmap_c[lp]; 125059243Sobrien _mbmap[lp] = 0; /* Default map all 0 */ 125159243Sobrien } 125259243Sobrien _enable_mbdisp = 0; 125359243Sobrien dspmbyte_ls = 0; 125459243Sobrien } 125559243Sobrien#ifdef MBYTEDEBUG /* Sorry, use for beta testing */ 125659243Sobrien { 125759243Sobrien Char mbmapstr[300]; 1258167465Smp for (lp = 0; lp < 256; lp++) 125959243Sobrien mbmapstr[lp] = _mbmap[lp] + '0'; 1260167465Smp mbmapstr[lp] = 0; 1261167465Smp setcopy(STRmbytemap, mbmapstr, VAR_READWRITE); 126259243Sobrien } 126359243Sobrien#endif /* MBYTEMAP */ 126459243Sobrien} 126559243Sobrien 126659243Sobrien/* dspkanji/dspmbyte autosetting */ 126759243Sobrien/* PATCH IDEA FROM Issei.Suzuki VERY THANKS */ 126859243Sobrienvoid 1269167465Smpautoset_dspmbyte(const Char *pcp) 127059243Sobrien{ 127159243Sobrien int i; 1272167465Smp static const struct dspm_autoset_Table { 127359243Sobrien Char *n; 127459243Sobrien Char *v; 127559243Sobrien } dspmt[] = { 1276145479Smp { STRLANGEUCJP, STReuc }, 1277145479Smp { STRLANGEUCKR, STReuc }, 1278145479Smp { STRLANGEUCZH, STReuc }, 1279145479Smp { STRLANGEUCJPB, STReuc }, 1280145479Smp { STRLANGEUCKRB, STReuc }, 1281145479Smp { STRLANGEUCZHB, STReuc }, 1282231990Smp#ifdef __linux__ 1283145479Smp { STRLANGEUCJPC, STReuc }, 1284131962Smp#endif 1285145479Smp { STRLANGSJIS, STRsjis }, 1286145479Smp { STRLANGSJISB, STRsjis }, 1287145479Smp { STRLANGBIG5, STRbig5 }, 1288145479Smp { STRstarutfstar8, STRutf8 }, 128959243Sobrien { NULL, NULL } 129059243Sobrien }; 1291167465Smp#if defined(HAVE_NL_LANGINFO) && defined(CODESET) 1292167465Smp static const struct dspm_autoset_Table dspmc[] = { 1293145479Smp { STRstarutfstar8, STRutf8 }, 1294145479Smp { STReuc, STReuc }, 1295145479Smp { STRGB2312, STReuc }, 1296145479Smp { STRLANGBIG5, STRbig5 }, 1297145479Smp { NULL, NULL } 1298145479Smp }; 1299145479Smp Char *codeset; 130059243Sobrien 1301145479Smp codeset = str2short(nl_langinfo(CODESET)); 1302145479Smp if (*codeset != '\0') { 1303145479Smp for (i = 0; dspmc[i].n; i++) { 1304167465Smp const Char *estr; 1305145479Smp if (dspmc[i].n[0] && t_pmatch(pcp, dspmc[i].n, &estr, 0) > 0) { 1306167465Smp setcopy(CHECK_MBYTEVAR, dspmc[i].v, VAR_READWRITE); 1307145479Smp update_dspmbyte_vars(); 1308145479Smp return; 1309145479Smp } 1310145479Smp } 1311145479Smp } 1312145479Smp#endif 1313145479Smp 131459243Sobrien if (*pcp == '\0') 131559243Sobrien return; 131659243Sobrien 131759243Sobrien for (i = 0; dspmt[i].n; i++) { 1318167465Smp const Char *estr; 1319145479Smp if (dspmt[i].n[0] && t_pmatch(pcp, dspmt[i].n, &estr, 0) > 0) { 1320167465Smp setcopy(CHECK_MBYTEVAR, dspmt[i].v, VAR_READWRITE); 132159243Sobrien update_dspmbyte_vars(); 132259243Sobrien break; 132359243Sobrien } 132459243Sobrien } 132559243Sobrien} 1326231990Smp# elif defined(AUTOSET_KANJI) 1327231990Smpvoid 1328231990Smpautoset_kanji(void) 1329231990Smp{ 1330231990Smp char *codeset = nl_langinfo(CODESET); 1331231990Smp 1332231990Smp if (*codeset == '\0') { 1333231990Smp if (adrof(STRnokanji) == NULL) 1334231990Smp setNS(STRnokanji); 1335231990Smp return; 1336231990Smp } 1337231990Smp 1338231990Smp if (strcasestr(codeset, "SHIFT_JIS") == (char*)0) { 1339231990Smp if (adrof(STRnokanji) == NULL) 1340231990Smp setNS(STRnokanji); 1341231990Smp return; 1342231990Smp } 1343231990Smp 1344231990Smp if (adrof(STRnokanji) != NULL) 1345231990Smp unsetv(STRnokanji); 1346231990Smp} 134759243Sobrien#endif 1348231990Smp#endif 1349316957Sdchagin 1350316957Sdchaginvoid 1351316957Sdchaginupdate_wordchars(void) 1352316957Sdchagin{ 1353316957Sdchagin if ((word_chars == STR_WORD_CHARS) || (word_chars == STR_WORD_CHARS_VI)) { 1354316957Sdchagin word_chars = (VImode ? STR_WORD_CHARS_VI : STR_WORD_CHARS); 1355316957Sdchagin } 1356316957Sdchagin} 1357