source: trunk/third/tcsh/ed.xmap.c @ 12039

Revision 12039, 19.0 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12038, which included commits to RCS files with non-trunk default branches.
Line 
1/* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/ed.xmap.c,v 1.1.1.2 1998-10-03 21:09:49 danw Exp $ */
2/*
3 * ed.xmap.c: This module contains the procedures for maintaining
4 *            the extended-key map.
5 *
6 *            An extended-key (Xkey) is a sequence of keystrokes
7 *            introduced with an sequence introducer and consisting
8 *            of an arbitrary number of characters.  This module maintains
9 *            a map (the Xmap) to convert these extended-key sequences
10 *            into input strings (XK_STR), editor functions (XK_CMD), or
11 *            unix commands (XK_EXE). It contains the
12 *            following externally visible functions.
13 *
14 *              int GetXkey(ch,val);
15 *              CStr *ch;
16 *              XmapVal *val;
17 *
18 *            Looks up *ch in map and then reads characters until a
19 *            complete match is found or a mismatch occurs. Returns the
20 *            type of the match found (XK_STR, XK_CMD, or XK_EXE).
21 *            Returns NULL in val.str and XK_STR for no match. 
22 *            The last character read is returned in *ch.
23 *
24 *              void AddXkey(Xkey, val, ntype);
25 *              CStr *Xkey;
26 *              XmapVal *val;
27 *              int ntype;
28 *
29 *            Adds Xkey to the Xmap and associates the value in val with it.
30 *            If Xkey is already is in Xmap, the new code is applied to the
31 *            existing Xkey. Ntype specifies if code is a command, an
32 *            out string or a unix command.
33 *
34 *              int DeleteXkey(Xkey);
35 *              CStr *Xkey;
36 *
37 *            Delete the Xkey and all longer Xkeys staring with Xkey, if
38 *            they exists.
39 *
40 *            Warning:
41 *              If Xkey is a substring of some other Xkeys, then the longer
42 *              Xkeys are lost!!  That is, if the Xkeys "abcd" and "abcef"
43 *              are in Xmap, adding the key "abc" will cause the first two
44 *              definitions to be lost.
45 *
46 *              void ResetXmap();
47 *
48 *            Removes all entries from Xmap and resets the defaults.
49 *
50 *              void PrintXkey(Xkey);
51 *              CStr *Xkey;
52 *
53 *            Prints all extended keys prefixed by Xkey and their associated
54 *            commands.
55 *
56 *            Restrictions:
57 *            -------------
58 *              1) It is not possible to have one Xkey that is a
59 *                 substring of another.
60 */
61/*-
62 * Copyright (c) 1980, 1991 The Regents of the University of California.
63 * All rights reserved.
64 *
65 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions
67 * are met:
68 * 1. Redistributions of source code must retain the above copyright
69 *    notice, this list of conditions and the following disclaimer.
70 * 2. Redistributions in binary form must reproduce the above copyright
71 *    notice, this list of conditions and the following disclaimer in the
72 *    documentation and/or other materials provided with the distribution.
73 * 3. All advertising materials mentioning features or use of this software
74 *    must display the following acknowledgement:
75 *      This product includes software developed by the University of
76 *      California, Berkeley and its contributors.
77 * 4. Neither the name of the University nor the names of its contributors
78 *    may be used to endorse or promote products derived from this software
79 *    without specific prior written permission.
80 *
81 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
82 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
84 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
85 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
86 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
87 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
88 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
89 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
90 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
91 * SUCH DAMAGE.
92 */
93#include "sh.h"
94
95RCSID("$Id: ed.xmap.c,v 1.1.1.2 1998-10-03 21:09:49 danw Exp $")
96
97#include "ed.h"
98#include "ed.defns.h"
99
100#ifndef NULL
101#define NULL 0
102#endif
103
104/* Internal Data types and declarations */
105
106/* The Nodes of the Xmap.  The Xmap is a linked list of these node
107 * elements
108 */
109typedef struct Xmapnode {
110    Char    ch;                 /* single character of Xkey */
111    int     type;
112    XmapVal val;                /* command code or pointer to string, if this
113                                 * is a leaf */
114    struct Xmapnode *next;      /* ptr to next char of this Xkey */
115    struct Xmapnode *sibling;   /* ptr to another Xkey with same prefix */
116} XmapNode;
117
118static XmapNode *Xmap = NULL;   /* the current Xmap */
119#define MAXXKEY 100             /* max length of a Xkey for print putposes */
120static Char printbuf[MAXXKEY];  /* buffer for printing */
121
122
123/* Some declarations of procedures */
124static  int       TraverseMap   __P((XmapNode *, CStr *, XmapVal *));
125static  int       TryNode       __P((XmapNode *, CStr *, XmapVal *, int));
126static  XmapNode *GetFreeNode   __P((CStr *));
127static  void      PutFreeNode   __P((XmapNode *));
128static  int       TryDeleteNode __P((XmapNode **, CStr *));
129static  int       Lookup        __P((CStr *, XmapNode *, int));
130static  int       Enumerate     __P((XmapNode *, int));
131static  int       unparsech     __P((int, Char *));
132
133
134XmapVal *
135XmapCmd(cmd)
136    int cmd;
137{
138    static XmapVal xm;
139    xm.cmd = (KEYCMD) cmd;
140    return &xm;
141}
142
143XmapVal *
144XmapStr(str)
145    CStr  *str;
146{
147    static XmapVal xm;
148    xm.str.len = str->len;
149    xm.str.buf = str->buf;
150    return &xm;
151}
152
153/* ResetXmap():
154 *      Takes all nodes on Xmap and puts them on free list.  Then
155 *      initializes Xmap with arrow keys
156 */
157void
158ResetXmap()
159{
160    PutFreeNode(Xmap);
161    Xmap = NULL;
162
163    DefaultArrowKeys();
164    return;
165}
166
167
168/* GetXkey():
169 *      Calls the recursive function with entry point Xmap
170 */
171int
172GetXkey(ch, val)
173    CStr     *ch;
174    XmapVal  *val;
175{
176    return (TraverseMap(Xmap, ch, val));
177}
178
179/* TraverseMap():
180 *      recursively traverses node in tree until match or mismatch is
181 *      found.  May read in more characters.
182 */
183static int
184TraverseMap(ptr, ch, val)
185    XmapNode *ptr;
186    CStr     *ch;
187    XmapVal  *val;
188{
189    Char    tch;
190
191    if (ptr->ch == *(ch->buf)) {
192        /* match found */
193        if (ptr->next) {
194            /* Xkey not complete so get next char */
195            if (GetNextChar(&tch) != 1) {       /* if EOF or error */
196                val->cmd = F_SEND_EOF;
197                return XK_CMD;/* PWP: Pretend we just read an end-of-file */
198            }
199            *(ch->buf) = tch;
200            return (TraverseMap(ptr->next, ch, val));
201        }
202        else {
203            *val = ptr->val;
204            if (ptr->type != XK_CMD)
205                *(ch->buf) = '\0';
206            return ptr->type;
207        }
208    }
209    else {
210        /* no match found here */
211        if (ptr->sibling) {
212            /* try next sibling */
213            return (TraverseMap(ptr->sibling, ch, val));
214        }
215        else {
216            /* no next sibling -- mismatch */
217            val->str.buf = NULL;
218            val->str.len = 0;
219            return XK_STR;
220        }
221    }
222}
223
224void
225AddXkey(Xkey, val, ntype)
226    CStr    *Xkey;
227    XmapVal *val;
228    int      ntype;
229{
230    CStr cs;
231    cs.buf = Xkey->buf;
232    cs.len = Xkey->len;
233    if (Xkey->len == 0) {
234        xprintf(CGETS(9, 1, "AddXkey: Null extended-key not allowed.\n"));
235        return;
236    }
237
238    if (ntype == XK_CMD && val->cmd == F_XKEY) {
239        xprintf(CGETS(9, 2, "AddXkey: sequence-lead-in command not allowed\n"));
240        return;
241    }
242
243    if (Xmap == NULL)
244        /* tree is initially empty.  Set up new node to match Xkey[0] */
245        Xmap = GetFreeNode(&cs);        /* it is properly initialized */
246
247    /* Now recurse through Xmap */
248    (void) TryNode(Xmap, &cs, val, ntype);     
249    return;
250}
251
252static int
253TryNode(ptr, str, val, ntype)
254    XmapNode *ptr;
255    CStr     *str;
256    XmapVal  *val;
257    int       ntype;
258{
259    /*
260     * Find a node that matches *string or allocate a new one
261     */
262    if (ptr->ch != *(str->buf)) {
263        XmapNode *xm;
264
265        for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
266            if (xm->sibling->ch == *(str->buf))
267                break;
268        if (xm->sibling == NULL)
269            xm->sibling = GetFreeNode(str);     /* setup new node */
270        ptr = xm->sibling;
271    }
272
273    str->buf++;
274    str->len--;
275    if (str->len == 0) {
276        /* we're there */
277        if (ptr->next != NULL) {
278            PutFreeNode(ptr->next);     /* lose longer Xkeys with this prefix */
279            ptr->next = NULL;
280        }
281
282        switch (ptr->type) {
283        case XK_STR:
284        case XK_EXE:
285            if (ptr->val.str.buf != NULL)
286                xfree((ptr_t) ptr->val.str.buf);
287            ptr->val.str.len = 0;
288            break;
289        case XK_NOD:
290        case XK_CMD:
291            break;
292        default:
293            abort();
294            break;
295        }
296
297        switch (ptr->type = ntype) {
298        case XK_CMD:
299            ptr->val = *val;
300            break;
301        case XK_STR:
302        case XK_EXE:
303            ptr->val.str.len = (val->str.len + 1) * sizeof(Char);
304            ptr->val.str.buf = (Char *) xmalloc((size_t) ptr->val.str.len);
305            (void) memmove((ptr_t) ptr->val.str.buf, (ptr_t) val->str.buf,
306                           (size_t) ptr->val.str.len);
307            ptr->val.str.len = val->str.len;
308            break;
309        default:
310            abort();
311            break;
312        }
313    }
314    else {
315        /* still more chars to go */
316        if (ptr->next == NULL)
317            ptr->next = GetFreeNode(str);       /* setup new node */
318        (void) TryNode(ptr->next, str, val, ntype);
319    }
320    return (0);
321}
322
323void
324ClearXkey(map, in)
325    KEYCMD *map;
326    CStr   *in;
327{
328    unsigned char c = (unsigned char) *(in->buf);
329    if ((map[c] == F_XKEY) &&
330        ((map == CcKeyMap && CcAltMap[c] != F_XKEY) ||
331         (map == CcAltMap && CcKeyMap[c] != F_XKEY)))
332        (void) DeleteXkey(in);
333}
334
335int
336DeleteXkey(Xkey)
337    CStr   *Xkey;
338{
339    if (Xkey->len == 0) {
340        xprintf(CGETS(9, 3, "DeleteXkey: Null extended-key not allowed.\n"));
341        return (-1);
342    }
343
344    if (Xmap == NULL)
345        return (0);
346
347    (void) TryDeleteNode(&Xmap, Xkey);
348    return (0);
349}
350
351static int
352TryDeleteNode(inptr, str)
353    XmapNode **inptr;
354    CStr   *str;
355{
356    XmapNode *ptr;
357    XmapNode *prev_ptr = NULL;
358
359    ptr = *inptr;
360    /*
361     * Find a node that matches *string or allocate a new one
362     */
363    if (ptr->ch != *(str->buf)) {
364        XmapNode *xm;
365
366        for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
367            if (xm->sibling->ch == *(str->buf))
368                break;
369        if (xm->sibling == NULL)
370            return (0);
371        prev_ptr = xm;
372        ptr = xm->sibling;
373    }
374
375    str->buf++;
376    str->len--;
377
378    if (str->len == 0) {
379        /* we're there */
380        if (prev_ptr == NULL)
381            *inptr = ptr->sibling;
382        else
383            prev_ptr->sibling = ptr->sibling;
384        ptr->sibling = NULL;
385        PutFreeNode(ptr);
386        return (1);
387    }
388    else if (ptr->next != NULL && TryDeleteNode(&ptr->next, str) == 1) {
389        if (ptr->next != NULL)
390            return (0);
391        if (prev_ptr == NULL)
392            *inptr = ptr->sibling;
393        else
394            prev_ptr->sibling = ptr->sibling;
395        ptr->sibling = NULL;
396        PutFreeNode(ptr);
397        return (1);
398    }
399    else {
400        return (0);
401    }
402}
403
404/* PutFreeNode():
405 *      Puts a tree of nodes onto free list using free(3).
406 */
407static void
408PutFreeNode(ptr)
409    XmapNode *ptr;
410{
411    if (ptr == NULL)
412        return;
413
414    if (ptr->next != NULL) {
415        PutFreeNode(ptr->next);
416        ptr->next = NULL;
417    }
418
419    PutFreeNode(ptr->sibling);
420
421    switch (ptr->type) {
422    case XK_CMD:
423    case XK_NOD:
424        break;
425    case XK_EXE:
426    case XK_STR:
427        if (ptr->val.str.buf != NULL)
428            xfree((ptr_t) ptr->val.str.buf);
429        break;
430    default:
431        abort();
432        break;
433    }
434    xfree((ptr_t) ptr);
435}
436
437
438/* GetFreeNode():
439 *      Returns pointer to an XmapNode for ch.
440 */
441static XmapNode *
442GetFreeNode(ch)
443    CStr *ch;
444{
445    XmapNode *ptr;
446
447    ptr = (XmapNode *) xmalloc((size_t) sizeof(XmapNode));
448    ptr->ch = ch->buf[0];
449    ptr->type = XK_NOD;
450    ptr->val.str.buf = NULL;
451    ptr->val.str.len = 0;
452    ptr->next = NULL;
453    ptr->sibling = NULL;
454    return (ptr);
455}
456 
457
458/* PrintXKey():
459 *      Print the binding associated with Xkey key.
460 *      Print entire Xmap if null
461 */
462void
463PrintXkey(key)
464    CStr   *key;
465{
466    CStr cs;
467
468    if (key) {
469        cs.buf = key->buf;
470        cs.len = key->len;
471    }
472    else {
473        cs.buf = STRNULL;
474        cs.len = 0;
475    }
476    /* do nothing if Xmap is empty and null key specified */
477    if (Xmap == NULL && cs.len == 0)
478        return;
479
480    printbuf[0] =  '"';
481    if (Lookup(&cs, Xmap, 1) <= -1)
482        /* key is not bound */
483        xprintf(CGETS(9, 4, "Unbound extended key \"%S\"\n"), cs.buf);
484    return;
485}
486
487/* Lookup():
488 *      look for the string starting at node ptr.
489 *      Print if last node
490 */
491static int
492Lookup(str, ptr, cnt)
493    CStr   *str;
494    XmapNode *ptr;
495    int     cnt;
496{
497    int     ncnt;
498
499    if (ptr == NULL)
500        return (-1);            /* cannot have null ptr */
501
502    if (str->len == 0) {
503        /* no more chars in string.  Enumerate from here. */
504        (void) Enumerate(ptr, cnt);
505        return (0);
506    }
507    else {
508        /* If match put this char into printbuf.  Recurse */
509        if (ptr->ch == *(str->buf)) {
510            /* match found */
511            ncnt = unparsech(cnt, &ptr->ch);
512            if (ptr->next != NULL) {
513                /* not yet at leaf */
514                CStr tstr;
515                tstr.buf = str->buf + 1;
516                tstr.len = str->len - 1;
517                return (Lookup(&tstr, ptr->next, ncnt + 1));
518            }
519            else {
520                /* next node is null so key should be complete */
521                if (str->len == 1) {
522                    CStr pb;
523                    printbuf[ncnt + 1] = '"';
524                    printbuf[ncnt + 2] = '\0';
525                    pb.buf = printbuf;
526                    pb.len = ncnt + 2;
527                    (void) printOne(&pb, &ptr->val, ptr->type);
528                    return (0);
529                }
530                else
531                    return (-1);/* mismatch -- string still has chars */
532            }
533        }
534        else {
535            /* no match found try sibling */
536            if (ptr->sibling)
537                return (Lookup(str, ptr->sibling, cnt));
538            else
539                return (-1);
540        }
541    }
542}
543
544static int
545Enumerate(ptr, cnt)
546    XmapNode *ptr;
547    int     cnt;
548{
549    int     ncnt;
550
551    if (cnt >= MAXXKEY - 5) {   /* buffer too small */
552        printbuf[++cnt] = '"';
553        printbuf[++cnt] = '\0';
554        xprintf(CGETS(9, 5,
555                "Some extended keys too long for internal print buffer"));
556        xprintf(" \"%S...\"\n", printbuf);
557        return (0);
558    }
559
560    if (ptr == NULL) {
561#ifdef DEBUG_EDIT
562        xprintf(CGETS(9, 6, "Enumerate: BUG!! Null ptr passed\n!"));
563#endif
564        return (-1);
565    }
566
567    ncnt = unparsech(cnt, &ptr->ch); /* put this char at end of string */
568    if (ptr->next == NULL) {
569        CStr pb;
570        /* print this Xkey and function */
571        printbuf[++ncnt] = '"';
572        printbuf[++ncnt] = '\0';
573        pb.buf = printbuf;
574        pb.len = ncnt;
575        (void) printOne(&pb, &ptr->val, ptr->type);
576    }
577    else
578        (void) Enumerate(ptr->next, ncnt + 1);
579
580    /* go to sibling if there is one */
581    if (ptr->sibling)
582        (void) Enumerate(ptr->sibling, cnt);
583    return (0);
584}
585
586
587/* PrintOne():
588 *      Print the specified key and its associated
589 *      function specified by val
590 */
591int
592printOne(key, val, ntype)
593    CStr    *key;
594    XmapVal *val;
595    int      ntype;
596{
597    struct KeyFuncs *fp;
598    unsigned char unparsbuf[200];
599    static char *fmt = "%s\n";
600
601    xprintf("%-15S-> ", key->buf);
602    if (val != NULL)
603        switch (ntype) {
604        case XK_STR:
605        case XK_EXE:
606            xprintf(fmt, unparsestring(&val->str, unparsbuf,
607                                       ntype == XK_STR ? STRQQ : STRBB));
608            break;
609        case XK_CMD:
610            for (fp = FuncNames; fp->name; fp++)
611                if (val->cmd == fp->func)
612                    xprintf(fmt, fp->name);
613                break;
614        default:
615            abort();
616            break;
617        }
618    else
619        xprintf(fmt, key, CGETS(9, 7, "no input"));
620    return (0);
621}
622
623static int
624unparsech(cnt, ch)
625    int   cnt;
626    Char  *ch;
627{
628    if (ch == 0) {
629        printbuf[cnt++] = '^';
630        printbuf[cnt] = '@';
631        return cnt;
632    }
633
634    if (Iscntrl(*ch)) {
635#ifndef _OSD_POSIX
636        printbuf[cnt++] = '^';
637        if (*ch == CTL_ESC('\177'))
638            printbuf[cnt] = '?';
639        else
640            printbuf[cnt] = *ch | 0100;
641#else /*_OSD_POSIX*/
642        if (*ch == CTL_ESC('\177'))
643        {
644                printbuf[cnt++] = '^';
645                printbuf[cnt] = '?';
646        }
647        else if (Isupper(_toebcdic[_toascii[*ch]|0100])
648                || strchr("@[\\]^_", _toebcdic[_toascii[*ch]|0100]) != NULL)
649        {
650                printbuf[cnt++] = '^';
651                printbuf[cnt] = _toebcdic[_toascii[*ch]|0100];
652        }
653        else
654        {
655                printbuf[cnt++] = '\\';
656                printbuf[cnt++] = ((*ch >> 6) & 7) + '0';
657                printbuf[cnt++] = ((*ch >> 3) & 7) + '0';
658                printbuf[cnt] = (*ch & 7) + '0';
659        }
660#endif /*_OSD_POSIX*/
661    }
662    else if (*ch == '^') {
663        printbuf[cnt++] = '\\';
664        printbuf[cnt] = '^';
665    }
666    else if (*ch == '\\') {
667        printbuf[cnt++] = '\\';
668        printbuf[cnt] = '\\';
669    }
670    else if (*ch == ' ' || (Isprint(*ch) && !Isspace(*ch))) {
671        printbuf[cnt] = *ch;
672    }
673    else {
674        printbuf[cnt++] = '\\';
675        printbuf[cnt++] = ((*ch >> 6) & 7) + '0';
676        printbuf[cnt++] = ((*ch >> 3) & 7) + '0';
677        printbuf[cnt] = (*ch & 7) + '0';
678    }
679    return cnt;
680}
681
682int
683parseescape(ptr)
684    const Char  **ptr;
685{
686    const Char *p;
687    Char c;
688
689    p = *ptr;
690
691    if ((p[1] & CHAR) == 0) {
692        xprintf(CGETS(9, 8, "Something must follow: %c\n"), *p);
693        return -1;
694    }
695    if ((*p & CHAR) == '\\') {
696        p++;
697        switch (*p & CHAR) {
698        case 'a':
699            c = CTL_ESC('\007');         /* Bell */
700            break;
701        case 'b':
702            c = CTL_ESC('\010');         /* Backspace */
703            break;
704        case 't':
705            c = CTL_ESC('\011');         /* Horizontal Tab */
706            break;
707        case 'n':
708            c = CTL_ESC('\012');         /* New Line */
709            break;
710        case 'v':
711            c = CTL_ESC('\013');         /* Vertical Tab */
712            break;
713        case 'f':
714            c = CTL_ESC('\014');         /* Form Feed */
715            break;
716        case 'r':
717            c = CTL_ESC('\015');         /* Carriage Return */
718            break;
719        case 'e':
720            c = CTL_ESC('\033');         /* Escape */
721            break;
722        case '0':
723        case '1':
724        case '2':
725        case '3':
726        case '4':
727        case '5':
728        case '6':
729        case '7':
730            {
731                register int cnt, val, ch;
732
733                for (cnt = 0, val = 0; cnt < 3; cnt++) {
734                    ch = *p++ & CHAR;
735                    if (ch < '0' || ch > '7') {
736                        p--;
737                        break;
738                    }
739                    val = (val << 3) | (ch - '0');
740                }
741                if ((val & 0xffffff00) != 0) {
742                    xprintf(CGETS(9, 9,
743                            "Octal constant does not fit in a char.\n"));
744                    return 0;
745                }
746#ifdef _OSD_POSIX
747                if (CTL_ESC(val) != val && adrof(STRwarnebcdic))
748                    xprintf(/*CGETS(9, 9, no NLS-String yet!*/
749                            "Warning: Octal constant \\%3.3o is interpreted as EBCDIC value.\n", val/*)*/);
750#endif
751                c = (Char) val;
752                --p;
753            }
754            break;
755        default:
756            c = *p;
757            break;
758        }
759    }
760    else if ((*p & CHAR) == '^' && (Isalpha(p[1] & CHAR) ||
761                                    strchr("@^_?\\|[{]}", p[1] & CHAR))) {
762        p++;
763#ifndef _OSD_POSIX
764        c = ((*p & CHAR) == '?') ? CTL_ESC('\177') : ((*p & CHAR) & 0237);
765#else /*_OSD_POSIX*/
766        c = ((*p & CHAR) == '?') ? CTL_ESC('\177') : _toebcdic[_toascii[*p & CHAR] & 0237];
767        if (adrof(STRwarnebcdic))
768            xprintf(/*CGETS(9, 9, no NLS-String yet!*/
769                "Warning: Control character ^%c may be interpreted differently in EBCDIC.\n", *p & CHAR /*)*/);
770#endif /*_OSD_POSIX*/
771    }
772    else
773        c = *p;
774    *ptr = p;
775    return (c);
776}
777
778
779unsigned char *
780unparsestring(str, buf, sep)
781    CStr   *str;
782    unsigned char *buf;
783    Char   *sep;
784{
785    unsigned char *b;
786    Char   p;
787    int l;
788
789    b = buf;
790    if (sep[0])
791#ifndef WINNT
792        *b++ = sep[0];
793#else /* WINNT */
794        *b++ = CHAR & sep[0];
795#endif /* !WINNT */
796
797    for (l = 0; l < str->len; l++) {
798        p = str->buf[l];
799        if (Iscntrl(p)) {
800#ifndef _OSD_POSIX
801            *b++ = '^';
802            if (p == CTL_ESC('\177'))
803                *b++ = '?';
804            else
805                *b++ = (unsigned char) (p | 0100);
806#else /*_OSD_POSIX*/
807            if (_toascii[p] == '\177' || Isupper(_toebcdic[_toascii[p]|0100])
808                 || strchr("@[\\]^_", _toebcdic[_toascii[p]|0100]) != NULL)
809            {
810                *b++ = '^';
811                *b++ = (_toascii[p] == '\177') ? '?' : _toebcdic[_toascii[p]|0100];
812            }
813            else
814            {
815                *b++ = '\\';
816                *b++ = ((p >> 6) & 7) + '0';
817                *b++ = ((p >> 3) & 7) + '0';
818                *b++ = (p & 7) + '0';
819            }
820#endif /*_OSD_POSIX*/
821        }
822        else if (p == '^' || p == '\\') {
823            *b++ = '\\';
824            *b++ = (unsigned char) p;
825        }
826        else if (p == ' ' || (Isprint(p) && !Isspace(p))) {
827            *b++ = (unsigned char) p;
828        }
829        else {
830            *b++ = '\\';
831            *b++ = ((p >> 6) & 7) + '0';
832            *b++ = ((p >> 3) & 7) + '0';
833            *b++ = (p & 7) + '0';
834        }
835    }
836    if (sep[0] && sep[1])
837#ifndef WINNT
838        *b++ = sep[1];
839#else /* WINNT */
840        *b++ = CHAR & sep[1];
841#endif /* !WINNT */
842    *b++ = 0;
843    return buf;                 /* should check for overflow */
844}
Note: See TracBrowser for help on using the repository browser.