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