1232633Smp/* $Header: /p/tcsh/cvsroot/tcsh/sh.set.c,v 3.83 2012/01/15 17:15:28 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 35232633SmpRCSID("$tcsh: sh.set.c,v 3.83 2012/01/15 17:15:28 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 *); 53232633Smpstatic 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); 5859243Sobrien 5959243Sobrien/* 6059243Sobrien * C Shell 6159243Sobrien */ 6259243Sobrien 6359243Sobrienstatic void 64167465Smpupdate_vars(Char *vp) 6559243Sobrien{ 6659243Sobrien if (eq(vp, STRpath)) { 67167465Smp struct varent *p = adrof(STRpath); 68167465Smp if (p == NULL) 69167465Smp stderror(ERR_NAME | ERR_UNDVAR); 70167465Smp else { 71167465Smp exportpath(p->vec); 72167465Smp dohash(NULL, NULL); 73167465Smp } 7459243Sobrien } 7559243Sobrien else if (eq(vp, STRhistchars)) { 76145479Smp Char *pn = varval(vp); 7759243Sobrien 7859243Sobrien HIST = *pn++; 79232633Smp if (HIST) 80232633Smp HISTSUB = *pn; 81232633Smp else 82232633Smp HISTSUB = HIST; 8359243Sobrien } 8459243Sobrien else if (eq(vp, STRpromptchars)) { 85145479Smp Char *pn = varval(vp); 8659243Sobrien 8759243Sobrien PRCH = *pn++; 88232633Smp if (PRCH) 89232633Smp PRCHROOT = *pn; 90232633Smp else 91232633Smp PRCHROOT = PRCH; 9259243Sobrien } 9359243Sobrien else if (eq(vp, STRhistlit)) { 9459243Sobrien HistLit = 1; 9559243Sobrien } 9659243Sobrien else if (eq(vp, STRuser)) { 9759243Sobrien tsetenv(STRKUSER, varval(vp)); 9859243Sobrien tsetenv(STRLOGNAME, varval(vp)); 9959243Sobrien } 10059243Sobrien else if (eq(vp, STRgroup)) { 10159243Sobrien tsetenv(STRKGROUP, varval(vp)); 10259243Sobrien } 10359243Sobrien else if (eq(vp, STRwordchars)) { 10459243Sobrien word_chars = varval(vp); 10559243Sobrien } 10659243Sobrien else if (eq(vp, STRloginsh)) { 10759243Sobrien loginsh = 1; 10859243Sobrien } 109232633Smp else if (eq(vp, STRanyerror)) { 110232633Smp anyerror = 1; 111232633Smp } 11259243Sobrien else if (eq(vp, STRsymlinks)) { 113145479Smp Char *pn = varval(vp); 11459243Sobrien 11559243Sobrien if (eq(pn, STRignore)) 11659243Sobrien symlinks = SYM_IGNORE; 11759243Sobrien else if (eq(pn, STRexpand)) 11859243Sobrien symlinks = SYM_EXPAND; 11959243Sobrien else if (eq(pn, STRchase)) 12059243Sobrien symlinks = SYM_CHASE; 12159243Sobrien else 12259243Sobrien symlinks = 0; 12359243Sobrien } 12459243Sobrien else if (eq(vp, STRterm)) { 12559243Sobrien Char *cp = varval(vp); 12659243Sobrien tsetenv(STRKTERM, cp); 12759243Sobrien#ifdef DOESNT_WORK_RIGHT 12859243Sobrien cp = getenv("TERMCAP"); 12959243Sobrien if (cp && (*cp != '/')) /* if TERMCAP and not a path */ 13059243Sobrien Unsetenv(STRTERMCAP); 13159243Sobrien#endif /* DOESNT_WORK_RIGHT */ 13259243Sobrien GotTermCaps = 0; 13359243Sobrien if (noediting && Strcmp(cp, STRnetwork) != 0 && 13459243Sobrien Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) { 13559243Sobrien editing = 1; 13659243Sobrien noediting = 0; 137167465Smp setNS(STRedit); 13859243Sobrien } 13959243Sobrien ed_Init(); /* reset the editor */ 14059243Sobrien } 14159243Sobrien else if (eq(vp, STRhome)) { 142167465Smp Char *cp, *canon; 14359243Sobrien 14459243Sobrien cp = Strsave(varval(vp)); /* get the old value back */ 145167465Smp cleanup_push(cp, xfree); 14659243Sobrien 14759243Sobrien /* 14859243Sobrien * convert to cononical pathname (possibly resolving symlinks) 14959243Sobrien */ 150167465Smp canon = dcanon(cp, cp); 151167465Smp cleanup_ignore(cp); 152167465Smp cleanup_until(cp); 153167465Smp cleanup_push(canon, xfree); 15459243Sobrien 155167465Smp setcopy(vp, canon, VAR_READWRITE); /* have to save the new val */ 15659243Sobrien 15759243Sobrien /* and now mirror home with HOME */ 158167465Smp tsetenv(STRKHOME, canon); 15959243Sobrien /* fix directory stack for new tilde home */ 16059243Sobrien dtilde(); 161167465Smp cleanup_until(canon); 16259243Sobrien } 16359243Sobrien else if (eq(vp, STRedit)) { 16459243Sobrien editing = 1; 16559243Sobrien noediting = 0; 16659243Sobrien /* PWP: add more stuff in here later */ 16759243Sobrien } 16859243Sobrien else if (eq(vp, STRshlvl)) { 16959243Sobrien tsetenv(STRKSHLVL, varval(vp)); 17059243Sobrien } 171131962Smp else if (eq(vp, STRignoreeof)) { 172131962Smp Char *cp; 173131962Smp numeof = 0; 174131962Smp for ((cp = varval(STRignoreeof)); cp && *cp; cp++) { 175131962Smp if (!Isdigit(*cp)) { 176131962Smp numeof = 0; 177131962Smp break; 178131962Smp } 179131962Smp numeof = numeof * 10 + *cp - '0'; 180131962Smp } 181131962Smp if (numeof <= 0) numeof = 26; /* Sanity check */ 182131962Smp } 18359243Sobrien else if (eq(vp, STRbackslash_quote)) { 18459243Sobrien bslash_quote = 1; 18559243Sobrien } 186195609Smp else if (eq(vp, STRcompat_expr)) { 187195609Smp compat_expr = 1; 188195609Smp } 18959243Sobrien else if (eq(vp, STRdirstack)) { 19059243Sobrien dsetstack(); 19159243Sobrien } 19259243Sobrien else if (eq(vp, STRrecognize_only_executables)) { 19359243Sobrien tw_cmd_free(); 19459243Sobrien } 19583098Smp else if (eq(vp, STRkillring)) { 196232633Smp SetKillRing((int)getn(varval(vp))); 19783098Smp } 19859243Sobrien#ifndef HAVENOUTMP 19959243Sobrien else if (eq(vp, STRwatch)) { 20059243Sobrien resetwatch(); 20159243Sobrien } 20259243Sobrien#endif /* HAVENOUTMP */ 20359243Sobrien else if (eq(vp, STRimplicitcd)) { 20459243Sobrien implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1); 20559243Sobrien } 20659243Sobrien#ifdef COLOR_LS_F 20759243Sobrien else if (eq(vp, STRcolor)) { 20859243Sobrien set_color_context(); 20959243Sobrien } 21059243Sobrien#endif /* COLOR_LS_F */ 21159243Sobrien#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) 21259243Sobrien else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) { 21359243Sobrien update_dspmbyte_vars(); 21459243Sobrien } 21559243Sobrien#endif 21669408Sache#ifdef NLS_CATALOGS 21769408Sache else if (eq(vp, STRcatalog)) { 218145479Smp nlsclose(); 21969408Sache nlsinit(); 22069408Sache } 221100616Smp#if defined(FILEC) && defined(TIOCSTI) 222100616Smp else if (eq(vp, STRfilec)) 223100616Smp filec = 1; 224100616Smp#endif 22569408Sache#endif /* NLS_CATALOGS */ 22659243Sobrien} 22759243Sobrien 22859243Sobrien 22959243Sobrien/*ARGSUSED*/ 23059243Sobrienvoid 231167465Smpdoset(Char **v, struct command *c) 23259243Sobrien{ 233145479Smp Char *p; 234232633Smp Char *vp; 23559243Sobrien Char **vecp; 236145479Smp int hadsub; 23759243Sobrien int subscr; 23859243Sobrien int flags = VAR_READWRITE; 239145479Smp int first_match = 0; 240145479Smp int last_match = 0; 241145479Smp int changed = 0; 24259243Sobrien 24359243Sobrien USE(c); 24459243Sobrien v++; 24559243Sobrien do { 24659243Sobrien changed = 0; 24759243Sobrien /* 24859243Sobrien * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov> 24959243Sobrien */ 25059243Sobrien if (*v && eq(*v, STRmr)) { 25159243Sobrien flags = VAR_READONLY; 25259243Sobrien v++; 25359243Sobrien changed = 1; 25459243Sobrien } 25559243Sobrien if (*v && eq(*v, STRmf) && !last_match) { 25659243Sobrien first_match = 1; 25759243Sobrien v++; 25859243Sobrien changed = 1; 25959243Sobrien } 26059243Sobrien if (*v && eq(*v, STRml) && !first_match) { 26159243Sobrien last_match = 1; 26259243Sobrien v++; 26359243Sobrien changed = 1; 26459243Sobrien } 26559243Sobrien } while(changed); 26659243Sobrien p = *v++; 26759243Sobrien if (p == 0) { 26859243Sobrien plist(&shvhed, flags); 26959243Sobrien return; 27059243Sobrien } 27159243Sobrien do { 27259243Sobrien hadsub = 0; 27359243Sobrien vp = p; 274232633Smp if (!letter(*p)) 27559243Sobrien stderror(ERR_NAME | ERR_VARBEGIN); 276232633Smp do { 277232633Smp p++; 278232633Smp } while (alnum(*p)); 27959243Sobrien if (*p == '[') { 28059243Sobrien hadsub++; 28159243Sobrien p = getinx(p, &subscr); 28259243Sobrien } 283232633Smp if (*p != '\0' && *p != '=') 284232633Smp stderror(ERR_NAME | ERR_VARALNUM); 285232633Smp if (*p == '=') { 286232633Smp *p++ = '\0'; 287232633Smp if (*p == '\0' && *v != NULL && **v == '(') 28859243Sobrien p = *v++; 28959243Sobrien } 29059243Sobrien else if (*v && eq(*v, STRequal)) { 291232633Smp if (*++v != NULL) 29259243Sobrien p = *v++; 29359243Sobrien } 29459243Sobrien if (eq(p, STRLparen)) { 295145479Smp Char **e = v; 29659243Sobrien 29759243Sobrien if (hadsub) 29859243Sobrien stderror(ERR_NAME | ERR_SYNTAX); 29959243Sobrien for (;;) { 30059243Sobrien if (!*e) 30159243Sobrien stderror(ERR_NAME | ERR_MISSING, ')'); 30259243Sobrien if (**e == ')') 30359243Sobrien break; 30459243Sobrien e++; 30559243Sobrien } 30659243Sobrien p = *e; 30759243Sobrien *e = 0; 30859243Sobrien vecp = saveblk(v); 30959243Sobrien if (first_match) 31059243Sobrien flags |= VAR_FIRST; 31159243Sobrien else if (last_match) 31259243Sobrien flags |= VAR_LAST; 31359243Sobrien 31459243Sobrien set1(vp, vecp, &shvhed, flags); 31559243Sobrien *e = p; 31659243Sobrien v = e + 1; 31759243Sobrien } 318167465Smp else if (hadsub) { 319167465Smp Char *copy; 320167465Smp 321167465Smp copy = Strsave(p); 322167465Smp cleanup_push(copy, xfree); 323167465Smp asx(vp, subscr, copy); 324167465Smp cleanup_ignore(copy); 325167465Smp cleanup_until(copy); 326167465Smp } 32759243Sobrien else 328167465Smp setv(vp, Strsave(p), flags); 32959243Sobrien update_vars(vp); 33059243Sobrien } while ((p = *v++) != NULL); 33159243Sobrien} 33259243Sobrien 33359243Sobrienstatic Char * 334167465Smpgetinx(Char *cp, int *ip) 33559243Sobrien{ 33659243Sobrien *ip = 0; 33759243Sobrien *cp++ = 0; 33859243Sobrien while (*cp && Isdigit(*cp)) 33959243Sobrien *ip = *ip * 10 + *cp++ - '0'; 34059243Sobrien if (*cp++ != ']') 34159243Sobrien stderror(ERR_NAME | ERR_SUBSCRIPT); 34259243Sobrien return (cp); 34359243Sobrien} 34459243Sobrien 34559243Sobrienstatic void 346167465Smpasx(Char *vp, int subscr, Char *p) 34759243Sobrien{ 348145479Smp struct varent *v = getvx(vp, subscr); 349167465Smp Char *prev; 35059243Sobrien 35159243Sobrien if (v->v_flags & VAR_READONLY) 35259243Sobrien stderror(ERR_READONLY|ERR_NAME, v->v_name); 353167465Smp prev = v->vec[subscr - 1]; 354167465Smp cleanup_push(prev, xfree); 35559243Sobrien v->vec[subscr - 1] = globone(p, G_APPEND); 356167465Smp cleanup_until(prev); 35759243Sobrien} 35859243Sobrien 35959243Sobrienstatic struct varent * 360167465Smpgetvx(Char *vp, int subscr) 36159243Sobrien{ 362145479Smp struct varent *v = adrof(vp); 36359243Sobrien 36459243Sobrien if (v == 0) 36559243Sobrien udvar(vp); 36659243Sobrien if (subscr < 1 || subscr > blklen(v->vec)) 36759243Sobrien stderror(ERR_NAME | ERR_RANGE); 36859243Sobrien return (v); 36959243Sobrien} 37059243Sobrien 37159243Sobrien/*ARGSUSED*/ 37259243Sobrienvoid 373167465Smpdolet(Char **v, struct command *dummy) 37459243Sobrien{ 375145479Smp Char *p; 37659243Sobrien Char *vp, c, op; 377145479Smp int hadsub; 37859243Sobrien int subscr; 37959243Sobrien 38059243Sobrien USE(dummy); 38159243Sobrien v++; 38259243Sobrien p = *v++; 38359243Sobrien if (p == 0) { 38459243Sobrien prvars(); 38559243Sobrien return; 38659243Sobrien } 38759243Sobrien do { 38859243Sobrien hadsub = 0; 38959243Sobrien vp = p; 39059243Sobrien if (letter(*p)) 39159243Sobrien for (; alnum(*p); p++) 39259243Sobrien continue; 39359243Sobrien if (vp == p || !letter(*vp)) 39459243Sobrien stderror(ERR_NAME | ERR_VARBEGIN); 39559243Sobrien if (*p == '[') { 39659243Sobrien hadsub++; 39759243Sobrien p = getinx(p, &subscr); 39859243Sobrien } 39959243Sobrien if (*p == 0 && *v) 40059243Sobrien p = *v++; 40159243Sobrien if ((op = *p) != 0) 40259243Sobrien *p++ = 0; 40359243Sobrien else 40459243Sobrien stderror(ERR_NAME | ERR_ASSIGN); 40559243Sobrien 40659243Sobrien /* 40759243Sobrien * if there is no expression after the '=' then print a "Syntax Error" 40859243Sobrien * message - strike 40959243Sobrien */ 41059243Sobrien if (*p == '\0' && *v == NULL) 41159243Sobrien stderror(ERR_NAME | ERR_ASSIGN); 41259243Sobrien 41359243Sobrien vp = Strsave(vp); 414167465Smp cleanup_push(vp, xfree); 41559243Sobrien if (op == '=') { 41659243Sobrien c = '='; 41759243Sobrien p = xset(p, &v); 41859243Sobrien } 41959243Sobrien else { 42059243Sobrien c = *p++; 42159243Sobrien if (any("+-", c)) { 42259243Sobrien if (c != op || *p) 42359243Sobrien stderror(ERR_NAME | ERR_UNKNOWNOP); 42459243Sobrien p = Strsave(STR1); 42559243Sobrien } 42659243Sobrien else { 42759243Sobrien if (any("<>", op)) { 42859243Sobrien if (c != op) 42959243Sobrien stderror(ERR_NAME | ERR_UNKNOWNOP); 43059243Sobrien stderror(ERR_NAME | ERR_SYNTAX); 43159243Sobrien } 43259243Sobrien if (c != '=') 43359243Sobrien stderror(ERR_NAME | ERR_UNKNOWNOP); 43459243Sobrien p = xset(p, &v); 43559243Sobrien } 43659243Sobrien } 437167465Smp cleanup_push(p, xfree); 43859243Sobrien if (op == '=') { 43959243Sobrien if (hadsub) 44059243Sobrien asx(vp, subscr, p); 44159243Sobrien else 442167465Smp setv(vp, p, VAR_READWRITE); 443167465Smp cleanup_ignore(p); 44459243Sobrien } 44559243Sobrien else if (hadsub) { 44659243Sobrien struct varent *gv = getvx(vp, subscr); 447167465Smp Char *val; 44859243Sobrien 449167465Smp val = operate(op, gv->vec[subscr - 1], p); 450167465Smp cleanup_push(val, xfree); 451167465Smp asx(vp, subscr, val); 452167465Smp cleanup_ignore(val); 453167465Smp cleanup_until(val); 45459243Sobrien } 455167465Smp else { 456167465Smp Char *val; 457167465Smp 458167465Smp val = operate(op, varval(vp), p); 459167465Smp cleanup_push(val, xfree); 460167465Smp setv(vp, val, VAR_READWRITE); 461167465Smp cleanup_ignore(val); 462167465Smp cleanup_until(val); 463167465Smp } 46459243Sobrien update_vars(vp); 465167465Smp cleanup_until(vp); 46659243Sobrien } while ((p = *v++) != NULL); 46759243Sobrien} 46859243Sobrien 46959243Sobrienstatic Char * 470167465Smpxset(Char *cp, Char ***vp) 47159243Sobrien{ 472145479Smp Char *dp; 47359243Sobrien 47459243Sobrien if (*cp) { 47559243Sobrien dp = Strsave(cp); 47659243Sobrien --(*vp); 477167465Smp xfree(** vp); 47859243Sobrien **vp = dp; 47959243Sobrien } 48059243Sobrien return (putn(expr(vp))); 48159243Sobrien} 48259243Sobrien 48359243Sobrienstatic Char * 484167465Smpoperate(int op, Char *vp, Char *p) 48559243Sobrien{ 48659243Sobrien Char opr[2]; 48759243Sobrien Char *vec[5]; 488145479Smp Char **v = vec; 48959243Sobrien Char **vecp = v; 490232633Smp tcsh_number_t i; 49159243Sobrien 49259243Sobrien if (op != '=') { 49359243Sobrien if (*vp) 49459243Sobrien *v++ = vp; 495167465Smp opr[0] = op; 49659243Sobrien opr[1] = 0; 49759243Sobrien *v++ = opr; 49859243Sobrien if (op == '<' || op == '>') 49959243Sobrien *v++ = opr; 50059243Sobrien } 50159243Sobrien *v++ = p; 50259243Sobrien *v++ = 0; 50359243Sobrien i = expr(&vecp); 50459243Sobrien if (*vecp) 50559243Sobrien stderror(ERR_NAME | ERR_EXPRESSION); 50659243Sobrien return (putn(i)); 50759243Sobrien} 50859243Sobrien 509167465Smpstatic Char *putp; 51059243Sobrien 511232633SmpChar * 512232633Smpputn(tcsh_number_t n) 51359243Sobrien{ 514232633Smp Char nbuf[1024]; /* Enough even for octal */ 51559243Sobrien 51659243Sobrien putp = nbuf; 51759243Sobrien if (n < 0) { 51859243Sobrien n = -n; 51959243Sobrien *putp++ = '-'; 52059243Sobrien } 52159243Sobrien putn1(n); 52259243Sobrien *putp = 0; 52359243Sobrien return (Strsave(nbuf)); 52459243Sobrien} 52559243Sobrien 52659243Sobrienstatic void 527232633Smpputn1(tcsh_number_t n) 52859243Sobrien{ 52959243Sobrien if (n > 9) 53059243Sobrien putn1(n / 10); 531232633Smp *putp++ = (Char)(n % 10 + '0'); 53259243Sobrien} 53359243Sobrien 534232633Smptcsh_number_t 535232633Smpgetn(const Char *cp) 53659243Sobrien{ 537232633Smp tcsh_number_t n; 53859243Sobrien int sign; 539195609Smp int base; 54059243Sobrien 54159243Sobrien if (!cp) /* PWP: extra error checking */ 54259243Sobrien stderror(ERR_NAME | ERR_BADNUM); 54359243Sobrien 54459243Sobrien sign = 0; 54559243Sobrien if (cp[0] == '+' && cp[1]) 54659243Sobrien cp++; 54759243Sobrien if (*cp == '-') { 54859243Sobrien sign++; 54959243Sobrien cp++; 55059243Sobrien if (!Isdigit(*cp)) 55159243Sobrien stderror(ERR_NAME | ERR_BADNUM); 55259243Sobrien } 553195609Smp 554232633Smp if (cp[0] == '0' && cp[1] && is_set(STRparseoctal)) 555195609Smp base = 8; 556195609Smp else 557195609Smp base = 10; 558195609Smp 55959243Sobrien n = 0; 56059243Sobrien while (Isdigit(*cp)) 561195609Smp { 562195609Smp if (base == 8 && *cp >= '8') 563195609Smp stderror(ERR_NAME | ERR_BADNUM); 564195609Smp n = n * base + *cp++ - '0'; 565195609Smp } 56659243Sobrien if (*cp) 56759243Sobrien stderror(ERR_NAME | ERR_BADNUM); 56859243Sobrien return (sign ? -n : n); 56959243Sobrien} 57059243Sobrien 57159243SobrienChar * 572167465Smpvalue1(Char *var, struct varent *head) 57359243Sobrien{ 574145479Smp struct varent *vp; 57559243Sobrien 57659243Sobrien if (!var || !head) /* PWP: extra error checking */ 57759243Sobrien return (STRNULL); 57859243Sobrien 57959243Sobrien vp = adrof1(var, head); 580100616Smp return ((vp == NULL || vp->vec == NULL || vp->vec[0] == NULL) ? 581100616Smp STRNULL : vp->vec[0]); 58259243Sobrien} 58359243Sobrien 58459243Sobrienstatic struct varent * 585167465Smpmadrof(Char *pat, struct varent *vp) 58659243Sobrien{ 587145479Smp struct varent *vp1; 58859243Sobrien 58959243Sobrien for (vp = vp->v_left; vp; vp = vp->v_right) { 59059243Sobrien if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL) 59159243Sobrien return vp1; 59259243Sobrien if (Gmatch(vp->v_name, pat)) 59359243Sobrien return vp; 59459243Sobrien } 59559243Sobrien return vp; 59659243Sobrien} 59759243Sobrien 59859243Sobrienstruct varent * 599167465Smpadrof1(const Char *name, struct varent *v) 60059243Sobrien{ 60159243Sobrien int cmp; 60259243Sobrien 60359243Sobrien v = v->v_left; 60459243Sobrien while (v && ((cmp = *name - *v->v_name) != 0 || 60559243Sobrien (cmp = Strcmp(name, v->v_name)) != 0)) 60659243Sobrien if (cmp < 0) 60759243Sobrien v = v->v_left; 60859243Sobrien else 60959243Sobrien v = v->v_right; 61059243Sobrien return v; 61159243Sobrien} 61259243Sobrien 613167465Smpvoid 614167465Smpsetcopy(const Char *var, const Char *val, int flags) 615167465Smp{ 616167465Smp Char *copy; 617167465Smp 618167465Smp copy = Strsave(val); 619167465Smp cleanup_push(copy, xfree); 620167465Smp setv(var, copy, flags); 621167465Smp cleanup_ignore(copy); 622167465Smp cleanup_until(copy); 623167465Smp} 624167465Smp 62559243Sobrien/* 62659243Sobrien * The caller is responsible for putting value in a safe place 62759243Sobrien */ 62859243Sobrienvoid 629167465Smpsetv(const Char *var, Char *val, int flags) 63059243Sobrien{ 631167465Smp Char **vec = xmalloc(2 * sizeof(Char **)); 63259243Sobrien 63359243Sobrien vec[0] = val; 63459243Sobrien vec[1] = 0; 63559243Sobrien set1(var, vec, &shvhed, flags); 63659243Sobrien} 63759243Sobrien 63859243Sobrienvoid 639167465Smpset1(const Char *var, Char **vec, struct varent *head, int flags) 64059243Sobrien{ 641145479Smp Char **oldv = vec; 64259243Sobrien 64359243Sobrien if ((flags & VAR_NOGLOB) == 0) { 644167465Smp int gflag; 645167465Smp 646167465Smp gflag = tglob(oldv); 64759243Sobrien if (gflag) { 648167465Smp vec = globall(oldv, gflag); 64959243Sobrien if (vec == 0) { 65059243Sobrien blkfree(oldv); 65159243Sobrien stderror(ERR_NAME | ERR_NOMATCH); 65259243Sobrien } 65359243Sobrien blkfree(oldv); 65459243Sobrien } 65559243Sobrien } 65659243Sobrien /* 65759243Sobrien * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com> 65859243Sobrien */ 65959243Sobrien if ( flags & (VAR_FIRST | VAR_LAST) ) { 66059243Sobrien /* 66159243Sobrien * Code for -f (VAR_FIRST) and -l (VAR_LAST) options. 66259243Sobrien * Method: 66359243Sobrien * Delete all duplicate words leaving "holes" in the word array (vec). 66459243Sobrien * Then remove the "holes", keeping the order of the words unchanged. 66559243Sobrien */ 66659243Sobrien if (vec && vec[0] && vec[1]) { /* more than one word ? */ 66759243Sobrien int i, j; 66859243Sobrien int num_items; 66959243Sobrien 67059243Sobrien for (num_items = 0; vec[num_items]; num_items++) 67159243Sobrien continue; 67259243Sobrien if (flags & VAR_FIRST) { 67359243Sobrien /* delete duplications, keeping first occurance */ 67459243Sobrien for (i = 1; i < num_items; i++) 67559243Sobrien for (j = 0; j < i; j++) 67659243Sobrien /* If have earlier identical item, remove i'th item */ 67759243Sobrien if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) { 678167465Smp xfree(vec[i]); 67959243Sobrien vec[i] = NULL; 68059243Sobrien break; 68159243Sobrien } 68259243Sobrien } else if (flags & VAR_LAST) { 68359243Sobrien /* delete duplications, keeping last occurance */ 68459243Sobrien for (i = 0; i < num_items - 1; i++) 68559243Sobrien for (j = i + 1; j < num_items; j++) 68659243Sobrien /* If have later identical item, remove i'th item */ 68759243Sobrien if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) { 68859243Sobrien /* remove identical item (the first) */ 689167465Smp xfree(vec[i]); 69059243Sobrien vec[i] = NULL; 69159243Sobrien } 69259243Sobrien } 69359243Sobrien /* Compress items - remove empty items */ 69459243Sobrien for (j = i = 0; i < num_items; i++) 69559243Sobrien if (vec[i]) 69659243Sobrien vec[j++] = vec[i]; 69759243Sobrien 69859243Sobrien /* NULL-fy remaining items */ 69959243Sobrien for (; j < num_items; j++) 70059243Sobrien vec[j] = NULL; 70159243Sobrien } 70259243Sobrien /* don't let the attribute propagate */ 70359243Sobrien flags &= ~(VAR_FIRST|VAR_LAST); 70459243Sobrien } 70559243Sobrien setq(var, vec, head, flags); 70659243Sobrien} 70759243Sobrien 70859243Sobrien 70959243Sobrienvoid 710167465Smpsetq(const Char *name, Char **vec, struct varent *p, int flags) 71159243Sobrien{ 712145479Smp struct varent *c; 713145479Smp int f; 71459243Sobrien 71559243Sobrien f = 0; /* tree hangs off the header's left link */ 71659243Sobrien while ((c = p->v_link[f]) != 0) { 71759243Sobrien if ((f = *name - *c->v_name) == 0 && 71859243Sobrien (f = Strcmp(name, c->v_name)) == 0) { 71959243Sobrien if (c->v_flags & VAR_READONLY) 72059243Sobrien stderror(ERR_READONLY|ERR_NAME, c->v_name); 72159243Sobrien blkfree(c->vec); 72259243Sobrien c->v_flags = flags; 72359243Sobrien trim(c->vec = vec); 72459243Sobrien return; 72559243Sobrien } 72659243Sobrien p = c; 72759243Sobrien f = f > 0; 72859243Sobrien } 729167465Smp p->v_link[f] = c = xmalloc(sizeof(struct varent)); 73059243Sobrien c->v_name = Strsave(name); 73159243Sobrien c->v_flags = flags; 73259243Sobrien c->v_bal = 0; 73359243Sobrien c->v_left = c->v_right = 0; 73459243Sobrien c->v_parent = p; 73559243Sobrien balance(p, f, 0); 73659243Sobrien trim(c->vec = vec); 73759243Sobrien} 73859243Sobrien 73959243Sobrien/*ARGSUSED*/ 74059243Sobrienvoid 741167465Smpunset(Char **v, struct command *c) 74259243Sobrien{ 743145479Smp int did_roe, did_edit; 74459243Sobrien 74559243Sobrien USE(c); 74659243Sobrien did_roe = adrof(STRrecognize_only_executables) != NULL; 74759243Sobrien did_edit = adrof(STRedit) != NULL; 74859243Sobrien unset1(v, &shvhed); 749100616Smp 750100616Smp#if defined(FILEC) && defined(TIOCSTI) 751100616Smp if (adrof(STRfilec) == 0) 752100616Smp filec = 0; 753100616Smp#endif /* FILEC && TIOCSTI */ 754100616Smp 75559243Sobrien if (adrof(STRhistchars) == 0) { 75659243Sobrien HIST = '!'; 75759243Sobrien HISTSUB = '^'; 75859243Sobrien } 759131962Smp if (adrof(STRignoreeof) == 0) 760131962Smp numeof = 0; 76159243Sobrien if (adrof(STRpromptchars) == 0) { 762232633Smp PRCH = tcsh ? '>' : '%'; 76359243Sobrien PRCHROOT = '#'; 76459243Sobrien } 76559243Sobrien if (adrof(STRhistlit) == 0) 76659243Sobrien HistLit = 0; 76759243Sobrien if (adrof(STRloginsh) == 0) 76859243Sobrien loginsh = 0; 769232633Smp if (adrof(STRanyerror) == 0) 770232633Smp anyerror = 0; 77159243Sobrien if (adrof(STRwordchars) == 0) 77259243Sobrien word_chars = STR_WORD_CHARS; 77359243Sobrien if (adrof(STRedit) == 0) 77459243Sobrien editing = 0; 77559243Sobrien if (adrof(STRbackslash_quote) == 0) 77659243Sobrien bslash_quote = 0; 777195609Smp if (adrof(STRcompat_expr) == 0) 778195609Smp compat_expr = 0; 77959243Sobrien if (adrof(STRsymlinks) == 0) 78059243Sobrien symlinks = 0; 78159243Sobrien if (adrof(STRimplicitcd) == 0) 78259243Sobrien implicit_cd = 0; 78383098Smp if (adrof(STRkillring) == 0) 78483098Smp SetKillRing(0); 78559243Sobrien if (did_edit && noediting && adrof(STRedit) == 0) 78659243Sobrien noediting = 0; 78759243Sobrien if (did_roe && adrof(STRrecognize_only_executables) == 0) 78859243Sobrien tw_cmd_free(); 78959243Sobrien#ifdef COLOR_LS_F 79059243Sobrien if (adrof(STRcolor) == 0) 79159243Sobrien set_color_context(); 79259243Sobrien#endif /* COLOR_LS_F */ 79359243Sobrien#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) 79459243Sobrien update_dspmbyte_vars(); 79559243Sobrien#endif 79669408Sache#ifdef NLS_CATALOGS 797145479Smp nlsclose(); 79869408Sache nlsinit(); 79969408Sache#endif /* NLS_CATALOGS */ 80059243Sobrien} 80159243Sobrien 80259243Sobrienvoid 803167465Smpunset1(Char *v[], struct varent *head) 80459243Sobrien{ 805145479Smp struct varent *vp; 806145479Smp int cnt; 80759243Sobrien 80859243Sobrien while (*++v) { 80959243Sobrien cnt = 0; 81059243Sobrien while ((vp = madrof(*v, head)) != NULL) 81159243Sobrien if (vp->v_flags & VAR_READONLY) 81259243Sobrien stderror(ERR_READONLY|ERR_NAME, vp->v_name); 81359243Sobrien else 81459243Sobrien unsetv1(vp), cnt++; 81559243Sobrien if (cnt == 0) 81659243Sobrien setname(short2str(*v)); 81759243Sobrien } 81859243Sobrien} 81959243Sobrien 82059243Sobrienvoid 821167465Smpunsetv(Char *var) 82259243Sobrien{ 823145479Smp struct varent *vp; 82459243Sobrien 82559243Sobrien if ((vp = adrof1(var, &shvhed)) == 0) 82659243Sobrien udvar(var); 82759243Sobrien unsetv1(vp); 82859243Sobrien} 82959243Sobrien 83059243Sobrienstatic void 831167465Smpunsetv1(struct varent *p) 83259243Sobrien{ 833145479Smp struct varent *c, *pp; 834145479Smp int f; 83559243Sobrien 83659243Sobrien /* 83759243Sobrien * Free associated memory first to avoid complications. 83859243Sobrien */ 83959243Sobrien blkfree(p->vec); 840167465Smp xfree(p->v_name); 84159243Sobrien /* 84259243Sobrien * If p is missing one child, then we can move the other into where p is. 84359243Sobrien * Otherwise, we find the predecessor of p, which is guaranteed to have no 84459243Sobrien * right child, copy it into p, and move it's left child into it. 84559243Sobrien */ 84659243Sobrien if (p->v_right == 0) 84759243Sobrien c = p->v_left; 84859243Sobrien else if (p->v_left == 0) 84959243Sobrien c = p->v_right; 85059243Sobrien else { 85159243Sobrien for (c = p->v_left; c->v_right; c = c->v_right) 85259243Sobrien continue; 85359243Sobrien p->v_name = c->v_name; 85459243Sobrien p->v_flags = c->v_flags; 85559243Sobrien p->vec = c->vec; 85659243Sobrien p = c; 85759243Sobrien c = p->v_left; 85859243Sobrien } 85959243Sobrien 86059243Sobrien /* 86159243Sobrien * Move c into where p is. 86259243Sobrien */ 86359243Sobrien pp = p->v_parent; 86459243Sobrien f = pp->v_right == p; 86559243Sobrien if ((pp->v_link[f] = c) != 0) 86659243Sobrien c->v_parent = pp; 86759243Sobrien /* 86859243Sobrien * Free the deleted node, and rebalance. 86959243Sobrien */ 870167465Smp xfree(p); 87159243Sobrien balance(pp, f, 1); 87259243Sobrien} 87359243Sobrien 874232633Smp/* Set variable name to NULL. */ 87559243Sobrienvoid 876232633SmpsetNS(const Char *varName) 87759243Sobrien{ 878232633Smp setcopy(varName, STRNULL, VAR_READWRITE); 87959243Sobrien} 88059243Sobrien 88159243Sobrien/*ARGSUSED*/ 88259243Sobrienvoid 883167465Smpshift(Char **v, struct command *c) 88459243Sobrien{ 885145479Smp struct varent *argv; 886145479Smp Char *name; 88759243Sobrien 88859243Sobrien USE(c); 88959243Sobrien v++; 89059243Sobrien name = *v; 89159243Sobrien if (name == 0) 89259243Sobrien name = STRargv; 89359243Sobrien else 89459243Sobrien (void) strip(name); 89559243Sobrien argv = adrof(name); 896100616Smp if (argv == NULL || argv->vec == NULL) 89759243Sobrien udvar(name); 89859243Sobrien if (argv->vec[0] == 0) 89959243Sobrien stderror(ERR_NAME | ERR_NOMORE); 90059243Sobrien lshift(argv->vec, 1); 90159243Sobrien update_vars(name); 90259243Sobrien} 90359243Sobrien 90459243Sobrienstatic void 905167465Smpexportpath(Char **val) 90659243Sobrien{ 907167465Smp struct Strbuf buf = Strbuf_INIT; 908167465Smp Char *exppath; 90959243Sobrien 91059243Sobrien if (val) 91159243Sobrien while (*val) { 912167465Smp Strbuf_append(&buf, *val++); 913167465Smp if (*val == 0 || eq(*val, STRRparen)) 91459243Sobrien break; 915167465Smp Strbuf_append1(&buf, PATHSEP); 916167465Smp } 917167465Smp exppath = Strbuf_finish(&buf); 918167465Smp cleanup_push(exppath, xfree); 919167465Smp tsetenv(STRKPATH, exppath); 920167465Smp cleanup_until(exppath); 92159243Sobrien} 92259243Sobrien 92359243Sobrien#ifndef lint 92459243Sobrien /* 92559243Sobrien * Lint thinks these have null effect 92659243Sobrien */ 92759243Sobrien /* macros to do single rotations on node p */ 92859243Sobrien# define rright(p) (\ 92959243Sobrien t = (p)->v_left,\ 93059243Sobrien (t)->v_parent = (p)->v_parent,\ 93159243Sobrien (((p)->v_left = t->v_right) != NULL) ?\ 93259243Sobrien (t->v_right->v_parent = (p)) : 0,\ 93359243Sobrien (t->v_right = (p))->v_parent = t,\ 93459243Sobrien (p) = t) 93559243Sobrien# define rleft(p) (\ 93659243Sobrien t = (p)->v_right,\ 93759243Sobrien ((t)->v_parent = (p)->v_parent,\ 93859243Sobrien ((p)->v_right = t->v_left) != NULL) ? \ 93959243Sobrien (t->v_left->v_parent = (p)) : 0,\ 94059243Sobrien (t->v_left = (p))->v_parent = t,\ 94159243Sobrien (p) = t) 94259243Sobrien#else 94359243Sobrienstatic struct varent * 944167465Smprleft(struct varent *p) 94559243Sobrien{ 94659243Sobrien return (p); 94759243Sobrien} 94859243Sobrienstatic struct varent * 949167465Smprright(struct varent *p) 95059243Sobrien{ 95159243Sobrien return (p); 95259243Sobrien} 95359243Sobrien 95459243Sobrien#endif /* ! lint */ 95559243Sobrien 95659243Sobrien 95759243Sobrien/* 95859243Sobrien * Rebalance a tree, starting at p and up. 95959243Sobrien * F == 0 means we've come from p's left child. 96059243Sobrien * D == 1 means we've just done a delete, otherwise an insert. 96159243Sobrien */ 96259243Sobrienstatic void 963167465Smpbalance(struct varent *p, int f, int d) 96459243Sobrien{ 965145479Smp struct varent *pp; 96659243Sobrien 96759243Sobrien#ifndef lint 968145479Smp struct varent *t; /* used by the rotate macros */ 96959243Sobrien#endif /* !lint */ 970145479Smp int ff; 97159243Sobrien#ifdef lint 97259243Sobrien ff = 0; /* Sun's lint is dumb! */ 97359243Sobrien#endif 97459243Sobrien 97559243Sobrien /* 97659243Sobrien * Ok, from here on, p is the node we're operating on; pp is it's parent; f 97759243Sobrien * is the branch of p from which we have come; ff is the branch of pp which 97859243Sobrien * is p. 97959243Sobrien */ 98059243Sobrien for (; (pp = p->v_parent) != 0; p = pp, f = ff) { 98159243Sobrien ff = pp->v_right == p; 98259243Sobrien if (f ^ d) { /* right heavy */ 98359243Sobrien switch (p->v_bal) { 98459243Sobrien case -1: /* was left heavy */ 98559243Sobrien p->v_bal = 0; 98659243Sobrien break; 98759243Sobrien case 0: /* was balanced */ 98859243Sobrien p->v_bal = 1; 98959243Sobrien break; 99059243Sobrien case 1: /* was already right heavy */ 99159243Sobrien switch (p->v_right->v_bal) { 992167465Smp case 1: /* single rotate */ 99359243Sobrien pp->v_link[ff] = rleft(p); 99459243Sobrien p->v_left->v_bal = 0; 99559243Sobrien p->v_bal = 0; 99659243Sobrien break; 99759243Sobrien case 0: /* single rotate */ 99859243Sobrien pp->v_link[ff] = rleft(p); 99959243Sobrien p->v_left->v_bal = 1; 100059243Sobrien p->v_bal = -1; 100159243Sobrien break; 100259243Sobrien case -1: /* double rotate */ 100359243Sobrien (void) rright(p->v_right); 100459243Sobrien pp->v_link[ff] = rleft(p); 100559243Sobrien p->v_left->v_bal = 100659243Sobrien p->v_bal < 1 ? 0 : -1; 100759243Sobrien p->v_right->v_bal = 100859243Sobrien p->v_bal > -1 ? 0 : 1; 100959243Sobrien p->v_bal = 0; 101059243Sobrien break; 101159243Sobrien default: 101259243Sobrien break; 101359243Sobrien } 101459243Sobrien break; 101559243Sobrien default: 101659243Sobrien break; 101759243Sobrien } 101859243Sobrien } 101959243Sobrien else { /* left heavy */ 102059243Sobrien switch (p->v_bal) { 102159243Sobrien case 1: /* was right heavy */ 102259243Sobrien p->v_bal = 0; 102359243Sobrien break; 102459243Sobrien case 0: /* was balanced */ 102559243Sobrien p->v_bal = -1; 102659243Sobrien break; 102759243Sobrien case -1: /* was already left heavy */ 102859243Sobrien switch (p->v_left->v_bal) { 102959243Sobrien case -1: /* single rotate */ 103059243Sobrien pp->v_link[ff] = rright(p); 103159243Sobrien p->v_right->v_bal = 0; 103259243Sobrien p->v_bal = 0; 103359243Sobrien break; 1034167465Smp case 0: /* single rotate */ 103559243Sobrien pp->v_link[ff] = rright(p); 103659243Sobrien p->v_right->v_bal = -1; 103759243Sobrien p->v_bal = 1; 103859243Sobrien break; 103959243Sobrien case 1: /* double rotate */ 104059243Sobrien (void) rleft(p->v_left); 104159243Sobrien pp->v_link[ff] = rright(p); 104259243Sobrien p->v_left->v_bal = 104359243Sobrien p->v_bal < 1 ? 0 : -1; 104459243Sobrien p->v_right->v_bal = 104559243Sobrien p->v_bal > -1 ? 0 : 1; 104659243Sobrien p->v_bal = 0; 104759243Sobrien break; 104859243Sobrien default: 104959243Sobrien break; 105059243Sobrien } 105159243Sobrien break; 105259243Sobrien default: 105359243Sobrien break; 105459243Sobrien } 105559243Sobrien } 105659243Sobrien /* 105759243Sobrien * If from insert, then we terminate when p is balanced. If from 105859243Sobrien * delete, then we terminate when p is unbalanced. 105959243Sobrien */ 106059243Sobrien if ((p->v_bal == 0) ^ d) 106159243Sobrien break; 106259243Sobrien } 106359243Sobrien} 106459243Sobrien 106559243Sobrienvoid 1066167465Smpplist(struct varent *p, int what) 106759243Sobrien{ 1068145479Smp struct varent *c; 1069145479Smp int len; 107059243Sobrien 107159243Sobrien for (;;) { 107259243Sobrien while (p->v_left) 107359243Sobrien p = p->v_left; 107459243Sobrienx: 107559243Sobrien if (p->v_parent == 0) /* is it the header? */ 1076167465Smp break; 107759243Sobrien if ((p->v_flags & what) != 0) { 1078167465Smp if (setintr) { 1079167465Smp int old_pintr_disabled; 1080167465Smp 1081167465Smp pintr_push_enable(&old_pintr_disabled); 1082167465Smp cleanup_until(&old_pintr_disabled); 1083167465Smp } 108459243Sobrien len = blklen(p->vec); 108559243Sobrien xprintf("%S\t", p->v_name); 108659243Sobrien if (len != 1) 108759243Sobrien xputchar('('); 108859243Sobrien blkpr(p->vec); 108959243Sobrien if (len != 1) 109059243Sobrien xputchar(')'); 109159243Sobrien xputchar('\n'); 109259243Sobrien } 109359243Sobrien if (p->v_right) { 109459243Sobrien p = p->v_right; 109559243Sobrien continue; 109659243Sobrien } 109759243Sobrien do { 109859243Sobrien c = p; 109959243Sobrien p = p->v_parent; 110059243Sobrien } while (p->v_right == c); 110159243Sobrien goto x; 110259243Sobrien } 110359243Sobrien} 110459243Sobrien 1105232633Smp#if defined(KANJI) 1106232633Smp# if defined(SHORT_STRINGS) && defined(DSPMBYTE) 1107145479Smpextern int dspmbyte_ls; 110859243Sobrien 110959243Sobrienvoid 1110167465Smpupdate_dspmbyte_vars(void) 111159243Sobrien{ 111259243Sobrien int lp, iskcode; 111359243Sobrien Char *dstr1; 111459243Sobrien struct varent *vp; 111559243Sobrien 111659243Sobrien /* if variable "nokanji" is set, multi-byte display is disabled */ 111759243Sobrien if ((vp = adrof(CHECK_MBYTEVAR)) && !adrof(STRnokanji)) { 111859243Sobrien _enable_mbdisp = 1; 111959243Sobrien dstr1 = vp->vec[0]; 1120145479Smp if(eq (dstr1, STRsjis)) 112159243Sobrien iskcode = 1; 1122145479Smp else if (eq(dstr1, STReuc)) 112359243Sobrien iskcode = 2; 1124145479Smp else if (eq(dstr1, STRbig5)) 112583098Smp iskcode = 3; 1126145479Smp else if (eq(dstr1, STRutf8)) 1127100616Smp iskcode = 4; 112859243Sobrien else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) { 112959243Sobrien iskcode = 0; 113059243Sobrien } 113159243Sobrien else { 113259243Sobrien xprintf(CGETS(18, 2, 113359243Sobrien "Warning: unknown multibyte display; using default(euc(JP))\n")); 113459243Sobrien iskcode = 2; 113559243Sobrien } 113659243Sobrien if (dstr1 && vp->vec[1] && eq(vp->vec[1], STRls)) 113759243Sobrien dspmbyte_ls = 1; 113859243Sobrien else 113959243Sobrien dspmbyte_ls = 0; 114059243Sobrien for (lp = 0; lp < 256 && iskcode > 0; lp++) { 114159243Sobrien switch (iskcode) { 114259243Sobrien case 1: 114359243Sobrien /* Shift-JIS */ 114459243Sobrien _cmap[lp] = _cmap_mbyte[lp]; 114559243Sobrien _mbmap[lp] = _mbmap_sjis[lp]; 114659243Sobrien break; 114759243Sobrien case 2: 114859243Sobrien /* 2 ... euc */ 114959243Sobrien _cmap[lp] = _cmap_mbyte[lp]; 115059243Sobrien _mbmap[lp] = _mbmap_euc[lp]; 115159243Sobrien break; 115283098Smp case 3: 115383098Smp /* 3 ... big5 */ 115483098Smp _cmap[lp] = _cmap_mbyte[lp]; 115583098Smp _mbmap[lp] = _mbmap_big5[lp]; 115683098Smp break; 1157100616Smp case 4: 1158100616Smp /* 4 ... utf8 */ 1159100616Smp _cmap[lp] = _cmap_mbyte[lp]; 1160100616Smp _mbmap[lp] = _mbmap_utf8[lp]; 1161100616Smp break; 116259243Sobrien default: 116359243Sobrien xprintf(CGETS(18, 3, 116459243Sobrien "Warning: unknown multibyte code %d; multibyte disabled\n"), 116559243Sobrien iskcode); 116659243Sobrien _cmap[lp] = _cmap_c[lp]; 116759243Sobrien _mbmap[lp] = 0; /* Default map all 0 */ 116859243Sobrien _enable_mbdisp = 0; 116959243Sobrien break; 117059243Sobrien } 117159243Sobrien } 117259243Sobrien if (iskcode == 0) { 117359243Sobrien /* check original table */ 117459243Sobrien if (Strlen(dstr1) != 256) { 117559243Sobrien xprintf(CGETS(18, 4, 117659243Sobrien "Warning: Invalid multibyte table length (%d); multibyte disabled\n"), 117759243Sobrien Strlen(dstr1)); 117859243Sobrien _enable_mbdisp = 0; 117959243Sobrien } 118059243Sobrien for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) { 118159243Sobrien if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) { 118259243Sobrien xprintf(CGETS(18, 4, 118359243Sobrien "Warning: bad multibyte code at offset +%d; multibyte diabled\n"), 118459243Sobrien lp); 118559243Sobrien _enable_mbdisp = 0; 118659243Sobrien break; 118759243Sobrien } 118859243Sobrien } 118959243Sobrien /* set original table */ 119059243Sobrien for (lp = 0; lp < 256; lp++) { 119159243Sobrien if (_enable_mbdisp == 1) { 119259243Sobrien _cmap[lp] = _cmap_mbyte[lp]; 119359243Sobrien _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f); 119459243Sobrien } 119559243Sobrien else { 119659243Sobrien _cmap[lp] = _cmap_c[lp]; 119759243Sobrien _mbmap[lp] = 0; /* Default map all 0 */ 119859243Sobrien } 119959243Sobrien } 120059243Sobrien } 120159243Sobrien } 120259243Sobrien else { 120359243Sobrien for (lp = 0; lp < 256; lp++) { 120459243Sobrien _cmap[lp] = _cmap_c[lp]; 120559243Sobrien _mbmap[lp] = 0; /* Default map all 0 */ 120659243Sobrien } 120759243Sobrien _enable_mbdisp = 0; 120859243Sobrien dspmbyte_ls = 0; 120959243Sobrien } 121059243Sobrien#ifdef MBYTEDEBUG /* Sorry, use for beta testing */ 121159243Sobrien { 121259243Sobrien Char mbmapstr[300]; 1213167465Smp for (lp = 0; lp < 256; lp++) 121459243Sobrien mbmapstr[lp] = _mbmap[lp] + '0'; 1215167465Smp mbmapstr[lp] = 0; 1216167465Smp setcopy(STRmbytemap, mbmapstr, VAR_READWRITE); 121759243Sobrien } 121859243Sobrien#endif /* MBYTEMAP */ 121959243Sobrien} 122059243Sobrien 122159243Sobrien/* dspkanji/dspmbyte autosetting */ 122259243Sobrien/* PATCH IDEA FROM Issei.Suzuki VERY THANKS */ 122359243Sobrienvoid 1224167465Smpautoset_dspmbyte(const Char *pcp) 122559243Sobrien{ 122659243Sobrien int i; 1227167465Smp static const struct dspm_autoset_Table { 122859243Sobrien Char *n; 122959243Sobrien Char *v; 123059243Sobrien } dspmt[] = { 1231145479Smp { STRLANGEUCJP, STReuc }, 1232145479Smp { STRLANGEUCKR, STReuc }, 1233145479Smp { STRLANGEUCZH, STReuc }, 1234145479Smp { STRLANGEUCJPB, STReuc }, 1235145479Smp { STRLANGEUCKRB, STReuc }, 1236145479Smp { STRLANGEUCZHB, STReuc }, 1237232633Smp#ifdef __linux__ 1238145479Smp { STRLANGEUCJPC, STReuc }, 1239131962Smp#endif 1240145479Smp { STRLANGSJIS, STRsjis }, 1241145479Smp { STRLANGSJISB, STRsjis }, 1242145479Smp { STRLANGBIG5, STRbig5 }, 1243145479Smp { STRstarutfstar8, STRutf8 }, 124459243Sobrien { NULL, NULL } 124559243Sobrien }; 1246167465Smp#if defined(HAVE_NL_LANGINFO) && defined(CODESET) 1247167465Smp static const struct dspm_autoset_Table dspmc[] = { 1248145479Smp { STRstarutfstar8, STRutf8 }, 1249145479Smp { STReuc, STReuc }, 1250145479Smp { STRGB2312, STReuc }, 1251145479Smp { STRLANGBIG5, STRbig5 }, 1252145479Smp { NULL, NULL } 1253145479Smp }; 1254145479Smp Char *codeset; 125559243Sobrien 1256145479Smp codeset = str2short(nl_langinfo(CODESET)); 1257145479Smp if (*codeset != '\0') { 1258145479Smp for (i = 0; dspmc[i].n; i++) { 1259167465Smp const Char *estr; 1260145479Smp if (dspmc[i].n[0] && t_pmatch(pcp, dspmc[i].n, &estr, 0) > 0) { 1261167465Smp setcopy(CHECK_MBYTEVAR, dspmc[i].v, VAR_READWRITE); 1262145479Smp update_dspmbyte_vars(); 1263145479Smp return; 1264145479Smp } 1265145479Smp } 1266145479Smp } 1267145479Smp#endif 1268145479Smp 126959243Sobrien if (*pcp == '\0') 127059243Sobrien return; 127159243Sobrien 127259243Sobrien for (i = 0; dspmt[i].n; i++) { 1273167465Smp const Char *estr; 1274145479Smp if (dspmt[i].n[0] && t_pmatch(pcp, dspmt[i].n, &estr, 0) > 0) { 1275167465Smp setcopy(CHECK_MBYTEVAR, dspmt[i].v, VAR_READWRITE); 127659243Sobrien update_dspmbyte_vars(); 127759243Sobrien break; 127859243Sobrien } 127959243Sobrien } 128059243Sobrien} 1281232633Smp# elif defined(AUTOSET_KANJI) 1282232633Smpvoid 1283232633Smpautoset_kanji(void) 1284232633Smp{ 1285232633Smp char *codeset = nl_langinfo(CODESET); 1286232633Smp 1287232633Smp if (*codeset == '\0') { 1288232633Smp if (adrof(STRnokanji) == NULL) 1289232633Smp setNS(STRnokanji); 1290232633Smp return; 1291232633Smp } 1292232633Smp 1293232633Smp if (strcasestr(codeset, "SHIFT_JIS") == (char*)0) { 1294232633Smp if (adrof(STRnokanji) == NULL) 1295232633Smp setNS(STRnokanji); 1296232633Smp return; 1297232633Smp } 1298232633Smp 1299232633Smp if (adrof(STRnokanji) != NULL) 1300232633Smp unsetv(STRnokanji); 1301232633Smp} 130259243Sobrien#endif 1303232633Smp#endif 1304