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