My Project
 All Classes Files Functions Variables Enumerations Enumerator Friends Macros Pages
regmap.h
1 #ifndef regmap_h
2 #define regmap_h
3 
4 #include "hash.h"
5 #include "netbuf.h"
6 #include "input.h"
7 #include "output.h"
8 
9 #include "gcp/util/common/CoordAxes.h"
10 #include "gcp/util/common/Coord.h"
11 
12 #include <map>
13 
14 /* ***** PLEASE READ BEFORE MAKING MODIFICATIONS *****
15  * The following define must be incremented by 1 whenever a
16  * modification to the register map declarations makes
17  * the register template incompatible with older archived register
18  * maps. This number is recorded with archived register maps for
19  * subsequent comparison against the current value.
20  */
21 #define REGMAP_REVISION 1
22 
23 /*
24  * List supported addressing modes.
25  */
26 typedef enum {
27  ADDR_A16D08_O, /* A 16-bit address of an 8-bit-odd register */
28  ADDR_A24D08_O, /* A 24-bit address of an 8-bit-odd register */
29  ADDR_A32D08_O, /* A 32-bit address of an 8-bit-odd register */
30  ADDR_A16D08_EO, /* A 16-bit address of an 8-bit-even/odd register */
31  ADDR_A24D08_EO, /* A 24-bit address of an 8-bit-even/odd register */
32  ADDR_A32D08_EO, /* A 32-bit address of an 8-bit-even/odd register */
33  ADDR_A16D16, /* A 16-bit address of a 16-bit register */
34  ADDR_A24D16, /* A 24-bit address of a 16-bit register */
35  ADDR_A32D16, /* A 32-bit address of a 16-bit register */
36  ADDR_A16D32, /* A 16-bit address of a 32-bit register */
37  ADDR_A24D32, /* A 24-bit address of a 32-bit register */
38  ADDR_A32D32, /* A 32-bit address of a 32-bit register */
39  ADDR_A16D16_L, /* A 16-bit address of a 32-bit (aka longword) */
40  /* register to be read via two D16 transfers */
41  ADDR_A24D16_L, /* A 24-bit address of a 32-bit (aka longword) */
42  /* register to be read via two D16 transfers */
43  ADDR_A32D16_L, /* A 32-bit address of a 32-bit (aka longword) */
44  /* register to be read via two D16 transfers */
45  ADDR_DEFAULT /* A local 32-bit array of 32-bit integers */
46 } RegAddrMode;
47 
48 /*
49  * The following bit-mask enumerators are used to specify many of the
50  * characteristics of each register. When describing a register in
51  * a RegBlkTmpl template, the value of the flags member is either 0,
52  * or the bitwise OR of one or more of the following enumerators.
53  * Note that REG_READABLE and REG_WRITABLE are ignored for REG_LOCAL
54  * registers. Also note that when writing to unreadable vme registers,
55  * a copy of the written value is recorded in a software shadow
56  * register. This value will be returned on subsequent reads.
57  * REG_EXC should be used for registers that are used internally
58  * but shouldn't be archived. Note that reading from vme registers can
59  * sometimes have side-effects such as acknowledging an interrupt, so
60  * be careful to exclude such registers from the archive.
61  */
62 enum RegFlags {
63  REG_NONE = 0x0, // None of the following.
64  REG_COMPLEX = 0x1, // Include if register contains real,imaginary
65  // pairs Exclude if register contains only real
66  // values
67  REG_R = 0x4, // Include if the register's vme address is
68  // readable. Exclude to read written values from
69  // the shadow array.
70  REG_W = 0x8, // Include if the register's vme address is
71  // writable. Exclude if the register can't be
72  // written to.
73  REG_RW = REG_R | REG_W,
74  REG_PREAVG = 0x10, // Include for integrated registers. Exclude if
75  REG_POSTAVG = 0x20, // Include for integrated registers. Exclude if
76  REG_SUM = 0x40, // Include for integrated registers. Exclude if
77  // the register contains a snapshot value.
78  REG_UNION = 0x80, // Including this tells the archiver to
79  // integrate this register by taking the
80  // bit-mask union of the values of the register
81  // that are to be combined.
82  REG_EXC = 0x100, // Include to exclude the register from the
83  // archive. Exclude to include the register in
84  // the archive.
85  REG_UTC = 0x200, // Include for registers that represent times in
86  // UTC. Such registers must consist of one or
87  // more pairs of elements in which the first
88  // element contains a modified Julian day
89  // number, and the second element contains the
90  // corresponding time of day in milliseconds.
91  REG_PCI = 0x400, // A PCI register.
92  REG_BOOL = 0x800, // This register of single bytes
93  REG_CHAR = 0x1000, // This register of single bytes
94  REG_UCHAR = 0x2000, // This register of single bytes
95  REG_SHORT = 0x4000, // This register of shorts
96  REG_USHORT = 0x8000, // This register of shorts
97  REG_INT = 0x10000, // A register of ints
98  REG_UINT = 0x20000, // A register of ints
99  REG_FLOAT = 0x40000, // A register of floating point values
100  REG_DOUBLE = 0x80000, // A register of doubles
101  REG_DEFAULT = REG_UINT,// The default is a register of unsigned ints
102  // which should be summed together on integration
103  REG_DPRAM = 0x100000,// Include if this is a register on the PMAC's
104  // DPRAM. These registers will correspond to an
105  // actual memory space in the PMAC DPRAM, but
106  // are read and written over a serial
107  // connection. Internally these registers are
108  // read from and written to shadow registers.
109  REG_FAST = 0x200000,// Include for multidimensional registers
110  // where the fastest-changing axis is a time
111  // subsample
112 };
113 
114 /*
115  * The following bit-mask enumerators are used to specify many of the
116  * characteristics of each register. When describing a register in
117  * a RegBlkTmpl template, the value of the flags member is either 0,
118  * or the bitwise OR of one or more of the following enumerators.
119  * Note that REG_READABLE and REG_WRITABLE are ignored for REG_LOCAL
120  * registers. Also note that when writing to unreadable vme registers,
121  * a copy of the written value is recorded in a software shadow
122  * register. This value will be returned on subsequent reads.
123  * REG_EXC should be used for registers that are used internally
124  * but shouldn't be archived. Note that reading from vme registers can
125  * sometimes have side-effects such as acknowledging an interrupt, so
126  * be careful to exclude such registers from the archive.
127  */
128 typedef enum {
129  CBI_REG_DEFAULT = 0, /* None of the following */
130  CBI_REG_COMPLEX = 1, /* Include if register contains real,imaginary pairs */
131  /* Exclude if register contains only real values */
132  CBI_REG_SIGNED = 2, /* Include if register contains signed values (2s-comp) *\/
133  /* Exclude if register contains unsigned values */
134  CBI_REG_R_VME = 4, /* Include if the register's vme address is readable */
135  /* Exclude to read written values from the shadow array *\/
136  REG_W_VME = 8, /* Include if the register's vme address is writable */
137  /* Exclude if the register can't be written to */
138  CBI_REG_W_VME = 8, /* Include if the register's vme address is writable */
139  /* Exclude if the register can't be written to */
140  CBI_REG_RW_VME = CBI_REG_R_VME | CBI_REG_W_VME,
141 
142  CBI_REG_SUM = 16, /* Include for integrated registers */
143  /* Exclude if the register contains a snapshot value */
144  CBI_REG_UNION = 32, /* Including this tells the archiver to integrate */
145  /* this register by taking the bit-mask union of */
146  /* the values of the register that are to be combined. *\/
147  REG_EXC = 64, /* Include to exclude the register from the archive */
148  /* Exclude to include the register in the archive */
149  CBI_REG_EXC = 64, /* Include to exclude the register from the archive */
150  /* Exclude to include the register in the archive */
151  CBI_REG_UTC = 128 /* Include for registers that represent times in UTC. */
152  /* Such registers must consist of one or more pairs */
153  /* of elements in which the first element contains */
154  /* a modified Julian day number, and the second */
155  /* element contains the corresponding time of day in */
156  /* milliseconds. */
157 } CbiRegFlags;
158 
159 /*
160  * Record the locations at which VME address spaces are mapped
161  * into VxWorks memory.
162  */
163 #define VME_A16_BASE 0x0
164 #define VME_A24D16_BASE 0x0
165 #define VME_A24D32_BASE 0x0
166 #define VME_A32_BASE 0x0
167 
168 /*
169  * Set the max length of names of register blocks and boards.
170  */
171 #define REG_NAME_LEN 31
172 
173 /*
174  * Define type aliases for the structures that are being declared
175  * below.
176  */
177 typedef struct RegMapBlock RegMapBlock;
178 typedef struct RegMapBoard RegMapBoard;
179 typedef struct RegMap RegMap;
180 
181 /*
182  * Describe an array of registers.
183  */
184 struct RegMapBlock {
185  RegMapBoard* brd_; // The parent register board
186  unsigned number_; // The index of the block on its parent
187  // board
188  char name_[REG_NAME_LEN+1]; // The name of the block of registers
189  std::string* comment_; // Description of register
190  char axesHelp_[REG_NAME_LEN+1]; // Description of axis indices
191  unsigned flags_; // A bit-set of RegFlags enumerators
192  RegAddrMode addr_mode_; // The addressing mode of the register
193  unsigned location_; // The address of the first register in
194  // VxWorks address-space (0 for non-VME
195  // registers)
196  unsigned ireg_; // The sequential number of the first
197  // register
198  unsigned nreg_; // The total number of elements in the
199  // block
200  int slot_; // The start index of the block in the
201  // archive array (or -1 if [flags &
202  // REG_EXC != 0].
203 
204  gcp::util::CoordAxes* axes_;// An axis specifier for this register
205 
206  int iSlot_; // The sequential slot index of the
207  // first register in parent slot array
208  int iArcSlot_; // The sequential slot index of the
209  // first register in parent archived
210  // slot array
211  unsigned iByte_; // The sequential byte index of the
212  // first register in the parent register
213  // map
214  int iArcByte_; // The starting index of this block in
215  // the archive byte array, or -1 if this
216  // register is not archived
217  unsigned nBytePerEl_; // The number of bytes in each element
218  // of this register
219 
220  // Methods of the RegMapBlock struct
221 
222  // Constructors
223 
224  RegMapBlock();
225 
226  RegMapBlock(RegMapBoard* parent, void* tbrd, void* tblk,
227  unsigned iBlock, unsigned nper_brd_blocks);
228 
229  // Destructor
230 
231  ~RegMapBlock();
232 
233  // Return the number of bytes in this register block
234 
235  unsigned nByte();
236 
237  // Return the total number of elements in this register
238 
239  unsigned nEl();
240 
241  // Return the number of butes per element of this register
242 
243  unsigned nBytePerEl() {
244  return nBytePerEl_;
245  }
246 
247  // Return the offset, in bytes, of the requested element of this
248  // register in the register map archive array
249 
250  int byteOffsetInWholeRegMapOf(gcp::util::Coord* coord=0);
251  int byteOffsetInArcRegMapOf(gcp::util::Coord* coord=0);
252 
253  int byteOffsetInBoardOf(bool archivedOnly, gcp::util::Coord* coord=0);
254 
255  // Convenience method for the above
256 
257  int byteOffsetInRegMapOf(bool archivedOnly, gcp::util::Coord* coord=0) {
258  return archivedOnly ? byteOffsetInArcRegMapOf(coord) :
259  byteOffsetInWholeRegMapOf(coord);
260  }
261 
262  // Methods for returning the slot offset of an element of this
263  // register
264 
265  int slotOffsetInArcRegMapOf(gcp::util::Coord* coord=0) {
266  return (iArcSlot_ < 0) ? -1 : (int)(iArcSlot_ + elementOffsetOf(coord));
267  }
268 
269  int slotOffsetInWholeRegMapOf(gcp::util::Coord* coord=0) {
270  return iSlot_ + (int)elementOffsetOf(coord);
271  }
272 
273  // Return the start index of this block in the archived slot array
274 
275  int slotOffsetInRegMapOf(bool archivedOnly, gcp::util::Coord* coord=0) {
276  return archivedOnly ? slotOffsetInArcRegMapOf(coord) :
277  slotOffsetInWholeRegMapOf(coord);
278  }
279 
280  // Methods returning the element offset of the requested coordinate
281 
282  int elementOffsetOf(gcp::util::Coord* coord);
283 
284  // Return true if this block is archived
285 
286  bool isArchived();
287 
288  // Return true if the block type matches
289 
290  bool isBool()
291  {
292  return (flags_ & REG_BOOL);
293  }
294 
295  bool isChar()
296  {
297  return (flags_ & REG_CHAR);
298  }
299 
300  bool isUchar()
301  {
302  return (flags_ & REG_UCHAR);
303  }
304 
305  bool isUshort()
306  {
307  return (flags_ & REG_USHORT);
308  }
309 
310  bool isShort()
311  {
312  return (flags_ & REG_SHORT);
313  }
314 
315  bool isUint()
316  {
317  return (flags_ & REG_UINT);
318  }
319 
320  bool isInt()
321  {
322  return (flags_ & REG_INT);
323  }
324 
325  bool isFloat()
326  {
327  return (flags_ & REG_FLOAT);
328  }
329 
330  bool isDouble()
331  {
332  return (flags_ & REG_DOUBLE);
333  }
334 
335  bool isUtc()
336  {
337  return (flags_ & REG_UTC);
338  }
339 
340  bool isSummed(); // True if summed on integration
341  bool isUnioned(); // True if bitwise-unioned on integration
342  bool isPreAveraged(); // True if averaged on integration
343  bool isPostAveraged(); // True if averaged when read
344 
345  bool isComplex();
349  void checkConsistency();
350 
354  void checkType(unsigned flags);
355 
359  void checkIntegration(unsigned flags);
360 
364  void checkAttributes();
365 
366  friend std::ostream& operator<<(std::ostream& os, RegMapBlock& block);
367 };
368 
369 /*
370  * Collect registers that reside on a given board.
371  */
372 struct RegMapBoard {
373  RegMap *regmap; /* The parent register map */
374  unsigned number; /* The index of the board in the register map */
375  char name[REG_NAME_LEN+1]; /* An unambiguous name for the board */
376  std::string* comment_;
377  std::vector<RegMapBlock*> blocks; /* The registers of the board */
378  int nblock; /* The number of register blocks in blocks[] */
379 
380 #if USE_HASH
381  HashTable *hash; /* Symbol table of register blocks */
382 #else
383  std::map<std::string, RegMapBlock*> mapOfBlocks_;
384 #endif
385  unsigned nreg; /* The total number of registers on the board */
386  unsigned narchive; /* The number of archived registers on the board */
387 
388  unsigned nByte_;
389  unsigned nArcByte_;
390 
391  unsigned iSlot_; // The sequential index of the first
392  // register of this board in the parent
393  // register map slot array
394  int iArcSlot_; // The sequential index of the first
395  // register of this board in the parent
396  // archived slot array
397  unsigned iByte_; // The sequential index of the first byte
398  // of this board in the parent register map
399  int iArcByte_; // The sequential index of the first byte
400  // of this board in the archived parent
401  // register map
402 
403  // Return the byte offset of this board in the parent register map
404 
405  int byteOffsetInRegMap(bool archivedOnly) {
406  return archivedOnly ? iArcByte_ : iByte_;
407  }
408 
409  // Return the slot offset of this board in the parent register map
410 
411  int slotOffsetInRegMap(bool archivedOnly) {
412  return archivedOnly ? iArcSlot_ : iSlot_;
413  }
414 
415  // Return the number of bytes in this board
416 
417  unsigned nByte(bool archivedOnly) {
418  return archivedOnly ? nArcByte_ : nByte_;
419  }
420 
421  RegMapBoard();
422 
423  RegMapBoard(RegMap* parent, void* vbrd, unsigned iboard,
424  void* vper_brd_blocks, unsigned nper_brd_blocks);
425 
426  ~RegMapBoard();
427 
428  // Return the named register block
429 
430  RegMapBlock* findRegMapBlock(std::string blockName);
431 
432  // Return a vector of blocks matching the input string
433 
434  std::vector<RegMapBlock*> matchRegMapBlock(std::string regExpStr);
435 };
436 
437 /*
438  * Collect information about all boards.
439  */
440 struct RegMap {
441  unsigned ref_count_; // Reference counter
442  std::vector<RegMapBoard*> boards_; // All addressable boards
443  int nboard_; // The number of boards
444 #if USE_HASH
445  HashMemory *hash_mem_; // Memory for hash tables
446  HashTable *hash_; // Symbol table of boards
447 #else
448  std::map<std::string, RegMapBoard*> mapOfBoards_;
449 #endif
450  unsigned nreg_; // The total number of registers
451  unsigned narchive_; // The total number of archived registers
452  unsigned nByte_; // The size in bytes of all registers in
453  // this register map
454  unsigned nArcByte_; // The size in bytes of all archived
455  // registers in this register map
456 
457  // A constructor
458 
459  RegMap(void *regtmp, bool addDefaults=true);
460 
461  // Destructor
462 
463  ~RegMap();
464 
465  // Return the offset, in bytes_ of the named board and block from
466  // the start of the archived array
467 
468  int byteOffsetInArcRegMapOf(std::string board, std::string block,
469  gcp::util::Coord* coord=0);
470  int byteOffsetInWholeRegMapOf(std::string board, std::string block,
471  gcp::util::Coord* coord=0);
472 
473  // Convenience method for the above two
474 
475  int byteOffsetInRegMapOf(bool archivedOnly,
476  std::string board, std::string block,
477  gcp::util::Coord* coord=0) {
478  return archivedOnly ? byteOffsetInArcRegMapOf(board, block, coord) :
479  byteOffsetInWholeRegMapOf(board, block, coord);
480  }
481 
482  int byteOffsetInArcRegMapOf(RegMapBlock* blk, gcp::util::Coord* coord=0);
483  int byteOffsetInWholeRegMapOf(RegMapBlock* blk, gcp::util::Coord* coord=0);
484 
485  // Convenience method for the above two
486 
487  int byteOffsetInRegMapOf(bool archivedOnly,
488  RegMapBlock* blk,
489  gcp::util::Coord* coord=0) {
490  return archivedOnly ? byteOffsetInArcRegMapOf(blk, coord) :
491  byteOffsetInWholeRegMapOf(blk, coord);
492  }
493 
494  unsigned nByte() {return nByte_;};
495  unsigned nArcByte() {return nArcByte_;};
496 
497  // Convenience method for the above two
498 
499  int nByte(bool archivedOnly) {
500  return archivedOnly ? nArcByte() : nByte();
501  }
502 
503  // Find the named block
504 
505  RegMapBlock* findRegMapBlock(std::string board_name, std::string block_name,
506  bool booldoThrow=false);
507 };
508 
509 /* NB. new_RegMap() is prototyped in regtemplate.h */
510 
514 RegMap* del_RegMap(RegMap* regmap);
515 
516 /* Allocate a readonly alias to a given register map. */
517 /* When no longer required this should be discarded by calling */
518 /* del_RegMap(). */
519 
520 RegMap *alias_RegMap(RegMap *regmap);
521 
522 /* Return non-zero if two register maps are equivalent. */
523 
524 int equiv_RegMap(RegMap *regmap1, RegMap *regmap2);
525 
526 RegMapBoard *find_RegMapBoard(RegMap *regmap, std::string board_name);
527 RegMapBlock *find_RegMapBoard_Block(RegMapBoard *board, std::string block_name);
528 RegMapBlock *find_RegMapBlock(RegMap *regmap, std::string board_name,
529  std::string block_name);
530 
531 /*
532  * Enumerate the register-specifications read by input_RegMapReg().
533  * The comment next to each mode indicates the type of input expected,
534  * where "board" is the name of a board, "register" is the name of
535  * a block of registers, and index is the sequential number of
536  * a register within a block.
537  */
538 typedef enum {
539  REG_INPUT_BLOCK, /* board.register */
540  REG_INPUT_ELEMENT, /* board.register[index] */
541  REG_INPUT_RANGE /* board.register[index-index] */
542 } RegInputMode;
543 
544 /*
545  * When the extend argument of input_RegMapReg() is true, and a complex or
546  * utc register-pair specification is read, a member of the following type
547  * is used to record what aspect of the complex register has been selected
548  * by the user. If the user doesn't specify anything then REG_PLAIN is
549  * substituted. Where appropriate these enumerators can be used as
550  * indexes of arrays of REG_NASPECT elements.
551  */
552 typedef enum {
553  REG_PLAIN, /* Treat complex register pairs as two registers */
554  REG_REAL, /* The real member of the complex register pair */
555  REG_IMAG, /* The imaginary member of the complex register pair */
556  REG_AMP, /* The amplitude of a complex register pair */
557  REG_PHASE, /* The phase of a complex register pair */
558  REG_DATE, /* The Modified Julian Date of a day/time utc pair */
559  REG_TIME /* The time-of-day of a day/time utc pair */
560 } RegAspect;
561 
562 enum {REG_NASPECT = 7}; /* The number of enumerators in RegAspect */
563 
564 char *name_RegAspect(RegAspect aspect);
565 
566 typedef enum {
567  REG_INT_PLAIN, // Treat the register normally
568  REG_INT_INT, // Integrate the register
569  REG_INT_DER // Take the derivative of the register
570 } RegInteg;
571 
572 enum {REG_NINTEG = 3}; /* The number of enumerators in RegInteg */
573 
574 char *name_RegInteg(RegInteg integ);
575 
576 /*
577  * A structure of the following form is filled by input_RegMapReg().
578  * The meanings of reg and nreg depend on the input mode as follows:
579  *
580  * REG_INPUT_BLOCK:
581  * index will be 0.
582  * slot will be the frame index of the first register of the block.
583  * nreg will be the number of registers in the block.
584  * REG_INPUT_ELEMENT:
585  * index will be the block index of the selected member of the block.
586  * slot will be the frame index of the selected member of the block.
587  * nreg will always be 1.
588  * REG_INPUT_RANGE:
589  * index will be the block index of the selected member of the block.
590  * slot will be the frame index of the first selected member of the block.
591  * nreg will be the number of registers in the range.
592  *
593  * Note that if the selected register is not an archived register, the
594  * slot index will be -1.
595  */
596 struct RegMapReg {
597  int board; // The index of the specified board in the
598  // register-map
599  int block; // The index of the specified block on the
600  // regmap board
601  unsigned index; // The block index of the first register
602  // specified
603  signed slot; // The frame index of the first register
604  // specified
605  unsigned nreg; // The number of registers specified. The
606  // associated regmap slots are: slot -> slot +
607  // nreg*size - 1
608  unsigned size; // The number of slots per register. This is 1
609  // unless aspect!=REG_PLAIN, in which case it
610  // becomes 2
611  RegAspect aspect; // The quantity to derive from complex or utc
612  // register pairs
613  RegInteg integ; // The integration status of this register
614  // register pairs
615  int iByte_; // The byte index into the register map of the
616  // first register specified
617  int iArcByte_; // The byte index into the archived register
618  // map of the first register specified
619  unsigned nBytePerEl_;// The number of bytes per element of this register
620 
621  gcp::util::CoordAxes* axes_; // An axis specifier for this register
622  gcp::util::CoordRange* range_; // An index-range specifier
623 };
624 
625 int find_RegMapReg(RegMap *regmap, std::string board_name, std::string block_name,
626  RegAspect facet, unsigned index, unsigned n,
627  RegMapReg *reg);
628 
629 int init_RegMapReg(RegMap *regmap, unsigned board, unsigned block,
630  unsigned index, unsigned nreg, RegAspect aspect,
631  RegMapReg *reg);
632 
633 typedef enum {
634  REG_VALID=0, /* A valid register was found */
635  REG_UNKNOWN, /* Valid specification syntax, but unknown register */
636  REG_INVALID /* Invalid register specification syntax */
637 } RegValidity;
638 
639 RegValidity input_RegMapReg(InputStream *stream, int tell, RegMap *regmap,
640  RegInputMode mode, int extend, RegMapReg *reg);
641 
642 /*
643  * Save a register specification in the form read by input_RegMapReg().
644  */
645 typedef enum {
646  REG_OUTPUT_BLOCK, /* board.register */
647  REG_OUTPUT_ELEMENT, /* board.register[index] */
648  REG_OUTPUT_RANGE /* board.register[index-index] */
649 } RegOutputMode;
650 
651 int output_RegMapReg(OutputStream *stream, RegMap *regmap, RegOutputMode mode,
652  RegMapReg *reg);
653 
654 void clr_RegMapReg(RegMapReg *reg);
655 
656 /*
657  * If registers are represented as 32-bit integers then we need a method
658  * to pack a string into an array of 32-bit integers. The following function
659  * does this.
660  */
661 int pack_int_string(char *string, int ndata, unsigned *data);
662 
663 /*
664  * Unpack a string that was previously packed by pack_int_string().
665  */
666 int unpack_int_string(unsigned *data, int ndata, int size, char *string);
667 
668 /*
669  * Unpack a string that was previously packed by pack_int_string() and
670  * then assigned to a parallel array of double.
671  */
672 int unpack_double_string(double *data, int ndata, int size, char *string);
673 
674 #endif
Definition: CoordAxes.h:25
Definition: hash.h:119
Definition: hash.h:76
Definition: input.h:87
Definition: Coord.h:21
Definition: CoordRange.h:20
Definition: output.h:40