Bioplib
Protein Structure C Library
 All Data Structures Files Functions Variables Typedefs Macros Pages
macros.h
Go to the documentation of this file.
1 /************************************************************************/
2 /**
3 
4  \file macros.h
5 
6  \version V2.26
7  \date 14.12.16
8  \brief Useful macros
9 
10  \copyright (c) Dr. Andrew C.R. Martin / UCL 1991-2016
11  \author Dr. Andrew C. R. Martin
12  \par
13  Institute of Structural & Molecular Biology,
14  University College London,
15  Gower Street,
16  London.
17  WC1E 6BT.
18  \par
19  andrew@bioinf.org.uk
20  andrew.martin@ucl.ac.uk
21 
22 **************************************************************************
23 
24  This code is NOT IN THE PUBLIC DOMAIN, but it may be copied
25  according to the conditions laid out in the accompanying file
26  COPYING.DOC.
27 
28  The code may be modified as required, but any modifications must be
29  documented so that the person responsible can be identified.
30 
31  The code may not be sold commercially or included as part of a
32  commercial product except as described in the file COPYING.DOC.
33 
34 **************************************************************************
35 
36  Description:
37  ============
38 
39  If not Amiga defines abs().
40  Defines max(), min() and PI if not done.
41  Defines list handling macros.
42  Defines newline() and toggle() macros.
43 
44 **************************************************************************
45 
46  Usage:
47  ======
48 
49 **************************************************************************
50 
51  Revision History:
52  =================
53 - V1.0 06.02.91 Original
54 - V1.1 15.02.91 Moved PI definition to non-Amiga's only
55 - V1.2 21.03.91 Added RANGECHECK
56 - V1.3 06.09.91 Added DIST, DISTSQ and Vec3f
57 - V1.4 09.09.91 Fixed multi-command macros with {}
58 - V1.5 24.01.92 Fixed for 32 bit addresses and added malloc checks.
59 - V1.6 03.04.92 Small change to ALLOCNEXT and ALLOCNEXTPREV, so
60  will do a NEXT() even if malloc() fails.
61 - V1.7 06.05.92 Added TERMINATE()
62 - V1.8 06.07.92 Added MAX(), MIN() and ABS()
63 - V1.9 22.07.92 Fixed ABS()
64 - V1.10 28.09.92 Added TRUE & FALSE and UPPER()
65 - V1.11 03.11.92 Changed TOGGLE and newline is now upper case.
66 - V1.12 16.11.92 Added KILLLEADSPACES()
67 - V1.13 18.11.92 Fixed UPPER() for MicrosoftC which returns strlen()
68  as unsigned
69 - V1.14 20.11.92 ABS() now uses 0 rather than 0.0, so we don't
70  try to use floats with ints...
71 - V2.0 24.11.92 Removed all small letter macros
72 - V2.1 12.07.93 Added double include check, moved math definitions
73  to MathType.h and added LOWER()
74 - V2.2 07.10.93 UPPER() and LOWER() check case first for ESV
75  compatibility
76 - V2.3 23.05.94 Added D(BUG)
77 - V2.4 14.07.94 Added do{}while(0) bracketing of all multi-line macros
78 - V2.5 21.11.94 ABS, MAX and MIN check that they're not already defined
79 - V2.6 16.02.95 Added DELETE()
80 - V2.7 21.02.95 Updated some internal variable names
81 - V2.8 02.08.95 Added TESTINARRAY(), FINDINARRAY(),
82  SET(), UNSET() and ISSET()
83 - V2.9 20.11.95 Added TERMAT()
84 - V2.10 06.02.96 Added KILLTRAILSPACES()
85 - V2.11 14.06.96 Added PROMPT()
86 - V2.12 23.07.96 Added PADMINTERM()
87 - V2.13 19.09.96 Include ctype for UPPER() etc
88 - V2.14 13.03.99 Added DELETEDOUBLE()
89 - V2.15 01.03.01 Added DOTIFY() DEDOTIFY() PADCHARMINTERM() SUBSCHAR()
90 - V2.16 25.01.06 Added FINDPREV()
91 - V2.17 10.04.08 Fixed bug in DELETE() - the break was not properly
92  stopping prev from being changed
93 - V2.18 29.04.14 Added DEPRECATED() By: CTP
94 - V2.19 07.05.14 Moved DEPRECATED() to deprecated.h By: CTP
95 - V2.20 07.07.14 Use bl prefix for functions - change padterm() to
96  blPadterm() By: CTP
97 - V2.21 24.07.14 Initialize list pointers for DELETE macro. By: CTP
98 - V2.22 25.02.15 LAST() is now safe if the pointer is NULL
99 - V2.23 26.06.15 Added STRNCPYNOSPACES(out, in, mx)
100 - V2.24 28.08.15 Added FREE()
101 - V2.25 04.11.15 Added FCLOSE()
102 - V2.26 14.12.16 Added TERMINATECR()
103 
104 *************************************************************************/
105 /* Doxygen
106  -------
107  #GROUP General Programming
108  #SUBGROUP Handling linked lists
109 
110  #FUNCTION INIT(x,y)
111  Macro: Initialise list of name x and type y. Set x->next to NULL
112  #FUNCTION INITPREV(x,y)
113  Macro: Initialise list of name x and type y.
114  Set x->next and x->prev to NULL
115  #FUNCTION NEXT(x)
116  Macro: Step on in linked list
117  #FUNCTION PREV(x)
118  Macro: Step back in doubly linked list
119  #FUNCTION ALLOCNEXT(x,y)
120  Macro: Allocate next item in list and step on
121  #FUNCTION ALLOCNEXTPREV(x,y)
122  Macro: Allocate next item in doubly linked list and step on.
123  #FUNCTION LAST(x)
124  Macro: Move to end of list
125  #FUNCTION FREELIST(y,z)
126  Macro: Free list y of type z
127  #FUNCTION FREE(x)
128  Macro: Free memory if non-NULL and set the variable to NULL
129  #FUNCTION DELETE(lst,itm,type)
130  Macro: Deletes (itm) from linked list (lst) of type (type)
131  #FUNCTION FINDPREV(p, start, q)
132  Set p to item in linked list start before q
133  #FUNCTION DELETEDOUBLE(lst,itm,type)
134  Macro: Deletes (itm) from a doubly linked list (lst) of type (type)
135 
136  #SUBGROUP Miscellaneous
137  #FUNCTION NEWLINE
138  Macro: Print a newline character to stdout
139  #FUNCTION RANGECHECK(x,y,z)
140  Macro: Return x constrained to range y to z
141 
142  #SUBGROUP Flags and bitwise operations
143  #FUNCTION TOGGLE(x)
144  Macro: Toggle a flag
145  #FUNCTION SET(x,y)
146  Macro: Sets bit y (a hex value) in variable x
147  #FUNCTION UNSET(x,y)
148  Macro: Clears bit y (a hex value) in variable x
149  #FUNCTION ISSET(x,y)
150  Macro: Tests bit y (a hex value) in variable x
151 
152  #SUBGROUP String handling
153  #FUNCTION TERMINATE(x)
154  Macro: Terminate a string at the first \n
155  #FUNCTION TERMINATECR(x)
156  Macro: Terminate a string at the first \r
157  #FUNCTION UPPER(x)
158  Macro: Converts a string to upper case
159  #FUNCTION KILLLEADSPACES(x,y)
160  Macro: Makes x a pointer into string y after any spaces or tabs.
161  #FUNCTION TERMAT(x,y)
162  Macro: Terminates character string x at first character y
163  #FUNCTION KILLTRAILSPACES(x)
164  Macro: Terminate string to remove any trailing white space
165  #FUNCTION PADMINTERM(str,len)
166  Macro: Pads a string to len chars only if it is shorter
167  #FUNCTION PADCHARMINTERM(str,char,len)
168  Macro: Pads a string to len chars with specified
169  character only if it is shorter
170  #FUNCTION DOTIFY(str)
171  Macro: Replace ' ' with '.' in string
172  #FUNCTION DEDOTIFY(str)
173  Macro: Replace '.' with ' ' in string
174  #FUNCTION STRNCPYNOSPACES(out, in, maxlen)
175  Macro: Like strncpy() but skips spaces
176 
177  #SUBGROUP Maths
178  #FUNCTION MAX(x,y)
179  Macro: max() as macro
180  #FUNCTION MIN(x,y)
181  Macro: min() as macro
182  #FUNCTION ABS(x,y)
183  Macro: abs() as macro
184 
185  #SUBGROUP Debugging
186  #FUNCTION D(BUG)
187  Macro: Prints the BUG string if DEBUG is defined first
188 
189  #SUBGROUP Array handling
190  #FUNCTION TESTINARRAY(x,l,y,r)
191  Macro: Tests whether value (y) is in array (x) if length (l) returning the result in (r)
192  #FUNCTION FINDINARRAY(x,l,y,r)
193  Macro: Finds value (y) is in array (x) if length
194  (l) returning the offset in (r). Offset is -1 if not found
195 
196  #SUBGROUP User interaction
197  #FUNCTION PROMPT(fp,x)
198  Macro: Issue a prompt to stdout if fp is a terminal
199 
200  #SUBGROUP File handling
201  #FUNCTION FCLOSE(fp)
202  Macro: close a file pointer if it is non-NULL and not stdin/out/err.
203  Set the file pointer to NULL afterwards
204 
205 */
206 /************************************************************************/
207 #ifndef _MACROS_H
208 #define _MACROS_H
209 
210 /***************************** Includes *********************************/
211 #include <ctype.h>
212 
213 /**************************** Definitions *******************************/
214 #ifndef PI
215 #define PI (4.0 * atan(1.0))
216 #endif
217 
218 #ifndef TRUE
219 #define TRUE 1
220 #endif
221 
222 #ifndef FALSE
223 #define FALSE 0
224 #endif
225 
226 /***************************** Maths macros *****************************/
227 #define RANGECHECK(x,y,z) ((x)<(y)) ? (y) : ((x)>(z)) ? (z) : (x)
228 #define DISTSQ(a,b) (((a)->x - (b)->x) * ((a)->x - (b)->x) + \
229  ((a)->y - (b)->y) * ((a)->y - (b)->y) + \
230  ((a)->z - (b)->z) * ((a)->z - (b)->z))
231 #define DIST(a,b) sqrt(((a)->x - (b)->x) * ((a)->x - (b)->x) + \
232  ((a)->y - (b)->y) * ((a)->y - (b)->y) + \
233  ((a)->z - (b)->z) * ((a)->z - (b)->z))
234 #ifndef ABS
235 #define ABS(x) (((x)<0) ? (-(x)) : (x))
236 #endif
237 
238 #ifndef MAX
239 #define MAX(a,b) (((a)>(b)) ? (a) : (b))
240 #define MIN(a,b) (((a)<(b)) ? (a) : (b))
241 #endif
242 
243 /***************************** List macros ******************************/
244 #define INIT(x,y) do { x=(y *)malloc(sizeof(y)); \
245  if(x != NULL) x->next = NULL; } while(0)
246 #define INITPREV(x,y) do { x=(y *)malloc(sizeof(y));\
247  if(x != NULL) {x->next=NULL; x->prev=NULL;} } \
248  while(0)
249 #define NEXT(x) (x)=(x)->next
250 #define PREV(x) (x)=(x)->prev
251 #define ALLOCNEXT(x,y) do { (x)->next=(y *)malloc(sizeof(y));\
252  if((x)->next != NULL) { (x)->next->next=NULL; }\
253  NEXT(x); } while(0)
254 #define ALLOCNEXTPREV(x,y) do { (x)->next=(y *)malloc(sizeof(y));\
255  if((x)->next != NULL)\
256  { (x)->next->prev = (x); \
257  (x)->next->next=NULL; }\
258  NEXT(x);} while(0)
259 #define LAST(x) while(((x)!=NULL) && ((x)->next != NULL)) NEXT(x)
260 /* FREELIST takes 2 parameters:
261  y: name of list
262  z: type of list
263 */
264 #define FREELIST(y,z) while((y)!=NULL) \
265  { z *_freelist_macro_q; \
266  _freelist_macro_q = (y)->next; \
267  free((char *)(y)); \
268  (y) = _freelist_macro_q; \
269  }
270 #define FREE(x) if((x)!=NULL) free(x); (x) = NULL
271 
272 /*>DELETE(start, item, type)
273  -------------------------
274  Deletes (item) from a linked list.
275  (start) will be modified if (item) is the first in the list.
276  (item) is returned as the pointer to the next item in the list (i.e.
277  as item->next). One can therefore simply call the routine N times
278  to delete N items. If (start) or (item) is NULL, does nothing
279 
280 - 16.02.95 Original By: ACRM
281 - 10.04.08 Fixed position of break. By: CTP
282 - 24.07.14 Initialize list pointers. By: CTP
283 */
284 #define DELETE(x, y, z) \
285 do { \
286  z *_delete_macro_p = NULL, \
287  *_delete_macro_prev = NULL, \
288  *_delete_macro_temp = NULL, \
289  *_delete_macro_temp2 = NULL; \
290  if((x)!=NULL && (y)!=NULL) \
291  { \
292  for(_delete_macro_p=(x); \
293  _delete_macro_p!=NULL; \
294  NEXT(_delete_macro_p)) \
295  { \
296  if(_delete_macro_p == (y)) \
297  { \
298  _delete_macro_temp2 = (y)->next; \
299  if(_delete_macro_prev == NULL) \
300  { \
301  _delete_macro_temp = (x)->next; \
302  free(x); \
303  (x) = _delete_macro_temp; \
304  } \
305  else \
306  { \
307  _delete_macro_prev->next = _delete_macro_p->next; \
308  free(_delete_macro_p); \
309  } \
310  break; \
311  } \
312  _delete_macro_prev = _delete_macro_p; \
313  } \
314  (y) = _delete_macro_temp2; \
315  } \
316 } while(FALSE)
317 
318 
319 /*>DELETEDOUBLE(start, item, type)
320  -------------------------------
321  Deletes (item) from a doubly linked list.
322  (start) will be modified if (item) is the first in the list.
323  (item) is returned as the pointer to the next item in the list (i.e.
324  as item->next). One can therefore simply call the routine N times
325  to delete N items. If (start) or (item) is NULL, does nothing
326 
327 - 13.03.99 Original By: ACRM
328 */
329 #define DELETEDOUBLE(s, x, y) \
330  do { y *_deleteandnext_macro_temp; \
331  if(((s)!=NULL) && ((x)!=NULL)) \
332  { if((x)==(s)) (s) = (x)->next; \
333  _deleteandnext_macro_temp = (x)->next; \
334  if((x)->prev != NULL) (x)->prev->next = (x)->next; \
335  if((x)->next != NULL) (x)->next->prev = (x)->prev; \
336  free(x); \
337  (x) = _deleteandnext_macro_temp; \
338  } } while(0)
339 
340 /*>FINDPREV(ptr, start, item)
341  --------------------------
342  Searches a linked list beginning at (start) to find the item which
343  preceeds (item). Its address is put into (ptr). If (item) is the
344  same as (start) or (item) is not found, then the routine returns
345  NULL in (ptr)
346  This is used when wanting to look at the previous item in a singly
347  linked list.
348 
349 - 26.01.06 Original By: ACRM
350 */
351 #define FINDPREV(p, s, l) \
352  do { p = (s); \
353  if((s)==(l)) \
354  { p = NULL; } else \
355  { \
356  while((p != NULL) && (p->next != (l))) \
357  { p = p->next; \
358  } } } while(0)
359 
360 
361 /***************************** Misc. macros *****************************/
362 #define NEWLINE printf("\n")
363 
364 #define TOGGLE(x) (x) = (x) ? FALSE : TRUE
365 
366 #define TERMINATE(x) do { int _terminate_macro_j; \
367  for(_terminate_macro_j=0; \
368  (x)[_terminate_macro_j]; \
369  _terminate_macro_j++) \
370  { if((x)[_terminate_macro_j] == '\n') \
371  { (x)[_terminate_macro_j] = '\0'; \
372  break; \
373  } } } while(0)
374 #define TERMINATECR(x) do { int _terminate_macro_j; \
375  for(_terminate_macro_j=0; \
376  (x)[_terminate_macro_j]; \
377  _terminate_macro_j++) \
378  { if((x)[_terminate_macro_j] == '\r') \
379  { (x)[_terminate_macro_j] = '\0'; \
380  break; \
381  } } } while(0)
382 #define TERMAT(x, y) do { int _termat_macro_j; \
383  for(_termat_macro_j=0; \
384  (x)[_termat_macro_j]; \
385  _termat_macro_j++) \
386  { if((x)[_termat_macro_j] == (y)) \
387  { (x)[_termat_macro_j] = '\0'; \
388  break; \
389  } } } while(0)
390 #define UPPER(x) do { int _upper_macro_i; \
391  for(_upper_macro_i=0; \
392  _upper_macro_i<(int)strlen(x) && \
393  (x)[_upper_macro_i]; \
394  _upper_macro_i++) \
395  if(islower((x)[_upper_macro_i])) \
396  (x)[_upper_macro_i] = \
397  (char)toupper((x)[_upper_macro_i]); \
398  } while(0)
399 #define LOWER(x) do { int _lower_macro_i; \
400  for(_lower_macro_i=0; \
401  _lower_macro_i<(int)strlen(x) && \
402  (x)[_lower_macro_i]; \
403  _lower_macro_i++) \
404  if(isupper((x)[_lower_macro_i])) \
405  (x)[_lower_macro_i] = \
406  (char)tolower((x)[_lower_macro_i]); \
407  } while(0)
408 #define KILLLEADSPACES(y,x) \
409  do \
410  { for((y)=(x); *(y) == ' ' || *(y) == '\t'; (y)++) ; } \
411  while(0)
412 
413 
414 #define KILLTRAILSPACES(x) \
415 do { int _kts_macro_i; \
416  _kts_macro_i = strlen(x) - 1; \
417  while(((x)[_kts_macro_i] == ' ' || \
418  (x)[_kts_macro_i] == '\t') && \
419  _kts_macro_i>=0) \
420  (_kts_macro_i)--; \
421  (x)[++(_kts_macro_i)] = '\0'; \
422  } while(0)
423 
424 
425 /* Tests for the presence of (y) in array (x) of length (l). The result
426  (TRUE or FALSE) is returned in (r)
427 - 02.08.95 Original
428 */
429 #define TESTINARRAY(x, l, y, r) \
430 do { \
431  int _inarray_macro_i; \
432  (r) = FALSE; \
433  if((x)==NULL) break; \
434  for(_inarray_macro_i=0; _inarray_macro_i<(l); _inarray_macro_i++) \
435  { if((x)[_inarray_macro_i] == (y)) \
436  { (r) = TRUE; \
437  break; \
438 } } } while(FALSE)
439 
440 /* Finds offset of item (y) in array (x) of length (l). The result
441  is returned in (r) which is -1 if item not found
442 - 02.08.95 Original
443 */
444 #define FINDINARRAY(x, l, y, r) \
445 do { \
446  int _inarray_macro_i; \
447  (r) = (-1); \
448  if((x)==NULL) break; \
449  for(_inarray_macro_i=0; _inarray_macro_i<(l); _inarray_macro_i++) \
450  { if((x)[_inarray_macro_i] == (y)) \
451  { (r) = _inarray_macro_i; \
452  break; \
453 } } } while(FALSE)
454 
455 
456 /* Used just like padterm, but doesn't touch the string if it's already
457  longer than len characters
458 */
459 #define PADMINTERM(string, len) \
460  do { \
461  if(strlen((string)) < (len)) blPadterm((string), (len)); \
462  } while(0)
463 
464 /************************************************************************/
465 /*>PADCHARMINTERM(string, char, length)
466  ------------------------------------
467 *//**
468 
469  Pads a string to a specified length using char and terminates at that
470  point
471 
472 - 13.03.99 Original By: ACRM
473 */
474 #define PADCHARMINTERM(s, c, l) \
475 do { int _padminterm_macro_i; \
476  if(strlen((s)) < (l)) \
477  { for(_padminterm_macro_i=strlen((s)); \
478  _padminterm_macro_i<(l); \
479  _padminterm_macro_i++) \
480  (s)[_padminterm_macro_i] = (c); \
481  (s)[(l)] = '\0'; \
482  } } while(0)
483 
484 
485 /************************************************************************/
486 /*>DOTIFY(char *str)
487  -----------------
488 *//**
489 
490  Macro to replace ' ' in a string with '.'
491 
492 - 21.04.99 Original By: ACRM
493 */
494 #define DOTIFY(str) \
495 do { \
496  char *_dotify_macro_chp; \
497  _dotify_macro_chp = str; \
498  while(*_dotify_macro_chp) { \
499  if(*_dotify_macro_chp==' ') *_dotify_macro_chp = '.'; \
500  _dotify_macro_chp++; \
501 } } while(0)
502 
503 /************************************************************************/
504 /*>DEDOTIFY(char *str)
505  -------------------
506 *//**
507 
508  Macro to replace '.' in a string with ' '
509 
510 - 21.04.99 Original By: ACRM
511 */
512 #define DEDOTIFY(str) \
513 do { \
514  char *_dedotify_macro_chp; \
515  _dedotify_macro_chp = str; \
516  while(*_dedotify_macro_chp) { \
517  if(*_dedotify_macro_chp=='.') *_dedotify_macro_chp = ' '; \
518  _dedotify_macro_chp++; \
519 } } while(0)
520 
521 
522 /************************************************************************/
523 /*>SUBSCHAR(s, x, y)
524  -----------------
525 *//**
526 
527  Substitute character x by character y in string s
528 
529 - 21.05.99 Original
530 */
531 #define SUBSCHAR(s, x, y) \
532 do { char *_subschar_macro_ch = (s); \
533  while(*_subschar_macro_ch != '\0') \
534  { if(*_subschar_macro_ch == (x)) *_subschar_macro_ch = (y); \
535  _subschar_macro_ch++; \
536  } } while(0)
537 
538 
539 /************************************************************************/
540 #define STRNCPYNOSPACES(out, in, mx) \
541 do { char *_chp; \
542  int _pos = 0; \
543  for(_chp=(in); *_chp != '\0'; _chp++) \
544  { if(*_chp != ' ') \
545  { buffer[_pos++] = *_chp; \
546  if(_pos >= (mx)) break; \
547  } } \
548  if(_pos < (mx)) buffer[_pos] = '\0'; \
549  } while(0)
550 
551 
552 /* Bit-wise operators
553 - 02.08.95 Original
554 */
555 #define SET(x, y) (x) |= (y)
556 #define UNSET(x, y) (x) &= (~(y))
557 #define ISSET(x, y) ((BOOL)((x)&(y)))
558 
559 /* A version of fclose() that checks the file pointer is non-NULL and
560  not standard in/out/err. After closing the file, it sets the file
561  pointer to NULL
562  04.11.15 Original By: ACRM
563 */
564 #define FCLOSE(x) \
565  do { \
566  if(((x) != NULL) && ((x) != stdin) && \
567  ((x) != stdout) && ((x) != stderr)) { \
568  fclose((x)); \
569  (x) = NULL; \
570  } \
571  } while (0)
572 
573 #ifdef DEBUG
574 #define D(BUG) fprintf(stderr,"%s",BUG); fflush(stderr)
575 #else
576 #define D(BUG)
577 #endif
578 
579 
580 /************************** The PROMPT macro ****************************/
581 /* isatty() is not POSIX */
582 #ifdef __unix
583 # if defined(_POSIX_SOURCE) || !defined(_SVR4_SOURCE)
584  #include <unistd.h>
585 # endif
586 #endif
587 
588 /* Default is just to print a string as a prompt */
589 #define PROMPT(in,x) printf("%s",(x))
590 
591 /* More intelligent prompts for systems where we know the FILE structure*/
592 #ifdef __sgi
593 # undef PROMPT
594 # define PROMPT(in,x) do{if(isatty((in)->_file)) \
595  printf("%s",(x));}while(0)
596 #endif
597 #ifdef __linux__
598 # undef PROMPT
599 # define PROMPT(in,x) do{if(isatty((in)->_fileno)) \
600  printf("%s",(x));}while(0)
601 #endif
602 
603 #endif /* _MACROS_H */
604