1 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2   backend-dbiba.c defines the DocBook V.3.1 bibliography output backend
3   of refdbd (helper functions)
4   markus@mhoenicka.de 2001-01-18
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 
20   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
21 
22 
23 #include <string.h>
24 #include <stdio.h>
25 #include <dbi/dbi.h>
26 #include <syslog.h>
27 #include <ctype.h> /* for isdigit() */
28 #include <limits.h> /* for MAX_INT */
29 
30 #include "refdb.h"
31 #include "backend.h"
32 #include "xmlhelper.h"
33 #include "backend-dbib.h"
34 #include "strfncs.h"
35 #include "linklist.h"
36 #include "refdbd.h"
37 #include "tokenize.h"
38 #include "dbfncs.h"
39 #include "risdb.h"
40 #include "authorinfo.h"
41 #include "connect.h"
42 #include "mset.h"
43 
44 extern int n_log_level;
45 extern char main_db[];
46 
47 
48 /* forward declarations of local functions */
49 static char* arabic_to_roman(char* roman, const char* arabic);
50 static int format_authorname(char** ptr_ref, size_t* ptr_ref_len, struct AUTHOR_INFO* ptr_ainfo, const char* authorsep, const char* nameorder, const char* initialstyle, const char* author_upper, const char* author_preceeding, const char* author_following, int nis_intext, int type, const char* ns, struct xmlindent* ptr_indent, int n_ref_format);
51 static char* format_day(char* ref, size_t* ptr_ref_len, const char* day, const char* dayformat, const char* pad);
52 static char* format_firstmiddlename(char** ptr_ref, size_t* ptr_ref_len, struct AUTHOR_INFO* ptr_ainfo, const char* author_upper, const char* initialstyle, int nis_intext, int type, const char* ns, struct xmlindent* ptr_indent, int n_ref_format);
53 static char* format_lastname(char** ptr_ref, size_t* ptr_ref_len, char* lastname, const char* author_upper, int nis_intext, int type, const char* ns, struct xmlindent* ptr_indent);
54 static char* format_month(char* ref, size_t* ptr_ref_len, const char* month, const char* monthformat, const char* pad, dbi_result dbirescit);
55 static char* format_year(char* ref, size_t* ptr_ref_len, unsigned short n_year, const char* yearformat, const char* pad, const char* unique_suffix);
56 static char* normalize_pages(char* new_endpage, const char* startpage, const char* endpage, const char* format);
57 
58 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
59   format_refnumber(): formats the refnumber part of a bibliography entry
60                       as a DocBook bibliomixed text
61 
62   char* format_refnumber returns ptr to the buffer if successful, NULL if failed
63 
64   char** ptr_ref ptr to a ptr to a buffer created with malloc which will receive
65         the output. The calling function must allocate the buffer
66         with at least 4096 byte. This function will reallocate the
67         buffer as needed. *ptr will be updated whenever a realloc is
68         necessary. The calling function is responsible for freeing the
69         memory again.
70 
71   size_t* ptr_ref_len ptr to an int holding the current length of ref.
72                      Will be modified if ref is reallocated.
73 
74   struct BIBCONNS* ptr_bibconns ptr to structure with database connections
75 
76   dbi_result dbires ptr to a dbi result structure containing the
77                     current reference
78 
79   dbi_result dbires_ref ptr to a row containing the pubtype style
80 
81   int nref_counter number of current dataset in bibliography sequence
82 
83   int n_intext_subseq will not be used unless pubtype=INTEXT. Set to 1
84                   to format the intext citation for subsequent citations
85                   of the same publication. Set to 0 to format the first
86                   citation
87 
88   const char* ns optional namespace prefix
89 
90   struct xmlindent* ptr_indent  indentation information
91 
92   int n_ref_format requested output format: REFDOCBK, REFDOCBKX, REFTEIX
93 
94   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_refnumber(char ** ptr_ref,size_t * ptr_ref_len,struct BIBCONNS * ptr_bibconns,dbi_result dbires,dbi_result dbires_ref,int nref_counter,int n_intext_subseq,const char * ns,struct xmlindent * ptr_indent,int n_ref_format)95 char* format_refnumber(char** ptr_ref, size_t* ptr_ref_len, struct BIBCONNS* ptr_bibconns, dbi_result dbires, dbi_result dbires_ref, int nref_counter, int n_intext_subseq, const char* ns, struct xmlindent* ptr_indent, int n_ref_format) {
96   char* new_ref;
97   char* item;
98   char buffer[16];
99 /*   dbi_conn conn; */
100 
101 /*   conn = dbi_result_get_conn(dbires_ref); */
102 
103   if (n_ref_format == REFTEIX5) {
104     if (print_elstart_x(ptr_ref, ptr_ref_len, "abbr", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
105       return NULL;
106     }
107   }
108   else {
109     if (print_elstart_x(ptr_ref, ptr_ref_len, "abbrev", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
110       return NULL;
111     }
112   }
113 
114   /* get the result string in an allocated buffer */
115   item = my_dbi_result_get_string_copy_idx(dbires_ref, REFNUMBERPRECEEDING);
116   if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* preceeding */
117     if (sgml_entitize(&item, NULL) == NULL) {
118       free(item);
119       return NULL;
120     }
121 
122     if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
123       free(item);
124       return NULL;
125     }
126     else {
127       *ptr_ref = new_ref;
128     }
129   }
130   if (item) {
131     free(item);
132   }
133 
134   sprintf(buffer, "%d", nref_counter);
135   if ((new_ref = mstrcat(*ptr_ref, buffer, ptr_ref_len, 0)) == NULL) {
136     return NULL;
137   }
138   else {
139     *ptr_ref = new_ref;
140   }
141 
142   item = my_dbi_result_get_string_copy_idx(dbires_ref, REFNUMBERFOLLOWING);
143   if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* following */
144     if (sgml_entitize(&item, NULL) == NULL) {
145       free(item);
146       return NULL;
147     }
148 
149     if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
150       free(item);
151       return NULL;
152     }
153     else {
154       *ptr_ref = new_ref;
155     }
156   }
157   if (item) {
158     free(item);
159   }
160 
161   if (n_ref_format == REFTEIX5) {
162     if (print_elend_x(ptr_ref, ptr_ref_len, "abbr", ptr_indent, ns) == NULL) {
163       return NULL;
164     }
165   }
166   else {
167     if (print_elend_x(ptr_ref, ptr_ref_len, "abbrev", ptr_indent, ns) == NULL) {
168       return NULL;
169     }
170   }
171 
172   return *ptr_ref;
173 }
174 
175 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
176   format_citekey(): formats the citekey part of a bibliography entry
177                       as a DocBook bibliomixed text
178 
179   char* format_citekey returns ptr to the buffer if successful, NULL if failed
180 
181   char** ptr_ref ptr to a ptr to a buffer created with malloc which will receive
182         the output. The calling function must allocate the buffer
183         with at least 4096 byte. This function will reallocate the
184         buffer as needed. *ptr will be updated whenever a realloc is
185         necessary. The calling function is responsible for freeing the
186         memory again.
187 
188   size_t* ptr_ref_len ptr to an int holding the current length of ref.
189                      Will be modified if ref is reallocated.
190 
191   struct BIBCONNS* ptr_bibconns ptr to structure with database connections
192 
193   dbi_result dbires ptr to a dbi result structure containing the
194                     current reference
195 
196   dbi_result dbires_ref ptr to a row containing the pubtype style
197 
198   int n_intext_subseq will not be used unless pubtype=INTEXT. Set to 1
199                   to format the intext citation for subsequent citations
200                   of the same publication. Set to 0 to format the first
201                   citation
202 
203   const char* ns optional namespace prefix
204 
205   struct xmlindent* ptr_indent  indentation information
206 
207   int n_ref_format requested output format: REFDOCBK, REFDOCBKX, REFTEIX
208 
209   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_citekey(char ** ptr_ref,size_t * ptr_ref_len,struct BIBCONNS * ptr_bibconns,dbi_result dbires,dbi_result dbires_ref,int n_intext_subseq,const char * ns,struct xmlindent * ptr_indent,int n_ref_format)210 char* format_citekey(char** ptr_ref, size_t* ptr_ref_len, struct BIBCONNS* ptr_bibconns, dbi_result dbires, dbi_result dbires_ref, int n_intext_subseq, const char* ns, struct xmlindent* ptr_indent, int n_ref_format) {
211   char* new_ref;
212   char* item;
213 
214   if (n_ref_format == REFTEIX5) {
215     if (print_elstart_x(ptr_ref, ptr_ref_len, "abbr", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
216       return NULL;
217     }
218   }
219   else {
220     if (print_elstart_x(ptr_ref, ptr_ref_len, "abbrev", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
221       return NULL;
222     }
223   }
224 
225   /* get the result string in an allocated buffer */
226   item = my_dbi_result_get_string_copy_idx(dbires_ref, CITEKEYPRECEEDING);
227   if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* preceeding */
228     if (sgml_entitize(&item, NULL) == NULL) {
229       free(item);
230       return NULL;
231     }
232 
233     if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
234       free(item);
235       return NULL;
236     }
237     else {
238       *ptr_ref = new_ref;
239     }
240   }
241   if (item) {
242     free(item);
243   }
244 
245   /* get citation key */
246   item = my_dbi_result_get_string_copy_idx(dbires, REFDB_CITEKEY);
247   if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* preceeding */
248     if (sgml_entitize(&item, NULL) == NULL) {
249       free(item);
250       return NULL;
251     }
252 
253     if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
254       free(item);
255       return NULL;
256     }
257     else {
258       *ptr_ref = new_ref;
259     }
260   }
261   if (item) {
262     free(item);
263   }
264 
265 
266   item = my_dbi_result_get_string_copy_idx(dbires_ref, CITEKEYFOLLOWING);
267   if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* following */
268     if (sgml_entitize(&item, NULL) == NULL) {
269       free(item);
270       return NULL;
271     }
272 
273     if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
274       free(item);
275       return NULL;
276     }
277     else {
278       *ptr_ref = new_ref;
279     }
280   }
281   if (item) {
282     free(item);
283   }
284 
285   if (n_ref_format == REFTEIX5) {
286     if (print_elend_x(ptr_ref, ptr_ref_len, "abbr", ptr_indent, ns) == NULL) {
287       return NULL;
288     }
289   }
290   else {
291     if (print_elend_x(ptr_ref, ptr_ref_len, "abbrev", ptr_indent, ns) == NULL) {
292       return NULL;
293     }
294   }
295 
296   return *ptr_ref;
297 }
298 
299 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
300   format_authorlist(): formats the author/editor/seditorlist part of a
301                       bibliography entry as a DocBook bibliomixed text
302 
303   int format_authorlist returns 0 if successful, >0 if failed
304 
305   char** ptr_ref ptr to a ptr to a buffer created with malloc which will receive
306         the output. This function will reallocate the
307         buffer as needed. *ptr will be updated whenever a realloc is
308         necessary. The calling function is responsible for freeing the
309         memory again.
310 
311   size_t* ptr_ref_len ptr to an int holding the current length of ref.
312                      Will be modified if ref is reallocated.
313 
314   struct BIBCONNS* ptr_bibconns ptr to struct with dbi connections
315 
316   dbi_result dbires ptr to a dbi result structure containing the current
317                     reference. This may be NULL if the refdb_id is
318 		    provided in the ptr_biblio_info structure
319 
320   dbi_result dbires_ref ptr to a dbi result structure containing the
321                     pubtype style
322 
323   int type 1=part authors, 2=publication authors, 3=series authors
324            4=first available
325 
326   const char* database ptr to string containing the database with the
327                        author data
328 
329   int n_intext  0 = bibliography citation; 1 = intext citation; 2 =
330                     intext citation subsequent
331 
332   struct bibinfo* ptr_biblio_info ptr to struct with additional bibliographic
333                   info
334 
335   short title_as_author if >0 the reference has no authors and the style
336                   expects the title to be printed instead
337 		  1=title, 2=booktitle
338 
339   const char* ns optional namespace prefix
340 
341   struct xmlindent* ptr_indent  indentation information
342 
343   int n_ref_format requested output format: REFDOCBK, REFDOCBKX, REFTEIX
344 
345   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_authorlist(char ** ptr_ref,size_t * ptr_ref_len,struct BIBCONNS * ptr_bibconns,dbi_result dbires,dbi_result dbires_ref,int type,const char * database,int n_intext,struct bibinfo * ptr_biblio_info,short title_as_author,const char * ns,struct xmlindent * ptr_indent,int n_ref_format)346 int format_authorlist(char** ptr_ref, size_t* ptr_ref_len, struct BIBCONNS* ptr_bibconns, dbi_result dbires, dbi_result dbires_ref, int type, const char* database, int n_intext, struct bibinfo* ptr_biblio_info, short title_as_author, const char* ns, struct xmlindent* ptr_indent, int n_ref_format) {
347   int num_authors;
348   int nauthor_count = 0;
349   int nauthor_max;
350   int nauthor_display;
351   int nhave_content = 0;
352   int n_status;
353   int n_have_editor = 0;
354   int must_free_dbires = 0;
355   unsigned long long n_id;
356   const char *authorsep;
357   const char *nameorder;
358   const char *initialstyle;
359   const char *author_upper;
360   const char *citem;
361   const char *alternatetext;
362   char *author_anonymous = NULL;
363   char *author_preceeding = NULL;
364   char *author_following = NULL;
365   char *alist_preceeding = NULL;
366   char *new_ref;
367   char *item;
368   char *item1;
369   char *the_refdb_id;
370   char id[32] = "";
371   struct AUTHOR_INFO ainfo;
372 
373   dbi_result dbires_author;
374 /*   dbi_conn conn; */
375   enum refdb_col n_preceeding_index;
376   enum refdb_col n_following_index;
377   enum refdb_col n_abbreviate_first_index;
378   enum refdb_col n_abbreviate_max_first_index;
379   enum refdb_col n_abbreviate_display_first_index;
380   enum refdb_col n_abbreviate_subseq_index;
381   enum refdb_col n_abbreviate_max_subseq_index;
382   enum refdb_col n_abbreviate_display_subseq_index;
383   enum refdb_col n_authorempty_index;
384   enum refdb_col n_alternatetext_index;
385   enum refdb_col n_asame_index;
386   enum refdb_col n_twoseps_index;
387   enum refdb_col n_threesepseach_index;
388   enum refdb_col n_threesepslast_index;
389   enum refdb_col n_namefirstorder_index;
390   enum refdb_col n_namefirstinitial_index;
391   enum refdb_col n_namefirstupper_index;
392   enum refdb_col n_nameotherorder_index;
393   enum refdb_col n_nameotherinitial_index;
394   enum refdb_col n_nameotherupper_index;
395   enum refdb_col n_singlepreceeding_index;
396   enum refdb_col n_singlefollowing_index;
397   enum refdb_col n_multiplepreceeding_index;
398   enum refdb_col n_multiplefollowing_index;
399   enum refdb_col n_edsinglepreceeding_index;
400   enum refdb_col n_edsinglefollowing_index;
401   enum refdb_col n_edmultiplepreceeding_index;
402   enum refdb_col n_edmultiplefollowing_index;
403   enum refdb_col n_my_singlepreceeding_index;
404   enum refdb_col n_my_singlefollowing_index;
405   enum refdb_col n_my_multiplepreceeding_index;
406   enum refdb_col n_my_multiplefollowing_index;
407 
408 /*   printf("start format_authorlist(), type went to %d\n", type); */
409 
410   /* map the database query result columns to index variables according to the type of authorlist */
411   if (type == 1) { /* part authors */
412     n_preceeding_index = AUTHORLISTPRECEEDING;
413     n_following_index = AUTHORLISTFOLLOWING;
414     n_abbreviate_first_index = AUTHORLISTABBREVIATEFIRST;
415     n_abbreviate_max_first_index = AUTHORLISTABBREVIATEFIRSTMAXAUTHOR;
416     n_abbreviate_display_first_index = AUTHORLISTABBREVIATEFIRSTDISPLAYAUTHOR;
417     n_abbreviate_subseq_index = AUTHORLISTABBREVIATESUBSEQ;
418     n_abbreviate_max_subseq_index = AUTHORLISTABBREVIATESUBSEQMAXAUTHOR;
419     n_abbreviate_display_subseq_index = AUTHORLISTABBREVIATESUBSEQDISPLAYAUTHOR;
420     n_authorempty_index = AUTHORLISTAEMPTY;
421     n_alternatetext_index = AUTHORLISTALTERNATETEXT;
422     n_asame_index = AUTHORLISTASAME;
423     n_twoseps_index = AUTHORLISTAUTHORSEPSTWOSEPS;
424     n_threesepseach_index = AUTHORLISTAUTHORSEPSTHREESEPSTHREESEPSEACH;
425     n_threesepslast_index = AUTHORLISTAUTHORSEPSTHREESEPSTHREESEPSLAST;
426     n_namefirstorder_index = AUTHORLISTAUTHORNAMESNAMEFIRSTNAMEORDER;
427     n_namefirstinitial_index = AUTHORLISTAUTHORNAMESNAMEFIRSTINITIALSTYLE;
428     n_namefirstupper_index = AUTHORLISTAUTHORNAMESNAMEFIRSTUPPERCASE;
429     n_nameotherorder_index = AUTHORLISTAUTHORNAMESNAMEOTHERNAMEORDER;
430     n_nameotherinitial_index = AUTHORLISTAUTHORNAMESNAMEOTHERINITIALSTYLE;
431     n_nameotherupper_index = AUTHORLISTAUTHORNAMESNAMEOTHERUPPERCASE;
432     n_singlepreceeding_index = AUTHORLISTTEXTTEXTSINGLEPRECEEDING;
433     n_singlefollowing_index = AUTHORLISTTEXTTEXTSINGLEFOLLOWING;
434     n_multiplepreceeding_index = AUTHORLISTTEXTTEXTMULTIPLEPRECEEDING;
435     n_multiplefollowing_index = AUTHORLISTTEXTTEXTMULTIPLEFOLLOWING;
436     n_edsinglepreceeding_index = AUTHORLISTTEXTEDTEXTSINGLEPRECEEDING;
437     n_edsinglefollowing_index = AUTHORLISTTEXTEDTEXTSINGLEFOLLOWING;
438     n_edmultiplepreceeding_index = AUTHORLISTTEXTEDTEXTMULTIPLEPRECEEDING;
439     n_edmultiplefollowing_index = AUTHORLISTTEXTEDTEXTMULTIPLEFOLLOWING;
440   }
441   else if (type == 2) { /* publication authors */
442     n_preceeding_index = EDITORLISTPRECEEDING;
443     n_following_index = EDITORLISTFOLLOWING;
444     n_abbreviate_first_index = EDITORLISTABBREVIATEFIRST;
445     n_abbreviate_max_first_index = EDITORLISTABBREVIATEFIRSTMAXAUTHOR;
446     n_abbreviate_display_first_index = EDITORLISTABBREVIATEFIRSTDISPLAYAUTHOR;
447     n_abbreviate_subseq_index = EDITORLISTABBREVIATESUBSEQ;
448     n_abbreviate_max_subseq_index = EDITORLISTABBREVIATESUBSEQMAXAUTHOR;
449     n_abbreviate_display_subseq_index = EDITORLISTABBREVIATESUBSEQDISPLAYAUTHOR;
450     n_authorempty_index = EDITORLISTAEMPTY;
451     n_alternatetext_index = EDITORLISTALTERNATETEXT;
452     n_asame_index = EDITORLISTASAME;
453     n_twoseps_index = EDITORLISTAUTHORSEPSTWOSEPS;
454     n_threesepseach_index = EDITORLISTAUTHORSEPSTHREESEPSTHREESEPSEACH;
455     n_threesepslast_index = EDITORLISTAUTHORSEPSTHREESEPSTHREESEPSLAST;
456     n_namefirstorder_index = EDITORLISTAUTHORNAMESNAMEFIRSTNAMEORDER;
457     n_namefirstinitial_index = EDITORLISTAUTHORNAMESNAMEFIRSTINITIALSTYLE;
458     n_namefirstupper_index = EDITORLISTAUTHORNAMESNAMEFIRSTUPPERCASE;
459     n_nameotherorder_index = EDITORLISTAUTHORNAMESNAMEOTHERNAMEORDER;
460     n_nameotherinitial_index = EDITORLISTAUTHORNAMESNAMEOTHERINITIALSTYLE;
461     n_nameotherupper_index = EDITORLISTAUTHORNAMESNAMEOTHERUPPERCASE;
462     n_singlepreceeding_index = EDITORLISTTEXTTEXTSINGLEPRECEEDING;
463     n_singlefollowing_index = EDITORLISTTEXTTEXTSINGLEFOLLOWING;
464     n_multiplepreceeding_index = EDITORLISTTEXTTEXTMULTIPLEPRECEEDING;
465     n_multiplefollowing_index = EDITORLISTTEXTTEXTMULTIPLEFOLLOWING;
466     n_edsinglepreceeding_index = EDITORLISTTEXTEDTEXTSINGLEPRECEEDING;
467     n_edsinglefollowing_index = EDITORLISTTEXTEDTEXTSINGLEFOLLOWING;
468     n_edmultiplepreceeding_index = EDITORLISTTEXTEDTEXTMULTIPLEPRECEEDING;
469     n_edmultiplefollowing_index = EDITORLISTTEXTEDTEXTMULTIPLEFOLLOWING;
470   }
471   else if (type == 3) { /* series authors */
472     n_preceeding_index = SEDITORLISTPRECEEDING;
473     n_following_index = SEDITORLISTFOLLOWING;
474     n_abbreviate_first_index = SEDITORLISTABBREVIATEFIRST;
475     n_abbreviate_max_first_index = SEDITORLISTABBREVIATEFIRSTMAXAUTHOR;
476     n_abbreviate_display_first_index = SEDITORLISTABBREVIATEFIRSTDISPLAYAUTHOR;
477     n_abbreviate_subseq_index = SEDITORLISTABBREVIATESUBSEQ;
478     n_abbreviate_max_subseq_index = SEDITORLISTABBREVIATESUBSEQMAXAUTHOR;
479     n_abbreviate_display_subseq_index = SEDITORLISTABBREVIATESUBSEQDISPLAYAUTHOR;
480     n_authorempty_index = SEDITORLISTAEMPTY;
481     n_alternatetext_index = SEDITORLISTALTERNATETEXT;
482     n_asame_index = SEDITORLISTASAME;
483     n_twoseps_index = SEDITORLISTAUTHORSEPSTWOSEPS;
484     n_threesepseach_index = SEDITORLISTAUTHORSEPSTHREESEPSTHREESEPSEACH;
485     n_threesepslast_index = SEDITORLISTAUTHORSEPSTHREESEPSTHREESEPSLAST;
486     n_namefirstorder_index = SEDITORLISTAUTHORNAMESNAMEFIRSTNAMEORDER;
487     n_namefirstinitial_index = SEDITORLISTAUTHORNAMESNAMEFIRSTINITIALSTYLE;
488     n_namefirstupper_index = SEDITORLISTAUTHORNAMESNAMEFIRSTUPPERCASE;
489     n_nameotherorder_index = SEDITORLISTAUTHORNAMESNAMEOTHERNAMEORDER;
490     n_nameotherinitial_index = SEDITORLISTAUTHORNAMESNAMEOTHERINITIALSTYLE;
491     n_nameotherupper_index = SEDITORLISTAUTHORNAMESNAMEOTHERUPPERCASE;
492     n_singlepreceeding_index = SEDITORLISTTEXTTEXTSINGLEPRECEEDING;
493     n_singlefollowing_index = SEDITORLISTTEXTTEXTSINGLEFOLLOWING;
494     n_multiplepreceeding_index = SEDITORLISTTEXTTEXTMULTIPLEPRECEEDING;
495     n_multiplefollowing_index = SEDITORLISTTEXTTEXTMULTIPLEFOLLOWING;
496     n_edsinglepreceeding_index = SEDITORLISTTEXTEDTEXTSINGLEPRECEEDING;
497     n_edsinglefollowing_index = SEDITORLISTTEXTEDTEXTSINGLEFOLLOWING;
498     n_edmultiplepreceeding_index = SEDITORLISTTEXTEDTEXTMULTIPLEPRECEEDING;
499     n_edmultiplefollowing_index = SEDITORLISTTEXTEDTEXTMULTIPLEFOLLOWING;
500   }
501   else { /* allalist */
502     n_preceeding_index = ALLALISTPRECEEDING;
503     n_following_index = ALLALISTFOLLOWING;
504     n_abbreviate_first_index = ALLALISTABBREVIATEFIRST;
505     n_abbreviate_max_first_index = ALLALISTABBREVIATEFIRSTMAXAUTHOR;
506     n_abbreviate_display_first_index = ALLALISTABBREVIATEFIRSTDISPLAYAUTHOR;
507     n_abbreviate_subseq_index = ALLALISTABBREVIATESUBSEQ;
508     n_abbreviate_max_subseq_index = ALLALISTABBREVIATESUBSEQMAXAUTHOR;
509     n_abbreviate_display_subseq_index = ALLALISTABBREVIATESUBSEQDISPLAYAUTHOR;
510     n_authorempty_index = ALLALISTAEMPTY;
511     n_alternatetext_index = ALLALISTALTERNATETEXT;
512     n_asame_index = ALLALISTASAME;
513     n_twoseps_index = ALLALISTAUTHORSEPSTWOSEPS;
514     n_threesepseach_index = ALLALISTAUTHORSEPSTHREESEPSTHREESEPSEACH;
515     n_threesepslast_index = ALLALISTAUTHORSEPSTHREESEPSTHREESEPSLAST;
516     n_namefirstorder_index = ALLALISTAUTHORNAMESNAMEFIRSTNAMEORDER;
517     n_namefirstinitial_index = ALLALISTAUTHORNAMESNAMEFIRSTINITIALSTYLE;
518     n_namefirstupper_index = ALLALISTAUTHORNAMESNAMEFIRSTUPPERCASE;
519     n_nameotherorder_index = ALLALISTAUTHORNAMESNAMEOTHERNAMEORDER;
520     n_nameotherinitial_index = ALLALISTAUTHORNAMESNAMEOTHERINITIALSTYLE;
521     n_nameotherupper_index = ALLALISTAUTHORNAMESNAMEOTHERUPPERCASE;
522     n_singlepreceeding_index = ALLALISTTEXTTEXTSINGLEPRECEEDING;
523     n_singlefollowing_index = ALLALISTTEXTTEXTSINGLEFOLLOWING;
524     n_multiplepreceeding_index = ALLALISTTEXTTEXTMULTIPLEPRECEEDING;
525     n_multiplefollowing_index = ALLALISTTEXTTEXTMULTIPLEFOLLOWING;
526     n_edsinglepreceeding_index = ALLALISTTEXTEDTEXTSINGLEPRECEEDING;
527     n_edsinglefollowing_index = ALLALISTTEXTEDTEXTSINGLEFOLLOWING;
528     n_edmultiplepreceeding_index = ALLALISTTEXTEDTEXTMULTIPLEPRECEEDING;
529     n_edmultiplefollowing_index = ALLALISTTEXTEDTEXTMULTIPLEFOLLOWING;
530   }
531 
532   /* initialize struct */
533   *(ainfo.name) = '\0';
534   *(ainfo.lastname) = '\0';
535   *(ainfo.firstname) = '\0';
536   *(ainfo.middlename) = '\0';
537   *(ainfo.suffix) = '\0';
538 
539   /* ToDo: fix the n_id/id/the_refdb_id/whatever kludge */
540   if (dbires) {
541     n_id = my_dbi_result_get_idval(dbires, "refdb_id");
542     if (!n_id) {
543       return 244;
544     }
545     sprintf(id, ULLSPEC, (unsigned long long)n_id);
546     the_refdb_id = id;
547   }
548   else {
549     sprintf(id, ULLSPEC, (unsigned long long)(ptr_biblio_info->n_refdb_id));
550     the_refdb_id = id;
551     n_id = ptr_biblio_info->n_refdb_id;
552   }
553 
554 /*   conn = dbi_result_get_conn(dbires_ref); */
555 
556   if ((!n_intext && ptr_biblio_info->is_subseq) || (n_intext == 2)) {
557     citem = dbi_result_get_string_idx(dbires_ref, n_abbreviate_max_subseq_index);
558     if (citem && *citem && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
559       nauthor_max = atoi((char*)citem);
560       nauthor_max = (nauthor_max < 1) ? 1 : nauthor_max;
561     }
562     else {
563       nauthor_max = INT_MAX;
564     }
565 
566     citem = dbi_result_get_string_idx(dbires_ref, n_abbreviate_display_subseq_index);
567     if (citem && *citem && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
568       nauthor_display = atoi((char*)citem);
569       nauthor_display = (nauthor_display < 1) ? 1 : nauthor_display;
570     }
571     else {
572       nauthor_display = INT_MAX;
573     }
574   }
575   else {
576     citem = dbi_result_get_string_idx(dbires_ref, n_abbreviate_max_first_index);
577     if (citem && *citem && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
578       nauthor_max = atoi((char*)citem);
579       nauthor_max = (nauthor_max < 1) ? 1 : nauthor_max;
580     }
581     else {
582       nauthor_max = INT_MAX;
583     }
584 
585     citem = dbi_result_get_string_idx(dbires_ref, n_abbreviate_display_first_index);
586     if (citem && *citem && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
587       nauthor_display = atoi((char*)citem);
588       nauthor_display = (nauthor_display < 1) ? 1 : nauthor_display;
589     }
590     else {
591       nauthor_display = INT_MAX;
592     }
593   }
594 
595   /* check for subsequent reference of same author(s) */
596   if ((!n_intext && ptr_biblio_info->is_subseq) || (n_intext == 2)) {
597     item = my_dbi_result_get_string_copy_idx(dbires_ref, n_asame_index);
598     if (item && !*item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
599       free(item);
600       return 0; /* ASAME is empty string -> suppress authorlist */
601     }
602     else if (item) {
603       item1 = my_dbi_result_get_string_copy_idx(dbires_ref, n_preceeding_index);
604       if (item1 && *item1 && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* preceeding */
605 	if (sgml_entitize(&item1, NULL) == NULL) {
606 	  free(item);
607 	  free(item1);
608 	  return 801;
609 	}
610 
611 	if ((new_ref = mstrcat(*ptr_ref, item1, ptr_ref_len, 0)) == NULL) {
612 	  free(item1);
613 	  free(item);
614 	  return 801;
615 	}
616 	else {
617 	  *ptr_ref = new_ref;
618 	}
619       }
620       if (item1) { /* found, but empty */
621 	free(item1);
622       }
623 
624       item1 = my_dbi_result_get_string_copy_idx(dbires_ref, n_singlepreceeding_index);
625       if (item1 && *item1 && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* textpreceeding */
626 	if (sgml_entitize(&item1, NULL) == NULL) {
627 	  free(item1);
628 	  free(item);
629 	  return 801;
630 	}
631 
632 	if ((new_ref = mstrcat(*ptr_ref, item1, ptr_ref_len, 0)) == NULL) {
633 	  free(item1);
634 	  free(item);
635 	  return 801;
636 	}
637 	else {
638 	  *ptr_ref = new_ref;
639 	}
640       }
641       if (item1) { /* found but empty */
642 	free(item1);
643       }
644 
645       /* item contains asame */
646       if (sgml_entitize(&item, NULL) == NULL) {
647 	free(item);
648 	return 801;
649       }
650 
651       if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
652 	free(item);
653 	return 801;
654       }
655       else {
656 	*ptr_ref = new_ref;
657       }
658       free(item);
659 
660       nhave_content = 1;
661 
662       /* reuse item */
663       item = my_dbi_result_get_string_copy_idx(dbires_ref, n_following_index);
664       if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* following */
665 	if (sgml_entitize(&item, NULL) == NULL) {
666 	  free(item);
667 	  return 801;
668 	}
669 
670 	if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
671 	  free(item);
672 	  return 801;
673 	}
674 	else {
675 	  *ptr_ref = new_ref;
676 	}
677       }
678       if (item) {
679 	free(item);
680       }
681       return 0;
682     }
683     /* else: ASAME undefined, process authorlist as usual */
684   } /* end if is_subseq */
685 
686   if ((dbires_author = request_authors(ptr_bibconns->conn_source, type, NULL /* all roles */, database, 0, n_id)) != NULL) {
687     while (get_author_parts(dbires_author, &ainfo) != NULL) {
688       if (!strcmp(ainfo.role, "editor")) {
689 	n_have_editor++;
690       }
691     }
692     dbi_result_free(dbires_author);
693   }
694 
695   if (n_have_editor) {
696     n_my_singlepreceeding_index = n_edsinglepreceeding_index;
697     n_my_singlefollowing_index = n_edsinglefollowing_index;
698     n_my_multiplepreceeding_index = n_edmultiplepreceeding_index;
699     n_my_multiplefollowing_index = n_edmultiplefollowing_index;
700   }
701   else {
702     n_my_singlepreceeding_index = n_singlepreceeding_index;
703     n_my_singlefollowing_index = n_singlefollowing_index;
704     n_my_multiplepreceeding_index = n_multiplepreceeding_index;
705     n_my_multiplefollowing_index = n_multiplefollowing_index;
706   }
707 
708   alist_preceeding = my_dbi_result_get_string_copy_idx(dbires_ref, n_preceeding_index);
709   if (alist_preceeding && *alist_preceeding && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* preceeding */
710     if (sgml_entitize(&alist_preceeding, NULL) == NULL) {
711       free(alist_preceeding);
712       return 801;
713     }
714 
715     /* this will be used later only if we insert some author data */
716   }
717 
718   /* todo: check whether authors have a role attribute of editor, set preceeding and following indexes appropriately */
719   if ((dbires_author = request_authors(ptr_bibconns->conn_source, type, NULL /* all roles */, database, 0, n_id)) != NULL) {
720 
721     /* depending on the total number of authors we need different preceedings and followings */
722     num_authors = dbi_result_get_numrows(dbires_author);
723 /*     fprintf(stderr, "num_authors went to %d<<\n", num_authors); */
724     if (num_authors > 1) {
725       author_preceeding = my_dbi_result_get_string_copy_idx(dbires_ref, n_my_multiplepreceeding_index);
726       if (author_preceeding && dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
727 	free(author_preceeding);
728 	author_preceeding = NULL;
729       }
730 
731       author_following = my_dbi_result_get_string_copy_idx(dbires_ref, n_my_multiplefollowing_index);
732       if (author_following && dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
733 	free(author_following);
734 	author_following = NULL;
735       }
736     }
737     else if (num_authors == 0) {
738       char sql_command[1024];
739 
740       alternatetext = my_dbi_result_get_string_idx(dbires_ref, n_alternatetext_index);
741       if (alternatetext && dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
742 	alternatetext = NULL;
743       }
744 
745 /*       printf("alternatetext went to %s<<\n", alternatetext); */
746 /*       if (title_as_author) { */
747       if (alternatetext && strcmp(alternatetext, "AEMPTY")) {
748 	/* use title here if style requires it */
749 
750 	/* todo: use alternatetext here */
751 	if (!dbires) {
752 	  /* when asking only for the authorlist, we don't have a result with the contents of t_refdb */
753 	  sprintf(sql_command, "SELECT refdb_id, refdb_type, refdb_pubyear, refdb_startpage, refdb_endpage, refdb_abstract, refdb_title, refdb_volume, refdb_issue, refdb_booktitle, refdb_city, refdb_publisher, refdb_title_series, refdb_address, refdb_issn, refdb_periodical_id, refdb_pyother_info, refdb_secyear, refdb_secother_info, refdb_user1, refdb_user2, refdb_user3, refdb_user4, refdb_user5, refdb_typeofwork, refdb_area, refdb_ostype, refdb_degree, refdb_runningtime, refdb_classcodeintl, refdb_classcodeus, refdb_senderemail, refdb_recipientemail, refdb_mediatype, refdb_numvolumes, refdb_edition, refdb_computer, refdb_conferencelocation, refdb_registrynum, refdb_classification, refdb_section, refdb_pamphletnum, refdb_chapternum, refdb_citekey FROM t_refdb WHERE refdb_id="ULLSPEC, (unsigned long long)n_id);
754 
755 	  LOG_PRINT(LOG_DEBUG, sql_command);
756 	  dbires = dbi_conn_query(ptr_bibconns->conn_source, sql_command);
757 
758 	  if (!dbires || dbi_result_next_row(dbires) == 0) {
759 	    /* todo: exit gracefully */
760 	    LOG_PRINT(LOG_WARNING, "retrieve title instead of author failed");
761 	  }
762 	  must_free_dbires++;
763 	}
764 
765 	if (dbires) {
766 	  const char* type;
767 
768 	  type = my_dbi_result_get_string_idx(dbires, REFDB_TYPE);
769 
770 	  /* returns 0 if type==NULL */
771 	  if (has_part_data(type)) {
772 	    title_as_author = 1;
773 	  }
774 	  else {
775 	    title_as_author = 2;
776 	  }
777 	}
778 	else {
779 	  title_as_author = 0;
780 	}
781       }
782       else { /* use AEMPTY instead of title */
783 	author_anonymous = my_dbi_result_get_string_copy_idx(dbires_ref, n_authorempty_index);
784 	if (author_anonymous && *author_anonymous && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
785 	  if (sgml_entitize(&author_anonymous, NULL) == NULL) {
786 	    free(author_anonymous);
787 	    free(alist_preceeding);
788 	    clean_request(dbires_author);
789 	    return 801;
790 	  }
791 
792 	  author_preceeding = my_dbi_result_get_string_copy_idx(dbires_ref, n_my_singlepreceeding_index);
793 	  if (author_preceeding && dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
794 	    free(author_preceeding);
795 	    author_preceeding = NULL;
796 	  }
797 
798 	  author_following = my_dbi_result_get_string_copy_idx(dbires_ref, n_my_singlefollowing_index);
799 	  if (author_following && dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
800 	    free(author_following);
801 	    author_following = NULL;
802 	  }
803 	}
804 	else {    /* no authors, go home */
805 	  if (author_anonymous) {
806 	    free(author_anonymous);
807 	  }
808 	  clean_request(dbires_author);
809 	  if (alist_preceeding) {
810 	    free(alist_preceeding);
811 	  }
812 	  return 0;
813 	}
814       } /* end if title as author */
815     }
816     else { /* num_authors == 1 */
817       author_preceeding = my_dbi_result_get_string_copy_idx(dbires_ref, n_my_singlepreceeding_index);
818       if (author_preceeding && dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
819 	free(author_preceeding);
820 	author_preceeding = NULL;
821       }
822 
823       author_following = my_dbi_result_get_string_copy_idx(dbires_ref, n_my_singlefollowing_index);
824       if (author_following && dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
825 	free(author_following);
826 	author_following = NULL;
827       }
828     }
829 
830     /* list preceeding */
831 
832     if (alist_preceeding && *alist_preceeding) { /* preceeding */
833       if ((new_ref = mstrcat(*ptr_ref, alist_preceeding, ptr_ref_len, 0)) == NULL) {
834 	free(alist_preceeding);
835 	if (author_anonymous) {
836 	  free(author_anonymous);
837 	}
838 	if (author_following) {
839 	  free(author_following);
840 	}
841 	clean_request(dbires_author);
842 	return 801;
843       }
844       else {
845 	*ptr_ref = new_ref;
846       }
847     }
848     if (alist_preceeding) {
849       free(alist_preceeding);
850     }
851 
852     /* text preceeding */
853     if (author_preceeding && *author_preceeding) { /* preceeding */
854       if (sgml_entitize(&author_preceeding, NULL) == NULL) {
855 	free(author_preceeding);
856 	if (author_anonymous) {
857 	  free(author_anonymous);
858 	}
859 	if (author_following) {
860 	  free(author_following);
861 	}
862 	clean_request(dbires_author);
863 	return 801;
864       }
865 
866       if ((new_ref = mstrcat(*ptr_ref, author_preceeding, ptr_ref_len, 0)) == NULL) {
867 	free(author_preceeding);
868 	if (author_following) {
869 	  free(author_following);
870 	}
871 	clean_request(dbires_author);
872 	return 801;
873       }
874       else {
875 	*ptr_ref = new_ref;
876       }
877     }
878     if (author_preceeding) {
879       free(author_preceeding);
880     }
881 
882 
883     if (author_anonymous) {
884       strncpy(ainfo.name, author_anonymous, 255);
885       ainfo.name[255] = '\0';
886 
887       nhave_content = 1;
888       authorsep = NULL;
889       nameorder = dbi_result_get_string_idx(dbires_ref, n_namefirstorder_index);
890       initialstyle = dbi_result_get_string_idx(dbires_ref, n_namefirstinitial_index);
891       author_upper = dbi_result_get_string_idx(dbires_ref, n_namefirstupper_index);
892 
893       if ((n_status = format_authorname(ptr_ref, ptr_ref_len, &ainfo, authorsep, nameorder, initialstyle, author_upper, author_preceeding, author_following, n_intext, type, ns, ptr_indent, n_ref_format)) != 0) {
894 	clean_request(dbires_author);
895 	free(author_anonymous);
896 	if (author_following) {
897 	  free(author_following);
898 	}
899 	return n_status;
900       }
901 
902       free(author_anonymous);
903     }
904     else if (title_as_author) {
905       /* todo: kosherize output of format_title under these conditions */
906       if (n_ref_format == REFTEIX5) {
907 	if (print_elstart_x(ptr_ref, ptr_ref_len, "persName", "type", "author", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
908 	  return 801;
909 	}
910       }
911       else {
912 	if (print_elstart_x(ptr_ref, ptr_ref_len, "bibliomset", "relation", "author", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
913 	  return 801;
914 	}
915       }
916 
917       if ((new_ref = format_title(ptr_ref, ptr_ref_len, ptr_bibconns, dbires, dbires_ref, title_as_author, n_intext, 1 /* title as author */, ns, ptr_indent, n_ref_format)) == NULL) {
918 	free(alist_preceeding);
919 	clean_request(dbires_author);
920 	return 801;
921       }
922       else {
923 	*ptr_ref = new_ref;
924       }
925 
926       if (n_ref_format == REFTEIX5) {
927 	if (print_elend_x(ptr_ref, ptr_ref_len, "persName", ptr_indent, ns) == NULL) {
928 	  return 801;
929 	}
930       }
931       else {
932 	if (print_elend_x(ptr_ref, ptr_ref_len, "bibliomset", ptr_indent, ns) == NULL) {
933 	  return 801;
934 	}
935       }
936 
937       nhave_content = 1;
938       if (must_free_dbires) {
939 	dbi_result_free(dbires);
940       }
941     }
942     else { /* regular author/editor */
943       while (get_author_parts(dbires_author, &ainfo) != NULL) {
944 	/* increment counter, so first author will be 1 */
945 	nauthor_count++;
946 	nhave_content = 1;
947 
948 	/* we may need different formats for the first, the last, and the inbetween authors */
949 	if (nauthor_count == 1) {
950 	  authorsep = NULL;
951 	  nameorder = dbi_result_get_string_idx(dbires_ref, n_namefirstorder_index);
952 	  initialstyle = dbi_result_get_string_idx(dbires_ref, n_namefirstinitial_index);
953 	  author_upper = dbi_result_get_string_idx(dbires_ref, n_namefirstupper_index);
954 	}
955 	else if (nauthor_count == num_authors) {
956 	  if (num_authors > 2) {
957 	    authorsep = my_dbi_result_get_string_idx(dbires_ref, n_threesepslast_index);
958 	  }
959 	  else {
960 	    authorsep = my_dbi_result_get_string_idx(dbires_ref, n_twoseps_index);
961 	  }
962 	  nameorder = dbi_result_get_string_idx(dbires_ref, n_nameotherorder_index);
963 	  initialstyle = dbi_result_get_string_idx(dbires_ref, n_nameotherinitial_index);
964 	  author_upper = dbi_result_get_string_idx(dbires_ref, n_nameotherupper_index);
965 	}
966 	else {
967 	  authorsep = my_dbi_result_get_string_idx(dbires_ref, n_threesepseach_index);
968 	  nameorder = dbi_result_get_string_idx(dbires_ref, n_nameotherorder_index);
969 	  initialstyle = dbi_result_get_string_idx(dbires_ref, n_nameotherinitial_index);
970 	  author_upper = dbi_result_get_string_idx(dbires_ref, n_nameotherupper_index);
971 	}
972 
973 	/* if we don't want to display all authors, we'll display something like 'et.al' instead and exit the loop */
974 	if (nauthor_count > nauthor_display && num_authors > nauthor_max) {
975 	  if ((!n_intext && ptr_biblio_info->is_subseq) || (n_intext == 2)) {
976 	    new_ref = *ptr_ref;
977 	    item = my_dbi_result_get_string_copy_idx(dbires_ref, n_abbreviate_subseq_index);
978 	    if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
979 	      if (n_ref_format == REFTEIX5) {
980 		if (print_elstart_x(ptr_ref, ptr_ref_len, "seg", "type", "etal", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
981 		  clean_request(dbires_author);
982 		  free(item);
983 		  if (author_following) {
984 		    free(author_following);
985 		  }
986 		  return 801;
987 		}
988 	      }
989 	      else {
990 		if (print_elstart_x(ptr_ref, ptr_ref_len, "bibliomset", "relation", "etal", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
991 		  clean_request(dbires_author);
992 		  free(item);
993 		  if (author_following) {
994 		    free(author_following);
995 		  }
996 		  return 801;
997 		}
998 	      }
999 
1000 	      if (sgml_entitize(&item, NULL) == NULL) {
1001 		clean_request(dbires_author);
1002 		free(item);
1003 		if (author_following) {
1004 		  free(author_following);
1005 		}
1006 		return 801;
1007 	      }
1008 
1009 	      if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
1010 		clean_request(dbires_author);
1011 		free(item);
1012 		if (author_following) {
1013 		  free(author_following);
1014 		}
1015 		return 801;
1016 	      }
1017 	      else {
1018 		*ptr_ref = new_ref;
1019 	      }
1020 
1021 	      if (n_ref_format == REFTEIX5) {
1022 		if (print_elend_x(ptr_ref, ptr_ref_len, "seg", ptr_indent, ns) == NULL) {
1023 		  clean_request(dbires_author);
1024 		  if (author_following) {
1025 		    free(author_following);
1026 		  }
1027 		  free(item);
1028 		  return 801;
1029 		}
1030 	      }
1031 	      else {
1032 		if (print_elend_x(ptr_ref, ptr_ref_len, "bibliomset", ptr_indent, ns) == NULL) {
1033 		  clean_request(dbires_author);
1034 		  if (author_following) {
1035 		    free(author_following);
1036 		  }
1037 		  free(item);
1038 		  return 801;
1039 		}
1040 	      }
1041 	    }
1042 	    if (item) {
1043 	      free(item);
1044 	    }
1045 	  }
1046 	  else {
1047 	    new_ref = *ptr_ref;
1048 	    item = my_dbi_result_get_string_copy_idx(dbires_ref, n_abbreviate_first_index);
1049 	    if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
1050 	      if (n_ref_format == REFTEIX5) {
1051 		if (print_elstart_x(ptr_ref, ptr_ref_len, "seg", "type", "etal", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
1052 		  clean_request(dbires_author);
1053 		  free(item);
1054 		  if (author_following) {
1055 		    free(author_following);
1056 		  }
1057 		  return 801;
1058 		}
1059 	      }
1060 	      else {
1061 		if (print_elstart_x(ptr_ref, ptr_ref_len, "bibliomset", "relation", "etal", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
1062 		  clean_request(dbires_author);
1063 		  free(item);
1064 		  if (author_following) {
1065 		    free(author_following);
1066 		  }
1067 		  return 801;
1068 		}
1069 	      }
1070 
1071 	      if (sgml_entitize(&item, NULL) == NULL) {
1072 		clean_request(dbires_author);
1073 		free(item);
1074 		if (author_following) {
1075 		  free(author_following);
1076 		}
1077 		return 801;
1078 	      }
1079 
1080 	      if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
1081 		clean_request(dbires_author);
1082 		free(item);
1083 		if (author_following) {
1084 		  free(author_following);
1085 		}
1086 		return 801;
1087 	      }
1088 	      else {
1089 		*ptr_ref = new_ref;
1090 	      }
1091 
1092 	      if (n_ref_format == REFTEIX5) {
1093 		if (print_elend_x(ptr_ref, ptr_ref_len, "seg", ptr_indent, ns) == NULL) {
1094 		  clean_request(dbires_author);
1095 		  if (author_following) {
1096 		    free(author_following);
1097 		  }
1098 		  return 801;
1099 		}
1100 	      }
1101 	      else {
1102 		if (print_elend_x(ptr_ref, ptr_ref_len, "bibliomset", ptr_indent, ns) == NULL) {
1103 		  clean_request(dbires_author);
1104 		  if (author_following) {
1105 		    free(author_following);
1106 		  }
1107 		  return 801;
1108 		}
1109 	      }
1110 	    }
1111 	    if (item) {
1112 	      free(item);
1113 	    }
1114 	  }
1115 	  *ptr_ref = new_ref;
1116 	  break;
1117 	}
1118 
1119 	if ((n_status = format_authorname(ptr_ref, ptr_ref_len, &ainfo, authorsep, nameorder, initialstyle, author_upper, author_preceeding, author_following, n_intext, type, ns, ptr_indent, n_ref_format)) != 0) {
1120 	  clean_request(dbires_author);
1121 	  if (author_following) {
1122 	    free(author_following);
1123 	  }
1124 	  return n_status;
1125 	}
1126 
1127 /* 	*ptr_ref = new_ref; */
1128       } /* end while have authors */
1129     } /* end if have author_anonymous */
1130 
1131     clean_request(dbires_author);
1132   } /* end if author query ok */
1133 
1134   /* text following */
1135   if (author_following && *author_following) { /* following */
1136     if (sgml_entitize(&author_following, NULL) == NULL) {
1137       free(author_following);
1138       return 801;
1139     }
1140 
1141     if ((new_ref = mstrcat(*ptr_ref, author_following, ptr_ref_len, 0)) == NULL) {
1142       free(author_following);
1143       return 801;
1144     }
1145     else {
1146       *ptr_ref = new_ref;
1147     }
1148   }
1149   if (author_following) {
1150     free(author_following);
1151   }
1152 
1153   item = my_dbi_result_get_string_copy_idx(dbires_ref, n_following_index);
1154   if (item && *item) { /* following */
1155     if (sgml_entitize(&item, NULL) == NULL) {
1156       free(item);
1157       return 801;
1158     }
1159 
1160     if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
1161       free(item);
1162       return 801;
1163     }
1164     else {
1165       *ptr_ref = new_ref;
1166     }
1167   }
1168   if (item) {
1169     free(item);
1170   }
1171 /*   printf("end format_authorlist():%s\n", *ptr_ref); */
1172 
1173   if (!nhave_content) {
1174     (*ptr_ref)[0] = '\0'; /* return empty string if no real content */
1175   }
1176   return 0;
1177 }
1178 
1179 
1180 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1181   format_pubdate(): formats the pubdate/pubdatesec part of a
1182                     bibliography entry as a DocBook bibliomixed text
1183 
1184   char* format_pubdate returns ptr to the buffer if successful, NULL if failed
1185 
1186   char** ptr_ref ptr to a ptr to a buffer created with malloc which will receive
1187         the output. The calling function must allocate the buffer
1188         with at least 4096 byte. This function will reallocate the
1189         buffer as needed. *ptr will be updated whenever a realloc is
1190         necessary. The calling function is responsible for freeing the
1191         memory again.
1192 
1193   size_t* ptr_ref_len ptr to an int holding the current length of ref.
1194                      Will be modified if ref is reallocated.
1195 
1196   struct BIBCONNS* ptr_bibconns ptr to structure with database connections
1197 
1198   dbi_result dbires ptr to a dbi result structure containing the
1199                     current reference
1200 
1201   dbi_result dbires_ref ptr to a dbi result structure containing the
1202                     reference style
1203 
1204   dbi_result dbires_cit ptr to a dbi result structure containing the
1205                         current citation style info
1206 
1207   int type 0 = pubdate, 1 = pubdatesec, 2 = pubdateall
1208 
1209   int n_intext  0 = bibliography citation; 1 = intext citation; 2 =
1210                     intext citation subsequent
1211 
1212   char* year_unique_suffix ptr to a string with a unique suffix for
1213                    pubyear
1214 
1215   const char* ns optional namespace prefix
1216 
1217   struct xmlindent* ptr_indent  indentation information
1218 
1219   int n_ref_format requested output format: REFDOCBK, REFDOCBKX, REFTEIX
1220 
1221   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_pubdate(char ** ptr_ref,size_t * ptr_ref_len,struct BIBCONNS * ptr_bibconns,dbi_result dbires,dbi_result dbires_ref,dbi_result dbires_cit,int type,int n_intext,const char * year_unique_suffix,const char * ns,struct xmlindent * ptr_indent,int n_ref_format)1222 char* format_pubdate(char** ptr_ref, size_t* ptr_ref_len, struct BIBCONNS* ptr_bibconns, dbi_result dbires, dbi_result dbires_ref, dbi_result dbires_cit, int type, int n_intext, const char* year_unique_suffix, const char* ns, struct xmlindent* ptr_indent, int n_ref_format) {
1223   char* new_ref;
1224   char pubdaterole[28];
1225   char year_buffer[32];
1226   char dummy_year[] = "nd";
1227   char *item;
1228   char *item_dateother;
1229   char *item_firstsep;
1230   char *item_secondsep;
1231   const char *citem;
1232   const char *item_yearformat;
1233   const char *item_monthformat;
1234   const char *item_dayformat;
1235   const char *item_pad;
1236   const char *item_sequence;
1237   const char *item_format;
1238   const char default_sequence[] = "Y"; /* defaults are taken from citestylex.dtd. Be aware of code duplication which is bad per se */
1239   const char default_yearformat[] = "FOURDIGIT";
1240   const char default_pad[] = "NN";
1241   const char default_monthformat[] = "ARABICMONTH";
1242   const char default_dayformat[] = "ARABICDAY";
1243   enum refdbref_col n_date_index;
1244   enum refdbref_col n_dateother_index;
1245   int nhave_content = 0;
1246   unsigned int n_pubyear = 0;
1247   enum refdb_col n_preceeding_index;
1248   enum refdb_col n_following_index;
1249   enum refdb_col n_format_index;
1250   enum refdb_col n_sequence_index;
1251   enum refdb_col n_firstsep_index;
1252   enum refdb_col n_secondsep_index;
1253   enum refdb_col n_yearformat_index;
1254   enum refdb_col n_monthformat_index;
1255   enum refdb_col n_dayformat_index;
1256   enum refdb_col n_pad_index;
1257 /*   dbi_conn conn; */
1258   struct lilimem sentinel;
1259 
1260   sentinel.ptr_mem = NULL;
1261   sentinel.ptr_next = NULL;
1262   sentinel.varname[0] = '\0';
1263 
1264   /* set indices according to pubdate type */
1265   if (!type) {
1266     n_date_index = REFDB_PUBYEAR;
1267     n_dateother_index = REFDB_PYOTHER_INFO;
1268     n_preceeding_index = PUBDATEPRECEEDING;
1269     n_following_index = PUBDATEFOLLOWING;
1270     n_format_index = PUBDATEFORMAT;
1271     n_sequence_index = PUBDATESEQUENCE;
1272     n_firstsep_index = PUBDATEFIRSTSEP;
1273     n_secondsep_index = PUBDATESECONDSEP;
1274     n_yearformat_index = PUBDATEYEARFORMAT;
1275     n_monthformat_index = PUBDATEMONTHFORMAT;
1276     n_dayformat_index = PUBDATEDAYFORMAT;
1277     n_pad_index = PUBDATEPADLEADINGZERO;
1278     strcpy(pubdaterole, "primary");
1279   }
1280   else if (type == 1) {
1281     n_date_index = REFDB_SECYEAR;
1282     n_dateother_index = REFDB_SECOTHER_INFO;
1283     n_preceeding_index = PUBDATESECPRECEEDING;
1284     n_following_index = PUBDATESECFOLLOWING;
1285     n_format_index = PUBDATESECFORMAT;
1286     n_sequence_index = PUBDATESECSEQUENCE;
1287     n_firstsep_index = PUBDATESECFIRSTSEP;
1288     n_secondsep_index = PUBDATESECSECONDSEP;
1289     n_yearformat_index = PUBDATESECYEARFORMAT;
1290     n_monthformat_index = PUBDATESECMONTHFORMAT;
1291     n_dayformat_index = PUBDATESECDAYFORMAT;
1292     n_pad_index = PUBDATESECPADLEADINGZERO;
1293     strcpy(pubdaterole, "secondary");
1294   }
1295   else if (type == 2) {
1296     n_preceeding_index = PUBDATEALLPRECEEDING;
1297     n_following_index = PUBDATEALLFOLLOWING;
1298     n_format_index = PUBDATEALLFORMAT;
1299     n_sequence_index = PUBDATEALLSEQUENCE;
1300     n_firstsep_index = PUBDATEALLFIRSTSEP;
1301     n_secondsep_index = PUBDATEALLSECONDSEP;
1302     n_yearformat_index = PUBDATEALLYEARFORMAT;
1303     n_monthformat_index = PUBDATEALLMONTHFORMAT;
1304     n_dayformat_index = PUBDATEALLDAYFORMAT;
1305     n_pad_index = PUBDATEALLPADLEADINGZERO;
1306     strcpy(pubdaterole, "all");
1307   }
1308   else { /* currently same as 0 */
1309     n_date_index = REFDB_PUBYEAR;
1310     n_dateother_index = REFDB_PYOTHER_INFO;
1311     n_preceeding_index = PUBDATEPRECEEDING;
1312     n_following_index = PUBDATEFOLLOWING;
1313     n_format_index = PUBDATEFORMAT;
1314     n_sequence_index = PUBDATESEQUENCE;
1315     n_firstsep_index = PUBDATEFIRSTSEP;
1316     n_secondsep_index = PUBDATESECONDSEP;
1317     n_yearformat_index = PUBDATEYEARFORMAT;
1318     n_monthformat_index = PUBDATEMONTHFORMAT;
1319     n_dayformat_index = PUBDATEDAYFORMAT;
1320     n_pad_index = PUBDATEPADLEADINGZERO;
1321     strcpy(pubdaterole, "primary");
1322   }
1323 
1324 /*    printf("in format_pubdate. year_unique_suffix=%s; type=%d, n_intext=%d<<\n", year_unique_suffix, type, n_intext); */
1325 
1326 /*   conn = dbi_result_get_conn(dbires); */
1327 
1328   if (type == 2) {
1329     /* first try pubdate, then pubdatesec */
1330     n_pubyear = dbi_result_get_ushort_idx(dbires, REFDB_PUBYEAR);
1331     if (!n_pubyear/*  && dbi_conn_error_flag(ptr_bibconns->conn_source) */) { /* reference has no pubdate data */
1332       citem = my_dbi_result_get_string_idx(dbires, REFDB_PYOTHER_INFO);
1333       if (!citem || !*citem) { /* reference has no pubdate data */
1334 	return *ptr_ref;
1335       }
1336       else {
1337 	n_dateother_index = REFDB_SECOTHER_INFO;
1338       }
1339       n_pubyear = dbi_result_get_ushort_idx(dbires, REFDB_SECYEAR);
1340     }
1341     else {
1342       n_date_index = REFDB_PUBYEAR;
1343       n_dateother_index = REFDB_PYOTHER_INFO;
1344     }
1345   }
1346   else {
1347     /* use only requested date */
1348     n_pubyear = dbi_result_get_ushort_idx(dbires, n_date_index);
1349     if (!n_pubyear/*  && dbi_conn_error_flag(ptr_bibconns->conn_source) */) { /* reference has no pubdate data */
1350       return *ptr_ref;
1351     }
1352   }
1353 
1354   item = my_dbi_result_get_string_copy_idx(dbires_ref, n_preceeding_index);
1355   if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* preceeding */
1356     if (sgml_entitize(&item, NULL) == NULL) {
1357       LOG_PRINT(LOG_WARNING, get_status_msg(801));
1358       free(item);
1359       return NULL;
1360     }
1361 
1362     if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
1363       LOG_PRINT(LOG_WARNING, get_status_msg(801));
1364       return NULL;
1365     }
1366     else {
1367       *ptr_ref = new_ref;
1368     }
1369   }
1370   if (item) {
1371     free(item);
1372   }
1373 
1374   if (n_ref_format == REFTEIX5) {
1375     if (print_elstart_x(ptr_ref, ptr_ref_len, "date", "rend", pubdaterole, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
1376       LOG_PRINT(LOG_WARNING, get_status_msg(801));
1377       return NULL;
1378     }
1379   }
1380   else {
1381     if (print_elstart_x(ptr_ref, ptr_ref_len, "pubdate", "role", pubdaterole, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
1382       LOG_PRINT(LOG_WARNING, get_status_msg(801));
1383       return NULL;
1384     }
1385   }
1386 
1387   item_dateother = my_dbi_result_get_string_copy_idx(dbires, n_dateother_index);
1388 
1389   if (item_dateother && *item_dateother && !dbi_conn_error_flag(ptr_bibconns->conn_source)) {
1390     if (sgml_entitize(&item_dateother, NULL) == NULL) {
1391       LOG_PRINT(LOG_WARNING, get_status_msg(801));
1392       free(item_dateother);
1393       return NULL;
1394     }
1395     else {
1396       if (insert_lilimem(&sentinel, (void**)&item_dateother, "item_dateother")) {
1397 	delete_all_lilimem(&sentinel);
1398 	return NULL;
1399       }
1400     }
1401   }
1402   else if (item_dateother && *item_dateother) {
1403     free(item_dateother);
1404     item_dateother = NULL;
1405   }
1406 
1407   item_format = dbi_result_get_string_idx(dbires_ref, n_format_index);
1408 
1409   /* switch on formatting if the attribute is either missing or set to "YES". To disable formatting, the attribute has to be set to "NO" explicitly */
1410   if (!item_format || strcmp(item_format, "YES") == 0) {
1411     /* do some formatting here */
1412     item_sequence = dbi_result_get_string_idx(dbires_ref, n_sequence_index);
1413     if (!item_sequence) {
1414       item_sequence = default_sequence;
1415     }
1416 
1417     item_yearformat = dbi_result_get_string_idx(dbires_ref, n_yearformat_index);
1418     if (!item_yearformat) {
1419       item_yearformat = default_yearformat;
1420     }
1421 
1422     item_pad = dbi_result_get_string_idx(dbires_ref, n_pad_index);
1423     if (!item_pad) {
1424       item_pad = default_pad;
1425     }
1426 
1427     item_monthformat = dbi_result_get_string_idx(dbires_ref, n_monthformat_index);
1428     if (!item_monthformat) {
1429       item_monthformat = default_monthformat;
1430     }
1431 
1432     item_dayformat = dbi_result_get_string_idx(dbires_ref, n_dayformat_index);
1433     if (!item_dayformat) {
1434       item_dayformat = default_dayformat;
1435     }
1436 
1437     item_firstsep = my_dbi_result_get_string_copy_idx(dbires_ref, n_firstsep_index);
1438     if (item_firstsep && *item_firstsep && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
1439       if (sgml_entitize(&item_firstsep, NULL) == NULL) {
1440 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
1441 	free(item_firstsep);
1442 	return NULL;
1443       }
1444       else {
1445 	if (insert_lilimem(&sentinel, (void**)&item_firstsep, "item_firstsep")) {
1446 	  delete_all_lilimem(&sentinel);
1447 	  return NULL;
1448 	}
1449       }
1450     }
1451     else if (item_firstsep) {
1452       free(item_firstsep);
1453       item_firstsep = NULL;
1454     }
1455 
1456     item_secondsep = my_dbi_result_get_string_copy_idx(dbires_ref, n_secondsep_index);
1457     if (item_secondsep && *item_secondsep && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
1458       if (sgml_entitize(&item_secondsep, NULL) == NULL) {
1459 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
1460 	free(item_secondsep);
1461 	return NULL;
1462       }
1463       else {
1464 	if (insert_lilimem(&sentinel, (void**)&item_secondsep, "item_secondsep")) {
1465 	  delete_all_lilimem(&sentinel);
1466 	  return NULL;
1467 	}
1468       }
1469     }
1470     else if (item_secondsep) {
1471       free(item_secondsep);
1472       item_secondsep = NULL;
1473     }
1474 
1475     if (item_sequence && strcmp(item_sequence, "Y") == 0) {
1476       if (n_pubyear) {
1477 	nhave_content = 1;
1478 	if ((new_ref = format_year(*ptr_ref, ptr_ref_len, n_pubyear, item_yearformat, item_pad, year_unique_suffix)) == NULL) {
1479 	  delete_all_lilimem(&sentinel);
1480 	  return NULL;
1481 	}
1482 	else {
1483 	  *ptr_ref = new_ref;
1484 	}
1485       }
1486       else {
1487 	/* insert dummy pubdate */
1488 	/* we do not increment nhave_content here. If the missing pubdate is
1489 	   all we "have", the whole element should be omitted */
1490 	if ((new_ref = mstrcat(*ptr_ref, dummy_year, ptr_ref_len, 0)) == NULL) {
1491 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
1492 	  delete_all_lilimem(&sentinel);
1493 	  return NULL;
1494 	}
1495 	else {
1496 	  *ptr_ref = new_ref;
1497 	}
1498       }
1499     }
1500     else if (item_sequence && strcmp(item_sequence, "MY") == 0) {
1501       if (item_dateother && *item_dateother) {
1502 	nhave_content = 1;
1503 	if ((new_ref = format_month(*ptr_ref, ptr_ref_len, item_dateother, item_monthformat, item_pad, dbires_cit)) == NULL) {
1504 	  delete_all_lilimem(&sentinel);
1505 	  return NULL;
1506 	}
1507 	else {
1508 	  *ptr_ref = new_ref;
1509 	}
1510       }
1511 
1512       /* firstsep goes in here */
1513       if (item_firstsep && *item_firstsep) {
1514 	if ((new_ref = mstrcat(*ptr_ref, item_firstsep, ptr_ref_len, 0)) == NULL) {
1515 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
1516 	  delete_all_lilimem(&sentinel);
1517 	  return NULL;
1518 	}
1519 	else {
1520 	  *ptr_ref = new_ref;
1521 	}
1522       }
1523 
1524       if (n_pubyear) {
1525 	nhave_content = 1;
1526 
1527 	if ((new_ref = format_year(*ptr_ref, ptr_ref_len, n_pubyear, item_yearformat, item_pad, year_unique_suffix)) == NULL) {
1528 	  delete_all_lilimem(&sentinel);
1529 	  return NULL;
1530 	}
1531 	else {
1532 	  *ptr_ref = new_ref;
1533 	}
1534       }
1535       else {
1536 	/* insert dummy pubdate */
1537 	if ((new_ref = mstrcat(*ptr_ref, dummy_year, ptr_ref_len, 0)) == NULL) {
1538 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
1539 	  delete_all_lilimem(&sentinel);
1540 	  return NULL;
1541 	}
1542 	else {
1543 	  *ptr_ref = new_ref;
1544 	}
1545       }
1546     }
1547     else if (item_sequence && strcmp(item_sequence, "DMY") == 0) {
1548       if (item_dateother && *item_dateother) {
1549 	nhave_content = 1;
1550 	if ((new_ref = format_day(*ptr_ref, ptr_ref_len, item_dateother, item_dayformat, item_pad)) == NULL) {
1551 	  delete_all_lilimem(&sentinel);
1552 	  return NULL;
1553 	}
1554 	else {
1555 	  *ptr_ref = new_ref;
1556 	}
1557       }
1558 
1559       /* firstsep goes in here */
1560       if (item_firstsep && *item_firstsep) {
1561 	if ((new_ref = mstrcat(*ptr_ref, item_firstsep, ptr_ref_len, 0)) == NULL) {
1562 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
1563 	  delete_all_lilimem(&sentinel);
1564 	  return NULL;
1565 	}
1566 	else {
1567 	  *ptr_ref = new_ref;
1568 	}
1569       }
1570 
1571       if (item_dateother && *item_dateother) {
1572 	if ((new_ref = format_month(*ptr_ref, ptr_ref_len, item_dateother, item_monthformat, item_pad, dbires_cit)) == NULL) {
1573 	  delete_all_lilimem(&sentinel);
1574 	  return NULL;
1575 	}
1576 	else {
1577 	  *ptr_ref = new_ref;
1578 	}
1579       }
1580 
1581       /* secondsep goes in here */
1582       if (item_secondsep && *item_secondsep) {
1583 	if ((new_ref = mstrcat(*ptr_ref, item_secondsep, ptr_ref_len, 0)) == NULL) {
1584 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
1585 	  delete_all_lilimem(&sentinel);
1586 	  return NULL;
1587 	}
1588 	else {
1589 	  *ptr_ref = new_ref;
1590 	}
1591       }
1592 
1593       if (n_pubyear) {
1594 	if ((new_ref = format_year(*ptr_ref, ptr_ref_len, n_pubyear, item_yearformat, item_pad, year_unique_suffix)) == NULL) {
1595 	  delete_all_lilimem(&sentinel);
1596 	  return NULL;
1597 	}
1598 	else {
1599 	  *ptr_ref = new_ref;
1600 	}
1601       }
1602       else {
1603 	/* insert dummy pubdate */
1604 	if ((new_ref = mstrcat(*ptr_ref, dummy_year, ptr_ref_len, 0)) == NULL) {
1605 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
1606 	  delete_all_lilimem(&sentinel);
1607 	  return NULL;
1608 	}
1609 	else {
1610 	  *ptr_ref = new_ref;
1611 	}
1612       }
1613     }
1614     else if (item_sequence && strcmp(item_sequence, "MDY") == 0) {
1615       if (item_dateother && *item_dateother) {
1616 	nhave_content = 1;
1617 
1618 	if ((new_ref = format_month(*ptr_ref, ptr_ref_len, item_dateother, item_monthformat, item_pad, dbires_cit)) == NULL) {
1619 	  delete_all_lilimem(&sentinel);
1620 	  return NULL;
1621 	}
1622 	else {
1623 	  *ptr_ref = new_ref;
1624 	}
1625       }
1626 
1627       /* firstsep goes in here */
1628       if (item_firstsep && *item_firstsep) {
1629 	if ((new_ref = mstrcat(*ptr_ref, item_firstsep, ptr_ref_len, 0)) == NULL) {
1630 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
1631 	  delete_all_lilimem(&sentinel);
1632 	  return NULL;
1633 	}
1634 	else {
1635 	  *ptr_ref = new_ref;
1636 	}
1637       }
1638 
1639       if (item_dateother && *item_dateother) {
1640 	if ((new_ref = format_day(*ptr_ref, ptr_ref_len, item_dateother, item_dayformat, item_pad)) == NULL) {
1641 	  delete_all_lilimem(&sentinel);
1642 	  return NULL;
1643 	}
1644 	else {
1645 	  *ptr_ref = new_ref;
1646 	}
1647       }
1648 
1649       /* secondsep goes in here */
1650       if (item_secondsep && *item_secondsep) {
1651 	if ((new_ref = mstrcat(*ptr_ref, item_secondsep, ptr_ref_len, 0)) == NULL) {
1652 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
1653 	  delete_all_lilimem(&sentinel);
1654 	  return NULL;
1655 	}
1656 	else {
1657 	  *ptr_ref = new_ref;
1658 	}
1659       }
1660 
1661       if (n_pubyear) {
1662 	if ((new_ref = format_year(*ptr_ref, ptr_ref_len, n_pubyear, item_yearformat, item_pad, year_unique_suffix)) == NULL) {
1663 	  delete_all_lilimem(&sentinel);
1664 	  return NULL;
1665 	}
1666 	else {
1667 	  *ptr_ref = new_ref;
1668 	}
1669       }
1670       else {
1671 	/* insert dummy pubdate */
1672 	if ((new_ref = mstrcat(*ptr_ref, dummy_year, ptr_ref_len, 0)) == NULL) {
1673 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
1674 	  delete_all_lilimem(&sentinel);
1675 	  return NULL;
1676 	}
1677 	else {
1678 	  *ptr_ref = new_ref;
1679 	}
1680       }
1681     }
1682     else if (item_sequence && strcmp(item_sequence, "YMD") == 0) {
1683       if (n_pubyear) {
1684 	if ((new_ref = format_year(*ptr_ref, ptr_ref_len, n_pubyear, item_yearformat, item_pad, year_unique_suffix)) == NULL) {
1685 	  delete_all_lilimem(&sentinel);
1686 	  return NULL;
1687 	}
1688 	else {
1689 	  *ptr_ref = new_ref;
1690 	}
1691       }
1692       else {
1693 	/* insert dummy pubdate */
1694 	if ((new_ref = mstrcat(*ptr_ref, dummy_year, ptr_ref_len, 0)) == NULL) {
1695 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
1696 	  delete_all_lilimem(&sentinel);
1697 	  return NULL;
1698 	}
1699 	else {
1700 	  *ptr_ref = new_ref;
1701 	}
1702       }
1703 
1704       /* firstsep goes in here */
1705       if (item_firstsep && *item_firstsep) {
1706 	if ((new_ref = mstrcat(*ptr_ref, item_firstsep, ptr_ref_len, 0)) == NULL) {
1707 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
1708 	  delete_all_lilimem(&sentinel);
1709 	  return NULL;
1710 	}
1711 	else {
1712 	  *ptr_ref = new_ref;
1713 	}
1714       }
1715 
1716       if (item_dateother && *item_dateother) {
1717 	nhave_content = 1;
1718 
1719 	if ((new_ref = format_month(*ptr_ref, ptr_ref_len, item_dateother, item_monthformat, item_pad, dbires_cit)) == NULL) {
1720 	  delete_all_lilimem(&sentinel);
1721 	  return NULL;
1722 	}
1723 	else {
1724 	  *ptr_ref = new_ref;
1725 	}
1726       }
1727 
1728       /* secondsep goes in here */
1729       if (item_secondsep && *item_secondsep) {
1730 	if ((new_ref = mstrcat(*ptr_ref, item_secondsep, ptr_ref_len, 0)) == NULL) {
1731 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
1732 	  delete_all_lilimem(&sentinel);
1733 	  return NULL;
1734 	}
1735 	else {
1736 	  *ptr_ref = new_ref;
1737 	}
1738       }
1739 
1740       if (item_dateother && *item_dateother) {
1741 	if ((new_ref = format_day(*ptr_ref, ptr_ref_len, item_dateother, item_dayformat, item_pad)) == NULL) {
1742 	  delete_all_lilimem(&sentinel);
1743 	  return NULL;
1744 	}
1745 	else {
1746 	  *ptr_ref = new_ref;
1747 	}
1748       }
1749     }
1750   }
1751   else if (n_pubyear) {
1752     /* no formatting */
1753     nhave_content = 1;
1754 
1755     sprintf(year_buffer, "%d", n_pubyear);
1756     if ((new_ref = mstrcat(*ptr_ref, year_buffer, ptr_ref_len, 0)) == NULL) {
1757       LOG_PRINT(LOG_WARNING, get_status_msg(801));
1758       delete_all_lilimem(&sentinel);
1759       return NULL;
1760     }
1761     else {
1762       *ptr_ref = new_ref;
1763     }
1764   }
1765   else {
1766     /* insert dummy pubdate */
1767     if ((new_ref = mstrcat(*ptr_ref, dummy_year, ptr_ref_len, 0)) == NULL) {
1768       LOG_PRINT(LOG_WARNING, get_status_msg(801));
1769       delete_all_lilimem(&sentinel);
1770       return NULL;
1771     }
1772     else {
1773       *ptr_ref = new_ref;
1774     }
1775   }
1776 
1777   delete_all_lilimem(&sentinel);
1778 
1779   if (n_ref_format == REFTEIX5) {
1780     if (print_elend_x(ptr_ref, ptr_ref_len, "date", ptr_indent, ns) == NULL) {
1781       LOG_PRINT(LOG_WARNING, get_status_msg(801));
1782       return NULL;
1783     }
1784   }
1785   else {
1786     if (print_elend_x(ptr_ref, ptr_ref_len, "pubdate", ptr_indent, ns) == NULL) {
1787       LOG_PRINT(LOG_WARNING, get_status_msg(801));
1788       return NULL;
1789     }
1790   }
1791 
1792   item = my_dbi_result_get_string_copy_idx(dbires_ref, n_following_index);
1793   if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* following */
1794     if (sgml_entitize(&item, NULL) == NULL) {
1795       LOG_PRINT(LOG_WARNING, get_status_msg(801));
1796       free(item);
1797       return NULL;
1798     }
1799 
1800     if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
1801       LOG_PRINT(LOG_WARNING, get_status_msg(801));
1802       free(item);
1803       return NULL;
1804     }
1805     else {
1806       *ptr_ref = new_ref;
1807     }
1808   }
1809   if (item) {
1810     free(item);
1811   }
1812 
1813 /*    printf("done with format_pubdate. ptr_ref=%s<<\n", *ptr_ref); */
1814   if (!nhave_content) {
1815     (*ptr_ref)[0] ='\0';
1816   }
1817   return *ptr_ref;
1818 }
1819 
1820 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1821   format_title(): formats the title/booktitle/seriestitle part of a
1822                       bibliography entry as a DocBook bibliomixed text
1823 
1824   char* format_title returns ptr to the buffer if successful, NULL if failed
1825 
1826   char** ptr_ref ptr to a ptr to a buffer created with malloc which will receive
1827         the output. The calling function must allocate the buffer
1828         with at least 4096 byte. This function will reallocate the
1829         buffer as needed. *ptr will be updated whenever a realloc is
1830         necessary. The calling function is responsible for freeing the
1831         memory again.
1832 
1833   size_t* ptr_ref_len ptr to an int holding the current length of ref.
1834                      Will be modified if ref is reallocated.
1835 
1836   dbi_result dbires ptr to a dbi result structure containing the
1837                     current reference
1838 
1839   dbi_result dbires_ref ptr to a dbi result structure containing the
1840                         reference style
1841 
1842   int type 1=title, 2=booktitle, 3=seriestitle, 4=alltitle
1843 
1844   int n_intext  0 = bibliography citation; 1 = intext citation; 2 =
1845                     intext citation subsequent
1846 
1847   int n_title_as_author if >0, title is printed instead of authors
1848 
1849   const char* ns optional namespace prefix
1850 
1851   struct xmlindent* ptr_indent  indentation information
1852 
1853   int n_ref_format requested output format: REFDOCBK, REFDOCBKX, REFTEIX
1854 
1855   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_title(char ** ptr_ref,size_t * ptr_ref_len,struct BIBCONNS * ptr_bibconns,dbi_result dbires,dbi_result dbires_ref,int type,int n_intext,int n_title_as_author,const char * ns,struct xmlindent * ptr_indent,int n_ref_format)1856 char* format_title(char** ptr_ref, size_t* ptr_ref_len, struct BIBCONNS* ptr_bibconns, dbi_result dbires, dbi_result dbires_ref, int type, int n_intext, int n_title_as_author, const char* ns, struct xmlindent* ptr_indent, int n_ref_format) {
1857   char* new_ref;
1858   char role[7];
1859   char roleatt[6] = "role";
1860   char *item;
1861   char *real_item_title = NULL;
1862   const char *citem;
1863   const char *item_title;
1864   const char *item_titlebook;
1865   const char *item_titleseries;
1866   int n_title_index = 0;
1867   int nhave_content = 0;
1868   enum refdb_col n_preceeding_index;
1869   enum refdb_col n_following_index;
1870   int n_uplow = 0; /* 0=asis, 1=uppercase, 2=lowercase, 3=initialcaps */
1871 
1872 /*    printf("start format_title. title_as_author=%d\n", n_title_as_author); */
1873 
1874   /* set a few parameters based on title type */
1875   switch (type) {
1876   case 1:
1877     n_title_index = REFDB_TITLE;
1878     n_preceeding_index = TITLEPRECEEDING;
1879     n_following_index = TITLEFOLLOWING;
1880     citem = dbi_result_get_string_idx(dbires_ref, TITLECASE);
1881     if (citem && strcmp(citem, "UPPER") == 0) {
1882       n_uplow = 1;
1883     }
1884     else if (citem && strcmp(citem, "LOWER") == 0) {
1885       n_uplow = 2;
1886     }
1887     else if (citem && strcmp(citem, "ICAPS") == 0) {
1888       n_uplow = 3;
1889     }
1890     if (n_ref_format == REFTEIX5) {
1891       strcpy(role, "a");
1892       strcpy(roleatt, "level");
1893     }
1894     else {
1895       strcpy(role, "JOUR");
1896     }
1897     break;
1898   default: /* same as booktitle, fall through */
1899   case 2:
1900     n_title_index = REFDB_BOOKTITLE;
1901     n_preceeding_index = BOOKTITLEPRECEEDING;
1902     n_following_index = BOOKTITLEFOLLOWING;
1903     citem = dbi_result_get_string_idx(dbires_ref, BOOKTITLECASE);
1904     if (citem && strcmp(citem, "UPPER") == 0) {
1905       n_uplow = 1;
1906     }
1907     else if (citem && strcmp(citem, "LOWER") == 0) {
1908       n_uplow = 2;
1909     }
1910     else if (citem && strcmp(citem, "ICAPS") == 0) {
1911       n_uplow = 3;
1912     }
1913     if (n_ref_format == REFTEIX5) {
1914       strcpy(role, "m");
1915       strcpy(roleatt, "level");
1916     }
1917     else {
1918       strcpy(role, "BOOK");
1919     }
1920     break;
1921   case 3:
1922     n_title_index = REFDB_TITLE_SERIES;
1923     n_preceeding_index = SERIESTITLEPRECEEDING;
1924     n_following_index = SERIESTITLEFOLLOWING;
1925     citem = dbi_result_get_string_idx(dbires_ref, SERIESTITLECASE);
1926     if (citem && strcmp(citem, "UPPER") == 0) {
1927       n_uplow = 1;
1928     }
1929     else if (citem && strcmp(citem, "LOWER") == 0) {
1930       n_uplow = 2;
1931     }
1932     else if (citem && strcmp(citem, "ICAPS") == 0) {
1933       n_uplow = 3;
1934     }
1935     if (n_ref_format == REFTEIX5) {
1936       strcpy(role, "s");
1937       strcpy(roleatt, "level");
1938     }
1939     else {
1940       strcpy(role, "SERIES");
1941     }
1942     break;
1943   case 4:
1944     item_title = my_dbi_result_get_string_idx(dbires, REFDB_TITLE);
1945     if (item_title && dbi_conn_error_flag(ptr_bibconns->conn_source)) {
1946       item_title = NULL;
1947     }
1948     item_titlebook = my_dbi_result_get_string_idx(dbires, REFDB_BOOKTITLE);
1949     if (item_titlebook && dbi_conn_error_flag(ptr_bibconns->conn_source)) {
1950       item_titlebook = NULL;
1951     }
1952     item_titleseries = my_dbi_result_get_string_idx(dbires, REFDB_TITLE_SERIES);
1953     if (item_titleseries && dbi_conn_error_flag(ptr_bibconns->conn_source)) {
1954       item_titleseries = NULL;
1955     }
1956 
1957     if (item_title && *item_title) {
1958       n_title_index = REFDB_TITLE;
1959     }
1960     else if (item_titlebook && *item_titlebook) {
1961       n_title_index = REFDB_BOOKTITLE;
1962     }
1963     else if (item_titleseries && *item_titleseries) {
1964       n_title_index = REFDB_TITLE_SERIES;
1965     }
1966     n_preceeding_index = ALLTITLEPRECEEDING;
1967     n_following_index = ALLTITLEFOLLOWING;
1968     citem = dbi_result_get_string_idx(dbires_ref, ALLTITLECASE);
1969     if (citem && strcmp(citem, "UPPER") == 0) {
1970       n_uplow = 1;
1971     }
1972     else if (citem && strcmp(citem, "LOWER") == 0) {
1973       n_uplow = 2;
1974     }
1975     else if (citem && strcmp(citem, "ICAPS") == 0) {
1976       n_uplow = 3;
1977     }
1978     if (n_ref_format == REFTEIX5) {
1979       strcpy(roleatt, "level");
1980     }
1981     strcpy(role, "ALL");
1982     break;
1983   }
1984 
1985   if (!n_title_index) { /* no title data available */
1986     goto Finish;
1987   }
1988 
1989   /* now assemble the string */
1990   real_item_title = my_dbi_result_get_string_copy_idx(dbires, n_title_index);
1991   if (real_item_title && *real_item_title && !dbi_conn_error_flag(ptr_bibconns->conn_source)) { /* reference has title data */
1992     nhave_content = 1;
1993     item = my_dbi_result_get_string_copy_idx(dbires_ref, n_preceeding_index);
1994     if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* preceeding */
1995       if (sgml_entitize(&item, NULL) == NULL) {
1996 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
1997 	free(item);
1998 	free(real_item_title);
1999 	return NULL;
2000       }
2001 
2002       if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
2003 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2004 	free(item);
2005 	free(real_item_title);
2006 	return NULL;
2007       }
2008       else {
2009 	*ptr_ref = new_ref;
2010       }
2011     }
2012     if (item) {
2013       free(item);
2014     }
2015 
2016     /* all types go into a title element. */
2017     if (n_title_as_author) {
2018       if (print_elstart_x(ptr_ref, ptr_ref_len, "title", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2019 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2020 	free(real_item_title);
2021 	return NULL;
2022       }
2023     }
2024     else {
2025       if (print_elstart_x(ptr_ref, ptr_ref_len, "title", roleatt, role, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2026 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2027 	free(real_item_title);
2028 	return NULL;
2029       }
2030     }
2031 
2032     if (n_uplow == 1) { /* want uppercase */
2033       strup(real_item_title);
2034     }
2035     else if (n_uplow == 2) { /* want lowercase */
2036       strdn(real_item_title);
2037     }
2038     else if (n_uplow == 3) { /* initial caps */
2039       stricap(real_item_title);
2040     }
2041     /* else: leave as is */
2042 
2043     if (sgml_entitize(&real_item_title, NULL) == NULL) {
2044       LOG_PRINT(LOG_WARNING, get_status_msg(801));
2045       free(real_item_title);
2046       return NULL;
2047     }
2048 
2049     if ((new_ref = mstrcat(*ptr_ref, real_item_title, ptr_ref_len, 0)) == NULL) {
2050       LOG_PRINT(LOG_WARNING, get_status_msg(801));
2051       free(real_item_title);
2052       return NULL;
2053     }
2054     else {
2055       *ptr_ref = new_ref;
2056     }
2057 
2058     free(real_item_title);
2059     real_item_title = NULL;
2060 
2061     if (print_elend_x(ptr_ref, ptr_ref_len, "title", ptr_indent, ns) == NULL) {
2062 
2063       LOG_PRINT(LOG_WARNING, get_status_msg(801));
2064       return NULL;
2065     }
2066 
2067     item = my_dbi_result_get_string_copy_idx(dbires_ref, n_following_index);
2068     if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* following */
2069       if (sgml_entitize(&item, NULL) == NULL) {
2070 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2071 	free(item);
2072 	return NULL;
2073       }
2074 
2075       if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
2076 	free(item);
2077 	return NULL;
2078       }
2079       else {
2080 	*ptr_ref = new_ref;
2081       }
2082     }
2083     if (item) {
2084       free(item);
2085     }
2086   }
2087     /* else: no title found */
2088 /*   else { */
2089 /*     printf("no title found\n"); */
2090 /*   } */
2091 
2092   if (real_item_title) {
2093     free(real_item_title);
2094   }
2095 
2096 /*    printf("end format_title:%s\n", *ref); */
2097  Finish:
2098   if (!nhave_content) {
2099     (*ptr_ref)[0] = '\0';
2100   }
2101   return *ptr_ref;
2102 }
2103 
2104 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2105   format_ulink(): formats the url/link part of a
2106                       bibliography entry as a DocBook bibliomixed text
2107 
2108   char* format_ulink returns ptr to the buffer if successful, NULL if failed
2109 
2110   char** ptr_ref ptr to a ptr to a buffer created with malloc which will receive
2111         the output. The calling function must allocate the buffer
2112         with at least 4096 byte. This function will reallocate the
2113         buffer as needed. *ptr will be updated whenever a realloc is
2114         necessary. The calling function is responsible for freeing the
2115         memory again.
2116 
2117   size_t* ptr_ref_len ptr to an int holding the current length of ref.
2118                      Will be modified if ref is reallocated.
2119 
2120   dbi_result dbires ptr to a dbi result structure containing the
2121                     current reference
2122 
2123   dbi_result dbires_ref ptr to a dbi result structure containing the
2124                         reference style
2125 
2126   int type 0=url, 1=pdf, 2=fulltext, 3=related, 4=image
2127 
2128   int n_intext  0 = bibliography citation; 1 = intext citation; 2 =
2129                     intext citation subsequent
2130 
2131   int n_preceeding_index the index of the preceeding stuff in dbires_ref
2132 
2133   int n_following_index the index of the following stuff in dbires_ref
2134 
2135   const char* ns optional namespace prefix
2136 
2137   struct xmlindent* ptr_indent  indentation information
2138 
2139   int n_ref_format requested output format: REFDOCBK, REFDOCBKX, REFTEIX
2140 
2141   const char* pdfroot optional path prefix for file:// links
2142 
2143   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_ulink(char ** ptr_ref,size_t * ptr_ref_len,struct BIBCONNS * ptr_bibconns,dbi_result dbires,dbi_result dbires_ref,int type,int n_intext,int n_preceeding_index,int n_following_index,const char * ns,struct xmlindent * ptr_indent,int n_ref_format,const char * pdfroot)2144 char* format_ulink(char** ptr_ref, size_t* ptr_ref_len, struct BIBCONNS* ptr_bibconns, dbi_result dbires, dbi_result dbires_ref, int type, int n_intext, int n_preceeding_index, int n_following_index, const char* ns, struct xmlindent* ptr_indent, int n_ref_format, const char* pdfroot) {
2145   char* new_ref;
2146   char role_string[16];
2147   char *preceeding;
2148   char *following;
2149   char *entitize_string;
2150   const char *citem;
2151   dbi_result dbires_ulink;
2152 
2153 /*   printf("start format_ulink, preceeding:%d; following:%d\n", n_preceeding_index, n_following_index); */
2154 
2155   dbires_ulink = request_ulinks(ptr_bibconns->conn, my_dbi_result_get_idval(dbires, "refdb_id"), 0 /* ref entry */, type /* link type */, 0 /* is_temp */, NULL /* todo: use only user's own links? */);
2156   if (dbires_ulink == NULL) {
2157     LOG_PRINT(LOG_DEBUG, "requesting links failed");
2158     return NULL;
2159   }
2160 
2161   if (!dbi_result_get_numrows(dbires_ulink)) {
2162     /* return unaltered string */
2163     return *ptr_ref;
2164   }
2165 
2166   preceeding = my_dbi_result_get_string_copy_idx(dbires_ref, n_preceeding_index);
2167 
2168   if (preceeding && *preceeding && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* preceeding */
2169     if (sgml_entitize(&preceeding, NULL) == NULL) {
2170       LOG_PRINT(LOG_WARNING, get_status_msg(801));
2171       free(preceeding);
2172       return NULL;
2173     }
2174   }
2175 
2176   following = my_dbi_result_get_string_copy_idx(dbires_ref, n_following_index);
2177   if (following && *following && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* following */
2178     if (sgml_entitize(&following, NULL) == NULL) {
2179       LOG_PRINT(LOG_WARNING, get_status_msg(801));
2180       free(following);
2181       if (preceeding) {
2182 	free(preceeding);
2183       }
2184       return NULL;
2185     }
2186   }
2187 
2188 
2189   if (n_ref_format != REFTEIX5) {
2190     if (print_elstart_x(ptr_ref, ptr_ref_len, "bibliomisc", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2191       LOG_PRINT(LOG_CRIT, get_status_msg(801));
2192       return NULL;
2193     }
2194   }
2195 
2196 
2197   while ((citem = get_ulink(dbires_ulink)) != NULL) {
2198     if (preceeding) {
2199       if ((new_ref = mstrcat(*ptr_ref, preceeding, ptr_ref_len, 0)) == NULL) {
2200 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2201 	free(preceeding);
2202 	if (following) {
2203 	  free(following);
2204 	}
2205 	return NULL;
2206       }
2207       else {
2208 	*ptr_ref = new_ref;
2209       }
2210     }
2211 
2212     if (type > 0 && type < 5) {
2213       entitize_string = add_root_to_link(citem, pdfroot);
2214     }
2215     else {
2216       entitize_string = strdup(citem);
2217     }
2218 
2219     if (entitize_string == NULL
2220 	|| sgml_entitize(&entitize_string, NULL) == NULL) {
2221       if (preceeding) {
2222 	free(preceeding);
2223       }
2224       if (following) {
2225 	free(following);
2226       }
2227       return NULL;
2228     }
2229 
2230     if (!type) {
2231       strncpy(role_string, "url", 16);
2232     }
2233     else if (type == 1) {
2234       strncpy(role_string, "pdf", 16);
2235     }
2236     else if (type == 2) {
2237       strncpy(role_string, "fulltext", 16);
2238     }
2239     else if (type == 3) {
2240       strncpy(role_string, "related", 16);
2241     }
2242     else if (type == 4) {
2243       strncpy(role_string, "image", 16);
2244     }
2245 
2246     if (n_ref_format == REFDOCBKX5) {
2247       if (print_element_x(entitize_string, ptr_ref, ptr_ref_len, "link", "xl:role", role_string, "xl:href", entitize_string, ptr_indent, ns) == NULL) {
2248 	LOG_PRINT(LOG_CRIT, get_status_msg(801));
2249 	if (preceeding) {
2250 	  free(preceeding);
2251 	}
2252 	if (following) {
2253 	  free(following);
2254 	}
2255 	return NULL;
2256       }
2257     }
2258     else if (n_ref_format == REFTEIX5) {
2259       if (print_element_x(entitize_string, ptr_ref, ptr_ref_len, "seg", "type", "ulink", NULL, NULL, ptr_indent, ns) == NULL) {
2260 	LOG_PRINT(LOG_CRIT, get_status_msg(801));
2261 	if (preceeding) {
2262 	  free(preceeding);
2263 	}
2264 	if (following) {
2265 	  free(following);
2266 	}
2267 	return NULL;
2268       }
2269     }
2270     else {
2271       if (print_element_x(entitize_string, ptr_ref, ptr_ref_len, "ulink", "role", role_string, "url", entitize_string, ptr_indent, ns) == NULL) {
2272 	LOG_PRINT(LOG_CRIT, get_status_msg(801));
2273 	if (preceeding) {
2274 	  free(preceeding);
2275 	}
2276 	if (following) {
2277 	  free(following);
2278 	}
2279 	return NULL;
2280       }
2281     }
2282 
2283     free(entitize_string);
2284 
2285     if (following) {
2286       if ((new_ref = mstrcat(*ptr_ref, following, ptr_ref_len, 0)) == NULL) {
2287 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2288 	free(following);
2289 	if (preceeding) {
2290 	  free(preceeding);
2291 	}
2292 	return NULL;
2293       }
2294       else {
2295 	*ptr_ref = new_ref;
2296       }
2297     }
2298   } /* end while */
2299 
2300   clean_request(dbires_ulink);
2301 
2302   if (preceeding) {
2303     free(preceeding);
2304   }
2305   if (following) {
2306     free(following);
2307   }
2308 
2309   if (n_ref_format != REFTEIX5) {
2310     if (print_elend_x(ptr_ref, ptr_ref_len, "bibliomisc", ptr_indent, ns) == NULL) {
2311       LOG_PRINT(LOG_CRIT, get_status_msg(801));
2312       return NULL;
2313     }
2314   }
2315 
2316 /*    printf("end format_ulink:%s\n", *ref); */
2317 
2318   return *ptr_ref;
2319 }
2320 
2321 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2322   format_journalname(): formats the journalname part of a bibliography
2323                       entry as a DocBook bibliomixed text
2324 
2325   char* format_journalname returns ptr to the buffer if successful, NULL if failed
2326 
2327   char** ptr_ref ptr to a ptr to a buffer created with malloc which will receive
2328         the output. The calling function must allocate the buffer
2329         with at least 4096 byte. This function will reallocate the
2330         buffer as needed. *ptr will be updated whenever a realloc is
2331         necessary. The calling function is responsible for freeing the
2332         memory again.
2333 
2334   size_t* ptr_ref_len ptr to an int holding the current length of ref.
2335                      Will be modified if ref is reallocated.
2336 
2337   struct BIBCONNS* ptr_bibconns ptr to structure with database connections
2338 
2339   dbi_result dbires ptr to a dbi result structure containing the
2340                     current reference
2341 
2342   dbi_result dbires_ref ptr to a dbi result structure containing the
2343                         pubtype style
2344 
2345   const char* database ptr to a string containing the database name of the
2346                  current reference
2347 
2348   int n_intext  0 = bibliography citation; 1 = intext citation; 2 =
2349                     intext citation subsequent; 3 = bibtex output
2350 
2351   const char* ns optional namespace prefix
2352 
2353   struct xmlindent* ptr_indent  indentation information
2354 
2355   int n_ref_format requested output format: REFDOCBK, REFDOCBKX, REFTEIX
2356 
2357   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_journalname(char ** ptr_ref,size_t * ptr_ref_len,struct BIBCONNS * ptr_bibconns,dbi_result dbires,dbi_result dbires_ref,const char * database,int n_intext,const char * ns,struct xmlindent * ptr_indent,int n_ref_format)2358 char* format_journalname(char** ptr_ref, size_t* ptr_ref_len, struct BIBCONNS* ptr_bibconns, dbi_result dbires, dbi_result dbires_ref, const char* database, int n_intext, const char* ns, struct xmlindent* ptr_indent, int n_ref_format) {
2359   int nhave_content = 0;
2360   int errcode; /* receives error code for periodical requests */
2361   char *new_ref;
2362   char *period;
2363   char periodical[256] = "";
2364   char *item;
2365   const char *citem;
2366   char *mod_periodical;
2367 
2368   /* try the first choice of the periodical name */
2369   citem = dbi_result_get_string_idx(dbires_ref, JOURNALNAMEDEFAULTTEXT);
2370   if (citem && strcmp(citem, "ABBREV") == 0) {
2371     item = get_periodical(ptr_bibconns->conn_source, periodical, database, 3, &errcode, 0, my_dbi_result_get_idval(dbires, "refdb_id"), NULL /* no frequency required */);
2372     if (item == NULL && errcode != 1) {
2373       return NULL; /* db error */
2374     }
2375   }
2376   else if (citem && strcmp(citem, "FULL") == 0) {
2377     item = get_periodical(ptr_bibconns->conn_source, periodical, database, 0, &errcode, 0, my_dbi_result_get_idval(dbires, "refdb_id"), NULL /* no frequency required */);
2378     if (item == NULL && errcode != 1) {
2379       return NULL; /* db error */
2380     }
2381   }
2382   else if (citem && strcmp(citem, "USERONE") == 0) {
2383     item = get_periodical(ptr_bibconns->conn_source, periodical, database, 1, &errcode, 0, my_dbi_result_get_idval(dbires, "refdb_id"), NULL /* no frequency required */);
2384     if (item == NULL && errcode != 1) {
2385       return NULL; /* db error */
2386     }
2387   }
2388   else if (citem && strcmp(citem, "USERTWO") == 0) {
2389     item = get_periodical(ptr_bibconns->conn_source, periodical, database, 2, &errcode, 0, my_dbi_result_get_idval(dbires, "refdb_id"), NULL /* no frequency required */);
2390     if (item == NULL && errcode != 1) {
2391       return NULL; /* db error */
2392     }
2393   }
2394 
2395   if (!*periodical) { /* try the second choice */
2396     citem = dbi_result_get_string_idx(dbires_ref, JOURNALNAMEALTERNATETEXT);
2397     if (citem && strcmp(citem, "AABBREV") == 0) {
2398       item = get_periodical(ptr_bibconns->conn_source, periodical, database, 3, &errcode, 0, my_dbi_result_get_idval(dbires, "refdb_id"), NULL /* no frequency required */);
2399       if (item == NULL && errcode != 1) {
2400 	return NULL; /* db error */
2401       }
2402     }
2403     else if (citem && strcmp(citem, "AFULL") == 0) {
2404       item = get_periodical(ptr_bibconns->conn_source, periodical, database, 0, &errcode, 0, my_dbi_result_get_idval(dbires, "refdb_id"), NULL /* no frequency required */);
2405       if (item == NULL && errcode != 1) {
2406 	return NULL; /* db error */
2407       }
2408     }
2409     else if (citem && strcmp(citem, "AUSERONE") == 0) {
2410       item = get_periodical(ptr_bibconns->conn_source, periodical, database, 1, &errcode, 0, my_dbi_result_get_idval(dbires, "refdb_id"), NULL /* no frequency required */);
2411       if (item == NULL && errcode != 1) {
2412 	return NULL; /* db error */
2413       }
2414     }
2415     else if (citem && strcmp(citem, "AUSERTWO") == 0) {
2416       item = get_periodical(ptr_bibconns->conn_source, periodical, database, 2, &errcode, 0, my_dbi_result_get_idval(dbires, "refdb_id"), NULL /* no frequency required */);
2417       if (item == NULL && errcode != 1) {
2418 	return NULL; /* db error */
2419       }
2420     }
2421   }
2422 
2423   if (!*periodical) {
2424 /*     (*ptr_ref)[0] = '\0'; */
2425     return *ptr_ref; /* no periodical specified */
2426   }
2427 
2428   /* reference has periodical data */
2429   nhave_content = 1;
2430   item = my_dbi_result_get_string_copy_idx(dbires_ref, JOURNALNAMEPRECEEDING);
2431   if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* preceeding */
2432     if (n_intext != 3) {
2433       if (sgml_entitize(&item, NULL) == NULL) {
2434 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2435 	free(item);
2436 	return NULL;
2437       }
2438       if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
2439 	free(item);
2440 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2441 	return NULL;
2442       }
2443       else {
2444 	*ptr_ref = new_ref;
2445       }
2446     }
2447     else {
2448       char* escaped_item;
2449 
2450       if ((escaped_item = escape_latex_chars_copy(item, strlen(item))) == NULL) {
2451 	free(item);
2452 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2453 	return NULL;
2454       }
2455 
2456       if ((new_ref = mstrcat(*ptr_ref, escaped_item, ptr_ref_len, 0)) == NULL) {
2457 	free(item);
2458 	free(escaped_item);
2459 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2460 	return NULL;
2461       }
2462       else {
2463 	*ptr_ref = new_ref;
2464 	free(escaped_item);
2465       }
2466     }
2467   }
2468   if (item) {
2469     free(item);
2470   }
2471 
2472   if (n_intext != 3) {
2473     if (n_ref_format == REFTEIX5) {
2474       if (print_elstart_x(ptr_ref, ptr_ref_len, "title", "level", "m", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2475 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2476 	return NULL;
2477       }
2478     }
2479     else {
2480       if (print_elstart_x(ptr_ref, ptr_ref_len, "title", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2481 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2482 	return NULL;
2483       }
2484     }
2485   }
2486 
2487   /* do some formatting */
2488   mod_periodical = malloc(strlen(periodical)*2); /* extra spaces */
2489   if (!mod_periodical) {
2490     LOG_PRINT(LOG_WARNING, get_status_msg(801));
2491     return NULL;
2492   }
2493 
2494   strcpy(mod_periodical, periodical);
2495 
2496   citem = dbi_result_get_string_idx(dbires_ref, JOURNALNAMEPUNCTUATION);
2497   if (citem && strcmp(citem, "SPACE") == 0) {
2498     /* replace all periods with spaces */
2499     while ((period = strchr(mod_periodical, (int)'.')) != NULL) {
2500       *period = ' ';
2501     }
2502   }
2503   else if (citem && strcmp(citem, "PERIODSPACE") == 0) {
2504     /* insert a space after each period */
2505     period = mod_periodical;
2506     while((period = strchr(period, (int)'.')) != NULL) {
2507       /* don't add a space if this is the last word */
2508       if (*(period+1) != '\0') {
2509 	replace_char_string(period, ". ", 1);
2510 	period++;
2511       }
2512       else {
2513 	break;
2514       }
2515     }
2516   }
2517   /* else: database already contains the periodonly format */
2518 
2519   /* handle the case requirements */
2520   citem = dbi_result_get_string_idx(dbires_ref, JOURNALNAMECASE);
2521   if (citem && strcmp(citem, "UPPER") == 0) {
2522     strup(mod_periodical);
2523   }
2524   else if (citem && strcmp(citem, "LOWER") == 0) {
2525     strdn(mod_periodical);
2526   }
2527   else if (citem && strcmp(citem, "ICAPS") == 0) {
2528     stricap(mod_periodical);
2529   }
2530   /* else: asis needs no changes */
2531 
2532   if (n_intext != 3) {
2533     if (sgml_entitize(&mod_periodical, NULL) == NULL) {
2534       free(mod_periodical);
2535       return NULL;
2536     }
2537 
2538     if ((new_ref = mstrcat(*ptr_ref, mod_periodical, ptr_ref_len, 0)) == NULL) {
2539       free(mod_periodical);
2540       LOG_PRINT(LOG_WARNING, get_status_msg(801));
2541       return NULL;
2542     }
2543     else {
2544       *ptr_ref = new_ref;
2545     }
2546   }
2547   else {
2548     char* escaped_item;
2549 
2550     if ((escaped_item = escape_latex_chars_copy(mod_periodical, strlen(mod_periodical))) == NULL) {
2551       free(mod_periodical);
2552       LOG_PRINT(LOG_WARNING, get_status_msg(801));
2553       return NULL;
2554     }
2555 
2556     if ((new_ref = mstrcat(*ptr_ref, escaped_item, ptr_ref_len, 0)) == NULL) {
2557       free(mod_periodical);
2558       free(escaped_item);
2559       LOG_PRINT(LOG_WARNING, get_status_msg(801));
2560       return NULL;
2561     }
2562     else {
2563       *ptr_ref = new_ref;
2564       free(escaped_item);
2565     }
2566   }
2567 
2568   free(mod_periodical);
2569 
2570   if (n_intext != 3) {
2571     if (print_elend_x(ptr_ref, ptr_ref_len, "title", ptr_indent, ns) == NULL) {
2572       LOG_PRINT(LOG_WARNING, get_status_msg(801));
2573       return NULL;
2574     }
2575   }
2576 
2577   item = my_dbi_result_get_string_copy_idx(dbires_ref, JOURNALNAMEFOLLOWING);
2578   if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* following */
2579     if (n_intext != 3) {
2580       if (sgml_entitize(&item, NULL) == NULL) {
2581 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2582 	free(item);
2583 	return NULL;
2584       }
2585 
2586       if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
2587 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2588 	return NULL;
2589       }
2590       else {
2591 	*ptr_ref = new_ref;
2592       }
2593     }
2594     else {
2595       char* escaped_item;
2596 
2597       if ((escaped_item = escape_latex_chars_copy(item, strlen(item))) == NULL) {
2598 	free(item);
2599 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2600 	return NULL;
2601       }
2602 
2603       if ((new_ref = mstrcat(*ptr_ref, escaped_item, ptr_ref_len, 0)) == NULL) {
2604 	free(item);
2605 	free(escaped_item);
2606 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2607 	return NULL;
2608       }
2609       else {
2610 	*ptr_ref = new_ref;
2611 	free(escaped_item);
2612       }
2613     }
2614   }
2615   if (item) {
2616     free(item);
2617   }
2618 
2619   if (!nhave_content) {
2620     (*ptr_ref)[0] = '\0';
2621   }
2622   return *ptr_ref;
2623 }
2624 
2625 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2626   format_simple(): formats a simple part of a bibliography entry
2627                       as a DocBook bibliomixed text
2628 
2629   char* format_simple returns ptr to the buffer if successful, NULL if failed
2630 
2631   char** ptr_ref ptr to a ptr to a buffer created with malloc which will receive
2632         the output. The calling function must allocate the buffer
2633         with at least 4096 byte. This function will reallocate the
2634         buffer as needed. *ptr will be updated whenever a realloc is
2635         necessary. The calling function is responsible for freeing the
2636         memory again.
2637 
2638   size_t* ptr_ref_len ptr to an int holding the current length of ref.
2639                      Will be modified if ref is reallocated.
2640 
2641   dbi_result dbires ptr to a dbi result structure containing the
2642                     current reference
2643 
2644   dbi_result dbires_ref ptr to a dbi result structure containing the
2645                     reference style
2646 
2647   int n_intext  0 = bibliography citation; 1 = intext citation; 2 =
2648                     intext citation subsequent
2649 
2650   int n_item_index the index of the requested contents in dbires
2651 
2652   int n_preceeding_index the index of the preceeding stuff in dbires_ref
2653 
2654   int n_following_index the index of the following stuff in dbires_ref
2655 
2656   const char* elname the name of the element that receives the output
2657 
2658   const char* ns optional namespace prefix
2659 
2660   struct xmlindent* ptr_indent  indentation information
2661 
2662   int n_ref_format requested output format: REFDOCBK, REFDOCBKX, REFTEIX
2663 
2664   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_simple(char ** ptr_ref,size_t * ptr_ref_len,struct BIBCONNS * ptr_bibconns,dbi_result dbires,dbi_result dbires_ref,int n_intext,int n_item_index,int n_preceeding_index,int n_following_index,const char * elname,const char * ns,struct xmlindent * ptr_indent,int n_ref_format)2665 char* format_simple(char** ptr_ref, size_t* ptr_ref_len, struct BIBCONNS* ptr_bibconns, dbi_result dbires, dbi_result dbires_ref, int n_intext, int n_item_index, int n_preceeding_index, int n_following_index, const char* elname, const char* ns, struct xmlindent* ptr_indent, int n_ref_format) {
2666   int nhave_content = 0;
2667   char *new_ref;
2668   char *item_simple;
2669   char *item;
2670 
2671   item_simple = my_dbi_result_get_string_copy_idx(dbires, n_item_index);
2672 
2673   if (item_simple && *item_simple && !dbi_conn_error_flag(ptr_bibconns->conn_source)) { /* reference has requested data */
2674     nhave_content = 1;
2675 
2676     if (sgml_entitize(&item_simple, NULL) == NULL) {
2677       LOG_PRINT(LOG_WARNING, get_status_msg(801));
2678       free(item_simple);
2679       return NULL;
2680     }
2681 
2682     LOG_PRINT(LOG_DEBUG, elname);
2683 
2684     /* some elements need some special care */
2685     item = my_dbi_result_get_string_copy_idx(dbires_ref, n_preceeding_index);
2686     if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* preceeding */
2687       if (sgml_entitize(&item, NULL) == NULL) {
2688 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2689 	free(item);
2690 	free(item_simple);
2691 	return NULL;
2692       }
2693 
2694       if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
2695 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2696 	free(item);
2697 	free(item_simple);
2698 	return NULL;
2699       }
2700       else {
2701 	*ptr_ref = new_ref;
2702       }
2703     }
2704     if (item) {
2705       free(item);
2706     }
2707 
2708     if (!strcmp(elname, "city")) {
2709       if (n_ref_format == REFTEIX5) {
2710 	if (print_elstart_x(ptr_ref, ptr_ref_len, "seg", "type", "pubplace", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2711 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2712 	  free(item_simple);
2713 	  return NULL;
2714 	}
2715       }
2716       else {
2717 	if (print_elstart_x(ptr_ref, ptr_ref_len, "address", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2718 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2719 	  free(item_simple);
2720 	  return NULL;
2721 	}
2722 	if (print_elstart_x(ptr_ref, ptr_ref_len, "city", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2723 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2724 	  free(item_simple);
2725 	  return NULL;
2726 	}
2727       }
2728     }
2729     else if (!strcmp(elname, "ulink")) {
2730       if (n_ref_format == REFTEIX5) {
2731 	if (print_elstart_x(ptr_ref, ptr_ref_len, "seg", "type", "ulink", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2732 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2733 	  free(item_simple);
2734 	  return NULL;
2735 	}
2736       }
2737       else {
2738 	if (print_elstart_x(ptr_ref, ptr_ref_len, "bibliomisc", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2739 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2740 	  free(item_simple);
2741 	  return NULL;
2742 	}
2743 	if (print_elstart_x(ptr_ref, ptr_ref_len, "ulink", "url", item_simple, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2744 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2745 	  free(item_simple);
2746 	  return NULL;
2747 	}
2748       }
2749     }
2750     else if (!strcmp(elname, "userdef1")
2751 	     || !strcmp(elname, "userdef2")
2752 	     || !strcmp(elname, "userdef3")
2753 	     || !strcmp(elname, "userdef4")
2754 	     || !strcmp(elname, "userdef5")
2755 	     || !strcmp(elname, "link0")
2756 	     || !strcmp(elname, "link1")
2757 	     || !strcmp(elname, "link2")
2758 	     || !strcmp(elname, "link3")
2759 	     || !strcmp(elname, "link4")
2760 	     || !strcmp(elname, "typeofwork")
2761 	     || !strcmp(elname, "area")
2762 	     || !strcmp(elname, "ostype")
2763 	     || !strcmp(elname, "degree")
2764 	     || !strcmp(elname, "runningtime")
2765 	     || !strcmp(elname, "classcodeintl")
2766 	     || !strcmp(elname, "classcodeus")
2767 	     || !strcmp(elname, "senderemail")
2768 	     || !strcmp(elname, "recipientemail")
2769 	     || !strcmp(elname, "mediatype")
2770 	     || !strcmp(elname, "numvolumes")
2771 	     || !strcmp(elname, "edition")
2772 	     || !strcmp(elname, "computer")
2773 	     || !strcmp(elname, "conferencelocation")
2774 	     || !strcmp(elname, "registrynum")
2775 	     || !strcmp(elname, "classification")
2776 	     || !strcmp(elname, "section")
2777 	     || !strcmp(elname, "pamphletnum")
2778 	     || !strcmp(elname, "chapternum")
2779 ) {
2780       if (n_ref_format == REFTEIX5) {
2781 	if (print_elstart_x(ptr_ref, ptr_ref_len, "seg", "type", elname, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2782 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2783 	  free(item_simple);
2784 	  return NULL;
2785 	}
2786       }
2787       else {
2788 	if (print_elstart_x(ptr_ref, ptr_ref_len, "bibliomset", "role", elname, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2789 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2790 	  free(item_simple);
2791 	  return NULL;
2792 	}
2793       }
2794     }
2795     else if (!strcmp(elname, "volumenum")) {
2796       if (n_ref_format == REFTEIX5) {
2797 	if (print_elstart_x(ptr_ref, ptr_ref_len, "seg", "type", "volume", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2798 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2799 	  free(item_simple);
2800 	  return NULL;
2801 	}
2802       }
2803       else {
2804 	if (print_elstart_x(ptr_ref, ptr_ref_len, elname, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2805 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2806 	  free(item_simple);
2807 	  return NULL;
2808 	}
2809       }
2810     }
2811     else if (!strcmp(elname, "issuenum")) {
2812       if (n_ref_format == REFTEIX5) {
2813 	if (print_elstart_x(ptr_ref, ptr_ref_len, "seg", "type", "issue", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2814 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2815 	  free(item_simple);
2816 	  return NULL;
2817 	}
2818       }
2819       else {
2820 	if (print_elstart_x(ptr_ref, ptr_ref_len, elname, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2821 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2822 	  free(item_simple);
2823 	  return NULL;
2824 	}
2825       }
2826     }
2827     else if (!strcmp(elname, "publishername")) {
2828       if (n_ref_format == REFTEIX5) {
2829 	if (print_elstart_x(ptr_ref, ptr_ref_len, "seg", "type", "publisher", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2830 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2831 	  free(item_simple);
2832 	  return NULL;
2833 	}
2834       }
2835       else {
2836 	if (print_elstart_x(ptr_ref, ptr_ref_len, elname, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2837 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2838 	  free(item_simple);
2839 	  return NULL;
2840 	}
2841       }
2842     }
2843     else {
2844       if (print_elstart_x(ptr_ref, ptr_ref_len, elname, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
2845 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2846 	free(item_simple);
2847 	return NULL;
2848       }
2849     }
2850 
2851     if ((new_ref = mstrcat(*ptr_ref, item_simple, ptr_ref_len, 0)) == NULL) {
2852       LOG_PRINT(LOG_WARNING, get_status_msg(801));
2853       free(item_simple);
2854       return NULL;
2855     }
2856     else {
2857       *ptr_ref = new_ref;
2858     }
2859 
2860     if (!strcmp(elname, "city")) {
2861       if (n_ref_format == REFTEIX5) {
2862 	if (print_elend_x(ptr_ref, ptr_ref_len, "seg", ptr_indent, ns) == NULL) {
2863 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2864 	  free(item_simple);
2865 	  return NULL;
2866 	}
2867       }
2868       else {
2869 	if (print_elend_x(ptr_ref, ptr_ref_len, "city", ptr_indent, ns) == NULL) {
2870 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2871 	  free(item_simple);
2872 	  return NULL;
2873 	}
2874 	if (print_elend_x(ptr_ref, ptr_ref_len, "address", ptr_indent, ns) == NULL) {
2875 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2876 	  free(item_simple);
2877 	  return NULL;
2878 	}
2879       }
2880     }
2881     else if (!strcmp(elname, "ulink")) {
2882       if (n_ref_format == REFTEIX5) {
2883 	if (print_elend_x(ptr_ref, ptr_ref_len, "seg", ptr_indent, ns) == NULL) {
2884 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2885 	  free(item_simple);
2886 	  return NULL;
2887 	}
2888       }
2889       else {
2890 	if (print_elend_x(ptr_ref, ptr_ref_len, "ulink", ptr_indent, ns) == NULL) {
2891 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2892 	  free(item_simple);
2893 	  return NULL;
2894 	}
2895 	if (print_elend_x(ptr_ref, ptr_ref_len, "bibliomisc", ptr_indent, ns) == NULL) {
2896 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2897 	  free(item_simple);
2898 	  return NULL;
2899 	}
2900       }
2901     }
2902     else if (!strcmp(elname, "userdef1")
2903 	     || !strcmp(elname, "userdef2")
2904 	     || !strcmp(elname, "userdef3")
2905 	     || !strcmp(elname, "userdef4")
2906 	     || !strcmp(elname, "userdef5")
2907 	     || !strcmp(elname, "link0")
2908 	     || !strcmp(elname, "link1")
2909 	     || !strcmp(elname, "link2")
2910 	     || !strcmp(elname, "link3")
2911 	     || !strcmp(elname, "link4")
2912 	     || !strcmp(elname, "typeofwork")
2913 	     || !strcmp(elname, "area")
2914 	     || !strcmp(elname, "ostype")
2915 	     || !strcmp(elname, "degree")
2916 	     || !strcmp(elname, "runningtime")
2917 	     || !strcmp(elname, "classcodeintl")
2918 	     || !strcmp(elname, "classcodeus")
2919 	     || !strcmp(elname, "senderemail")
2920 	     || !strcmp(elname, "recipientemail")
2921 	     || !strcmp(elname, "mediatype")
2922 	     || !strcmp(elname, "numvolumes")
2923 	     || !strcmp(elname, "edition")
2924 	     || !strcmp(elname, "computer")
2925 	     || !strcmp(elname, "conferencelocation")
2926 	     || !strcmp(elname, "registrynum")
2927 	     || !strcmp(elname, "classification")
2928 	     || !strcmp(elname, "section")
2929 	     || !strcmp(elname, "pamphletnum")
2930 	     || !strcmp(elname, "chapternum")
2931 ) {
2932       if (n_ref_format == REFTEIX5) {
2933 	if (print_elend_x(ptr_ref, ptr_ref_len, "seg", ptr_indent, ns) == NULL) {
2934 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2935 	  free(item_simple);
2936 	  return NULL;
2937 	}
2938       }
2939       else {
2940 	if (print_elend_x(ptr_ref, ptr_ref_len, "bibliomset", ptr_indent, ns) == NULL) {
2941 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2942 	  free(item_simple);
2943 	  return NULL;
2944 	}
2945       }
2946     }
2947     else if (!strcmp(elname, "volumenum")) {
2948       if (n_ref_format == REFTEIX5) {
2949 	if (print_elend_x(ptr_ref, ptr_ref_len, "seg", ptr_indent, ns) == NULL) {
2950 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2951 	  free(item_simple);
2952 	  return NULL;
2953 	}
2954       }
2955       else {
2956 	if (print_elend_x(ptr_ref, ptr_ref_len, elname, ptr_indent, ns) == NULL) {
2957 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2958 	  free(item_simple);
2959 	  return NULL;
2960 	}
2961       }
2962     }
2963     else if (!strcmp(elname, "issuenum")) {
2964       if (n_ref_format == REFTEIX5) {
2965 	if (print_elend_x(ptr_ref, ptr_ref_len, "seg", ptr_indent, ns) == NULL) {
2966 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2967 	  free(item_simple);
2968 	  return NULL;
2969 	}
2970       }
2971       else {
2972 	if (print_elend_x(ptr_ref, ptr_ref_len, elname, ptr_indent, ns) == NULL) {
2973 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2974 	  free(item_simple);
2975 	  return NULL;
2976 	}
2977       }
2978     }
2979     else if (!strcmp(elname, "publishername")) {
2980       if (n_ref_format == REFTEIX5) {
2981 	if (print_elend_x(ptr_ref, ptr_ref_len, "seg", ptr_indent, ns) == NULL) {
2982 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2983 	  free(item_simple);
2984 	  return NULL;
2985 	}
2986       }
2987       else {
2988 	if (print_elend_x(ptr_ref, ptr_ref_len, elname, ptr_indent, ns) == NULL) {
2989 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
2990 	  free(item_simple);
2991 	  return NULL;
2992 	}
2993       }
2994     }
2995     else {
2996       if (print_elend_x(ptr_ref, ptr_ref_len, elname, ptr_indent, ns) == NULL) {
2997 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
2998 	free(item_simple);
2999 	return NULL;
3000       }
3001     }
3002 
3003     item = my_dbi_result_get_string_copy_idx(dbires_ref, n_following_index);
3004     if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* following */
3005       if (sgml_entitize(&item, NULL) == NULL) {
3006 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3007 	free(item);
3008 	free(item_simple);
3009 	return NULL;
3010       }
3011 
3012       if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
3013 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3014 	free(item);
3015 	free(item_simple);
3016 	return NULL;
3017       }
3018       else {
3019 	*ptr_ref = new_ref;
3020       }
3021     }
3022     if (item) {
3023       free(item);
3024     }
3025   }
3026   if (item_simple) {
3027     free(item_simple);
3028   }
3029 
3030   if (!nhave_content) {
3031     (*ptr_ref)[0] = '\0';
3032   }
3033   return *ptr_ref;
3034 }
3035 
3036 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3037   format_pages(): formats the pages part of a bibliography entry
3038                       as a DocBook bibliomixed text
3039 
3040   char* format_pages returns ptr to the buffer if successful, NULL if failed
3041 
3042   char** ptr_ref ptr to a ptr to a buffer created with malloc which will receive
3043         the output. The calling function must allocate the buffer
3044         with at least 4096 byte. This function will reallocate the
3045         buffer as needed. *ptr will be updated whenever a realloc is
3046         necessary. The calling function is responsible for freeing the
3047         memory again.
3048 
3049   size_t* ptr_ref_len ptr to an int holding the current length of ref.
3050                      Will be modified if ref is reallocated.
3051 
3052   struct BIBCONNS* ptr_bibconns ptr to structure with database connections
3053 
3054   dbi_result dbires ptr to a dbi result structure containing the
3055                     current reference
3056 
3057   dbi_result dbires_ref ptr to a dbi result structure containing
3058                     the reference style
3059 
3060   int n_intext  0 = bibliography citation; 1 = intext citation; 2 =
3061                     intext citation subsequent
3062 
3063   const char* ns optional namespace prefix
3064 
3065   struct xmlindent* ptr_indent  indentation information
3066 
3067   int n_ref_format requested output format: REFDOCBK, REFDOCBKX, REFTEIX
3068 
3069   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_pages(char ** ptr_ref,size_t * ptr_ref_len,struct BIBCONNS * ptr_bibconns,dbi_result dbires,dbi_result dbires_ref,int n_intext,const char * ns,struct xmlindent * ptr_indent,int n_ref_format)3070 char* format_pages(char** ptr_ref, size_t* ptr_ref_len, struct BIBCONNS* ptr_bibconns, dbi_result dbires, dbi_result dbires_ref, int n_intext, const char* ns, struct xmlindent* ptr_indent, int n_ref_format) {
3071   int nhave_content = 0;
3072   char *new_ref;
3073   char new_endpage[256];
3074   char *item_sp;
3075   char *item_ep;
3076   char *item;
3077   const char *item_type;
3078   struct lilimem sentinel;
3079 /*   dbi_conn conn; */
3080 
3081 /*   conn = dbi_result_get_conn(dbires_ref); */
3082 
3083   sentinel.ptr_mem = NULL;
3084   sentinel.ptr_next = NULL;
3085   sentinel.varname[0] = '\0';
3086 
3087   item_sp = my_dbi_result_get_string_copy_idx(dbires, REFDB_STARTPAGE);
3088   if (item_sp  && dbi_conn_error_flag(ptr_bibconns->conn_source)) {
3089     free(item_sp);
3090     item_sp = NULL;
3091   }
3092   else if (item_sp) {
3093     if (insert_lilimem(&sentinel, (void**)&item_sp, NULL)) {
3094       return NULL;
3095     }
3096   }
3097 
3098   item_ep = my_dbi_result_get_string_copy_idx(dbires, REFDB_ENDPAGE);
3099   if (item_ep  && dbi_conn_error_flag(ptr_bibconns->conn_source)) {
3100     free(item_ep);
3101     item_ep = NULL;
3102   }
3103   else if (item_ep) {
3104     if (insert_lilimem(&sentinel, (void**)&item_ep, NULL)) {
3105       delete_all_lilimem(&sentinel);
3106       return NULL;
3107     }
3108   }
3109 
3110   if (item_sp && *item_sp) { /* reference has at least start page data */
3111     nhave_content = 1;
3112     item = my_dbi_result_get_string_copy_idx(dbires_ref, PAGESPRECEEDING);
3113     if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* preceeding */
3114       if (sgml_entitize(&item, NULL) == NULL) {
3115 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3116 	free(item);
3117 	delete_all_lilimem(&sentinel);
3118 	return NULL;
3119       }
3120 
3121       if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
3122 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3123 	free(item);
3124 	delete_all_lilimem(&sentinel);
3125 	return NULL;
3126       }
3127       else {
3128 	*ptr_ref = new_ref;
3129       }
3130     }
3131     if (item) {
3132       free(item);
3133     }
3134 
3135     /* if we only have the start page or the format says to only use the start page, forget about the end page */
3136     item_type = dbi_result_get_string_idx(dbires_ref, PAGESPAGERANGETYPE);
3137     if (!item_ep || !*item_ep || (item_type && strcmp(item_type, "STARTONLY") == 0)) {
3138 
3139       item = my_dbi_result_get_string_copy_idx(dbires_ref, PAGESSINGLEPAGEPRECEEDING);
3140       if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
3141 	if (sgml_entitize(&item, NULL) == NULL) {
3142 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3143 	  free(item);
3144 	  delete_all_lilimem(&sentinel);
3145 	  return NULL;
3146 	}
3147 
3148 	if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
3149 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3150 	  free(item);
3151 	  delete_all_lilimem(&sentinel);
3152 	  return NULL;
3153 	}
3154 	else {
3155 	  *ptr_ref = new_ref;
3156 	}
3157       }
3158       if (item) {
3159 	free(item);
3160       }
3161 
3162       if (n_ref_format == REFTEIX5) {
3163 	if (print_elstart_x(ptr_ref, ptr_ref_len, "seg", "type", "pages", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
3164 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3165 	  delete_all_lilimem(&sentinel);
3166 	  return NULL;
3167 	}
3168       }
3169       else {
3170 	if (print_elstart_x(ptr_ref, ptr_ref_len, "pagenums", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
3171 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3172 	  delete_all_lilimem(&sentinel);
3173 	  return NULL;
3174 	}
3175       }
3176 
3177       if (sgml_entitize(&item_sp, NULL) == NULL) {
3178 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3179 	delete_all_lilimem(&sentinel);
3180 	return NULL;
3181       }
3182 
3183       if ((new_ref = mstrcat(*ptr_ref, item_sp, ptr_ref_len, 0)) == NULL) {
3184 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3185 	delete_all_lilimem(&sentinel);
3186 	return NULL;
3187       }
3188       else {
3189 	*ptr_ref = new_ref;
3190       }
3191 
3192       if (n_ref_format == REFTEIX5) {
3193 	if (print_elend_x(ptr_ref, ptr_ref_len, "seg", ptr_indent, ns) == NULL) {
3194 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3195 	  delete_all_lilimem(&sentinel);
3196 	  return NULL;
3197 	}
3198       }
3199       else {
3200 	if (print_elend_x(ptr_ref, ptr_ref_len, "pagenums", ptr_indent, ns) == NULL) {
3201 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3202 	  delete_all_lilimem(&sentinel);
3203 	  return NULL;
3204 	}
3205       }
3206 
3207       item = my_dbi_result_get_string_copy_idx(dbires_ref, PAGESSINGLEPAGEFOLLOWING);
3208       if (item && *item & !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
3209 	if (sgml_entitize(&item, NULL) == NULL) {
3210 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3211 	  free(item);
3212 	  delete_all_lilimem(&sentinel);
3213 	  return NULL;
3214 	}
3215 
3216 	if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
3217 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3218 	  free(item);
3219 	  delete_all_lilimem(&sentinel);
3220 	  return NULL;
3221 	}
3222 	else {
3223 	  *ptr_ref = new_ref;
3224 	}
3225       }
3226       if (item) {
3227 	free(item);
3228       }
3229     }
3230     /* we have both start- and end-pages and we're supposed to render both */
3231     else if (item_ep && *item_ep) {
3232       item = my_dbi_result_get_string_copy_idx(dbires_ref, PAGESPAGERANGEPRECEEDING);
3233       if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
3234 	if (sgml_entitize(&item, NULL) == NULL) {
3235 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3236 	  free(item);
3237 	  delete_all_lilimem(&sentinel);
3238 	  return NULL;
3239 	}
3240 
3241 	if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
3242 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3243 	  free(item);
3244 	  delete_all_lilimem(&sentinel);
3245 	  return NULL;
3246 	}
3247 	else {
3248 	  *ptr_ref = new_ref;
3249 	}
3250       }
3251       if (item) {
3252 	free(item);
3253       }
3254 
3255       if (n_ref_format == REFTEIX5) {
3256 	if (print_elstart_x(ptr_ref, ptr_ref_len, "seg", "type", "pages", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
3257 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3258 	  delete_all_lilimem(&sentinel);
3259 	  return NULL;
3260 	}
3261       }
3262       else {
3263 	if (print_elstart_x(ptr_ref, ptr_ref_len, "pagenums", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
3264 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3265 	  delete_all_lilimem(&sentinel);
3266 	  return NULL;
3267 	}
3268       }
3269 
3270       if (sgml_entitize(&item_sp, NULL) == NULL) {
3271 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3272 	delete_all_lilimem(&sentinel);
3273 	return NULL;
3274       }
3275 
3276       if ((new_ref = mstrcat(*ptr_ref, item_sp, ptr_ref_len, 0)) == NULL) {
3277 	return NULL;
3278       }
3279       else {
3280 	*ptr_ref = new_ref;
3281       }
3282 
3283       /* if RANGESEPARATOR is defined, use it (even if it is the empty string)
3284          otherwise use a dash */
3285       item = my_dbi_result_get_string_copy_idx(dbires_ref, PAGESPAGERANGERANGESEPARATOR);
3286       if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
3287 	if (sgml_entitize(&item, NULL) == NULL) {
3288 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3289 	  free(item);
3290 	  delete_all_lilimem(&sentinel);
3291 	  return NULL;
3292 	}
3293 
3294 	if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
3295 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3296 	  free(item);
3297 	  delete_all_lilimem(&sentinel);
3298 	  return NULL;
3299 	}
3300 	else {
3301 	  *ptr_ref = new_ref;
3302 	}
3303       }
3304       else {
3305 	if ((new_ref = mstrcat(*ptr_ref, "-", ptr_ref_len, 0)) == NULL) {
3306 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3307 	  delete_all_lilimem(&sentinel);
3308 	  return NULL;
3309 	}
3310 	else {
3311 	  *ptr_ref = new_ref;
3312 	}
3313       }
3314       if (item) {
3315 	free(item);
3316       }
3317 
3318       if ((new_ref = mstrcat(*ptr_ref, normalize_pages(new_endpage, item_sp, item_ep, item_type), ptr_ref_len, 0)) == NULL) {
3319 	delete_all_lilimem(&sentinel);
3320 	return NULL;
3321       }
3322       else {
3323 	*ptr_ref = new_ref;
3324       }
3325 
3326       if (n_ref_format == REFTEIX5) {
3327 	if (print_elend_x(ptr_ref, ptr_ref_len, "seg", ptr_indent, ns) == NULL) {
3328 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3329 	  delete_all_lilimem(&sentinel);
3330 	  return NULL;
3331 	}
3332       }
3333       else {
3334 	if (print_elend_x(ptr_ref, ptr_ref_len, "pagenums", ptr_indent, ns) == NULL) {
3335 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3336 	  delete_all_lilimem(&sentinel);
3337 	  return NULL;
3338 	}
3339       }
3340 
3341       item = my_dbi_result_get_string_copy_idx(dbires_ref, PAGESPAGERANGEFOLLOWING);
3342       if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
3343 	if (sgml_entitize(&item, NULL) == NULL) {
3344 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3345 	  free(item);
3346 	  delete_all_lilimem(&sentinel);
3347 	  return NULL;
3348 	}
3349 
3350 	if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
3351 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
3352 	  free(item);
3353 	  delete_all_lilimem(&sentinel);
3354 	  return NULL;
3355 	}
3356 	else {
3357 	  *ptr_ref = new_ref;
3358 	}
3359       }
3360       if (item) {
3361 	free(item);
3362       }
3363     }
3364     /* else: no endpage data available */
3365 
3366     item = my_dbi_result_get_string_copy_idx(dbires_ref, PAGESFOLLOWING);
3367     if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* following */
3368       if (sgml_entitize(&item, NULL) == NULL) {
3369 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3370 	free(item);
3371 	delete_all_lilimem(&sentinel);
3372 	return NULL;
3373       }
3374 
3375       if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
3376 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3377 	free(item);
3378 	delete_all_lilimem(&sentinel);
3379 	return NULL;
3380       }
3381       else {
3382 	*ptr_ref = new_ref;
3383       }
3384     }
3385     if (item) {
3386       free(item);
3387     }
3388   }
3389 
3390   delete_all_lilimem(&sentinel);
3391 
3392   if (!nhave_content) {
3393     (*ptr_ref)[0] = '\0';
3394   }
3395   return *ptr_ref;
3396 }
3397 
3398 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3399   format_notes(): formats the notes part of a bibliography entry
3400                       as a DocBook bibliomixed text
3401 
3402   char* format_notes returns NULL on error, ptr to ref if ok. ref may
3403                      be reallocated during the rendering, so it is
3404                      essential that upon return of this function *ONLY*
3405                      the returned pointer is used to address the result
3406                      and *NOT* the original pointer which may be
3407                      invalid.
3408 
3409   char** ptr_ref ptr to a ptr to a malloc()'ed string that will receive
3410                      the output
3411                      *ptr_ref will be reallocated if necessary
3412 
3413   size_t* ptr_ref_len ptr to an int holding the current length of ref.
3414                      Will be modified if ref is reallocated.
3415 
3416   struct BIBCONNS* ptr_bibconns ptr to structure with database connections
3417 
3418   dbi_result dbires ptr to a dbi result structure containing the
3419                     current reference
3420 
3421   dbi_result dbires_ref ptr to a dbi result structure containing
3422                     the reference style
3423 
3424   const char* username ptr to string with the current user
3425 
3426   const char* ns optional namespace prefix
3427 
3428   struct xmlindent* ptr_indent  indentation information
3429 
3430   int n_ref_format requested output format: REFDOCBK, REFDOCBKX, REFTEIX
3431 
3432   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_notes(char ** ptr_ref,size_t * ptr_ref_len,struct BIBCONNS * ptr_bibconns,dbi_result dbires,dbi_result dbires_ref,const char * username,const char * ns,struct xmlindent * ptr_indent,int n_ref_format)3433 char* format_notes(char** ptr_ref, size_t* ptr_ref_len, struct BIBCONNS* ptr_bibconns, dbi_result dbires, dbi_result dbires_ref, const char* username, const char* ns, struct xmlindent* ptr_indent, int n_ref_format) {
3434   int nhave_content = 0;
3435   char *new_ref;
3436   char *item;
3437   char *item_notes;
3438 
3439   item_notes = get_notes_copy(dbires, (char*)username);
3440 
3441   if (item_notes && *item_notes) {
3442     nhave_content = 1;
3443 
3444     item = my_dbi_result_get_string_copy_idx(dbires_ref, NOTESPRECEEDING);
3445     if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* preceeding */
3446       if (sgml_entitize(&item, NULL) == NULL) {
3447 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3448 	free(item);
3449 	free(item_notes);
3450 	return NULL;
3451       }
3452 
3453       if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
3454 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3455 	free(item);
3456 	free(item_notes);
3457 	return NULL;
3458       }
3459       else {
3460 	*ptr_ref = new_ref;
3461       }
3462     }
3463     if (item) {
3464       free(item);
3465     }
3466 
3467     if (n_ref_format == REFTEIX5) {
3468       if (print_elstart_x(ptr_ref, ptr_ref_len, "seg", "type", "notes", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
3469 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3470 	free(item_notes);
3471 	return NULL;
3472       }
3473     }
3474     else {
3475       if (print_elstart_x(ptr_ref, ptr_ref_len, "bibliomset", "role", "notes", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
3476 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3477 	free(item_notes);
3478 	return NULL;
3479       }
3480     }
3481 
3482     if (sgml_entitize(&item_notes, NULL) == NULL) {
3483       LOG_PRINT(LOG_WARNING, get_status_msg(801));
3484       free(item_notes);
3485       return NULL;
3486     }
3487 
3488     if ((new_ref = mstrcat(*ptr_ref, item_notes, ptr_ref_len, 0)) == NULL) {
3489       LOG_PRINT(LOG_WARNING, get_status_msg(801));
3490       free(item_notes);
3491       return NULL;
3492     }
3493     else {
3494       *ptr_ref = new_ref;
3495     }
3496 
3497     if (n_ref_format == REFTEIX5) {
3498       if (print_elend_x(ptr_ref, ptr_ref_len, "seg", ptr_indent, ns) == NULL) {
3499 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3500 	free(item_notes);
3501 	return NULL;
3502       }
3503     }
3504     else {
3505       if (print_elend_x(ptr_ref, ptr_ref_len, "bibliomset", ptr_indent, ns) == NULL) {
3506 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3507 	free(item_notes);
3508 	return NULL;
3509       }
3510     }
3511 
3512     item = my_dbi_result_get_string_copy_idx(dbires_ref, NOTESFOLLOWING);
3513     if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) { /* following */
3514       if (sgml_entitize(&item, NULL) == NULL) {
3515 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3516 	free(item);
3517 	free(item_notes);
3518 	return NULL;
3519       }
3520 
3521       if ((new_ref = mstrcat(*ptr_ref, item, ptr_ref_len, 0)) == NULL) {
3522 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3523 	free(item);
3524 	free(item_notes);
3525 	return NULL;
3526       }
3527       else {
3528 	*ptr_ref = new_ref;
3529       }
3530     }
3531     if (item) {
3532       free(item);
3533     }
3534   }
3535 
3536   if (item_notes) {
3537     free(item_notes);
3538   }
3539 
3540   if (!nhave_content) {
3541     (*ptr_ref)[0] = '\0';
3542   }
3543   return *ptr_ref;
3544 }
3545 
3546 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3547   format_separator(): formats the separator part of a bibliography entry
3548                       as a DocBook bibliomixed text
3549 
3550   char* format_separator returns NULL on error, ptr to ref if ok. ref may
3551                      be reallocated during the rendering, so it is
3552                      essential that upon return of this function *ONLY*
3553                      the returned pointer is used to address the result
3554                      and *NOT* the original pointer which may be
3555                      invalid.
3556 
3557   char* ref ptr to an malloc()'ed string that will receive the output
3558                      ref will be reallocated if necessary
3559 
3560   size_t* ptr_ref_len ptr to an int holding the current length of ref.
3561                      Will be modified if ref is reallocated.
3562 
3563   struct BIBCONNS* ptr_bibconns ptr to structure with database connections
3564 
3565   unsigned int separator_id  the ID of the separator
3566 
3567   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_separator(char * ref,size_t * ptr_ref_len,struct BIBCONNS * ptr_bibconns,unsigned int n_separator_id)3568 char* format_separator(char* ref, size_t* ptr_ref_len, struct BIBCONNS* ptr_bibconns, unsigned int n_separator_id) {
3569   int nhave_content = 0;
3570   char *new_ref;
3571   char *item;
3572   const char* drivername;
3573   char sql_command[256];
3574   dbi_result dbires_sep;
3575 
3576 
3577   drivername = dbi_driver_get_name(dbi_conn_get_driver(ptr_bibconns->conn_refdb));
3578 
3579   if (!strcmp(my_dbi_conn_get_cap(ptr_bibconns->conn_refdb, "multiple_db"), "t")) {
3580     sprintf(sql_command, "SELECT VALUE from %s.SEPARATORS where ID=%u", main_db, n_separator_id);
3581   }
3582   else {
3583     sprintf(sql_command, "SELECT VALUE from SEPARATORS where ID=%u", n_separator_id);
3584   }
3585 
3586   LOG_PRINT(LOG_DEBUG, sql_command);
3587   dbires_sep = dbi_conn_query(ptr_bibconns->conn_refdb, sql_command);
3588   if (!dbires_sep) {
3589     LOG_PRINT(LOG_WARNING, "SEPARATORS select failed");
3590     return NULL;
3591   }
3592 
3593   if (dbi_result_next_row(dbires_sep) == 0) {
3594     LOG_PRINT(LOG_WARNING, "SEPARATORS select failed");
3595     dbi_result_free(dbires_sep);
3596     return NULL;
3597   }
3598 
3599   item = my_dbi_result_get_string_copy(dbires_sep, "VALUE");
3600 
3601   if (item && *item && !dbi_conn_error_flag(ptr_bibconns->conn_refdb)) {
3602     nhave_content = 1;
3603 
3604     if (sgml_entitize(&item, NULL) == NULL) {
3605       LOG_PRINT(LOG_WARNING, get_status_msg(801));
3606       free(item);
3607       dbi_result_free(dbires_sep);
3608       return NULL;
3609     }
3610     if ((new_ref = mstrcat(ref, item, ptr_ref_len, 0)) == NULL) {
3611       LOG_PRINT(LOG_WARNING, get_status_msg(801));
3612       dbi_result_free(dbires_sep);
3613       free(item);
3614       return NULL;
3615     }
3616     else {
3617       ref = new_ref;
3618     }
3619   }
3620   if (item) {
3621     free(item);
3622   }
3623 
3624   dbi_result_free(dbires_sep);
3625 /*    printf("end separators\n"); */
3626   if (!nhave_content) {
3627     ref[0] = '\0';
3628   }
3629   return ref;
3630 }
3631 
3632 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3633   format_year(): formats the year part of a pubdate in a bibliography
3634                      entry
3635 
3636   static char* format_year returns NULL on error, ptr to ref if ok. ref may
3637                      be reallocated during the rendering, so it is
3638                      essential that upon return of this function *ONLY*
3639                      the returned pointer is used to address the result
3640                      and *NOT* the original pointer which may be
3641                      invalid.
3642 
3643   char* ref ptr to an malloc()'ed string that will receive the output
3644                      ref will be reallocated if necessary
3645 
3646   size_t* ptr_ref_len ptr to an int holding the current length of ref.
3647                      Will be modified if ref is reallocated.
3648 
3649   unsigned short n_year  the publication year
3650 
3651   const char* yearformat ptr to a string containing the formatting info
3652 
3653   const char* pad ptr to a string containing the padding info
3654 
3655   const char* unique_suffix ptr to a string which makes the year unique
3656 
3657   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_year(char * ref,size_t * ptr_ref_len,unsigned short n_year,const char * yearformat,const char * pad,const char * unique_suffix)3658 static char* format_year(char* ref, size_t* ptr_ref_len, unsigned short n_year, const char* yearformat, const char* pad, const char* unique_suffix) {
3659   char* new_ref;
3660   char the_year[32] = "";
3661   char year_string[32];
3662 
3663 /*    printf("in format_year: year=%s; unique_suffix=%s<<\n", year, unique_suffix); */
3664 /*    fflush(stdout); */
3665 
3666   sprintf(year_string, "%d", n_year);
3667 
3668   if (yearformat && strcmp(yearformat, "FOURDIGIT") == 0) {
3669     if (strcmp(pad, "YY") == 0) {
3670       /* yes I know there will be a Y10k problem... */
3671       strcpy(the_year, "0000");
3672       strcpy(the_year+(4-strlen(year_string)), year_string);
3673     }
3674     else {
3675       strcpy(the_year, year_string);
3676     }
3677   }
3678   else if (yearformat && strcmp(yearformat, "TWODIGIT") == 0) {
3679     if (strcmp(pad, "YY") == 0) {
3680       if (strlen(year_string) == 1) {
3681 	strcpy(the_year, "00");
3682 	strcpy(the_year+1, year_string);
3683       }
3684       else {
3685 	/* take only last two digits */
3686 	strncpy(the_year, year_string+strlen(year_string)-2, 2);
3687 	the_year[2] = '\0';
3688       }
3689     }
3690     else {
3691       if (strlen(year_string) == 1) {
3692 	strcpy(the_year, year_string);
3693       }
3694       else {
3695 	/* take only last two digits */
3696 	strncpy(the_year, year_string+strlen(year_string)-2, 2);
3697 	the_year[2] = '\0';
3698       }
3699     }
3700   }
3701 
3702   else if (yearformat && strcmp(yearformat, "ROMANYEAR") == 0) {
3703     arabic_to_roman(the_year, year_string);
3704   }
3705 
3706   if (unique_suffix && *unique_suffix) {
3707     strcat(the_year, unique_suffix);
3708   }
3709 
3710   if ((new_ref = mstrcat(ref, the_year, ptr_ref_len, 0)) == NULL) {
3711     return NULL;
3712   }
3713   else {
3714     ref = new_ref;
3715   }
3716 /*    printf("done with format_year. ref=%s<<\n", ref); */
3717   return ref;
3718 }
3719 
3720 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3721   format_month(): formats the month part of a pubdate in a bibliography
3722                      entry
3723 
3724   staticchar* format_month returns NULL on error, ptr to ref if ok. ref may
3725                      be reallocated during the rendering, so it is
3726                      essential that upon return of this function *ONLY*
3727                      the returned pointer is used to address the result
3728                      and *NOT* the original pointer which may be
3729                      invalid.
3730 
3731   char* ref ptr to an malloc()'ed string that will receive the output
3732                      ref will be reallocated if necessary
3733 
3734   size_t* ptr_ref_len ptr to an int holding the current length of ref.
3735                      Will be modified if ref is reallocated.
3736 
3737   const char* month ptr to a string containing the RIS PY /MM/DD/otherinfo part
3738 
3739   const char* monthformat ptr to a string containing the formatting info
3740 
3741   const char* pad ptr to a string containing the padding info
3742 
3743   dbi_result dbires_cit ptr to a dbi result structure containing
3744                     the citation style
3745 
3746   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_month(char * ref,size_t * ptr_ref_len,const char * month,const char * monthformat,const char * pad,dbi_result dbires_cit)3747 static char* format_month(char* ref, size_t* ptr_ref_len, const char* month, const char* monthformat, const char* pad, dbi_result dbires_cit) {
3748   char* slash;
3749   char* new_ref;
3750   char* monthstring;
3751   const char* item_full;
3752   const char* item_abbrev;
3753   const char* item_threelet;
3754   dbi_conn conn;
3755   char the_month[3];
3756   char fullmonth[12][9] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
3757   char threelettermonth[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
3758   /* ToDo: dunno if the following abbreviations are correct */
3759   char abbrevmonth[12][6] = {"Jan.", "Feb.", "March", "April", "May", "June", "July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec."};
3760   char romanmonth[12][10] = {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII"};
3761   int i = 0;
3762   int month_len;
3763   int n_month;
3764   char* slashes[3] = {NULL, NULL, NULL}; /* only the first three slashes are relevant, if at all */
3765 
3766   conn = dbi_result_get_conn(dbires_cit);
3767 
3768   slash = strchr(month, (int)'/');
3769 
3770   /* fill the slashes array with up to three slashes. Only the first three may be relevant, as the others would be part of the otherinfo string */
3771   while (slash != NULL && i < 3) {
3772     slashes[i] = slash;
3773     i++;
3774     if (*(slash+1)) {
3775       slash = strchr(slash+1, (int)'/');
3776     }
3777     else {
3778       break;
3779     }
3780   }
3781 
3782   /* we need at least two slashes to extract the month. This can be a one- or two-digit number. If its longer or shorter, we can't safely handle it */
3783   if (slashes[0] && slashes[1]) {
3784     month_len = slashes[1] - slashes[0];
3785     if (month_len == 2) {
3786       if (strcmp(pad, "YY") == 0) {
3787 	the_month[0] = '0';
3788 	the_month[1] = *(slashes[0]+1);
3789 	the_month[2] = '\0';
3790       }
3791       else {
3792 	the_month[0] = *(slashes[0]+1);
3793 	the_month[1] = '\0';
3794       }
3795     }
3796     else if (month_len == 3 && *(slashes[0]+1) == '0' && strcmp(pad, "NN") == 0) {
3797       the_month[0] = *(slashes[0]+2);
3798       the_month[1] = '\0';
3799     }
3800     else if (month_len == 3) {
3801       strncpy(the_month, slashes[0]+1, 2);
3802       the_month[2] = '\0';
3803     }
3804     else { /* month was not existent or improperly formatted */
3805       return ref;
3806     }
3807 
3808     /* sanity test */
3809     n_month = atoi(the_month);
3810     if (n_month < 1 || n_month > 12) {
3811       return ref;
3812     }
3813 
3814     item_full = dbi_result_get_string_idx(dbires_cit, n_month + JANFULL - 1);
3815     if (item_full && dbi_conn_error_flag(conn)) {
3816       item_full = NULL;
3817     }
3818     item_abbrev = dbi_result_get_string_idx(dbires_cit, n_month + JANABBREV - 1);
3819     if (item_abbrev && dbi_conn_error_flag(conn)) {
3820       item_abbrev = NULL;
3821     }
3822     item_threelet = dbi_result_get_string_idx(dbires_cit, n_month + JANTHREELET - 1);
3823     if (item_threelet && dbi_conn_error_flag(conn)) {
3824       item_threelet = NULL;
3825     }
3826 
3827     /* do the actual formatting */
3828     /* ptr_cit_row points to the result of a query for citstyle stuff */
3829     if (strcmp(monthformat, "FULL") == 0) {
3830       monthstring = (item_full && *item_full) ? (char*)item_full : fullmonth[n_month-1];
3831       if ((new_ref = mstrcat(ref, monthstring, ptr_ref_len, 0)) == NULL) {
3832 	return NULL;
3833       }
3834       else {
3835 	ref = new_ref;
3836       }
3837     }
3838     else if (strcmp(monthformat, "ABBREVDOT") == 0) {
3839       monthstring = (item_abbrev && *item_abbrev) ? (char*)item_abbrev : abbrevmonth[n_month-1];
3840       if ((new_ref = mstrcat(ref, monthstring, ptr_ref_len, 0)) == NULL) {
3841 	return NULL;
3842       }
3843       else {
3844 	ref = new_ref;
3845       }
3846     }
3847     else if (strcmp(monthformat, "THREELETTER") == 0) {
3848       monthstring = (item_threelet && *item_threelet) ? (char*)item_threelet : threelettermonth[n_month-1];
3849       if ((new_ref = mstrcat(ref, monthstring, ptr_ref_len, 0)) == NULL) {
3850 	return NULL;
3851       }
3852       else {
3853 	ref = new_ref;
3854       }
3855     }
3856     else if (strcmp(monthformat, "ARABICMONTH") == 0) {
3857       if ((new_ref = mstrcat(ref, the_month, ptr_ref_len, 0)) == NULL) {
3858 	return NULL;
3859       }
3860       else {
3861 	ref = new_ref;
3862       }
3863     }
3864     else if (strcmp(monthformat, "ROMANMONTH") == 0) {
3865       if ((new_ref = mstrcat(ref, romanmonth[n_month-1], ptr_ref_len, 0)) == NULL) {
3866 	return NULL;
3867       }
3868       else {
3869 	ref = new_ref;
3870       }
3871     }
3872   }
3873 
3874   return ref;
3875 }
3876 
3877 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3878   format_day(): formats the day part of a pubdate in a bibliography
3879                      entry
3880 
3881   static char* format_day returns NULL on error, ptr to ref if ok. ref may
3882                      be reallocated during the rendering, so it is
3883                      essential that upon return of this function *ONLY*
3884                      the returned pointer is used to address the result
3885                      and *NOT* the original pointer which may be
3886                      invalid.
3887 
3888   char* ref ptr to an malloc()'ed string that will receive the output
3889                      ref will be reallocated if necessary
3890 
3891   size_t* ptr_ref_len ptr to an int holding the current length of ref.
3892                      Will be modified if ref is reallocated.
3893 
3894   const char* day ptr to a string containing the RIS PY /MM/DD/otherinfo part
3895 
3896   const char* dayformat ptr to a string containing the formatting info
3897 
3898   const char* pad ptr to a string containing the padding info
3899 
3900   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_day(char * ref,size_t * ptr_ref_len,const char * day,const char * dayformat,const char * pad)3901 static char* format_day(char* ref, size_t* ptr_ref_len, const char* day, const char* dayformat, const char* pad) {
3902   char* slash;
3903   char* new_ref;
3904   char the_day[3];
3905   char romanday[31][7] = {"i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix", "x", "xi", "xii", "xiii", "xiv", "xv", "xvi", "xvii", "xviii", "xix", "xx", "xxi", "xxii", "xxiii", "xxiv", "xxv", "xxvi", "xxvii", "xxviii", "xxix", "xxx", "xxxi"};
3906   char* slashes[3] = {NULL, NULL, NULL}; /* only the first three slashes are relevant, if at all */
3907   int i = 0;
3908   int day_len;
3909   int n_day;
3910 
3911   slash = strchr(day, (int)'/');
3912 
3913   /* fill the slashes array with up to three slashes. Only the first three may be relevant, as the others would be part of the otherinfo string */
3914   while (slash != NULL && i < 3) {
3915     slashes[i] = slash;
3916     i++;
3917     if (*(slash+1)) {
3918       slash = strchr(slash+1, (int)'/');
3919     }
3920     else {
3921       break;
3922     }
3923   }
3924 
3925   /* for the day we need the second and third slash. Between them may be a one- or two-digit number. Anything smaller or larger cannot be formatted safely */
3926   if (slashes[1] && slashes[2]) {
3927     day_len = slashes[2] - slashes[1];
3928     if (day_len == 2) {
3929       if (strcmp(pad, "YY") == 0) {
3930 	the_day[0] = '0';
3931 	the_day[1] = *(slashes[1]+1);
3932 	the_day[2] = '\0';
3933       }
3934       else {
3935 	the_day[0] = *(slashes[1]+1);
3936 	the_day[1] = '\0';
3937       }
3938     }
3939     else if (day_len == 3 && *(slashes[1]+1) == '0' && strcmp(pad, "NN") == 0) {
3940       the_day[0] = *(slashes[1]+2);
3941       the_day[1] = '\0';
3942     }
3943     else if (day_len == 3) {
3944       strncpy(the_day, slashes[1]+1, 2);
3945       the_day[2] = '\0';
3946     }
3947     else { /* day was not existent or improperly formatted */
3948       return ref;
3949     }
3950 
3951     /* sanity test */
3952     n_day = atoi(the_day);
3953     if (n_day < 1 || n_day > 31) {
3954       return ref;
3955     }
3956 
3957     /* do the actual formatting */
3958     if (strcmp(dayformat, "ARABICDAY") == 0) {
3959       if ((new_ref = mstrcat(ref, the_day, ptr_ref_len, 0)) == NULL) {
3960 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3961 	return NULL;
3962       }
3963       else {
3964 	ref = new_ref;
3965       }
3966     }
3967     else if (strcmp(dayformat, "ROMANDAY") == 0) {
3968       if ((new_ref = mstrcat(ref, romanday[n_day-1], ptr_ref_len, 0)) == NULL) {
3969 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
3970 	return NULL;
3971       }
3972       else {
3973 	ref = new_ref;
3974       }
3975     }
3976   }
3977 
3978   return ref;
3979 }
3980 
3981 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3982   arabic_to_roman(): converts an arabic number between 0 and 3999 (incl)
3983                      to a roman numeral
3984 
3985   static char* arabic_to_roman returns the result string (roman)
3986 
3987   char* roman ptr to a buffer which receives the roman output. The
3988                      buffer must hold at least 16 chars (incl. '\0')
3989 
3990   const char* arabic ptr to a buffer containing the arabic number to convert
3991 
3992   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
arabic_to_roman(char * roman,const char * arabic)3993 static char* arabic_to_roman(char* roman, const char* arabic) {
3994   int len;
3995   char romandigit[4][3][2] = {
3996     {{'I', '\0'}, {'V', '\0'}, {'X', '\0'}},
3997     {{'X', '\0'}, {'L', '\0'}, {'C', '\0'}},
3998     {{'C', '\0'}, {'D', '\0'}, {'M', '\0'}},
3999     {{'M', '\0'}, {'\0', '\0'}, {'\0', '\0'}}
4000   };
4001 
4002   /* start with a clean string */
4003   *roman = '\0';
4004 
4005   /* give up if the number cannot be nicely formatted */
4006   if (atoi(arabic) >= 4000) {
4007     return roman;
4008   }
4009 
4010   /* the romandigit array contains 4 sets of strings for the values of 1, 5, and 10 times 1, 10, 100, and 1000. We simply walk through the arabic string from left to right (i.e. 1000s, 100s, 10s, 1s) and assemble the roman string by translating the digit into a series of roman digits, following the usual subtraction and addition rules. The algorithm silently discards all non-numeric characters including minus signs */
4011   /* a good source for the rules for roman numerals can be found at: */
4012   /* http://netdirect.net/~charta/Roman_numerals.html */
4013   while((len = strlen(arabic)) > 0) {
4014     switch (*arabic) {
4015     case '1':
4016       strcat(roman, romandigit[len-1][0]);
4017       break;
4018     case '2':
4019       strcat(roman, romandigit[len-1][0]);
4020       strcat(roman, romandigit[len-1][0]);
4021       break;
4022     case '3':
4023       strcat(roman, romandigit[len-1][0]);
4024       strcat(roman, romandigit[len-1][0]);
4025       strcat(roman, romandigit[len-1][0]);
4026       break;
4027     case '4':
4028       strcat(roman, romandigit[len-1][0]);
4029       strcat(roman, romandigit[len-1][1]);
4030       break;
4031     case '5':
4032       strcat(roman, romandigit[len-1][1]);
4033       break;
4034     case '6':
4035       strcat(roman, romandigit[len-1][1]);
4036       strcat(roman, romandigit[len-1][0]);
4037       break;
4038     case '7':
4039       strcat(roman, romandigit[len-1][1]);
4040       strcat(roman, romandigit[len-1][0]);
4041       strcat(roman, romandigit[len-1][0]);
4042       break;
4043     case '8':
4044       strcat(roman, romandigit[len-1][1]);
4045       strcat(roman, romandigit[len-1][0]);
4046       strcat(roman, romandigit[len-1][0]);
4047       strcat(roman, romandigit[len-1][0]);
4048       break;
4049     case '9':
4050       strcat(roman, romandigit[len-1][0]);
4051       strcat(roman, romandigit[len-1][2]);
4052       break;
4053     }
4054     arabic++;
4055   }
4056   return roman;
4057 }
4058 
4059 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4060   normalize_pages(): formats endpage according to the format spec
4061 
4062   static char* normalize_pages returns the normalized endpage string
4063 
4064   char* new_endpage ptr to a buffer large enough to receive the
4065             modified endpage. Should hold at least 256 chars (incl \0)
4066 
4067   const char* startpage ptr to a buffer containing the startpage
4068 
4069   const char* endpage ptr to a buffer containing the original endpage
4070 
4071   const char* format ptr to a buffer containing the formatting instructions
4072 
4073   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
normalize_pages(char * new_endpage,const char * startpage,const char * endpage,const char * format)4074 static char* normalize_pages(char* new_endpage, const char* startpage, const char* endpage, const char* format) {
4075   int n_startpage;
4076   int n_endpage;
4077   int n_testpage;
4078   int i;
4079   char my_startpage[256];
4080   char my_endpage[256];
4081   char startpage_leading_slack[256];
4082   char endpage_leading_slack[256];
4083   char endpage_trailing_slack[256];
4084   char* ptr_start_start;
4085   char* ptr_end_start;
4086   char* ptr_start;
4087   char* ptr_end;
4088   char* ptr_end_end;
4089 
4090   if (!startpage || !endpage) {
4091     return NULL;
4092   }
4093 
4094   /* ToDo: this algorithm currently drops all non-numeric information in the page strings. This is not good for e.g. Am.J.Physiol. which uses the page numbers to denote the subdivision (e.g. H1223 for a paper in the heart and circulation section). The algorithm should be extended to leave those non-numeric parts alone */
4095 
4096   ptr_start_start = strpbrk(startpage, "123456789");
4097   ptr_end_start = strpbrk(endpage, "123456789");
4098 
4099   /* if the strings don't contain numbers, we just leave them as they are */
4100   if (!ptr_start_start || !ptr_end_start) {
4101     return (char*)endpage;
4102   }
4103 
4104   strncpy(startpage_leading_slack, startpage, ptr_start_start - startpage);
4105   startpage_leading_slack[ptr_start_start - startpage] = '\0';
4106 
4107   strncpy(endpage_leading_slack, endpage, ptr_end_start - endpage);
4108   endpage_leading_slack[ptr_end_start - endpage] = '\0';
4109 
4110   /* find the end of the number in the string */
4111   i = 0;
4112   while (ptr_end_start[i] != '\0' && isdigit((int)ptr_end_start[i])) {
4113     i++;
4114   }
4115 
4116   strcpy(endpage_trailing_slack, &ptr_end_start[i]); /* may be empty string */
4117 
4118   /* atoi and then sprintf removes any trailing slack */
4119   n_startpage = atoi(ptr_start_start);
4120   if (n_startpage < 0) {
4121     return (char*)endpage; /* don't even try any formatting here */
4122   }
4123   else {
4124     sprintf(my_startpage, "%d", n_startpage);
4125   }
4126 
4127   n_endpage = atoi(ptr_end_start);
4128   if (n_endpage < 0) {
4129     return (char*)endpage; /* don't try any formatting here */
4130   }
4131   else {
4132     sprintf(my_endpage, "%d", n_endpage);
4133   }
4134 
4135   /* if the endpage is not fully qualified (i.e. the numeric value is smaller than the value of startpage), we have to expand it. We simply use the cropped startpage string as a template and overwrite whatever part is specified in the cropped endpage string*/
4136   if (n_startpage > n_endpage) {
4137     strcpy(new_endpage, my_startpage);
4138     strcpy(new_endpage+strlen(my_startpage)-strlen(my_endpage), my_endpage);
4139     n_endpage = atoi(new_endpage);
4140 
4141     /* now we have to correct the endpage string if e.g. start=99, end=3. So far we get 93 which is dead wrong. We need 103 instead */
4142     n_testpage = n_endpage;
4143     i = 10;
4144 
4145     while (n_startpage > n_testpage) {
4146       n_testpage = n_endpage + i;
4147       i *= 10;
4148     }
4149     n_endpage = n_testpage;
4150     sprintf(new_endpage, "%d", n_endpage);
4151   }
4152   else {
4153     strcpy(new_endpage, my_endpage);
4154   }
4155 
4156   /* if either the startpage or the endpage contained leading slack, we have to add it back here */
4157   if (*endpage_leading_slack) {
4158     strcat(endpage_leading_slack, new_endpage);
4159     strcpy(new_endpage, endpage_leading_slack);
4160   }
4161   else if (*startpage_leading_slack) {
4162     strcat(startpage_leading_slack, new_endpage);
4163     strcpy(new_endpage, startpage_leading_slack);
4164   }
4165 
4166   /* try abbreviating numbers only if there is no leading slack. In the latter case we always use the full format */
4167   if (!(*endpage_leading_slack || *startpage_leading_slack)) {
4168     /* this format uses the minimum number of digits necessary to unambiguously denote the endpage */
4169     if (format && strcmp(format, "ABBREV") == 0) {
4170       strcpy(my_endpage, new_endpage);
4171       ptr_start = my_startpage;
4172       ptr_end = my_endpage;
4173 
4174       /* walk from left to right through startpage and expanded endpage until the digits differ */
4175       while (*ptr_end != '\0') {
4176 	if (*ptr_start != *ptr_end) {
4177 	  break;
4178 	}
4179 	ptr_start++;
4180 	ptr_end++;
4181       }
4182       strcpy(new_endpage, ptr_end);
4183     }
4184 
4185     /* this format uses one (1-9) or two digits (> 10) or at least two digits (> 100) to render the endpage */
4186     else if (format && strcmp(format, "TWODIGIT") == 0) {
4187       if (strlen(new_endpage) > 2) {
4188 	strcpy(my_endpage, new_endpage);
4189 	ptr_start = my_startpage;
4190 	ptr_end = my_endpage;
4191 	ptr_end_end = my_endpage + strlen(my_endpage);
4192 
4193 	/* take as many digits as are different between start and end, but take at least two digits */
4194 	while (ptr_end_end - ptr_end > 2) {
4195 	  if (*ptr_start != *ptr_end) {
4196 	    break;
4197 	  }
4198 	  ptr_start++;
4199 	  ptr_end++;
4200 	}
4201 
4202 	strcpy(new_endpage, ptr_end);
4203       }
4204       /* else: one or two-digit string is still in new_endpage, needs no modification */
4205     }
4206 
4207     /* ToDo: this format appears odd to me and needs some more research to find out about the rules. A brief web search made me feel it is best to use full citation style here. Only Reference Manager claims that Chicago style is different from full, but the examples given are inconsistent. */
4208     /*    else if (format && strcmp(format, "CHICAGO") == 0) { */
4209     /*    } */
4210 
4211     /* full means the endpage is rendered with at least as many digits as the startpage, nothing gets abbreviated. Nothing to do, expanded endpage is still in new_endpage */
4212     /*    if (format && strcmp(format, "FULL") == 0) { */
4213     /*    } */
4214   }
4215   /* else: with leading slack, assume "FULL" which means nothing to do */
4216 
4217   return strcat(new_endpage, endpage_trailing_slack);
4218 }
4219 
4220 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4221   format_authorname(): converts a RIS author into a sequence of DocBook
4222                   or TEI elements
4223 
4224   static int format_authorname returns 0 if successful, >0 if failed
4225 
4226   char** ptr_ref ptr to a ptr to a buffer created with malloc which will receive
4227         the output. The calling function must allocate the buffer
4228         with at least one byte. This function will reallocate the
4229         buffer as needed. *ptr will be updated whenever a realloc is
4230         necessary. The calling function is responsible for freeing the
4231         memory again.
4232 
4233   size_t* ptr_ref_len ptr to an int containing the allocated length of res
4234                    will be updated accordingly if ref is reallocated
4235 
4236   const AUTHOR_INFO* ptr_ainfo ptr to struct with author name parts
4237 
4238   const char* authorsep ptr to a buffer containing the separator that
4239                    should appear right before the current author
4240 
4241   const char* nameorder ptr to a string containing the name order info
4242 
4243   const char* initialstyle ptr to a string containing the initials style
4244 
4245   const char* author_upper ptr to a string containing the upper/lowercase
4246                    info
4247 
4248   const char* author_preceeding ptr to a string containing a string to be
4249                    printed in front of the author name
4250 
4251   const char* author_following ptr to a string containing a string to be
4252                    printed after the author name
4253 
4254   int nis_intext 1 if we format an in-text citation; 0 if bibliography
4255 
4256   int type 1=part author 2=publication author 3=series author 4=first available
4257            0=all
4258 
4259   const char* ns optional namespace prefix
4260 
4261   struct xmlindent* ptr_indent  indentation information
4262 
4263   int n_ref_format requested output format: REFDOCBK, REFDOCBKX, REFTEIX
4264 
4265  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_authorname(char ** ptr_ref,size_t * ptr_ref_len,struct AUTHOR_INFO * ptr_ainfo,const char * authorsep,const char * nameorder,const char * initialstyle,const char * author_upper,const char * author_preceeding,const char * author_following,int nis_intext,int type,const char * ns,struct xmlindent * ptr_indent,int n_ref_format)4266 static int format_authorname(char** ptr_ref, size_t* ptr_ref_len, struct AUTHOR_INFO* ptr_ainfo, const char* authorsep, const char* nameorder, const char* initialstyle, const char* author_upper, const char* author_preceeding, const char* author_following, int nis_intext, int type, const char* ns, struct xmlindent* ptr_indent, int n_ref_format) {
4267   char elname[16];
4268   char attname[16];
4269   char attvalue[16];
4270   char* new_ref;
4271   char* entitize_buf; /* buffer for replacing &<> with sgml entities */
4272 
4273 /*    printf("in format_authorname; author:%s; authorsep:%s; nameorder:%s; initialstyle:%s; author_upper:%s; author_preceeding:%s; author_following:%s; nis_intext:%d<<\n", author, authorsep, nameorder, initialstyle, author_upper, author_preceeding, author_following, nis_intext); */
4274 
4275   if (!ptr_ainfo) {
4276     return 234;
4277   }
4278 
4279   /* assemble string */
4280   if (authorsep && *authorsep) { /* have separator string */
4281     if ((entitize_buf = mstrdup((char*)authorsep)) == NULL) {
4282       return 801;
4283     }
4284 
4285     if (sgml_entitize(&entitize_buf, NULL) == NULL) {
4286       free(entitize_buf);
4287       return 801;
4288     }
4289 
4290     if ((new_ref = mstrcat(*ptr_ref, entitize_buf, ptr_ref_len, 0)) == NULL) {
4291       free(entitize_buf);
4292       return 801;
4293     }
4294     else {
4295       *ptr_ref = new_ref;
4296     }
4297     free(entitize_buf);
4298   }
4299 
4300   /* set wrapper element and attribute */
4301   switch (n_ref_format) {
4302   case REFDOCBKX5:
4303     strcpy(elname, "personname");
4304     strcpy(attname, "role");
4305     break;
4306   case REFTEIX5:
4307     strcpy(elname, "persName");
4308     strcpy(attname, "type");
4309     break;
4310   default:
4311     strcpy(elname, "bibliomset");
4312     strcpy(attname, "relation");
4313     break;
4314   }
4315 
4316   /* wrap bibliomset around the name parts */
4317   switch (type) {
4318   case 1: /* fall through */
4319   case 4:
4320     if (print_elstart_x(ptr_ref, ptr_ref_len, elname, attname, "author", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
4321       return 801;
4322     }
4323     break;
4324   case 2:
4325     if (print_elstart_x(ptr_ref, ptr_ref_len, elname, attname, "editor", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
4326       return 801;
4327     }
4328     break;
4329   case 3:
4330     if (print_elstart_x(ptr_ref, ptr_ref_len, elname, attname, "seditor", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
4331       return 801;
4332     }
4333     break;
4334   default:
4335     break;
4336   }
4337 
4338   if (nameorder && strcmp(nameorder, "FIRSTMIDDLELAST") == 0) {
4339     if ((new_ref = format_firstmiddlename(ptr_ref, ptr_ref_len, ptr_ainfo, author_upper, initialstyle, nis_intext, type, ns, ptr_indent, n_ref_format)) == NULL) {
4340       return 801;
4341     }
4342     else {
4343       *ptr_ref = new_ref;
4344     }
4345 
4346     if ((*(ptr_ainfo->firstname) || *(ptr_ainfo->middlename)) && (*(ptr_ainfo->lastname) || *(ptr_ainfo->name))) {
4347       if ((new_ref = mstrcat(*ptr_ref, " ", ptr_ref_len, 0)) == NULL) {
4348 	return 801;
4349       }
4350       else {
4351 	*ptr_ref = new_ref;
4352       }
4353     }
4354 
4355     if ((new_ref = format_lastname(ptr_ref, ptr_ref_len, *(ptr_ainfo->lastname) ? ptr_ainfo->lastname : ptr_ainfo->name, author_upper, nis_intext, type, ns, ptr_indent)) == NULL) {
4356       return 801;
4357     }
4358     else {
4359       *ptr_ref = new_ref;
4360     }
4361   }
4362   else if (nameorder && (strcmp(nameorder, "LASTCOMMAFIRSTMIDDLE") == 0
4363 			 || strcmp(nameorder, "LASTCOMMASPCFIRSTMIDDLE") == 0)) {
4364     char sep[3];
4365 
4366     /* quick and dirty strcmp */
4367     if (nameorder[9] == 'F') {
4368       strcpy(sep, ",");
4369     }
4370     else {
4371       strcpy(sep, ", ");
4372     }
4373 
4374     if ((new_ref = format_lastname(ptr_ref, ptr_ref_len, *(ptr_ainfo->lastname) ? ptr_ainfo->lastname : ptr_ainfo->name, author_upper, nis_intext, type, ns, ptr_indent)) == NULL) {
4375       return 801;
4376     }
4377     else {
4378       *ptr_ref = new_ref;
4379     }
4380 
4381     if ((*(ptr_ainfo->lastname) || *(ptr_ainfo->name)) && (*(ptr_ainfo->firstname) || *ptr_ainfo->middlename)) {
4382       if ((new_ref = mstrcat(*ptr_ref, sep, ptr_ref_len, 0)) == NULL) {
4383 	return 801;
4384       }
4385       else {
4386 	*ptr_ref = new_ref;
4387       }
4388     }
4389 
4390     if ((new_ref = format_firstmiddlename(ptr_ref, ptr_ref_len, ptr_ainfo, author_upper, initialstyle, nis_intext, type, ns, ptr_indent, n_ref_format)) == NULL) {
4391       return 801;
4392     }
4393     else {
4394       *ptr_ref = new_ref;
4395     }
4396   }
4397   else if (nameorder && strcmp(nameorder, "LASTFIRSTMIDDLE") == 0) {
4398     if ((new_ref = format_lastname(ptr_ref, ptr_ref_len, *(ptr_ainfo->lastname) ? ptr_ainfo->lastname : ptr_ainfo->name, author_upper, nis_intext, type, ns, ptr_indent)) == NULL) {
4399       return 801;
4400     }
4401     else {
4402       *ptr_ref = new_ref;
4403     }
4404 
4405     if ((*(ptr_ainfo->lastname) || *(ptr_ainfo->name)) && (*(ptr_ainfo->firstname) || *(ptr_ainfo->middlename))) {
4406       if ((new_ref = mstrcat(*ptr_ref, " ", ptr_ref_len, 0)) == NULL) {
4407 	return 801;
4408       }
4409       else {
4410 	*ptr_ref = new_ref;
4411       }
4412     }
4413 
4414     if ((new_ref = format_firstmiddlename(ptr_ref, ptr_ref_len, ptr_ainfo, author_upper, initialstyle, nis_intext, type, ns, ptr_indent, n_ref_format)) == NULL) {
4415       return 801;
4416     }
4417     else {
4418       *ptr_ref = new_ref;
4419     }
4420   }
4421   else if (nameorder && strcmp(nameorder, "LAST") == 0) {
4422     if ((new_ref = format_lastname(ptr_ref, ptr_ref_len, *(ptr_ainfo->lastname) ? ptr_ainfo->lastname : ptr_ainfo->name, author_upper, nis_intext, type, ns, ptr_indent)) == NULL) {
4423       return 801;
4424     }
4425     else {
4426       *ptr_ref = new_ref;
4427     }
4428   }
4429 
4430   if (*(ptr_ainfo->suffix)) {
4431     if ((entitize_buf = mstrdup(ptr_ainfo->suffix)) == NULL) {
4432       return 801;
4433     }
4434 
4435     if (sgml_entitize(&entitize_buf, NULL) == NULL) {
4436       free(entitize_buf);
4437       return 801;
4438     }
4439 
4440     if (n_ref_format == REFTEIX5) {
4441       if (print_element_x(entitize_buf, ptr_ref, ptr_ref_len, "name", "type", "lineage", NULL, NULL, ptr_indent, ns) == NULL) {
4442 	free(entitize_buf);
4443 	return 801;
4444       }
4445     }
4446     else {
4447       if (print_element_x(entitize_buf, ptr_ref, ptr_ref_len, "lineage", NULL, NULL, NULL, NULL, ptr_indent, ns) == NULL) {
4448 	free(entitize_buf);
4449 	return 801;
4450       }
4451     }
4452     free(entitize_buf);
4453   }
4454 
4455   /* end bibliomset wrap around the name parts */
4456   if (print_elend_x(ptr_ref, ptr_ref_len, elname, ptr_indent, ns) == NULL) {
4457     return 801;
4458   }
4459 
4460 /*    printf("done format_authorname\n"); */
4461   return 0;
4462 }
4463 
4464 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4465   format_lastname(): appends a surname as a docbook element to a string
4466 
4467   static char* format_lastname returns a pointer to the modified string
4468 
4469   char* format_lastname returns ptr to the buffer if successful, NULL if failed
4470 
4471   char** ptr_ref ptr to a ptr to a buffer created with malloc which will receive
4472         the output. The calling function must allocate the buffer
4473         with at least one byte. This function will reallocate the
4474         buffer as needed. *ptr will be updated whenever a realloc is
4475         necessary. The calling function is responsible for freeing the
4476         memory again.
4477 
4478   size_t* ptr_ref_len ptr to length of *ptr_ref
4479 
4480   char* lastname ptr to a string containing the lastname
4481 
4482   const char* author_upper ptr to a string containing the upper/lowercase
4483                    information
4484 
4485   int nis_intext 1 if we format an in-text citation; 0 if bibliography
4486 
4487   int type 1=part author 2=publication author 3=series author 4=first
4488            available 0=all
4489 
4490   const char* ns optional namespace prefix
4491 
4492   struct xmlindent* ptr_indent  indentation information
4493 
4494   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_lastname(char ** ptr_ref,size_t * ptr_ref_len,char * lastname,const char * author_upper,int nis_intext,int type,const char * ns,struct xmlindent * ptr_indent)4495 static char* format_lastname(char** ptr_ref, size_t* ptr_ref_len, char* lastname, const char* author_upper, int nis_intext, int type, const char* ns, struct xmlindent* ptr_indent) {
4496   char* entitize_buf; /* buffer for replacing &<> with sgml entities */
4497 
4498   if (lastname && *lastname) {
4499 
4500     if (author_upper && (strcmp(author_upper, "LASTNAME") == 0 || strcmp(author_upper, "ALL") == 0)) {
4501       strup(lastname);
4502     }
4503 
4504     if ((entitize_buf = mstrdup(lastname)) == NULL) {
4505       LOG_PRINT(LOG_WARNING, get_status_msg(801));
4506       return NULL;
4507     }
4508 
4509     if (sgml_entitize(&entitize_buf, NULL) == NULL) {
4510       LOG_PRINT(LOG_WARNING, get_status_msg(801));
4511       free(entitize_buf);
4512       return NULL;
4513     }
4514 
4515     if (print_element_x(entitize_buf, ptr_ref, ptr_ref_len, "surname", NULL, NULL, NULL, NULL, ptr_indent, ns) == NULL) {
4516       LOG_PRINT(LOG_WARNING, get_status_msg(801));
4517       free(entitize_buf);
4518       return NULL;
4519     }
4520   }
4521   return *ptr_ref;
4522 }
4523 
4524 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4525   format_firstmiddlename(): appends a firstname/middlename combo as a
4526                    docbook element to a string
4527 
4528   static char* format_firstmiddlename returns ptr to the buffer if successful, NULL if failed
4529 
4530   char** ptr_ref ptr to a ptr to a buffer created with malloc which will receive
4531         the output. The calling function must allocate the buffer
4532         with at least one byte. This function will reallocate the
4533         buffer as needed. *ptr will be updated whenever a realloc is
4534         necessary. The calling function is responsible for freeing the
4535         memory again.
4536 
4537   size_t* ptr_ref_len ptr to an int containing the allocated length of res
4538                    will be updated accordingly if ref is reallocated
4539 
4540   struct AUTHOR_INFO* ptr_ainfo ptr to struct with name parts
4541 
4542   const char* author_upper ptr to a string containing the upper/lowercase
4543                    information
4544 
4545   const char* initialstyle ptr to a string containing the initial style
4546                    information
4547 
4548   int nis_intext 1 if we format an in-text citation; 0 if bibliography
4549 
4550   int type 1=part author 2=publication author 3=series author 4=first
4551            available 0=all
4552 
4553   const char* ns optional namespace prefix
4554 
4555   struct xmlindent* ptr_indent  indentation information
4556 
4557   int n_ref_format requested output format: REFDOCBK, REFDOCBKX, REFTEIX
4558 
4559   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
format_firstmiddlename(char ** ptr_ref,size_t * ptr_ref_len,struct AUTHOR_INFO * ptr_ainfo,const char * author_upper,const char * initialstyle,int nis_intext,int type,const char * ns,struct xmlindent * ptr_indent,int n_ref_format)4560 static char* format_firstmiddlename(char** ptr_ref, size_t* ptr_ref_len, struct AUTHOR_INFO* ptr_ainfo, const char* author_upper, const char* initialstyle, int nis_intext, int type, const char* ns, struct xmlindent* ptr_indent, int n_ref_format) {
4561   char* new_ref;
4562   char* entitize_buf; /* buffer for replacing &<> with sgml entities */
4563 
4564   if (*(ptr_ainfo->firstname)) {
4565 
4566     if (author_upper && strcmp(author_upper, "ALL") == 0) {
4567       strup(ptr_ainfo->firstname);
4568     }
4569 
4570     if (n_ref_format == REFTEIX5) {
4571       if (print_elstart_x(ptr_ref, ptr_ref_len, "forename", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
4572 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
4573 	return NULL;
4574       }
4575     }
4576     else {
4577       if (print_elstart_x(ptr_ref, ptr_ref_len, "firstname", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
4578 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
4579 	return NULL;
4580       }
4581     }
4582 
4583     if ((entitize_buf = mstrdup(ptr_ainfo->firstname)) == NULL) {
4584       LOG_PRINT(LOG_WARNING, get_status_msg(801));
4585       return NULL;
4586     }
4587 
4588     /* see whether we need the initial or the full name */
4589     if (initialstyle && (strcmp(initialstyle, "F.SPCM.") == 0 ||
4590 			 strcmp(initialstyle, "F.M.") == 0 ||
4591 			 strcmp(initialstyle, "FM") == 0 ||
4592 			 strcmp(initialstyle, "FSPCM") == 0)) {
4593       if (strlen(entitize_buf) > 0) {
4594 	*(entitize_buf + 1) = '\0';
4595       }
4596     }
4597 
4598     if (sgml_entitize(&entitize_buf, NULL) == NULL) {
4599       LOG_PRINT(LOG_WARNING, get_status_msg(801));
4600       free(entitize_buf);
4601       return NULL;
4602     }
4603 
4604     if ((new_ref = mstrcat(*ptr_ref, entitize_buf, ptr_ref_len, 0)) == NULL) {
4605       LOG_PRINT(LOG_WARNING, get_status_msg(801));
4606       free(entitize_buf);
4607       return NULL;
4608     }
4609     else {
4610       *ptr_ref = new_ref;
4611     }
4612     free(entitize_buf);
4613 
4614     if (initialstyle && (strcmp(initialstyle, "F.SPCM.") == 0 ||
4615 			 strcmp(initialstyle, "F.M.") == 0)) {
4616       if ((new_ref = mstrcat(*ptr_ref, ".", ptr_ref_len, 0)) == NULL) {
4617 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
4618 	return NULL;
4619       }
4620       else {
4621 	*ptr_ref = new_ref;
4622       }
4623     }
4624 
4625     if (n_ref_format == REFTEIX5) {
4626       if (print_elend_x(ptr_ref, ptr_ref_len, "forename", ptr_indent, ns) == NULL) {
4627 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
4628 	return NULL;
4629       }
4630     }
4631     else {
4632       if (print_elend_x(ptr_ref, ptr_ref_len, "firstname", ptr_indent, ns) == NULL) {
4633 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
4634 	return NULL;
4635       }
4636     }
4637   }
4638 
4639   if (*(ptr_ainfo->middlename)) {
4640     char* item;
4641 
4642     for (item = strtok(ptr_ainfo->middlename, " "); item; item = strtok(NULL, " ")) {
4643       if (initialstyle && (strcmp(initialstyle, "F.SPCM.") == 0 ||
4644 			   strcmp(initialstyle, "FIRSTSPCMIDDLE") == 0 ||
4645 			   strcmp(initialstyle, "FIRSTSPCM.") == 0 ||
4646 			   strcmp(initialstyle, "FIRSTSPCM") == 0 ||
4647 			   strcmp(initialstyle, "FSPCM") == 0)) {
4648 	if ((new_ref = mstrcat(*ptr_ref, " ", ptr_ref_len, 0)) == NULL) {
4649 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
4650 	  return NULL;
4651 	}
4652 	else {
4653 	  *ptr_ref = new_ref;
4654 	}
4655       }
4656 
4657       if (n_ref_format == REFTEIX5) {
4658 	if (print_elstart_x(ptr_ref, ptr_ref_len, "name", "type", "othername", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
4659 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
4660 	  return NULL;
4661 	}
4662       }
4663       else {
4664 	if (print_elstart_x(ptr_ref, ptr_ref_len, "othername", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0 /* not empty */, ptr_indent, ns) == NULL) {
4665 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
4666 	  return NULL;
4667 	}
4668       }
4669 
4670       if ((entitize_buf = mstrdup(item)) == NULL) {
4671 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
4672 	return NULL;
4673       }
4674 
4675       if (author_upper && strcmp(author_upper, "ALL") == 0) {
4676 	strup(entitize_buf);
4677       }
4678 
4679       /* see whether we need the initial or the full name */
4680       if (initialstyle && (strcmp(initialstyle, "F.SPCM.") == 0 ||
4681 			   strcmp(initialstyle, "F.M.") == 0 ||
4682 			   strcmp(initialstyle, "FM") == 0 ||
4683 			   strcmp(initialstyle, "FIRSTSPCM.") == 0 ||
4684 			   strcmp(initialstyle, "FIRSTSPCM") == 0 ||
4685 			   strcmp(initialstyle, "FSPCM") == 0)) {
4686 	if (strlen(entitize_buf) > 0) {
4687 	  *(entitize_buf + 1) = '\0';
4688 	}
4689       }
4690 
4691       if (sgml_entitize(&entitize_buf, NULL) == NULL) {
4692 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
4693 	free(entitize_buf);
4694 	return NULL;
4695       }
4696 
4697       if ((new_ref = mstrcat(*ptr_ref, entitize_buf, ptr_ref_len, 0)) == NULL) {
4698 	LOG_PRINT(LOG_WARNING, get_status_msg(801));
4699 	free(entitize_buf);
4700 	return NULL;
4701       }
4702       else {
4703 	*ptr_ref = new_ref;
4704       }
4705       free(entitize_buf);
4706 
4707       if (initialstyle && (strcmp(initialstyle, "F.SPCM.") == 0 ||
4708 			   strcmp(initialstyle, "F.M.") == 0 ||
4709 			   strcmp(initialstyle, "FIRSTSPCM.") == 0)) {
4710 	if ((new_ref = mstrcat(*ptr_ref, ".", ptr_ref_len, 0)) == NULL) {
4711 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
4712 	  return NULL;
4713 	}
4714 	else {
4715 	  *ptr_ref = new_ref;
4716 	}
4717       }
4718 
4719       if (n_ref_format == REFTEIX5) {
4720 	if (print_elend_x(ptr_ref, ptr_ref_len, "name", ptr_indent, ns) == NULL) {
4721 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
4722 	  return NULL;
4723 	}
4724       }
4725       else {
4726 	if (print_elend_x(ptr_ref, ptr_ref_len, "othername", ptr_indent, ns) == NULL) {
4727 	  LOG_PRINT(LOG_WARNING, get_status_msg(801));
4728 	  return NULL;
4729 	}
4730       }
4731     } /* end for */
4732   } /* end if have middlename */
4733   return *ptr_ref;
4734 }
4735 
4736