IDZEBRA
2.0.54
Main Page
Data Structures
Files
File List
Globals
index
marcomp.c
Go to the documentation of this file.
1
/* This file is part of the Zebra server.
2
Copyright (C) 2004-2013 Index Data
3
4
Zebra is free software; you can redistribute it and/or modify it under
5
the terms of the GNU General Public License as published by the Free
6
Software Foundation; either version 2, or (at your option) any later
7
version.
8
9
Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10
WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
for more details.
13
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
18
*/
19
20
#if HAVE_CONFIG_H
21
#include <
config.h
>
22
#endif
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <ctype.h>
27
28
#include <yaz/yaz-util.h>
29
30
#include "
marcomp.h
"
31
32
static
mc_token
mc_gettoken
(
mc_context
*c);
33
static
void
mc_ungettoken
(
mc_context
*c);
34
static
int
mc_getval
(
mc_context
*c);
35
static
int
mc_getdata
(
mc_context
*c,
char
*s,
int
sz);
36
static
void
mc_getinterval
(
mc_context
*c,
int
*start,
int
*
end
);
37
38
static
mc_subfield
*
mc_mk_subfield
(
mc_subfield
*parent);
39
static
mc_field
*
mc_mk_field
(
void
);
40
41
static
struct
mc_errmsg
42
{
43
mc_errcode
code
;
44
const
char
*
msg
;
45
}
mc_errmsg
[] = {
46
{
EMCOK
,
"OK"
},
47
{
EMCNOMEM
,
"NO mem"
},
48
{
EMCF
,
"not complete field"
},
49
{
EMCSF
,
"not complete subfield"
},
50
{
EMCSFGROUP
,
"not closed GROUP"
},
51
{
EMCSFVAR
,
"not closed VARIANT"
},
52
{
EMCSFINLINE
,
"not closed IN-LINE"
},
53
{
EMCEND
,
"not correct errno"
}
54
};
55
mc_errcode
mc_errno
(
mc_context
*c)
56
{
57
return
c->
errcode
;
58
}
59
const
char
*
mc_error
(
mc_errcode
no)
60
{
61
if
(no >=
EMCOK
&& no<
EMCEND
)
62
return
mc_errmsg
[no].
msg
;
63
else
64
return
mc_errmsg
[
EMCEND
].
msg
;
65
}
66
mc_context
*
mc_mk_context
(
const
char
*s)
67
{
68
mc_context
*p=0;
69
70
if
(s && strlen(s))
71
{
72
p = (
mc_context
*) xmalloc(
sizeof
(*p));
73
74
if
(!p)
75
return
0;
76
77
memset(p, 0,
sizeof
(*p));
78
p->
errcode
=
EMCOK
;
79
p->
data
= s;
80
p->
len
= strlen(s);
81
p->
crrtok
=
NOP
;
82
}
83
84
return
p;
85
}
86
void
mc_destroy_context
(
mc_context
*c)
87
{
88
if
(c) xfree(c);
89
}
90
mc_token
mc_gettoken
(
mc_context
*c)
91
{
92
if
(c->
offset
>= c->
len
)
93
return
NOP
;
94
95
switch
(*(c->
data
+c->
offset
))
96
{
97
case
'{'
: c->
crrtok
=
LVARIANT
;
break
;
98
case
'}'
: c->
crrtok
=
RVARIANT
;
break
;
99
case
'('
: c->
crrtok
=
LGROUP
;
break
;
100
case
')'
: c->
crrtok
=
RGROUP
;
break
;
101
case
'<'
: c->
crrtok
=
LINLINE
;
break
;
102
case
'>'
: c->
crrtok
=
RINLINE
;
break
;
103
case
'$'
: c->
crrtok
=
SUBFIELD
;
break
;
104
case
'['
: c->
crrtok
=
LINTERVAL
;
break
;
105
case
']'
: c->
crrtok
=
RINTERVAL
;
break
;
106
default
:
107
if
(isspace(*(
unsigned
char
*) (c->
data
+c->
offset
))
108
|| *(c->
data
+c->
offset
) ==
'\n'
)
109
{
110
c->
crrtok
=
NOP
;
111
}
112
else
113
{
114
c->
crrtok
=
REGULAR
;
115
c->
crrval
= *(c->
data
+c->
offset
);
116
}
117
}
118
#ifdef DEBUG
119
fprintf(stderr,
"gettoken(): offset: %d"
, c->
offset
);
120
if
(c->
crrtok
==
REGULAR
)
121
fprintf(stderr,
"<%c>"
, c->
crrval
);
122
fprintf(stderr,
"\n"
);
123
#endif
124
c->
offset
++;
125
return
c->
crrtok
;
126
}
127
void
mc_ungettoken
(
mc_context
*c)
128
{
129
if
(c->
offset
> 0)
130
c->
offset
--;
131
}
132
int
mc_getval
(
mc_context
*c)
133
{
134
return
c->
crrval
;
135
}
136
int
mc_getdata
(
mc_context
*c,
char
*s,
int
sz)
137
{
138
int
i;
139
140
for
(i=0; i<sz; i++)
141
{
142
if
(
mc_gettoken
(c)!=
REGULAR
)
143
{
144
mc_ungettoken
(c);
145
break
;
146
}
147
s[i] =
mc_getval
(c);
148
}
149
s[i] =
'\0'
;
150
151
return
i;
152
}
153
void
mc_getinterval
(
mc_context
*c,
int
*start,
int
*
end
)
154
{
155
char
buf[6+1];
156
int
start_pos, end_pos;
157
158
start_pos = end_pos = -1;
159
160
if
(
mc_gettoken
(c) ==
LINTERVAL
)
161
{
162
int
i;
163
164
for
(i=0;i<6;i++)
165
{
166
mc_token
tok =
mc_gettoken
(c);
167
168
if
(tok ==
RINTERVAL
|| tok ==
NOP
)
169
break
;
170
171
buf[i] =
mc_getval
(c);
172
}
173
174
buf[i] =
'\0'
;
175
i = sscanf(buf,
"%d-%d"
, &start_pos, &end_pos);
176
177
if
(i == 1)
178
end_pos = start_pos;
179
else
if
( i == 0)
180
{
181
start_pos = 0;
182
}
183
}
184
*start = start_pos;
185
*end = end_pos;
186
}
187
mc_field
*
mc_mk_field
(
void
)
188
{
189
mc_field
*p = (
mc_field
*)xmalloc(
sizeof
(*p));
190
191
if
(p)
192
{
193
memset(p, 0,
sizeof
(*p));
194
p->
name
= (
char
*)xmalloc(
SZ_FNAME
+1);
195
*p->
name
=
'\0'
;
196
p->
ind1
= (
char
*)xmalloc(
SZ_IND
+1);
197
*p->
ind1
=
'\0'
;
198
p->
ind2
= (
char
*)xmalloc(
SZ_IND
+1);
199
*p->
ind2
=
'\0'
;
200
p->
interval
.
start
= p->
interval
.
end
= -1;
201
}
202
return
p;
203
}
204
void
mc_destroy_field
(
mc_field
*p)
205
{
206
if
(!p)
207
return
;
208
if
(p->
name
) xfree(p->
name
);
209
if
(p->
ind1
) xfree(p->
ind1
);
210
if
(p->
ind2
) xfree(p->
ind2
);
211
if
(p->
list
)
mc_destroy_subfields_recursive
(p->
list
);
212
xfree(p);
213
}
214
mc_field
*
mc_getfield
(
mc_context
*c)
215
{
216
mc_field
*pf;
217
218
pf =
mc_mk_field
();
219
220
if
(!pf)
221
{
222
c->
errcode
=
EMCNOMEM
;
223
return
0;
224
}
225
226
if
(
mc_getdata
(c, pf->
name
,
SZ_FNAME
) ==
SZ_FNAME
)
227
{
228
mc_token
nexttok =
mc_gettoken
(c);
229
230
mc_ungettoken
(c);
231
232
if
(nexttok ==
LINTERVAL
)
233
{
234
mc_getinterval
(c, &pf->
interval
.
start
, &pf->
interval
.
end
);
235
#ifdef DEBUG
236
fprintf(stderr,
"ineterval (%d)-(%d)\n"
, pf->
interval
.
start
,
237
pf->
interval
.
end
);
238
#endif
239
}
240
241
if
((
mc_getdata
(c, pf->
ind1
,
SZ_IND
) ==
SZ_IND
) &&
242
(
mc_getdata
(c, pf->
ind2
,
SZ_IND
) ==
SZ_IND
))
243
{
244
pf->
list
=
mc_getsubfields
(c, 0);
245
}
246
}
247
else
248
{
249
c->
errcode
=
EMCF
;
250
mc_destroy_field
(pf);
251
return
0;
252
}
253
254
return
pf;
255
}
256
mc_subfield
*
mc_mk_subfield
(
mc_subfield
*parent)
257
{
258
mc_subfield
*p = (
mc_subfield
*)xmalloc(
sizeof
(*p));
259
260
if
(p)
261
{
262
memset(p, 0,
sizeof
(*p));
263
p->
which
=
MC_SF
;
264
p->
name
= (
char
*)xmalloc(
SZ_SFNAME
+1);
265
*p->
name
=
'\0'
;
266
p->
prefix
= (
char
*)xmalloc(
SZ_PREFIX
+1);
267
*p->
prefix
=
'\0'
;
268
p->
suffix
= (
char
*)xmalloc(
SZ_SUFFIX
+1);
269
*p->
suffix
=
'\0'
;
270
p->
parent
= parent;
271
p->
interval
.
start
= p->
interval
.
end
= -1;
272
}
273
return
p;
274
}
275
void
mc_destroy_subfield
(
mc_subfield
*p)
276
{
277
if
(!p)
278
return
;
279
280
if
(p->
which
==
MC_SFGROUP
|| p->
which
==
MC_SFVARIANT
)
281
{
282
if
(p->
u
.
child
)
283
mc_destroy_subfields_recursive
(p->
u
.
child
);
284
}
285
else
if
(p->
which
==
MC_SF
)
286
{
287
if
(p->
u
.
in_line
)
288
mc_destroy_field
(p->
u
.
in_line
);
289
}
290
if
(p->
name
) xfree(p->
name
);
291
if
(p->
prefix
) xfree(p->
prefix
);
292
if
(p->
suffix
) xfree(p->
suffix
);
293
if
(p->
parent
) p->
parent
->
next
= p->
next
;
294
xfree(p);
295
}
296
void
mc_destroy_subfields_recursive
(
mc_subfield
*p)
297
{
298
if
(!p)
299
return
;
300
301
mc_destroy_subfields_recursive
(p->
next
);
302
303
if
(p->
which
==
MC_SFGROUP
|| p->
which
==
MC_SFVARIANT
)
304
{
305
if
(p->
u
.
child
)
306
mc_destroy_subfields_recursive
(p->
u
.
child
);
307
}
308
else
if
(p->
which
==
MC_SF
)
309
{
310
if
(p->
u
.
in_line
)
311
mc_destroy_field
(p->
u
.
in_line
);
312
}
313
314
if
(p->
name
) xfree(p->
name
);
315
if
(p->
prefix
) xfree(p->
prefix
);
316
if
(p->
suffix
) xfree(p->
suffix
);
317
if
(p->
parent
) p->
parent
->
next
= 0;
318
xfree(p);
319
}
320
mc_subfield
*
mc_getsubfields
(
mc_context
*c,
mc_subfield
*parent)
321
{
322
mc_subfield
*psf=0;
323
mc_token
tok =
mc_gettoken
(c);
324
325
if
(tok ==
NOP
)
326
return
0;
327
328
if
(tok ==
LGROUP
)
329
{
330
if
(!(psf =
mc_mk_subfield
(parent)))
331
{
332
c->
errcode
=
EMCNOMEM
;
333
return
0;
334
}
335
336
psf->
which
=
MC_SFGROUP
;
337
psf->
u
.
child
=
mc_getsubfields
(c, psf);
338
339
if
(
mc_gettoken
(c) ==
RGROUP
)
340
psf->
next
=
mc_getsubfields
(c, psf);
341
else
342
{
343
c->
errcode
=
EMCSFGROUP
;
344
mc_destroy_subfield
(psf);
345
return
0;
346
}
347
}
348
else
if
(tok ==
LVARIANT
)
349
{
350
if
(!(psf =
mc_mk_subfield
(parent)))
351
{
352
c->
errcode
=
EMCNOMEM
;
353
return
0;
354
}
355
356
psf->
which
=
MC_SFVARIANT
;
357
psf->
u
.
child
=
mc_getsubfields
(c, psf);
358
359
if
(
mc_gettoken
(c) ==
RVARIANT
)
360
psf->
next
=
mc_getsubfields
(c, psf);
361
else
362
{
363
c->
errcode
=
EMCSFVAR
;
364
mc_destroy_subfield
(psf);
365
return
0;
366
}
367
}
368
else
if
(tok ==
RGROUP
|| tok ==
RVARIANT
|| tok ==
RINLINE
)
369
{
370
mc_ungettoken
(c);
371
return
0;
372
}
373
else
if
(tok ==
REGULAR
)
374
{
375
if
(!(psf =
mc_mk_subfield
(parent)))
376
{
377
c->
errcode
=
EMCNOMEM
;
378
return
0;
379
}
380
381
mc_ungettoken
(c);
382
383
if
((
mc_getdata
(c, psf->
prefix
,
SZ_PREFIX
) ==
SZ_PREFIX
) &&
384
(
mc_gettoken
(c) ==
SUBFIELD
) &&
385
(
mc_getdata
(c, psf->
name
,
SZ_SFNAME
) ==
SZ_SFNAME
))
386
{
387
mc_token
tok =
mc_gettoken
(c);
388
389
mc_ungettoken
(c);
390
391
if
(tok ==
LINTERVAL
)
392
{
393
mc_getinterval
(c, &psf->
interval
.
start
, &psf->
interval
.
end
);
394
}
395
else
if
(tok ==
LINLINE
)
396
{
397
mc_gettoken
(c);
398
psf->
u
.
in_line
=
mc_getfield
(c);
399
if
(
mc_gettoken
(c) !=
RINLINE
)
400
{
401
c->
errcode
=
EMCSFINLINE
;
402
mc_destroy_subfield
(psf);
403
return
0;
404
}
405
}
406
407
if
(
mc_getdata
(c, psf->
suffix
,
SZ_SUFFIX
) ==
SZ_SUFFIX
)
408
{
409
psf->
which
=
MC_SF
;
410
psf->
next
=
mc_getsubfields
(c, psf);
411
}
412
else
413
{
414
c->
errcode
=
EMCSF
;
415
mc_destroy_subfield
(psf);
416
return
0;
417
}
418
}
419
}
420
return
psf;
421
}
422
/*
423
* Local variables:
424
* c-basic-offset: 4
425
* c-file-style: "Stroustrup"
426
* indent-tabs-mode: nil
427
* End:
428
* vim: shiftwidth=4 tabstop=8 expandtab
429
*/
430
Generated on Mon Jan 21 2013 13:16:50 for IDZEBRA by
1.8.1.2