1 /*
2      ccp4_parser.h: Headers for functions to read in and "parse" CCP4 keyworded input.
3      Copyright (C) 2001  CCLRC, Peter Briggs
4 
5      This library is free software: you can redistribute it and/or
6      modify it under the terms of the GNU Lesser General Public License
7      version 3, modified in accordance with the provisions of the
8      license to address the requirements of UK law.
9 
10      You should have received a copy of the modified GNU Lesser General
11      Public License along with this library.  If not, copies may be
12      downloaded from http://www.ccp4.ac.uk/ccp4license.php
13 
14      This program is distributed in the hope that it will be useful,
15      but WITHOUT ANY WARRANTY; without even the implied warranty of
16      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17      GNU Lesser General Public License for more details.
18 */
19 
20 /** @page cparser_page CParser library
21  *
22  * @verbatim
23 
24 <!-- ::INDEX_INFO::CParser library::Library::::C Software Library for CCP4-style parsing:::::::: -->
25 
26    @endverbatim
27  *
28  *  @section cparser_file_list File list
29 
30 <ul>
31 <li>ccp4_parser.h - contains details of the C/C++ API
32 </ul>
33 
34  *  @section cparser_overview Overview
35 
36 These functions do CCP4-style parsing, as used for processing keywords
37 of CCP4 programs, MTZ header records, etc.
38 
39  *  @section cparser_usage Usage
40 
41 The following code snippets illustrate how the functions might be used
42 to read from stdin:
43 <pre>
44 
45 int           ntok=0;
46 char          line[201],*key;
47 CCP4PARSERTOKEN * token=NULL;
48 CCP4PARSERARRAY * parser;
49 
50   parser = (CCP4PARSERARRAY *) ccp4_parse_start(20);
51   key   = parser->keyword;
52   token = parser->token;
53 
54   RC   = 0;
55   while (!RC) {
56 
57     line[0] = '\0';
58     ntok = ccp4_parser(line,200,parser,1);
59 
60     if (ntok < 1) {
61 
62       RC = 111;
63 
64     } else {
65 
66       if (ccp4_keymatch("MINDIST",key))  {
67 	if (ntok != 2) {
68 	  ccperror ( 1,"MINDIST requires a single numerical argument" );
69 	  RC = -100;
70 	} else {
71 	  minDist = token[1].value;
72         }
73       }	else  {
74 	printf ( "Unrecognised keyword \"%s\"\n",token[0].fullstring );
75 	RC = -118;
76       }
77     }
78   }
79 
80   ccp4_parse_end ( parser );
81 
82 </pre>
83 
84  *  @section cparser_examples Examples
85 
86 See the distributed programs <a href="../ncont.html">NCONT</a> and
87 <a href="../pdbcur.html">PDBCUR</a>.
88 
89  */
90 
91 /** @file ccp4_parser.h
92  *
93  *  @brief Functions to read in and "parse" CCP4-style keyworded input.
94  *
95  *  @author Peter Briggs
96  *  @date April 2001
97  */
98 
99 /*------------------------------------------------------------------*/
100 
101 /* Macro definitions */
102 
103 /*------------------------------------------------------------------*/
104 
105 #ifndef __CCP4_Parser__
106 #define __CCP4_Parser__
107 
108 /* rcsidhhh[] = "$Id$" */
109 
110 /* note order: these must be outside CCP4 namespace */
111 #include <stdio.h>
112 #include"ccp4_utils.h"
113 #include"ccp4_spg.h"
114 
115 /* Macro to make C functions callable from C++ */
116 #ifdef  __cplusplus
117 namespace CCP4 {
118 extern "C" {
119 typedef CSym::ccp4_symop ccp4_symop;
120 #endif
121 
122 /*------------------------------------------------------------------*/
123 
124 /* Structures and typedefs */
125 
126 /*------------------------------------------------------------------*/
127 
128 /* CCP4 Parser token
129    Construct to hold the information about a single token */
130 
131 typedef struct {
132   char   *fullstring;   /* Full string containing all of token */
133   char   word[5];       /* First four characters of token */
134   double value;         /* Equivalent numerical value */
135   int    isstring;      /* Flag: true if token is character string */
136   int    strlength;     /* Number of characters in whole token (strings only) */
137   int    isnumber;      /* Flag: true if token is number */
138   int    intdigits;     /* Number of 'digits' preceeding the decimal point
139 			   (numbers only) */
140   int    frcdigits;     /* Number of 'digits' after the decimal point (numbers
141 			   only) */
142   int    isquoted;      /* Flag: true if token is contained in quotes */
143   int    isnull;        /* Flag: true if token is null field */
144   int    ibeg,iend;     /* Begin and end character positions of token
145 			   in input line */
146 } CCP4PARSERTOKEN;
147 
148 /* CCP4 Parser array
149    Construct to hold the information about a parsed line */
150 
151 typedef struct {
152   /* "Public" members */
153   char   keyword[5];      /* Keyword (=token[1].token, uppercased) */
154   int    ntokens;         /* Number of tokens */
155   CCP4PARSERTOKEN *token; /* Array of tokens */
156   /* "Private" members */
157   FILE   *fp;             /* Pointer to an external command file */
158   int    maxtokens;       /* Maximum number of tokens allowed */
159   char   *delim;          /* List of delimiter characters */
160   char   *nulldelim;      /* List of null delimiter characters */
161   char   *comment;        /* List of comment characters */
162   double max_exponent;    /* Largest allowed exponent for numerical tokens */
163   double min_exponent;    /* Smallest allowed exponent for numerical tokens */
164 } CCP4PARSERARRAY;
165 
166 /*------------------------------------------------------------------*/
167 
168 /* Function Prototypes */
169 
170 /*------------------------------------------------------------------*/
171 
172 /* Core cparser functions */
173 
174 /** Initialise a CCP4PARSERARRAY to be used in subsequent calls to
175  *  ccp4_parser routines. The calling function must supply the maximum
176  *  number of tokens on a line (including continuation lines).
177  * @param maxtokens maximum number of tokens on a line
178  * @return pointer to a new CCP4PARSERARRAY structure
179  */
180 CCP4PARSERARRAY* ccp4_parse_start(const int maxtokens);
181 
182 /** Cleans up a CCP4PARSEARRAY after being used by ccp4_parse/
183    ccp4_parser functions.
184  * @param parsePtr pointer to a CCP4PARSERARRAY structure
185  * @return 0 on completion
186  */
187 int ccp4_parse_end(CCP4PARSERARRAY *parsePtr);
188 
189 int ccp4_parse_init_token(const CCP4PARSERARRAY *parsePtr, const int itok);
190 
191 int ccp4_parse_delimiters(CCP4PARSERARRAY *parsePtr, const char *delim,
192 				  const char *nulldelim);
193 
194 int ccp4_parse_comments(CCP4PARSERARRAY *parsePtr, const char *comment_chars);
195 
196 int ccp4_parse_maxmin(CCP4PARSERARRAY *parsePtr, const double max_exponent,
197 			      const double min_exponent);
198 
199 int ccp4_parse_reset(CCP4PARSERARRAY *parsePtr);
200 
201 int ccp4_parse(const char *line, CCP4PARSERARRAY *parser);
202 
203 /** The main function for parsing lines, either supplied or read
204  * from stdin.
205  * @param line pointer to a null-terminated string of characters,
206  * forming the input to be processed. On input can either be an empty
207  * string ("") which forces reading from stdin, or contain characters
208  * to be processed. On output "line" will be overwritten with the actual
209  * input line.
210  * @param n maximum number of characters that can be read into
211  * "line" i.e. the size of "line" in memory.
212  * @param parser pointer to a CCP4PARSERARRAY structure which will
213  * be used to hold the results of processing the input line.
214  * @param print flag controlling echoing of input lines to stdout.
215  * print=0: suppress echoing of lines to stdout. Otherwise echoing is
216  * turned on.
217  * @return Number of tokens found.
218  */
219 int ccp4_parser(char *line, const int n, CCP4PARSERARRAY *parser,
220 			const int print);
221 
222 /* External utility functions */
223 
224 /** Test whether two keywords are identical. Keywords are identical if
225  * they are the same up to the first four characters, independent of case.
226  * @param keyin1 keyword 1.
227  * @param keyin2 keyword 2.
228  * @return 1 if keywords keyin1 and keyin2 are "identical", 0 otherwise.
229  */
230 int ccp4_keymatch(const char *keyin1, const char *keyin2);
231 
232 /* Internal utility functions */
233 
234 /** Convert string to uppercase.
235  * @param str1 On exit str1 will contain uppercased copy of str2
236  * @param str2 Input string
237  * @return str1
238  */
239 char *strtoupper (char *str1, const char *str2);
240 
241 /** Convert string to lowercase.
242  * @param str1 On exit str1 will contain lowercased copy of str2
243  * @param str2 Input string
244  * @return str1
245  */
246 char *strtolower (char *str1, const char *str2);
247 
248 int strmatch (const char *str1, const char *str2);
249 
250 int charmatch(const char character, const char *charlist);
251 
252 int doublefromstr(const char *str, const double max_exp, const double min_exp,
253 			  double *valuePtr, double *intvaluePtr, int *intdigitsPtr,
254 			  double *frcvaluePtr, int *frcdigitsPtr,
255 			  double *expvaluePtr, int *expdigitsPtr);
256 
257 /** Convert symmetry operator as string to ccp4_symop struct.
258  * @param symchs_begin pointer to beginning of string
259  * @param symchs_end pointer to end of string (i.e. last character
260  *   is *(symchs_end-1) )
261  * @return pointer to ccp4_symop struct
262  */
263 ccp4_symop symop_to_rotandtrn(const char *symchs_begin, const char *symchs_end);
264 
265 /** Convert symmetry operator as string to matrix.
266  * This is Charles' version of symfr. Note that translations
267  * are held in elements [*][3] and [3][3] is set to 1.0
268  * @param symchs_begin pointer to beginning of string
269  * @param symchs_end pointer to end of string (i.e. last character
270  *   is *(symchs_end-1) )
271  * @param rot 4 x 4 matrix operator
272  * @return  NULL on error, final position pointer on success
273  */
274 const char * symop_to_mat4(const char *symchs_begin, const char *symchs_end, float *rot);
275 int symop_to_mat4_err(const char *symop);
276 ccp4_symop mat4_to_rotandtrn(const float rsm[4][4]);
277 /* This is Charles' version of symtr */
278 char *rotandtrn_to_symop(char *symchs_begin, char *symchs_end, const ccp4_symop symop);
279 void rotandtrn_to_mat4(float rsm[4][4], const ccp4_symop symop);
280 
281 /** Convert symmetry operator as matrix to string.
282  * This is Charles' version of symtr. Note that translations
283  * are held in elements [*][3] and [3][3] is set to 1.0
284  * @param symchs_begin pointer to beginning of string
285  * @param symchs_end pointer to end of string (i.e. last character
286  *   is *(symchs_end-1) )
287  * @param rsm 4 x 4 matrix operator
288  * @return pointer to beginning of string
289  */
290 char *mat4_to_symop(char *symchs_begin, char *symchs_end, const float rsm[4][4]);
291 
292 /** Convert symmetry operator as matrix to string in reciprocal space notation.
293  * This is Charles' version of symtr. Note that translations
294  * are held in elements [*][3] and [3][3] is set to 1.0
295  * @param symchs_begin pointer to beginning of string
296  * @param symchs_end pointer to end of string (i.e. last character
297  *   is *(symchs_end-1) )
298  * @param rsm 4 x 4 matrix operator
299  * @return pointer to beginning of string
300  */
301 char *mat4_to_recip_symop(char *symchs_begin, char *symchs_end, const float rsm[4][4]);
302 
303 #ifdef __cplusplus
304 }
305 }
306 #endif
307 
308 #endif  /* __CCP4_Parser__ */
309