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