Visual Servoing Platform  version 3.0.0
vpKeyword.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Le module "keyword.c" contient les procedures de gestion
32  * des mots cles retournes par l'analyseur lexical "lex".
33  *
34  * Authors:
35  * Jean-Luc CORRE
36  *
37  *****************************************************************************/
38 
39 
40 
41 
42 #include <visp3/robot/vpMy.h>
43 #include <visp3/robot/vpToken.h>
44 
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #ifndef DOXYGEN_SHOULD_SKIP_THIS
49 
50 void open_keyword (Keyword *kwp);
51 static void open_hash (void);
52 static void close_hash (void);
53 static int hashpjw (const char *str);
54 static void insert_keyword (const char *str, Index token);
55 Index get_symbol (char *ident, int length);
56 
57 #ifdef debug
58 static void delete_keyword (void);
59 static char *get_keyword (void);
60 #endif /* debug */
61 
62 
63 #define PRIME 211
64 #define NEXT(x) (x) = (x)->next
65 
66 typedef struct bucket {
67  struct bucket *next; /* element suivant */
68  char *ident; /* identifateur */
69  Byte length; /* longueur de "ident" */
70  Index token; /* code du jeton */
71 } Bucket;
72 
73 
74 static Bucket **hash_tbl; /* table de "hash-coding" */
75 
76 
77 /*
78  * La procedure "open_keyword" alloue et initialise les variables utilisees
79  * par les procedures de gestion des mots cles.
80  * Entree :
81  * kwp Tableau des mots cles termine par NULL.
82  */
83 void open_keyword (Keyword *kwp)
84 {
85  open_hash ();
86  for (; kwp->ident != NULL; kwp++) /* recopie les mots cles */
87  insert_keyword (kwp->ident, kwp->token);
88 }
89 
90 /*
91  * La procedure "close_keyword" libere les variables utilisees
92  * par les procedures de gestion des mots cles.
93  */
94 void close_keyword (void)
95 {
96  close_hash ();
97 }
98 
99 /*
100  * La procedure "open_hash" alloue et initialise la table de codage.
101  */
102 static void
103 open_hash (void)
104 {
105  static char proc_name[] = "open_hash";
106 
107  Bucket **head, **bend;
108 
109  if ((hash_tbl = (Bucket **) malloc (sizeof (Bucket *) * PRIME))==NULL){
110  perror (proc_name);
111  exit (1);
112  }
113  head = hash_tbl;
114  bend = head + PRIME;
115  for (; head < bend; *head++ = NULL) {};
116 }
117 
118 /*
119  * La procedure "close_hash" libere la table de codage et ses elements.
120  */
121 static void
122 close_hash (void)
123 {
124  Bucket **head = hash_tbl;
125  Bucket **bend = head + PRIME;
126  Bucket *bp; /* element courant */
127  Bucket *next; /* element suivant */
128 
129  for (; head < bend; head++) { /* libere les listes */
130  for (bp = *head; bp != NULL; bp = next) {
131  next = bp->next;
132  free ((char *) bp);
133  }
134  }
135  free ((char *) hash_tbl); /* libere la table */
136 }
137 
138 /*
139  * La procedure "hashpjw" calcule un indice code a partir de la chaine
140  * de caracteres "str".
141  * Pour plus de renseignements, voir :
142  * "Compilers. Principles, Techniques, and Tools",
143  * A.V. AHO, R. SETHI, J.D. ULLMAN,
144  * ADDISON-WESLEY PUBLISHING COMPANY, pp 436.
145  * Entree :
146  * str Chaine de caracteres a coder.
147  * Sortie :
148  * Le code de la chaine.
149  */
150 static int
151 hashpjw (const char *str)
152 {
153  unsigned h = 0; /* "hash value" */
154  unsigned g;
155 
156  for (; *str != '\0'; str++) {
157  h = (h << 4) + (unsigned)(*str);
158  if ((g = h & ~0xfffffff) != 0) {
159  h ^= g >> 24;
160  h ^= g;
161  }
162  }
163  return ((int)(h % PRIME));
164 }
165 
166 
167 /*
168  * La procedure "insert_keyword" insere en tete d'un point d'entree
169  * de la table de "hachage" le mot cle ayant pour identificateur
170  * la chaine de caracteres "str" et pour valeur "token".
171  * Entree :
172  * str Chaine de caracteres du mot cle.
173  * token Valeur du jeton associe au mot cle.
174  */
175 static void
176 insert_keyword (const char *str, Index token)
177 {
178  static const char proc_name[] = "insert_keyword";
179 
180  Bucket **head = hash_tbl + hashpjw (str);
181  Bucket *bp;
182  Byte length;
183 
184  length = (Byte)( strlen(str) ); // Warning! Overflow possible!
185  if ((bp = (Bucket *) malloc (sizeof (Bucket) + length + 1)) == NULL) {
186  perror (proc_name);
187  exit (1);
188  }
189  bp->length = length;
190  bp->token = token;
191  bp->ident = (char *) (bp + 1);
192  strcpy (bp->ident, str);
193 
194  bp->next = *head; /* insere "b" en tete de "head" */
195  *head = bp;
196 }
197 
198 /*
199  * La pocedure "get_symbol" verifie que la chaine pointee par "ident"
200  * de longeur "length" est un mot cle.
201  * Entree :
202  * ident Chaine de l'identificateur.
203  * length Nombre de caracteres de la chaine.
204  * Note :
205  * La chaine "ident" n'est pas terminee par '\0'.
206  * Sortie :
207  * Valeur du jeton associe si c'est un mot cle, 0 sinon.
208  */
209 Index get_symbol (char *ident, int length)
210 {
211  Bucket *bp;
212  const char *kwd;
213  char *idn = ident;
214  int len = length;
215 
216  { /* calcule le code de hachage (voir "hashpjw") */
217  unsigned h = 0; /* "hash value" */
218  unsigned g;
219 
220  for (; len != 0; idn++, len--) {
221  h = (h << 4) + (unsigned)(*idn);
222  if ((g = h & ~0xfffffff) != 0) {
223  h ^= g >> 24;
224  h ^= g;
225  }
226  }
227  bp = hash_tbl[h % PRIME];
228  }
229 
230  /* recherche le mot cle */
231 
232  for (; bp != NULL; NEXT(bp)) {
233  if (length == bp->length) {
234  idn = ident;
235  len = length;
236  kwd = bp->ident;
237  for (; *idn == *kwd; idn++, kwd++)
238  if (--len == 0) return (bp->token);
239  }
240  }
241  return (0); /* identificateur */
242 }
243 
244 #endif