/* get variable string value */ char * str_val(struct tbl *vp) { char *s; if ((vp->flag&SPECIAL)) getspec(vp); if (!(vp->flag&ISSET)) s = null; /* special to dollar() */ else if (!(vp->flag&INTEGER)) /* string source */ s = vp->val.s + vp->type; else { /* integer source */ /* worst case number length is when base=2, so use BITS(long) */ /* minus base # number null */ char strbuf[1 + 2 + 1 + BITS(long) + 1]; const char *digits = (vp->flag & UCASEV_AL) ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" : "0123456789abcdefghijklmnopqrstuvwxyz"; unsigned long n; int base; s = strbuf + sizeof(strbuf); if (vp->flag & INT_U) n = (unsigned long) vp->val.i; else n = (vp->val.i < 0) ? -vp->val.i : vp->val.i; base = (vp->type == 0) ? 10 : vp->type; if (base < 2 || base > strlen(digits)) base = 10; *--s = '\0'; do { *--s = digits[n % base]; n /= base; } while (n != 0); if (base != 10) { *--s = '#'; *--s = digits[base % 10]; if (base >= 10) *--s = digits[base / 10]; } if (!(vp->flag & INT_U) && vp->val.i < 0) *--s = '-'; if (vp->flag & (RJUST|LJUST)) /* case already dealt with */ s = formatstr(vp, s); else s = str_save(s, ATEMP); } return s; }
tableput() { saveline(); savefill(); ifdivert(); cleanfc(); getcomm(); getspec(); gettbl(); getstop(); checkuse(); choochar(); maktab(); runout(); release(); rstofill(); endoff(); restline(); }
static int getint(struct tbl *vp, mksh_ari_u *nump, bool arith) { mksh_uari_t c, num = 0, base = 10; const char *s; bool have_base = false, neg = false; if (vp->flag & SPECIAL) getspec(vp); /* XXX is it possible for ISSET to be set and val.s to be NULL? */ if (!(vp->flag & ISSET) || (!(vp->flag & INTEGER) && vp->val.s == NULL)) return (-1); if (vp->flag & INTEGER) { nump->i = vp->val.i; return (vp->type); } s = vp->val.s + vp->type; do { c = (unsigned char)*s++; } while (ksh_isspace(c)); switch (c) { case '-': neg = true; /* FALLTHROUGH */ case '+': c = (unsigned char)*s++; break; } if (c == '0' && arith) { if (ksh_eq(s[0], 'X', 'x')) { /* interpret as hexadecimal */ base = 16; ++s; goto getint_c_style_base; } else if (Flag(FPOSIX) && ksh_isdigit(s[0]) && !(vp->flag & ZEROFIL)) { /* interpret as octal (deprecated) */ base = 8; getint_c_style_base: have_base = true; c = (unsigned char)*s++; } } do { if (c == '#') { /* ksh-style base determination */ if (have_base || num < 1) return (-1); if ((base = num) == 1) { /* mksh-specific extension */ unsigned int wc; if (!UTFMODE) wc = *(const unsigned char *)s; else if (utf_mbtowc(&wc, s) == (size_t)-1) /* OPTU-8 -> OPTU-16 */ /* * (with a twist: 1#\uEF80 converts * the same as 1#\x80 does, thus is * not round-tripping correctly XXX) */ wc = 0xEF00 + *(const unsigned char *)s; nump->u = (mksh_uari_t)wc; return (1); } else if (base > 36) base = 10; num = 0; have_base = true; continue; } if (ksh_isdigit(c)) c = ksh_numdig(c); else if (ksh_isupper(c)) c = ksh_numuc(c) + 10; else if (ksh_islower(c)) c = ksh_numlc(c) + 10; else return (-1); if (c >= base) return (-1); /* handle overflow as truncation */ num = num * base + c; } while ((c = (unsigned char)*s++)); if (neg) num = -num; nump->u = num; return (base); }
/* get variable string value */ char * str_val(struct tbl *vp) { char *s; if ((vp->flag&SPECIAL)) getspec(vp); if (!(vp->flag&ISSET)) /* special to dollar() */ s = null; else if (!(vp->flag&INTEGER)) /* string source */ s = vp->val.s + vp->type; else { /* integer source */ mksh_uari_t n; unsigned int base; /** * worst case number length is when base == 2: * 1 (minus) + 2 (base, up to 36) + 1 ('#') + * number of bits in the mksh_uari_t + 1 (NUL) */ char strbuf[1 + 2 + 1 + 8 * sizeof(mksh_uari_t) + 1]; const char *digits = (vp->flag & UCASEV_AL) ? digits_uc : digits_lc; s = strbuf + sizeof(strbuf); if (vp->flag & INT_U) n = vp->val.u; else n = (vp->val.i < 0) ? -vp->val.u : vp->val.u; base = (vp->type == 0) ? 10U : (unsigned int)vp->type; if (base == 1 && n == 0) base = 2; if (base == 1) { size_t sz = 1; *(s = strbuf) = '1'; s[1] = '#'; if (!UTFMODE || ((n & 0xFF80) == 0xEF80)) /* OPTU-16 -> raw octet */ s[2] = n & 0xFF; else sz = utf_wctomb(s + 2, n); s[2 + sz] = '\0'; } else { *--s = '\0'; do { *--s = digits[n % base]; n /= base; } while (n != 0); if (base != 10) { *--s = '#'; *--s = digits[base % 10]; if (base >= 10) *--s = digits[base / 10]; } if (!(vp->flag & INT_U) && vp->val.i < 0) *--s = '-'; } if (vp->flag & (RJUST|LJUST)) /* case already dealt with */ s = formatstr(vp, s); else strdupx(s, s, ATEMP); } return (s); }
/* * cmd is one of: * 'p': normal print * 'h': just print headwords * 'P': print raw */ void pgwprintentry(Entry e, int cmd) { char *p, *pe; int t; long r, rprev, rlig; Rune *transtab; p = e.start; pe = e.end; transtab = normtab; rprev = NONE; changett(0, 0, 0); curentry = e; if(cmd == 'h') outinhibit = 1; while(p < pe) { if(cmd == 'r') { outchar(*p++); continue; } r = transtab[(*p++)&0x7F]; if(r < NONE) { /* Emit the rune, but buffer in case of ligature */ if(rprev != NONE) outrune(rprev); rprev = r; } else if(r == SPCS) { /* Start of special character name */ p = getspec(p, pe); r = lookassoc(spectab, asize(spectab), spec); if(r == -1) { if(debug) err("spec %ld %d %s", e.doff, cursize, spec); r = L'�'; } if(r >= LIGS && r < LIGE) { /* handle possible ligature */ rlig = liglookup(r, rprev); if(rlig != NONE) rprev = rlig; /* overwrite rprev */ else { /* could print accent, but let's not */ if(rprev != NONE) outrune(rprev); rprev = NONE; } } else if(r >= MULTI && r < MULTIE) { if(rprev != NONE) { outrune(rprev); rprev = NONE; } outrunes(multitab[r-MULTI]); } else if(r == PAR) { if(rprev != NONE) { outrune(rprev); rprev = NONE; } outnl(1); } else { if(rprev != NONE) outrune(rprev); rprev = r; } } else if(r == TAGS) { /* Start of tag name */ if(rprev != NONE) { outrune(rprev); rprev = NONE; } p = gettag(p, pe); t = lookassoc(tagtab, asize(tagtab), tag); if(t == -1) { if(debug) err("tag %ld %d %s", e.doff, cursize, tag); continue; } switch(t) { case Hw: if(cmd == 'h') { if(!tagstarts) outchar(' '); outinhibit = !tagstarts; } break; case Sn: if(tagstarts) { outnl(2); } break; case P: outnl(tagstarts); break; case Col: case Br: case Blockquote: if(tagstarts) outnl(1); break; case U: outchar('/'); } } } if(cmd == 'h') { outinhibit = 0; outnl(0); } }
static int getint(struct tbl *vp, mksh_ari_t *nump, bool arith) { int c, base, neg; mksh_uari_t num; const char *s; bool have_base = false; if (vp->flag&SPECIAL) getspec(vp); /* XXX is it possible for ISSET to be set and val.s to be 0? */ if (!(vp->flag&ISSET) || (!(vp->flag&INTEGER) && vp->val.s == NULL)) return (-1); if (vp->flag&INTEGER) { *nump = vp->val.i; return (vp->type); } s = vp->val.s + vp->type; base = 10; num = 0; neg = 0; if (arith && s[0] == '0' && (s[1] | 0x20) == 'x') { s += 2; base = 16; have_base = true; } #ifdef MKSH_LEGACY_MODE if (arith && s[0] == '0' && ksh_isdigit(s[1]) && !(vp->flag & ZEROFIL)) { /* interpret as octal (deprecated) */ base = 8; have_base = true; } #endif while ((c = *s++)) { if (c == '-') { neg++; continue; } else if (c == '#') { if (have_base || num < 1 || num > 36) return (-1); base = (int)num; if (base == 1) { unsigned int wc; if (!UTFMODE) wc = *(const unsigned char *)s; else if (utf_mbtowc(&wc, s) == (size_t)-1) /* OPTU-8 -> OPTU-16 */ /* * (with a twist: 1#\uEF80 converts * the same as 1#\x80 does, thus is * not round-tripping correctly XXX) */ wc = 0xEF00 + *(const unsigned char *)s; *nump = (mksh_ari_t)wc; return (1); } num = 0; have_base = true; continue; } else if (ksh_isdigit(c)) c -= '0'; else if (ksh_islower(c)) c -= 'a' - 10; else if (ksh_isupper(c)) c -= 'A' - 10; else return (-1); if (c < 0 || c >= base) return (-1); num = num * base + c; } *nump = neg ? -((mksh_ari_t)num) : (mksh_ari_t)num; return (base); }