convert all Imakefile LinuxDistribution to LinuxArchitecture.
[oweals/cde.git] / cde / programs / dtksh / exksh_prpar.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: exksh_prpar.c /main/4 1995/11/01 15:54:12 rswiston $ */
24
25 /*      Copyright (c) 1991, 1992 UNIX System Laboratories, Inc. */
26 /*      All Rights Reserved     */
27
28 /*      THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF    */
29 /*      UNIX System Laboratories, Inc.                  */
30 /*      The copyright notice above does not evidence any       */
31 /*      actual or intended publication of such source code.    */
32
33
34 #include        "name.h"
35 #include        "shell.h"
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include "exksh.h"
41 #include "stdio.h"
42 #include "exksh_prpar.h"
43 #include "symbolic.h"
44 #include "msgs.h"
45
46
47
48 static int xk_uppercase( 
49                         char *s) ;
50 static int getsize( 
51                         int fd,
52                         int *psize) ;
53
54
55
56 #define OBJ_END 100
57
58 struct symlist Val_list;
59
60 unsigned int Pr_format = PRSYMBOLIC|PRMIXED|PRNAMES;
61
62
63 /*
64  * Takes a pointer to a pointer to a character buffer, and skips any
65  * whitespace, as defined by isspace(section 3).  Increments the
66  * buf parameter to the first non-whitespace character.
67  * Returns SUCCESS, there are no known ways for it to fail.
68  */
69
70 int
71 xk_skipwhite(
72         char **buf )
73 {
74         while (isspace(**buf))
75                 (*buf)++;
76         return(SUCCESS);
77 }
78
79 int
80 xk_backskip(
81         char **buf,
82         int *n )
83 {
84         *n = 0;
85         while (isspace(**buf)) {
86                 (*buf)--;
87                 *n++;
88         }
89         if ((*buf)[0] == '\\')
90                 return(TRUE);
91         else
92                 return(FALSE);
93 }
94
95 /*
96  * Takes a pointer to a character buffer and a string.  Sees if
97  * the str is present as the first part of the buffer (minus any
98  * whitespace), and if so increments the buffer past the string.
99  * If not, returns FAIL without incrementing buffer (except perhaps
100  * by eating leading whitespace).
101  */
102
103 int
104 xk_parexpect(
105         char **buf,
106         char *str )
107 {
108         RIF(xk_skipwhite(buf));
109         if (strncmp(*buf, str, strlen(str)) == 0) {
110                 *buf += strlen(str);
111         } else {
112                 return(FAIL);
113         }
114         return(SUCCESS);
115 }
116
117 /*
118  * Takes a pointer to a char buffer, and a string.  Returns
119  * TRUE if the string appears immediately (after skipping whitespace).
120  * or FALSE otherwise.
121  */
122
123 int
124 xk_parpeek(
125         char **buf,
126         char *str )
127 {
128         RIF(xk_skipwhite(buf));
129         if (strncmp(*buf, str, strlen(str)) == 0)
130                 return(TRUE);
131         else
132                 return(FALSE);
133 }
134
135 int
136 xk_prin_int(
137         memtbl_t *tbl,
138         char **buf,
139         unsigned long *old_v )
140
141 {
142         register int i, printed = 0;
143         struct symlist *sym;
144         unsigned long v;
145
146         switch (tbl->kind) {
147         case K_CHAR:
148                 v = *((unsigned char *) old_v);
149                 break;
150         case K_SHORT:
151                 v = *((unsigned short *) old_v);
152                 break;
153         case K_INT:
154                 v = *((unsigned int *) old_v);
155                 break;
156         default:
157                 v = *old_v;
158         }
159         **buf = '\0';
160         if ((Pr_format & PRSYMBOLIC) && ((Val_list.syms != NULL) || ((sym = fsymbolic(tbl)) != NULL))) {
161                 if (Val_list.syms != NULL)
162                         sym = &Val_list;
163                 if (sym->isflag) {
164                         if (v == 0) {
165                                 *buf += lsprintf(*buf, "0");
166                                 return(SUCCESS);
167                         }
168                         for (i = 0; i < sym->nsyms; i++) {
169                                 if (sym->syms[i].addr & v) {
170                                         if (Pr_format & PRMIXED_SYMBOLIC) {
171                                                 if (Pr_format & PRDECIMAL)
172                                                         *buf += lsprintf(*buf, "%s%s(%d)", printed ? "|" : "", sym->syms[i].str, sym->syms[i].addr);
173                                                 else
174                                                         *buf += lsprintf(*buf, "%s%s(0x%x)", printed ? "|" : "", sym->syms[i].str, sym->syms[i].addr);
175                                         }
176                                         else
177                                                 *buf += lsprintf(*buf, "%s%s", printed ? "|" : "", sym->syms[i].str);
178                                         v &= ~(sym->syms[i].addr);
179                                         printed++;
180                                 }
181                         }
182                         if (v) {
183                                 if (Pr_format & PRMIXED_SYMBOLIC) {
184                                         if (Pr_format & PRDECIMAL)
185                                                 *buf += lsprintf(*buf, "%sNOSYMBOLIC(%d)", printed ? "|" : "", v);
186                                         else
187                                                 *buf += lsprintf(*buf, "%sNOSYMBOLIC(0x%x)", printed ? "|" : "", v);
188                                 }
189                                 else {
190                                         if (Pr_format & PRDECIMAL)
191                                                 *buf += lsprintf(*buf, "%s%d", printed ? "|" : "", v);
192                                         else
193                                                 *buf += lsprintf(*buf, "%s0x%x", printed ? "|" : "", v);
194                                 }
195                         }
196                         return(SUCCESS);
197                 }
198                 else {
199                         for (i = 0; i < sym->nsyms; i++) {
200                                 if (sym->syms[i].addr == v) {
201                                         if (Pr_format & PRMIXED_SYMBOLIC) {
202                                                 if (Pr_format & PRDECIMAL)
203                                                         *buf += lsprintf(*buf, "%s(%d)", sym->syms[i].str, v);
204                                                 else
205                                                         *buf += lsprintf(*buf, "%s(0x%x)", sym->syms[i].str, v);
206                                         }
207                                         else
208                                                 *buf += lsprintf(*buf, "%s", sym->syms[i].str);
209                                         return(SUCCESS);
210                                 }
211                         }
212                 }
213         }
214         if (Pr_format & PRHEX)
215                 *buf += lsprintf(*buf, "0x%x", v);
216         else if (Pr_format & PRDECIMAL)
217                 *buf += lsprintf(*buf, "%d", v);
218         else
219                 *buf += lsprintf(*buf, "%d(0x%x)", v, v);
220         return(SUCCESS);
221 }
222
223 int
224 xk_par_int(
225         char **buf,
226         long *v,
227         struct envsymbols *env )
228 {
229         register int ret, base;
230         char *p, *q, *pp;
231         char nbuf[512];
232
233         xk_skipwhite(buf);
234         strncpy(nbuf, *buf, sizeof(nbuf)-1);
235         if (strchr(nbuf, '|') == NULL) {
236                 for (p = nbuf; *p && *p != ' ' && *p != ',' && *p != ']'
237                 && *p != '{' && *p != '}' && *p != '/' && *p != '@'
238                 && *p != ':' && *p != '.' && *p != 13 && *p != 10 && *p != 11
239                 && *p != 12 && *p != 9; p++)
240                         ;
241                 *p = '\0';
242         }
243         else {
244                 for (p = nbuf; *p && *p != ','
245                 && *p != '{' && *p != '}' && *p != '/' && *p != '@'
246                 && *p != ':' && *p != '.' ; p++)
247                         ;
248                 *p = '\0';
249
250         }
251         ret = strlen(nbuf);
252         if (ret == 0)
253                 return(OBJ_END);
254         *v = 0;
255
256         if ((p = strchr(nbuf, '"')) != NULL) {
257                 return(FAIL);
258         }
259         if ((p = strchr(nbuf, '+')) != NULL) {
260                 char *qq;
261                 long v1, v2;
262
263                 *p = '\0';
264                 v1 = v2 = 0;
265                 qq = nbuf;
266                 p++;
267                 xk_par_int(&qq, &v1, env);
268                 xk_par_int(&p, &v2, env);
269                 *v = v1 + v2;
270                 *buf += ret;
271                 return(SUCCESS);
272         }
273         if ((p = strchr(&nbuf[1], '-')) != NULL) {
274                 long v1, v2;
275                 char *qq;
276
277                 *p = '\0';
278                 v1 = v2 = 0;
279                 qq = nbuf;
280                 p++;
281                 xk_par_int(&qq, &v1, env);
282                 xk_par_int(&p, &v2, env);
283                 *v = v1 - v2;
284                 *buf += ret;
285                 return(SUCCESS);
286         }
287         for (p = strtok(nbuf, " |\t\n"); p; p = strtok(NULL, " |\t\n")) {
288                 for (pp = p; *pp && *pp != ' ' && *pp != ','
289                 && *pp != '{' && *pp != '}' && *pp != '/' && *pp != '@'
290                 && *pp != ':' && *pp != '.' && *pp != 13 &&
291                 *pp != 11 && *pp != 12 && *pp != 9; pp++)
292                         ;
293                 *pp = '\0';
294                 if ((pp = strchr(p, '#')) != NULL) {
295                         base = strtol(p, &p, 10);
296                         if (p != pp)
297                                 return(FAIL);
298                         p++;
299                 }
300                 else
301                         base = 0;
302                 xk_skipwhite(&p);
303                 if (*p == '\0')
304                         continue;
305                 if (isdigit(*p) || *p == '-') {
306                         *v |= strtoul(p, (char **)NULL, base);
307                 }
308                 else {
309                         unsigned long val;
310
311                         /* knock out commentary parenthesized things */
312                         if ((q = strchr(p, '(' /*)*/ )) != NULL)
313                                 *q = '\0';
314                         /* Search through available names for partial match */
315                         if (!fdef(p, &val)) {
316                                 return(FAIL);
317                         }
318                         else
319                                 *v |= val;
320                 }
321         }
322         *buf += ret;
323         return(SUCCESS);
324 }
325
326
327 int
328 xk_prin_nts(
329         char **buf,
330         char *str )
331 {
332         return(xk_prin_charstr(buf, (unsigned char *)str, 
333                str ? strlen(str) : 0));
334 }
335
336 int
337 xk_prin_charstr(
338         char **buf,
339         unsigned char *str,
340         int len )
341 {
342         register int i;
343
344         if (str == NULL)
345                 *buf += lsprintf(*buf, "NULL");
346         else {
347                 *buf += lsprintf(*buf, "\"");
348                 for (i = 0; i < len; i++) {
349                         if (str[i] == '"') {
350                                 *buf += lsprintf(*buf, "\\\"");
351                         } else if (isprint(str[i])) {
352                                 *buf += lsprintf(*buf, "%c", str[i]);
353                         } else {
354                                 switch (str[i]) {
355                                 case '\n':
356                                         *buf += lsprintf(*buf, "\\n");
357                                         break;
358                                 case '\t':
359                                         *buf += lsprintf(*buf, "\\t");
360                                         break;
361                                 case '\b':
362                                         *buf += lsprintf(*buf, "\\b");
363                                         break;
364                                 case '\v':
365                                         *buf += lsprintf(*buf, "\\v");
366                                         break;
367                                 case '\f':
368                                         *buf += lsprintf(*buf, "\\f");
369                                         break;
370                                 case '\r':
371                                         *buf += lsprintf(*buf, "\\r");
372                                         break;
373                                 case '\0':
374                                         *buf += lsprintf(*buf, "\\00");
375                                         break;
376                                 default:
377                                         *buf += lsprintf(*buf, "\\%x", (unsigned int)str[i]);
378                                         break;
379                                 }
380                         }
381                 }
382                 *buf += lsprintf(*buf, "\"");
383         }
384         return(SUCCESS);
385 }
386
387 int
388 xk_prin_hexstr(
389         char **buf,
390         char *str,
391         int len )
392 {
393         register int i;
394         unsigned char tempc;
395
396         if (str == NULL)
397                 *buf += lsprintf(*buf, "NULL");
398         else {
399                 *buf += lsprintf(*buf, "%s", "0x");
400                 for (i = 0; i < len; i++) {
401                         tempc = str[i];
402                         if (str[i] & 0xf0) {
403                                 *buf += lsprintf(*buf, "%x", tempc);
404                         }
405                         else
406                                 *buf += lsprintf(*buf, "0%x", tempc);
407                 }
408         }
409         return(SUCCESS);
410 }
411
412 #define MALSIZ 16       /* initial size of string to malloc */
413
414 int
415 xk_par_chararr(
416         char **buf,
417         char *str,
418         int *len )
419 {
420         return(xk_par_charstr(buf, &str, len));
421 }
422
423 #define CHAR_QUOTED     0
424 #define CHAR_HEXSTR     1
425 #define CHAR_FILE       2
426
427 int
428 xk_par_nts(
429         char **buf,
430         char **str )
431 {
432         int temp = 0;
433
434         RIF(xk_par_charstr(buf, str, &temp));
435         if (temp >= 0)
436                 str[0][temp] = '\0';
437         return(SUCCESS);
438 }
439
440 int
441 xk_par_charstr(
442         char **buf,
443         char **str,
444         int *len )
445 {
446         register int i;
447         char delim;
448         int didmalloc = FALSE, getmode;
449         char cbuf[3];   /* conversion buffer for hex strings */
450         char filename[128];
451         char * errmsg;
452
453         RIF(xk_skipwhite(buf));
454         if (xk_parpeek(buf, "NULL")) {
455                 RIF(xk_parexpect(buf, "NULL"));
456                 *str = NULL;
457                 *len = -1;
458                 return(SUCCESS);
459         }
460         /* this is pure internal feature, no error setting */
461         if (**buf == '<') {
462                 char *p;
463                 FILE *fp;
464                 char gbuf[BUFSIZ];
465                 int line;
466                 int size;
467
468                 (*buf)++;
469                 xk_skipwhite(buf);
470                 for (p = &filename[0];
471                      **buf != ',' && **buf != /* { */ '}' && **buf != ' ' &&
472                         **buf != '\t' && p < &filename[sizeof(filename)];
473                         *p++ = *(*buf)++)
474                         ;
475                 *p++ = '\0';
476                 if ((fp = fopen(filename, "r")) == NULL) {
477                         errmsg=strdup(GETMESSAGE(7,1, 
478                              "Unable to open the file '%s'; verify that it exists and is readable"));
479                         lsprintf(gbuf, errmsg, filename);
480                         fprintf(stderr, gbuf);
481                         free(errmsg);
482                         return(FAIL);
483                 }
484                 if (*len == 0) {
485                         if (getsize(fileno(fp), &size) == FAIL) {
486                                 errmsg=strdup(GETMESSAGE(7,2, 
487                                      "Unable to access the file '%s'; verify you have permission to access it"));
488                                 lsprintf(gbuf, errmsg, filename);
489                                 fprintf(stderr, gbuf);
490                                 free(errmsg);
491                                 return(FAIL);
492                         }
493                         *len = size/2 + 1;
494                         if ((*str = malloc(*len)) == NULL) {
495                                 return(FAIL);
496                         }
497                 }
498                 line = i = 0;
499                 while (fgets(gbuf, sizeof(gbuf), fp) != NULL) {
500                         line++;
501                         p = gbuf;
502                         /* eat any leading 0x */
503                         if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
504                                 p += 2;
505                         }
506                         for ( ; *p && *p != '\n'; ) {
507                                 if (i > *len - 1) {
508                                         fclose(fp);
509                                         return(FAIL);
510                                 }
511                                 if (!isxdigit(*p)) {
512                                         p++;
513                                         continue;
514                                 }
515                                 if (!isxdigit(p[1])) {
516                                         fclose(fp);
517                                         return(FAIL);
518                                 }
519                                 cbuf[0] = p[0];
520                                 cbuf[1] = p[1];
521                                 cbuf[2] = '\0';
522                                 str[0][i++] = (char)strtol(cbuf, (char **)NULL, 16);
523                                 p += 2;
524                                 xk_skipwhite(&p);
525                         }
526                 }
527                 *len = i;
528                 fclose(fp);
529                 return(SUCCESS);
530         } else if (!ispunct(**buf)) {
531                 getmode = CHAR_HEXSTR;
532                 if ((*buf)[0] == '0' && ((*buf)[1] == 'x' || (*buf)[1] == 'X'))
533                         (*buf) += 2;
534         } else {
535                 delim = *((*buf)++);
536                 getmode = CHAR_QUOTED;
537         }
538         if (*len == 0) {
539                 if ((*str = malloc(MALSIZ)) == NULL) {
540                         return(FAIL);
541                 }
542                 didmalloc = TRUE;
543                 *len = MALSIZ;
544         }
545         i = 0;
546         while ((*buf)[0] != '\0' && ((getmode == CHAR_QUOTED && (*buf)[0] != delim) ||
547                (getmode == CHAR_HEXSTR && (isxdigit((*buf)[0]))) ||
548                (getmode == CHAR_HEXSTR && (isspace((*buf)[0]))))) {
549                /* NOTE: must always leave 1 additional byte for a null
550                 * termination, because could be called by xk_par_nts!
551                 */
552                 if (i >= *len - 1) {
553                         if (didmalloc == FALSE) {
554                                 return(FAIL);
555                         } else {
556                                 if ((*str = realloc(*str, *len + MALSIZ)) == NULL) {
557                                         return(FAIL);
558                                 }
559                                 *len += MALSIZ;
560                         }
561                 }
562                 if (getmode == CHAR_QUOTED) {
563                         if ((*buf)[0] == '\\') {
564                                 (*buf)++;
565                                 switch ((*buf)[0]) {
566                                 case 't':
567                                         str[0][i++] = '\t';
568                                         (*buf)++;
569                                         break;
570                                 case 'v':
571                                         str[0][i++] = '\v';
572                                         (*buf)++;
573                                         break;
574                                 case 'f':
575                                         str[0][i++] = '\f';
576                                         (*buf)++;
577                                         break;
578                                 case 'n':
579                                         str[0][i++] = '\n';
580                                         (*buf)++;
581                                         break;
582                                 case 'r':
583                                         str[0][i++] = '\r';
584                                         (*buf)++;
585                                         break;
586                                 case 'b':
587                                         str[0][i++] = '\b';
588                                         (*buf)++;
589                                         break;
590                                 case '0':
591                                         str[0][i++] = (char)strtol(*buf, buf, 8);
592                                         break;
593                                 case 's':
594                                         (*buf)++;
595                                         break;
596                                 default:
597                                         str[0][i++] = *(*buf)++;
598                                 }
599                         } else
600                                 str[0][i++] = *(*buf)++;
601                 } else {
602                         if (!isxdigit((*buf)[1])) {
603                                 return(FAIL);
604                         }
605                         cbuf[0] = (*buf)[0];
606                         cbuf[1] = (*buf)[1];
607                         cbuf[2] = '\0';
608                         str[0][i++] = (char)strtol(cbuf, (char **)NULL, 16);
609                         (*buf) += 2;
610                         xk_skipwhite(buf);
611                 }
612         }
613         if (getmode == CHAR_QUOTED)
614                 (*buf)++;       /* eat the trailing quote */
615         /*
616          * NOTE: We leave a malloced buffer the same size rather
617          * than realloc()'ing it to be the exact size in order
618          * to save time and avoid malloc arena fragmentation
619          */
620         *len = i;
621         return(SUCCESS);
622 }
623
624 /* Case Ignoring String Functions. */
625
626 static int
627 xk_uppercase(
628         char *s )
629 {
630         while (*s) {
631                 if (islower(*s))
632                         *s = toupper(*s);
633                 s++;
634         }
635 }
636
637 int
638 xk_Strncmp(
639         char *s1,
640         char *s2,
641         int len )
642 {
643         int diff, i;
644
645         for (i=0; i < len && s1[i] != '\0' && s2[i] != '\0'; i++)
646                 if ((diff = tolower(s1[i]) - tolower(s2[i])) != 0)
647                         return (diff);
648         return(i == len ? 0 : s1[i] - s2[i]);
649 }
650
651 static int
652 getsize(
653         int fd,
654         int *psize )
655 {
656         struct stat stat;
657
658         if (fstat(fd, &stat) == FAIL)
659                 return(FAIL);
660         *psize = stat.st_size;
661         return(SUCCESS);
662 }