cdesktopenv/cde/programs/dtksh/exksh_prpar.c

663 lines
14 KiB
C

/*
* 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 <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <ctype.h>
#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);
}