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