/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these librararies and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* $XConsortium: exksh_prpar.c /main/4 1995/11/01 15:54:12 rswiston $ */ /* Copyright (c) 1991, 1992 UNIX System Laboratories, Inc. */ /* All Rights Reserved */ /* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF */ /* UNIX System Laboratories, Inc. */ /* The copyright notice above does not evidence any */ /* actual or intended publication of such source code. */ #include "name.h" #include "shell.h" #include #include #include #include #include "exksh.h" #include "stdio.h" #include "exksh_prpar.h" #include "symbolic.h" #include "msgs.h" static int xk_uppercase( char *s) ; static int getsize( int fd, int *psize) ; #define OBJ_END 100 struct symlist Val_list; unsigned int Pr_format = PRSYMBOLIC|PRMIXED|PRNAMES; /* * Takes a pointer to a pointer to a character buffer, and skips any * whitespace, as defined by isspace(section 3). Increments the * buf parameter to the first non-whitespace character. * Returns SUCCESS, there are no known ways for it to fail. */ int xk_skipwhite( char **buf ) { while (isspace(**buf)) (*buf)++; return(SUCCESS); } int xk_backskip( char **buf, int *n ) { *n = 0; while (isspace(**buf)) { (*buf)--; *n++; } if ((*buf)[0] == '\\') return(TRUE); else return(FALSE); } /* * Takes a pointer to a character buffer and a string. Sees if * the str is present as the first part of the buffer (minus any * whitespace), and if so increments the buffer past the string. * If not, returns FAIL without incrementing buffer (except perhaps * by eating leading whitespace). */ int xk_parexpect( char **buf, char *str ) { RIF(xk_skipwhite(buf)); if (strncmp(*buf, str, strlen(str)) == 0) { *buf += strlen(str); } else { return(FAIL); } return(SUCCESS); } /* * Takes a pointer to a char buffer, and a string. Returns * TRUE if the string appears immediately (after skipping whitespace). * or FALSE otherwise. */ int xk_parpeek( char **buf, char *str ) { RIF(xk_skipwhite(buf)); if (strncmp(*buf, str, strlen(str)) == 0) return(TRUE); else return(FALSE); } int xk_prin_int( memtbl_t *tbl, char **buf, unsigned long *old_v ) { register int i, printed = 0; struct symlist *sym; unsigned long v; switch (tbl->kind) { case K_CHAR: v = *((unsigned char *) old_v); break; case K_SHORT: v = *((unsigned short *) old_v); break; case K_INT: v = *((unsigned int *) old_v); break; default: v = *old_v; } **buf = '\0'; if ((Pr_format & PRSYMBOLIC) && ((Val_list.syms != NULL) || ((sym = fsymbolic(tbl)) != NULL))) { if (Val_list.syms != NULL) sym = &Val_list; if (sym->isflag) { if (v == 0) { *buf += lsprintf(*buf, "0"); return(SUCCESS); } for (i = 0; i < sym->nsyms; i++) { if (sym->syms[i].addr & v) { if (Pr_format & PRMIXED_SYMBOLIC) { if (Pr_format & PRDECIMAL) *buf += lsprintf(*buf, "%s%s(%d)", printed ? "|" : "", sym->syms[i].str, sym->syms[i].addr); else *buf += lsprintf(*buf, "%s%s(0x%x)", printed ? "|" : "", sym->syms[i].str, sym->syms[i].addr); } else *buf += lsprintf(*buf, "%s%s", printed ? "|" : "", sym->syms[i].str); v &= ~(sym->syms[i].addr); printed++; } } if (v) { if (Pr_format & PRMIXED_SYMBOLIC) { if (Pr_format & PRDECIMAL) *buf += lsprintf(*buf, "%sNOSYMBOLIC(%d)", printed ? "|" : "", v); else *buf += lsprintf(*buf, "%sNOSYMBOLIC(0x%x)", printed ? "|" : "", v); } else { if (Pr_format & PRDECIMAL) *buf += lsprintf(*buf, "%s%d", printed ? "|" : "", v); else *buf += lsprintf(*buf, "%s0x%x", printed ? "|" : "", v); } } return(SUCCESS); } else { for (i = 0; i < sym->nsyms; i++) { if (sym->syms[i].addr == v) { if (Pr_format & PRMIXED_SYMBOLIC) { if (Pr_format & PRDECIMAL) *buf += lsprintf(*buf, "%s(%d)", sym->syms[i].str, v); else *buf += lsprintf(*buf, "%s(0x%x)", sym->syms[i].str, v); } else *buf += lsprintf(*buf, "%s", sym->syms[i].str); return(SUCCESS); } } } } if (Pr_format & PRHEX) *buf += lsprintf(*buf, "0x%x", v); else if (Pr_format & PRDECIMAL) *buf += lsprintf(*buf, "%d", v); else *buf += lsprintf(*buf, "%d(0x%x)", v, v); return(SUCCESS); } int xk_par_int( char **buf, long *v, struct envsymbols *env ) { register int ret, base; char *p, *q, *pp; char nbuf[512]; xk_skipwhite(buf); strncpy(nbuf, *buf, sizeof(nbuf)-1); if (strchr(nbuf, '|') == NULL) { for (p = nbuf; *p && *p != ' ' && *p != ',' && *p != ']' && *p != '{' && *p != '}' && *p != '/' && *p != '@' && *p != ':' && *p != '.' && *p != 13 && *p != 10 && *p != 11 && *p != 12 && *p != 9; p++) ; *p = '\0'; } else { for (p = nbuf; *p && *p != ',' && *p != '{' && *p != '}' && *p != '/' && *p != '@' && *p != ':' && *p != '.' ; p++) ; *p = '\0'; } ret = strlen(nbuf); if (ret == 0) return(OBJ_END); *v = 0; if ((p = strchr(nbuf, '"')) != NULL) { return(FAIL); } if ((p = strchr(nbuf, '+')) != NULL) { char *qq; long v1, v2; *p = '\0'; v1 = v2 = 0; qq = nbuf; p++; xk_par_int(&qq, &v1, env); xk_par_int(&p, &v2, env); *v = v1 + v2; *buf += ret; return(SUCCESS); } if ((p = strchr(&nbuf[1], '-')) != NULL) { long v1, v2; char *qq; *p = '\0'; v1 = v2 = 0; qq = nbuf; p++; xk_par_int(&qq, &v1, env); xk_par_int(&p, &v2, env); *v = v1 - v2; *buf += ret; return(SUCCESS); } for (p = strtok(nbuf, " |\t\n"); p; p = strtok(NULL, " |\t\n")) { for (pp = p; *pp && *pp != ' ' && *pp != ',' && *pp != '{' && *pp != '}' && *pp != '/' && *pp != '@' && *pp != ':' && *pp != '.' && *pp != 13 && *pp != 11 && *pp != 12 && *pp != 9; pp++) ; *pp = '\0'; if ((pp = strchr(p, '#')) != NULL) { base = strtol(p, &p, 10); if (p != pp) return(FAIL); p++; } else base = 0; xk_skipwhite(&p); if (*p == '\0') continue; if (isdigit(*p) || *p == '-') { *v |= strtoul(p, (char **)NULL, base); } else { unsigned long val; /* knock out commentary parenthesized things */ if ((q = strchr(p, '(' /*)*/ )) != NULL) *q = '\0'; /* Search through available names for partial match */ if (!fdef(p, &val)) { return(FAIL); } else *v |= val; } } *buf += ret; return(SUCCESS); } int xk_prin_nts( char **buf, char *str ) { return(xk_prin_charstr(buf, (unsigned char *)str, str ? strlen(str) : 0)); } int xk_prin_charstr( char **buf, unsigned char *str, int len ) { register int i; if (str == NULL) *buf += lsprintf(*buf, "NULL"); else { *buf += lsprintf(*buf, "\""); for (i = 0; i < len; i++) { if (str[i] == '"') { *buf += lsprintf(*buf, "\\\""); } else if (isprint(str[i])) { *buf += lsprintf(*buf, "%c", str[i]); } else { switch (str[i]) { case '\n': *buf += lsprintf(*buf, "\\n"); break; case '\t': *buf += lsprintf(*buf, "\\t"); break; case '\b': *buf += lsprintf(*buf, "\\b"); break; case '\v': *buf += lsprintf(*buf, "\\v"); break; case '\f': *buf += lsprintf(*buf, "\\f"); break; case '\r': *buf += lsprintf(*buf, "\\r"); break; case '\0': *buf += lsprintf(*buf, "\\00"); break; default: *buf += lsprintf(*buf, "\\%x", (unsigned int)str[i]); break; } } } *buf += lsprintf(*buf, "\""); } return(SUCCESS); } int xk_prin_hexstr( char **buf, char *str, int len ) { register int i; unsigned char tempc; if (str == NULL) *buf += lsprintf(*buf, "NULL"); else { *buf += lsprintf(*buf, "%s", "0x"); for (i = 0; i < len; i++) { tempc = str[i]; if (str[i] & 0xf0) { *buf += lsprintf(*buf, "%x", tempc); } else *buf += lsprintf(*buf, "0%x", tempc); } } return(SUCCESS); } #define MALSIZ 16 /* initial size of string to malloc */ int xk_par_chararr( char **buf, char *str, int *len ) { return(xk_par_charstr(buf, &str, len)); } #define CHAR_QUOTED 0 #define CHAR_HEXSTR 1 #define CHAR_FILE 2 int xk_par_nts( char **buf, char **str ) { int temp = 0; RIF(xk_par_charstr(buf, str, &temp)); if (temp >= 0) str[0][temp] = '\0'; return(SUCCESS); } int xk_par_charstr( char **buf, char **str, int *len ) { register int i; char delim; int didmalloc = FALSE, getmode; char cbuf[3]; /* conversion buffer for hex strings */ char filename[128]; char * errmsg; RIF(xk_skipwhite(buf)); if (xk_parpeek(buf, "NULL")) { RIF(xk_parexpect(buf, "NULL")); *str = NULL; *len = -1; return(SUCCESS); } /* this is pure internal feature, no error setting */ if (**buf == '<') { char *p; FILE *fp; char gbuf[BUFSIZ]; int line; int size; (*buf)++; xk_skipwhite(buf); for (p = &filename[0]; **buf != ',' && **buf != /* { */ '}' && **buf != ' ' && **buf != '\t' && p < &filename[sizeof(filename)]; *p++ = *(*buf)++) ; *p++ = '\0'; if ((fp = fopen(filename, "r")) == NULL) { errmsg=strdup(GETMESSAGE(7,1, "Unable to open the file '%s'; verify that it exists and is readable")); lsprintf(gbuf, errmsg, filename); fprintf(stderr, gbuf); free(errmsg); return(FAIL); } if (*len == 0) { if (getsize(fileno(fp), &size) == FAIL) { errmsg=strdup(GETMESSAGE(7,2, "Unable to access the file '%s'; verify you have permission to access it")); lsprintf(gbuf, errmsg, filename); fprintf(stderr, gbuf); free(errmsg); return(FAIL); } *len = size/2 + 1; if ((*str = malloc(*len)) == NULL) { return(FAIL); } } line = i = 0; while (fgets(gbuf, sizeof(gbuf), fp) != NULL) { line++; p = gbuf; /* eat any leading 0x */ if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { p += 2; } for ( ; *p && *p != '\n'; ) { if (i > *len - 1) { fclose(fp); return(FAIL); } if (!isxdigit(*p)) { p++; continue; } if (!isxdigit(p[1])) { fclose(fp); return(FAIL); } cbuf[0] = p[0]; cbuf[1] = p[1]; cbuf[2] = '\0'; str[0][i++] = (char)strtol(cbuf, (char **)NULL, 16); p += 2; xk_skipwhite(&p); } } *len = i; fclose(fp); return(SUCCESS); } else if (!ispunct(**buf)) { getmode = CHAR_HEXSTR; if ((*buf)[0] == '0' && ((*buf)[1] == 'x' || (*buf)[1] == 'X')) (*buf) += 2; } else { delim = *((*buf)++); getmode = CHAR_QUOTED; } if (*len == 0) { if ((*str = malloc(MALSIZ)) == NULL) { return(FAIL); } didmalloc = TRUE; *len = MALSIZ; } i = 0; while ((*buf)[0] != '\0' && ((getmode == CHAR_QUOTED && (*buf)[0] != delim) || (getmode == CHAR_HEXSTR && (isxdigit((*buf)[0]))) || (getmode == CHAR_HEXSTR && (isspace((*buf)[0]))))) { /* NOTE: must always leave 1 additional byte for a null * termination, because could be called by xk_par_nts! */ if (i >= *len - 1) { if (didmalloc == FALSE) { return(FAIL); } else { if ((*str = realloc(*str, *len + MALSIZ)) == NULL) { return(FAIL); } *len += MALSIZ; } } if (getmode == CHAR_QUOTED) { if ((*buf)[0] == '\\') { (*buf)++; switch ((*buf)[0]) { case 't': str[0][i++] = '\t'; (*buf)++; break; case 'v': str[0][i++] = '\v'; (*buf)++; break; case 'f': str[0][i++] = '\f'; (*buf)++; break; case 'n': str[0][i++] = '\n'; (*buf)++; break; case 'r': str[0][i++] = '\r'; (*buf)++; break; case 'b': str[0][i++] = '\b'; (*buf)++; break; case '0': str[0][i++] = (char)strtol(*buf, buf, 8); break; case 's': (*buf)++; break; default: str[0][i++] = *(*buf)++; } } else str[0][i++] = *(*buf)++; } else { if (!isxdigit((*buf)[1])) { return(FAIL); } cbuf[0] = (*buf)[0]; cbuf[1] = (*buf)[1]; cbuf[2] = '\0'; str[0][i++] = (char)strtol(cbuf, (char **)NULL, 16); (*buf) += 2; xk_skipwhite(buf); } } if (getmode == CHAR_QUOTED) (*buf)++; /* eat the trailing quote */ /* * NOTE: We leave a malloced buffer the same size rather * than realloc()'ing it to be the exact size in order * to save time and avoid malloc arena fragmentation */ *len = i; return(SUCCESS); } /* Case Ignoring String Functions. */ static int xk_uppercase( char *s ) { while (*s) { if (islower(*s)) *s = toupper(*s); s++; } } int xk_Strncmp( char *s1, char *s2, int len ) { int diff, i; for (i=0; i < len && s1[i] != '\0' && s2[i] != '\0'; i++) if ((diff = tolower(s1[i]) - tolower(s2[i])) != 0) return (diff); return(i == len ? 0 : s1[i] - s2[i]); } static int getsize( int fd, int *psize ) { struct stat stat; if (fstat(fd, &stat) == FAIL) return(FAIL); *psize = stat.st_size; return(SUCCESS); }