key.cxx

Go to the documentation of this file.
00001 // @(#)root/editline:$Id: key.cxx 30194 2009-09-16 12:19:46Z axel $
00002 // Author: Mary-Louise Gill, 2009
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 /*      $NetBSD: key.c,v 1.12 2001/05/17 01:02:17 christos Exp $        */
00013 
00014 /*-
00015  * Copyright (c) 1992, 1993
00016  *      The Regents of the University of California.  All rights reserved.
00017  *
00018  * This code is derived from software contributed to Berkeley by
00019  * Christos Zoulas of Cornell University.
00020  *
00021  * Redistribution and use in source and binary forms, with or without
00022  * modification, are permitted provided that the following conditions
00023  * are met:
00024  * 1. Redistributions of source code must retain the above copyright
00025  *    notice, this list of conditions and the following disclaimer.
00026  * 2. Redistributions in binary form must reproduce the above copyright
00027  *    notice, this list of conditions and the following disclaimer in the
00028  *    documentation and/or other materials provided with the distribution.
00029  * 3. Neither the name of the University nor the names of its contributors
00030  *    may be used to endorse or promote products derived from this software
00031  *    without specific prior written permission.
00032  *
00033  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00034  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00035  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00036  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00037  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00038  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00039  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00040  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00041  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00042  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00043  * SUCH DAMAGE.
00044  */
00045 
00046 #include "compat.h"
00047 
00048 /*
00049  * key.c: This module contains the procedures for maintaining
00050  *        the extended-key map.
00051  *
00052  *      An extended-key (key) is a sequence of keystrokes introduced
00053  *      with an sequence introducer and consisting of an arbitrary
00054  *      number of characters.  This module maintains a map (the el->fKey.fMap)
00055  *      to convert these extended-key sequences into input strs
00056  *      (XK_STR), editor functions (XK_CMD), or unix commands (XK_EXE).
00057  *
00058  *      Warning:
00059  *        If key is a substr of some other keys, then the longer
00060  *        keys are lost!!  That is, if the keys "abcd" and "abcef"
00061  *        are in el->fKey.fMap, adding the key "abc" will cause the first two
00062  *        definitions to be lost.
00063  *
00064  *      Restrictions:
00065  *      -------------
00066  *      1) It is not possible to have one key that is a
00067  *         substr of another.
00068  */
00069 #include "sys.h"
00070 #include <string.h>
00071 #include <stdlib.h>
00072 
00073 #include "el.h"
00074 
00075 /*
00076  * The Nodes of the el->fKey.fMap.  The el->fKey.fMap is a linked list
00077  * of these node elements
00078  */
00079 struct KeyNode_t {
00080    char fCh;                             /* single character of key       */
00081    int fType;                            /* node type                    */
00082    KeyValue_t fVal;                     /* command code or pointer to str,  */
00083                                         /* if this is a leaf             */
00084    struct KeyNode_t* fNext;             /* ptr to next char of this key  */
00085    struct KeyNode_t* fSibling;          /* ptr to another key with same prefix*/
00086 };
00087 
00088 el_private int node_trav(EditLine_t*, KeyNode_t*, char*,
00089                          KeyValue_t*);
00090 el_private int node__try(EditLine_t*, KeyNode_t*, const char*,
00091                          KeyValue_t*, int);
00092 el_private KeyNode_t* node__get(int);
00093 el_private void node__put(EditLine_t*, KeyNode_t*);
00094 el_private int node__delete(EditLine_t*, KeyNode_t**, char*);
00095 el_private int node_lookup(EditLine_t*, const char*, KeyNode_t*, int);
00096 el_private int node_enum(EditLine_t*, KeyNode_t*, int);
00097 el_private int key__decode_char(char*, int, int);
00098 
00099 #define KEY_BUFSIZ EL_BUFSIZ
00100 
00101 
00102 /* key_init():
00103  *      Initialize the key maps
00104  */
00105 el_protected int
00106 key_init(EditLine_t* el) {
00107    el->fKey.fBuf = (char*) el_malloc(KEY_BUFSIZ);
00108 
00109    if (el->fKey.fBuf == NULL) {
00110       return -1;
00111    }
00112    el->fKey.fMap = NULL;
00113    key_reset(el);
00114    return 0;
00115 }
00116 
00117 
00118 /* key_end():
00119  *      Free the key maps
00120  */
00121 el_protected void
00122 key_end(EditLine_t* el) {
00123    el_free((ptr_t) el->fKey.fBuf);
00124    el->fKey.fBuf = NULL;
00125    /* XXX: provide a function to clear the keys */
00126    el->fKey.fMap = NULL;
00127 }
00128 
00129 
00130 /* key_map_cmd():
00131  *      Associate cmd with a key value
00132  */
00133 el_protected KeyValue_t*
00134 key_map_cmd(EditLine_t* el, int cmd) {
00135    el->fKey.fVal.fCmd = (ElAction_t) cmd;
00136    return &el->fKey.fVal;
00137 }
00138 
00139 
00140 /* key_map_str():
00141  *      Associate str with a key value
00142  */
00143 el_protected KeyValue_t*
00144 key_map_str(EditLine_t* el, char* str) {
00145    el->fKey.fVal.fStr = str;
00146    return &el->fKey.fVal;
00147 }
00148 
00149 
00150 /* key_reset():
00151  *      Takes all nodes on el->fKey.fMap and puts them on free list.  Then
00152  *      initializes el->fKey.fMap with arrow keys
00153  *      [Always bind the ansi arrow keys?]
00154  */
00155 el_protected void
00156 key_reset(EditLine_t* el) {
00157    node__put(el, el->fKey.fMap);
00158    el->fKey.fMap = NULL;
00159    return;
00160 }
00161 
00162 
00163 /* key_get():
00164  *      Calls the recursive function with entry point el->fKey.fMap
00165  *      Looks up *ch in map and then reads characters until a
00166  *      complete match is found or a mismatch occurs. Returns the
00167  *      type of the match found (XK_STR, XK_CMD, or XK_EXE).
00168  *      Returns NULL in val.fStr and XK_STR for no match.
00169  *      The last character read is returned in *ch.
00170  */
00171 el_protected int
00172 key_get(EditLine_t* el, char* ch, KeyValue_t* val) {
00173    return node_trav(el, el->fKey.fMap, ch, val);
00174 }
00175 
00176 
00177 /* key_add():
00178  *      Adds key to the el->fKey.fMap and associates the value in val with it.
00179  *      If key is already is in el->fKey.fMap, the new code is applied to the
00180  *      existing key. Ntype specifies if code is a command, an
00181  *      out str or a unix command.
00182  */
00183 el_protected void
00184 key_add(EditLine_t* el, const char* key, KeyValue_t* val, int ntype) {
00185    if (key[0] == '\0') {
00186       (void) fprintf(el->fErrFile,
00187                      "key_add: Null extended-key not allowed.\n");
00188       return;
00189    }
00190 
00191    if (ntype == XK_CMD && val->fCmd == ED_SEQUENCE_LEAD_IN) {
00192       (void) fprintf(el->fErrFile,
00193                      "key_add: sequence-lead-in command not allowed\n");
00194       return;
00195    }
00196 
00197    if (el->fKey.fMap == NULL) {
00198       /* tree is initially empty.  Set up new node to match key[0] */
00199       el->fKey.fMap = node__get(key[0]);
00200    }
00201    /* it is properly initialized */
00202 
00203    /* Now recurse through el->fKey.fMap */
00204    (void) node__try(el, el->fKey.fMap, key, val, ntype);
00205    return;
00206 } // key_add
00207 
00208 
00209 /* key_clear():
00210  *
00211  */
00212 el_protected void
00213 key_clear(EditLine_t* el, ElAction_t* map, char* in) {
00214    if ((map[(unsigned char) *in] == ED_SEQUENCE_LEAD_IN) &&
00215        ((map == el->fMap.fKey &&
00216          el->fMap.fAlt[(unsigned char) *in] != ED_SEQUENCE_LEAD_IN) ||
00217         (map == el->fMap.fAlt &&
00218               el->fMap.fKey[(unsigned char) *in] != ED_SEQUENCE_LEAD_IN))) {
00219       (void) key_delete(el, in);
00220    }
00221 }
00222 
00223 
00224 /* key_delete():
00225  *      Delete the key and all longer keys staring with key, if
00226  *      they exists.
00227  */
00228 el_protected int
00229 key_delete(EditLine_t* el, char* key) {
00230    if (key[0] == '\0') {
00231       (void) fprintf(el->fErrFile,
00232                      "key_delete: Null extended-key not allowed.\n");
00233       return -1;
00234    }
00235 
00236    if (el->fKey.fMap == NULL) {
00237       return 0;
00238    }
00239 
00240    (void) node__delete(el, &el->fKey.fMap, key);
00241    return 0;
00242 }
00243 
00244 
00245 /* key_print():
00246  *      Print the binding associated with key key.
00247  *      Print entire el->fKey.fMap if null
00248  */
00249 el_protected void
00250 key_print(EditLine_t* el, const char* key) {
00251    /* do nothing if el->fKey.fMap is empty and null key specified */
00252    if (el->fKey.fMap == NULL && *key == 0) {
00253       return;
00254    }
00255 
00256    el->fKey.fBuf[0] = '"';
00257 
00258    if (node_lookup(el, key, el->fKey.fMap, 1) <= -1) {
00259       /* key is not bound */
00260       (void) fprintf(el->fErrFile, "Unbound extended key \"%s\"\n",
00261                      key);
00262    }
00263    return;
00264 }
00265 
00266 
00267 /* node_trav():
00268  *      recursively traverses node in tree until match or mismatch is
00269  *      found.  May read in more characters.
00270  */
00271 el_private int
00272 node_trav(EditLine_t* el, KeyNode_t* ptr, char* ch, KeyValue_t* val) {
00273    if (ptr->fCh == *ch) {
00274       /* match found */
00275       if (ptr->fNext) {
00276          /* key not complete so get next char */
00277          if (el_getc(el, ch) != 1) {                    /* if EOF or error */
00278             val->fCmd = ED_END_OF_FILE;
00279             return XK_CMD;
00280             /* PWP: Pretend we just read an end-of-file */
00281          }
00282          return node_trav(el, ptr->fNext, ch, val);
00283       } else {
00284          *val = ptr->fVal;
00285 
00286          if (ptr->fType != XK_CMD) {
00287             *ch = '\0';
00288          }
00289          return ptr->fType;
00290       }
00291    } else {
00292       /* no match found here */
00293       if (ptr->fSibling) {
00294          /* try next sibling */
00295          return node_trav(el, ptr->fSibling, ch, val);
00296       } else {
00297          /* no next sibling -- mismatch */
00298          val->fStr = NULL;
00299          return XK_STR;
00300       }
00301    }
00302 } // node_trav
00303 
00304 
00305 /* node__try():
00306  *      Find a node that matches *str or allocate a new one
00307  */
00308 el_private int
00309 node__try(EditLine_t* el, KeyNode_t* ptr, const char* str, KeyValue_t* val, int ntype) {
00310    if (ptr->fCh != *str) {
00311       KeyNode_t* xm;
00312 
00313       for (xm = ptr; xm->fSibling != NULL; xm = xm->fSibling) {
00314          if (xm->fSibling->fCh == *str) {
00315             break;
00316          }
00317       }
00318 
00319       if (xm->fSibling == NULL) {
00320          xm->fSibling = node__get(*str);                 /* setup new node */
00321       }
00322       ptr = xm->fSibling;
00323    }
00324 
00325    if (*++str == '\0') {
00326       /* we're there */
00327       if (ptr->fNext != NULL) {
00328          node__put(el, ptr->fNext);
00329          /* lose longer keys with this prefix */
00330          ptr->fNext = NULL;
00331       }
00332 
00333       switch (ptr->fType) {
00334       case XK_CMD:
00335       case XK_NOD:
00336          break;
00337       case XK_STR:
00338       case XK_EXE:
00339 
00340          if (ptr->fVal.fStr) {
00341             el_free((ptr_t) ptr->fVal.fStr);
00342          }
00343          break;
00344       default:
00345          EL_ABORT((el->fErrFile, "Bad XK_ type %d\n",
00346                    ptr->fType));
00347          break;
00348       }
00349 
00350       switch (ptr->fType = ntype) {
00351       case XK_CMD:
00352          ptr->fVal = *val;
00353          break;
00354       case XK_STR:
00355       case XK_EXE:
00356          ptr->fVal.fStr = strdup(val->fStr);
00357          break;
00358       default:
00359          EL_ABORT((el->fErrFile, "Bad XK_ type %d\n", ntype));
00360          break;
00361       }
00362    } else {
00363       /* still more chars to go */
00364       if (ptr->fNext == NULL) {
00365          ptr->fNext = node__get(*str);                   /* setup new node */
00366       }
00367       (void) node__try(el, ptr->fNext, str, val, ntype);
00368    }
00369    return 0;
00370 } // node__try
00371 
00372 
00373 /* node__delete():
00374  *      Delete node that matches str
00375  */
00376 el_private int
00377 node__delete(EditLine_t* el, KeyNode_t** inptr, char* str) {
00378    KeyNode_t* ptr;
00379    KeyNode_t* prev_ptr = NULL;
00380 
00381    ptr = *inptr;
00382 
00383    if (ptr->fCh != *str) {
00384       KeyNode_t* xm;
00385 
00386       for (xm = ptr; xm->fSibling != NULL; xm = xm->fSibling) {
00387          if (xm->fSibling->fCh == *str) {
00388             break;
00389          }
00390       }
00391 
00392       if (xm->fSibling == NULL) {
00393          return 0;
00394       }
00395       prev_ptr = xm;
00396       ptr = xm->fSibling;
00397    }
00398 
00399    if (*++str == '\0') {
00400       /* we're there */
00401       if (prev_ptr == NULL) {
00402          *inptr = ptr->fSibling;
00403       } else {
00404          prev_ptr->fSibling = ptr->fSibling;
00405       }
00406       ptr->fSibling = NULL;
00407       node__put(el, ptr);
00408       return 1;
00409    } else if (ptr->fNext != NULL &&
00410               node__delete(el, &ptr->fNext, str) == 1) {
00411       if (ptr->fNext != NULL) {
00412          return 0;
00413       }
00414 
00415       if (prev_ptr == NULL) {
00416          *inptr = ptr->fSibling;
00417       } else {
00418          prev_ptr->fSibling = ptr->fSibling;
00419       }
00420       ptr->fSibling = NULL;
00421       node__put(el, ptr);
00422       return 1;
00423    } else {
00424       return 0;
00425    }
00426 } // node__delete
00427 
00428 
00429 /* node__put():
00430  *      Puts a tree of nodes onto free list using free(3).
00431  */
00432 el_private void
00433 node__put(EditLine_t* el, KeyNode_t* ptr) {
00434    if (ptr == NULL) {
00435       return;
00436    }
00437 
00438    if (ptr->fNext != NULL) {
00439       node__put(el, ptr->fNext);
00440       ptr->fNext = NULL;
00441    }
00442    node__put(el, ptr->fSibling);
00443 
00444    switch (ptr->fType) {
00445    case XK_CMD:
00446    case XK_NOD:
00447       break;
00448    case XK_EXE:
00449    case XK_STR:
00450 
00451       if (ptr->fVal.fStr != NULL) {
00452          el_free((ptr_t) ptr->fVal.fStr);
00453       }
00454       break;
00455    default:
00456       EL_ABORT((el->fErrFile, "Bad XK_ type %d\n", ptr->fType));
00457       break;
00458    }
00459    el_free((ptr_t) ptr);
00460 } // node__put
00461 
00462 
00463 /* node__get():
00464  *      Returns pointer to an KeyNode_t for ch.
00465  */
00466 el_private KeyNode_t*
00467 node__get(int ch) {
00468    KeyNode_t* ptr;
00469 
00470    ptr = (KeyNode_t*) el_malloc((size_t) sizeof(KeyNode_t));
00471 
00472    if (ptr == NULL) {
00473       return NULL;
00474    }
00475    ptr->fCh = ch;
00476    ptr->fType = XK_NOD;
00477    ptr->fVal.fStr = NULL;
00478    ptr->fNext = NULL;
00479    ptr->fSibling = NULL;
00480    return ptr;
00481 }
00482 
00483 
00484 /* node_lookup():
00485  *      look for the str starting at node ptr.
00486  *      Print if last node
00487  */
00488 el_private int
00489 node_lookup(EditLine_t* el, const char* str, KeyNode_t* ptr, int cnt) {
00490    int ncnt;
00491 
00492    if (ptr == NULL) {
00493       return -1;                /* cannot have null ptr */
00494 
00495    }
00496 
00497    if (*str == 0) {
00498       /* no more chars in str.  node_enum from here. */
00499       (void) node_enum(el, ptr, cnt);
00500       return 0;
00501    } else {
00502       /* If match put this char into el->fKey.fBuf.  Recurse */
00503       if (ptr->fCh == *str) {
00504          /* match found */
00505          ncnt = key__decode_char(el->fKey.fBuf, cnt,
00506                                  (unsigned char) ptr->fCh);
00507 
00508          if (ptr->fNext != NULL) {
00509             /* not yet at leaf */
00510             return node_lookup(el, str + 1, ptr->fNext,
00511                                ncnt + 1);
00512          } else {
00513             /* next node is null so key should be complete */
00514             if (str[1] == 0) {
00515                el->fKey.fBuf[ncnt + 1] = '"';
00516                el->fKey.fBuf[ncnt + 2] = '\0';
00517                key_kprint(el, el->fKey.fBuf,
00518                           &ptr->fVal, ptr->fType);
00519                return 0;
00520             } else {
00521                return -1;
00522             }
00523             /* mismatch -- str still has chars */
00524          }
00525       } else {
00526          /* no match found try sibling */
00527          if (ptr->fSibling) {
00528             return node_lookup(el, str, ptr->fSibling,
00529                                cnt);
00530          } else {
00531             return -1;
00532          }
00533       }
00534    }
00535 } // node_lookup
00536 
00537 
00538 /* node_enum():
00539  *      Traverse the node printing the characters it is bound in buffer
00540  */
00541 el_private int
00542 node_enum(EditLine_t* el, KeyNode_t* ptr, int cnt) {
00543    int ncnt;
00544 
00545    if (cnt >= KEY_BUFSIZ - 5) {         /* buffer too small */
00546       el->fKey.fBuf[++cnt] = '"';
00547       el->fKey.fBuf[++cnt] = '\0';
00548       (void) fprintf(el->fErrFile,
00549                      "Some extended keys too long for internal print buffer");
00550       (void) fprintf(el->fErrFile, " \"%s...\"\n", el->fKey.fBuf);
00551       return 0;
00552    }
00553 
00554    if (ptr == NULL) {
00555 #ifdef DEBUG_EDIT
00556          (void) fprintf(el->fErrFile,
00557                         "node_enum: BUG!! Null ptr passed\n!");
00558 #endif
00559       return -1;
00560    }
00561    /* put this char at end of str */
00562    ncnt = key__decode_char(el->fKey.fBuf, cnt, (unsigned char) ptr->fCh);
00563 
00564    if (ptr->fNext == NULL) {
00565       /* print this key and function */
00566       el->fKey.fBuf[ncnt + 1] = '"';
00567       el->fKey.fBuf[ncnt + 2] = '\0';
00568       key_kprint(el, el->fKey.fBuf, &ptr->fVal, ptr->fType);
00569    } else {
00570       (void) node_enum(el, ptr->fNext, ncnt + 1);
00571    }
00572 
00573    /* go to sibling if there is one */
00574    if (ptr->fSibling) {
00575       (void) node_enum(el, ptr->fSibling, cnt);
00576    }
00577    return 0;
00578 } // node_enum
00579 
00580 
00581 /* key_kprint():
00582  *      Print the specified key and its associated
00583  *      function specified by val
00584  */
00585 el_protected void
00586 key_kprint(EditLine_t* el, const char* key, KeyValue_t* val, int ntype) {
00587    ElBindings_t* fp;
00588    char unparsbuf[EL_BUFSIZ];
00589    static const char fmt[] = "%-15s->  %s\n";
00590 
00591    if (val != NULL) {
00592       switch (ntype) {
00593       case XK_STR:
00594       case XK_EXE:
00595          (void) fprintf(el->fOutFile, fmt, key,
00596                         key__decode_str(val->fStr, unparsbuf,
00597                                         ntype == XK_STR ? "\"\"" : "[]"));
00598          break;
00599       case XK_CMD:
00600 
00601          for (fp = el->fMap.fHelp; fp->fName; fp++) {
00602             if (val->fCmd == fp->fFunc) {
00603                (void) fprintf(el->fOutFile, fmt,
00604                               key, fp->fName);
00605                break;
00606             }
00607          }
00608 #ifdef DEBUG_KEY
00609 
00610          if (fp->fName == NULL) {
00611             (void) fprintf(el->fOutFile,
00612                            "BUG! Command not found.\n");
00613          }
00614 #endif
00615 
00616          break;
00617       default:
00618          EL_ABORT((el->fErrFile, "Bad XK_ type %d\n", ntype));
00619          break;
00620       } // switch
00621    } else {
00622       (void) fprintf(el->fOutFile, fmt, key, "no input");
00623    }
00624 } // key_kprint
00625 
00626 
00627 /* key__decode_char():
00628  *      Put a printable form of char in buf.
00629  */
00630 el_private int
00631 key__decode_char(char* buf, int cnt, int ch) {
00632    if (ch == 0) {
00633       buf[cnt++] = '^';
00634       buf[cnt] = '@';
00635       return cnt;
00636    }
00637 
00638    if (iscntrl(ch)) {
00639       buf[cnt++] = '^';
00640 
00641       if (ch == '\177') {
00642          buf[cnt] = '?';
00643       } else {
00644          buf[cnt] = ch | 0100;
00645       }
00646    } else if (ch == '^') {
00647       buf[cnt++] = '\\';
00648       buf[cnt] = '^';
00649    } else if (ch == '\\') {
00650       buf[cnt++] = '\\';
00651       buf[cnt] = '\\';
00652    } else if (ch == ' ' || (isprint(ch) && !isspace(ch))) {
00653       buf[cnt] = ch;
00654    } else {
00655       buf[cnt++] = '\\';
00656       buf[cnt++] = (((unsigned int) ch >> 6) & 7) + '0';
00657       buf[cnt++] = (((unsigned int) ch >> 3) & 7) + '0';
00658       buf[cnt] = (ch & 7) + '0';
00659    }
00660    return cnt;
00661 } // key__decode_char
00662 
00663 
00664 /* key__decode_str():
00665  *      Make a printable version of the ey
00666  */
00667 el_protected char*
00668 key__decode_str(char* str, char* buf, const char* sep) {
00669    char* b, * p;
00670 
00671    b = buf;
00672 
00673    if (sep[0] != '\0') {
00674       *b++ = sep[0];
00675    }
00676 
00677    if (*str == 0) {
00678       *b++ = '^';
00679       *b++ = '@';
00680 
00681       if (sep[0] != '\0' && sep[1] != '\0') {
00682          *b++ = sep[1];
00683       }
00684       *b++ = 0;
00685       return buf;
00686    }
00687 
00688    for (p = str; *p != 0; p++) {
00689       if (iscntrl((unsigned char) *p)) {
00690          *b++ = '^';
00691 
00692          if (*p == '\177') {
00693             *b++ = '?';
00694          } else {
00695             *b++ = *p | 0100;
00696          }
00697       } else if (*p == '^' || *p == '\\') {
00698          *b++ = '\\';
00699          *b++ = *p;
00700       } else if (*p == ' ' || (isprint((unsigned char) *p) &&
00701                                !isspace((unsigned char) *p))) {
00702          *b++ = *p;
00703       } else {
00704          *b++ = '\\';
00705          *b++ = (((unsigned int) *p >> 6) & 7) + '0';
00706          *b++ = (((unsigned int) *p >> 3) & 7) + '0';
00707          *b++ = (*p & 7) + '0';
00708       }
00709    }
00710 
00711    if (sep[0] != '\0' && sep[1] != '\0') {
00712       *b++ = sep[1];
00713    }
00714    *b++ = 0;
00715    return buf;                  /* should check for overflow */
00716 } // key__decode_str

Generated on Tue Jul 5 14:11:38 2011 for ROOT_528-00b_version by  doxygen 1.5.1