1 /*  tomedlin.c
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *               National Center for Biotechnology Information
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government have not placed any restriction on its use or reproduction.
13 *
14 *  Although all reasonable efforts have been taken to ensure the accuracy
15 *  and reliability of the software and data, the NLM and the U.S.
16 *  Government do not and cannot warrant the performance or results that
17 *  may be obtained by using this software or data. The NLM and the U.S.
18 *  Government disclaim all warranties, express or implied, including
19 *  warranties of performance, merchantability or fitness for any particular
20 *  purpose.
21 *
22 *  Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * File Name:  tomedlin.c
27 *
28 * Author:  Jonathan Kans
29 *
30 * Version Creation Date: 10/15/91
31 *
32 * $Revision: 6.12 $
33 *
34 * File Description:  conversion to medlars format
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 * Date	   Name        Description of modification
39 * -------  ----------  -----------------------------------------------------
40 *
41 *
42 * $Log: tomedlin.c,v $
43 * Revision 6.12  2012/08/21 19:18:45  kans
44 * fixed several potential null dereferences found by clang
45 *
46 * Revision 6.11  2004/03/10 15:19:47  kans
47 * ParseMedline loops on journal, only saves one of iso-jta or ml-jta to avoid memory leak
48 *
49 * Revision 6.10  2003/09/28 20:22:47  kans
50 * added PubmedEntryToXXXFile functions
51 *
52 * Revision 6.9  2003/09/26 18:57:51  kans
53 * MedlineEntryToDataFile calls MakeMLAuthString for structured author
54 *
55 * Revision 6.8  2001/10/29 20:37:06  kans
56 * MakeAuthorString for structured authors
57 *
58 * Revision 6.7  2001/10/22 13:37:12  kans
59 * break up huge author list
60 *
61 * Revision 6.6  2001/10/15 12:24:05  kans
62 * MedlineEntryToDataFile breaks up long mesh, substance, and xref lists
63 *
64 * Revision 6.5  1999/10/26 20:17:04  kans
65 * allocate separate string for abstract since some may be very long
66 *
67 * Revision 6.4  1999/10/01 17:20:08  kans
68 * fixed stack overflow found by DV
69 *
70 * Revision 6.3  1999/03/11 23:32:08  kans
71 * sprintf casts
72 *
73 * Revision 6.2  1998/06/12 20:05:50  kans
74 * fixed unix compiler warnings
75 *
76 * Revision 6.1  1997/12/02 17:42:29  kans
77 * added cast in sprintf
78 *
79 * Revision 6.0  1997/08/25 18:07:55  madden
80 * Revision changed to 6.0
81 *
82 * Revision 5.16  1997/06/19 18:39:27  vakatov
83 * [WIN32,MSVC++]  Adopted for the "NCBIOBJ.LIB" DLL'ization
84 *
85 * Revision 5.15  1997/04/14 18:02:31  grisha
86 * set MedlarsEntryToDataFile() to be external
87 *
88  * Revision 5.14  1997/04/11  16:24:13  levitsky
89  * *** empty log message ***
90  *
91  * Revision 5.13  1997/04/11  15:58:58  levitsky
92  * New functions for support tomedlars added
93  *
94  * Revision 5.12  1997/04/10  18:16:06  levitsky
95  * New version of MEDLARS output
96  *
97  * Revision 5.11  1997/04/08  19:35:43  levitsky
98  * *** empty log message ***
99  *
100  * Revision 5.10  1997/04/08  17:30:46  levitsky
101  * fixed break error
102  *
103  * Revision 5.9  1997/04/07  21:34:40  levitsky
104  * Added SO field for medlars report
105  *
106  * Revision 5.8  1997/03/19  18:06:23  kans
107  * fixed use of mep->pub_type
108  *
109  * Revision 5.7  1997/03/19  16:53:08  levitsky
110  * publication type added to output
111  *
112  * Revision 5.6  1997/02/20  21:25:17  kans
113  * added MedlineEntryToAbsFile and MedlarsEntryToAbsFile
114  *
115  * Revision 5.5  1997/02/19  15:09:22  levitsky
116  * pmid added to output
117  *
118  * Revision 5.4  1997/02/12  21:30:02  grisha
119  * add code to support MEDLARS report generation
120  * for MedlarsEntry
121  *
122  * Revision 5.3  1997/01/27  16:15:39  grisha
123  * Fix bugs with SO field generation
124  *
125  * Revision 5.2  1996/08/27  23:10:43  kans
126  * protect prefixes (e.g., van, el, den) with initials that can be
127  * mistaken for suffixes (e.g., I).  this won't protect against
128  * names with the Van incorrectly entered at the end.
129  *
130  * Revision 5.1  1996/05/31  21:04:12  kans
131  * check for individual suffixes before stripping
132  *
133  * Revision 5.0  1996/05/28  13:23:23  ostell
134  * Set to revision 5.0
135  *
136  * Revision 4.2  1996/01/23  20:59:15  kans
137  * now allows iso-jta as well as ml-jta
138  *
139  * Revision 4.1  1995/12/27  17:50:11  kans
140  * changed StringAppend to StrngAppend to avoid conflict with future ncbistr.h
141  *
142  * Revision 4.0  1995/07/26  13:49:01  ostell
143  * force revision to 4.0
144  *
145  * Revision 2.5  1995/05/15  21:46:05  ostell
146  * added Log line
147  *
148 *
149 *
150 * ==========================================================================
151 */
152 
153 #include <objmedli.h>
154 #include <tofile.h>
155 #include <tomedlin.h>
156 
157 #ifdef VAR_ARGS
158 #include <varargs.h>
159 #else
160 #include <stdarg.h>
161 #endif
162 
163 #ifdef COMP_MPW
164 #pragma segment CdrSegD
165 #endif
166 
167 #define BUFSIZE 8192
168 
169 static CharPtr  buffer;
170 static CharPtr  pos;
171 
172 /* ----- Function Prototypes ----- */
173 
174 static void ClearString PROTO((void));
175 static void AddString PROTO((CharPtr string));
176 static CharPtr CleanAuthorString PROTO((CharPtr auth));
177 static CharPtr CDECL StrngAppend VPROTO((CharPtr first, ...));
178 
179 /* ----- Function Bodies ----- */
180 
ClearString(void)181 static void ClearString (void)
182 
183 {
184   pos = buffer;
185   *pos = '\0';
186 }
187 
AddString(CharPtr string)188 static void AddString (CharPtr string)
189 
190 {
191   pos = StringMove (pos, string);
192   *pos = '\0';
193 }
194 
195 static ColData table [2] = {{0, 6, 0, 'l', TRUE, TRUE, FALSE},
196                             {0, 72, 0, 'l', TRUE, TRUE, TRUE}};
197 
198 
199 static Char *months[13] = {"", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
200                            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
201 
MakeMLAuthString(CharPtr name,CharPtr initials,CharPtr suffix)202 static CharPtr MakeMLAuthString (
203   CharPtr name,
204   CharPtr initials,
205   CharPtr suffix
206 )
207 
208 {
209   Char     ch;
210   size_t   len;
211   CharPtr  ptr;
212   CharPtr  str;
213   CharPtr  tmp;
214 
215   if (name == NULL) return NULL;
216 
217   len = StringLen (name) + StringLen (initials) * 3 + StringLen (suffix);
218   str = MemNew (sizeof (Char) * (len + 4));
219   if (str == NULL) return NULL;
220 
221   tmp = str;
222 
223   tmp = StringMove (tmp, name);
224 
225   ptr = initials;
226   if (! StringHasNoText (initials)) {
227     tmp = StringMove (tmp, " ");
228     ch = *ptr;
229     while (ch != '\0') {
230       if (ch == '-') {
231         *tmp = '-';
232         tmp++;
233       } else if (ch != '.') {
234         *tmp = ch;
235         tmp++;
236       }
237       ptr++;
238       ch = *ptr;
239     }
240     *tmp = '\0';
241   }
242 
243   if (! StringHasNoText (suffix)) {
244     tmp = StringMove (tmp, " ");
245     tmp = StringMove (tmp, suffix);
246   }
247 
248   return str;
249 }
250 
MedlineEntryToDataFileEx(MedlineEntryPtr mep,Int4 pmid,FILE * fp)251 static Boolean MedlineEntryToDataFileEx (MedlineEntryPtr mep, Int4 pmid, FILE *fp)
252 
253 {
254   CharPtr         abstract;
255   AffilPtr        affil;
256   AuthorPtr       ap;
257   AuthListPtr     authors = NULL;
258   CitArtPtr       cit = NULL;
259   CitJourPtr      citjour = NULL;
260   Int2            count;
261   CharPtr         curr;
262   DatePtr         date = NULL;
263   ValNodePtr      gene;
264   Int2            i;
265   ImprintPtr      imp = NULL;
266   CharPtr         issue = NULL;
267   size_t          len;
268   MedlineMeshPtr  mesh;
269   ValNodePtr      names;
270   NameStdPtr      nsp;
271   CharPtr         p;
272   CharPtr         pages = NULL;
273   ParData         para;
274   PersonIdPtr     pid;
275   CharPtr         ptr;
276   ValNodePtr      qual;
277   Boolean         rsult;
278   Char            str [32];
279   MedlineRnPtr    substance;
280   ValNodePtr      title;
281   CharPtr         tmp;
282   CharPtr         volume = NULL;
283   ValNodePtr      xref;
284   CharPtr         lpTemp;
285   CharPtr         lpMedAbbr = NULL;
286   CharPtr         lpMedCode = NULL;
287   CharPtr         lpIssn = NULL;
288 
289   rsult = TRUE;
290   buffer = MemNew (BUFSIZE);
291   if (buffer != NULL) {
292     para.openSpace = FALSE;
293     ClearString ();
294     AddString ("UI  -\t");
295     sprintf (str, "%ld", (long) mep->uid);
296     AddString (str);
297     AddString ("\n");
298     rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
299     ClearString ();
300 
301     if ( mep->pmid > 0 ) {
302       ClearString ();
303       AddString ("PM  -\t");
304       sprintf (str, "%ld", (long) mep->pmid);
305       AddString (str);
306       AddString ("\n");
307       rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
308       ClearString ();
309     }
310 
311     if ( mep->pub_type != NULL ) {
312       ClearString ();
313       AddString ("PT  -\t");
314       AddString ((CharPtr) mep->pub_type->data.ptrvalue);
315       AddString ("\n");
316       rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
317       ClearString ();
318     }
319 
320     cit = mep->cit;
321     if (cit != NULL) {
322       authors = cit->authors;
323       if (authors != NULL) {
324         if (authors->choice == 1) {
325           names = authors->names;
326           count = 0;
327           while (names != NULL) {
328             if (count >= 20) {
329               rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
330               ClearString ();
331               count = 0;
332             }
333             curr = NULL;
334             ap = (AuthorPtr) names->data.ptrvalue;
335             if (ap != NULL) {
336               pid = ap->name;
337               if (pid != NULL) {
338                 if (pid->choice == 2) {
339                   nsp = (NameStdPtr) pid->data;
340                   if (nsp != NULL) {
341                     if (! StringHasNoText (nsp->names [0])) {
342                       curr = MakeMLAuthString (nsp->names [0], nsp->names [4], nsp->names [5]);
343                     } else if (! StringHasNoText (nsp->names [3])) {
344                       curr = MakeMLAuthString (nsp->names [3], NULL, NULL);
345                     }
346                   }
347                 } else if (pid->choice == 3 || pid->choice == 4) {
348                   curr = MakeMLAuthString ((CharPtr) pid->data, NULL, NULL);
349                 }
350               }
351             }
352             if (curr != NULL) {
353               AddString ("AU  -\t");
354               AddString (curr);
355               AddString ("\n");
356               curr = MemFree (curr);
357             }
358             names = names->next;
359             count++;
360           }
361         } else if (authors->choice == 2 || authors->choice == 3) {
362           names = authors->names;
363           count = 0;
364           while (names != NULL) {
365             if (count >= 20) {
366               rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
367               ClearString ();
368               count = 0;
369             }
370             AddString ("AU  -\t");
371             AddString (names->data.ptrvalue);
372             AddString ("\n");
373             names = names->next;
374             count++;
375           }
376         }
377       }
378       rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
379       ClearString ();
380       title = cit->title;
381       count = 0;
382       while (title != NULL) {
383         if (count >= 20) {
384           rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
385           ClearString ();
386           count = 0;
387         }
388         if (title->choice == 1) {
389           AddString ("TI  -\t");
390           AddString (title->data.ptrvalue);
391           AddString ("\n");
392         }
393         title = title->next;
394         count++;
395       }
396       rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
397       ClearString ();
398     }
399 
400     mesh = mep->mesh;
401     count = 0;
402     while (mesh != NULL) {
403       if (count >= 20) {
404         rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
405         ClearString ();
406         count = 0;
407       }
408       AddString ("MH  -\t");
409       if (mesh->mp) {
410         AddString ("*");
411       }
412       AddString (mesh->term);
413       qual = mesh->qual;
414       while (qual != NULL) {
415         AddString ("/");
416         if (qual->choice != 0) {
417           AddString ("*");
418         }
419         p = (CharPtr) qual->data.ptrvalue;
420         while (*p != '\0') {
421           *p = TO_UPPER (*p);
422           p++;
423         }
424         AddString (qual->data.ptrvalue);
425         qual = qual->next;
426       }
427       AddString ("\n");
428       mesh = mesh->next;
429       count++;
430     }
431     rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
432     ClearString ();
433     substance = mep->substance;
434     count = 0;
435     while (substance != NULL) {
436       if (count >= 20) {
437         rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
438         ClearString ();
439         count = 0;
440       }
441       AddString ("RN  -\t");
442       switch (substance->type) {
443         case 0:
444           AddString ("0 (");
445           AddString (substance->name);
446           AddString (")");
447           break;
448         case 1:
449           AddString (substance->cit);
450           AddString (" (");
451           AddString (substance->name);
452           AddString (")");
453           break;
454         case 2:
455           AddString ("EC ");
456           AddString (substance->cit);
457           AddString (" (");
458           AddString (substance->name);
459           AddString (")");
460           break;
461         default:
462           break;
463       }
464       AddString ("\n");
465       substance = substance->next;
466       count++;
467     }
468     rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
469     ClearString ();
470     gene = mep->gene;
471     while (gene != NULL) {
472       AddString ("GS  -\t");
473       AddString (gene->data.ptrvalue);
474       AddString ("\n");
475       gene = gene->next;
476     }
477     xref = mep->xref;
478     count = 0;
479     while (xref != NULL) {
480       if (count >= 20) {
481         rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
482         ClearString ();
483         count = 0;
484       }
485       AddString ("SI  -\t");
486       switch (xref->choice) {
487         case 1:
488           AddString ("DDBJ/");
489           break;
490         case 2:
491           AddString ("CARBBANK/");
492           break;
493         case 3:
494           AddString ("EMBL/");
495           break;
496         case 4:
497           AddString ("HDB/");
498           break;
499         case 5:
500           AddString ("GENBANK/");
501           break;
502         case 6:
503           AddString ("HGML/");
504           break;
505         case 7:
506           AddString ("MIM/");
507           break;
508         case 8:
509           AddString ("MSD/");
510           break;
511         case 9:
512           AddString ("PDB/");
513           break;
514         case 10:
515           AddString ("PIR/");
516           break;
517         case 11:
518           AddString ("PRFSEQDB/");
519           break;
520         case 12:
521           AddString ("PSD/");
522           break;
523         case 13:
524           AddString ("SWISSPROT/");
525           break;
526         default:
527           AddString ("?/");
528           break;
529       }
530       AddString (xref->data.ptrvalue);
531       AddString ("\n");
532       xref = xref->next;
533       count++;
534     }
535     rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
536     ClearString ();
537     if (cit != NULL) {
538       citjour = cit->fromptr;
539     }
540     if (citjour != NULL) {
541       imp = citjour->imp;
542       if (imp != NULL) {
543         date = imp->date;
544         if (date != NULL) {
545           switch (date->data [0]) {
546             case 0:
547               AddString ("DP  -\t");
548               StringNCpy (str, date->str, sizeof (str) - 1);
549               AddString (str);
550               AddString ("\n");
551               break;
552             case 1:
553               AddString ("DP  -\t");
554               sprintf (str, "%d", date->data [1] + 1900);
555               AddString (str);
556               AddString (" ");
557               i = date->data [2];
558               if (i >= 0 && i <= 11) {
559                 AddString (months [i]);
560               }
561               if (date->data [3] > 0) {
562                 AddString (" ");
563                 sprintf (str, "%d", date->data [3]);
564                 AddString (str);
565               }
566               AddString ("\n");
567             default:
568               break;
569           }
570         }
571       }
572       title = citjour->title;
573       while (title != NULL) {
574         if ( title->choice == Cit_title_jta ) {
575             lpTemp = "JC  -\t";
576             lpMedCode = title->data.ptrvalue;
577         } else if ( title->choice == Cit_title_ml_jta ) {
578             lpTemp = "TA  -\t";
579             lpMedAbbr = title->data.ptrvalue;
580         } else if ( title->choice == Cit_title_issn ) {
581             lpTemp = "IS  -\t";
582             lpIssn = title->data.ptrvalue;
583         } else {
584             title = title->next;
585             continue;
586         }
587         AddString (lpTemp);
588         AddString (title->data.ptrvalue);
589         AddString ("\n");
590         title = title->next;
591       }
592       if (imp != NULL) {
593         pages = imp->pages;
594         if (pages != NULL) {
595           AddString ("PG  -\t");
596           AddString (pages);
597           AddString ("\n");
598         }
599         issue = imp->issue;
600         if (issue != NULL) {
601           AddString ("IP  -\t");
602           AddString (issue);
603           AddString ("\n");
604         }
605         volume = imp->volume;
606         if (volume != NULL) {
607           AddString ("VI  -\t");
608           AddString (volume);
609           AddString ("\n");
610         }
611       }
612     }
613     rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
614     ClearString ();
615     abstract = mep->abstract;
616     if (abstract != NULL) {
617       len = StringLen (abstract);
618       tmp = (CharPtr) MemNew (sizeof (Char) * (len + 10));
619       ptr = StringMove (tmp, "AB  -\t");
620       ptr = StringMove (ptr, abstract);
621       ptr = StringMove (ptr, "\n");
622       rsult = (Boolean) (SendTextToFile (fp, tmp, &para, table) && rsult);
623       MemFree (tmp);
624     }
625     ClearString ();
626     if (cit != NULL && authors != NULL) {
627       affil = authors->affil;
628       if (affil != NULL && affil->choice == 1) {
629         AddString ("AD  -\t");
630         AddString (affil->affil);
631         AddString ("\n");
632       }
633     }
634     if (citjour != NULL && imp != NULL) {
635       AddString ("SO  -\t");
636       if ( lpMedAbbr != NULL ) {
637           AddString(lpMedAbbr);
638       } else if ( lpIssn != NULL ) {
639           AddString(lpIssn);
640       } else if ( lpMedCode != NULL ) {
641           AddString(lpMedCode);
642       }
643       AddString (" ");
644       if (date != NULL) {
645         switch (date->data [0]) {
646           case 0:
647             StringNCpy (str, date->str, sizeof (str) - 1);
648             AddString (str);
649             AddString (";");
650             break;
651           case 1:
652             sprintf (str, "%d", date->data [1] + 1900);
653             AddString (str);
654             AddString (" ");
655             i = date->data [2];
656             if (i >= 0 && i <= 11) {
657               AddString (months [i]);
658             }
659             if (date->data [3] > 0) {
660               AddString (" ");
661               sprintf (str, "%d", date->data [3]);
662               AddString (str);
663             }
664             AddString (";");
665           default:
666             break;
667         }
668       }
669       if (volume != NULL) {
670         AddString (volume);
671       }
672       if (issue != NULL) {
673         AddString ("(");
674         AddString (issue);
675         AddString (")");
676       }
677       if (pages != NULL) {
678         AddString (":");
679         AddString (pages);
680       }
681       AddString ("\n");
682     }
683     rsult = (Boolean) (SendTextToFile (fp, buffer, &para, table) && rsult);
684     ClearString ();
685     buffer = MemFree (buffer);
686   }
687   return rsult;
688 }
689 
MedlineEntryToDataFile(MedlineEntryPtr mep,FILE * fp)690 NLM_EXTERN Boolean MedlineEntryToDataFile (MedlineEntryPtr mep, FILE *fp)
691 
692 {
693   return MedlineEntryToDataFileEx (mep, 0, fp);
694 }
695 
PubmedEntryToDataFile(PubmedEntryPtr pep,FILE * fp)696 NLM_EXTERN Boolean PubmedEntryToDataFile (PubmedEntryPtr pep, FILE *fp)
697 
698 {
699   MedlineEntryPtr  mep;
700 
701   if (pep == NULL || fp == NULL) return FALSE;
702   mep = (MedlineEntryPtr) pep->medent;
703   if (mep == NULL) return FALSE;
704   return MedlineEntryToDataFileEx (mep, pep->pmid, fp);
705 }
706 
707 #ifdef VAR_ARGS
StrngAppend(first,va_alist)708 static CharPtr CDECL StrngAppend (first, va_alist)
709 CharPtr first;
710 va_dcl
711 #else
712 static CharPtr CDECL StrngAppend (CharPtr first, ...)
713 #endif
714 
715 {
716   va_list  args;
717   Uint2    len;
718   CharPtr  rsult;
719   CharPtr  str;
720 
721 #ifdef VAR_ARGS
722   va_start (args);
723 #else
724   va_start (args, first);
725 #endif
726   len = (Uint2) StringLen (first);
727   str = va_arg (args, CharPtr);
728   while (str != NULL) {
729     len += StringLen (str);
730     str = va_arg (args, CharPtr);
731   }
732   va_end(args);
733 
734 #ifdef VAR_ARGS
735   va_start (args);
736 #else
737   va_start (args, first);
738 #endif
739   rsult = MemNew (len + 1);
740   StringCpy (rsult, first);
741   str = va_arg (args, CharPtr);
742   while (str != NULL) {
743     StringCat (rsult, str);
744     str = va_arg (args, CharPtr);
745   }
746   va_end(args);
747   return rsult;
748 }
749 
750 static CharPtr suffixes [] =
751 {"Jr", "Sr", "I", "II", "III", "IV", "V", "VI",
752 "1st", "2nd", "3rd", "4th", "5th", "6th",
753 "1d", "2d", "3d", NULL};
754 
755 static CharPtr prefixes [] =
756 {"van ", "ten ", "ter ", "Mac ", "Mc ", "el ", "al ",
757 "Ben ", "ben ", "Bar ", "den ", NULL};
758 
CleanAuthorString(CharPtr auth)759 static CharPtr CleanAuthorString (CharPtr auth)
760 
761 {
762   Char     ch;
763   CharPtr  first;
764   Int2     i;
765   CharPtr  last;
766   Uint4    len;
767   CharPtr  p;
768   CharPtr  per;
769   CharPtr  ps;
770   CharPtr  str;
771 
772   if (StringLen (auth) > 0) {
773     if (StringCmp (auth, "et al") == 0) {
774       str = StringSave ("...");
775     } else {
776       p = NULL;
777       first = NULL;
778       last = StringSave (auth);
779       ps = StringRChr (last, ' ');
780       if (ps != NULL && ps != StringChr (last, ' ')) {
781         i = 0;
782         while (prefixes [i] != NULL) {
783           len = StringLen (prefixes [i]);
784           if (len > 0 && StringNCmp (last, prefixes [i], len) == 0) {
785             last [len - 1] = '_';
786           }
787           i++;
788         }
789         ps = StringRChr (last, ' ');
790       }
791       if (ps != NULL && ps != StringChr (last, ' ')) {
792         per = StringChr (ps, '.');
793         if (per != NULL) {
794           *per = '\0';
795         }
796         i = 0;
797         while (suffixes [i] != NULL) {
798           if (StringCmp (ps + 1, suffixes [i]) == 0) {
799             *ps = '\0';
800           }
801           i++;
802         }
803         /*
804         p = ps + 1;
805         while (*p != '\0') {
806           if (! IS_UPPER(*p)) {
807             *ps = '\0';
808             p = ps;
809           } else {
810             p++;
811           }
812         }
813         */
814       }
815       ps = StringRChr (last, ' ');
816       if (ps != NULL) {
817         p = ps + 1;
818         *ps = '\0';
819       }
820       if (p != NULL) {
821         len = StringLen (p);
822         first = MemNew (3 * (size_t) len + 1);
823         i = 0;
824         while (*p != '\0') {
825           first [i] = *p;
826           i++;
827           first [i] = '.';
828           i++;
829           first [i] = ' ';
830           i++;
831           p++;
832         }
833       }
834       ps = last;
835       ch = *ps;
836       while (ch != '\0') {
837         if (ch == '_') {
838           *ps = ' ';
839         }
840         ps++;
841         ch = *ps;
842       }
843       if (first != NULL) {
844         str = StrngAppend (first, (CharPtr) last, (CharPtr) NULL);
845         last = MemFree (last);
846         first = MemFree (first);
847       } else {
848         str = last;
849       }
850     }
851   } else {
852     str = StringSave ("");
853   }
854   return str;
855 }
856 
MakeAuthorString(CharPtr name,CharPtr initials,CharPtr suffix)857 static CharPtr MakeAuthorString (
858   CharPtr name,
859   CharPtr initials,
860   CharPtr suffix
861 )
862 
863 {
864   Char     ch;
865   size_t   len;
866   CharPtr  ptr;
867   CharPtr  str;
868   CharPtr  tmp;
869 
870   if (name == NULL) return NULL;
871 
872   len = StringLen (name) + StringLen (initials) * 3 + StringLen (suffix);
873   str = MemNew (sizeof (Char) * (len + 4));
874   if (str == NULL) return NULL;
875 
876   tmp = str;
877 
878   ptr = initials;
879   if (! StringHasNoText (initials)) {
880     ch = *ptr;
881     while (ch != '\0') {
882       if (ch == '-') {
883         *tmp = '-';
884         tmp++;
885       } else if (ch != '.') {
886         *tmp = ch;
887         tmp++;
888         *tmp = '.';
889         tmp++;
890         *tmp = ' ';
891         tmp++;
892       }
893       ptr++;
894       ch = *ptr;
895     }
896     *tmp = '\0';
897   }
898 
899   tmp = StringMove (tmp, name);
900   if (! StringHasNoText (suffix)) {
901     tmp = StringMove (tmp, " ");
902     tmp = StringMove (tmp, suffix);
903   }
904 
905   return str;
906 }
907 
ParseMedline(MedlineEntryPtr mep)908 NLM_EXTERN MedlinePtr ParseMedline (MedlineEntryPtr mep)
909 
910 {
911   AffilPtr         affil;
912   AuthorPtr        ap;
913   AuthListPtr      authors;
914   CharPtr          chptr;
915   CitArtPtr        cit;
916   CitJourPtr       citjour;
917   CharPtr          curr;
918   DatePtr          date;
919   ValNodePtr       gene;
920   ImprintPtr       imp;
921   CharPtr          iso_jta;
922   CharPtr          last;
923   MedlineMeshPtr   mesh;
924   CharPtr          ml_jta;
925   MedlinePtr       mPtr = NULL;
926   ValNodePtr       names;
927   NameStdPtr       nsp;
928   PersonIdPtr      pid;
929   ValNodePtr       qual;
930   Char             str [32];
931   MedlineRnPtr     substance;
932   ValNodePtr       title;
933 
934   buffer = MemNew (BUFSIZE);
935   if (buffer != NULL) {
936     ClearString ();
937     mPtr = MemNew (sizeof (MedlineData));
938     if (mPtr != NULL && mep != NULL) {
939       sprintf (str, "%1ld", (long) mep->uid);
940       mPtr->uid = StringSave (str);
941       cit = mep->cit;
942       if (cit != NULL) {
943         if (cit->from == 1) {
944           citjour = (CitJourPtr) cit->fromptr;
945           if (citjour != NULL) {
946             iso_jta = NULL;
947             ml_jta = NULL;
948             title = citjour->title;
949             while (title != NULL) {
950               if (title->choice == 5) {
951                 iso_jta = title->data.ptrvalue;
952               } else if (title->choice == 6) {
953                 ml_jta = title->data.ptrvalue;
954               }
955               title = title->next;
956             }
957             if (iso_jta != NULL) {
958               AddString (iso_jta);
959               AddString (" ");
960               mPtr->journal = StringSave (buffer);
961               ClearString ();
962             } else if (ml_jta != NULL) {
963               AddString (ml_jta);
964               AddString (" ");
965               mPtr->journal = StringSave (buffer);
966               ClearString ();
967             }
968             imp = citjour->imp;
969             if (imp != NULL) {
970               date = imp->date;
971               if (date != NULL) {
972                 switch (date->data [0]) {
973                   case 0:
974                     StringNCpy (str, date->str, sizeof (str) - 1);
975                     chptr = StringChr (str, ' ');
976                     if (chptr != NULL) {
977                       *chptr = '\0';
978                     }
979                     mPtr->year = StringSave (str);
980                     break;
981                   case 1:
982                     sprintf (str, "%0d", (Int2) (date->data [1] + 1900));
983                     mPtr->year = StringSave (str);
984                   default:
985                     break;
986                 }
987               }
988               mPtr->volume = StringSave (imp->volume);
989               mPtr->pages = StringSave (imp->pages);
990             }
991           }
992         }
993         title = cit->title;
994         while (title != NULL) {
995           switch (title->choice) {
996             case 1:
997               mPtr->title = StringSave ((CharPtr) title->data.ptrvalue);
998               break;
999             case 2:
1000               break;
1001             case 3:
1002               mPtr->transl = StringSave ((CharPtr) title->data.ptrvalue);
1003               break;
1004             default:
1005               break;
1006           }
1007           title = title->next;
1008         }
1009         authors = cit->authors;
1010         if (authors != NULL) {
1011           if (authors->choice == 1 || authors->choice == 2 || authors->choice == 3) {
1012             names = authors->names;
1013             while (names != NULL) {
1014               last = mPtr->authors;
1015               curr = NULL;
1016               if (authors->choice == 1) {
1017                 ap = (AuthorPtr) names->data.ptrvalue;
1018                 if (ap != NULL) {
1019                   pid = ap->name;
1020                   if (pid != NULL) {
1021                     if (pid->choice == 2) {
1022                       nsp = (NameStdPtr) pid->data;
1023                       if (nsp != NULL) {
1024                         if (! StringHasNoText (nsp->names [0])) {
1025                           curr = MakeAuthorString (nsp->names [0], nsp->names [4], nsp->names [5]);
1026                         } else if (! StringHasNoText (nsp->names [3])) {
1027                           curr = MakeAuthorString (nsp->names [3], NULL, NULL);
1028                         }
1029                       }
1030                     } else if (pid->choice == 3 || pid->choice == 4) {
1031                       curr = MakeAuthorString ((CharPtr) pid->data, NULL, NULL);
1032                     }
1033                   }
1034                 }
1035               } else if (authors->choice == 2 || authors->choice == 3) {
1036                 curr = CleanAuthorString ((CharPtr) names->data.ptrvalue);
1037               }
1038               if (last != NULL) {
1039                 if (names->next != NULL) {
1040                   mPtr->authors = StrngAppend (last, (CharPtr) ", ",
1041                                                 (CharPtr) curr, (CharPtr) NULL);
1042                 } else {
1043                   mPtr->authors = StrngAppend (last, (CharPtr) " & ",
1044                                                 (CharPtr) curr, (CharPtr) NULL);
1045                 }
1046                 last = MemFree (last);
1047                 curr = MemFree (curr);
1048               } else {
1049                 mPtr->authors = curr;
1050               }
1051               names = names->next;
1052             }
1053           }
1054           affil = authors->affil;
1055           if (affil != NULL) {
1056             if (affil->choice == 1) {
1057               mPtr->affil = StringSave (affil->affil);
1058             }
1059           }
1060         }
1061       }
1062       mPtr->abstract = StringSave (mep->abstract);
1063       mesh = mep->mesh;
1064       while (mesh != NULL) {
1065         if (mesh->mp) {
1066           StringNCpy (str, "*", sizeof (str));
1067         } else {
1068           StringNCpy (str, "", sizeof (str));
1069         }
1070         last = mPtr->mesh;
1071         if (last != NULL) {
1072           mPtr->mesh = StrngAppend (last, (CharPtr) "\n  ", (CharPtr) str,
1073                                      (CharPtr) mesh->term, (CharPtr) NULL);
1074           last = MemFree (last);
1075         } else {
1076           mPtr->mesh = StrngAppend ((CharPtr) "  ", (CharPtr) str,
1077                                      (CharPtr) mesh->term, (CharPtr) NULL);
1078         }
1079         qual = mesh->qual;
1080         while (qual != NULL) {
1081           if (qual->choice != 0) {
1082             StringNCpy (str, "*", sizeof (str));
1083           } else {
1084             StringNCpy (str, "", sizeof (str));
1085           }
1086           last = mPtr->mesh;
1087           mPtr->mesh = StrngAppend (last, (CharPtr) "/", (CharPtr) str,
1088                                     (CharPtr) qual->data.ptrvalue, (CharPtr) NULL);
1089           last = MemFree (last);
1090           qual = qual->next;
1091         }
1092         mesh = mesh->next;
1093       }
1094       if (mPtr->mesh != NULL) {
1095         last = mPtr->mesh;
1096         mPtr->mesh = StrngAppend (last, (CharPtr) "\n", (CharPtr) NULL);
1097         last = MemFree (last);
1098       }
1099       gene = mep->gene;
1100       if (gene != NULL) {
1101         ClearString ();
1102         while (gene != NULL) {
1103           AddString ("  ");
1104           AddString (gene->data.ptrvalue);
1105           AddString ("\n");
1106           gene = gene->next;
1107         }
1108         mPtr->gene = StringSave (buffer);
1109       }
1110       substance = mep->substance;
1111       if (substance != NULL) {
1112         ClearString ();
1113         while (substance != NULL) {
1114           AddString ("  ");
1115           switch (substance->type) {
1116             case 0:
1117               AddString (substance->name);
1118               break;
1119             case 1:
1120               AddString (substance->name);
1121               AddString (" (");
1122               AddString ("CAS ");
1123               AddString (substance->cit);
1124               AddString (")");
1125               break;
1126             case 2:
1127               AddString (substance->name);
1128               AddString (" (");
1129               AddString ("EC ");
1130               AddString (substance->cit);
1131               AddString (")");
1132               break;
1133             default:
1134               break;
1135           }
1136           AddString ("\n");
1137           substance = substance->next;
1138         }
1139         mPtr->substance = StringSave (buffer);
1140       }
1141     }
1142     ClearString ();
1143     buffer = MemFree (buffer);
1144   }
1145   return mPtr;
1146 }
1147 
FreeMedline(MedlinePtr mPtr)1148 NLM_EXTERN MedlinePtr FreeMedline (MedlinePtr mPtr)
1149 
1150 {
1151   if (mPtr != NULL) {
1152     mPtr->journal = MemFree (mPtr->journal);
1153     mPtr->volume = MemFree (mPtr->volume);
1154     mPtr->pages = MemFree (mPtr->pages);
1155     mPtr->year = MemFree (mPtr->year);
1156     mPtr->title = MemFree (mPtr->title);
1157     mPtr->transl = MemFree (mPtr->transl);
1158     mPtr->authors = MemFree (mPtr->authors);
1159     mPtr->affil = MemFree (mPtr->affil);
1160     mPtr->abstract = MemFree (mPtr->abstract);
1161     mPtr->mesh = MemFree (mPtr->mesh);
1162     mPtr->gene = MemFree (mPtr->gene);
1163     mPtr->substance = MemFree (mPtr->substance);
1164     mPtr->uid = MemFree (mPtr->uid);
1165     mPtr = MemFree (mPtr);
1166   }
1167   return NULL;
1168 }
1169 
1170 static ColData  colFmt [3] = {{0, 0, 0, 'l', TRUE, TRUE, FALSE},
1171                               {0, 0, 0, 'l', TRUE, TRUE, FALSE},
1172                               {0, 0, 0, 'l', TRUE, TRUE, TRUE}};
1173 
1174 static ColData  mshFmt [1] = {{0, 80, 0, 'l', FALSE, FALSE, TRUE}};
1175 
MedlineEntryToDocOrAbsFile(MedlineEntryPtr mep,Int4 pmid,FILE * fp,Boolean showMesh)1176 static Boolean MedlineEntryToDocOrAbsFile (MedlineEntryPtr mep, Int4 pmid, FILE *fp, Boolean showMesh)
1177 
1178 {
1179   size_t      len;
1180   MedlinePtr  mPtr;
1181   ParData     para;
1182   CharPtr     ptr;
1183   Boolean     rsult;
1184   CharPtr     tmp;
1185 
1186   rsult = TRUE;
1187   if (fp != NULL && mep != NULL) {
1188     mPtr = ParseMedline (mep);
1189     if (mPtr != NULL) {
1190       buffer = MemNew (BUFSIZE);
1191       if (buffer != NULL) {
1192         para.openSpace = FALSE;
1193         ClearString ();
1194         AddString (mPtr->journal);
1195         AddString ("\t");
1196         AddString (mPtr->volume);
1197         AddString (":\t");
1198         AddString (mPtr->pages);
1199         AddString ("  (");
1200         AddString (mPtr->year);
1201         AddString (")");
1202         AddString (" [");
1203         AddString (mPtr->uid);
1204         AddString ("]");
1205         AddString ("\n");
1206         rsult = (Boolean) (SendTextToFile (fp, buffer, &para, colFmt) && rsult);
1207         ClearString ();
1208         AddString (mPtr->title);
1209         AddString ("\n");
1210         rsult = (Boolean) (SendTextToFile (fp, buffer, NULL, NULL) && rsult);
1211         ClearString ();
1212         if (mPtr->transl != NULL) {
1213           AddString ("[");
1214           AddString (mPtr->transl);
1215           AddString ("]\n");
1216           rsult = (Boolean) (SendTextToFile (fp, buffer, NULL, NULL) && rsult);
1217           ClearString ();
1218         }
1219         AddString (mPtr->authors);
1220         AddString ("\n");
1221         rsult = (Boolean) (SendTextToFile (fp, buffer, NULL, NULL) && rsult);
1222         ClearString ();
1223         if (mPtr->affil != NULL) {
1224           AddString (mPtr->affil);
1225           AddString ("\n");
1226           rsult = (Boolean) (SendTextToFile (fp, buffer, NULL, NULL) && rsult);
1227           ClearString ();
1228         }
1229         if (mPtr->abstract != NULL) {
1230           len = StringLen (mPtr->abstract);
1231           tmp = (CharPtr) MemNew (sizeof (Char) * (len + 10));
1232           ptr = StringMove (tmp, mPtr->abstract);
1233           ptr = StringMove (ptr, "\n");
1234           rsult = (Boolean) (SendTextToFile (fp, tmp, NULL, NULL) && rsult);
1235           MemFree (tmp);
1236         }
1237         if (showMesh) {
1238           if (mPtr->mesh != NULL) {
1239             rsult = (Boolean) (SendTextToFile (fp, "MeSH Terms:\n", NULL, NULL) && rsult);
1240             rsult = (Boolean) (SendTextToFile (fp, mPtr->mesh, &para, mshFmt) && rsult);
1241           }
1242           if (mPtr->gene != NULL) {
1243             rsult = (Boolean) (SendTextToFile (fp, "Gene Symbols:\n", NULL, NULL) && rsult);
1244             rsult = (Boolean) (SendTextToFile (fp, mPtr->gene, &para, mshFmt) && rsult);
1245           }
1246           if (mPtr->substance != NULL) {
1247             rsult = (Boolean) (SendTextToFile (fp, "Substances:\n", NULL, NULL) && rsult);
1248             rsult = (Boolean) (SendTextToFile (fp, mPtr->substance, &para, mshFmt) && rsult);
1249           }
1250         }
1251         buffer = MemFree (buffer);
1252       }
1253       mPtr = FreeMedline (mPtr);
1254     }
1255   }
1256   return rsult;
1257 }
1258 
MedlineEntryToDocFile(MedlineEntryPtr mep,FILE * fp)1259 NLM_EXTERN Boolean MedlineEntryToDocFile (MedlineEntryPtr mep, FILE *fp)
1260 
1261 {
1262   return MedlineEntryToDocOrAbsFile (mep, 0, fp, TRUE);
1263 }
1264 
MedlineEntryToAbsFile(MedlineEntryPtr mep,FILE * fp)1265 NLM_EXTERN Boolean MedlineEntryToAbsFile (MedlineEntryPtr mep, FILE *fp)
1266 
1267 {
1268   return MedlineEntryToDocOrAbsFile (mep, 0, fp, FALSE);
1269 }
1270 
PubmedEntryToDocFile(PubmedEntryPtr pep,FILE * fp)1271 NLM_EXTERN Boolean PubmedEntryToDocFile (PubmedEntryPtr pep, FILE *fp)
1272 
1273 {
1274   MedlineEntryPtr  mep;
1275 
1276   if (pep == NULL || fp == NULL) return FALSE;
1277   mep = (MedlineEntryPtr) pep->medent;
1278   if (mep == NULL) return FALSE;
1279   return MedlineEntryToDocOrAbsFile (mep, pep->pmid, fp, TRUE);
1280 }
1281 
PubmedEntryToAbsFile(PubmedEntryPtr pep,FILE * fp)1282 NLM_EXTERN Boolean PubmedEntryToAbsFile (PubmedEntryPtr pep, FILE *fp)
1283 
1284 {
1285   MedlineEntryPtr  mep;
1286 
1287   if (pep == NULL || fp == NULL) return FALSE;
1288   mep = (MedlineEntryPtr) pep->medent;
1289   if (mep == NULL) return FALSE;
1290   return MedlineEntryToDocOrAbsFile (mep, pep->pmid, fp, FALSE);
1291 }
1292 
1293 #define IBM_MEDLINE_DIVSS '$'
1294 #define IBM_MEDLINE_DIVSV '&'
1295 #define IBM_MEDLINE_DIVEV '#'
1296 #define SIZE_OF_ARRAY(x)  (sizeof(x)/sizeof(x[0]))
1297 
1298 typedef struct {
1299     char  cSubHead[4];
1300     char* pFullName;
1301   } SSubheadAbbr;
1302 
1303 static SSubheadAbbr theSubHead [] = {
1304   { "VE", "veterinary" },
1305   { "UR", "urine" },
1306   { "UT", "utilization" },
1307   { "UY", "Uruguay" },
1308   { "UL", "ultrastructure" },
1309   { "US", "ultrasonography" },
1310   { "TD", "trends" },
1311   { "TR", "transplantation" },
1312   { "TM", "transmission" },
1313   { "TO", "toxicity" },
1314   { "TH", "therapy" },
1315   { "TU", "therapeutic use" },
1316   { "SU", "surgery" },
1317   { "SD", "supply & distribution" },
1318   { "SN", "statistics & numerical data" },
1319   { "ST", "standards" },
1320   { "SE", "secretion" },
1321   { "SC", "secondary" },
1322   { "RH", "rehabilitation" },
1323   { "RT", "radiotherapy" },
1324   { "RI", "radionuclide imaging" },
1325   { "RA", "radiography" },
1326   { "RE", "radiation effects" },
1327   { "PX", "psychology" },
1328   { "PC", "prevention & control" },
1329   { "PO", "poisoning" },
1330   { "PP", "physiopathology" },
1331   { "PH", "physiology" },
1332   { "PD", "pharmacology" },
1333   { "PK", "pharmacokinetics" },
1334   { "PA", "pathology" },
1335   { "PY", "pathogenicity" },
1336   { "PS", "parasitology" },
1337   { "OG", "organization & administration" },
1338   { "NU", "nursing" },
1339   { "NP", "Nepal" },
1340   { "MO", "mortality" },
1341   { "MI", "microbiology" },
1342   { "MT", "methods" },
1343   { "ME", "metabolism" },
1344   { "MA", "manpower" },
1345   { "LJ", "legislation & jurisprudence" },
1346   { "IP", "isolation & purification" },
1347   { "IS", "instrumentation" },
1348   { "IR", "innervation" },
1349   { "IN", "injuries" },
1350   { "PR", "in pregnancy" },
1351   { "OA", "in old age" },
1352   { "MY", "in middle age" },
1353   { "IC", "in infancy & childhood" },
1354   { "AU", "in adulthood" },
1355   { "AO", "in adolescence" },
1356   { "IM", "immunology" },
1357   { "IL", "Illinois" },
1358   { "HI", "history" },
1359   { "GD", "growth & development" },
1360   { "GE", "genetics" },
1361   { "ET", "etiology" },
1362   { "EH", "ethnology" },
1363   { "EP", "epidemiolgy" },
1364   { "EN", "enzymology" },
1365   { "EM", "embryology" },
1366   { "ED", "education" },
1367   { "EC", "economics" },
1368   { "DT", "drug therapy" },
1369   { "DE", "drug effects" },
1370   { "DH", "diet therapy" },
1371   { "DU", "diagnostic use" },
1372   { "DI", "diagnosis" },
1373   { "DF", "deficiency" },
1374   { "CI", "chemically induced" },
1375   { "CY", "cytology" },
1376   { "CT", "contraindications" },
1377   { "CN", "congenital" },
1378   { "CO", "complications" },
1379   { "CL", "classification" },
1380   { "CH", "chemistry" },
1381   { "CL", "chemistry induced" },
1382   { "CS", "chemical synthesis" },
1383   { "CD", "Chad" },
1384   { "CF", "cerebrospinal fluid" },
1385   { "BS", "blood supply" },
1386   { "BL", "blood" },
1387   { "BI", "biosynthesis" },
1388   { "BT", "Bhutan" },
1389   { "AI", "antagonists & inhibitors" },
1390   { "AH", "anatomy & histology" },
1391   { "AN", "analysis" },
1392   { "AA", "analogs & derivatives" },
1393   { "AE", "adverse effects" },
1394   { "AD", "administration & dosage" },
1395   { "AB", "abnormalities" },
1396   { "AG", "AG" },
1397   { "VI", "VI" }
1398 };
1399 
1400 /****************************************************************************/
1401 /*.doc GetTopicSubHead (internal) */
1402 /*+
1403   This function search subhead using subhead abbreviation. Return
1404   pointer to founded subhead or original subhead abbreviation if
1405   subhead not found.
1406 -*/
1407 /****************************************************************************/
1408 static char*
GetTopicSubHead(char * lpSubHead)1409 /*FCN*/GetTopicSubHead (
1410   char* lpSubHead
1411 ){
1412     register int i;            /* fast index */
1413 
1414     for ( i = 0; i < SIZE_OF_ARRAY(theSubHead); i++ ) {
1415          if ( StringICmp (lpSubHead, theSubHead[i].cSubHead)
1416                                                                 == 0 ) {
1417              return theSubHead[i].pFullName; /* return full name */
1418 	   }
1419        }
1420 
1421     return lpSubHead;          /* return original subhead */
1422   }                                /* GetTopicSubHead() */
1423 
1424 /****************************************************************************/
1425 /*.doc TranslateMesh (internal) */
1426 /*+
1427    This function translate MeSH string to standart printable form
1428 -*/
1429 /****************************************************************************/
1430 static void
TranslateMesh(char * lpOut,char * lpRecord)1431 /*FCN*/TranslateMesh (
1432   char* lpOut,
1433   char* lpRecord
1434 ){
1435     register char* lpTemp;               /* Temporary pointer */
1436     char*          lpMainTerm;           /* Main termin */
1437     int            iDescClass;           /* Descriptor Class */
1438     char           cInputType;           /* Input type */
1439 
1440     /* extract Mesh Term from Mesh record */
1441     if ( (lpTemp = strchr (lpRecord, IBM_MEDLINE_DIVSS)) != NULL ) {
1442         *lpTemp = '\0';         /* set EOS for Mesh Term */
1443         lpTemp++;               /* lpTemp set to next character after $ */
1444       } else {
1445         strcpy(lpOut,lpRecord);
1446         return;
1447       }
1448 
1449     lpMainTerm = lpRecord;
1450     strcpy(lpOut,lpMainTerm);
1451 
1452     /* Skip descriptor class. A number that designates to
1453        what class the MeSH heading belongs as follows:
1454        1 - an INDEX MEDICUS major descriptor
1455        2 - a citation type major descriptor, e.g., ENGLISH ABSTRACT
1456        3 - a check tag major descriptor, e.g., HUMAN
1457        4 - a geographic major descriptor, e.g., FRANCE
1458        5 - a non-MeSH major descriptor, e.g., PATIENT CARE
1459            MANAGEMENT (NON MESH)
1460        6 - a withdrawn major descriptor
1461     */
1462     if ( isdigit((int)(*lpTemp)) ) {
1463         lpRecord = lpTemp;
1464         lpTemp++;
1465         iDescClass = atoi (lpRecord);
1466         iDescClass = iDescClass;       /* Do not use descriptor class */
1467       }
1468 
1469     /* Skip next subelement. Value is I or M. 'I' means an indexer
1470        input the Heading. 'M' means it was attached throwgh
1471        computer mapping
1472     */
1473     if (    *lpTemp == IBM_MEDLINE_DIVSS
1474          && (*(lpTemp+1) == 'I' || *(lpTemp+1) == 'M') ) {
1475         lpTemp++;                         /* skip IBM_MEDLINE_DIVSS */
1476         cInputType = *lpTemp++;
1477         cInputType = cInputType;
1478       }
1479 
1480     /* Qualifier List. A list of two-letter subheading (qualifier)
1481        abbreviations, separated by slashes if there is more than
1482        one value. Each subheading abbreviation may have an *
1483        (central concept indicator) preceding it. This subelement
1484        may consist of a single *, which indicates the MeSH
1485        heading alone is a central concept of the article.
1486     */
1487     if ( *lpTemp == IBM_MEDLINE_DIVSS ) {
1488         int        bIsCentralConcept;
1489         char       cSubHead[3];
1490 
1491         lpTemp++;               /* skip IBM_MEDLINE_DIVSS */
1492         cSubHead[2] = '\0';     /* set EOL */
1493 
1494         /* read tokens from qualifier list */
1495         while ( (cSubHead[0]=*lpTemp++) != '\0' ) {
1496              bIsCentralConcept = 0;
1497              if ( cSubHead[0] == '*' ) { /* is central concept mark? */
1498                  cSubHead[0] = *lpTemp++;
1499                  if ( cSubHead[0] == '/' ) {
1500                      strcpy(lpOut,"*");
1501                      strcat(lpOut,lpMainTerm);
1502                      continue;
1503 		   }
1504                  if (    cSubHead[0] == '\0'
1505                       || cSubHead[0] == IBM_MEDLINE_DIVEV
1506                       || cSubHead[0] == IBM_MEDLINE_DIVSV ) {
1507                      strcpy(lpOut,"*");
1508                      strcat(lpOut,lpMainTerm);
1509                      break;
1510 		   }
1511                  bIsCentralConcept = 1;
1512 	       }
1513              if ( (cSubHead[1] = *lpTemp++) == '\0' ) {
1514                  /* Special case for mii.d80.back66.rf, it has a bad data
1515                     in MeSH heading for entry 68324942
1516                  */
1517                  break;
1518 	       }
1519              strcat(lpOut,"/");
1520              if ( bIsCentralConcept == 1 ) {
1521                  strcat(lpOut,"*");
1522 	       }
1523              strcat(lpOut,GetTopicSubHead(cSubHead));
1524              if ( *lpTemp == '/' ) {
1525                  lpTemp++;
1526 	       } else if (    *lpTemp == IBM_MEDLINE_DIVEV
1527                          || *lpTemp == IBM_MEDLINE_DIVSV ) {
1528                  /* ignore Sort version and Entry version */
1529                  break;
1530 	       }
1531 	   }
1532       }
1533 
1534     return;
1535   }                                /* TranslateMesh() */
1536 
1537 
1538 /***********************************************************************/
1539 /*.doc MedlarsEntryToDataFile (external) */
1540 /*+
1541    Function send MEDLARS entry to I/O stream
1542 -*/
1543 /***********************************************************************/
1544 NLM_EXTERN Boolean
MedlarsEntryToDataFile(MedlarsEntryPtr mep,FILE * fp)1545 /*FCN*/MedlarsEntryToDataFile (
1546   MedlarsEntryPtr mep,
1547   FILE *fp
1548 ){
1549     ParData thePara;
1550     CharPtr lpBuffer;
1551     MedlarsRecordPtr pRecord;
1552     Boolean bResult = TRUE;
1553     char buf[BUFSIZE];
1554     int i, exist;
1555     char* ptr;
1556 #define MAX_ELHILL 24
1557     int ElhillOrder[MAX_ELHILL] = {
1558       /* UI */ MEDLINE_UI,
1559       /* AU */ MEDLINE_AU,
1560       /* TI */ MEDLINE_TI,
1561       /* LA */ MEDLINE_LA,
1562       /* MH */ MEDLINE_MH,
1563       /* RN */ MEDLINE_RN,
1564       /* PT */ MEDLINE_PT,
1565       /* ID */ MEDLINE_ID,
1566       /* DA */ MEDLINE_DA,
1567       /* DP */ MEDLINE_DP,
1568       /* IS */ MEDLINE_IS,
1569       /* TA */ MEDLINE_TA,
1570       /* PG */ MEDLINE_PG,
1571       /* SB */ MEDLINE_SB,
1572       /* CY */ MEDLINE_CY,
1573       /* IP */ MEDLINE_IP,
1574       /* VI */ MEDLINE_VI,
1575       /* JC */ MEDLINE_JC,
1576       /* AA */ MEDLINE_AA,
1577       /* EM */ MEDLINE_EM,
1578       /* AB */ MEDLINE_AB,
1579       /* AD */ MEDLINE_AD,
1580       /* RF */ MEDLINE_RF,
1581       /* RO */ MEDLINE_RO
1582     };
1583 
1584     char* TA="";
1585     char* DP="";
1586     char* VI="";
1587     char* IP="";
1588     char* PG="";
1589 
1590     if ( mep == NULL || fp == NULL ) {
1591         return FALSE;
1592       }
1593 
1594     MemSet (&thePara, 0, sizeof(thePara));
1595 
1596     if ( (lpBuffer=MemNew(BUFSIZE)) == NULL ) return FALSE;
1597 
1598     /* First run to print known Elhill codes */
1599     for( i = 0; i < MAX_ELHILL; i++ ) {
1600 
1601         for ( pRecord = mep->recs;
1602               pRecord != NULL;
1603               pRecord = pRecord->next ) {
1604 
1605           if( pRecord->code != ElhillOrder[i] ) continue;
1606 
1607           if ( pRecord->abbr != NULL ) {
1608             /* This record has record type abbreviation */
1609             sprintf( lpBuffer, "%-4s-\t", pRecord->abbr );
1610           } else {
1611             /* This record has no record type abbreviation, use number */
1612             sprintf ( lpBuffer, "%-4d-\t", pRecord->code );
1613           }
1614 
1615           if ( MEDLINE_TA == pRecord->code )
1616             TA = pRecord->data; /* TA - name of journal */
1617           if ( MEDLINE_DP == pRecord->code )
1618             DP = pRecord->data; /* DP - date of publication */
1619           if ( MEDLINE_VI == pRecord->code )
1620             VI = pRecord->data; /* VI - volume number */
1621           if ( MEDLINE_IP == pRecord->code )
1622             IP = pRecord->data; /* IP - issue number */
1623           if ( MEDLINE_PG == pRecord->code )
1624             PG = pRecord->data; /* PG - page numbers */
1625 
1626 
1627            switch( pRecord->code ) {
1628 
1629              case MEDLINE_MH:
1630                TranslateMesh( buf, pRecord->data);
1631                StringCat(lpBuffer,buf);
1632                break;
1633 
1634              case MEDLINE_RO:
1635                strncpy( buf, pRecord->data, BUFSIZE-1 );
1636                for ( ptr = buf; *ptr; ptr++ )
1637                  if( '$' == *ptr ) *ptr = ':';
1638                StringCat( lpBuffer, buf );
1639                break;
1640 
1641              case MEDLINE_ID:
1642                strncpy( buf, pRecord->data, BUFSIZE-1 );
1643                for ( ptr = buf; *ptr; ptr++ )
1644                  if( '$' == *ptr ) *ptr = '/';
1645                StringCat( lpBuffer, buf );
1646                break;
1647 
1648              default:
1649                StringCat(lpBuffer,pRecord->data);
1650                break;
1651 
1652           }
1653 
1654           StringCat(lpBuffer,"\n");
1655 
1656           if ( SendTextToFile (fp, lpBuffer, &thePara, table) != TRUE ) {
1657             MemFree(lpBuffer);
1658             return FALSE;
1659           }
1660       }
1661   }
1662 
1663      /* Second run to print unknown Elhill codes */
1664      for ( pRecord = mep->recs;
1665            pRecord != NULL;
1666            pRecord = pRecord->next ) {
1667 
1668        exist = 0;
1669        for( i = 0; i < MAX_ELHILL; i++ ) {
1670          if( pRecord->code == ElhillOrder[i] ) {
1671            exist = 1;
1672            break;
1673          }
1674        }
1675        if( exist ) continue;
1676        if ( pRecord->abbr != NULL ) {
1677          /* This record has record type abbreviation */
1678          sprintf (
1679            lpBuffer,
1680            "%-4s-\t",
1681            pRecord->abbr
1682          );
1683        } else {
1684          /* This record has no record type abbreviation, use number */
1685          sprintf (
1686            lpBuffer,
1687            "%-4d-\t",
1688            pRecord->code
1689          );
1690        }
1691 
1692        StringCat(lpBuffer,pRecord->data);
1693        StringCat(lpBuffer,"\n");
1694 
1695        if ( SendTextToFile (fp, lpBuffer, &thePara, table) != TRUE ) {
1696          MemFree(lpBuffer);
1697          return FALSE;
1698        }
1699      }
1700 
1701     /* Generate SO field */
1702     strcpy( lpBuffer,"SO  -\t");
1703     strcat( lpBuffer, TA );
1704     strcat( lpBuffer," " );
1705     strcat( lpBuffer, DP );
1706     strcat( lpBuffer,";" );
1707     strcat( lpBuffer, VI );
1708     if ( *IP != '\0' ) {
1709       strcat( lpBuffer,"(");
1710       strcat( lpBuffer, IP );
1711       strcat( lpBuffer,")" );
1712     }
1713     strcat( lpBuffer, ":" );
1714     strcat( lpBuffer, PG );
1715     strcat(lpBuffer,"\n");
1716 
1717     if ( SendTextToFile (fp, lpBuffer, &thePara, table) != TRUE )
1718       bResult = FALSE;
1719 
1720     MemFree(lpBuffer);
1721     return bResult;
1722 }                               /* MedlarsEntryToDataFile() */
1723 
1724 /***********************************************************************/
1725 /*.doc MedlarsEntryToDocFile (external) */
1726 /*+
1727    Function send MEDLARS entry to I/O stream
1728 -*/
1729 /***********************************************************************/
1730 NLM_EXTERN Boolean
MedlarsEntryToDocFile(MedlarsEntryPtr mep,FILE * fp)1731 /*FCN*/MedlarsEntryToDocFile (
1732   MedlarsEntryPtr mep,
1733   FILE *fp
1734 ){
1735     if ( mep == NULL || fp == NULL ) {
1736         return FALSE;
1737     }
1738     return TRUE;
1739 }                               /* MedlarsEntryToDocFile() */
1740 
1741 /***********************************************************************/
1742 /*.doc MedlarsEntryToAbsFile (external) */
1743 /*+
1744    Function send MEDLARS entry to I/O stream
1745 -*/
1746 /***********************************************************************/
1747 NLM_EXTERN Boolean
MedlarsEntryToAbsFile(MedlarsEntryPtr mep,FILE * fp)1748 /*FCN*/MedlarsEntryToAbsFile (
1749   MedlarsEntryPtr mep,
1750   FILE *fp
1751 ){
1752     if ( mep == NULL || fp == NULL ) {
1753         return FALSE;
1754     }
1755     return TRUE;
1756 }                               /* MedlarsEntryToAbsFile() */
1757 
1758