/*
*+
*  Name:
*     NBS_INIT_ALLOC

*  Purpose:
*     Allocate an area of contiguous memory and return a pointer to its start.
*     Also initialise for allocating memory for noticeboard data.

*  Language:
*     ANSI C

*  Invocation:
*     (Char *) = NBS_INIT_ALLOC (NBYTES,DATA)

*  Description:
*     Use MALLOC to allocate the memory
*     Set the base for noticeboard data allocation.
*
*     Note that noticeboard data is not really allocated. A counter is simply
*     maintained that shows where the data address would be. When the definition
*     phase is complete these data addresses are relocated to start just above
*     the noticeboard definition.

*  Arguments:
*     int NBYTES (Given)
*        Number of bytes of contiguous memory to allocate.
*     char * DATA (Given)
*        Address to use as base for allocating data memory.

*  Returned Value:
*     char *NBS_INIT_ALLOC
*        Pointer to first character of allocated memory area.

*  Copyright:
*     Copyright (C) 1987 Science & Engineering Research Council. All
*     Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     23-Jul-1987 (WFL):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     C RTL:
*        MALLOC         Allocate dynamic memory

*  Prior Requirements:
*     None

*-
*/


/*
*+
*  Name:
*     NBS_ALLOC

*  Purpose:
*     Allocate NBYTES bytes from the private allocation buffer.

*  Language:
*     ANSI C

*  Invocation:
*     (Char *) = NBS_ALLOC (NBYTES)

*  Description:
*     If there is not enough memory, return NIL.
*     Coerce size of memory segment up to an integral number of quadwords.
*     Otherwise increment the top-of-memory pointer and return a pointer to
*     the first allocated byte.
*
*     This routine is used for allocating memory during the definition phase
*     for everything except for noticeboard data.

*  Arguments:
*     int NBYTES (Given)
*        Number of bytes of contiguous memory to allocate.

*  Returned Value:
*     char *NBS_ALLOC
*        Pointer to first character of allocated memory area.

*  Copyright:
*     Copyright (C) 1987 Science & Engineering Research Council.
*     Copyright (C) 1995 Central Laboratory of the Research Councils.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     23-Jul-1987 (WFL):
*        Original version.
*     17-May-1995 (DJA):
*        Ensure data address is sizeof(double) aligned
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     None

*  Prior Requirements:
*     NBS_INIT_ALLOC must have been called.

*-
*/


/*
*+
*  Name:
*     NBS_DATA_ALLOC

*  Purpose:
*     Return a pointer to an imaginary data area used for keeping track of
*     where noticeboard data will live.

*  Language:
*     ANSI C

*  Invocation:
*     (Char *) = NBS_DATA_ALLOC (NBYTES)

*  Description:
*     Increment the top-of-memory pointer and return a pointer to the first
*     allocated byte.
*
*     This routine is used for allocating memory during the definition phase
*     for noticeboard data. It allocates relative to the base address specified
*     in the call to NBS_INIT_ALLOC. The addresses so allocated are later
*     relocated to place the data immediately above the definition part of
*     the noticeboard.
*
*     This routine is used for allocating memory during the definition phase
*     for everything except for noticeboard data.

*  Arguments:
*     int NBYTES (Given)
*        Number of bytes of contiguous memory to allocate.

*  Returned Value:
*     char *NBS_DATA_ALLOC
*        Pointer to first character of allocated memory area.

*  Copyright:
*     Copyright (C) 1987 Science & Engineering Research Council.
*     Copyright (C) 1995 Central Laboratory of the Research Councils.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     23-Jul-1987 (WFL):
*        Original version.
*     17-May-1995 (DJA):
*        Ensure data address is sizeof(double) aligned
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     None

*  Prior Requirements:
*     NBS_INIT_ALLOC must have been called.

*-
*/


/*
*+
*  Name:
*     NBS_DEINIT_ALLOC

*  Purpose:
*     Free the storage obtained with NBS_INIT_ALLOC.

*  Language:
*     ANSI C

*  Invocation:
*     (Char *) = NBS_DEINIT_ALLOC ()

*  Description:
*     Simply use the appropriate RTL routine.

*  Arguments:
*     None

*  Returned Value:
*     char *NBS_ALLOC
*        (Char *) The value returned by FREE.

*  Copyright:
*     Copyright (C) 1987 Science & Engineering Research Council. All
*     Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     23-Jul-1987 (WFL):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     C RTL:
*        FREE          Release dynamic memory
*     None

*  Prior Requirements:
*     NBS_INIT_ALLOC must have been called.

*-
*/


/*
*+
*  Name:
*     NBS_WRITE_FILE

*  Purpose:
*     Create a noticeboard definition file, write header record, then write
*     noticeboard definition.

*  Language:
*     ANSI C

*  Invocation:
*     (Void) = NBS_WRITE_FILE (NAME,DATA,FILE_SIZE,DEFN_SIZE,
*        					   SECTION_SIZE,STATUS)

*  Description:
*     Create the file with a default file extension of .NBD
*     Encode and write the header.
*     Write the noticeboard definition.
*     Close the file.

*  Arguments:
*     FORTRAN/C string NAME (Given)
*        Name of file. Default file extension is .NBD.
*     char *DATA (Given)
*        Pointer to first byte of noticeboard definition.
*     int FILE_SIZE (Given)
*         Total size of file. This will be either DEFN_SIZE or SECTION_SIZE
*         and is the number of bytes to write to the file following the header.
*     int DEFN_SIZE (Given)
*         Size of definition part of noticeboard.
*     int SECTION_SIZE (Given)
*         Total size of global section.
*     int *STATUS (Given and returned)
*         The global status. Possible codes are,
*        	NBS__CANTOPEN	=> Can't open the file
*        	NBS__CANTWRITE	=> Can't write the file

*  Returned Value:
*     (void)

*  Copyright:
*     Copyright (C) 1987, 1993 Science & Engineering Research Council.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     23-Jul-1987 (WFL):
*        Original version.
*     22-Mar-1993 (DJA):
*        Updated string handling. Added error reporting.
*
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     C RTL:
*        FCLOSE            	Close a file
*        FOPEN            	Open a file
*        FWRITE            	Write to a file
*        TIME            	Get the current time
*     NBS:
*        NBS_STRIMP        Import a string, converting to upper-case

*  Prior Requirements:
*     None

*-
*/


/*
*+
*  Name:
*     NBS_OPEN_FILE

*  Purpose:
*     Open a noticeboard definition file and read and decode its header record.

*  Language:
*     ANSI C

*  Invocation:
*     (Void) = NBS_OPEN_FILE (NAME,CHAN,FILE_SIZE,DEFN_SIZE,SECTION_SIZE,STATUS)

*  Description:
*     Open the file.
*     Read its header record.
*     Decode the header record and check the software version.

*  Arguments:
*     FORTRAN/C string NAME (Given)
*        Name of file. Default file extension is .NBD.
*     FILE **CHAN (Returned)
*        Channel on which file has been opened.
*     int FILE_SIZE (Returned)
*         Total size of file. This will be either DEFN_SIZE or SECTION_SIZE
*         and is the number of bytes to write to the file following the header.
*     int DEFN_SIZE (Returned)
*         Size of definition part of noticeboard.
*     int SECTION_SIZE (Returned)
*         Total size of global section.
*     int *STATUS (Given and returned)
*         The global status. Possible codes are,
*        	NBS__CANTOPEN	=> Can't open the file
*        	NBS__CANTREAD	=> Can't read the file
*        	NBS__BADVERSION	=> File written with wrong s/w version

*  Returned Value:
*     (void)

*  Copyright:
*     Copyright (C) 1987, 1993 Science & Engineering Research Council.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     23-Jul-1987 (WFL):
*        Original version.
*     22-Mar-1993 (DJA):
*        Updated string handling. Added error reporting.
*
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     C RTL:
*        FOPEN             Open a file
*        FREAD             Read from a file
*     NBS:
*       NBS_STRIMP   Import a string, converting to upper-case

*  Prior Requirements:
*     None

*-
*/


/*
*+
*  Name:
*     NBS_CLOSE_FILE

*  Purpose:
*     Close a noticeboard definition file.

*  Language:
*     ANSI C

*  Invocation:
*     (Void) = NBS_CLOSE_FILE (CHAN)

*  Description:
*     Simply close the file using the appropriate RTL routine.

*  Arguments:
*     FILE **CHAN (Given)
*        Channel on which file has been opened.

*  Returned Value:
*     (void)

*  Copyright:
*     Copyright (C) 1987 Science & Engineering Research Council. All
*     Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     23-Jul-1987 (WFL):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     C RTL:
*        FCLOSE            Close a file

*  Prior Requirements:
*     None

*-
*/


/*
*+
*  Name:
*     NBS_OPEN_WRITE

*  Purpose:
*     Open a noticeboard definition file for append update access.

*  Language:
*     ANSI C

*  Invocation:
*     (Void) = NBS_OPEN_WRITE (SAVE_NAME,CHAN,STATUS)

*  Description:
*     Simply open the file for append update access.

*  Arguments:
*     char *SAVE_NAME (Given)
*        Name of file. Default file extension is .NBD.
*     FILE **CHAN (Returned)
*        Channel on which file has been opened for write access.
*     int *STATUS (Given and returned)
*         The global status. Possible codes are,
*        	NBS__CANTOPEN	=> Can't open the file

*  Returned Value:
*     (void)

*  Copyright:
*     Copyright (C) 1988, 1993 Science & Engineering Research Council.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     25-Mar-1988 (WFL):
*        Original version.
*     22-Mar-1993 (DJA):
*        Added error reporting.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     C RTL:
*        FOPEN            Open a file

*  Prior Requirements:
*     None

*-
*/


/*
*+
*  Name:
*     NBS_UPDATE_FILE

*  Purpose:
*     Write the contents of a noticeboard to its noticeboard definition
*     file.

*  Language:
*     ANSI C

*  Invocation:
*     (Void) = NBS_UPDATE_FILE (CHAN,SECTION,SECTION_SIZE,STATUS)

*  Description:
*     Position the file to the beginning of the definition part.
*     Write the noticeboard definition and data to the file.
*
*     The file is assumed to be open and is not closed afterwards.

*  Arguments:
*     FILE *CHAN (Given)
*        Channel number on which file is open.
*     char *SECTION (Given)
*        Pointer to first byte of noticeboard.
*     int SECTION_SIZE (Given)
*        Size of noticeboard. It begins at an offset of
*        "length of header" into the file.
*     int *STATUS (Given and returned)
*         The global status. Possible codes are,
*        	NBS__CANTWRITE	=> Can't write the file

*  Returned Value:
*     (void)

*  Copyright:
*     Copyright (C) 1988, 1993 Science & Engineering Research Council.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     28-Mar-1988 (WFL):
*        Original version.
*     22-Mar-1993 (DJA):
*        Added error reporting.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     C RTL:
*        FSEEK      Position to a given offset within a file
*        FWRITE            Write to a file

*  Prior Requirements:
*     None

*-
*/


/*
*+
*  Name:
*     NBS_RELOCATE_POINTERS

*  Purpose:
*     Recursively relocate all pointers in the hierarchical structure rooted
*     at a specified point.

*  Language:
*     ANSI C

*  Invocation:
*     (Void) = NBS_RELOCATE_POINTERS (ID,I_OFFSET,FBS_OFFSET,D_OFFSET,ADD)

*  Description:
*     Do nothing if passed a NIL identifier.
*     If adding offsets beforehand relocate pointers at the current level.
*     Make a recursive call to relocate the eldest child tree.
*     Make a recursive call to relocate the next sibling tree.
*     If subtracting offsets afterwards relocate pointers at the current level.
*
*     This routine may be called either to turn real virtual addresses into
*     process-independent numbers suitable for storing in a noticeboard defin-
*     ition file or a global section, or to turn such process-independent num-
*     bers into real virtual addresses. In the former case, the relocation
*     must be done after all use of the pointers as virtual addresses has been
*     completed (ie at the end of the routine). In the latter case, the reloc-
*     ation must be done before any use of the pointers as virtual addresses
*     (ie at the beginning of the routine).

*  Arguments:
*     int *ID  (Given)
*        Identifier of root of tree. If this is a NIL identifier then the
*        routine does nothing.
*     int I_OFFSET (Given)
*        Offset to apply to pointers to item descriptors
*     int FBS_OFFSET (Given)
*        Offset to apply to pointers to fixed information,
*        board information and shape information.
*     int D_OFFSET (Given)
*        Offset to apply to pointers to noticeboard data.
*     int ADD (Given)
*        Whether add the offsets at the beginning (1) or subtract them
*        at the end (0).

*  Returned Value:
*     (void)

*  Copyright:
*     Copyright (C) 1987 Science & Engineering Research Council. All
*     Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     23-Jul-1987 (WFL):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     NBS:
*        NBS_RELOCATE_ITEM     Relocate pointers for an item at a single level
*        NBS_RELOCATE_POINTERS Relocate pointers for an item and all
*                              lower-level items

*  Prior Requirements:
*     None

*-
*/


/*
*+
*  Name:
*     NBS_RELOCATE_ITEM

*  Purpose:
*     Relocate all the pointers associated with a given item.

*  Language:
*     ANSI C

*  Invocation:
*     (Void) = NBS_RELOCATE_ITEM (ID,I_OFFSET,FBS_OFFSET,D_OFFSET,ADD)

*  Description:
*     Simply call the single address relocation routine once for each pointer
*     in the item descriptor, taking care to pass the correct offset for each
*     pointer.

*  Arguments:
*     int *ID  (Given)
*        Item identifier.
*     int I_OFFSET (Given)
*        Offset to apply to pointers to item descriptors
*     int FBS_OFFSET (Given)
*        Offset to apply to pointers to fixed information,
*        board information and shape information.
*     int D_OFFSET (Given)
*        Offset to apply to pointers to noticeboard data.
*     int ADD (Given)
*        Whether add the offsets at the beginning (1) or subtract them
*        at the end (0).

*  Returned Value:
*     (void)

*  Copyright:
*     Copyright (C) 1987 Science & Engineering Research Council. All
*     Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     23-Jul-1987 (WFL):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     NBS:
*        NBS_RELOCATE_ADDRESS  Relocate a single address

*  Prior Requirements:
*     None

*-
*/


/*
*+
*  Name:
*     NBS_RELOCATE_ADDRESS

*  Purpose:
*     Relocate an address (provided it is not NIL and will not result in a
*     NIL address when relocated).

*  Language:
*     ANSI C

*  Invocation:
*     (Char *) = NBS_RELOCATE_ADDRESS (ADDRESS,OFFSET,ADD)

*  Description:
*     If subtracting the offset, negate it.
*     If the address is not NIL and the address after relocation will not be
*     NIL, return the relocated address.
*     Otherwise return the unaltered address.

*  Arguments:
*     int ADDRESS (Given)
*        Address which is to be offset.
*     int OFFSET (Given)
*        Offset to apply to the address.
*     int ADD (Given)
*        Whether add the offsets (1) or subtract them (0).

*  Returned Value:
*     (Char *) NBS_RELOCATE_ADDRESS
*        The relocated address.

*  Copyright:
*     Copyright (C) 1987, 1993 Science & Engineering Research Council.
*     All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     23-Jul-1987 (WFL):
*        Original version.
*     22-Mar-1993 (DJA):
*        Removed check for negative address as both ULTRIX and SunOS can
*        generate such legal addresses.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     None

*  Prior Requirements:
*     None

*-
*/


/*
*+
*  Name:
*     NBS_MLIST_EXITHANDLER

*  Purpose:
*     Remove any global sections present on process exit

*  Language:
*     ANSI C

*  Invocation:
*     (void) = NBS_MLIST_EXITHANDLER()

*  Description:
*     A process using the UNIX version of NBS may leave behind mapped
*     global sections due to failed or absent NBS_LOSE_NOTICEBAORD calls.
*     This exit handler removes the mappings between the process address
*     space and all such sections in order that they can be removed from
*     the system without further actionn by the user.

*  Returned Value:
*     (Void)

*  Copyright:
*     Copyright (C) 1993 Science & Engineering Research Council. All
*     Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     30-Apr-1993 (DJA):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     NBS:
*        NBS_MLIST_UNMAP   Unmap a global section from process address space

*  Prior Requirements:
*     None

*-
*/


/*
*+
*  Name:
*     NBS_MLIST_ADD

*  Purpose:
*     Add a mapped section to the process's mapped section list

*  Language:
*     ANSI C

*  Invocation:
*     (void) = NBS_MLIST_ADD(CREATOR,MEMID,ADDR,STATUS)

*  Description:
*     Adds the address of the specified mapped section to this process's
*     list of mapped sections. If the error NBS__IMPOSSIBLE is returned,
*     a programming error is indicated as the logic in the routines using
*     the NBS_MLIST_ functions should ensure that NBS_MLIST_FIND is called
*     first. The first time this routine is called, the exit handler to
*     remove unmapped global section is installed.

*  Arguments:
*     int CREATOR (Given)
*        Is the caller the first mapper of the noticeboard?
*     int MEMID (Given)
*        Global section memory identifier
*     char *ADDR (Given)
*        Address at which section has been mapped
*     int *STATUS (Given and returned)
*        Global status. Possible codes are,
*           NBS__IMPOSSIBLE => Section already mapped, indicates failure
*           of logic elsewhere in NBS

*  Returned Value:
*     (Void)

*  Copyright:
*     Copyright (C) 1993 Science & Engineering Research Council. All
*     Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     05-Feb-1993 (DJA):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     C RTL:
*        MALLOC        Allocate dynamic memory

*  Prior Requirements:
*     None

*-
*/


/*
*+
*  Name:
*     NBS_MLIST_FIND

*  Purpose:
*     Requests a copy of the pointer to a global section which may already
*     be mapped. If it is not already mapped, then this routine returns -1

*  Language:
*     ANSI C

*  Invocation:
*     (Char *) = NBS_MLIST_FIND (MEMID,STATUS)

*  Description:
*     The list of sections mapped by this process is searched for the
*     required memory identifier. If found, the process address at which
*     the section mapped is returned, otherwise -1.

*  Arguments:
*     int MEMID (Given)
*        Global section memory identifier
*     int *STATUS (Given and returned)
*        Global status. Possible codes are,

*  Returned Value:
*     (char * ) = NBS_MLIST_FIND
*        Start address of mapped global section

*  Copyright:
*     Copyright (C) 1993 Science & Engineering Research Council. All
*     Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     05-Feb-1993 (DJA):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     C RTL:
*        MALLOC        Allocate dynamic memory

*  Prior Requirements:
*     None

*-
*/


/*
*+
*  Name:
*     NBS_MLIST_UNMAP

*  Purpose:
*     Unmaps a global section mapped by this process given the address of
*     that mapping.

*  Language:
*     ANSI C

*  Invocation:
*     (void) = NBS_MLIST_UNMAP(ADDR,STATUS)

*  Description:
*     The list of sections mapped by this process is searched for the
*     required address. If not found, NBS__SECTIONNOTFOUND is returned,
*     otherwise the reference count is decreased by one. If the
*     reference count drops to zero, the section is unmapped. If the
*     destroy field of the map is set, the section is also destroyed.

*  Arguments:
*     char *ADDR (Given)
*        Address at which global section is mapped
*     int *STATUS (Given and returned)
*        Global status. Possible codes are,

*  Returned Value:
*     (Void)

*  Copyright:
*     Copyright (C) 1993 Science & Engineering Research Council. All
*     Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful, but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 59 Temple Place,Suite 330, Boston, MA
*     02111-1307, USA

*  Authors:
*     {original_author_entry}

*  History:
*     05-Feb-1993 (DJA):
*        Original version.
*     {enter_changes_here}

*  Bugs:
*     {note_any_bugs_here}

*  External Routines Used:
*     UNIX RTL:
*        SHMDT         Unmap global section from process address space
*        SHMCTL        Shared memory control operations
*     C RTL:
*        FREE          Release dynamic memory

*  Prior Requirements:
*     None

*-
*/


/*+ EMS1_GET_FACILITY_ERROR - interface to the facility error system
 *
 * This function translates the given 'errcode' to a facility number and a
 * message number. (As errcode is VMS compatable there is an severity code
 * available as well but this is currently unused on Unix).
 *
 * The facility code number (fac_code) is used to locate a file on the search
 * path defined by environment variable EMS_PATH (if defined).
 * If EMS_PATH is not defined, or does not produce a file, the file is looked
 * for at a pathname relative to each of the directories in the user's PATH.
 *
 * The error corresponding to the 'message number' is located and the three
 * strings facility name, message name and message text are returned. Suitable
 * defaults are used for any error condition.
 *
 * Arguments:
 *        errcode = unsigned int (given)
 *           error code in messgen format
 *        facility_name = char ** (returned)
 *           facility name
 *        error_ident = char ** (returned)
 *           message identifier
 *        error_text = char ** (retuned)
 *           message text
 *
 * Author:
 *    B.K. McIlwrath (STARLINK)
 *    P.W. Draper (JAC, Durham University)
 * History:
 *    Created: bkm, 18/08/1994
 *    Modified: bkm, 02/08/1995
 *      Close file descriptor used to search facility error files
 *    Modified: pwd, 19/05/2008
 *      Add POSIX threads support. Use mutexes to protect the cache that is
 *      shared globally. Introduce thread-specific data storage for the
 *      various result strings.
 */


/*************************************************************************
 *
 *  EMS1_CREIM( source_f, sourcelen )
 *
 *  Purpose:
 *     Create a temporary C string and import a FORTRAN string into it
 *     Returns a pointer to the temporary string
 *
 *  Note:
 *     This is a copy of the CNF routine. It is included here to avoid
 *     a dependency on CNF for the Conly system. But it may be system
 *     dependent.
 *
 *************************************************************************
 */


/***************************************************************************
 *
 * EMS_STARF_
 *
 * The Fortran interface to ems1Starf
 * Called from Fortran by:
 *
 * CALL EMS1_STARF( ENVAR, RELPATH, ACMODE, FILENAME, PATHLEN )
 *
 ***************************************************************************
 */


/* This would seem to be an exact cut-and-paste of msgFmt but there is no
   gain to be hand short of aliasing msgFmt directly to emsSet with the
   pre-processor. */


/*
 * Algorithm:
 *
 *   [1] Transform boundary of area to be filled from WC to DC.
 *   [2] Clip boundary of area to be filled.  This will result in one  or  more
 *       potentially  self  intersecting  boundaries  describing  the  disjoint
 *       area(s) to be filled.
 *   [3] Translate the boundary coordinates from DC to pixrect coordinates  and
 *       calculate the bounding box of the primitive.
 *   [4] Render the area(s) to be filled according to  the  interior  style  as
 *       follows:
 *
 *       HOLLOW areas have their boundaries drawn as 1 pixel  wide  vectors  in
 *         the current fill area colour using pr_polyline().
 *       SOLID areas are  filled  with  the  current  fill  area  colour  using
 *         pr_polygon_2().
 *       PATTERN areas are filled using a texture pixrect and pr_polygon_2().
 *         The pattern pixrect is  generated  by  creating  a  pattern  element
 *         pixrect from the pattern description stored  on  the  GKS  heap  and
 *         replicating this onto a pixrect the size of the  primitive  bounding
 *         box.
 *       HATCH areas are filled using a texture pixrect and pr_polygon_2(). The
 *         hatch pixrect is created by forcing the  current  fill  area  colour
 *         through a stencil formed from a replicated hatch element onto a copy
 *         of the current screen contents of the primitive bounding box.
 *
 * Errors:
 *
 *  -1016  Internal error detected within GKS
 *    304  Input/Output error while sending data to a workstation
 *
 * Comments:
 *
 *  This routine uses the RAL GKS stack allocation routines for FORTRAN routine
 *  workspace and malloc() for C routine workspace.
 *
 *  The ww foreground colour,  dd->d_fore,  must be set to the fill area colour
 *  index and the ww default bitmap pointer ddbm must be set to the appropriate
 *  workstation bitmap before this routine is called.
 */


/*
 * Errors:
 *
 *  -2006  Value of internal enumerated type is invalid
 */


/* Saved digital echo window */


/*
 * Errors:
 *
 *  -1016  Internal error detected within GKS
 *
 * Comments:
 *
 *  The constant ICHSIZ above is dependant on the PARAMETER of the same name
 *  in GK9SWD(),  and should have a value one less than the PARAMETER.
 *
 *  The font geometry information is copied into QWKDAT,  and the index of the
 *  font in 'fonts' is stored in KWKDAT.
 *
 *  If the font style used is changed,  you must update the WDT files for the
 *  Sun workstation types.  The values that need changing are kchh, qmnchh and
 *  qmxchh in the WDT section (the number of fonts as given by NFONT and the
 *  minimum and maximum height of the font family as given in FONT_TABLE).
 *
 *  The quantities held in a Font_info structure relate to a Sun raster
 *  character as follows (a 'M' is used as an example):
 *
 *			. . . . . . .> cap_to_top (1)
 *		       <X . . . . X .
 *		       <X . . . . X .
 *		       <X X . . X X .
 *		       <X X . . X X .
 *	    height (9) <X . X X . X .
 *		       <X . X X . X .
 *		       <X . . . . X .
 *		       <X . . . . X .<---- SunView baseline
 *		       <X . . . . X .<---- GKS baseline
 *			. . . . . . .>
 *			. . . . . . .> base_to_bottom (3)
 *			. . . . . . .>
 *			V V V V V V V
 *                        width (7)
 *
 *  baseline_offset is set by inspection.  If the GKS baseline (the lowest
 *  pixel set on a letter with no descenders) is one pixel below the SunView
 *  baseline (as shown by fontedit) then baseline_offset = -1,  and so forth.
 *
 *  Note that base_to_bottom is the number of pixels from below the GKS
 *  baseline to the lowest set pixel in a raster, NOT the bottom of the raster.
 */


/* Number of items */


/*
 * emugets - gets a string from the terminal emulator specified by ep. s is
 *           first of all printed and then any characters typed may be
 *           appended to it or edited using DEL or control-U. Input is
 *           terminated either by a carriage-return, or the break character
 *           or if n-1 chars are typed. The interface is as close to gets
 *           as makes sense. The function result is the terminating character.
 *
 *           Undefined things may happen if s is not initialised sensibly.
 */


/* Number of choices */


/* Saved foreground colour */


/* Window for digital echo */


/*
 * Errors:
 *
 *    300  Storage overflow has occurred in GKS
 *
 * Comments:
 *
 *  The size of the workstation colour table is used to decide whether the
 *  workstation's monochrome or colour.  The code to grab the pixfont from
 *  ww was supplied by M M Martin.
 */


/*
 * Comments:
 *
 *  To get compatibility between monochrome and colour windows,  SunView maps
 *  a monochrome index of 1 to the top entry in the colourmap of a colour
 *  window.  We must follow suit.
 *
 *  The GKS standard says that if an index used in a cell array is not present
 *  in the colour table on a workstation, a workstation dependent index is
 *  used on that workstation.  We simply cycle round the colour table.
 *  (This routine is also used for pattern fill, but the colour indices in the
 *  pattern definition will have been checked already in GKSRPA.)
 */


/*
 * Comments:
 *
 *  Assumes that the default pointers have been properly configured with
 *  gk9sww_() or an equivalent.
 */


/* Real data returned from GKS */


/*
 * Comments:
 *
 *  This routine will require modification when NeWS appears,  as it uses
 *  pixrects.
 */


/*
 * Errors:
 *
 *     304 Input/Output error has occurred while sending data to a workstation
 *
 * Comments:
 *
 *  Renders the raster on the ww backing pixrect using pr_put.
 *
 *  The raster data is stored in column major order,  but each line of the
 *  raster is stored as a column of the array and is therefore contiguous.
 */


/*
 * Errors:
 *
 *    300  Storage overflow has occurred in GKS
 *    304  Input/Output error has occurred while sending data to a workstation
 *
 * Comments:
 *
 *  Uses XDrawLine to render the polyline on the Pixmap ww maintains to
 *  back the window.
 *
 *  The brush and texture structures for the GC LGC are cached and only
 *  updated when the line width or line style are changed.
 *
 *  The array of shorts used to hold the cached line pattern ('cached_pattern')
 *  must be large enough to hold the largest pattern defined.
 */


/*
 * Errors:
 *
 *  -1016  Internal error detected within GKS
 *
 * Comments:
 *
 *  The constant ICHSIZ above is dependant on the PARAMETER of the same name
 *  in GK0XWD(),  and should have a value one less than the PARAMETER.
 *
 *  The font geometry information is copied into QWKDAT,  and the index of the
 *  font in 'fonts' is stored in KWKDAT.
 *
 *  If the font style used is changed,  you must update the WDT files for the
 *  X workstation types.  The values that need changing are kchh, qmnchh and
 *  qmxchh in the WDT section (the number of fonts as given by NFONT and the
 *  minimum and maximum height of the font family as given in FONT_TABLE).
 *
 *  The quantities held in a Font_info structure relate to a X glyph
 *  as follows (a 'M' is used as an example):
 *
 *			. . . . . . .> cap_to_top (1)
 *		       <X . . . . X .
 *		       <X . . . . X .
 *		       <X X . . X X .
 *		       <X X . . X X .
 *	    height (9) <X . X X . X .
 *		       <X . X X . X .
 *		       <X . . . . X .
 *		       <X . . . . X .
 *		       <X . . . . X .<---- GKS baseline
 *			. . . . . . .><---- X baseline
 *			. . . . . . .> base_to_bottom (3)
 *			. . . . . . .>
 *			V V V V V V V
 *                        width (7)
 *
 *  The GKS baseline is the lowest pixel (excluding descenders) but the X
 *  baseline is the pixel below that.
 *
 *  Note that base_to_bottom is the number of pixels from below the GKS
 *  baseline to the lowest set pixel in a raster, NOT the bottom of the raster.
 */


/*
 * Algorithm:
 *
 *   [1] Transform boundary of area to be filled from WC to DC.
 *   [2] Clip boundary of area to be filled.  This will result in one  or  more
 *       potentially  self  intersecting  boundaries  describing  the  disjoint
 *       area(s) to be filled.
 *   [3] Translate the boundary coordinates from DC to pixrect coordinates  and
 *       calculate the bounding box of the primitive.
 *   [4] Render the area(s) to be filled according to  the  interior  style  as
 *       follows:
 *
 *       HOLLOW areas have their boundaries drawn as 1 pixel  wide  vectors  in
 *         the current fill area colour using XDrawLine().
 *       SOLID areas are  filled  with  the  current  fill  area  colour  using
 *         XPolygonFill().
 *       PATTERN areas are filled using a texture pixrect and ???.
 *         The pattern pixrect is  generated  by  creating  a  pattern  element
 *         pixrect from the pattern description stored  on  the  GKS  heap  and
 *         replicating this onto a pixrect the size of the  primitive  bounding
 *         box.
 *       HATCH areas are filled using an hatches image Pixmap. The
 *         hatch Pixmap is created by forcing the  current  fill  area  colour
 *         through a stencil formed from a replicated hatch element onto a copy
 *         of the current screen contents of the primitive bounding box.
 *
 * Errors:
 *
 *  -1016  Internal error detected within GKS
 *    304  Input/Output error while sending data to a workstation
 *
 * Comments:
 *
 *  This routine uses the RAL GKS stack allocation routines for FORTRAN routine
 *  workspace and malloc() for C routine workspace.
 *
 *  The ww foreground colour,  dd->d_fore,  must be set to the fill area colour
 *  index and the ww default bitmap pointer ddbm must be set to the appropriate
 *  workstation bitmap before this routine is called.
 */


/*
 * Errors:
 *
 *     304 Input/Output error has occurred while sending data to a workstation
 *
 * Comments:
 *
 *  Renders the raster on the ww backing Pixmap using ??.
 *
 *  The raster data is stored in column major order,  but each line of the
 *  raster is stored as a column of the array and is therefore contiguous.
 */


/*
 * Comments:
 *
 *  Assumes that the default pointers have been properly configured with
 *  gk0xww_() or an equivalent.
 */


/*
 * draw vert line from (l,t) to (l,b) and ditto for -l
 */


/*
 * draw horiz line from (l,b) to (r,b) and ditto for -b
 */


/*
 * Scan conversion procedures to generate the set of points
 * which approximate the respective curve. A S Williams 20 Oct 81
 * Uses Bresenham's algorithm to compute pixel coordinates
 * which approximate a circle  centre (0,0) in the first octant
 * (E to SE) ie from (Radius,0) to (Radius/Sqrt(2),Radius/Sqrt(2).
 *
 * translated to C. Mark Martin @ RAL Jan 86.
 * and made to do whole solid circle. Apr 86

		|   /\
		|  /  \   <-----generates this octant only
		| /    |
	  ------|/-----|
		|
		|
		|

 */


/*
 * Uses Bresenham's algorithm to compute the pixel coordinates which
 * approximate the straight line from (0,0) to (dx,dy). Other starting
 * positions can obviously be achieved by applying a translation
 * in the routine Point
 */


/* !JUSETRICK=> box b not used */


/*
 * Comments:
 *
 *   Some UNIX systems do not support the same range of baud rates  as  in
 *   "bauds" below.  In particular,  the EXTA and EXTB entries may contain
 *   different values.
 *
 *   If "*ichan" is not connected to a terminal,  "*ittspd" will be set to
 *   zero.
 */


/*
 * Comments:
 *
 *   This routine does no error checking or reporting.
 *
 *  *lun    Fortran logical unit number (Input)
 *  *echo   Echo control (Input)    [logical]
 *  *purge  Purge control (Input)   [logical]
 *
 *  Always returns 0
 */


/*
 * Comments:
 *
 * This routine is called by GKIOOP() and GKIOCL().  It assumes that the GKS
 * break character will appear at most once in the terminal's special character
 * set.
 *
 * The logical unit whose number is passed in lun must be connected to a tty.
 *
 * Assumes the C implementation defaults to signed char.

 * *lun    - f77 logical unit number (Input)
 * *action - Modify/restore terminal characters (Input)

 */


/*
 * Check that an assumption is true.  If the TEST argument is true
 * (non-zero), then return immediately.  Otherwise, print the message
 * to stderr and exit with a non-zero (failure) status.  That is, this
 * is effectively an assert with better manners, and documentation of
 * where our possibly dubious processor assumptions are located.
 */


/*
 * Write out a number in hex.  `p' points to a Number which has a
 * `p->nbytes'-byte value in it.
 */


/*
 * Replacement nextafter functions.  These are NOT general
 * implementations of these functions: they work only for negative
 * IEEE floats (of either endianness), and always take the next after
 * in the direction of positive numbers.  They won't work for VAX
 * floats, for example (because while VAX integers are little-endian,
 * VAX floats are PDP-endian, with the sign bit in the middle, so
 * simply adjusting the aliased integer's LSB will make bigger changes
 * in the aliased float).  They work only as long as the sizes of the
 * aliasing types are indeed the same, so we check this.
 */


/* Return true/non-zero if using denormalized numbers throws a SIGFPE
   (Alphas do this). */


/* Helper for sigfpe_on_denormalized_test */


/* No need for this more elaborate, and less portable, declaration */
/* void num_trap_( int sig, int code, struct sigcontext *scp, char *addr ) */


/* Source function for reading a line of text from the input file. */


/* Append an F77 space-padded string to the VFS, removing trailing
   spaces. */


/* Sink function for writing out a link of text to the output file. */


/* Return the Fortran ID value for a given Grp structure. */
/* ------------------------------------------------------------------- */


/* Public workforce-related functions */
/* ---------------------------------- */


/* Private workforce-related functions */
/* ----------------------------------- */


/* Public pthreads wrapper functions */
/* --------------------------------- */


/*
 * Copy src to string dst of size siz.  At most siz-1 characters
 * will be copied.  Always NUL terminates (unless siz == 0).
 * Returns strlen(src); if retval >= siz, truncation occurred.
 */


/*
 * Appends src to string dst of size siz (unlike strncat, siz is the
 * full size of dst, not space left).  At most siz-1 characters
 * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
 * Returns strlen(src) + MIN(siz, strlen(initial dst)).
 * If retval >= siz, truncation occurred.
 */


/* Local support functions. */
/* ======================== */


/* Verify the supplied event type and return the corresponding index
   within the "handlers" and "types" arrays. */


/* Functions to set the corresponding tuning parameters in EMS
   and also to return EMS to its original state. Note that an
   ErrTune struct is passed in to the first function and will
   be filled in with original state. It is then passed to the
   restore function. */


/* Wait for access to the TCB. */


/*
*+
* Name:
*    v1_interface.c

* Purpose:
*    Wrapper function for stand-alone C functions that provide legacy
*    NDF V1 interface.

* Description:
*    This file wrappers that provide the NDF V1 interfaces for those
*    non-ADAM C functions that changed interface in going from V1 to V2.
*    This is for the benefit of legacy systems that have not yet updated
*    to V2.

* Copyright:
*    Copyright (C) 2018 East Asian Observatory
*    All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful,but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA
*     02110-1301, USA

* Authors:
*     DSB: David S Berry (EAO)

* History:
*     10-AUG-2018 (DSB):
*       Original version.

*-
*/


/*
*+
* Name:
*    v1_interface_adam.c

* Purpose:
*    Wrapper function for ADAM C functions that provide legacy NDF V1 interface.

* Description:
*    This file wrappers that provide the NDF V1 interfaces for those
*    ADAM C functions that changed interface in going from V1 to V2.
*    This is for the benefit of legacy systems that have not yet updated
*    to V2.

* Copyright:
*    Copyright (C) 2018 East Asian Observatory
*    All Rights Reserved.

*  Licence:
*     This program is free software; you can redistribute it and/or
*     modify it under the terms of the GNU General Public License as
*     published by the Free Software Foundation; either version 2 of
*     the License, or (at your option) any later version.
*
*     This program is distributed in the hope that it will be
*     useful,but WITHOUT ANY WARRANTY; without even the implied
*     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
*     PURPOSE. See the GNU General Public License for more details.
*
*     You should have received a copy of the GNU General Public License
*     along with this program; if not, write to the Free Software
*     Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA
*     02110-1301, USA

* Authors:
*     DSB: David S Berry (EAO)

* History:
*     10-AUG-2018 (DSB):
*       Original version.

*-
*/


/* A function to run in a secondary thread. */


/* end of PARAMETER translations */


/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**	Creates a subprocess with the refresh program running in it.
**
**  FORMAL PARAMETERS:
**
**	name:
**	    Name of image to run
**
**	argv:
**	    argument array
**
**  RETURN VALUE:
**
**      VMS status
**
**  DESIGN:
**
**	A temporary mail box is created and a subprocess created with the
**	mail box name as SYS$INPUT. The arguments are then written to the
**	mail box followed by an EOF.
**
**--
*/


/*
*+
*  Name:
*     cmpPrim

*  Purpose:
*     Enquire if component is primitive.
*
*  Synopsis:
*     void cmpPrim( HDSLoc *struc, const char *comp, hdsbool_t *prim, int *status )

*  Description:
*     An enquiry is made as to whether or not the structure component
*     is a primitive object.

*  Parameters:
*     struc
*        Locator associated with a structured data object.
*     comp
*        The component name of a primitive object contained in the structure.
*     prim
*        Whether or not the structure component is primitive.
*     status
*        Global status value.

*  Authors:
*     GSB: Graham Bell (EAO)

*  History:
*     07-MAY-2019 (GSB):
*        Original version, based on equivalent Fortran routine.
*-
*/


/*
 *+
 *  Name:
 *    datImportFloc

 *  Purpose:
 *    Import a Fortran HDS locator buffer into C

 *  Invocation:
 *    datImportFloc( const char flocator[DAT__SZLOC], int loc_length, HDSLoc **clocator, int * status);

 *  Description:
 *    This function should be used to convert a Fortran HDS locator
 *    (implemented as a string buffer) to a C locator struct.
 *    This function is also available via the
 *    HDS_IMPORT_FLOCATOR macro defined in hds_fortran.h.

 *  Arguments
 *    flocator = const char [DAT__SZLOC] (Given)
 *       Fortran character string buffer. Should be at least DAT__SZLOC
 *       characters long.
 *    loc_length = int (Given)
 *       Size of Fortran character buffer. Sanity check.
 *       Should be DAT__SZLOC.
 *    clocator = HDSLoc ** (Returned)
 *       Assigned to the C version of the Fortran locator.
 *       Must be NULL on entry. Memory is not allocated by this routine
 *       and the locator must not be annulled whilst the Fortran
 *       locator is still being used.
 *    status = int * (Given and Returned)
 *       Inherited status. Attempts to excecute even if status is not SAI__OK
 *       on entry.

 *  Authors:
 *    Tim Jenness (JAC, Hawaii)
 *    David Berry (JAC, Preston)
 *    Tim Jenness (Cornell)

 *  History:
 *    16-NOV-2005 (TIMJ):
 *      Initial version
 *    18-NOV-2004 (TIMJ):
 *      Rename from dat1_import_floc so that it can be made public for
 *      fortran wrappers.
 *    27-JAN-2006 (DSB):
 *      Attempt to execute even if status is set on entry.
 *    27-JAN-2006 (TIMJ):
 *      Slight reworking of DSB's patch, to allow the memory
 *      to be freed if dat1_import_floc failed to copy anything
 *      into the empty struct. Otherwise the uninitialised struct
 *      can cause real problems later on.
 *    23-FEB-2006 (TIMJ):
 *      Use starmem
 *    22-OCT-2010 (DSB):
 *      Return a NULL pointer without error if the supplied pointer is
 *      DAT__NOLOC.
 *    2014-09-07 (TIMJ):
 *      Complete rewrite. No long allocate and memcpy, just extract the
 *      pointer directly from the buffer.

 *  Notes:
 *    - A NULL pointer is returned if the supplied locator is DAT__NOLOC.
 *    - Does check the contents of the locator for validity to avoid
 *      uncertainty when receiving uninitialized memory.
 *    - The expectation is that this routine is used solely for C
 *      interfaces to Fortran library routines.
 *    - The locator returned by this routine has not been allocated
 *      independently. It is the same locator tracked by the Fortran
 *      layer. Do not annul this locator if the Fortran layer is still
 *      tracking it.

 *  See Also:
 *    - datExportFloc

 *  Copyright:
 *    Copyright (C) 2014 Cornell University.
 *    Copyright (C) 2010 Science & Technology Facilities Council.
 *    Copyright (C) 2005-2006 Particle Physics and Astronomy Research Council.
 *    All Rights Reserved.

 *  Licence:
 *     This program is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU General Public License as
 *     published by the Free Software Foundation; either version 2 of
 *     the License, or (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be
 *     useful, but WITHOUT ANY WARRANTY; without even the implied
 *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *     PURPOSE. See the GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public
 *     License along with this program; if not, write to the Free
 *     Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *     MA 02110-1301, USA

 *  Bugs:
 *     {note_any_bugs_here}

 *-
 */


/*
*+
*  Name:
*     cmpShape

*  Purpose:
*     Enquire component shape.
*
*  Synopsis:
*     void cmpShape( HDSLoc *struc, const char *comp, int maxdim,
*                    hdsdim dims[], int *actdim, int *status )

*  Description:
*     A shape enquiry is made for a structure component.

*  Parameters:
*     struc
*        Locator associated with a structured data object.
*     comp
*        The component name of a primitive object contained in the structure.
*     maxdim
*        Allocated size of dims[].
*     dims
*        Component dimensions.
*     actdim
*        Actual number of dimensions.
*     status
*        Global status value.

*  Authors:
*     GSB: Graham Bell (EAO)

*  History:
*     07-MAY-2019 (GSB):
*        Original version, based on equivalent Fortran routine.
*-
*/


/*
 *+
 *  Name:
 *    dat1_import_floc

 *  Purpose:
 *    Import a fortran HDS locator buffer into C

 *  Invocation:
 *    clocator = dat1_import_floc( const char flocator[DAT__SZLOC], int len, int * status);

 *  Description:
 *    This function should be used to convert a Fortran HDS locator
 *    (implemented as a string buffer) to a C locator struct.

 *  Arguments
 *    flocator = const char * (Given)
 *       Fortran character string buffer. Should be at least DAT__SZLOC
 *       characters long.
 *    len = int (Given)
 *       Size of Fortran character buffer. Sanity check.
 *    status = int * (Given and Returned)
 *       Inherited status. Attempts to execute even if status is not SAI__OK
 *       on entry.

 *  Returned Value:
 *    clocator = HDSLoc *
 *       C HDS locator corresponding to the Fortran locator.
 *       Should be freed by using datAnnul().

 *  Authors:
 *    Tim Jenness (JAC, Hawaii)
 *    David Berry (JAC, Preston)

 *  History:
 *    16-NOV-2005 (TIMJ):
 *      Initial version
 *    27-JAN-2006 (DSB)
 *      Attempt to execute even if status is set on entry.
 *    2014-09-07 (TIMJ):
 *      Complete rewrite to now extract pointer value from buffer. API change
 *      to return the pointer directly.

 *  Notes:
 *    - Does not check the contents of the locator for validity but does check for
 *      common Fortran error locators such as DAT__ROOT and DAT__NOLOC.
 *    - For internal usage by HDS only. The public version is datImportFloc.
 *    - Differs from the original HDS API in that it returns the locator.
 *    - Attempts to execute even if status is bad.
 *    - This change has been made to allow the struct to be extended without forcing
 *      a recompile when DAT__SZLOC changes.

 *  See Also:
 *    - datImportFloc
 *    - datExportFloc

 *  Copyright:
 *    Copyright (C) 2014 Cornell University
 *    Copyright (C) 2005 Particle Physics and Astronomy Research Council.
 *    All Rights Reserved.

 *  Licence:
 *     This program is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU General Public License as
 *     published by the Free Software Foundation; either version 2 of
 *     the License, or (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be
 *     useful, but WITHOUT ANY WARRANTY; without even the implied
 *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *     PURPOSE. See the GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public
 *     License along with this program; if not, write to the Free
 *     Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *     MA 02110-1301, USA

 *  Bugs:
 *     {note_any_bugs_here}

 *-
 */


/*=================================*/
/* datAlter - Alter size of object */
/*=================================*/


/*==============================================*/
/* datBasic - Map data (in basic machine units) */
/*==============================================*/


/*=====================================*/
/* datCcopy - copy one structure level */
/*=====================================*/


/*=======================================*/
/* datCctyp - construct _CHAR*nnn string */
/*=======================================*/


/*===========================================*/
/* datCell - Locate a "cell" (array element) */
/*===========================================*/


/*=================================================*/
/* datChscn - validate the supplied component name */
/*=================================================*/


/*==========================================*/
/* datClen - Obtain character string length */
/*==========================================*/


/*================================*/
/* datCoerc - coerce object shape */
/*================================*/


/*==============================================================*/
/* datDsame - See if 2 objects have the same data representation*/
/*==============================================================*/


/*============================================================*/
/* datDrep - Obtain primitive data representation information */
/*============================================================*/


/*===========================================================*/
/* datErmsg - Translate a status value into an error message */
/*===========================================================*/


/*================================*/
/* datFind - Find named component */
/*================================*/


/*===================================*/
/* datGetC - Read _CHAR primitive(s) */
/*===================================*/


/*=====================================*/
/* datGetD - Read _DOUBLE primitive(s) */
/*=====================================*/


/*======================================*/
/* datGetI - Read _INTEGER primitive(s) */
/*======================================*/


/*======================================*/
/* datGetK - Read _INT64 primitive(s) */
/*======================================*/


/*===================================*/
/* datGetW - Read _WORD primitive(s) */
/*===================================*/


/*===================================*/
/* datGetUW - Read _UWORD primitive(s) */
/*===================================*/


/*======================================*/
/* datGetL - Read _LOGICAL primitive(s) */
/*======================================*/


/*===================================*/
/* datGetR - Read _REAL primitive(s) */
/*===================================*/


/*======================================*/
/* datGet0C - Read scalar string value  */
/*======================================*/


/*======================================*/
/* datGet0D - Read scalar double value  */
/*======================================*/


/*=====================================*/
/* datGet0R - Read scalar float value  */
/*=====================================*/


/*=======================================*/
/* datGet0I - Read scalar integer value  */
/*=======================================*/


/*================================================*/
/* datGet0K - Read scalar 64-bit integer value  */
/*================================================*/


/*=============================================*/
/* datGet0W - Read scalar short integer value  */
/*=============================================*/


/*=============================================*/
/* datGet0UW - Read scalar unsigned short integer value  */
/*=============================================*/


/*=======================================*/
/* datGet0L - Read scalar logical value  */
/*=======================================*/


/*==================================*/
/* DAT_GET1C - Read 1D string array */
/*==================================*/


/*==================================*/
/* DAT_GET1D - Read 1D Double array */
/*==================================*/


/*==================================*/
/* DAT_GET1I - Read 1D Integer array */
/*==================================*/


/*============================================*/
/* DAT_GET1K - Read 1D 64-bit Integer array */
/*============================================*/


/*=========================================*/
/* DAT_GET1W - Read 1D Short Integer array */
/*=========================================*/


/*===================================================*/
/* DAT_GET1UW - Read 1D Unsigned Short Integer array */
/*===================================================*/


/*==================================*/
/* DAT_GET1R - Read 1D REAL array */
/*==================================*/


/*==================================*/
/* DAT_GET1L - Read 1D Logical array */
/*==================================*/


/*==================================*/
/* DAT_GETVC - Read vectorized 1D string array */
/*==================================*/


/*==========================================*/
/* DAT_GETVD - Read vectorized Double array */
/*==========================================*/


/*==========================================*/
/* DAT_GETVI - Read vectorized Integer array */
/*==========================================*/


/*==========================================*/
/* DAT_GETVK - Read vectorized Int64 array */
/*==========================================*/


/*==========================================*/
/* DAT_GETVR - Read vectorized REAL array */
/*==========================================*/


/*==========================================*/
/* DAT_GETVL - Read vectorized Logical array */
/*==========================================*/


/*======================================*/
/* datIndex - Index into component list */
/*======================================*/


/*===================================*/
/* datLen - Inquire primitive length */
/*===================================*/


/*=========================================================*/
/* datLock - Lock an object for use by the current thread. */
/*=========================================================*/


/*=======================================================================*/
/* datLocked - See of an object is locked for use by the current thread. */
/*=======================================================================*/


/*==================================*/
/* datMapC - Map _CHAR primitive(s) */
/*==================================*/


/*====================================*/
/* datMapD - Map _DOUBLE primitive(s) */
/*====================================*/


/*=====================================*/
/* datMapI - Map _INTEGER primitive(s) */
/*=====================================*/


/*=====================================*/
/* datMapK - Map _INT64 primitive(s) */
/*=====================================*/


/*=====================================*/
/* datMapL - Map _LOGICAL primitive(s) */
/*=====================================*/


/*==================================*/
/* datMapR - Map _REAL primitive(s) */
/*==================================*/


/*========================================*/
/* datMapN - Map primitive as N-dim array */
/*========================================*/


/*==================================*/
/* datMapV - Map vectorized primitive(s) */
/*==================================*/


/*==================================*/
/* datMould - Alter shape of object */
/*==================================*/


/*======================================*/
/* datMsg - store filename in EMS token */
/*======================================*/


/*===============================*/
/* datName - Enquire object name */
/*===============================*/


/*=========================================*/
/* datNcomp - Inquire number of components */
/*=========================================*/


/*===============================*/
/* datNew - Create new component */
/*===============================*/


/*============================================*/
/* datNewC - Create new _CHAR type component */
/*============================================*/


/*=======================================*/
/* datNew0 - Create new scalar component */
/*=======================================*/


/*===============================================*/
/* datNew0D - Create new scalar double component */
/*===============================================*/


/*================================================*/
/* datNew0I - Create new scalar integer component */
/*================================================*/


/*=========================================================*/
/* datNew0K - Create new scalar 64-bit integer component */
/*=========================================================*/


/*======================================================*/
/* datNew0W - Create new scalar short integer component */
/*======================================================*/


/*================================================================*/
/* datNew0UW - Create new scalar unsigned short integer component */
/*================================================================*/


/*=============================================*/
/* datNew0R - Create new scalar real component */
/*=============================================*/


/*================================================*/
/* datNew0L - Create new scalar logical component */
/*================================================*/


/*=======================================*/
/* datNew1 - Create new vector component */
/*=======================================*/


/*=======================================*/
/* datNew1C - Create new vector string  */
/*=======================================*/


/*=======================================*/
/* datNew1d - Create new vector double   */
/*=======================================*/


/*=======================================*/
/* datNew1I - Create new vector integer  */
/*=======================================*/


/*================================================*/
/* datNew1K - Create new vector 64-bit integer  */
/*================================================*/


/*=============================================*/
/* datNew1W - Create new vector short integer  */
/*=============================================*/


/*=======================================================*/
/* datNew1UW - Create new vector unsigned short integer  */
/*=======================================================*/


/*=======================================*/
/* datNew1L - Create new vector logical   */
/*=======================================*/


/*=======================================*/
/* datNew1R - Create new vector float   */
/*=======================================*/


/*====================================*/
/* datParen - Locate parent structure */
/*====================================*/


/*=====================================*/
/* datPrec - Enquire storage precision */
/*=====================================*/


/*====================================*/
/* datPrim - Enquire object primitive */
/*====================================*/


/*=========================================================*/
/* datPrmry - Set/Enquire primary/secondary locator status */
/*=========================================================*/


/*==================================*/
/* datPutC - Write _CHAR primitive */
/*==================================*/


/*====================================*/
/* datPutD - Write _DOUBLE primitives */
/*====================================*/


/*=====================================*/
/* datPutI - Write _INTEGER primitives */
/*=====================================*/


/*=====================================*/
/* datPutK - Write _INT64 primitives */
/*=====================================*/


/*=====================================*/
/* datPutW - Write _WORD primitives */
/*=====================================*/


/*====================================*/
/* datPutUW - Write _UWORD primitives */
/*====================================*/


/*==================================*/
/* datPutR - Write _REAL primitives */
/*==================================*/


/*=====================================*/
/* datPutL - Write _LOGICAL primitives */
/*=====================================*/


/*=======================================*/
/* datPut0C - Write scalar string value  */
/*=======================================*/


/*=======================================*/
/* datPut0D - Write scalar double value  */
/*=======================================*/


/*======================================*/
/* datPut0R - Write scalar float value  */
/*======================================*/


/*========================================*/
/* datPut0I - Write scalar integer value  */
/*========================================*/


/*========================================*/
/* datPut0I - Write scalar 64-bit integer value  */
/*========================================*/


/*==============================================*/
/* datPut0W - Write scalar short integer value  */
/*===============================================*/


/*========================================================*/
/* datPut0UW - Write scalar unsigned short integer value  */
/*========================================================*/


/*========================================*/
/* datPut0L - Write scalar logical value  */
/*========================================*/


/*========================================*/
/* datPut1C - Write 1D character array       */
/*========================================*/


/*========================================*/
/* datPut1D - Write 1D double array       */
/*========================================*/


/*========================================*/
/* datPut1I - Write 1D int array       */
/*========================================*/


/*========================================*/
/* datPut1K - Write 1D 64-bit int array */
/*========================================*/


/*===========================================*/
/* datPut1W - Write 1D short int array       */
/*===========================================*/


/*===============================================*/
/* datPut1UW - Write 1D unsigned short int array */
/*===============================================*/


/*========================================*/
/* datPut1R - Write 1D double array       */
/*========================================*/


/*========================================*/
/* datPut1L - Write 1D Logical/int array       */
/*========================================*/


/*================================================*/
/* datPutVD - Write vectorized double array       */
/*================================================*/


/*================================================*/
/* datPutVI - Write vectorized int array       */
/*================================================*/


/*================================================*/
/* datPutVI - Write vectorized int64 array       */
/*================================================*/


/*================================================*/
/* datPutVR - Write vectorized REAL/float array       */
/*================================================*/


/*================================================*/
/* datPutVL - Write vectorized Logical array       */
/*================================================*/


/*================================================*/
/* datPutVC - Write vectorized character array       */
/*================================================*/


/*========================================*/
/* datRef - Enquire object reference name */
/*========================================*/


/*===================================================*/
/* datRefct - Enquire container file reference count */
/*===================================================*/


/*=============================*/
/* datRenam - Rename an object */
/*=============================*/


/*================================*/
/* datReset - Reset object state */
/*================================*/


/*================================*/
/* datRetyp - Change object type */
/*================================*/


/*=================================*/
/* datShape - Enquire object shape */
/*=================================*/


/*===============================*/
/* datSize - Enquire object size */
/*===============================*/


/*================================*/
/* datSlice - Locate object slice */
/*================================*/


/*=================================*/
/* datState - Enquire object state */
/*=================================*/


/*=====================================*/
/* datStruc - Enquire object structure */
/*=====================================*/


/*===================================*/
/* datTemp - Create temporary object */
/*===================================*/


/*=========================================*/
/* datThere - Enquire component existence */
/*=========================================*/


/*===============================*/
/* datType - Enquire object type */
/*===============================*/


/*=============================================================*/
/* datUnlock - Unlock an object so another thread can lock it. */
/*=============================================================*/


/*==================================*/
/* datValid - Enquire locator valid */
/*==================================*/


/*==================================================*/
/* hdsCopy - Copy an object to a new container file */
/*==================================================*/


/*=================================*/
/* hdsErase - Erase container file */
/*=================================*/


/*===============================================================*/
/* hdsEwild - End a wild card search for HDS container files     */
/*===============================================================*/


/*================================*/
/* hdsFlush - Flush locator group */
/*=================================*/


/*===============================*/
/* hdsFree - Free container file */
/*===============================*/


/*==================================*/
/* hdsGroup - Enquire locator group */
/*==================================*/


/*=========================================*/
/* hdsGtune - Get HDS tuning parameter     */
/*=========================================*/


/*=========================================*/
/* hdsGtune - Get HDS status integers      */
/*=========================================*/


/*=================================*/
/* hdsLink - Link locator to group */
/*=================================*/


/*================================*/
/* hdsLock - Lock container file */
/*================================*/


/*====================================*/
/* hdsNew - Create new container file */
/*====================================*/


/*========================================*/
/* hdsOpen - Open existing container file */
/*========================================*/


/*===============================*/
/* hdsShow - Show HDS statistics */
/*===============================*/


/*===============================================*/
/* hdsState - Enquire the current state of HDS   */
/*===============================================*/


/*============================*/
/* hdsStop - Close down HDS   */
/*============================*/


/*==============================*/
/* hdsTrace - Trace object path */
/*==============================*/


/*========================================*/
/* hdsTune - Set HDS tuning parameter     */
/*========================================*/


/*=================================================================*/
/* hdsWild - Perform a wild-card search for HDS container files   */
/*=================================================================*/


/*=====================================================*/
/* hdsClose - Close container file (Obsolete routine!) */
/*=====================================================*/


/*===================================================================*/
/* hdsFind - Find an object (Fortran routine, requires hdsf library) */
/*===================================================================*/


/*======================================================================

  dat1InitialiseV4Mutex() - Called exactly once to initialise the mutex
  that is used to serialise calls to HDS V4 functions. Since internal HDS
  V4 functions sometimes call other top-level HDS V4 functions, this
  mutex needs to be recursive. This dynamic initialisation function is
  needed because some versions of OSX do not provide the pthreads macros
  needed to do static initialisation of recursive mutexes.

  ====================================================================== */


/*======================================================================
   Test if a specified file is an HDF file by looking at the first 8
   bytes. The first 8 bytes of an HDF file are always set to the
   advertised HDF magic number pattern.
  ====================================================================== */


/*
 *+
 *  Name:
 *    hdsDimC2F

 *  Purpose:
 *    Convert an array of hdsdim[] to F77_INTEGER_TYPE[]

 *  Invocation:
 *    outdims = hdsDimC2F( int ndim, const hdsdim dims[],
 *                         F77_INTEGER_TYPE fdims[DAT__MXDIM], int * status );

 *  Description:
 *    This function should be used to convert a an array of dimensions
 *    of type hdsdim to an array of dimensions suitable for Fortran
 *    usage. Returns a pointer to an array of F77_INTEGER_TYPE suitable
 *    for the Fortran routine and always fills the Fortran array.

 *  Arguments
 *    ndim = int (Given)
 *       Number of relevant dimensions. Should not exceed DAT__MXDIM.
 *    dims[] = const hdsdim (Given)
 *       Input dimensions to copy, of size ndim.
 *    fdims[DAT__MXDIM] = F77_INTEGER_TYPE (Given & Returned)
 *       Buffer space that can be used to store the copied dimensions.
 *       Will contain the dimensions even if the types for dims and
 *       fdims match.
 *    int *status = Given and Returned
 *       Inherited status. If set, this routine will return NULL.

 *  Return Value:
 *    outdims = F77_INTEGER_TYPE*
 *       Pointer to an array of Fortran integers containing the dimensions.

 *  Authors:
 *    Tim Jenness (JAC, Hawaii)
 *    Tim Jenness (Cornell University)

 *  History:
 *    11-JUL-2005 (TIMJ):
 *      Initial version
 *    2014-09-15 (TIMJ):
 *      To ensure that this routine can be used in the fortran
 *      interface we now always guarantee to fill fdims. This is a change of
 *      behavior but allows HDSDIM2INT to be removed from interfaces.

 *  Notes:
 *    - This routine is commonly used to copy the output of a C routine
 *      to a pre-existing Fortran buffer. This requires that fdims[] is
 *      filled regardless of type matching. If the types match then a
 *      fast memmove will be used to do the filling rather than a for loop.
 *    - Status will be set to bad if the C dimension can not fit into
 *      the corresponding Fortran integer.
 *    - The expectation is that this routine is used solely for C
 *      interfaces to Fortran library routines.
 *    - fdims is always filled, so the return value is now always fdims.
 *      It is retained for API compatibility.

 *  Copyright:
 *    Copyright (C) 2014 Cornell University.
 *    Copyright (C) 2006 Particle Physics and Astronomy Research Council.
 *    All Rights Reserved.

 *  Licence:
 *     This program is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU General Public License as
 *     published by the Free Software Foundation; either version 2 of
 *     the License, or (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be
 *     useful, but WITHOUT ANY WARRANTY; without even the implied
 *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *     PURPOSE. See the GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public
 *     License along with this program; if not, write to the Free
 *     Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *     MA 02110-1301, USA

 *  Bugs:
 *     {note_any_bugs_here}

 *-
 */


/*
 *+
 *  Name:
 *    hdsDimF2C

 *  Purpose:
 *    Convert an array of F77_INTEGER_TYPE[] to hdsdim[]

 *  Invocation:
 *    outdims = hdsDimF2C( int ndim, const F77_INTEGER_TYPE fdims[],
 *                         hdsdim cdims[DAT__MXDIM], int * status );

 *  Description:
 *    This function should be used to convert a an array of Fortran dimensions
 *    of type F77_INTEGER_TYPE to an array of dimensions suitable for HDS C
 *    usage. Returns a pointer to an array of hdsdim[] suitable
 *    for the C function.

 *  Arguments
 *    ndim = int (Given)
 *       Number of relevant dimensions. Should not exceed DAT__MXDIM.
 *    fdims[DAT__MXDIM] = const F77_INTEGER_TYPE (Given)
 *       Input dimensions to copy, of size ndim.
 *    cdims[] = hdsdim (Given)
 *       Buffer space that can be used to store the copied dimensions.
 *       Note that there is no guarantee that at exit this array will
 *       have been used.
 *    int *status = Given and Returned
 *       Inherited status. If set, this routine will return NULL.

 *  Return Value:
 *    outdims = hdsdim*
 *       Pointer to an array of HDS C integers containing the dimensions.

 *  Authors:
 *    Tim Jenness (JAC, Hawaii)

 *  History:
 *    12-JUL-2005 (TIMJ):
 *      Initial version

 *  Notes:
 *    - Only use the pointer returned by this routine. Do not
 *      assume that cdims[] will be filled since it may not be
 *      used if the type of hdsdim is the same as a F77_INTEGER_TYPE.
 *    - The expectation is that this routine is used solely for C
 *      interfaces to Fortran library routines or converting from Fortran
 *      to C.
 *    - A Fortran INTEGER will always fit in a hdsdim without overflow.

 *  Copyright:
 *    Copyright (C) 2006 Particle Physics and Astronomy Research Council.
 *    All Rights Reserved.

 *  Licence:
 *     This program is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU General Public License as
 *     published by the Free Software Foundation; either version 2 of
 *     the License, or (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be
 *     useful, but WITHOUT ANY WARRANTY; without even the implied
 *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *     PURPOSE. See the GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public
 *     License along with this program; if not, write to the Free
 *     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *     MA 02111-1307, USA

 *  Bugs:
 *     {note_any_bugs_here}

 *-
 */


/* Versions of the above functions that use F77_INTEGER8_TYPE to
   represent an hdsdim in Fortran rather than an F77_INTEGER_TYPE.
   These assume that an hdsdim is a 64 bit signed integer, so a simple
   copy is all that is needed. */


/*
*+
*  Name:
*     cmpPut1C

*  Purpose:
*     Write vector structure component values.

*  Synopsis:
*     void cmpPut1C( HDSLoc *struc, const char *comp,
*                    size_t nval, const char *values[], int *status )

*  Description:
*     This routine writes the values associated with a vector primitive
*     component of a structure. There is a routine for each access type,
*
*        cmpPut1D    double precision
*        cmpPut1R    real
*        cmpPut1I    integer
*        cmpPut1L    logical
*        cmpPut1C    character[*N]

*     If the object data type differs from the access type, then
*     conversion is performed.

*  Parameters:
*     struc
*        Locator associated with a structured data object.
*     comp
*        The component name of a primitive object contained in the structure.
*     nval
*        The number of values.
*     values
*        The values to be written.
*     status
*        Global status value.

*  Authors:
*     GSB: Graham Bell (EAO)

*  History:
*     07-MAY-2019 (GSB):
*        Original version, based on equivalent Fortran routine.

*-
*/


/*
*+
*  Name:
*     cmpSize

*  Purpose:
*     Component size enquiry.
*
*  Synopsis:
*     void cmpSize( HDSLoc *struc, const char *comp, size_t *size, int *status )

*  Description:
*     A size enquiry is made for a structure component.

*  Parameters:
*     struc
*        Locator associated with a structured data object.
*     comp
*        The component name of a primitive object contained in the structure.
*     size
*        Component size.
*     status
*        Global status value.

*  Authors:
*     GSB: Graham Bell (EAO)

*  History:
*     07-MAY-2019 (GSB):
*        Original version, based on equivalent Fortran routine.
*-
*/


/*
*+
*  Name:
*     cmpLen

*  Purpose:
*     Component length enquiry.
*
*  Synopsis:
*     void cmpLen( HDSLoc *struc, const char *comp, size_t *len, int *status)

*  Description:
*     A length enquiry is made for a structure component.

*  Parameters:
*     struc
*        Locator associated with a structured data object.
*     comp
*        The component name of a primitive object contained in the structure.
*     len
*        The number of bytes per element.
*     status
*        Global status value.

*  Authors:
*     GSB: Graham Bell (EAO)

*  History:
*     07-MAY-2019 (GSB):
*        Original version, based on equivalent Fortran routine.
*-
*/


/*
*+
*  Name:
*     cmpGet1C

*  Purpose:
*     Read vector structure component values.

*  Synopsis:
*     void cmpGet1C( HDSLoc *struc, const char *comp, size_t maxval, size_t bufsize,
*                    char *buffer, char *pntrs[], size_t *actval, int *status )

*  Description:
*     This routine reads the values associated with a vector primitive
*     component of a structure. There is a routine for each access type,
*
*        cmpGet1D    double precision
*        cmpGet1R    real
*        cmpGet1I    integer
*        cmpGet1L    logical
*        cmpGet1C    character[*N]

*     If the object data type differs from the access type, then
*     conversion is performed.

*  Parameters:
*     struc
*        Locator associated with a structured data object.
*     comp
*        The component name of a primitive object contained in the structure.
*     maxval
*        The size of pntrs.
*     bufsize
*        The size of buffer.
*     buffer
*        An array to receive the values.
*     pntrs
*        An array to be filled with pointers to the start of each string.
*     actval
*        The number of array elements read.
*     status
*        Global status value.

*  Authors:
*     GSB: Graham Bell (EAO)

*  History:
*     02-MAY-2019 (GSB):
*        Original version, based on equivalent Fortran routine.

*-
*/


/*
 *+
 *  Name:
 *    datExportFloc

 *  Purpose:
 *    Export from a C HDS Locator to a Fortran HDS locator

 *  Language:
 *    Starlink ANSI C

 *  Type of Module:
 *    Library routine

 *  Invocation:
 *    datExportFloc( HDSLoc** clocator, int free, int len, char flocator[DAT__SZLOC], int * status );

 *  Description:
 *    This function should be used to populate a Fortran HDS locator buffer
 *    (usually a Fortran CHARACTER string of size DAT__SZLOC) from a C HDS
 *    locator structure. This function is also available in the
 *    HDS_EXPORT_CLOCATOR macro defined in hds_fortran.h.

 *  Arguments:
 *    clocator = HDSLoc ** (Given and Returned)
 *       Pointer to the locator to be exported. See the "free" description below
 *       as to whether this locator will be annulled or not.
 *    free = int (Given)
 *       If true (1) the C locator is nulled out once the
 *       Fortran locator is populated. If false, the locator memory is not
 *       touched. Regardless, the locator itself is not annulled as it is
 *       now simply referenced from the Fortran.
 *    len = int (Given)
 *       Size of Fortran character buffer to receive the locator. Sanity check.
 *       Should be DAT__SZLOC.
 *    flocator = char [DAT__SZLOC] (Returned)
 *       Fortran character string buffer. Should be at least DAT__SZLOC
 *       characters long. If clocator is NULL, fills the buffer
 *       with DAT__NOLOC.
 *    status = int* (Given and Returned)
 *       Inherited status. If status is bad the Fortran locator will be
 *       filled with DAT__NOLOC. The memory associated with clocator will
 *       be freed if free is true regardless of status.

 *  Authors:
 *    TIMJ: Tim Jenness (JAC, Hawaii)
 *    TIMJ: Tim Jenness (Cornell)
 *    {enter_new_authors_here}

 *  History:
 *    16-NOV-2005 (TIMJ):
 *      Initial version
 *    18-NOV-2005 (TIMJ):
 *      Make semi public to allow other Fortran wrappers to use this function.
 *      Rename from dat1_export_floc to datExportFloc
 *    2014-09-07 (TIMJ):
 *      Rewrite to store the pointer (as string) directly in the Fortran
 *      string buffer rather than the contents of the struct.
 *     {enter_further_changes_here}

 *  Notes:
 *    - Fortran locator string must be preallocted. The C locator can be freed
 *    at the discretion of the caller. This simplifies code in the Fortran
 *    interface wrapper.
 *    - This routine is intended to be used solely for
 *    wrapping Fortran layers from C. "Export" means to export a native
 *    C locator to Fortran.
 *    - There is no Fortran eqiuvalent to this routine.
 *    - This routine differs from the previous HDS implementation in that the address
 *    of the supplied pointer is stored in the Fortran string buffer and not the contents
 *    of the struct. This is done to constrain the required size of the locator
 *    in Fortran to allow the locator structure to change without forcing a full recompile
 *    of everything.

 *  See Also:
 *    datImportFloc

 *  Copyright:
 *    Copyright (C) 2014 Cornell University
 *    Copyright (C) 2005 Particle Physics and Astronomy Research Council.
 *    All Rights Reserved.

 *  Licence:
 *     This program is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU General Public License as
 *     published by the Free Software Foundation; either version 2 of
 *     the License, or (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be
 *     useful, but WITHOUT ANY WARRANTY; without even the implied
 *     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *     PURPOSE. See the GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public
 *     License along with this program; if not, write to the Free
 *     Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *     MA 02110-1301, USA

 *  Bugs:
 *     {note_any_bugs_here}

 *-
 */


/* Configure HDS based on the given version number.  This includes
   setting the HDS-v4 tuning parameter 64BIT as appropriate for
   version 4 or 3. */


/* Parse tuning environment variables. Should only be called once the
   first time a tuning parameter is required */