Implemented function yaz_marc_read_line which parses MARC line format
authorAdam Dickmeiss <adam@indexdata.dk>
Fri, 15 Dec 2006 19:28:45 +0000 (19:28 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Fri, 15 Dec 2006 19:28:45 +0000 (19:28 +0000)
records. There is a wealth of formats out there. So far, this function
reads line records produced by yaz_marc_write_line.
yaz-marcdump's options -x, -X, -I, -e have been replaced with the
more generic and easier to remember(!) options: -i format and -o format
which specifies input format and output format respectively - where
format is one of "marc", "marcxml", "line", "marcxchange".

NEWS
doc/yaz-marcdump-man.xml
include/yaz/marcdisp.h
src/marc_read_line.c
src/marcdisp.c
test/marccol1.u8.1.lst
test/marccol1.u8.2.lst
test/tstmarccol.sh
test/tstmarciso.sh
test/tstmarcxml.sh
util/marcdump.c

diff --git a/NEWS b/NEWS
index d86bad8..02c112e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,12 @@
+Implemented function yaz_marc_read_line which parses MARC line format
+records. There is a wealth of formats out there. So far, this function
+reads line records produced by yaz_marc_write_line.
+
+yaz-marcdump's options -x, -X, -I, -e have been replaced with the
+more generic and easier to remember(!) options: -i format and -o format
+which specifies input format and output format respectively - where
+format is one of "marc", "marcxml", "line", "marcxchange".
+
 Added 'check only' option for MARC utilities. Option -n for yaz-marcdump
 does not print anything except warnings for records.
 
index 8b3daa1..ac6b685 100644 (file)
@@ -8,7 +8,7 @@
      <!ENTITY % common SYSTEM "common/common.ent">
      %common;
 ]>
-<!-- $Id: yaz-marcdump-man.xml,v 1.12 2006-08-28 19:18:02 adam Exp $ -->
+<!-- $Id: yaz-marcdump-man.xml,v 1.13 2006-12-15 19:28:46 adam Exp $ -->
 <refentry id="yaz-marcdump">
  <refentryinfo>
   <productname>YAZ</productname>
  <refsynopsisdiv>
   <cmdsynopsis>
    <command>yaz-marcdump</command>
-   <arg choice="opt"><option>-x</option></arg>
-   <arg choice="opt"><option>-X</option></arg>
-   <arg choice="opt"><option>-e</option></arg>
-   <arg choice="opt"><option>-I</option></arg>
+   <arg choice="opt"><option>-i <replaceable>format</replaceable></option></arg>
+   <arg choice="opt"><option>-o <replaceable>format</replaceable></option></arg>
    <arg choice="opt"><option>-f <replaceable>from</replaceable></option></arg>
    <arg choice="opt"><option>-t <replaceable>to</replaceable></option></arg>
    <arg choice="opt"><option>-l <replaceable>spec</replaceable></option></arg>
@@ -60,8 +58,7 @@
   <para>
    By default, each record is written to standard output in a line
    format with newline for each field, $x for each subfield x.
-   The output format may be changed with options <literal>-X</literal>,
-   <literal>-e</literal>, <literal>-I</literal>.
+   The output format may be changed with option <literal>-o</literal>,
   </para>
   <para>
    <command>yaz-marcdump</command> can also be requested to perform
   
   <variablelist>
    <varlistentry>
-    <term>-x</term>
+    <term>-i <replaceable>format</replaceable></term>
     <listitem><para>
-      Reads MARC records in MARCXML/MarcXchange format. Without
-      this option, <command>yaz-marcdump</command> reads records
-      in ISO2709 format.
+      Specifies input format. Must be one of
+      <literal>marcxml</literal>, <literal>marc</literal> (ISO2709),
+      <literal>line</literal> (line mode MARC).
      </para></listitem>
    </varlistentry>
 
    <varlistentry>
-    <term>-X</term>
+    <term>-o <replaceable>format</replaceable></term>
     <listitem><para>
-      Writes MARC records in MARCXML.
-      This format is equivalent to YAZ_MARC_MARCXML in
-      <filename>yaz/marcdisp.h</filename>.
-     </para></listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>-e</term>
-    <listitem><para>
-      Writes MARC records in MarcXchange format.
-      This format is equivalent to YAZ_MARC_XCHANGE in
-      <filename>yaz/marcdisp.h</filename>.
-     </para></listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>-I</term>
-    <listitem><para>
-      Writes MARC records in ISO2709 format.
-      This format is equivalent to YAZ_MARC_ISO2709 in
-      <filename>yaz/marcdisp.h</filename>.
+      Specifies output format. Must be one of
+      <literal>marcxml</literal>, <literal>marc</literal> (ISO2709),
+      <literal>line</literal> (line mode MARC).
      </para></listitem>
    </varlistentry>
 
    MARC21/USMARC in UTF-8 encoding. Leader offset 9 is set to 'a'.
    Both input and output records are ISO2709 encoded.
    <screen>
-    yaz-marcdump -f MARC-8 -t UTF-8 -I -l 9=97 marc21.raw >marc21.utf8.raw
+    yaz-marcdump -f MARC-8 -t UTF-8 -o marc -l 9=97 marc21.raw >marc21.utf8.raw
    </screen>
   </para>
   <para>
    The same records may be converted to MARCXML instead in UTF-8:
    <screen>
-    yaz-marcdump -f MARC-8 -t UTF-8 -X marc21.raw >marcxml.xml
+    yaz-marcdump -f MARC-8 -t UTF-8 -o marcxml marc21.raw >marcxml.xml
    </screen>
   </para>
  </refsect1> 
index 1b8e818..8805f71 100644 (file)
@@ -24,7 +24,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-/* $Id: marcdisp.h,v 1.22 2006-12-15 12:37:17 adam Exp $ */
+/* $Id: marcdisp.h,v 1.23 2006-12-15 19:28:46 adam Exp $ */
 
 /**
  * \file marcdisp.h
@@ -130,6 +130,16 @@ YAZ_EXPORT void yaz_marc_modify_leader(yaz_marc_t mt, size_t off,
 /** \brief like atoi(3) except that it reads exactly len characters */
 YAZ_EXPORT int atoi_n(const char *buf, int len);
 
+/** \brief like atoi_n but checks for proper formatting
+    \param buf buffer to read values from
+    \param size size of buffer
+    \param val value of decimal number (if successful)
+    \retval 0 no value found (non-digits found)
+    \retval 1 value found and *val holds value
+*/
+YAZ_EXPORT
+int atoi_n_check(const char *buf, int size, int *val);
+
 /** \brief MARC control char: record separator (29 Dec, 1D Hex) */
 #define ISO2709_RS 035
 /** \brief MARC control char: field separator (30 Dec, 1E Hex) */
@@ -334,6 +344,13 @@ void yaz_marc_reset(yaz_marc_t mt);
 YAZ_EXPORT
 int yaz_marc_get_debug(yaz_marc_t mt);
 
+/** \brief convert MARC format type to format type(YAZ_MARC_..)
+    \param arg string
+    \returns -1 if arg is not a known format; YAZ_MARC_.. otherwise (OK)
+*/  
+YAZ_EXPORT
+int yaz_marc_decode_formatstr(const char *arg);
+
 YAZ_END_CDECL
 
 #endif
index c05af1b..90a3521 100644 (file)
@@ -2,12 +2,12 @@
  * Copyright (C) 1995-2006, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: marc_read_line.c,v 1.1 2006-12-15 12:37:18 adam Exp $
+ * $Id: marc_read_line.c,v 1.2 2006-12-15 19:28:47 adam Exp $
  */
 
 /**
- * \file marc_read_iso2709.c
- * \brief Implements reading of MARC as ISO2709
+ * \file marc_read_line.c
+ * \brief Implements reading of MARC in line format
  */
 
 #if HAVE_CONFIG_H
@@ -18,6 +18,7 @@
 #include <windows.h>
 #endif
 
+#include <assert.h>
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <yaz/wrbuf.h>
 #include <yaz/yaz-util.h>
 
+int yaz_gets(int (*getbyte)(void *client_data),
+             void (*ungetbyte)(int b, void *client_data),
+             void *client_data,
+             char *buf, size_t len)
+{
+    size_t sz = 0;
+    int ch = getbyte(client_data);
+    while (ch != '\0' && ch != '\r' && ch != '\n')
+    {
+        if (sz < len-1)
+            buf[sz++] = ch;
+        ch = getbyte(client_data);
+    }
+    if (ch == '\r')
+    {
+        ch = getbyte(client_data);
+        if (ch != '\n' && ch != '\0')
+            ungetbyte(ch, client_data);
+    }
+    else if (ch == '\n')
+    {
+        ch = getbyte(client_data);
+        if (ch != '\r' && ch != '\0')
+            ungetbyte(ch, client_data);
+    }
+    buf[sz] = '\0';
+    if (sz)
+        return 1;
+    return 0;
+}
+    
 int yaz_marc_read_line(yaz_marc_t mt,
                        int (*getbyte)(void *client_data),
                        void (*ungetbyte)(int b, void *client_data),
                        void *client_data)
 {
+    int indicator_length;
+    int identifier_length;
+    int base_address;
+    int length_data_entry;
+    int length_starting;
+    int length_implementation;
+    int marker_ch = 0;
+    int marker_skip = 0;
+    int header_created = 0;
+    char line[4096];
+
     yaz_marc_reset(mt);
 
-    return -1;
+    while (yaz_gets(getbyte, ungetbyte, client_data, line, sizeof(line)))
+    {
+        int val;
+        size_t line_len = strlen(line);
+        /* see if have leader lines of the form:
+           00366nam  22001698a 4500
+        */
+        if (line_len == 0)       /* empty line indicates end of record */
+        {
+            if (header_created)
+                break;
+        }
+        else if (line[0] == '$') /* indicates beginning/end of record */
+        {
+            if (header_created)
+                break;
+        }
+        else if (line[0] == '(') /* annotation, skip it */
+            ;
+        else if (line_len == 24 && atoi_n_check(line, 5, &val) && val >= 24)
+        {
+            if (header_created)
+                break;
+            yaz_marc_set_leader(mt, line,
+                                &indicator_length,
+                                &identifier_length,
+                                &base_address,
+                                &length_data_entry,
+                                &length_starting,
+                                &length_implementation);
+            header_created = 1;
+        }
+        else if (line_len > 5 && memcmp(line, "    ", 4) == 0)
+        {  /* continuation line */
+            ;
+        }
+        else if (line_len > 5 && line[3] == ' ')
+        {
+            char tag[4];
+            char *datafield_start = line+6;
+            marker_ch = 0;
+            marker_skip = 0;
+
+            memcpy(tag, line, 3);
+            tag[3] = '\0';
+            if (line_len >= 8) /* control - or datafield ? */
+            {
+                if (*datafield_start == ' ')
+                    datafield_start++;  /* skip blank after indicator */
+
+                if (strchr("$_*", *datafield_start))
+                {
+                    marker_ch = *datafield_start;
+                    if (datafield_start[2] == ' ')
+                        marker_skip = 1; /* subfields has blank before data */
+                }
+            }
+            if (!header_created)
+            {
+                const char *leader = "01000cam  2200265 i 4500";
+
+                yaz_marc_set_leader(mt, leader,
+                                    &indicator_length,
+                                    &identifier_length,
+                                    &base_address,
+                                    &length_data_entry,
+                                    &length_starting,
+                                    &length_implementation);
+                header_created = 1;
+            }
+
+            if (marker_ch == 0)
+            {   /* control field */
+                yaz_marc_add_controlfield(mt, tag, line+4, strlen(line+4));
+            }
+            else
+            {   /* data field */
+                const char *indicator = line+4;
+                int indicator_len = 2;
+                char *cp = datafield_start;
+
+                yaz_marc_add_datafield(mt, tag, indicator, indicator_len);
+                for (;;)
+                {
+                    char *next;
+                    size_t len;
+                    
+                    assert(cp[0] == marker_ch);
+                    cp++;
+                    next = cp;
+                    while ((next = strchr(next, marker_ch)))
+                    {
+                        if ((next[1] >= 'A' && next[1] <= 'Z')
+                            ||(next[1] >= 'a' && next[1] <= 'z'))
+                        {
+                            if (!marker_skip)
+                                break;
+                            else if (next[2] == ' ')
+                                break;
+                        }
+                        next++;
+                    }
+                    len = strlen(cp);
+                    if (next)
+                        len = next - cp - marker_skip;
+
+                    if (marker_skip)
+                    {
+                        /* remove ' ' after subfield marker */
+                        char *cp_blank = strchr(cp, ' ');
+                        if (cp_blank)
+                        {
+                            len--;
+                            while (cp_blank != cp)
+                            {
+                                cp_blank[0] = cp_blank[-1];
+                                cp_blank--;
+                            }
+                            cp++;
+                        }
+                    }
+                    assert(len >= 0);
+                    assert(len < 399);
+                    yaz_marc_add_subfield(mt, cp, len);
+                    if (!next)
+                        break;
+                    cp = next;
+                }
+            }
+        }
+    }
+    if (!header_created)
+        return -1;
+    return 0;
 }
 
 /*
index 321cd72..54ad37b 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2006, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: marcdisp.c,v 1.38 2006-12-15 12:37:18 adam Exp $
+ * $Id: marcdisp.c,v 1.39 2006-12-15 19:28:47 adam Exp $
  */
 
 /**
@@ -267,10 +267,12 @@ void yaz_marc_add_subfield(yaz_marc_t mt,
     }
 }
 
-static int atoi_n_check(const char *buf, int size, int *val)
+int atoi_n_check(const char *buf, int size, int *val)
 {
-    if (!isdigit(*(const unsigned char *) buf))
-        return 0;
+    int i;
+    for (i = 0; i < size; i++)
+        if (!isdigit(i[(const unsigned char *) buf]))
+            return 0;
     *val = atoi_n(buf, size);
     return 1;
 }
@@ -491,6 +493,7 @@ int yaz_marc_write_line(yaz_marc_t mt, WRBUF wr)
             wrbuf_printf(wr, "%s\n", n->u.leader);
         }
     }
+    wrbuf_puts(wr, "\n");
     return 0;
 }
 
@@ -927,6 +930,20 @@ static int marc_exec_leader(const char *leader_spec, char *leader, size_t size)
     return 0;
 }
 
+int yaz_marc_decode_formatstr(const char *arg)
+{
+    int mode = -1; 
+    if (!strcmp(arg, "marc"))
+        mode = YAZ_MARC_ISO2709;
+    if (!strcmp(arg, "marcxml"))
+        mode = YAZ_MARC_MARCXML;
+    if (!strcmp(arg, "marcxchange"))
+        mode = YAZ_MARC_XCHANGE;
+    if (!strcmp(arg, "line"))
+        mode = YAZ_MARC_LINE;
+    return mode;
+}
+
 /*
  * Local variables:
  * c-basic-offset: 4
index d8fe3e2..ec47cef 100644 (file)
@@ -20,6 +20,7 @@
 880 0  $6 260-02/$1 $a [半田市] : $b 半田市, $c 昭和 43-<59> [1968-<1984>
 880  4 $6 651-03/$1 $a 半田市 (Japan)
 880  4 $6 651-04/$1 $a 半田市 (Japan) $x History $x Sources.
+
 00847nam a2200229 a 4500
 001    75840215 /ACN/r86
 003 DLC
@@ -38,6 +39,7 @@
 880 00 $6 245-01/$1 $a 歷叢.
 880 0  $6 260-02/$1 $a [高雄市] : $b 文化院 : $b 發行所 聖書 出版社, $c <民國63-66   [1974-1977   >
 880 20 $6 710-03/$1 $a 高雄市  文化院.
+
 01020nam a2200277 a 4500
 001    84226659 /ACN
 003 DLC
@@ -60,6 +62,7 @@
 880    $6 250-02/$1 $a 第1版.
 880 0  $6 260-03/$1 $a 成都 : $b 四川 人民 出版社 : $b 四川省 新华 书店 发行, $c 1983.
 880  0 $6 440-04/$1 $a 德育 丛书
+
 01336cam a2200349 a 4500
 001    84231405 
 003 DLC
@@ -88,6 +91,7 @@
 880 24 $6 610-04/$1 $a 中国 共产党 $x Party work.
 880 2  $6 710-05/$1 $a 辽宁 人氱 出版社.
 987    $a PINYIN $b CStRLIN $c 20001212 $d c $e 1.0
+
 00916nam a2200241 a 4500
 001    85174785 /ACN
 003 DLC
 880 00 $6 245-01/$1 $a 河北 氱间 故事 选 / $c [插图 张 文学].
 880    $6 250-02/$1 $a 新1版.
 880 0  $6 260-03/$1 $a 石家庄 : $b 花山 文艺 出版社 : $b 河北省 新華 書店 叱行, $c 1983.
+
 01171nam a2200325 a 4500
 001    86116930 /ACN
 003 DLC
 880    $6 250-03/$1 $a 第1版.
 880 0  $6 260-04/$1 $a 合肥市 : $b 安徽 文艺 出版社 : $b 安徽省 新華 書店 发行, $c 1984.
 880  0 $6 440-05/$1 $a 青年 文学 丛书
+
 01437nam a2200301 a 4500
 001    86117080 /ACN
 003 DLC
 880    $6 250-02/$1 $a 第1版.
 880 0  $6 260-03/$1 $a 西安 : $b 陕西 秱学 技术 出版社 : $b 陕西省 新華 書店 叱行, $c 1985.
 880 20 $6 710-04/$1 $a 国家 地震局 兰州 地震 研究所.
+
 01289cam a2200337 a 4500
 001    86118651 /ACN/r88
 003 DLC
 880    $6 250-03/$1 $a 初版.
 880 0  $6 260-04/$1 $a 台北市 : $b 名山 出版社, $c 氱國74 [1985]
 880 10 $6 700-05/$1 $a 黃 釱仙.
+
 00995nam a2200289 a 4500
 001    86118679 /ACN
 003 DLC
 880    $6 250-03/$1 $a 初版.
 880 0  $6 260-04/$1 $a 台北市 : $b 皇冠 出版社, $c 民國74 [1985]
 880  0 $6 440-05/$1 $a 皇冠 叢書 ; $v 第1143種
+
 01365cam a2200361 a 4500
 001    86119726 
 003 DLC
 880 1  $6 700-04/$1 $a 周 宝珠.
 880 1  $6 700-05/$1 $a 陈 振.
 987    $a PINYIN $b CStRLIN $c 20001214 $d c $e 1.0
+
 01069nam a2200289 a 4500
 001    86122256 /ACN
 003 DLC
 880 10 $6 245-02/$1 $a 中国 现代 诗歌 论 / $c [骆 寒超].
 880    $6 250-03/$1 $a 第1版.
 880 0  $6 260-04/$1 $a [南京市] : $b 江苏 人氱 出版社 : $b 江苏省 新華 書店 叱行, $c 1984.
+
 01194nam a2200325 a 4500
 001    86124008 /ACN
 003 DLC
 880    $6 250-03/$1 $a 第1版.
 880 0  $6 260-04/$1 $a 乌鲁木齐市 : $b 新疆 人民 出版社 : $b 新疆 新華 書店 发行, $c 1985.
 880  0 $6 440-05/$1 $a 祖国 大家庭 丛书
+
 01192cam a2200313 a 4500
 001    86124229 
 003 DLC
 880    $6 260-04/$1 $a 北京 : $b 人民 文学 出版社 : $b 新华 书店 北京 发行所 发行, $c 1985.
 880  0 $6 440-05/$1 $a 中国 小说 史料 丛书
 987    $a PINYIN $b CStRLIN $c 20001214 $d c $e 1.0
+
 01470cam a2200349 a 4500
 001    86124531 /ACN/r93
 003 DLC
 880    $6 250-02/$1 $a 第1版.
 880    $6 260-03/$1 $a 上海 : $b 上海 人氱 出版社 : $b 新華 書店 上海 叱行所 叱行, $c 1985.
 880 20 $6 710-04/$1 $a 中共 上海 市委. $b 宣传部.
+
 01072nam a2200301 a 4500
 001    86125160 /ACN
 003 DLC
 880    $6 250-03/$1 $a 第1版.
 880 0  $6 260-04/$1 $a 北京 : $b 北京 十月 文艺 出版社 : $b 新华 书店 北京 叱行所 叱行, $c 1985.
 880  0 $6 440-05/$1 $a 红叶 诗丛
+
 01248nam a2200301 a 4500
 001    86125348 /ACN
 003 DLC
 880 0  $6 260-03/$1 $a [臺北縣 永和市] : $b 文海 出版社, $c 民國74 [1985]
 880 1  $6 490-04/$1 $a 近代 中國 史料 叢刊 三編 : 第二輯 ; $v 20
 880  0 $6 830-05/$1 $a 近代 中國 史料 叢刊 三編 ; $v 20.
+
 01116cam a2200325 a 4500
 001    86125443 
 003 DLC
 880    $6 250-03/$1 $a 初版.
 880    $6 260-04/$1 $a 台北市 : $b 世界 書局, $c 氱國74 [1985]
 987    $a PINYIN $b DLC $c 20020326 $d c
+
 01199nam a2200301 a 4500
 001    86154542 /ACN/r86
 003 DLC
 880    $6 250-02/$1 $a 第1版.
 880 0  $6 260-03/$1 $a [长春市] : $b 吉林 人民 出版社 : $b 吉林省 新华 书店 发行, $c 1985.
 880 10 $6 700-04/$1 $a 虞 祖尧.
+
 00920nam a2200253 a 4500
 001    86159478 /AK
 003 DLC
 880 10 $6 245-02/$1 $a 들어라, 딸들 아 : $b 김 동길 대표 에세이.
 880 0  $6 260-03/$1 $a 서울 : $b 청년사, $c 1984 $g (1985 printing)
 880  0 $6 440-04/$1 $a 우리 시대 의 대표 산문선 ; $v 1
+
index dc0398f..557fdef 100644 (file)
@@ -20,6 +20,7 @@
 880 0  $6 260-02/$1 $a [半田市] : $b 半田市, $c 昭和 43-<59> [1968-<1984>
 880  4 $6 651-03/$1 $a 半田市 (Japan)
 880  4 $6 651-04/$1 $a 半田市 (Japan) $x History $x Sources.
+
 00885nam a2200229 a 4500
 001    75840215 /ACN/r86
 003 DLC
@@ -38,6 +39,7 @@
 880 00 $6 245-01/$1 $a 歷叢.
 880 0  $6 260-02/$1 $a [高雄市] : $b 文化院 : $b 發行所 聖書 出版社, $c <民國63-66   [1974-1977   >
 880 20 $6 710-03/$1 $a 高雄市  文化院.
+
 01054nam a2200277 a 4500
 001    84226659 /ACN
 003 DLC
@@ -60,6 +62,7 @@
 880    $6 250-02/$1 $a 第1版.
 880 0  $6 260-03/$1 $a 成都 : $b 四川 人民 出版社 : $b 四川省 新华 书店 发行, $c 1983.
 880  0 $6 440-04/$1 $a 德育 丛书
+
 01390cam a2200349 a 4500
 001    84231405 
 003 DLC
@@ -88,6 +91,7 @@
 880 24 $6 610-04/$1 $a 中国 共产党 $x Party work.
 880 2  $6 710-05/$1 $a 辽宁 人氱 出版社.
 987    $a PINYIN $b CStRLIN $c 20001212 $d c $e 1.0
+
 00953nam a2200241 a 4500
 001    85174785 /ACN
 003 DLC
 880 00 $6 245-01/$1 $a 河北 氱间 故事 选 / $c [插图 张 文学].
 880    $6 250-02/$1 $a 新1版.
 880 0  $6 260-03/$1 $a 石家庄 : $b 花山 文艺 出版社 : $b 河北省 新華 書店 叱行, $c 1983.
+
 01219nam a2200325 a 4500
 001    86116930 /ACN
 003 DLC
 880    $6 250-03/$1 $a 第1版.
 880 0  $6 260-04/$1 $a 合肥市 : $b 安徽 文艺 出版社 : $b 安徽省 新華 書店 发行, $c 1984.
 880  0 $6 440-05/$1 $a 青年 文学 丛书
+
 01502nam a2200301 a 4500
 001    86117080 /ACN
 003 DLC
 880    $6 250-02/$1 $a 第1版.
 880 0  $6 260-03/$1 $a 西安 : $b 陕西 学 技术 出版社 : $b 陕西省 新華 書店 叱行, $c 1985.
 880 20 $6 710-04/$1 $a 国家 地震局 兰州 地震 研究所.
+
 01333cam a2200337 a 4500
 001    86118651 /ACN/r88
 003 DLC
 880    $6 250-03/$1 $a 初版.
 880 0  $6 260-04/$1 $a 台北市 : $b 名山 出版社, $c 氱國74 [1985]
 880 10 $6 700-05/$1 $a 黃 釱仙.
+
 01051nam a2200289 a 4500
 001    86118679 /ACN
 003 DLC
 880    $6 250-03/$1 $a 初版.
 880 0  $6 260-04/$1 $a 台北市 : $b 皇冠 出版社, $c 民國74 [1985]
 880  0 $6 440-05/$1 $a 皇冠 叢書 ; $v 第1143種
+
 01437cam a2200361 a 4500
 001    86119726 
 003 DLC
 880 1  $6 700-04/$1 $a 周 宝珠.
 880 1  $6 700-05/$1 $a 陈 振.
 987    $a PINYIN $b CStRLIN $c 20001214 $d c $e 1.0
+
 01114nam a2200289 a 4500
 001    86122256 /ACN
 003 DLC
 880 10 $6 245-02/$1 $a 中国 现代 诗歌 论 / $c [骆 寒超].
 880    $6 250-03/$1 $a 第1版.
 880 0  $6 260-04/$1 $a [南京市] : $b 江苏 人氱 出版社 : $b 江苏省 新華 書店 叱行, $c 1984.
+
 01244nam a2200325 a 4500
 001    86124008 /ACN
 003 DLC
 880    $6 250-03/$1 $a 第1版.
 880 0  $6 260-04/$1 $a 乌鲁木齐市 : $b 新疆 人民 出版社 : $b 新疆 新華 書店 发行, $c 1985.
 880  0 $6 440-05/$1 $a 祖国 大家庭 丛书
+
 01252cam a2200313 a 4500
 001    86124229 
 003 DLC
 880    $6 260-04/$1 $a 北京 : $b 人民 文学 出版社 : $b 新华 书店 北京 发行所 发行, $c 1985.
 880  0 $6 440-05/$1 $a 中国 小说 史料 丛书
 987    $a PINYIN $b CStRLIN $c 20001214 $d c $e 1.0
+
 01516cam a2200349 a 4500
 001    86124531 /ACN/r93
 003 DLC
 880    $6 250-02/$1 $a 第1版.
 880    $6 260-03/$1 $a 上海 : $b 上海 人氱 出版社 : $b 新華 書店 上海 叱行所 叱行, $c 1985.
 880 20 $6 710-04/$1 $a 中共 上海 市委. $b 宣传部.
+
 01121nam a2200301 a 4500
 001    86125160 /ACN
 003 DLC
 880    $6 250-03/$1 $a 第1版.
 880 0  $6 260-04/$1 $a 北京 : $b 北京 十月 文艺 出版社 : $b 新华 书店 北京 叱行所 叱行, $c 1985.
 880  0 $6 440-05/$1 $a 红叶 诗丛
+
 01301nam a2200301 a 4500
 001    86125348 /ACN
 003 DLC
 880 0  $6 260-03/$1 $a [臺北縣 永和市] : $b 文海 出版社, $c 民國74 [1985]
 880 1  $6 490-04/$1 $a 近代 中國 史料 叢刊 三編 : 第二輯 ; $v 20
 880  0 $6 830-05/$1 $a 近代 中國 史料 叢刊 三編 ; $v 20.
+
 01158cam a2200325 a 4500
 001    86125443 
 003 DLC
 880    $6 250-03/$1 $a 初版.
 880    $6 260-04/$1 $a 台北市 : $b 世界 書局, $c 氱國74 [1985]
 987    $a PINYIN $b DLC $c 20020326 $d c
+
 01247nam a2200301 a 4500
 001    86154542 /ACN/r86
 003 DLC
 880    $6 250-02/$1 $a 第1版.
 880 0  $6 260-03/$1 $a [长春市] : $b 吉林 人民 出版社 : $b 吉林省 新华 书店 发行, $c 1985.
 880 10 $6 700-04/$1 $a 虞 祖尧.
+
 00951nam a2200253 a 4500
 001    86159478 /AK
 003 DLC
 880 10 $6 245-02/$1 $a 들어라, 딸들 아 : $b 김 동길 대표 에세이.
 880 0  $6 260-03/$1 $a 서울 : $b 청년사, $c 1984 $g (1985 printing)
 880  0 $6 440-04/$1 $a 우리 시대 의 대표 산문선 ; $v 1
+
index f201ae3..f7d1ce4 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# $Id: tstmarccol.sh,v 1.1 2006-08-28 12:34:42 adam Exp $
+# $Id: tstmarccol.sh,v 1.2 2006-12-15 19:28:47 adam Exp $
 # Tests reading of a bunch of non-roman UTF-8 ISO2709 and see if
 # we can encode it in MARC-8
 #
@@ -32,7 +32,7 @@ for f in ${srcdir}/marccol?.u8.marc; do
     fi
 
     filem=`echo $fb | sed 's/u8/m8/'`.marc
-    ../util/yaz-marcdump -I -f utf8 -t marc8 $f >$filem
+    ../util/yaz-marcdump -o marc -f utf8 -t marc8 $f >$filem
 
     DIFF=${fb}.2.lst.diff
     NEW=${fb}.2.lst.new
index 0ff5022..e4d56ea 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# $Id: tstmarciso.sh,v 1.3 2006-08-28 12:34:42 adam Exp $
+# $Id: tstmarciso.sh,v 1.4 2006-12-15 19:28:47 adam Exp $
 # Tests reading of ISO2709 and checks that we get identical MARCXML
 # 
 # Reads marc?.marc files , Generates marc?.xml files
@@ -11,7 +11,7 @@ for f in ${srcdir}/marc?.marc; do
     NEW=${fb}.new.xml
     OLD=${srcdir}/${fb}.xml
     DIFF=`basename ${f}`.diff
-    ../util/yaz-marcdump -f `cat $CHR` -t utf-8 -X $f > $NEW
+    ../util/yaz-marcdump -f `cat $CHR` -t utf-8 -o marcxml $f > $NEW
     if test $? != "0"; then
        echo "$f: yaz-marcdump returned error"
        ecode=1
@@ -25,7 +25,7 @@ for f in ${srcdir}/marc?.marc; do
        fi
     else
        echo "$f: Making test result $OLD for the first time"
-       if test -x /usr/bin/xmllint; then
+       if test -i marcxml /usr/bin/xmllint; then
            if xmllint --noout $NEW >out 2>stderr; then
                echo "$f: $NEW is well-formed"
                mv $NEW $OLD
index b18a3a8..6093628 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# $Id: tstmarcxml.sh,v 1.3 2006-08-28 12:34:42 adam Exp $
+# $Id: tstmarcxml.sh,v 1.4 2006-12-15 19:28:47 adam Exp $
 # Tests reading of MARCXML and checks that we get identical ISO2709 output.
 #
 # Reads marc?.xml files , Generates marc?.xml.marc files
@@ -14,7 +14,7 @@ for f in ${srcdir}/marc?.xml; do
     NEW=`basename ${f}`.new.marc
     OLD=${f}.marc
     DIFF=`basename ${f}`.diff
-    ../util/yaz-marcdump -f utf-8 -t utf-8 -x -I $f > $NEW
+    ../util/yaz-marcdump -f utf-8 -t utf-8 -i marcxml -o marc $f > $NEW
     if test $? != "0"; then
        echo "Failed decode of $f"
        ecode=1
index 040a51b..254c2d4 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2006, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: marcdump.c,v 1.44 2006-12-07 11:08:05 adam Exp $
+ * $Id: marcdump.c,v 1.45 2006-12-15 19:28:48 adam Exp $
  */
 
 #define _FILE_OFFSET_BITS 64
@@ -50,11 +50,52 @@ static char *prog;
 
 static void usage(const char *prog)
 {
-    fprintf (stderr, "Usage: %s [-c cfile] [-f from] [-t to] [-x] [-X] [-e] "
-             "[-I] [-n] [-l pos=value] [-v] [-C chunk] [-s splitfname] file...\n",
+    fprintf (stderr, "Usage: %s [-c cfile] [-f from] [-t to] "
+             "[-i format] [-o format] "
+             "[-n] [-l pos=value] [-v] [-C chunk] [-s splitfname] file...\n",
              prog);
 } 
 
+static int getbyte_stream(void *client_data)
+{
+    FILE *f = (FILE*) client_data;
+
+    int c = fgetc(f);
+    if (c == EOF)
+        return 0;
+    return c;
+}
+
+static void ungetbyte_stream(int c, void *client_data)
+{
+    FILE *f = (FILE*) client_data;
+
+    if (c == 0)
+        c = EOF;
+    ungetc(c, f);
+}
+
+static void marcdump_read_line(yaz_marc_t mt, const char *fname)
+{
+    FILE *inf = fopen(fname, "rb");
+    if (!inf)
+    {
+        fprintf (stderr, "%s: cannot open %s:%s\n",
+                 prog, fname, strerror (errno));
+        exit(1);
+    }
+    
+    while (yaz_marc_read_line(mt, getbyte_stream,
+                              ungetbyte_stream, inf) == 0)
+    {
+        WRBUF wrbuf = wrbuf_alloc();
+        yaz_marc_write_mode(mt, wrbuf);
+        fputs(wrbuf_buf(wrbuf), stdout);
+        wrbuf_free(wrbuf, 1);
+    }
+    fclose(inf);
+}
+
 #if YAZ_HAVE_XML2
 static void marcdump_read_xml(yaz_marc_t mt, const char *fname)
 {
@@ -84,7 +125,7 @@ static void marcdump_read_xml(yaz_marc_t mt, const char *fname)
 #endif
 
 static void dump(const char *fname, const char *from, const char *to,
-                 int read_xml, int xml,
+                 int input_format, int output_format,
                  int print_offset, const char *split_fname, int split_chunk,
                  int verbose, FILE *cfile, const char *leader_spec)
 {
@@ -109,18 +150,20 @@ static void dump(const char *fname, const char *from, const char *to,
         }
         yaz_marc_iconv(mt, cd);
     }
-    yaz_marc_xml(mt, xml);
+    yaz_marc_xml(mt, output_format);
     yaz_marc_debug(mt, verbose);
 
-    if (read_xml)
+    if (input_format == YAZ_MARC_MARCXML || input_format == YAZ_MARC_XCHANGE)
     {
 #if YAZ_HAVE_XML2
         marcdump_read_xml(mt, fname);
-#else
-        return;
 #endif
     }
-    else
+    else if (input_format == YAZ_MARC_LINE)
+    {
+        marcdump_read_line(mt, fname);
+    }
+    else if (input_format == YAZ_MARC_ISO2709)
     {
         FILE *inf = fopen(fname, "rb");
         int num = 1;
@@ -265,10 +308,10 @@ int main (int argc, char **argv)
     char *arg;
     int verbose = 0;
     int no = 0;
-    int xml = 0;
+    int output_format = YAZ_MARC_LINE;
     FILE *cfile = 0;
     char *from = 0, *to = 0;
-    int read_xml = 0;
+    int input_format = YAZ_MARC_ISO2709;
     int split_chunk = 1;
     const char *split_fname = 0;
     const char *leader_spec = 0;
@@ -283,11 +326,27 @@ int main (int argc, char **argv)
 #endif
 
     prog = *argv;
-    while ((r = options("C:npvc:xOeXIf:t:s:l:", argv, argc, &arg)) != -2)
+    while ((r = options("i:o:C:npvc:xOeXIf:t:s:l:", argv, argc, &arg)) != -2)
     {
         no++;
         switch (r)
         {
+        case 'i':
+            input_format = yaz_marc_decode_formatstr(arg);
+            if (input_format == -1)
+            {
+                fprintf(stderr, "%s: bad input format: %s\n", prog, arg);
+                exit(1);
+            }
+            break;
+        case 'o':
+            output_format = yaz_marc_decode_formatstr(arg);
+            if (output_format == -1)
+            {
+                fprintf(stderr, "%s: bad output format: %s\n", prog, arg);
+                exit(1);
+            }
+            break;
         case 'l':
             leader_spec = arg;
             break;
@@ -303,13 +362,9 @@ int main (int argc, char **argv)
             cfile = fopen(arg, "w");
             break;
         case 'x':
-#if YAZ_HAVE_XML2
-            read_xml = 1;
-#else
-            fprintf(stderr, "%s: -x not supported."
-                    " YAZ not compiled with Libxml2 support\n", prog);
-            exit(3);
-#endif
+            fprintf(stderr, "%s: -x no longer supported. "
+                    "Use -i marcxml instead\n", prog);
+            exit(1);
             break;
         case 'O':
             fprintf(stderr, "%s: OAI MARC no longer supported."
@@ -317,16 +372,22 @@ int main (int argc, char **argv)
             exit(1);
             break;
         case 'e':
-            xml = YAZ_MARC_XCHANGE;
+            fprintf(stderr, "%s: -e no longer supported. "
+                    "Use -o marcxchange instead\n", prog);
+            exit(1);
             break;
         case 'X':
-            xml = YAZ_MARC_MARCXML;
+            fprintf(stderr, "%s: -X no longer supported. "
+                    "Use -o marcxml instead\n", prog);
+            exit(1);
             break;
         case 'I':
-            xml = YAZ_MARC_ISO2709;
+            fprintf(stderr, "%s: -I no longer supported. "
+                    "Use -o marc instead\n", prog);
+            exit(1);
             break;
         case 'n':
-            xml = YAZ_MARC_CHECK;
+            output_format = YAZ_MARC_CHECK;
             break;
         case 'p':
             print_offset = 1;
@@ -338,7 +399,7 @@ int main (int argc, char **argv)
             split_chunk = atoi(arg);
             break;
         case 0:
-            dump(arg, from, to, read_xml, xml,
+            dump(arg, from, to, input_format, output_format,
                  print_offset, split_fname, split_chunk,
                  verbose, cfile, leader_spec);
             break;
@@ -347,7 +408,7 @@ int main (int argc, char **argv)
             break;
         default:
             usage(prog);
-            exit (1);
+            exit(1);
         }
     }
     if (cfile)