~ubuntu-branches/ubuntu/saucy/haskell-hs-bibutils/saucy

« back to all changes in this revision

Viewing changes to bibutils/copacin.c

  • Committer: Package Import Robot
  • Author(s): Joachim Breitner
  • Date: 2011-09-26 17:57:15 UTC
  • Revision ID: package-import@ubuntu.com-20110926175715-muzp5giy0rzonss2
Tags: upstream-4.12
ImportĀ upstreamĀ versionĀ 4.12

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * copacin.c
 
3
 *
 
4
 * Copyright (c) Chris Putnam 2004-2010
 
5
 *
 
6
 * Program and source code released under the GPL
 
7
 *
 
8
 */
 
9
#include <stdio.h>
 
10
#include <stdlib.h>
 
11
#include <string.h>
 
12
#include "is_ws.h"
 
13
#include "newstr.h"
 
14
#include "newstr_conv.h"
 
15
#include "list.h"
 
16
#include "name.h"
 
17
#include "title.h"
 
18
#include "fields.h"
 
19
#include "reftypes.h"
 
20
#include "serialno.h"
 
21
#include "copacin.h"
 
22
 
 
23
void
 
24
copacin_initparams( param *p, const char *progname )
 
25
{
 
26
        p->readformat       = BIBL_COPACIN;
 
27
        p->charsetin        = BIBL_CHARSET_DEFAULT;
 
28
        p->charsetin_src    = BIBL_SRC_DEFAULT;
 
29
        p->latexin          = 0;
 
30
        p->xmlin            = 0;
 
31
        p->utf8in           = 0;
 
32
        p->nosplittitle     = 0;
 
33
        p->verbose          = 0;
 
34
        p->addcount         = 0;
 
35
 
 
36
        p->readf    = copacin_readf;
 
37
        p->processf = copacin_processf;
 
38
        p->cleanf   = NULL;
 
39
        p->typef    = NULL;
 
40
        p->convertf = copacin_convertf;
 
41
        p->all      = copac_all;
 
42
        p->nall     = copac_nall;
 
43
 
 
44
        list_init( &(p->asis) );
 
45
        list_init( &(p->corps) );
 
46
 
 
47
        if ( !progname ) p->progname = NULL;
 
48
        else p->progname = strdup( progname );
 
49
}
 
50
 
 
51
/* Endnote-Refer/Copac tag definition:
 
52
    character 1 = alphabetic character
 
53
    character 2 = alphabetic character
 
54
    character 3 = dash
 
55
    character 4 = space
 
56
*/
 
57
static int
 
58
copacin_istag( char *buf )
 
59
{
 
60
        if (! ((buf[0]>='A' && buf[0]<='Z')) || (buf[0]>='a' && buf[0]<='z') )
 
61
                return 0;
 
62
        if (! ((buf[1]>='A' && buf[1]<='Z')) || (buf[1]>='a' && buf[1]<='z') )
 
63
                return 0;
 
64
        if (buf[2]!='-' ) return 0;
 
65
        if (buf[3]!=' ' ) return 0;
 
66
        return 1; 
 
67
}
 
68
static int
 
69
readmore( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line )
 
70
{
 
71
        if ( line->len ) return 1;
 
72
        else return newstr_fget( fp, buf, bufsize, bufpos, line );
 
73
}
 
74
 
 
75
int
 
76
copacin_readf( FILE *fp, char *buf, int bufsize, int *bufpos, newstr *line, newstr *reference, int *fcharset )
 
77
{
 
78
        int haveref = 0, inref=0;
 
79
        char *p;
 
80
        *fcharset = CHARSET_UNKNOWN;
 
81
        while ( !haveref && readmore( fp, buf, bufsize, bufpos, line ) ) {
 
82
                /* blank line separates */
 
83
                if ( line->data==NULL ) continue;
 
84
                if ( inref && line->len==0 ) haveref=1; 
 
85
                p = &(line->data[0]);
 
86
                /* Recognize UTF8 BOM */
 
87
                if ( line->len > 2 &&
 
88
                                (unsigned char)(p[0])==0xEF &&
 
89
                                (unsigned char)(p[1])==0xBB &&
 
90
                                (unsigned char)(p[2])==0xBF ) {
 
91
                        *fcharset = CHARSET_UNICODE;
 
92
                        p += 3;
 
93
                }
 
94
                if ( copacin_istag( p ) ) {
 
95
                        if ( inref ) newstr_addchar( reference, '\n' );
 
96
                        newstr_strcat( reference, p );
 
97
                        newstr_empty( line );
 
98
                        inref = 1;
 
99
                } else if ( inref ) {
 
100
                        if ( p ) {
 
101
                                /* copac puts tag only on 1st line */
 
102
                                newstr_addchar( reference, ' ' );
 
103
                                if ( *p ) p++;
 
104
                                if ( *p ) p++;
 
105
                                if ( *p ) p++;
 
106
                                newstr_strcat( reference, p );
 
107
                        }
 
108
                        newstr_empty( line );
 
109
                } else {
 
110
                        newstr_empty( line );
 
111
                }
 
112
        }
 
113
        return haveref;
 
114
}
 
115
 
 
116
static char*
 
117
copacin_addtag2( char *p, newstr *tag, newstr *data )
 
118
{
 
119
        int  i;
 
120
        i =0;
 
121
        while ( i<3 && *p ) {
 
122
                newstr_addchar( tag, *p++ );
 
123
                i++;
 
124
        }
 
125
        while ( *p==' ' || *p=='\t' ) p++;
 
126
        while ( *p && *p!='\r' && *p!='\n' ) {
 
127
                newstr_addchar( data, *p );
 
128
                p++;
 
129
        }
 
130
        newstr_trimendingws( data );
 
131
        while ( *p=='\n' || *p=='\r' ) p++;
 
132
        return p;
 
133
}
 
134
 
 
135
static char *
 
136
copacin_nextline( char *p )
 
137
{
 
138
        while ( *p && *p!='\n' && *p!='\r') p++;
 
139
        while ( *p=='\n' || *p=='\r' ) p++;
 
140
        return p;
 
141
}
 
142
 
 
143
int
 
144
copacin_processf( fields *copacin, char *p, char *filename, long nref )
 
145
{
 
146
        newstr tag, data;
 
147
        newstr_init( &tag );
 
148
        newstr_init( &data );
 
149
        while ( *p ) {
 
150
                p = skip_ws( p );
 
151
                if ( copacin_istag( p ) ) {
 
152
                        p = copacin_addtag2( p, &tag, &data );
 
153
                        /* don't add empty strings */
 
154
                        if ( tag.len && data.len )
 
155
                                fields_add( copacin, tag.data, data.data, 0 );
 
156
                        newstr_empty( &tag );
 
157
                        newstr_empty( &data );
 
158
                }
 
159
                else p = copacin_nextline( p );
 
160
        }
 
161
        newstr_free( &tag );
 
162
        newstr_free( &data );
 
163
        return 1;
 
164
}
 
165
 
 
166
/* copac names appear to always start with last name first, but don't
 
167
 * always seem to have a comma after the name
 
168
 *
 
169
 * editors seem to be stuck in as authors with the tag "[Editor]" in it
 
170
 */
 
171
static void
 
172
copacin_addname( fields *info, char *tag, newstr *name, int level, list *asis,
 
173
        list *corps )
 
174
{
 
175
        char *usetag = tag, editor[]="EDITOR", *p;
 
176
        int comma = 0;
 
177
        if ( strstr( name->data,"[Editor]" ) ) {
 
178
                newstr_findreplace( name, "[Editor]", "" );
 
179
                usetag = editor;
 
180
        }
 
181
        p = skip_ws( name->data );
 
182
        while ( *p && !is_ws( *p ) ) {
 
183
                if ( *p==',' ) comma++;
 
184
                p++;
 
185
        }
 
186
        if ( !comma && is_ws( *p ) ) *p = ',';
 
187
        name_add( info, usetag, name->data, level, asis, corps );
 
188
}
 
189
 
 
190
static void
 
191
copacin_addpage( fields *info, char *p, int level )
 
192
{
 
193
        newstr page;
 
194
        newstr_init( &page );
 
195
        p = skip_ws( p );
 
196
        while ( *p && !is_ws(*p) && *p!='-' && *p!='\r' && *p!='\n' ) 
 
197
                newstr_addchar( &page, *p++ );
 
198
        if ( page.len>0 ) fields_add( info, "PAGESTART", page.data, level );
 
199
        newstr_empty( &page );
 
200
        while ( *p && (is_ws(*p) || *p=='-' ) ) p++;
 
201
        while ( *p && !is_ws(*p) && *p!='-' && *p!='\r' && *p!='\n' ) 
 
202
                newstr_addchar( &page, *p++ );
 
203
        if ( page.len>0 ) fields_add( info, "PAGEEND", page.data, level );
 
204
        newstr_free( &page );
 
205
}
 
206
 
 
207
static void
 
208
copacin_adddate( fields *info, char *tag, char *newtag, char *p, int level )
 
209
{
 
210
        char *months[12]={ "January", "February", "March", "April",
 
211
                "May", "June", "July", "August", "September",
 
212
                "October", "November", "December" };
 
213
        char month[10];
 
214
        int found,i,part;
 
215
        newstr date;
 
216
        newstr_init( &date );
 
217
        part = (!strncasecmp(newtag,"PART",4));
 
218
        if ( !strcasecmp( tag, "%D" ) ) {
 
219
                while ( *p ) newstr_addchar( &date, *p++ );
 
220
                if ( date.len>0 ) {
 
221
                        if ( part ) 
 
222
                                fields_add(info, "PARTYEAR", date.data, level);
 
223
                        else
 
224
                                fields_add( info, "YEAR", date.data, level );
 
225
                }
 
226
        } else if ( !strcasecmp( tag, "%8" ) ) {
 
227
                while ( *p && *p!=' ' && *p!=',' ) newstr_addchar( &date, *p++ );
 
228
                if ( date.len>0 ) {
 
229
                        found = -1;
 
230
                        for ( i=0; i<12 && found==-1; ++i )
 
231
                                if ( !strncasecmp( date.data, months[i], 3 ) )
 
232
                                        found = i;
 
233
                        if ( found!=-1 ) {
 
234
                                if (found>8) sprintf( month, "%d", found+1 );
 
235
                                else sprintf( month, "0%d", found+1 );
 
236
                                if ( part ) 
 
237
                                        fields_add( info, "PARTMONTH", month, level );
 
238
                                else    fields_add( info, "MONTH", month, level );
 
239
                        } else {
 
240
                                if ( part )
 
241
                                        fields_add( info, "PARTMONTH", date.data, level );
 
242
                                else
 
243
                                        fields_add( info, "MONTH", date.data, level );
 
244
                        }
 
245
                }
 
246
                newstr_empty( &date );
 
247
                p = skip_ws( p );
 
248
                while ( *p && *p!='\n' && *p!=',' )
 
249
                        newstr_addchar( &date, *p++ );
 
250
                if ( date.len>0 && date.len<3 ) {
 
251
                        if ( part )
 
252
                                fields_add( info, "PARTDAY", date.data, level );
 
253
                        else
 
254
                                fields_add( info, "DAY", date.data, level );
 
255
                }
 
256
        }
 
257
        newstr_free( &date );
 
258
}
 
259
 
 
260
static void
 
261
copacin_report_notag( param *p, char *tag )
 
262
{
 
263
        if ( p->verbose ) {
 
264
                if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
 
265
                fprintf( stderr, "Cannot find tag '%s'\n", tag );
 
266
        }
 
267
}
 
268
 
 
269
void
 
270
copacin_convertf( fields *copacin, fields *info, int reftype, param *p, variants *all, int nall )
 
271
{
 
272
        newstr *t, *d;
 
273
        int  process, level, i, n;
 
274
        char *newtag;
 
275
        for ( i=0; i<copacin->nfields; ++i ) {
 
276
                t = &( copacin->tag[i] );
 
277
                d = &( copacin->data[i] );
 
278
                n = process_findoldtag( t->data, reftype, all, nall );
 
279
                if ( n==-1 ) {
 
280
                        copacin_report_notag( p, t->data );
 
281
                        continue;
 
282
                }
 
283
                process = ((all[reftype]).tags[n]).processingtype;
 
284
                if ( process == ALWAYS ) continue; /*add these later*/
 
285
                level = ((all[reftype]).tags[n]).level;
 
286
                newtag = ((all[reftype]).tags[n]).newstr;
 
287
                if ( process==SIMPLE )
 
288
                        fields_add( info, newtag, d->data, level );
 
289
                else if ( process==TITLE )
 
290
                        title_process( info, newtag, d->data, level, 
 
291
                                        p->nosplittitle );
 
292
                else if ( process==PERSON )
 
293
                        copacin_addname( info, newtag, d, level, &(p->asis), 
 
294
                                        &(p->corps) );
 
295
                else if ( process==DATE )
 
296
                        copacin_adddate(info,all[reftype].
 
297
                                        tags[i].oldstr,newtag,d->data,level);
 
298
                else if ( process==PAGES )
 
299
                        copacin_addpage( info, d->data, level );
 
300
                else if ( process==SERIALNO )
 
301
                        addsn( info, d->data, level );
 
302
/*              else {
 
303
                        fprintf(stderr,"%s: internal error -- "
 
304
                                "illegal process %d\n", r->progname, process );
 
305
                }*/
 
306
        }
 
307
}
 
308
 
 
309