Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpKeyword.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 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 "vpMy.h"
43 #include "vpToken.h"
44 #include "vpKeyword.h"
45 
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #ifndef DOXYGEN_SHOULD_SKIP_THIS
50 
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 
56 #ifdef debug
57 static void delete_keyword (void);
58 static char *get_keyword (void);
59 #endif /* debug */
60 
61 
62 #define PRIME 211
63 #define NEXT(x) (x) = (x)->next
64 
65 typedef struct bucket {
66  struct bucket *next; /* element suivant */
67  char *ident; /* identifateur */
68  Byte length; /* longueur de "ident" */
69  Index token; /* code du jeton */
70 } Bucket;
71 
72 
73 static Bucket **hash_tbl; /* table de "hash-coding" */
74 
75 
76 /*
77  * La procedure "open_keyword" alloue et initialise les variables utilisees
78  * par les procedures de gestion des mots cles.
79  * Entree :
80  * kwp Tableau des mots cles termine par NULL.
81  */
82 void open_keyword (Keyword *kwp)
83 {
84  open_hash ();
85  for (; kwp->ident != NULL; kwp++) /* recopie les mots cles */
86  insert_keyword (kwp->ident, kwp->token);
87 }
88 
89 /*
90  * La procedure "close_keyword" libere les variables utilisees
91  * par les procedures de gestion des mots cles.
92  */
93 void close_keyword (void)
94 {
95  close_hash ();
96 }
97 
98 /*
99  * La procedure "open_hash" alloue et initialise la table de codage.
100  */
101 static void
102 open_hash (void)
103 {
104  Bucket **head, **bend;
105 
106  if ((hash_tbl = (Bucket **) malloc (sizeof (Bucket *) * PRIME))==NULL){
107  static char proc_name[] = "open_hash";
108  perror (proc_name);
109  exit (1);
110  }
111  head = hash_tbl;
112  bend = head + PRIME;
113  for (; head < bend; *head++ = NULL) {};
114 }
115 
116 /*
117  * La procedure "close_hash" libere la table de codage et ses elements.
118  */
119 static void
120 close_hash (void)
121 {
122  Bucket **head = hash_tbl;
123  Bucket **bend = head + PRIME;
124  Bucket *bp; /* element courant */
125  Bucket *next; /* element suivant */
126 
127  for (; head < bend; head++) { /* libere les listes */
128  for (bp = *head; bp != NULL; bp = next) {
129  next = bp->next;
130  free ((char *) bp);
131  }
132  }
133  free ((char *) hash_tbl); /* libere la table */
134 }
135 
136 /*
137  * La procedure "hashpjw" calcule un indice code a partir de la chaine
138  * de caracteres "str".
139  * Pour plus de renseignements, voir :
140  * "Compilers. Principles, Techniques, and Tools",
141  * A.V. AHO, R. SETHI, J.D. ULLMAN,
142  * ADDISON-WESLEY PUBLISHING COMPANY, pp 436.
143  * Entree :
144  * str Chaine de caracteres a coder.
145  * Sortie :
146  * Le code de la chaine.
147  */
148 static int
149 hashpjw (const char *str)
150 {
151  unsigned h = 0; /* "hash value" */
152 
153  for (; *str != '\0'; str++) {
154  unsigned g;
155  h = (h << 4) + (unsigned)(*str);
156  if ((g = h & ~0xfffffff) != 0) {
157  h ^= g >> 24;
158  h ^= g;
159  }
160  }
161  return ((int)(h % PRIME));
162 }
163 
164 
165 /*
166  * La procedure "insert_keyword" insere en tete d'un point d'entree
167  * de la table de "hachage" le mot cle ayant pour identificateur
168  * la chaine de caracteres "str" et pour valeur "token".
169  * Entree :
170  * str Chaine de caracteres du mot cle.
171  * token Valeur du jeton associe au mot cle.
172  */
173 static void
174 insert_keyword (const char *str, Index token)
175 {
176  Bucket **head = hash_tbl + hashpjw (str);
177  Bucket *bp;
178  Byte length;
179 
180  length = (Byte)( strlen(str) ); // Warning! Overflow possible!
181  if ((bp = (Bucket *) malloc (sizeof (Bucket) + length + 1)) == NULL) {
182  static const char proc_name[] = "insert_keyword";
183  perror (proc_name);
184  exit (1);
185  }
186  bp->length = length;
187  bp->token = token;
188  bp->ident = (char *) (bp + 1);
189  strcpy (bp->ident, str);
190 
191  bp->next = *head; /* insere "b" en tete de "head" */
192  *head = bp;
193 }
194 
195 /*
196  * La pocedure "get_symbol" verifie que la chaine pointee par "ident"
197  * de longeur "length" est un mot cle.
198  * Entree :
199  * ident Chaine de l'identificateur.
200  * length Nombre de caracteres de la chaine.
201  * Note :
202  * La chaine "ident" n'est pas terminee par '\0'.
203  * Sortie :
204  * Valeur du jeton associe si c'est un mot cle, 0 sinon.
205  */
206 Index get_symbol (char *ident, int length)
207 {
208  Bucket *bp;
209  const char *kwd;
210  char *idn = ident;
211  int len = length;
212 
213  { /* calcule le code de hachage (voir "hashpjw") */
214  unsigned h = 0; /* "hash value" */
215 
216  for (; len != 0; idn++, len--) {
217  unsigned g;
218  h = (h << 4) + (unsigned)(*idn);
219  if ((g = h & ~0xfffffff) != 0) {
220  h ^= g >> 24;
221  h ^= g;
222  }
223  }
224  bp = hash_tbl[h % PRIME];
225  }
226 
227  /* recherche le mot cle */
228 
229  for (; bp != NULL; NEXT(bp)) {
230  if (length == bp->length) {
231  idn = ident;
232  len = length;
233  kwd = bp->ident;
234  for (; *idn == *kwd; idn++, kwd++) {
235  --len;
236  if (len == 0) return (bp->token);
237  }
238  }
239  }
240  return (0); /* identificateur */
241 }
242 
243 #endif