Use calloc, rather than malloc/memset
[openafs.git] / src / gtx / keymap.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14
15 #include "gtxkeymap.h"
16
17 struct keymap_map *
18 keymap_Create(void)
19 {
20     return calloc(1, sizeof(struct keymap_map));
21 }
22
23 /* make a copy of a string; generic utility */
24 char *
25 gtx_CopyString(char *aval)
26 {
27     if (!aval)
28         return NULL;            /* propagate null strings around */
29     return strdup(aval);
30 }
31
32 static int
33 BindIt(struct keymap_map *amap, int aslot, int atype, void *aproc, char *aname, void *arock)
34 {
35     char *tp;
36     struct keymap_entry *tentry;
37
38     if (aslot < 0 || aslot >= KEYMAP_NENTRIES)
39         return -1;
40     tentry = &amap->entries[aslot];
41     tentry->type = atype;
42     if ((tp = tentry->name))
43         free(tp);
44     if (atype == KEYMAP_EMPTY) {
45         tentry->u.generic = NULL;
46         tentry->name = NULL;
47     } else {
48         tentry->name = gtx_CopyString(aname);
49         tentry->u.generic = aproc;
50     }
51     tentry->rock = arock;
52     return 0;
53 }
54
55 int
56 keymap_BindToString(struct keymap_map *amap, char *astring,
57                     int (*aproc)(void *, void *),
58                     char *aname, void *arock)
59 {
60     char *cptr;
61     int tc;
62     afs_int32 code;
63     struct keymap_map *tmap;
64
65     cptr = astring;
66     /* walk down string, building submaps if possible, until we get to function
67      * at the end */
68     while ((tc = *cptr++)) {
69         /* see if we should do submap or final function */
70         if (*cptr == 0) {       /* we're peeking: already skipped command char */
71             /* last character, do final function */
72             if (!aproc)         /* delete the entry */
73                 code = BindIt(amap, tc, KEYMAP_EMPTY, NULL, NULL, NULL);
74             else
75                 code =
76                     BindIt(amap, tc, KEYMAP_PROC, aproc, aname, arock);
77             if (code)
78                 return code;
79         } else {
80             /* more characters after this; do submap */
81             if (amap->entries[tc].type != KEYMAP_SUBMAP) {
82                 tmap = keymap_Create();
83                 code =
84                     BindIt(amap, tc, KEYMAP_SUBMAP, tmap, NULL, NULL);
85             } else {
86                 tmap = amap->entries[tc].u.submap;
87                 code = 0;
88             }
89             if (code)
90                 return code;
91             amap = tmap;        /* continue processing this map */
92         }
93     }                           /* while loop */
94     /* here when all characters are gone */
95     return 0;
96 }
97
98 /* delete a keymap and all of its recursively-included maps */
99 int
100 keymap_Delete(struct keymap_map *amap)
101 {
102     int i;
103     struct keymap_entry *tentry;
104
105     for (i = 0; i < KEYMAP_NENTRIES; i++) {
106         tentry = &amap->entries[i];
107         if (tentry->name)
108             free(tentry->name);
109         if (tentry->type == KEYMAP_SUBMAP)
110             keymap_Delete(tentry->u.submap);
111     }
112     free(amap);
113     return 0;
114 }
115
116 int
117 keymap_InitState(struct keymap_state *astate, struct keymap_map *amap)
118 {
119     memset(astate, 0, sizeof(*astate));
120     astate->initMap = amap;
121     astate->currentMap = amap;
122     return 0;
123 }
124
125 int
126 keymap_ProcessKey(struct keymap_state *astate, int akey, void *arock)
127 {
128     struct keymap_entry *tentry;
129     afs_int32 code;
130
131     if (akey < 0 || akey >= KEYMAP_NENTRIES)
132         return -1;
133     tentry = &astate->currentMap->entries[akey];
134     code = 0;
135     switch (tentry->type) {
136     case KEYMAP_EMPTY:
137         keymap_ResetState(astate);
138         return -1;
139         /* break; */
140         /* break commented out because of return above causing compiler warnings */
141
142     case KEYMAP_SUBMAP:
143         astate->currentMap = tentry->u.submap;
144         break;
145
146     case KEYMAP_PROC:
147         code = (*tentry->u.proc) (arock, tentry->rock);
148         keymap_ResetState(astate);
149         break;
150     }
151     return code;
152 }
153
154 int
155 keymap_ResetState(struct keymap_state *astate)
156 {
157     return keymap_InitState(astate, astate->initMap);
158 }