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