1 /* $OpenBSD: shf.c,v 1.16 2013/04/19 17:36:09 millert Exp $ */
4 * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011,
5 * 2012, 2013, 2015, 2016, 2017
6 * mirabilos <m@mirbsd.org>
8 * Daniel Richard G. <skunk@iSKUNK.ORG>
10 * Provided that these terms and disclaimer and all copyright notices
11 * are retained or reproduced in an accompanying document, permission
12 * is granted to deal in this work without restriction, including un-
13 * limited rights to use, publicly perform, distribute, sell, modify,
14 * merge, give away, or sublicence.
16 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
17 * the utmost extent permitted by applicable law, neither express nor
18 * implied; without malicious intent or gross negligence. In no event
19 * may a licensor, author or contributor be held liable for indirect,
20 * direct, other damage, loss, or other issues arising in any way out
21 * of dealing in the work, even if advised of the possibility of such
22 * damage or existence of a defect, except proven that it results out
23 * of said person's immediate fault when using the work as intended.
25 * Use %zX instead of %p and floating point isn't supported at all.
30 __RCSID("$MirOS: src/bin/mksh/shf.c,v 1.95 2017/05/05 22:45:58 tg Exp $");
32 /* flags to shf_emptybuf() */
33 #define EB_READSW 0x01 /* about to switch to reading */
34 #define EB_GROW 0x02 /* grow buffer if necessary (STRING+DYNAMIC) */
37 * Replacement stdio routines. Stdio is too flakey on too many machines
38 * to be useful when you have multiple processes using the same underlying
42 static int shf_fillbuf(struct shf *);
43 static int shf_emptybuf(struct shf *, int);
46 * Open a file. First three args are for open(), last arg is flags for
47 * this package. Returns NULL if file could not be opened, or if a dup
51 shf_open(const char *name, int oflags, int mode, int sflags)
56 sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
59 /* Done before open so if alloca fails, fd won't be lost. */
60 shf = alloc(sizeof(struct shf) + bsize, ATEMP);
62 shf->buf = (unsigned char *)&shf[1];
64 shf->flags = SHF_ALLOCS;
65 /* Rest filled in by reopen. */
67 fd = binopen3(name, oflags, mode);
70 afree(shf, shf->areap);
74 if ((sflags & SHF_MAPHI) && fd < FDBASE) {
77 nfd = fcntl(fd, F_DUPFD, FDBASE);
81 afree(shf, shf->areap);
87 sflags &= ~SHF_ACCMODE;
88 sflags |= (oflags & O_ACCMODE) == O_RDONLY ? SHF_RD :
89 ((oflags & O_ACCMODE) == O_WRONLY ? SHF_WR : SHF_RDWR);
91 return (shf_reopen(fd, sflags, shf));
94 /* helper function for shf_fdopen and shf_reopen */
96 shf_open_hlp(int fd, int *sflagsp, const char *where)
98 int sflags = *sflagsp;
100 /* use fcntl() to figure out correct read/write flags */
101 if (sflags & SHF_GETFL) {
102 int flags = fcntl(fd, F_GETFL, 0);
105 /* will get an error on first read/write */
108 switch (flags & O_ACCMODE) {
123 if (!(sflags & (SHF_RD | SHF_WR)))
124 internal_errorf(Tf_sD_s, where, "missing read/write");
127 /* Set up the shf structure for a file descriptor. Doesn't fail. */
129 shf_fdopen(int fd, int sflags, struct shf *shf)
133 sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
135 shf_open_hlp(fd, &sflags, "shf_fdopen");
138 shf->buf = alloc(bsize, ATEMP);
139 sflags |= SHF_ALLOCB;
143 shf = alloc(sizeof(struct shf) + bsize, ATEMP);
144 shf->buf = (unsigned char *)&shf[1];
145 sflags |= SHF_ALLOCS;
149 shf->rp = shf->wp = shf->buf;
152 shf->wnleft = 0; /* force call to shf_emptybuf() */
153 shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize;
157 if (sflags & SHF_CLEXEC)
158 fcntl(fd, F_SETFD, FD_CLOEXEC);
162 /* Set up an existing shf (and buffer) to use the given fd */
164 shf_reopen(int fd, int sflags, struct shf *shf)
168 sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
170 shf_open_hlp(fd, &sflags, "shf_reopen");
171 if (!shf || !shf->buf || shf->bsize < bsize)
172 internal_errorf(Tf_sD_s, "shf_reopen", Tbad_bsize);
174 /* assumes shf->buf and shf->bsize already set up */
176 shf->rp = shf->wp = shf->buf;
179 shf->wnleft = 0; /* force call to shf_emptybuf() */
180 shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize;
181 shf->flags = (shf->flags & (SHF_ALLOCS | SHF_ALLOCB)) | sflags;
183 if (sflags & SHF_CLEXEC)
184 fcntl(fd, F_SETFD, FD_CLOEXEC);
189 * Open a string for reading or writing. If reading, bsize is the number
190 * of bytes that can be read. If writing, bsize is the maximum number of
191 * bytes that can be written. If shf is not NULL, it is filled in and
192 * returned, if it is NULL, shf is allocated. If writing and buf is NULL
193 * and SHF_DYNAMIC is set, the buffer is allocated (if bsize > 0, it is
194 * used for the initial size). Doesn't fail.
195 * When writing, a byte is reserved for a trailing NUL - see shf_sclose().
198 shf_sopen(char *buf, ssize_t bsize, int sflags, struct shf *shf)
200 /* can't have a read+write string */
201 if (!(!(sflags & SHF_RD) ^ !(sflags & SHF_WR)))
202 internal_errorf(Tf_flags, "shf_sopen",
203 (unsigned int)sflags);
206 shf = alloc(sizeof(struct shf), ATEMP);
207 sflags |= SHF_ALLOCS;
210 if (!buf && (sflags & SHF_WR) && (sflags & SHF_DYNAMIC)) {
213 sflags |= SHF_ALLOCB;
214 buf = alloc(bsize, shf->areap);
217 shf->buf = shf->rp = shf->wp = (unsigned char *)buf;
220 shf->wnleft = bsize - 1; /* space for a '\0' */
222 shf->flags = sflags | SHF_STRING;
229 /* Flush and close file descriptor, free the shf structure */
231 shf_close(struct shf *shf)
236 ret = shf_flush(shf);
237 if (close(shf->fd) < 0)
240 if (shf->flags & SHF_ALLOCS)
241 afree(shf, shf->areap);
242 else if (shf->flags & SHF_ALLOCB)
243 afree(shf->buf, shf->areap);
248 /* Flush and close file descriptor, don't free file structure */
250 shf_fdclose(struct shf *shf)
255 ret = shf_flush(shf);
256 if (close(shf->fd) < 0)
268 * Close a string - if it was opened for writing, it is NUL terminated;
269 * returns a pointer to the string and frees shf if it was allocated
270 * (does not free string if it was allocated).
273 shf_sclose(struct shf *shf)
275 unsigned char *s = shf->buf;
278 if (shf->flags & SHF_WR) {
282 if (shf->flags & SHF_ALLOCS)
283 afree(shf, shf->areap);
288 * Un-read what has been read but not examined, or write what has been
289 * buffered. Returns 0 for success, -1 for (write) error.
292 shf_flush(struct shf *shf)
296 if (shf->flags & SHF_STRING)
297 rv = (shf->flags & SHF_WR) ? -1 : 0;
298 else if (shf->fd < 0)
299 internal_errorf(Tf_sD_s, "shf_flush", "no fd");
300 else if (shf->flags & SHF_ERROR) {
301 errno = shf->errnosv;
303 } else if (shf->flags & SHF_READING) {
304 shf->flags &= ~(SHF_EOF | SHF_READING);
305 if (shf->rnleft > 0) {
306 if (lseek(shf->fd, (off_t)-shf->rnleft,
308 shf->flags |= SHF_ERROR;
309 shf->errnosv = errno;
315 } else if (shf->flags & SHF_WRITING)
316 rv = shf_emptybuf(shf, 0);
322 * Write out any buffered data. If currently reading, flushes the read
323 * buffer. Returns 0 for success, -1 for (write) error.
326 shf_emptybuf(struct shf *shf, int flags)
330 if (!(shf->flags & SHF_STRING) && shf->fd < 0)
331 internal_errorf(Tf_sD_s, "shf_emptybuf", "no fd");
333 if (shf->flags & SHF_ERROR) {
334 errno = shf->errnosv;
338 if (shf->flags & SHF_READING) {
339 if (flags & EB_READSW)
342 ret = shf_flush(shf);
343 shf->flags &= ~SHF_READING;
345 if (shf->flags & SHF_STRING) {
349 * Note that we assume SHF_ALLOCS is not set if
350 * SHF_ALLOCB is set... (changing the shf pointer could
353 if (!(flags & EB_GROW) || !(shf->flags & SHF_DYNAMIC) ||
354 !(shf->flags & SHF_ALLOCB))
356 /* allocate more space for buffer */
357 nbuf = aresize2(shf->buf, 2, shf->wbsize, shf->areap);
358 shf->rp = nbuf + (shf->rp - shf->buf);
359 shf->wp = nbuf + (shf->wp - shf->buf);
360 shf->rbsize += shf->wbsize;
361 shf->wnleft += shf->wbsize;
365 if (shf->flags & SHF_WRITING) {
366 ssize_t n, ntowrite = shf->wp - shf->buf;
367 unsigned char *buf = shf->buf;
369 while (ntowrite > 0) {
370 n = write(shf->fd, buf, ntowrite);
372 if (errno == EINTR &&
373 !(shf->flags & SHF_INTERRUPT))
375 shf->flags |= SHF_ERROR;
376 shf->errnosv = errno;
378 if (buf != shf->buf) {
380 * allow a second flush
383 memmove(shf->buf, buf,
385 shf->wp = shf->buf + ntowrite;
392 if (flags & EB_READSW) {
395 shf->flags &= ~SHF_WRITING;
400 shf->wnleft = shf->wbsize;
402 shf->flags |= SHF_WRITING;
407 /* Fill up a read buffer. Returns -1 for a read error, 0 otherwise. */
409 shf_fillbuf(struct shf *shf)
413 if (shf->flags & SHF_STRING)
417 internal_errorf(Tf_sD_s, "shf_fillbuf", "no fd");
419 if (shf->flags & (SHF_EOF | SHF_ERROR)) {
420 if (shf->flags & SHF_ERROR)
421 errno = shf->errnosv;
425 if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == -1)
428 shf->flags |= SHF_READING;
431 while (/* CONSTCOND */ 1) {
432 n = blocking_read(shf->fd, (char *)shf->buf, shf->rbsize);
433 if (n < 0 && errno == EINTR && !(shf->flags & SHF_INTERRUPT))
438 shf->flags |= SHF_ERROR;
439 shf->errnosv = errno;
444 if ((shf->rnleft = n) == 0)
445 shf->flags |= SHF_EOF;
450 * Read a buffer from shf. Returns the number of bytes read into buf, if
451 * no bytes were read, returns 0 if end of file was seen, -1 if a read
455 shf_read(char *buf, ssize_t bsize, struct shf *shf)
457 ssize_t ncopy, orig_bsize = bsize;
459 if (!(shf->flags & SHF_RD))
460 internal_errorf(Tf_flags, Tshf_read,
461 (unsigned int)shf->flags);
464 internal_errorf(Tf_szs, Tshf_read, bsize, Tbsize);
467 if (shf->rnleft == 0 &&
468 (shf_fillbuf(shf) == -1 || shf->rnleft == 0))
473 memcpy(buf, shf->rp, ncopy);
477 shf->rnleft -= ncopy;
479 /* Note: fread(3S) returns 0 for errors - this doesn't */
480 return (orig_bsize == bsize ? (shf_error(shf) ? -1 : 0) :
485 * Read up to a newline or -1. The newline is put in buf; buf is always
486 * NUL terminated. Returns NULL on read error or if nothing was read
487 * before end of file, returns a pointer to the NUL byte in buf
491 shf_getse(char *buf, ssize_t bsize, struct shf *shf)
495 char *orig_buf = buf;
497 if (!(shf->flags & SHF_RD))
498 internal_errorf(Tf_flags, "shf_getse",
499 (unsigned int)shf->flags);
504 /* save room for NUL */
507 if (shf->rnleft == 0) {
508 if (shf_fillbuf(shf) == -1)
510 if (shf->rnleft == 0) {
512 return (buf == orig_buf ? NULL : buf);
515 end = (unsigned char *)memchr((char *)shf->rp, '\n',
517 ncopy = end ? end - shf->rp + 1 : shf->rnleft;
520 memcpy(buf, (char *) shf->rp, ncopy);
522 shf->rnleft -= ncopy;
525 #ifdef MKSH_WITH_TEXTMODE
526 if (end && buf > orig_buf + 1 && buf[-2] == '\r') {
532 } while (!end && bsize);
533 #ifdef MKSH_WITH_TEXTMODE
534 if (!bsize && buf[-1] == '\r') {
535 int c = shf_getc(shf);
546 /* Returns the char read. Returns -1 for error and end of file. */
548 shf_getchar(struct shf *shf)
550 if (!(shf->flags & SHF_RD))
551 internal_errorf(Tf_flags, "shf_getchar",
552 (unsigned int)shf->flags);
554 if (shf->rnleft == 0 && (shf_fillbuf(shf) == -1 || shf->rnleft == 0))
561 * Put a character back in the input stream. Returns the character if
562 * successful, -1 if there is no room.
565 shf_ungetc(int c, struct shf *shf)
567 if (!(shf->flags & SHF_RD))
568 internal_errorf(Tf_flags, "shf_ungetc",
569 (unsigned int)shf->flags);
571 if ((shf->flags & SHF_ERROR) || c == -1 ||
572 (shf->rp == shf->buf && shf->rnleft))
575 if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == -1)
578 if (shf->rp == shf->buf)
579 shf->rp = shf->buf + shf->rbsize;
580 if (shf->flags & SHF_STRING) {
582 * Can unget what was read, but not something different;
583 * we don't want to modify a string.
585 if ((int)(shf->rp[-1]) != c)
587 shf->flags &= ~SHF_EOF;
592 shf->flags &= ~SHF_EOF;
599 * Write a character. Returns the character if successful, -1 if the
600 * char could not be written.
603 shf_putchar(int c, struct shf *shf)
605 if (!(shf->flags & SHF_WR))
606 internal_errorf(Tf_flags, "shf_putchar",
607 (unsigned int)shf->flags);
612 if (shf->flags & SHF_UNBUF) {
613 unsigned char cc = (unsigned char)c;
617 internal_errorf(Tf_sD_s, "shf_putchar", "no fd");
618 if (shf->flags & SHF_ERROR) {
619 errno = shf->errnosv;
622 while ((n = write(shf->fd, &cc, 1)) != 1)
624 if (errno == EINTR &&
625 !(shf->flags & SHF_INTERRUPT))
627 shf->flags |= SHF_ERROR;
628 shf->errnosv = errno;
632 /* Flush deals with strings and sticky errors */
633 if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == -1)
643 * Write a string. Returns the length of the string if successful, -1
644 * if the string could not be written.
647 shf_puts(const char *s, struct shf *shf)
652 return (shf_write(s, strlen(s), shf));
655 /* Write a buffer. Returns nbytes if successful, -1 if there is an error. */
657 shf_write(const char *buf, ssize_t nbytes, struct shf *shf)
659 ssize_t n, ncopy, orig_nbytes = nbytes;
661 if (!(shf->flags & SHF_WR))
662 internal_errorf(Tf_flags, Tshf_write,
663 (unsigned int)shf->flags);
666 internal_errorf(Tf_szs, Tshf_write, nbytes, Tbytes);
668 /* Don't buffer if buffer is empty and we're writting a large amount. */
669 if ((ncopy = shf->wnleft) &&
670 (shf->wp != shf->buf || nbytes < shf->wnleft)) {
673 memcpy(shf->wp, buf, ncopy);
677 shf->wnleft -= ncopy;
680 if (shf->flags & SHF_STRING) {
681 /* resize buffer until there's enough space left */
682 while (nbytes > shf->wnleft)
683 if (shf_emptybuf(shf, EB_GROW) == -1)
685 /* then write everything into the buffer */
687 /* flush deals with sticky errors */
688 if (shf_emptybuf(shf, EB_GROW) == -1)
690 /* write chunks larger than window size directly */
691 if (nbytes > shf->wbsize) {
694 ncopy -= nbytes % shf->wbsize;
697 n = write(shf->fd, buf, ncopy);
699 if (errno == EINTR &&
700 !(shf->flags & SHF_INTERRUPT))
702 shf->flags |= SHF_ERROR;
703 shf->errnosv = errno;
706 * Note: fwrite(3) returns 0
707 * for errors - this doesn't
715 /* ... and buffer the rest */
718 /* write remaining bytes to buffer */
719 memcpy(shf->wp, buf, nbytes);
721 shf->wnleft -= nbytes;
725 return (orig_nbytes);
729 shf_fprintf(struct shf *shf, const char *fmt, ...)
735 n = shf_vfprintf(shf, fmt, args);
742 shf_snprintf(char *buf, ssize_t bsize, const char *fmt, ...)
748 if (!buf || bsize <= 0)
749 internal_errorf("shf_snprintf: buf %zX, bsize %zd",
752 shf_sopen(buf, bsize, SHF_WR, &shf);
754 n = shf_vfprintf(&shf, fmt, args);
762 shf_smprintf(const char *fmt, ...)
767 shf_sopen(NULL, 0, SHF_WR|SHF_DYNAMIC, &shf);
769 shf_vfprintf(&shf, fmt, args);
772 return (shf_sclose(&shf));
775 #define FL_HASH 0x001 /* '#' seen */
776 #define FL_PLUS 0x002 /* '+' seen */
777 #define FL_RIGHT 0x004 /* '-' seen */
778 #define FL_BLANK 0x008 /* ' ' seen */
779 #define FL_SHORT 0x010 /* 'h' seen */
780 #define FL_LONG 0x020 /* 'l' seen */
781 #define FL_ZERO 0x040 /* '0' seen */
782 #define FL_DOT 0x080 /* '.' seen */
783 #define FL_UPPER 0x100 /* format character was uppercase */
784 #define FL_NUMBER 0x200 /* a number was formated %[douxefg] */
785 #define FL_SIZET 0x400 /* 'z' seen */
786 #define FM_SIZES 0x430 /* h/l/z mask */
789 shf_vfprintf(struct shf *shf, const char *fmt, va_list args)
794 size_t field, precision, len;
796 /* %#o produces the longest output */
797 char numbuf[(8 * sizeof(long) + 2) / 3 + 1 + /* NUL */ 1];
798 /* this stuff for dealing with the buffer */
799 ssize_t nwritten = 0;
801 #define VA(type) va_arg(args, type)
806 while ((c = *fmt++)) {
813 * This will accept flags/fields in any order - not just
814 * the order specified in printf(3), but this is the way
815 * _doprnt() seems to work (on BSD and SYSV). The only
816 * restriction is that the format character must come
820 field = precision = 0;
821 while ((c = *fmt++)) {
840 if (!(flags & FL_DOT))
855 field = (unsigned int)-tmp;
858 } else if (flags & FL_DOT)
859 precision = (unsigned int)tmp;
861 field = (unsigned int)tmp;
879 if (ctype(c, C_DIGIT)) {
880 bool overflowed = false;
883 while (ctype((c = *fmt++), C_DIGIT))
884 if (notok2mul(2147483647, tmp, 10))
887 tmp = tmp * 10 + ksh_numdig(c);
892 precision = (unsigned int)tmp;
894 field = (unsigned int)tmp;
904 if (ctype(c, C_UPPER)) {
912 if (flags & FL_SIZET)
913 lnum = (long)VA(ssize_t);
914 else if (flags & FL_LONG)
916 else if (flags & FL_SHORT)
917 lnum = (long)(short)VA(int);
919 lnum = (long)VA(int);
925 if (flags & FL_SIZET)
927 else if (flags & FL_LONG)
928 lnum = VA(unsigned long);
929 else if (flags & FL_SHORT)
930 lnum = (unsigned long)(unsigned short)VA(int);
932 lnum = (unsigned long)VA(unsigned int);
936 cp = numbuf + sizeof(numbuf);
942 if (0 > (long)lnum) {
950 *--cp = digits_lc[lnum % 10];
957 else if (flags & FL_PLUS)
959 else if (flags & FL_BLANK)
966 *--cp = digits_lc[lnum & 0x7];
970 if ((flags & FL_HASH) && *cp != '0')
975 const char *digits = (flags & FL_UPPER) ?
976 digits_uc : digits_lc;
978 *--cp = digits[lnum & 0xF];
982 if (flags & FL_HASH) {
983 *--cp = (flags & FL_UPPER) ? 'X' : 'x';
988 len = numbuf + sizeof(numbuf) - 1 - (s = cp);
989 if (flags & FL_DOT) {
990 if (precision > len) {
1000 if ((s = VA(const char *)) == NULL)
1002 else if (flags & FL_HASH) {
1003 print_value_quoted(shf, s);
1006 len = utf_mbswidth(s);
1011 c = (char)(VA(int));
1024 * At this point s should point to a string that is to be
1025 * formatted, and len should be the length of the string.
1027 if (!(flags & FL_DOT) || len < precision)
1029 if (field > precision) {
1031 if (!(flags & FL_RIGHT)) {
1032 /* skip past sign or 0x when padding with 0 */
1033 if ((flags & FL_ZERO) && (flags & FL_NUMBER)) {
1034 if (ctype(*s, C_SPC | C_PLUS | C_MINUS)) {
1039 } else if (*s == '0') {
1044 ksh_eq(*s, 'X', 'x')) {
1053 c = flags & FL_ZERO ? '0' : ' ';
1063 nwritten += precision;
1064 precision = utf_skipcols(s, precision, &tmp) - s;
1066 shf_putc(*s++, shf);
1073 return (shf_error(shf) ? -1 : nwritten);
1076 #if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST)
1078 shf_getc(struct shf *shf)
1080 return (shf_getc_i(shf));
1084 shf_putc(int c, struct shf *shf)
1086 return (shf_putc_i(c, shf));
1092 cstrerror(int errnum)
1095 return (strerror(errnum));
1096 #define strerror dontuse_strerror /* poisoned */
1098 #elif !HAVE_STRERROR
1100 #if HAVE_SYS_ERRLIST
1101 #if !HAVE_SYS_ERRLIST_DECL
1102 extern const int sys_nerr;
1103 extern const char * const sys_errlist[];
1108 cstrerror(int errnum)
1110 /* "Unknown error: " + sign + rough estimate + NUL */
1111 static char errbuf[15 + 1 + (8 * sizeof(int) + 2) / 3 + 1];
1113 #if HAVE_SYS_ERRLIST
1114 if (errnum > 0 && errnum < sys_nerr && sys_errlist[errnum])
1115 return (sys_errlist[errnum]);
1120 return ("Undefined error: 0");
1122 return ("Operation not permitted");
1124 return ("No such file or directory");
1127 return ("No such process");
1131 return ("Argument list too long");
1134 return ("Exec format error");
1136 return ("Bad file descriptor");
1139 return ("Cannot allocate memory");
1142 return ("Permission denied");
1144 return ("File exists");
1146 return ("Not a directory");
1149 return ("Invalid argument");
1153 return ("Too many levels of symbolic links");
1156 shf_snprintf(errbuf, sizeof(errbuf),
1157 "Unknown error: %d", errnum);
1163 /* fast character classes */
1164 const uint32_t tpl_ctypes[128] = {
1166 CiNUL, CiCNTRL, CiCNTRL, CiCNTRL,
1167 CiCNTRL, CiCNTRL, CiCNTRL, CiCNTRL,
1168 CiCNTRL, CiTAB, CiNL, CiSPX,
1169 CiSPX, CiCR, CiCNTRL, CiCNTRL,
1171 CiCNTRL, CiCNTRL, CiCNTRL, CiCNTRL,
1172 CiCNTRL, CiCNTRL, CiCNTRL, CiCNTRL,
1173 CiCNTRL, CiCNTRL, CiCNTRL, CiCNTRL,
1174 CiCNTRL, CiCNTRL, CiCNTRL, CiCNTRL,
1176 CiSP, CiALIAS | CiVAR1, CiQC, CiHASH,
1177 CiSS, CiPERCT, CiQCL, CiQC,
1178 CiQCL, CiQCL, CiQCX | CiVAR1, CiPLUS,
1179 CiALIAS, CiMINUS, CiALIAS, CiQCM,
1181 CiOCTAL, CiOCTAL, CiOCTAL, CiOCTAL,
1182 CiOCTAL, CiOCTAL, CiOCTAL, CiOCTAL,
1183 CiDIGIT, CiDIGIT, CiCOLON, CiQCL,
1184 CiANGLE, CiEQUAL, CiANGLE, CiQUEST,
1186 CiALIAS | CiVAR1, CiUPPER | CiHEXLT,
1187 CiUPPER | CiHEXLT, CiUPPER | CiHEXLT,
1188 CiUPPER | CiHEXLT, CiUPPER | CiHEXLT,
1189 CiUPPER | CiHEXLT, CiUPPER,
1190 CiUPPER, CiUPPER, CiUPPER, CiUPPER,
1191 CiUPPER, CiUPPER, CiUPPER, CiUPPER,
1193 CiUPPER, CiUPPER, CiUPPER, CiUPPER,
1194 CiUPPER, CiUPPER, CiUPPER, CiUPPER,
1195 CiUPPER, CiUPPER, CiUPPER, CiQCX | CiBRACK,
1196 CiQCX, CiBRACK, CiQCM, CiUNDER,
1198 CiGRAVE, CiLOWER | CiHEXLT,
1199 CiLOWER | CiHEXLT, CiLOWER | CiHEXLT,
1200 CiLOWER | CiHEXLT, CiLOWER | CiHEXLT,
1201 CiLOWER | CiHEXLT, CiLOWER,
1202 CiLOWER, CiLOWER, CiLOWER, CiLOWER,
1203 CiLOWER, CiLOWER, CiLOWER, CiLOWER,
1205 CiLOWER, CiLOWER, CiLOWER, CiLOWER,
1206 CiLOWER, CiLOWER, CiLOWER, CiLOWER,
1207 CiLOWER, CiLOWER, CiLOWER, CiCURLY,
1208 CiQCL, CiCURLY, CiQCM, CiCNTRL
1212 set_ifs(const char *s)
1214 #if defined(MKSH_EBCDIC) || defined(MKSH_FAUX_EBCDIC)
1217 memset(ksh_ctypes, 0, sizeof(ksh_ctypes));
1219 if (ebcdic_map[i] < 0x80U)
1220 ksh_ctypes[i] = tpl_ctypes[ebcdic_map[i]];
1222 memcpy(ksh_ctypes, tpl_ctypes, sizeof(tpl_ctypes));
1223 memset((char *)ksh_ctypes + sizeof(tpl_ctypes), '\0',
1224 sizeof(ksh_ctypes) - sizeof(tpl_ctypes));
1228 ksh_ctypes[ord(*s++)] |= CiIFS;
1231 #if defined(MKSH_EBCDIC) || defined(MKSH_FAUX_EBCDIC)
1235 * Many headaches with EBCDIC:
1236 * 1. There are numerous EBCDIC variants, and it is not feasible for us
1237 * to support them all. But we can support the EBCDIC code pages that
1238 * contain all (most?) of the characters in ASCII, and these
1239 * usually tend to agree on the code points assigned to the ASCII
1240 * subset. If you need a representative example, look at EBCDIC 1047,
1241 * which is first among equals in the IBM MVS development
1242 * environment: https://en.wikipedia.org/wiki/EBCDIC_1047
1243 * Unfortunately, the square brackets are not consistently mapped,
1244 * and for certain reasons, we need an unambiguous bijective
1245 * mapping between EBCDIC and "extended ASCII".
1246 * 2. Character ranges that are contiguous in ASCII, like the letters
1247 * in [A-Z], are broken up into segments (i.e. [A-IJ-RS-Z]), so we
1248 * can't implement e.g. islower() as { return c >= 'a' && c <= 'z'; }
1249 * because it will also return true for a handful of extraneous
1250 * characters (like the plus-minus sign at 0x8F in EBCDIC 1047, a
1251 * little after 'i'). But at least '_' is not one of these.
1252 * 3. The normal [0-9A-Za-z] characters are at codepoints beyond 0x80.
1253 * Not only do they require all 8 bits instead of 7, if chars are
1254 * signed, they will have negative integer values! Something like
1255 * (c - 'A') could actually become (c + 63)! Use the ord() macro to
1256 * ensure you're getting a value in [0, 255].
1257 * 4. '\n' is actually NL (0x15, U+0085) instead of LF (0x25, U+000A).
1258 * EBCDIC has a proper newline character instead of "emulating" one
1259 * with line feeds, although this is mapped to LF for our purposes.
1260 * 5. Note that it is possible to compile programs in ASCII mode on IBM
1261 * mainframe systems, using the -qascii option to the XL C compiler.
1262 * We can determine the build mode by looking at __CHARSET_LIB:
1263 * 0 == EBCDIC, 1 == ASCII
1274 ebcdic_rtt_toascii[i] = i;
1275 memset(ebcdic_rtt_fromascii, 0xFF, sizeof(ebcdic_rtt_fromascii));
1276 setlocale(LC_ALL, "");
1278 if (__etoa_l(ebcdic_rtt_toascii, 256) != 256) {
1279 write(2, "mksh: could not map EBCDIC to ASCII\n", 36);
1284 memset(mapcache, 0, sizeof(mapcache));
1287 t = ebcdic_rtt_toascii[i];
1288 /* ensure unique round-trip capable mapping */
1290 write(2, "mksh: duplicate EBCDIC to ASCII mapping\n", 40);
1294 * since there are 256 input octets, this also ensures
1295 * the other mapping direction is completely filled
1298 /* fill the complete round-trip map */
1299 ebcdic_rtt_fromascii[t] = i;
1301 * Only use the converted value if it's in the range
1302 * [0x00; 0x7F], which I checked; the "extended ASCII"
1303 * characters can be any encoding, not just Latin1,
1304 * and the C1 control characters other than NEL are
1305 * hopeless, but we map EBCDIC NEL to ASCII LF so we
1306 * cannot even use C1 NEL.
1307 * If ever we map to Unicode, bump the table width to
1308 * an unsigned int, and or the raw unconverted EBCDIC
1309 * values with 0x01000000 instead.
1312 ebcdic_map[i] = (unsigned short)ord(t);
1314 ebcdic_map[i] = (unsigned short)(0x100U | ord(i));
1316 if (ebcdic_rtt_toascii[0] || ebcdic_rtt_fromascii[0] || ebcdic_map[0]) {
1317 write(2, "mksh: NUL not at position 0\n", 28);