8
#define bzero(b,length) memset(b,0,length)
9
#define bcopy(b1,b2,length) memmove(b2,b1,length)
11
/* NOTE: The mr_get_article script will return sections is numerical order! */
13
#define MR_STATE_ARTICLE 0 /* Basic article data */
14
#define MR_STATE_ISO_VTITLE 1
15
#define MR_STATE_ISO_ADDRESS 2
16
#define MR_STATE_AUTHOR 3
17
#define MR_STATE_ISO_AUTHOR 4
18
#define MR_STATE_ISO_ABSTRACT 5 /* We send ISO first for the */
19
#define MR_STATE_ABSTRACT 6 /* abstract only */
20
#define MR_STATE_MESH 7
21
#define MR_STATE_SUBHEADING 8
22
#define MR_STATE_SUBSTANCE 9
23
#define MR_STATE_CROSSREFERENCE 10
24
#define MR_STATE_SUPPORT 11
25
#define MR_STATE_GENESYMBOL 12
26
#define MR_STATE_DONE 255
28
#define PATCH_BUFFER_SIZE 8192
29
#define TEXT_BUFFER_SIZE 8192
30
#define MAX_ABSTRACT_PATCHES 64
32
extern FILE * Id_timing_file;
35
hrtime_t Time_start, Time_back;
36
#define MACRO_before_exec \
38
Time_start = gethrtime();
40
#define MACRO_after_exec(type) \
41
if (Id_timing_file) {\
42
Time_back = gethrtime();\
43
fprintf(Id_timing_file,"%s %ld %ld\n", #type, (long) (Time_start/1000000.), (long) (( Time_back- Time_start)/ 1000000. )); fflush(Id_timing_file);}
45
struct timeb Time_start, Time_back;
46
#define MACRO_before_exec \
50
#define MACRO_after_exec(type) \
51
if (Id_timing_file) {\
53
fprintf(Id_timing_file,"%s %ld %ld\n", #type, (long) Time_start.time, (long) (( Time_back.time - Time_start.time)* 1000 + (Time_back.millitm - Time_start.millitm))); fflush(Id_timing_file);}
56
typedef struct AbPatch {
62
typedef struct AbPList {
64
AbPatch patches[MAX_ABSTRACT_PATCHES];
66
DBBINARY buffer[PATCH_BUFFER_SIZE];
73
* skip_undefined_section(DBPROCESSdb)
74
* RCS Modification History:
75
* $Log: getmedart.c,v $
76
* Revision 6.0 1997/08/25 18:36:12 madden
77
* Revision changed to 6.0
79
* Revision 1.3 1995/05/30 18:00:10 tatiana
82
* Revision 1.2 1995/05/17 17:54:43 epstein
83
* add RCS log revision history
86
int skip_undefined_section( DBPROCESS *db )
90
/* This simply skips to the end of the data */
92
while( (rc = dbnextrow( db )) != NO_MORE_ROWS && rc != FAIL );
93
return( (rc == FAIL) ? Error : True );
99
* title_append(DbTitle(title),charrest)
101
void title_append( DbTitle(title), char *rest )
105
if( *rest == 0 ) return;
106
for( len = strlen( title ); len < DBSIZE_Article_title; len++ )
108
strcpy( &title[len], rest );
111
static void check_title(char *title)
115
if ((s = strstr(title, "[see comments]")) != NULL) {
117
while( s >= title && (*s == ' ') ) {
124
void check_pages(char *pages)
128
for (; isspace(*pages); pages++);
129
if ((s = strchr(pages, ' ')) != NULL) {
136
* process_article(DBPROCESSdb,MedArtrec)
138
int process_article( DBPROCESS *db, MedArt *rec )
141
DbColumn (Article,title1);
142
DbColumn (Article,vtitle1);
145
/* Load the article row from the database */
146
/* TODO - CHECK THE FIELDS IN THE BIND! */
148
1, INTBIND, sizeof(rec->ui), &rec->ui,
149
2, INTBIND, sizeof(rec->mri), &rec->mri,
150
3, NTBSTRINGBIND, sizeof(rec->title), rec->title,
151
4, NTBSTRINGBIND, sizeof(title1), title1,
152
5, NTBSTRINGBIND, sizeof(rec->vtitle), rec->vtitle,
153
6, NTBSTRINGBIND, sizeof(vtitle1), vtitle1,
154
7, NTBSTRINGBIND, sizeof(rec->address), rec->address,
155
8, NTBSTRINGBIND, sizeof(rec->pages), rec->pages,
156
9, SMALLBIND, 0, &rec->entry_month,
157
10, NTBSTRINGBIND, sizeof(rec->volume), rec->volume,
158
11, NTBSTRINGBIND, sizeof(rec->issue), rec->issue,
159
12, NTBSTRINGBIND, sizeof(rec->pubdate), rec->pubdate,
160
13, NTBSTRINGBIND, sizeof(rec->med_abbr), rec->med_abbr,
161
14, NTBSTRINGBIND, sizeof(rec->language_code), rec->language_code,
163
if( rc != REG_ROW ) return( False );
165
/* Add the extension columns to the title and vtitle fields */
167
rec->title_type = 6; /* ml-jta */
168
title_append( rec->title, title1 );
169
title_append( rec->vtitle, vtitle1 );
171
check_title(rec->title);
172
check_title(rec->vtitle);
174
if (strncmp(rec->pages, "Suppl", 5) == 0) {
175
if ((chr = strchr(rec->pages, ':')) != NULL) {
177
if (rec->issue[0] != '\0') {
178
strncat(rec->issue, rec->pages,
179
DBSIZE_Issue_issue - strlen(rec->issue));
181
strncat(rec->volume, rec->pages,
182
DBSIZE_Issue_volume - strlen(rec->volume));
184
strcpy(rec->pages, chr + 1);
187
check_pages(rec->pages);
197
* process_pub_article(DBPROCESSdb,MedArtrec)
199
int process_pub_article( DBPROCESS *db, MedArt *rec )
202
DbColumn (Article,title1);
203
DbColumn (Article,vtitle1);
206
/* Load the article row from the database */
207
/* TODO - CHECK THE FIELDS IN THE BIND! */
209
1, INTBIND, sizeof(rec->ui), &rec->ui,
210
2, INTBIND, sizeof(rec->mri), &rec->mri,
211
3, NTBSTRINGBIND, sizeof(rec->title), rec->title,
212
4, NTBSTRINGBIND, sizeof(title1), title1,
213
5, NTBSTRINGBIND, sizeof(rec->vtitle), rec->vtitle,
214
6, NTBSTRINGBIND, sizeof(vtitle1), vtitle1,
215
7, NTBSTRINGBIND, sizeof(rec->address), rec->address,
216
8, NTBSTRINGBIND, sizeof(rec->pages), rec->pages,
217
9, SMALLBIND, 0, &rec->entry_month,
218
10, NTBSTRINGBIND, sizeof(rec->volume), rec->volume,
219
11, NTBSTRINGBIND, sizeof(rec->issue), rec->issue,
220
12, NTBSTRINGBIND, sizeof(rec->pubdate), rec->pubdate,
221
13, NTBSTRINGBIND, sizeof(rec->med_abbr), rec->med_abbr,
222
14, NTBSTRINGBIND, sizeof(rec->language_code), rec->language_code,
223
15, INTBIND, sizeof(rec->title_type),&rec->title_type,
225
if( rc != REG_ROW ) return( False );
227
/* Add the extension columns to the title and vtitle fields */
229
title_append( rec->title, title1 );
230
title_append( rec->vtitle, vtitle1 );
232
check_title(rec->title);
233
check_title(rec->vtitle);
235
if (strncmp(rec->pages, "Suppl", 5) == 0) {
236
if ((chr = strchr(rec->pages, ':')) != NULL) {
238
if (rec->issue[0] != '\0') {
239
strncat(rec->issue, rec->pages,
240
DBSIZE_Issue_issue - strlen(rec->issue));
242
strncat(rec->volume, rec->pages,
243
DBSIZE_Issue_volume - strlen(rec->volume));
245
strcpy(rec->pages, chr + 1);
248
check_pages(rec->pages);
256
static DBINT patch_sequence = 0;
257
static DBINT patch_item = 0;
258
static DBINT patch_length;
259
static MaxBinary patch_line;
263
* load_patch(DBPROCESSdb,DBBINARYpatches,intsize,
265
int load_patch( DBPROCESS *db, DBBINARY *patches, int size,
266
DBINT *item, DBINT *length, int first )
271
/* If we have buffered a line - get it */
273
if( ! first && patch_sequence == 1 ) {
275
bcopy( patch_line, patches, patch_length );
276
*length = patch_length;
279
*length = patch_length = patch_item = sequence = 0;
282
while ( (rc = SybaseLoad( db,
283
1, INTBIND, 0, &patch_item,
284
2, INTBIND, 0, &patch_sequence,
285
3, INTBIND, 0, &patch_length,
286
4, BINARYBIND, sizeof(patch_line), patch_line,
289
/* If this is the first line - init the setup */
291
if( sequence == 0 ) {
292
if( patch_sequence != 1 ) continue; /* Skip junk */
296
/* If we get this far, test for a continuation line */
298
if( patch_sequence == (sequence + 1) && patch_item == *item ) {
299
if( ( patch_length + *length ) > size )
300
goto error; /* Overflow */
301
bcopy( patch_line, patches + *length, patch_length );
302
*length += patch_length;
304
} else if( patch_sequence != 1 )
305
goto error; /* Patch sequence error */
307
/* If we get here - we're at the start of the next patch */
311
if( rc == FAIL ) goto error;
312
if( rc != REG_ROW ) patch_sequence = 0; /* Reset on end */
316
return( (*length == 0) ? False : True );
329
* patch_string(DBPROCESSdb,charstr,intsize)
331
int patch_string( DBPROCESS *db, char *str, int size )
333
DBBINARY patches[PATCH_BUFFER_SIZE];
334
DBINT patch_length = 0, item = 0;
335
DBCHAR buffer[TEXT_BUFFER_SIZE];
339
/* Get the title patches from the input string */
341
if( ! DBROWS( db ) ) return( False );
342
rv = load_patch( db, patches, sizeof(patches), &item, &patch_length, True );
343
if( rv != True ) return( rv );
345
/* We have the patches, apply them */
347
if( ApplyIsoPatches( str, size, buffer, sizeof(buffer),
348
patches, patch_length ) > 0 )
353
/* Done - put the stuff back */
354
strcpy( str, buffer );
361
* process_author(DBPROCESSdb,MedArtrec)
363
int process_author( DBPROCESS *db, MedArt *rec )
369
/* Read the author list */
371
while( (rc = SybaseLoad( db,
373
2, NTBSTRINGBIND, sizeof(name), name,
376
if( seq > MAX_AUTHOR_COUNT )
377
continue; /* Author index too large */
378
strcpy( rec->authors[seq], name );
379
if( (seq+1) > rec->n_authors ) rec->n_authors = seq+1;
382
return((rc == NO_MORE_ROWS) ? ((rec->n_authors == 0) ? False: True): Error);
389
* patch_author(DBPROCESSdb,MedArtrec)
391
int patch_author( DBPROCESS *db, MedArt *rec )
393
DBBINARY patches[PATCH_BUFFER_SIZE];
394
DBINT patch_length = 0, item = 0;
395
DBCHAR buffer[TEXT_BUFFER_SIZE];
399
for( first = 1;; first = 0 ) {
400
switch( load_patch( db, patches, sizeof(patches), &item,
401
&patch_length, first ) )
403
case True: /* We found a patch */
404
if( ApplyIsoPatches( rec->authors[item-1],
405
sizeof(rec->authors[0]), buffer, sizeof(buffer),
406
patches, patch_length ) == 0 )
408
strcpy( rec->authors[item-1], buffer );
412
case False: /* No patch found */
414
case Error: /* Oops - */
424
* process_abstract(DBPROCESSdb,MedArtrec,AbPListplist)
426
int process_abstract( DBPROCESS *db, MedArt *rec, AbPList *plist )
428
DbNColumn(Abstract,abstract,line); /* Line buffer */
429
int pi = 0; /* Index to next patch */
430
int ti = 0; /* Index to next text line */
431
int next_line = 1; /* Expect this line next */
436
while( (sizeof(rec->abstract) - ti) >= sizeof(line) ) {
438
/* Skip patches to lines alsready passed */
440
while(pi < plist->n_patches && next_line > plist->patches[pi].line_no)
442
/* If a patch is expected, prepare for it */
444
if( pi < plist->n_patches && next_line == plist->patches[pi].line_no ) {
446
/* The next line should be a patch line */
448
1, INTBIND, sizeof(line_no), &line_no,
449
2, NTBSTRINGBIND, sizeof(line), line,
452
/* Apply the patch */
454
if( rc == REG_ROW && line_no == next_line ) {
455
(void) ApplyIsoPatches( line, strlen(line), &rec->abstract[ti],
456
sizeof(rec->abstract) - ti, plist->patches[pi].start,
457
plist->patches[pi].length );
461
1, INTBIND, sizeof(line_no), &line_no,
462
2, NTBSTRINGBIND, sizeof(line), &rec->abstract[ti],
464
if( rc != REG_ROW ) break;
466
ti += strlen( &rec->abstract[ti] ); /* New abstract length */
467
next_line = line_no + 1;
472
/* Return the status */
474
return( (rv == Error) ? rv : ((ti > 0) ? True : False) );
481
* patch_abstract(DBPROCESSdb,MedArtrec,AbPListplist)
483
int patch_abstract( DBPROCESS *db, MedArt *rec, AbPList *plist )
488
/* Load the patches */
490
for( plist->n_patches = 0; plist->n_patches < MAX_ABSTRACT_PATCHES &&
491
(rv = load_patch( db, &plist->buffer[plist->used],
492
sizeof(plist->buffer) - plist->used,
493
&plist->patches[plist->n_patches].line_no,
494
&plist->patches[plist->n_patches].length,
498
/* A patch was loaded - record it */
499
plist->used += plist->patches[plist->n_patches].length;
505
return( (rv == Error) ? Error : ((plist->n_patches > 0) ? True : False) );
510
int mesh_compare( const void *m1, const void *m2 )
512
return( strcmp( ((Mesh *) m1)->heading, ((Mesh *) m2)->heading ) );
517
* process_mesh(DBPROCESSdb,MedArtrec)
519
int process_mesh( DBPROCESS *db, MedArt *rec )
522
DbColumn (Mesh,main_point);
523
DbColumn (Mesh,heading);
527
/* Read the main mesh headings into the table */
531
while( (rc = SybaseLoad( db,
532
1, INTBIND, 0, &id_mesh,
533
2, NTBSTRINGBIND, sizeof(main_point), main_point,
534
3, NTBSTRINGBIND, sizeof(heading), heading,
537
/* Load the MeSH heading into the table. */
538
if( rec->n_mesh >= MAX_MESH_COUNT ) continue; /* Too many */
539
rec->mesh[rec->n_mesh].id_mesh = id_mesh;
540
strcpy( rec->mesh[rec->n_mesh].main_point, main_point );
541
strcpy( rec->mesh[rec->n_mesh].heading, heading );
547
if ( rec->n_mesh > 0 )
548
qsort( rec->mesh, rec->n_mesh, sizeof(Mesh), mesh_compare );
550
return( rec->n_mesh == 0 ? False : True );
557
* process_subheading(DBPROCESSdb,MedArtrec)
559
int process_subheading( DBPROCESS *db, MedArt *rec )
562
DbColumn (Subheading,main_point);
563
DbColumn (Subheading,code);
564
DbColumn (Subheading,name);
565
DbColumn (Subheading,description);
568
while( (rc = SybaseLoad( db,
569
1, INTBIND, 0, &id_mesh,
570
2, NTBSTRINGBIND, sizeof(main_point), main_point,
571
3, NTBSTRINGBIND, sizeof(code), code,
572
4, NTBSTRINGBIND, sizeof(name), name,
573
5, NTBSTRINGBIND, sizeof(description), description,
579
for ( i = 0, seq = -1; i< rec->n_mesh; i++ )
580
if ( id_mesh == rec->mesh[i].id_mesh )
585
if( seq == -1 ) continue;
588
if( m->n_qual >= MAX_QUALIFIER_COUNT ) continue;
589
q = &m->qualifiers[m->n_qual++];
590
strcpy(q->main_point, main_point);
591
strcpy(q->code, code);
592
strcpy(q->name, name);
593
strcpy(q->description, description);
602
* process_substance(DBPROCESSdb,MedArtrec)
604
int process_substance( DBPROCESS *db, MedArt *rec )
609
/* Read the subsances from the database */
611
for( i = 0; i < MAX_SUBSTANCE_COUNT; i++ ) {
613
1, NTBSTRINGBIND, sizeof(rec->substances[0].number),
614
rec->substances[i].number,
615
2, NTBSTRINGBIND, sizeof(rec->substances[0].name),
616
rec->substances[i].name,
618
if( rc != REG_ROW ) break;
620
rec->n_substances = i;
622
return( (rc == FAIL) ? Error : ( (i==0) ? False : True ) );
629
* process_xref(DBPROCESSdb,MedArtrec)
631
int process_xref( DBPROCESS *db, MedArt *rec )
636
/* Read the subsances from the database */
638
for( i = 0; i < MAX_XREF_COUNT; i++ ) {
640
1, NTBSTRINGBIND, sizeof(rec->xrefs[0].database),
641
rec->xrefs[i].database,
642
2, NTBSTRINGBIND, sizeof(rec->xrefs[0].accession),
643
rec->xrefs[i].accession,
645
if( rc != REG_ROW ) break;
648
/* Make sure that + is last */
652
return( (rc == FAIL) ? Error : ( (i==0) ? False : True ) );
659
* process_support(DBPROCESSdb,MedArtrec)
661
int process_support( DBPROCESS *db, MedArt *rec )
667
/* Read the subsances from the database */
669
for( i = 0; i < MAX_IDNUM_COUNT; i++ ) {
671
1, NTBSTRINGBIND, sizeof(SupportId), rec->idnums[i],
673
if( rc != REG_ROW ) break;
675
/* If we get a +, just remeber that we saw it. We'll put it last */
677
if( strcmp( rec->idnums[i], "+" ) == 0 ) {
683
/* Add the plus back in */
685
if( i < MAX_IDNUM_COUNT && have_plus > 0 ) {
686
strcpy( rec->idnums[i], "+" );
691
return( (rc == FAIL) ? Error : ( (i==0) ? False : True ) );
698
* process_genesymbol(DBPROCESSdb,MedArtrec)
700
int process_genesymbol( DBPROCESS *db, MedArt *rec )
705
/* Read the subsances from the database */
707
for( i = 0; i < MAX_GENESYM_COUNT; i++ ) {
709
1, NTBSTRINGBIND, sizeof(GeneSymbol), rec->gene_symbols[i],
711
if( rc != REG_ROW ) break;
713
rec->n_gene_symbols = i;
715
return( (rc == FAIL) ? Error : ( (i==0) ? False : True ) );
720
* ProcessMedlineArticle(DBPROCESS *db, MedArt *rec)
723
int ProcessMedlineArticle( DBPROCESS *db, MedArt *rec, int is_pub )
727
DBCHAR state_msg[40]; /* Text description of state */
731
/* Clear out the input record */
733
bzero( rec, sizeof(MedArt) );
734
bzero( &plist, sizeof(plist) ); /* Get rid of all patches */
736
/* Collect the data from the database */
738
for(status = True; status != Error; rc = dbresults( db )) {
740
/* Get the next header row from the batch and then skip to
741
the results batch associated with the header (dbresults call) */
744
1, INTBIND, 0, &state,
745
2, NTBSTRINGBIND, sizeof(state_msg), state_msg,
747
if( rc == REG_ROW ) {
748
/* EOF marked with MR_STATE_DONE as the state */
749
if( state == MR_STATE_DONE )
752
/* Prepare to read the results section */
755
if( rc != SUCCEED ) return( Error );
757
/* Dispatch to the handler for this block of input */
760
case MR_STATE_ARTICLE: /* This one should be first */
762
status = process_pub_article( db, rec );
764
status = process_article( db, rec );
765
if( status != True ) return( status );
767
case MR_STATE_ISO_VTITLE:
768
status = patch_string(db, rec->vtitle, sizeof(rec->vtitle));
770
case MR_STATE_ISO_ADDRESS:
771
status = patch_string(db, rec->address, sizeof(rec->address));
773
case MR_STATE_AUTHOR:
774
status = process_author( db, rec );
776
case MR_STATE_ISO_AUTHOR:
777
status = patch_author( db, rec );
779
case MR_STATE_ISO_ABSTRACT:
780
if( plist.n_patches > 0 )
781
bzero( &plist, sizeof(plist) );
782
status = patch_abstract( db, rec, &plist );
784
case MR_STATE_ABSTRACT:
785
status = process_abstract( db, rec, &plist );
788
status = process_mesh( db, rec );
790
case MR_STATE_SUBHEADING:
791
status = process_subheading( db, rec );
793
case MR_STATE_SUBSTANCE:
794
status = process_substance( db, rec );
796
case MR_STATE_CROSSREFERENCE:
797
status = process_xref( db, rec );
799
case MR_STATE_SUPPORT:
800
status = process_support( db, rec );
802
case MR_STATE_GENESYMBOL:
803
status = process_genesymbol( db, rec );
805
default: /* Unknown state - ignore it */
806
status = skip_undefined_section( db );
811
/* Return the proper status */
818
* GetMedlineArticle(DBPROCESSdb,intui,intflags,MedArtrec)
820
int GetMedlineArticle( DBPROCESS *db, int ui, int flags, MedArt *rec )
826
rc = RunSybase( db, "execute mr_get_article %d, %d", ui, flags );
827
MACRO_after_exec(GetMedlineArticle)
828
if( rc != SUCCEED ) return( Error );
830
return( ProcessMedlineArticle( db, rec, 0 ) );
834
* GetMedlinePub(DBPROCESSdb,intui,intflags,MedArtrec)
836
int GetMedlinePub( DBPROCESS *db, int ui, int flags, MedArt *rec )
843
rc = RunSybase( db, "execute mr_get_pub %d, %d", ui, flags );
844
MACRO_after_exec(GetMedlinePub)
845
if( rc != SUCCEED ) return( Error );
847
return( ProcessMedlineArticle( db, rec, 1 ) );