Logo Search packages:      
Sourcecode: bibclean version File versions  Download package

isbn.c

/***********************************************************************
 @C-file{
    author              = "Nelson H. F. Beebe",
    version             = "1.01",
    date                = "09 May 1998",
    time                = "22:56:42 MDT",
    filename            = "isbn.c",
    address             = "Center for Scientific Computing
                     University of Utah
                     Department of Mathematics, 322 INSCC
                     155 S 1400 E RM 233
                     Salt Lake City, UT 84112-0090
                     USA",
    telephone           = "+1 801 581 5254",
    FAX                 = "+1 801 585 1640, +1 801 581 4148",
    URL                 = "http://www.math.utah.edu/~beebe",
    checksum            = "54390 923 3137 25116",
    email               = "beebe@math.utah.edu, beebe@acm.org,
                           beebe@ieee.org (Internet)",
    codetable           = "ISO/ASCII",
    keywords            = "bibliography, ISBN, hyphenation",
    supported           = "yes",
    docstring           = "This file contains code for hyphenating
                     International Standard Book Numbers (ISBNs),
                     using the function ISBN_hyphenate(s,t,maxs).
                     No other public objects are defined by this
                     file.

                     If this file is compiled with the
                     preprocessor symbol TEST defined, then a
                     standalone program is produced that can be
                     used to filter test data containing ISBN
                     key/value pairs extracted from BibTeX files.
                     For example, the UNIX commands

                     bibclean -no-warn -max-width 0 *.bib | \
                        grep '^ *ISBN *=' >tmpfile
                     sed -e 's/-//g' tmpfile | ./isbn | diff tmpfile -

                     should display no differences in ISBN
                     numbers, except where their hyphenation was
                     originally incorrect, or missing.

                     The checksum field above contains a CRC-16
                     checksum as the first value, followed by the
                     equivalent of the standard UNIX wc (word
                     count) utility output of lines, words, and
                     characters.  This is produced by Robert
                     Solovay's checksum utility.",
 }
The checksum does not match anymore after Henning Makholm
<henning@makholm.net> updated the ISBN prefix range data in December
2004.
***********************************************************************/

#include <config.h>
#include "xstdlib.h"
#include "xstring.h"
#include "xctype.h"

RCSID("$Id: isbn.c,v 1.4 1999/05/20 13:27:53 beebe Exp beebe $")

#define isISBNdigit(c)  (isdigit(c) || ((c) == 'X') || ((c) == 'x'))

#define MAX_ISBN  14 /* array size for complete ISBN and terminal NUL */

void              ISBN_hyphenate ARGS((char *s_,char *t_,size_t maxs_));

static const char *fix_ISBN ARGS((const char *ISBN_));
static const char *hyphenate_one_ISBN ARGS((const char *prefix_,
                                      const char *ISBN_));
static int        in_ISBN_range ARGS((const char *begin_,
                                  const char *ISBN_,
                                  const char *end_));
static const char       *next_ISBN ARGS((const char *s_, const char **end_));
static void       squeeze_ISBN ARGS((char * out_ISBN_,
                                 const char *in_ISBN_));

#if defined(TEST)

#define MAX_BUF         4096

int               main ARGS((int argc_, char* argv_[]));

#if defined(HAVE_STDC)
int
main(int argc, char* argv[])
#else
int
main(argc,argv)
int argc;
char* argv[];
#endif
{
    char buf[MAX_BUF];
    char buf2[MAX_BUF];

    while (fgets(buf,MAX_BUF,stdin) != (char*)NULL)
    {
      ISBN_hyphenate(buf,buf2,MAX_BUF);
      (void)fputs(buf,stdout);
      (void)fflush(stdout);
    }

    exit (EXIT_SUCCESS);
    return (EXIT_SUCCESS);
}
#endif /* defined(TEST) */

#if defined(HAVE_STDC)
static const char *
next_ISBN(const char *s,const char **next)
#else /* K&R style */
static const char *
next_ISBN(s,next)
const char *s;
const char **next;
#endif
{
    size_t n;
    const char *start;

    while (*s)                      /* scan over s[] */
    {
      for ( ; *s && !isISBNdigit(*s); ++s) /* ignore non-ISBN digits */
          /* NO-OP */;

      for (n = 0, start = s; *s; ++s)     /* scan over ISBN */
      {
          if (isISBNdigit(*s))
          {
            n++;
            if (n == 10)            /* then we found an ISBN */
            {
                *next = s + 1;
                return (start);
            }
          }
          else if ((*s == ' ') || (*s == '-'))
            /* NO-OP */;
          else
            break;
      }
    }
    *next = (const char*)NULL;
    return ((const char*)NULL);           /* no ISBN recognized */
}

    /*******************************************************************
    NB: We intentionally include the hyphen that separates the
    countrygroupnumber from the publishernumber, in order to improve
    readability, even though this complicates the processing in
    ISBN-in-rangep.  Given the position of that hyphen, we automatically
    compute the required hyphen positions.
    *******************************************************************/

#if defined(HAVE_STDC)
static const char *
fix_ISBN(const char *ISBN)
#else /* K&R style */
static const char *
fix_ISBN(ISBN)
const char *ISBN;
#endif
{
    size_t i;

    static struct
    {
      const char *begin;
      const char *end;
    } ISBN_range[] =
    {
     /* Table generated by ./rangecvt.pl; then edited manually */

     /* Australia, Canada (English), Gibraltar, Ireland, New Zealand,
      South Africa, Swaziland, United Kingdom, United States of America,
      Zimbabwe */
     { "0-00",                "0-19" },
     { "0-200",               "0-699" },
     { "0-7000",        "0-8499" },
     { "0-85000",       "0-89999" },
     { "0-900000",            "0-949999" },
     { "0-9500000",           "0-9999999" },

     /* Australia, Canada (English), Gibraltar, Ireland, New Zealand,
      South Africa, Swaziland, United Kingdom, United States of America,
      Zimbabwe */
     { "1-00",                "1-09" },
     { "1-100",               "1-399" },
     { "1-4000",        "1-5499" },
     { "1-55000",       "1-86979" },
     { "1-869800",            "1-998999" },
     { "1-9990000",           "1-9999999" },

     /* Belgium, Canada (French), France, Luxembourg, Switzerland (French) */
     { "2-00",                "2-19" },
     { "2-200",               "2-349" },
     { "2-35000",       "2-39999" },
     { "2-400",               "2-699" },
     { "2-7000",        "2-8399" },
     { "2-84000",       "2-89999" },
     { "2-900000",            "2-949999" },
     { "2-9500000",           "2-9999999" },

     /* Austria, Germany, Switzerland (German) */
     { "3-00",                "3-02" },
     { "3-030",               "3-033" },
     { "3-0340",        "3-0369" },
     { "3-03700",       "3-03999" },
     { "3-04",                "3-19" },
     { "3-200",               "3-699" },
     { "3-7000",        "3-8499" },
     { "3-85000",       "3-89999" },
     { "3-900000",            "3-949999" },
     { "3-9500000",           "3-9999999" },

     /* Japan */
     { "4-00",                "4-19" },
     { "4-200",               "4-699" },
     { "4-7000",        "4-8499" },
     { "4-85000",       "4-89999" },
     { "4-900000",            "4-949999" },
     { "4-9500000",           "4-9999999" },

     /* Azerbaijan, Belarus, Commonwealth of Independent States, Estonia,
      Georgia, Kazakhstan, Kyrgyzstan, Latvia, Lithuania, Tajikistan,
      Turkmenistan, Uzbekistan */
     { "5-00",                "5-19" },
     { "5-200",               "5-699" },
     { "5-7000",        "5-8499" },
     { "5-85000",       "5-89999" },
     { "5-900000",            "5-909999" },
     { "5-91000",       "5-91999" },
     { "5-9200",        "5-9299" },
     { "5-93000",       "5-94999" },
     { "5-9500",        "5-9799" },
     { "5-98000",       "5-98999" },
     { "5-9900000",           "5-9909999" },
     { "5-9910",        "5-9999" },

     /* China */
     { "7-00",                "7-09" },
     { "7-100",               "7-499" },
     { "7-5000",        "7-7999" },
     { "7-80000",       "7-89999" },
     { "7-900000",            "7-999999" },

     /* Czechoslovakia (Czech Republic, Slovakia) */
     { "80-00",               "80-19" },
     { "80-200",        "80-699" },
     { "80-7000",       "80-8499" },
     { "80-85000",            "80-89999" },
     { "80-900000",           "80-999999" },

     /* India */
     { "81-00",               "81-19" },
     { "81-200",        "81-699" },
     { "81-7000",       "81-8499" },
     { "81-85000",            "81-89999" },
     { "81-900000",           "81-999999" },

     /* Norway */
     { "82-00",               "82-19" },
     { "82-200",        "82-699" },
     { "82-7000",       "82-8999" },
     { "82-90000",            "82-98999" },
     { "82-990000",           "82-999999" },

     /* Poland */
     { "83-00",               "83-19" },
     { "83-200",        "83-599" },
     { "83-60000",            "83-69999" },
     { "83-7000",       "83-8499" },
     { "83-85000",            "83-89999" },
     { "83-900000",           "83-999999" },

     /* Spain */
     { "84-00",               "84-19" },
     { "84-200",        "84-699" },
     { "84-7000",       "84-8499" },
     { "84-85000",            "84-89999" },
     { "84-9000",       "84-9199" },
     { "84-920000",           "84-923999" },
     { "84-92400",            "84-92999" },
     { "84-930000",           "84-949999" },
     { "84-95000",            "84-96999" },
     { "84-9700",       "84-9999" },

     /* Brazil */
     { "85-00",               "85-19" },
     { "85-200",        "85-599" },
     { "85-60000",            "85-69999" },
     { "85-7000",       "85-8499" },
     { "85-85000",            "85-89999" },
     { "85-900000",           "85-979999" },
     { "85-98000",            "85-99999" },

     /* Bosnia and Herzegovina, Croatia, Macedonia, Slovenia, Yugoslavia */
     { "86-00",               "86-29" },
     { "86-300",        "86-699" },
     { "86-7000",       "86-7999" },
     { "86-80000",            "86-89999" },
     { "86-900000",           "86-999999" },

     /* Denmark */
     { "87-00",               "87-29" },
     { "87-400",        "87-649" },
     { "87-7000",       "87-7999" },
     { "87-85000",            "87-94999" },
     { "87-970000",           "87-999999" },

     /* Italy, Switzerland (Italian) */
     { "88-00",               "88-19" },
     { "88-200",        "88-599" },
     { "88-6000",       "88-8499" },
     { "88-85000",            "88-89999" },
     { "88-900000",           "88-949999" },
     { "88-95000",            "88-99999" },

     /* Republic of Korea */
     { "89-00",               "89-24" },
     { "89-250",        "89-549" },
     { "89-5500",       "89-8499" },
     { "89-85000",            "89-94999" },
     { "89-950000",           "89-999999" },

     /* Belgium (Flemish), Netherlands */
     { "90-00",               "90-19" },
     { "90-200",        "90-499" },
     { "90-5000",       "90-6999" },
     { "90-70000",            "90-79999" },
     { "90-800000",           "90-849999" },
     { "90-8500",       "90-8999" },
     { "90-900000",           "90-909999" },
     { "90-940000",           "90-949999" },

     /* Sweden */
     { "91-0",                "91-1" },
     { "91-20",               "91-49" },
     { "91-500",        "91-649" },
     { "91-7000",       "91-7999" },
     { "91-85000",            "91-94999" },
     { "91-970000",           "91-999999" },

     /* International Publishers (UNESCO) */
     { "92-0",                "92-5" },
     { "92-60",               "92-79" },
     { "92-800",        "92-899" },
     { "92-9000",       "92-9499" },
     { "92-95000",            "92-98999" },
     { "92-990000",           "92-999999" },

     /* India */
     { "93-0",                "93-0" /* <-no assignments yet */ },

     /* Argentina */
     { "950-00",        "950-49" },
     { "950-500",       "950-899" },
     { "950-9000",            "950-9899" },
     { "950-99000",           "950-99999" },

     /* Finland */
     { "951-0",               "951-1" },
     { "951-20",        "951-54" },
     { "951-550",       "951-889" },
     { "951-8900",            "951-9499" },
     { "951-95000",           "951-99999" },

     /* Finland */
     { "952-00",        "952-19" },
     { "952-200",       "952-499" },
     { "952-5000",            "952-5999" },
     { "952-60",        "952-65" },
     { "952-6600",            "952-6699" },
     { "952-67000",           "952-69999" },
     { "952-7000",            "952-7999" },
     { "952-89",        "952-94" },
     { "952-9500",            "952-9899" },
     { "952-99000",           "952-99999" },

     /* Croatia */
     { "953-0",               "953-0" },
     { "953-10",        "953-14" },
     { "953-150",       "953-599" },
     { "953-6000",            "953-9499" },
     { "953-95000",           "953-99999" },

     /* Bulgaria */
     { "954-00",        "954-29" },
     { "954-300",       "954-799" },
     { "954-8000",            "954-8999" },
     { "954-90000",           "954-92999" },
     { "954-9300",            "954-9999" },

     /* Sri Lanka */
     { "955-0",               "955-0" },
     { "955-1000",            "955-1999" },
     { "955-20",        "955-54" },
     { "955-550",       "955-799" },
     { "955-8000",            "955-9499" },
     { "955-95000",           "955-99999" },

     /* Chile */
     { "956-00",        "956-19" },
     { "956-200",       "956-699" },
     { "956-7000",            "956-9999" },

     /* Taiwan (Republic of China) */
     { "957-00",        "957-02" },
     { "957-0300",            "957-0499" },
     { "957-05",        "957-19" },
     { "957-2000",            "957-2099" },
     { "957-21",        "957-27" },
     { "957-28000",           "957-30999" },
     { "957-31",        "957-43" },
     { "957-440",       "957-819" },
     { "957-8200",            "957-9699" },
     { "957-97000",           "957-99999" },

     /* Colombia */
     { "958-00",        "958-59" },
     { "958-600",       "958-799" },
     { "958-8000",            "958-9499" },
     { "958-95000",           "958-99999" },

     /* Cuba */
     { "959-00",        "959-19" },
     { "959-200",       "959-699" },
     { "959-7000",            "959-8499" },

     /* Greece */
     { "960-00",        "960-19" },
     { "960-200",       "960-659" },
     { "960-6600",            "960-6899" },
     { "960-690",       "960-699" },
     { "960-7000",            "960-8499" },
     { "960-85000",           "960-99999" },

     /* Slovenia */
     { "961-00",        "961-19" },
     { "961-200",       "961-599" },
     { "961-6000",            "961-8999" },
     { "961-90000",           "961-94999" },

     /* Hong Kong */
     { "962-00",        "962-19" },
     { "962-200",       "962-699" },
     { "962-7000",            "962-8499" },
     { "962-85000",           "962-86999" },
     { "962-8700",            "962-8999" },
     { "962-900",       "962-999" },

     /* Hungary */
     { "963-00",        "963-19" },
     { "963-200",       "963-699" },
     { "963-7000",            "963-8499" },
     { "963-85000",           "963-89999" },
     { "963-9000",            "963-9999" },

     /* Iran */
     { "964-00",        "964-29" },
     { "964-300",       "964-549" },
     { "964-5500",            "964-8999" },
     { "964-90000",           "964-96999" },
     { "964-970",       "964-989" },
     { "964-9900",            "964-9999" },

     /* Israel */
     { "965-00",        "965-19" },
     { "965-200",       "965-599" },
     { "965-7000",            "965-7999" },
     { "965-90000",           "965-99999" },

     /* Ukraine */
     { "966-00",        "966-29" },
     { "966-300",       "966-699" },
     { "966-7000",            "966-8999" },
     { "966-90000",           "966-99999" },

     /* Malaysia */
     { "967-0",               "967-5" },
     { "967-60",        "967-89" },
     { "967-900",       "967-989" },
     { "967-9900",            "967-9989" },
     { "967-99900",           "967-99999" },

     /* Mexico */
     { "968-01",        "968-39" },
     { "968-400",       "968-499" },
     { "968-5000",            "968-7999" },
     { "968-800",       "968-899" },

     /* Pakistan */
     { "969-0",               "969-1" },
     { "969-20",        "969-39" },
     { "969-400",       "969-799" },
     { "969-8000",            "969-9999" },

     /* Mexico */
     { "970-01",        "970-59" },
     { "970-600",       "970-899" },
     { "970-9000",            "970-9099" },
     { "970-91000",           "970-96999" },
     { "970-9700",            "970-9999" },

     /* Philippines */
     { "971-000",       "971-019" },
     { "971-02",        "971-02" },
     { "971-0300",            "971-0599" },
     { "971-06",        "971-09" },
     { "971-10",        "971-49" },
     { "971-500",       "971-849" },
     { "971-8500",            "971-9099" },
     { "971-91000",           "971-99999" },

     /* Portugal */
     { "972-0",               "972-1" },
     { "972-20",        "972-54" },
     { "972-550",       "972-799" },
     { "972-8000",            "972-9499" },
     { "972-95000",           "972-99999" },

     /* Romania */
     { "973-0",               "973-1" },
     { "973-20",        "973-54" },
     { "973-550",       "973-759" },
     { "973-7600",            "973-8499" },
     { "973-85000",           "973-89999" },
     { "973-9000",            "973-9499" },
     { "973-95000",           "973-99999" },

     /* Thailand */
     { "974-00",        "974-19" },
     { "974-200",       "974-699" },
     { "974-7000",            "974-8499" },
     { "974-85000",           "974-89999" },
     { "974-90000",           "974-94999" },
     { "974-9500",            "974-9999" },

     /* Turkey */
     { "975-00000",           "975-00999" },
     { "975-01",        "975-24" },
     { "975-250",       "975-599" },
     { "975-6000",            "975-9199" },
     { "975-92000",           "975-98999" },
     { "975-990",       "975-999" },

     /* Caribbean Community (CARICOM): Antigua, Bahamas, Barbados,
        Belize, Dominica, Grenada, Guyana, Jamaica, Montserrat, Saint
        Kitts and Nevis, Saint Lucia, Saint Vincent, Trinidad and Tobago */
     { "976-0",               "976-3" },
     { "976-40",        "976-59" },
     { "976-600",       "976-799" },
     { "976-8000",            "976-9499" },
     { "976-95000",           "976-99999" },

     /* Egypt */
     { "977-00",        "977-19" },
     { "977-200",       "977-499" },
     { "977-5000",            "977-6999" },
     { "977-700",       "977-999" },

     /* Nigeria */
     { "978-000",       "978-199" },
     { "978-2000",            "978-2999" },
     { "978-30000",           "978-79999" },
     { "978-8000",            "978-8999" },
     { "978-900",       "978-999" },

     /* Indonesia */
     { "979-0",               "979-0" },
     { "979-20",        "979-29" },
     { "979-3000",            "979-3999" },
     { "979-400",       "979-799" },
     { "979-8000",            "979-9499" },
     { "979-95000",           "979-99999" },

     /* Venezuela */
     { "980-00",        "980-19" },
     { "980-200",       "980-599" },
     { "980-6000",            "980-9999" },

     /* Singapore */
     { "981-00",        "981-19" },
     { "981-200",       "981-299" },
     { "981-3000",            "981-9999" },

     /* South Pacific: Cook Islands, Fiji, Kiribati, Nauru, Niue,
        Solomon Islands, Tokelau, Tonga, Tuvalu, Vanuatu, Samoa */
     { "982-00",        "982-09" },
     { "982-100",       "982-699" },
     { "982-70",        "982-89" },
     { "982-9000",            "982-9999" },

     /* Malaysia */
     { "983-00",        "983-01" },
     { "983-020",       "983-199" },
     { "983-2000",            "983-3999" },
     { "983-40000",           "983-49999" },
     { "983-50",        "983-79" },
     { "983-800",       "983-899" },
     { "983-9000",            "983-9899" },
     { "983-99000",           "983-99999" },

     /* Bangladesh */
     { "984-00",        "984-39" },
     { "984-400",       "984-799" },
     { "984-8000",            "984-8999" },
     { "984-90000",           "984-99999" },

     /* Belarus */
     { "985-00",        "985-39" },
     { "985-400",       "985-599" },
     { "985-6000",            "985-8999" },
     { "985-90000",           "985-99999" },

     /* Taiwan [also 957] */
     { "986-00",        "986-11" },
     { "986-120",       "986-559" },
     { "986-5600",            "986-7999" },
     { "986-80000",           "986-99999" },

     /* Argentina */
     { "987-00",        "987-09" },
     { "987-1000",            "987-1999" },
     { "987-20000",           "987-29999" },
     { "987-30",        "987-49" },
     { "987-500",       "987-899" },
     { "987-9000",            "987-9499" },
     { "987-95000",           "987-99999" },

     /* Hongkong [also 962] */
     { "988-00",        "988-19" },
     { "988-200",       "988-799" },
     { "988-8000",            "988-9699" },
     { "988-97000",           "988-99999" },

     /* Portugal [also 972] */
     { "989-0",               "989-1" },
     { "989-20",        "989-54" },
     { "989-550",       "989-799" },
     { "989-8000",            "989-9499" },
     { "989-95000",           "989-99999" },

     /* Dominican Republic */
     { "9945-00",       "9945-39" },
     { "9945-400",            "9945-849" },
     { "9945-8500",           "9945-9999" },

     /* North Korea */
     { "9946-0",        "9946-1" },
     { "9946-20",       "9946-39" },
     { "9946-400",            "9946-899" },
     { "9946-9000",           "9946-9999" },

     /* Algeria */
     { "9947-0",        "9947-1" },
     { "9947-20",       "9947-79" },
     { "9947-800",            "9947-999" },

     /* United Arab Emirates */
     { "9948-00",       "9948-39" },
     { "9948-400",            "9948-849" },
     { "9948-8500",           "9948-9999" },

     /* Estonia */
     { "9949-0",        "9949-0" },
     { "9949-10",       "9949-39" },
     { "9949-400",            "9949-899" },
     { "9949-9000",           "9949-9999" },

     /* Palestine */
     { "9950-00",       "9950-29" },
     { "9950-300",            "9950-849" },
     { "9950-8500",           "9950-9999" },

     /* Kosova */
     { "9951-00",       "9951-39" },
     { "9951-400",            "9951-849" },
     { "9951-8500",           "9951-9999" },

     /* Azerbaijan */
     { "9952-0",        "9952-1" },
     { "9952-20",       "9952-39" },
     { "9952-400",            "9952-799" },
     { "9952-8000",           "9952-9999" },

     /* Lebanon */
     { "9953-0",        "9953-0" },
     { "9953-10",       "9953-39" },
     { "9953-400",            "9953-599" },
     { "9953-60",       "9953-89" },
     { "9953-9000",           "9953-9999" },

     /* Morocco */
     { "9954-0",        "9954-1" },
     { "9954-20",       "9954-39" },
     { "9954-400",            "9954-799" },
     { "9954-8000",           "9954-9999" },

     /* Lithuania */
     { "9955-00",       "9955-39" },
     { "9955-400",            "9955-929" },
     { "9955-9300",           "9955-9999" },

     /* Cameroon */
     { "9956-0",        "9956-0" },
     { "9956-10",       "9956-39" },
     { "9956-400",            "9956-899" },
     { "9956-9000",           "9956-9999" },

     /* Jordan */
     { "9957-00",       "9957-39" },
     { "9957-400",            "9957-849" },
     { "9957-8500",           "9957-9999" },

     /* Bosina and Herzegovina */
     { "9958-0",        "9958-0" },
     { "9958-10",       "9958-49" },
     { "9958-500",            "9958-899" },
     { "9958-9000",           "9958-9999" },

     /* Libya */
     { "9959-0",        "9959-1" },
     { "9959-20",       "9959-79" },
     { "9959-800",            "9959-949" },
     { "9959-9500",           "9959-9999" },

     /* Saudi Arabia */
     { "9960-00",       "9960-59" },
     { "9960-600",            "9960-899" },
     { "9960-9000",           "9960-9999" },

     /* Algeria */
     { "9961-0",        "9961-2" },
     { "9961-30",       "9961-69" },
     { "9961-700",            "9961-949" },
     { "9961-9500",           "9961-9999" },

     /* Panama */
     { "9962-00",       "9962-54" },
     { "9962-5500",           "9962-5599" },
     { "9962-56",       "9962-59" },
     { "9962-600",            "9962-849" },
     { "9962-8500",           "9962-9999" },

     /* Cyprus */
     { "9963-0",        "9963-2" },
     { "9963-30",       "9963-54" },
     { "9963-550",            "9963-749" },
     { "9963-7500",           "9963-9999" },

     /* Ghana */
     { "9964-0",        "9964-6" },
     { "9964-70",       "9964-94" },
     { "9964-950",            "9964-999" },

     /* Kazakhstan */
     { "9965-00",       "9965-39" },
     { "9965-400",            "9965-899" },
     { "9965-9000",           "9965-9999" },

     /* Kenya */
     { "9966-00",       "9966-69" },
     { "9966-7000",           "9966-7499" },
     { "9966-750",            "9966-959" },
     { "9966-9600",           "9966-9999" },

     /* Kyrgyzstan */
     { "9967-00",       "9967-39" },
     { "9967-400",            "9967-899" },
     { "9967-9000",           "9967-9999" },

     /* Costa Rica */
     { "9968-00",       "9968-49" },
     { "9968-500",            "9968-939" },
     { "9968-9400",           "9968-9999" },

     /* Uganda  */
     { "9970-00",       "9970-39" },
     { "9970-400",            "9970-899" },
     { "9970-9000",           "9970-9999" },

     /* Singapore */
     { "9971-0",        "9971-5" },
     { "9971-60",       "9971-89" },
     { "9971-900",            "9971-989" },
     { "9971-9900",           "9971-9999" },

     /* Peru */
     { "9972-00",       "9972-09" },
     { "9972-1",        "9972-1" },
     { "9972-200",            "9972-249" },
     { "9972-2500",           "9972-2999" },
     { "9972-30",       "9972-59" },
     { "9972-600",            "9972-899" },
     { "9972-9000",           "9972-9999" },

     /* Tunisia */
     { "9973-0",        "9973-0" },
     { "9973-10",       "9973-69" },
     { "9973-700",            "9973-969" },
     { "9973-9700",           "9973-9999" },

     /* Uruguay */
     { "9974-0",        "9974-2" },
     { "9974-30",       "9974-54" },
     { "9974-550",            "9974-749" },
     { "9974-7500",           "9974-9499" },
     { "9974-95",       "9974-99" },

     /* Moldova */
     { "9975-0",        "9975-4" },
     { "9975-50",       "9975-89" },
     { "9975-900",            "9975-949" },
     { "9975-9500",           "9975-9999" },

     /* Tanzania */
     { "9976-0",        "9976-5" },
     { "9976-60",       "9976-89" },
     { "9976-900",            "9976-989" },
     { "9976-9990",           "9976-9999" },

     /* Costa Rica */
     { "9977-00",       "9977-89" },
     { "9977-900",            "9977-989" },
     { "9977-9900",           "9977-9999" },

     /* Ecuador */
     { "9978-00",       "9978-29" },
     { "9978-300",            "9978-399" },
     { "9978-40",       "9978-94" },
     { "9978-950",            "9978-989" },
     { "9978-9900",           "9978-9999" },

     /* Iceland */
     { "9979-0",        "9979-4" },
     { "9979-50",       "9979-75" },
     { "9979-760",            "9979-899" },
     { "9979-9000",           "9979-9999" },

     /* Papua New Guinea */
     { "9980-0",        "9980-3" },
     { "9980-40",       "9980-89" },
     { "9980-900",            "9980-989" },
     { "9980-9900",           "9980-9999" },

     /* Morocco */
     { "9981-00",       "9981-09" },
     { "9981-100",            "9981-159" },
     { "9981-1600",           "9981-1999" },
     { "9981-20",       "9981-79" },
     { "9981-800",            "9981-949" },
     { "9981-9500",           "9981-9999" },

     /* Zambia */
     { "9982-00",       "9982-79" },
     { "9982-800",            "9982-989" },
     { "9982-9900",           "9982-9999" },

     /* Gambia */
     { "9983-80",       "9983-94" },
     { "9983-950",            "9983-989" },
     { "9983-9900",           "9983-9999" },

     /* Latvia */
     { "9984-00",       "9984-49" },
     { "9984-500",            "9984-899" },
     { "9984-9000",           "9984-9999" },

     /* Estonia */
     { "9985-0",        "9985-4" },
     { "9985-50",       "9985-79" },
     { "9985-800",            "9985-899" },
     { "9985-9000",           "9985-9999" },

     /* Lithuania */
     { "9986-00",       "9986-39" },
     { "9986-400",            "9986-899" },
     { "9986-9000",           "9986-9399" },
     { "9986-940",            "9986-969" },
     { "9986-97",       "9986-99" },

     /* Tanzania */
     { "9987-00",       "9987-39" },
     { "9987-400",            "9987-879" },
     { "9987-8800",           "9987-9999" },

     /* Ghana */
     { "9988-0",        "9988-2" },
     { "9988-30",       "9988-54" },
     { "9988-550",            "9988-749" },
     { "9988-7500",           "9988-9999" },

     /* Macedonia */
     { "9989-0",        "9989-0" },
     { "9989-100",            "9989-199" },
     { "9989-2000",           "9989-2999" },
     { "9989-30",       "9989-59" },
     { "9989-600",            "9989-949" },
     { "9989-9500",           "9989-9999" },

     /* Bahrain */
     { "99901-00",            "99901-49" },
     { "99901-500",           "99901-799" },
     { "99901-80",            "99901-99" },

     /* Mauritius [also 99949] */
     { "99903-0",       "99903-1" },
     { "99903-20",            "99903-89" },
     { "99903-900",           "99903-999" },

     /* Netherlands Antilles */
     { "99904-0",       "99904-5" },
     { "99904-60",            "99904-89" },
     { "99904-900",           "99904-999" },

     /* Bolivia */
     { "99905-0",       "99905-3" },
     { "99905-40",            "99905-79" },
     { "99905-800",           "99905-999" },

     /* Kuwait */
     { "99906-0",       "99906-2" },
     { "99906-30",            "99906-59" },
     { "99906-600",           "99906-699" },
     { "99906-70",            "99906-89" },
     { "99906-9",       "99906-9" },

     /* Malawi */
     { "99908-0",       "99908-0" },
     { "99908-10",            "99908-89" },
     { "99908-900",           "99908-999" },

     /* Malta */
     { "99909-0",       "99909-3" },
     { "99909-40",            "99909-94" },
     { "99909-950",           "99909-999" },

     /* Sierra Leone */
     { "99910-0",       "99910-2" },
     { "99910-30",            "99910-89" },
     { "99910-900",           "99910-999" },

     /* Lesotho */
     { "99911-00",            "99911-59" },
     { "99911-600",           "99911-999" },

     /* Botswana */
     { "99912-0",       "99912-4" },
     { "99912-500",           "99912-599" },
     { "99912-60",            "99912-89" },
     { "99912-900",           "99912-999" },

     /* Andorra */
     { "99913-0",       "99913-2" },
     { "99913-30",            "99913-35" },
     { "99913-600",           "99913-604" },

     /* Suriname */
     { "99914-0",       "99914-4" },
     { "99914-50",            "99914-89" },
     { "99914-900",           "99914-949" },

     /* Maldives */
     { "99915-0",       "99915-4" },
     { "99915-50",            "99915-79" },
     { "99915-800",           "99915-999" },

     /* Namibia [also 99945] */
     { "99916-0",       "99916-2" },
     { "99916-30",            "99916-69" },
     { "99916-700",           "99916-999" },

     /* Brunei Darussalam */
     { "99917-0",       "99917-2" },
     { "99917-30",            "99917-89" },
     { "99917-900",           "99917-999" },

     /* Faroe Islands */
     { "99918-0",       "99918-3" },
     { "99918-40",            "99918-79" },
     { "99918-800",           "99918-999" },

     /* Benin */
     { "99919-0",       "99919-2" },
     { "99919-40",            "99919-69" },
     { "99919-900",           "99919-999" },

     /* Andorra */
     { "99920-0",       "99920-4" },
     { "99920-50",            "99920-89" },
     { "99920-900",           "99920-999" },

     /* Qatar */
     { "99921-0",       "99921-1" },
     { "99921-20",            "99921-69" },
     { "99921-700",           "99921-799" },
     { "99921-8",       "99921-8" },
     { "99921-90",            "99921-99" },

     /* Guatemala */
     { "99922-0",       "99922-3" },
     { "99922-40",            "99922-69" },
     { "99922-700",           "99922-999" },

     /* El Salvador */
     { "99923-0",       "99923-1" },
     { "99923-20",            "99923-79" },
     { "99923-800",           "99923-999" },

     /* Nicaragua */
     { "99924-0",       "99924-2" },
     { "99924-30",            "99924-79" },
     { "99924-800",           "99924-900" },

     /* Paraguay */
     { "99925-0",       "99925-3" },
     { "99925-40",            "99925-79" },
     { "99925-800",           "99925-999" },

     /* Honduras */
     { "99926-0",       "99926-0" },
     { "99926-10",            "99926-59" },
     { "99926-600",           "99926-999" },

     /* Albania [also 99943] */
     { "99927-0",       "99927-2" },
     { "99927-30",            "99927-59" },
     { "99927-600",           "99927-999" },

     /* Georgia [also 99940] */
     { "99928-0",       "99928-0" },
     { "99928-10",            "99928-79" },
     { "99928-800",           "99928-999" },

     /* Mongolia */
     { "99929-0",       "99929-0" /* <-no assignments yet */ },

     /* Armenia [also 99941] */
     { "99930-0",       "99930-4" },
     { "99930-50",            "99930-79" },
     { "99930-800",           "99930-999" },

     /* Seychelles */
     { "99931-0",       "99931-4" },
     { "99931-50",            "99931-79" },
     { "99931-800",           "99931-999" },

     /* Malta [also 99909] */
     { "99932-0",       "99932-0" },
     { "99932-10",            "99932-59" },
     { "99932-600",           "99932-699" },
     { "99932-7",       "99932-7" },
     { "99932-80",            "99932-99" },

     /* Nepal [also 99946] */
     { "99933-0",       "99933-2" },
     { "99933-30",            "99933-59" },
     { "99933-600",           "99933-999" },

     /* Dominican Replublic [also 9945] */
     { "99934-0",       "99934-1" },
     { "99934-20",            "99934-79" },
     { "99934-800",           "99934-999" },

     /* Haiti */
     { "99935-0",       "99935-2" },
     { "99935-30",            "99935-59" },
     { "99935-600",           "99935-799" },
     { "99935-8",       "99935-8" },
     { "99935-90",            "99935-99" },

     /* Bhutan */
     { "99936-0",       "99936-0" },
     { "99936-10",            "99936-59" },
     { "99936-600",           "99936-999" },

     /* Macau */
     { "99937-0",       "99937-1" },
     { "99937-20",            "99937-59" },
     { "99937-600",           "99937-999" },

     /* Srpska */
     { "99938-0",       "99938-2" },
     { "99938-30",            "99938-59" },
     { "99938-600",           "99938-899" },
     { "99938-90",            "99938-99" },

     /* Guatemala [also 99922] */
     { "99939-0",       "99939-5" },
     { "99939-60",            "99939-89" },
     { "99939-900",           "99939-999" },

     /* Georgia [also 99928] */
     { "99940-0",       "99940-0" },
     { "99940-10",            "99940-69" },
     { "99940-700",           "99940-999" },

     /* Armenia [also 99930] */
     { "99941-0",       "99941-2" },
     { "99941-30",            "99941-89" },
     { "99941-900",           "99941-999" },

     /* Sudan */
     { "99942-0",       "99942-4" },
     { "99942-50",            "99942-79" },
     { "99942-800",           "99942-999" },

     /* Albania [also 99927] */
     { "99943-0",       "99943-2" },
     { "99943-30",            "99943-59" },
     { "99943-600",           "99943-999" },

     /* Ethiopia */
     { "99944-0",       "99944-4" },
     { "99944-50",            "99944-79" },
     { "99944-800",           "99944-999" },

     /* Namibia [also 99916] */
     { "99945-0",       "99945-5" },
     { "99945-60",            "99945-89" },
     { "99945-900",           "99945-999" },

     /* Nepal [also 99933] */
     { "99946-0",       "99946-2" },
     { "99946-30",            "99946-59" },
     { "99946-600",           "99946-999" },

     /* Tajikistan */
     { "99947-0",       "99947-0" /* <-no assignments yet */ },

     /* Eritrea */
     { "99948-0",       "99948-4" },
     { "99948-50",            "99948-79" },
     { "99948-800",           "99948-999" },

     /* Mauritius [also 99903] */
     { "99949-0",       "99949-1" },
     { "99949-20",            "99949-89" },
     { "99949-900",           "99949-999" },

     /* Cambodia */
     { "99950-0",       "99950-4" },
     { "99950-50",            "99950-79" },
     { "99950-800",           "99950-999" },

     { (const char*)NULL,     (const char*)NULL }
    };

    for (i = 0; (ISBN_range[i].begin != (const char*)NULL); ++i)
    {
      if (in_ISBN_range(ISBN_range[i].begin, ISBN, ISBN_range[i].end)
          == 0)
          return (hyphenate_one_ISBN(ISBN_range[i].begin, ISBN));
    }
    return ((const char*)NULL);
}

#define skip_non_ISBN_digit(p)    while (*p && !isISBNdigit(*p)) p++

#if defined(HAVE_STDC)
static const char *
hyphenate_one_ISBN(const char *prefix, const char *ISBN)
#else /* K&R style */
static const char *
hyphenate_one_ISBN(prefix,ISBN)
const char *prefix;
const char *ISBN;
#endif
{
    /*******************************************************************
      Given a countrygroupnumber-publishernumber prefix, and an ISBN
      optionally containing spaces and hyphens, return a pointer to an
      unmodifiable properly-hyphenated ISBN stored in an internal buffer
      that is overwritten on subsequent calls, or NULL if the correct
      number of ISBN digits is not found.

      The input ISBN can contain optional leading and trailing text,
      such as a line from a BibTeX .bib file, like this:

       ISBN =         "0-387-09823-2 (paperback)",

     ******************************************************************/

    static char new_ISBN[MAX_ISBN];
    int k;

    skip_non_ISBN_digit(ISBN);

    for (k = 0; *ISBN && (k < (MAX_ISBN - 2)); )
    {
      if (*prefix == '-')
      {
          new_ISBN[k++] = '-';
          prefix++;
      }
      else if (*prefix)
      {
          skip_non_ISBN_digit(ISBN);
          if (*ISBN == '\0')
            break;
          new_ISBN[k++] = *ISBN++;
          prefix++;
          if ((*prefix == '\0') && (k < MAX_ISBN))
            new_ISBN[k++] = '-';
      }
      else              /* past prefix */
      {
          skip_non_ISBN_digit(ISBN);
          if (*ISBN == '\0')
            break;
          new_ISBN[k++] = *ISBN++;
      }
    }
    if ((k == (MAX_ISBN - 2)) && !isISBNdigit(*ISBN))
    {
      new_ISBN[(MAX_ISBN - 2)] = new_ISBN[(MAX_ISBN - 3)];
                        /* move checksum digit to end */
      new_ISBN[(MAX_ISBN - 3)] = '-';     /* prefix it with a hyphen */
      new_ISBN[(MAX_ISBN - 1)] = '\0'; /* terminate the string */
      return ((const char*)&new_ISBN[0]);
    }
    else
      return ((const char*)NULL);
}

#if defined(HAVE_STDC)
void
ISBN_hyphenate(char *s,char *t,size_t maxs)
#else /* K&R style */
void
ISBN_hyphenate(s,t,maxs)
char *s;
char *t;
size_t maxs;
#endif
{
    const char *p;
    const char *r;
    const char *next;
    const char *start;

    /* Given a string s[] containing one or more ISBNs, rewrite the */
    /* string in-place with correct ISBN hyphenation.  Up to maxs-1 */
    /* non-NUL characters of s[] may be used. t[] is workspace, at */
    /* least as large as s[].   If insufficient workspace is */
    /* available, s[] is returned unchanged. */

    t[0] = '\0';

#if defined(__WATCOMC__)
    /* Watcom 10.0 C++ compilers on IBM PC cannot handle the original
       version, which was written that way to avoid compiler warnings,
       sigh... */
    for (p = start = s; (p = next_ISBN(p,&next)) != (const char*)NULL;
       start = p)
#else
    for (p = start = s; (p = next_ISBN(p,&next), p) != (const char*)NULL;
       start = p)
#endif
    {
      if ((strlen(t) + (size_t)(p-start)) >= maxs)
          return;       /* insufficient space: premature return */
      (void)strncat(t,start,(size_t)(p-start));
      r = fix_ISBN(p);
      if (r != (char*)NULL)
      {
          if ((strlen(t) + strlen(r)) >= maxs)
            return;           /* insufficient space: premature return */
          (void)strcat(t,r);
          p = next;
      }
      else
      {
          if ((strlen(t) + 1) >= maxs)
            return;           /* insufficient space: premature return */
          (void)strncat(t,p,1);
          ++p;
      }
    }
    if ((strlen(t) + strlen(start)) >= maxs)
      return;           /* insufficient space: premature return */
    (void)strcat(t,start);
    (void)strcpy(s,t);
}

#if defined(HAVE_STDC)
static int
in_ISBN_range(const char *begin, const char *ISBN, const char *end)
#else /* K&R style */
static int
in_ISBN_range(begin,ISBN,end)
const char *begin;
const char *ISBN;
const char *end;
#endif
{
    /* Compare the countrygroupnumber-publishernumber part of ISBN
       against the range (begin, end), and return -1 (less than),
       0 (in range), or +1 (greater than). */

    char begin_prefix[MAX_ISBN];
    char end_prefix[MAX_ISBN];
    char ISBN_prefix[MAX_ISBN];

    squeeze_ISBN(begin_prefix, begin);
    squeeze_ISBN(ISBN_prefix,ISBN);

    if (strncmp(ISBN_prefix,begin_prefix,strlen(begin_prefix)) < 0)
      return (-1);

    squeeze_ISBN(end_prefix,end);
    if (strncmp(end_prefix,ISBN_prefix,strlen(end_prefix)) < 0)
      return (1);

    return (0);
}

#if defined(HAVE_STDC)
static void
squeeze_ISBN(char * out_ISBN, const char *in_ISBN)
#else /* K&R style */
static void
squeeze_ISBN(out_ISBN,in_ISBN)
char * out_ISBN;
const char *in_ISBN;
#endif
{           /* Copy in_ISBN to out_ISBN, eliminating non-ISBN characters */
    char *limit = out_ISBN + MAX_ISBN;

    for ( ; out_ISBN < limit ; )
    {
      skip_non_ISBN_digit(in_ISBN);
      *out_ISBN = *in_ISBN;
      if (*in_ISBN == '\0')
          break;
      in_ISBN++;
      out_ISBN++;
    }
}

Generated by  Doxygen 1.6.0   Back to index