1/*********************************************************************
2Copyright 2008, 2010 Sandia Corporation.  Under the terms of Contract
3DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
4retains certain rights in this software.
5
6Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions
8are met:
9
10* Redistributions of source code must retain the above copyright
11notice, this list of conditions and the following disclaimer.
12
13* Redistributions in binary form must reproduce the above copyright
14notice, this list of conditions and the following disclaimer in the
15documentation and/or other materials provided with the distribution.
16
17* Neither the name of Sandia Corporation nor the names of its
18contributors may be used to endorse or promote products derived from
19this software without specific prior written permission.
20
21THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
25OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32***********************************************************************/
33
34/* dakreorder.c */
35
36#include <stdio.h>
37#include <string.h>
38#include <stdlib.h>
39
40extern int NIDR_disallow_missing_start;
41extern void nidr_parse(const char*, FILE*);
42extern int nidr_save_exedir(const char*, int);
43extern FILE *nidrin;
44
45 static char *progname, version[];
46
47 static int
48report_version(void)
49{
50	printf("%s", version+1);
51	return 0;
52	}
53
54 static int
55usage(int rc)
56{
57	fprintf(rc ? stderr : stdout, "Usage: %s [options]"
58#ifdef NO_NIDR_keywds0
59	" specsum"
60#endif
61	" [infile [outfile]]\n\
62	to reorder DAKOTA input file infile (or stdin if infile is not given)\n\
63	to an order that permits simple parsing, with abbreviated keywords\n\
64	expanded to their full forms.\nOptions:\n\t"
65#ifndef NO_NIDR_keywds0
66	"-1 ==> put data for a keyword on one line\n\
67	-c ==> retain comments\n\
68	-j specsum ==> read grammer specification from file specsum\n\
69		(written by \"nidrgen -j specsum dakota.input.nspec\")\n\
70	-p ==> replace aliases by the \"preferred\" name\n\t"
71#endif
72	"-v ==> report version\n", progname);
73	return rc;
74	}
75
76 static int specadj(char*s);
77
78 int
79main(int argc, char **argv)
80{
81	FILE *f;
82	char buf[8], *b, *s;
83	int comkeep, oneline, prefer;
84
85	nidr_save_exedir(progname = *argv, 0); /* 0 ==> no $PATH adjustment */
86#ifdef NO_NIDR_keywds0
87	comkeep = oneline = prefer = 1;
88#else
89	comkeep = oneline = prefer = 0;
90#endif
91nextarg:
92	while((s = *++argv) && *s == '-') {
93		for(;;)
94			switch(*++s) {
95			  case 0: goto nextarg;
96#ifndef NO_NIDR_keywds0
97			  case '1': ++oneline; continue;
98			  case 'c': ++comkeep; continue;
99			  case 'j': if (*++s || (s = *++argv)) {
100					if (specadj(s))
101						return 1;
102					goto nextarg;
103					}
104				    goto usage1;
105			  case 'p': ++prefer;  continue;
106#endif
107			  case 'h': return usage(!s[1] || !strcmp(s,"help") ? 0 : 1);
108#ifdef NIDR_DYLIB_DEBUG
109				/* -s is a debugging option, not mentioned in usage() */
110			  case 's': nidr_set_strict(1); goto nextarg;
111#endif
112			  case 'v': return report_version();
113			  case '?': return usage(s[1] != 0);
114			  case '-': if (!s[1]) {
115					s = *++argv;
116					goto optsdone;
117					}
118				if (!strcmp(s,"-help"))
119					return usage(0);
120				if (!strcmp(s,"-version"))
121					return report_version();
122			  usage1:
123			  default:  return usage(1);
124			  }
125		}
126 optsdone:
127	/* default nidrin (set by nidr-scanner) is stdin */
128	f = stdout;
129	NIDR_disallow_missing_start = 0;
130#ifdef NO_NIDR_keywds0
131	if (!s || specadj(s))
132		return usage(1);
133	s = *++argv;
134#endif
135	if (s) {
136		if (argv[1] && argv[2])
137			return usage(1);
138		if (!(nidrin = fopen(s,"r"))) {
139			fprintf(stderr, "%s: Cannot open input file \"%s\"\n",
140				progname, s);
141			return 1;
142			}
143		if ((b = argv[1]) && !(f = fopen(b, "w"))) {
144			fprintf(stderr, "%s: Cannot open output file \"%s\"\n", progname, b);
145			return 1;
146			}
147		}
148	b = buf;
149	if (oneline + comkeep + prefer) {
150		*b++ = '-';
151		if (oneline)
152			*b++ = '1';
153		if (comkeep)
154			*b++ = 'c';
155		if (prefer)
156			*b++ = 'p';
157		*b = 0;
158		}
159	nidr_parse(buf, f);
160	return 0;
161	}
162
163#include "nidr.h"
164
165#ifdef NO_NIDR_keywds0
166KeyWord Dakota_Keyword_Top = {"KeywordTop"};
167 static char version[] = "\ndakreord version YYYYMMDD\n";
168#else
169#include "NIDR_keywds0.h"
170 static char version[] = "\ndakreorder version " NSPEC_DATE "\n";
171#endif
172
173 static void*
174Malloc(size_t len)
175{
176	void *rv = malloc(len);
177	if (!rv) {
178		fprintf(stderr, "%s:  malloc(%lu) failure!\n",
179			progname, (unsigned long)len);
180		exit(1);
181		}
182	return rv;
183	}
184
185 static void
186swap4(void *v)
187{
188	int c;
189	char *s = (char*)v;
190	c = s[3];
191	s[3] = s[0];
192	s[0] = c;
193	c = s[2];
194	s[2] = s[1];
195	s[1] = c;
196	}
197
198 static void
199swap8(void *v)
200{
201	int c;
202	char *s, *t;
203	s = (char*)v;
204	t = s + 7;
205	do {
206		c = *s;
207		*s++ = *t;
208		*t-- = c;
209		} while(s < t);
210	}
211
212 static int
213specadj(char *specsum)
214{
215	FILE *f;
216	KeyWord *kw, *kw0;
217	KwpHead head;
218	Kwpack *p, *p0;
219	Kwpack0 *q;
220	Uint *u, *u0;
221	const char *strtab;
222	double *d, *fptab;
223	int swap;
224	size_t L, L1;
225
226	f = fopen(specsum, "rb");
227	if (!f) {
228		fprintf(stderr, "%s:  cannot open \"%s\"\n", progname, specsum);
229		return 1;
230		}
231	fread(&head, sizeof(head), 1, f);
232	swap = 0;
233	if (head.bkind != 0x1234abcd) {
234		swap4(&head.bkind);
235		if (head.bkind != 0x1234abcd) {
236 badfile:
237			fprintf(stderr, "%s:  invalid specsum file \"%s\"\n",
238				progname, specsum);
239			return 1;
240			}
241		swap8(&head.fpkind);
242		swap = 1;
243		swap4(&head.nkw);
244		swap4(&head.strtab_offset);
245		swap4(&head.kw_offset);
246		swap4(&head.end_offset);
247		}
248	if (head.fpkind != 1e13)
249		goto badfile;
250	L = head.end_offset;
251	L1 = head.kw_offset + (head.nkw+1)*sizeof(KeyWord);
252	if (L1 < L)
253		L1 = L;
254	fptab = (double*)Malloc(L1);
255	fread(fptab, L, 1, f);
256	fclose(f);
257	p = p0 = (Kwpack*)((char*)fptab + head.kw_offset);
258	strtab = (const char*)fptab + head.strtab_offset;
259	kw0 = (KeyWord*)p;
260	kw = ++kw0 + head.nkw;
261	p += head.nkw;
262	if (head.pad == 0) {
263		q = (Kwpack0*)p0 + head.nkw;
264		p = (Kwpack*)q;
265		}
266	if (swap) {
267		u0 = (Uint*)p0;
268		u = (Uint*)p;
269		while(u > u0)
270			swap4(--u);
271		d = fptab + head.strtab_offset/sizeof(double);
272		while(d > fptab)
273			swap8(--d);
274		}
275	if (head.pad == 0)
276		while(kw > kw0) { /* no DYNLIB data */
277			--kw;
278			--q;
279			kw->name = q->name ? strtab + q->name : 0;
280			kw->kind = q->kind;
281			kw->nkw = q->nkw;
282			kw->alt = q->alt;
283			kw->req = q->req;
284			kw->kw = q->kw ? kw0 + q->kw : 0;
285			kw->Lb = fptab[q->Lb];
286			kw->Ub = fptab[q->Ub];
287			kw->paoff = q->poff;
288			kw->f.start = kw->f.final = 0;
289			kw->f.vs = kw->f.vf = 0;
290			kw->comment = 0;
291			kw->kwnext = 0;
292			}
293	else
294		while(kw > kw0) {
295			--kw;
296			--p;
297			kw->name = p->name ? strtab + p->name : 0;
298			kw->kind = p->kind;
299			kw->nkw = p->nkw;
300			kw->alt = p->alt;
301			kw->req = p->req;
302			kw->kw = p->kw ? kw0 + p->kw : 0;
303			kw->Lb = fptab[p->Lb];
304			kw->Ub = fptab[p->Ub];
305			kw->paoff = p->poff;
306			kw->f.start = kw->f.final = 0;
307			kw->f.vs = kw->f.vf = 0;
308			kw->comment = 0;
309			kw->kwnext = 0;
310			if (kw->kind & KWKind_Dynlib)
311				kw->f.vf = (void*)(strtab + p->dylib);
312			}
313	kw = &Dakota_Keyword_Top;
314	kw->nkw = kw0->nkw;
315	kw->kw = kw0->kw;
316	kw->alt = kw0->alt;
317	kw->req = kw0->req;
318	return 0;
319	}
320