More type casts for char signed/unsigned and xmlChar. Using
[yaz-moved-to-github.git] / src / srwutil.c
1 /*
2  * Copyright (C) 1995-2005, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: srwutil.c,v 1.29 2005-08-22 20:34:21 adam Exp $
6  */
7 /**
8  * \file srwutil.c
9  * \brief Implements SRW/SRU utilities.
10  */
11
12 #include <stdlib.h>
13 #include <yaz/srw.h>
14 #include <yaz/yaz-iconv.h>
15
16 static int hex_digit (int ch)
17 {
18     if (ch >= '0' && ch <= '9')
19         return ch - '0';
20     else if (ch >= 'a' && ch <= 'f')
21         return ch - 'a'+10;
22     else if (ch >= 'A' && ch <= 'F')
23         return ch - 'A'+10;
24     return 0;
25 }
26
27 int yaz_uri_array(const char *path, ODR o, char ***name, char ***val)
28 {
29     int no = 2;
30     const char *cp;
31     *name = 0;
32     if (*path != '?')
33         return no;
34     path++;
35     cp = path;
36     while ((cp = strchr(cp, '&')))
37     {
38         cp++;
39         no++;
40     }
41     *name = odr_malloc(o, no * sizeof(char**));
42     *val = odr_malloc(o, no * sizeof(char**));
43
44     for (no = 0; *path; no++)
45     {
46         const char *p1 = strchr(path, '=');
47         size_t i = 0;
48         char *ret;
49         if (!p1)
50             break;
51
52         (*name)[no] = odr_malloc(o, (p1-path)+1);
53         memcpy((*name)[no], path, p1-path);
54         (*name)[no][p1-path] = '\0';
55
56         path = p1 + 1;
57         p1 = strchr(path, '&');
58         if (!p1)
59             p1 = strlen(path) + path;
60         (*val)[no] = ret = odr_malloc(o, p1 - path + 1);
61         while (*path && *path != '&')
62         {
63             if (*path == '+')
64             {
65                 ret[i++] = ' ';
66                 path++;
67             }
68             else if (*path == '%' && path[1] && path[2])
69             {
70                 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
71                 path = path + 3;
72             }
73             else
74                 ret[i++] = *path++;
75         }
76         ret[i] = '\0';
77
78         if (*path)
79             path++;
80     }
81     (*name)[no] = 0;
82     (*val)[no] = 0;
83     return no;
84 }
85
86 char *yaz_uri_val(const char *path, const char *name, ODR o)
87 {
88     size_t nlen = strlen(name);
89     if (*path != '?')
90         return 0;
91     path++;
92     while (path && *path)
93     {
94         const char *p1 = strchr(path, '=');
95         if (!p1)
96             break;
97         if ((size_t)(p1 - path) == nlen && !memcmp(path, name, nlen))
98         {
99             size_t i = 0;
100             char *ret;
101             
102             path = p1 + 1;
103             p1 = strchr(path, '&');
104             if (!p1)
105                 p1 = strlen(path) + path;
106             ret = (char *) odr_malloc(o, p1 - path + 1);
107             while (*path && *path != '&')
108             {
109                 if (*path == '+')
110                 {
111                     ret[i++] = ' ';
112                     path++;
113                 }
114                 else if (*path == '%' && path[1] && path[2])
115                 {
116                     ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
117                     path = path + 3;
118                 }
119                 else
120                     ret[i++] = *path++;
121             }
122             ret[i] = '\0';
123             return ret;
124         }
125         path = strchr(p1, '&');
126         if (path)
127             path++;
128     }
129     return 0;
130 }
131
132 void yaz_uri_val_int(const char *path, const char *name, ODR o, int **intp)
133 {
134     const char *v = yaz_uri_val(path, name, o);
135     if (v)
136         *intp = odr_intdup(o, atoi(v));
137 }
138
139 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d, 
140                            int code, const char *details)
141 {
142     d->uri = (char *) odr_malloc(o, 50);
143     sprintf(d->uri, "info:srw/diagnostic/1/%d", code);
144     d->message = 0;
145     if (details)
146         d->details = odr_strdup(o, details);
147     else
148         d->details = 0;
149 }
150
151 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
152                             int *num, int code, const char *addinfo)
153 {
154     Z_SRW_diagnostic *d_new;
155     d_new = (Z_SRW_diagnostic *) odr_malloc (o, (*num + 1)* sizeof(**d));
156     if (*num)
157         memcpy (d_new, *d, *num *sizeof(**d));
158     *d = d_new;
159
160     yaz_mk_std_diagnostic(o, *d + *num, code, addinfo);
161     (*num)++;
162 }
163
164 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
165                    Z_SOAP **soap_package, ODR decode, char **charset)
166 {
167     if (!strcmp(hreq->method, "POST"))
168     {
169         const char *content_type = z_HTTP_header_lookup(hreq->headers,
170                                                         "Content-Type");
171         if (content_type && 
172             (!yaz_strcmp_del("text/xml", content_type, "; ") ||
173              !yaz_strcmp_del("text/plain", content_type, "; ")))
174         {
175             char *db = "Default";
176             const char *p0 = hreq->path, *p1;
177             int ret = -1;
178             const char *charset_p = 0;
179             
180             static Z_SOAP_Handler soap_handlers[3] = {
181 #if HAVE_XML2
182                 {"http://www.loc.gov/zing/srw/", 0,
183                  (Z_SOAP_fun) yaz_srw_codec},
184                 {"http://www.loc.gov/zing/srw/v1.0/", 0,
185                  (Z_SOAP_fun) yaz_srw_codec},
186 #endif
187                 {0, 0, 0}
188             };
189             
190             if (*p0 == '/')
191                 p0++;
192             p1 = strchr(p0, '?');
193             if (!p1)
194                 p1 = p0 + strlen(p0);
195             if (p1 != p0)
196             {
197                 db = (char*) odr_malloc(decode, p1 - p0 + 1);
198                 memcpy (db, p0, p1 - p0);
199                 db[p1 - p0] = '\0';
200             }
201
202             if (charset && (charset_p = strstr(content_type, "; charset=")))
203             {
204                 int i = 0;
205                 charset_p += 10;
206                 while (i < 20 && charset_p[i] &&
207                        !strchr("; \n\r", charset_p[i]))
208                     i++;
209                 *charset = (char*) odr_malloc(decode, i+1);
210                 memcpy(*charset, charset_p, i);
211                 (*charset)[i] = '\0';
212             }
213             ret = z_soap_codec(decode, soap_package, 
214                                &hreq->content_buf, &hreq->content_len,
215                                soap_handlers);
216             if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
217             {
218                 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
219                 
220                 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
221                     (*srw_pdu)->u.request->database == 0)
222                     (*srw_pdu)->u.request->database = db;
223
224                 if ((*srw_pdu)->which == Z_SRW_explain_request &&
225                     (*srw_pdu)->u.explain_request->database == 0)
226                     (*srw_pdu)->u.explain_request->database = db;
227
228                 if ((*srw_pdu)->which == Z_SRW_scan_request &&
229                     (*srw_pdu)->u.scan_request->database == 0)
230                     (*srw_pdu)->u.scan_request->database = db;
231
232                 return 0;
233             }
234             return 1;
235         }
236     }
237     return 2;
238 }
239
240 /**
241   http://www.loc.gov/z3950/agency/zing/srw/service.html
242 */ 
243 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
244                    Z_SOAP **soap_package, ODR decode, char **charset,
245                    Z_SRW_diagnostic **diag, int *num_diag)
246 {
247 #if HAVE_XML2
248     static Z_SOAP_Handler soap_handlers[2] = {
249         {"http://www.loc.gov/zing/srw/", 0,
250          (Z_SOAP_fun) yaz_srw_codec},
251         {0, 0, 0}
252     };
253 #endif
254     if (!strcmp(hreq->method, "GET") ||
255       !strcmp(hreq->method, "POST") )
256     {
257         char *db = "Default";
258         const char *p0 = hreq->path, *p1;
259 #if HAVE_XML2
260         const char *operation = 0;
261         char *version = 0;
262         char *query = 0;
263         char *pQuery = 0;
264         char *sortKeys = 0;
265         char *stylesheet = 0;
266         char *scanClause = 0;
267         char *pScanClause = 0;
268         char *recordXPath = 0;
269         char *recordSchema = 0;
270         char *recordPacking = "xml";  /* xml packing is default for SRU */
271         char *maximumRecords = 0;
272         char *startRecord = 0;
273         char *maximumTerms = 0;
274         char *responsePosition = 0;
275         char *extraRequestData = 0;
276 #endif
277         char **uri_name;
278         char **uri_val;
279
280         if (charset)
281             *charset = 0;
282         if (*p0 == '/')
283             p0++;
284         p1 = strchr(p0, '?');
285         if (!p1)
286             p1 = p0 + strlen(p0);
287         if (p1 != p0)
288         {
289             db = (char*) odr_malloc(decode, p1 - p0 + 1);
290             memcpy (db, p0, p1 - p0);
291             db[p1 - p0] = '\0';
292         }
293         if (!strcmp(hreq->method, "POST"))
294             p1 = hreq->content_buf;
295         yaz_uri_array(p1, decode, &uri_name, &uri_val);
296 #if HAVE_XML2
297         if (uri_name)
298         {
299             int i;
300             for (i = 0; uri_name[i]; i++)
301             {
302                 char *n = uri_name[i];
303                 char *v = uri_val[i];
304                 if (!strcmp(n, "query"))
305                     query = v;
306                 else if (!strcmp(n, "x-pquery"))
307                     pQuery = v;
308                 else if (!strcmp(n, "operation"))
309                     operation = v;
310                 else if (!strcmp(n, "stylesheet"))
311                     stylesheet = v;
312                 else if (!strcmp(n, "sortKeys"))
313                     sortKeys = v;
314                 else if (!strcmp(n, "recordXPath"))
315                     recordXPath = v;
316                 else if (!strcmp(n, "recordSchema"))
317                     recordSchema = v;
318                 else if (!strcmp(n, "recordPacking"))
319                     recordPacking = v;
320                 else if (!strcmp(n, "version"))
321                     version = v;
322                 else if (!strcmp(n, "scanClause"))
323                     scanClause = v;
324                 else if (!strcmp(n, "x-pScanClause"))
325                     pScanClause = v;
326                 else if (!strcmp(n, "maximumRecords"))
327                     maximumRecords = v;
328                 else if (!strcmp(n, "startRecord"))
329                     startRecord = v;
330                 else if (!strcmp(n, "maximumTerms"))
331                     maximumTerms = v;
332                 else if (!strcmp(n, "responsePosition"))
333                     responsePosition = v;
334                 else if (!strcmp(n, "extraRequestData"))
335                     extraRequestData = v;
336                 else
337                     yaz_add_srw_diagnostic(decode, diag, num_diag, 8, n);
338             }
339         }
340         if (!version)
341         {
342             if (uri_name)
343                 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "version");
344             version = "1.1";
345         }
346         if (strcmp(version, "1.1"))
347             yaz_add_srw_diagnostic(decode, diag, num_diag, 5, "1.1");
348         if (!operation)
349         {
350             if (uri_name)
351                 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "operation");
352             operation = "explain";
353         }
354         if (!strcmp(operation, "searchRetrieve"))
355         {
356             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
357
358             sr->srw_version = version;
359             *srw_pdu = sr;
360             if (query)
361             {
362                 sr->u.request->query_type = Z_SRW_query_type_cql;
363                 sr->u.request->query.cql = query;
364             }
365             else if (pQuery)
366             {
367                 sr->u.request->query_type = Z_SRW_query_type_pqf;
368                 sr->u.request->query.pqf = pQuery;
369             }
370             else
371                 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "query");
372
373             if (sortKeys)
374             {
375                 sr->u.request->sort_type = Z_SRW_sort_type_sort;
376                 sr->u.request->sort.sortKeys = sortKeys;
377             }
378             sr->u.request->recordXPath = recordXPath;
379             sr->u.request->recordSchema = recordSchema;
380             sr->u.request->recordPacking = recordPacking;
381             sr->u.request->stylesheet = stylesheet;
382
383             if (maximumRecords)
384                 sr->u.request->maximumRecords =
385                     odr_intdup(decode, atoi(maximumRecords));
386             if (startRecord)
387                 sr->u.request->startRecord =
388                     odr_intdup(decode, atoi(startRecord));
389
390             sr->u.request->database = db;
391
392             (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
393             (*soap_package)->which = Z_SOAP_generic;
394             
395             (*soap_package)->u.generic =
396                 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
397             
398             (*soap_package)->u.generic->p = sr;
399             (*soap_package)->u.generic->ns = soap_handlers[0].ns;
400             (*soap_package)->u.generic->no = 0;
401             
402             (*soap_package)->ns = "SRU";
403
404             return 0;
405         }
406         else if (!strcmp(operation, "explain"))
407         {
408             /* Transfer SRU explain parameters to common struct */
409             /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
410             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
411
412             sr->srw_version = version;
413             *srw_pdu = sr;
414             sr->u.explain_request->recordPacking = recordPacking;
415             sr->u.explain_request->database = db;
416
417             sr->u.explain_request->stylesheet = stylesheet;
418
419             (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
420             (*soap_package)->which = Z_SOAP_generic;
421             
422             (*soap_package)->u.generic =
423                 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
424             
425             (*soap_package)->u.generic->p = sr;
426             (*soap_package)->u.generic->ns = soap_handlers[0].ns;
427             (*soap_package)->u.generic->no = 0;
428             
429             (*soap_package)->ns = "SRU";
430
431             return 0;
432         }
433         else if (!strcmp(operation, "scan"))
434         {
435             /* Transfer SRU scan parameters to common struct */
436             /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
437             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
438
439             sr->srw_version = version;
440             *srw_pdu = sr;
441
442             if (scanClause)
443             {
444                 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
445                 sr->u.scan_request->scanClause.cql = scanClause;
446             }
447             else if (pScanClause)
448             {
449                 sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
450                 sr->u.scan_request->scanClause.pqf = pScanClause;
451             }
452             else
453                 yaz_add_srw_diagnostic(decode, diag, num_diag, 7,
454                                        "scanClause");
455             sr->u.scan_request->database = db;
456
457             if (maximumTerms)
458                 sr->u.scan_request->maximumTerms =
459                     odr_intdup(decode, atoi(maximumTerms));
460             if (responsePosition)
461                 sr->u.scan_request->responsePosition =
462                     odr_intdup(decode, atoi(responsePosition));
463
464             sr->u.scan_request->stylesheet = stylesheet;
465
466             (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
467             (*soap_package)->which = Z_SOAP_generic;
468             
469             (*soap_package)->u.generic =
470                 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
471             
472             (*soap_package)->u.generic->p = sr;
473             (*soap_package)->u.generic->ns = soap_handlers[0].ns;
474             (*soap_package)->u.generic->no = 0;
475             
476             (*soap_package)->ns = "SRU";
477
478             return 0;
479         }
480         else
481         {
482             /* unsupported operation ... */
483             /* Act as if we received a explain request and throw diagnostic. */
484
485             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
486
487             sr->srw_version = version;
488             *srw_pdu = sr;
489             sr->u.explain_request->recordPacking = recordPacking;
490             sr->u.explain_request->database = db;
491
492             sr->u.explain_request->stylesheet = stylesheet;
493
494             (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
495             (*soap_package)->which = Z_SOAP_generic;
496             
497             (*soap_package)->u.generic =
498                 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
499             
500             (*soap_package)->u.generic->p = sr;
501             (*soap_package)->u.generic->ns = soap_handlers[0].ns;
502             (*soap_package)->u.generic->no = 0;
503             
504             (*soap_package)->ns = "SRU";
505
506             yaz_add_srw_diagnostic(decode, diag, num_diag, 4, operation);
507             return 0;
508         }
509 #endif
510         return 1;
511     }
512     return 2;
513 }
514
515 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
516 {
517     Z_SRW_PDU *sr = (Z_SRW_PDU *) odr_malloc(o, sizeof(*o));
518
519     sr->srw_version = odr_strdup(o, "1.1");
520     sr->which = which;
521     switch(which)
522     {
523     case Z_SRW_searchRetrieve_request:
524         sr->u.request = (Z_SRW_searchRetrieveRequest *)
525             odr_malloc(o, sizeof(*sr->u.request));
526         sr->u.request->query_type = Z_SRW_query_type_cql;
527         sr->u.request->query.cql = 0;
528         sr->u.request->sort_type = Z_SRW_sort_type_none;
529         sr->u.request->sort.none = 0;
530         sr->u.request->startRecord = 0;
531         sr->u.request->maximumRecords = 0;
532         sr->u.request->recordSchema = 0;
533         sr->u.request->recordPacking = 0;
534         sr->u.request->recordXPath = 0;
535         sr->u.request->database = 0;
536         sr->u.request->resultSetTTL = 0;
537         sr->u.request->stylesheet = 0;
538         break;
539     case Z_SRW_searchRetrieve_response:
540         sr->u.response = (Z_SRW_searchRetrieveResponse *)
541             odr_malloc(o, sizeof(*sr->u.response));
542         sr->u.response->numberOfRecords = 0;
543         sr->u.response->resultSetId = 0;
544         sr->u.response->resultSetIdleTime = 0;
545         sr->u.response->records = 0;
546         sr->u.response->num_records = 0;
547         sr->u.response->diagnostics = 0;
548         sr->u.response->num_diagnostics = 0;
549         sr->u.response->nextRecordPosition = 0;
550         break;
551     case Z_SRW_explain_request:
552         sr->u.explain_request = (Z_SRW_explainRequest *)
553             odr_malloc(o, sizeof(*sr->u.explain_request));
554         sr->u.explain_request->recordPacking = 0;
555         sr->u.explain_request->database = 0;
556         sr->u.explain_request->stylesheet = 0;
557         break;
558     case Z_SRW_explain_response:
559         sr->u.explain_response = (Z_SRW_explainResponse *)
560             odr_malloc(o, sizeof(*sr->u.explain_response));
561         sr->u.explain_response->record.recordData_buf = 0;
562         sr->u.explain_response->record.recordData_len = 0;
563         sr->u.explain_response->record.recordSchema = 0;
564         sr->u.explain_response->record.recordPosition = 0;
565         sr->u.explain_response->record.recordPacking =
566             Z_SRW_recordPacking_string;
567         sr->u.explain_response->diagnostics = 0;
568         sr->u.explain_response->num_diagnostics = 0;
569         break;
570     case Z_SRW_scan_request:
571         sr->u.scan_request = (Z_SRW_scanRequest *)
572             odr_malloc(o, sizeof(*sr->u.scan_request));
573         sr->u.scan_request->database = 0;
574         sr->u.scan_request->stylesheet = 0;
575         sr->u.scan_request->maximumTerms = 0;
576         sr->u.scan_request->responsePosition = 0;
577         sr->u.scan_request->query_type = Z_SRW_query_type_cql;
578         sr->u.scan_request->scanClause.cql = 0;
579         break;
580     case Z_SRW_scan_response:
581         sr->u.scan_response = (Z_SRW_scanResponse *)
582             odr_malloc(o, sizeof(*sr->u.scan_response));
583         sr->u.scan_response->terms = 0;
584         sr->u.scan_response->num_terms = 0;
585         sr->u.scan_response->diagnostics = 0;
586         sr->u.scan_response->num_diagnostics = 0;
587     }
588     return sr;
589 }
590
591
592
593 /* bib1:srw */
594 static int srw_bib1_map[] = {
595     1, 1,
596     2, 2,
597     3, 11,
598     4, 35,
599     5, 12,
600     6, 38,
601     7, 30,
602     8, 32,
603     9, 29,
604     108, 10,  /* Malformed query : Syntax error */
605     10, 10,
606     11, 12,
607     11, 23,
608     12, 60,
609     13, 61,
610     13, 62,
611     14, 63,
612     14, 64,
613     14, 65,
614     15, 68,
615     15, 69,
616     16, 70,
617     17, 70,
618     18, 50,
619     19, 55,
620     20, 56, 
621     21, 52,
622     22, 50,
623     23, 3,
624     24, 66,
625     25, 66,
626     26, 66,
627     27, 51,
628     28, 52,
629     29, 52,
630     30, 51,
631     31, 57,
632     32, 58,
633     33, 59,
634     100, 1, /* bad map */
635     101, 3,
636     102, 3,
637     103, 3,
638     104, 3,
639     105, 3, 
640     106, 66,
641     107, 11,
642     108, 13,
643     108, 14,
644     108, 25,
645     108, 26,
646     108, 27,
647     108, 45,
648         
649     109, 2,
650     110, 37,
651     111, 1,
652     112, 58,
653     113, 10,
654     114, 16,
655     115, 16,
656     116, 16,
657     117, 19,
658     117, 20,
659     118, 22,
660     119, 32,
661     119, 31,
662     120, 28,
663     121, 15,
664     122, 32,
665     123, 22,
666     123, 17,
667     123, 18,
668     124, 24,
669     125, 36,
670     126, 36, 
671     127, 36,
672     128, 51,
673     129, 39,
674     130, 43,
675     131, 40,
676     132, 42,
677     201, 44,
678     201, 33,
679     201, 34,
680     202, 41,
681     203, 43,
682     205, 1,  /* bad map */
683     206, 1,  /* bad map */
684     207, 89,
685     208, 1,  /* bad map */
686     209, 80,
687     210, 80,
688     210, 81,
689     211, 84,
690     212, 85,
691     213, 92,
692     214, 90,
693     215, 91,
694     216, 92,
695     217, 63,
696     218, 1,  /* bad map */
697     219, 1,  /* bad map */
698     220, 1,  /* bad map */
699     221, 1,  /* bad map */
700     222, 1,  /* bad map */
701     223, 1,  /* bad map */
702     224, 1,  /* bad map */
703     225, 1,  /* bad map */
704     226, 1,  /* bad map */
705     227, 66,
706     228, 1,  /* bad map */
707     229, 36,
708     230, 83,
709     231, 89,
710     232, 1,
711     233, 1, /* bad map */
712     234, 1, /* bad map */
713     235, 2,
714     236, 3, 
715     237, 82,
716     238, 67,
717     239, 66,
718     240, 1, /* bad map */
719     241, 1, /* bad map */
720     242, 70,
721     243, 1, /* bad map */
722     244, 66,
723     245, 10,
724     246, 10,
725     247, 10,
726     1001, 1, /* bad map */
727     1002, 1, /* bad map */
728     1003, 1, /* bad map */
729     1004, 1, /* bad map */
730     1005, 1, /* bad map */
731     1006, 1, /* bad map */
732     1007, 100,
733     1008, 1, 
734     1009, 1,
735     1010, 3,
736     1011, 3,
737     1012, 3,
738     1013, 3,
739     1014, 3,
740     1015, 3,
741     1015, 3,
742     1016, 3,
743     1017, 3,
744     1018, 2,
745     1019, 2,
746     1020, 2,
747     1021, 3,
748     1022, 3,
749     1023, 3,
750     1024, 16,
751     1025, 3,
752     1026, 64,
753     1027, 1,
754     1028, 65,
755     1029, 1,
756     1040, 1,
757     /* 1041-1065 */
758     1066, 66,
759     1066, 67,
760     0
761 };
762
763 int yaz_diag_bib1_to_srw (int code)
764 {
765     const int *p = srw_bib1_map;
766     while (*p)
767     {
768         if (code == p[0])
769             return p[1];
770         p += 2;
771     }
772     return 1;
773 }
774
775 int yaz_diag_srw_to_bib1(int code)
776 {
777     const int *p = srw_bib1_map;
778     while (*p)
779     {
780         if (code == p[1])
781             return p[0];
782         p += 2;
783     }
784     return 1;
785 }
786
787 /*
788  * Local variables:
789  * c-basic-offset: 4
790  * indent-tabs-mode: nil
791  * End:
792  * vim: shiftwidth=4 tabstop=8 expandtab
793  */
794