SDDSlib
Loading...
Searching...
No Matches
sddsprintout.c
1/*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * This file is distributed subject to a Software License Agreement found
7 * in the file LICENSE that is included with this distribution.
8\*************************************************************************/
9
10/* program: sddsprintout
11 * purpose: make a printout from SDDS data
12 *
13 * Michael Borland, 1995
14 $Log: not supported by cvs2svn $
15 Revision 1.47 2009/08/05 15:35:23 soliday
16 Updated to replace ld and lu in the format strings with PRId32 and PRIu32
17
18 Revision 1.46 2009/08/04 19:46:09 soliday
19 Updated to convert %ld format strings to %d for 64 bit systems.
20
21 Revision 1.45 2008/08/06 20:46:49 soliday
22 Fixed the format strings.
23
24 Revision 1.44 2008/06/06 18:10:32 soliday
25 Fixed a problem with one of the elements has the maximum number of characters
26 that SDDS will allow.
27
28 Revision 1.43 2006/10/19 17:55:40 soliday
29 Updated to work with linux-x86_64.
30
31 Revision 1.42 2006/08/31 15:08:55 soliday
32 Updated to work with SDDS2.
33
34 Revision 1.41 2005/11/04 22:46:17 soliday
35 Updated code to be compiled by a 64 bit processor.
36
37 Revision 1.40 2004/04/21 20:07:52 shang
38 the program will exit if checking datatype with format fails
39
40 Revision 1.39 2004/01/08 03:33:46 borland
41 Added escaping of latex output strings so that special characters don't
42 cause latex processing problems.
43
44 Revision 1.38 2004/01/06 20:11:25 borland
45 Added cpation to latex table output.
46
47 Revision 1.37 2003/12/03 00:11:17 borland
48 Added -latexFormat option for output of a LaTeX table.
49
50 Revision 1.36 2002/12/11 21:39:15 borland
51 Provided a slight speedup in processing large files when no columns
52 are printed by using SDDS_ReadPageSparse().
53
54 Revision 1.35 2002/08/14 17:12:51 soliday
55 Added Open License
56
57 Revision 1.34 2002/07/25 00:12:40 borland
58 Now check return values from SDDS_SprintTypedValue().
59
60 Revision 1.33 2001/09/05 20:16:34 shang
61 added cvs feature to -spreadsheet option, which has the same function as
62 -spreadsheet=quote=\",delimiter=\\, -notitle. And modified the default format
63 output to be the actual format when csv option is given.
64
65 Revision 1.32 2001/01/10 19:35:43 soliday
66 Standardized usage message.
67
68 Revision 1.31 2000/04/13 19:51:20 soliday
69 Added missing include statement.
70
71 Revision 1.30 1999/08/11 17:50:29 borland
72 Added -bufferlines option for putting blank lines between pages.
73
74 Revision 1.29 1999/05/25 19:13:30 soliday
75 Removed compiler warning on linux.
76
77 Revision 1.28 1999/01/06 19:54:51 borland
78 Fixed the version number in the usage message.
79
80 Revision 1.27 1998/08/24 14:42:10 soliday
81 Fixed bug when fromPage and toPage options are both used
82
83 Revision 1.26 1998/08/21 20:58:52 soliday
84 Added a noLabels option that works with columns and parameters
85
86 Revision 1.25 1996/11/15 00:30:30 borland
87 Added option to generate SCH file for spreadsheet output.
88
89 Revision 1.24 1996/11/15 00:15:17 borland
90 Added quote-mark and label control for spreadsheet mode.
91
92 Revision 1.23 1996/11/12 20:45:16 borland
93 Fixed bug with reuse of buffer used for edited column label.
94
95 Revision 1.22 1996/11/11 20:11:02 borland
96 Removed statements that added spaces after each field, as they aren't needed
97 with new format string padding. Added sensitivity to spreadsheet mode for
98 format string modification routine.
99
100 Revision 1.21 1996/11/11 18:43:26 borland
101 Some debugging statements added.
102
103 Revision 1.20 1996/11/07 22:18:22 borland
104 Better handling of field width adjustments for long labels. Now modifies
105 user or default format string to fill available space, rather than trying
106 to do symmetric space padding.
107
108 * Revision 1.19 1996/07/05 16:09:49 borland
109 * Removed routine cleanUpQuotes and started using SDDS_PRINT_NOQUOTES
110 * mode to SDDS_SprintTypedValue. Also, detects blank string data
111 * and substitutes " " to get proper filling of field.
112 *
113 * Revision 1.18 1996/05/13 20:33:58 borland
114 * Added -postPageLines option to allow putting blank lines after a page.
115 *
116 * Revision 1.17 1996/02/29 18:20:00 borland
117 * Added -noWarnings option, and implemented in all relevant subroutines.
118 *
119 * Revision 1.16 1996/02/21 16:08:38 borland
120 * For spreadsheet output, now set width=0 and use this to flag no line breaks
121 * for a row. User may reset width using -width option to get old behavior,
122 * though I doubt anyone will.
123 *
124 * Revision 1.15 1996/02/14 01:05:33 borland
125 * Changed over from scan_item_list() to scanItemList().
126 *
127 * Revision 1.14 1996/02/07 18:13:25 borland
128 * checkPagination now initializes currentLine to 0 rather than 1, which gets
129 * the right number of lines per page.
130 *
131 * Revision 1.13 1996/02/07 17:43:19 borland
132 * Added initialization for currentLine field of PAGINATION structure.
133 *
134 * Revision 1.12 1996/02/05 23:57:06 borland
135 * Added -pagination option.
136 *
137 * Revision 1.11 1996/01/29 22:28:42 borland
138 * Added editLabel qualifier to -column and -parameter options.
139 *
140 * Revision 1.10 1996/01/12 19:03:13 borland
141 * Added -spreadsheet option.
142 *
143 * Revision 1.9 1995/09/25 16:37:13 borland
144 * Modified header code for column output to eliminate units line if all units
145 * are blank.
146 *
147 * Revision 1.8 1995/09/18 17:26:01 borland
148 * Added label qualifers to -parameter and -column options.
149 *
150 * Revision 1.7 1995/09/15 21:31:40 borland
151 * Added -title option, and changed -noHeader option to -noTitle.
152 *
153 * Revision 1.6 1995/09/15 15:24:00 borland
154 * Added useDefaultFormat qualifer to -column and -parameter options. Added
155 * code to ensure use of any format_string defined in the SDDS file before
156 * any other string.
157 *
158 * Revision 1.5 1995/09/14 22:01:05 borland
159 * Added blankLines qualifier to -parameter and -column options.
160 *
161 * Revision 1.4 1995/09/14 04:28:00 borland
162 * Added -noHeader option to allow elimination of header on first page of
163 * printout.
164 *
165 * Revision 1.3 1995/09/06 14:56:57 saunders
166 * First test release of SDDS1.5
167 *
168 */
169#include <ctype.h>
170#include "mdb.h"
171#include "SDDS.h"
172#include "scan.h"
173#include "hashtab.h"
174/*#include "SDDSaps.h"*/
175
176#define SET_COLUMNS 0
177#define SET_PARAMETERS 1
178#define SET_ARRAYS 2
179#define SET_FROMPAGE 3
180#define SET_TOPAGE 4
181#define SET_FORMATDEFAULTS 5
182#define SET_WIDTH 6
183#define SET_PIPE 7
184#define SET_PAGEADVANCE 8
185#define SET_NOTITLE 9
186#define SET_TITLE 10
187#define SET_SPREADSHEET 11
188#define SET_PAGINATE 12
189#define SET_NOWARNINGS 13
190#define SET_POSTPAGELINES 14
191#define SET_NOLABELS 15
192#define SET_BUFFERLINES 16
193#define SET_LATEXFORMAT 17
194#define SET_HTMLFORMAT 18
195#define N_OPTIONS 19
196
197char *option[N_OPTIONS] = {
198 "columns", "parameters", "arrays", "frompage", "topage",
199 "formatdefaults", "width", "pipe", "pageadvance", "notitle", "title",
200 "spreadsheet", "paginate", "nowarnings", "postpagelines", "nolabels",
201 "bufferlines", "latexformat", "htmlformat"};
202
203char *USAGE = "sddsprintout [<SDDSinput>] [<outputfile>] [-pipe=[input][,output]] \n\
204[-columns[=<name-list>[,format={<string>|@<columnName>}][,label=<string>][,editLabel=<command>][,useDefaultFormat][,endsline][,blankLines=<number>]][,factor=<value>][,nounits]] \n\
205[-parameters[=<name-list>[,format={<string>|@<parameterName>}][,label=<string>][,editLabel=<command>][,useDefaultFormat][,endsline][,blankLines=<number]][,factor=<value>]] \n\
206[-array[=<name-list>[,format=<string>]] \n\
207[-fromPage=<number>] [-toPage=<number>] \n\
208[-formatDefaults=<SDDStype>=<format-string>[,...]]\n\
209[-width=<integer>] [-pageAdvance] [-paginate[=lines=<number>][,notitle][,nolabels]]\n\
210[-noTitle] [-title=<string>] [-noLabels] [-postPageLines=<number>]\n\
211[-spreadsheet[=delimiter=<string>][,quotemark=<string>][,nolabels][,csv][,schfile=<filename>]]\n\
212[-latexFormat[=longtable][,booktable][,sideways][,label={<string>|@<parameterName>}][,caption={<string>|@<parameterName>}][,group=<columnName>][,translate=<filename>][,justify=<codeList>][,complete][,comment=<string>]]\n\
213[-htmlFormat[=caption=<string>][,translate=<filename>]]\n\
214[-noWarnings]\n\
215-spreadsheet=csv is the simple way of -spreadsheet=nolabels,quote=\",delimiter=\\, -notitle \n\
216Translation file for LaTeX mode has columns OldName and NewName, and can be used to translate symbols and units.\n\n\
217Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
218
219#define PAGINATION_ON 0x0001U
220#define PAGINATION_NOTITLE 0x0002U
221#define PAGINATION_NOLABELS 0x0004U
222
223#define LATEX_FORMAT 0x0001UL
224#define LATEX_LONGTABLE 0x0002UL
225#define LATEX_BOOKTABLE 0x0004UL
226#define LATEX_LABEL 0x0008UL
227#define LATEX_CAPTION 0x0010UL
228#define LATEX_GROUP 0x0020UL
229#define LATEX_TRANSLATE 0x0040UL
230#define LATEX_SIDEWAYS 0x0080UL
231#define LATEX_JUSTIFY 0x0100UL
232#define LATEX_COMPLETE 0x0200UL
233#define LATEX_COMMENT 0x0400UL
234#define LATEX_LABEL_PARAM 0x0800UL
235#define LATEX_CAPTION_PARAM 0x1000UL
236
237#define HTML_FORMAT 0x0001U
238#define HTML_CAPTION 0x0002U
239#define HTML_TRANSLATE 0x0004U
240
241typedef struct
242{
243 int32_t lines;
244 long currentLine;
245 unsigned long flags;
246} PAGINATION;
247
248#define ENDSLINE 0x0001U
249#define USEDEFAULTFORMAT 0x0002U
250#define LABEL_GIVEN 0x0004U
251#define EDITLABEL_GIVEN 0x0008U
252#define FACTOR_GIVEN 0x0010U
253#define NO_UNITS 0x0020U
254
255typedef struct
256{
257 char *name, *format, **header, *label, *editLabel;
258 long fieldWidth, index, headers, type, endsLine, blankLines, useDefaultFormat, noUnits;
259 double factor;
260 void *data;
262
263typedef struct
264{
265 char *name, *format, *label, *editLabel;
266 long fieldWidth, index, type, endsLine, blankLines, useDefaultFormat;
267 double factor;
268 void *data;
270
271typedef struct
272{
273 char *name, *format, *label;
274 long index;
275 SDDS_ARRAY *array;
277
278char *makeTexSafeString(char *source);
279char *makeTexExponentialString(char *text);
280void copyAndPad(char *target, char *source, long sourceWidth, long targetWidth);
281long makeColumnHeaders(char ***header, long *fieldWidth, char *name, char *editLabel, char *units, double factor,
282 char **format, unsigned long spreadsheetFlags, unsigned long latexFormat, htab *translationTable, unsigned long htmlFormat);
283char *makeParameterLabel(long *fieldWidth, char *name, char *editLabel, char *units, double factor, char *format);
284long changeDefaultFormats(char **argv, long argc, long noWarnings);
285void setDefaultFormats(void);
286long processPrintColumns(PRINT_COLUMN **printRequestPtr, long printRequests, SDDS_DATASET *inTable, long noWarnings,
287 unsigned long spreadsheetFlags, long csv, unsigned long latexformat, htab *translationTable, unsigned long htmlformat);
288void printColumnHeaders(FILE *fpOut, PRINT_COLUMN *printColumn, long printColumns, long width, PAGINATION *pagination,
289 long latexFormat, char *latexTitle, long htmlFormat, char *htmlTitle);
290long processPrintParameters(PRINT_PARAMETER **printRequestPtr, long printRequests, SDDS_DATASET *inTable,
291 long noWarnings, long noLabels, long csv);
292long processPrintArrays(PRINT_ARRAY **printRequestPtr, long printRequests, SDDS_DATASET *inTable);
293long getFormatFieldLength(char *format, long *extraChars);
294char **makeListOfNames(char *string, long *names);
295void doPrintParameters(SDDS_DATASET *inTable, PRINT_PARAMETER *printParameter, long printParameters, long width,
296 FILE *fpOut, unsigned long spreadsheetFlags, char *spreadsheetDelimiter,
297 char *spreadsheetQuoteMark, PAGINATION *pagination, char *title, long noLabels);
298long characterCount(char *string, char c);
299long printPageTitle(FILE *fpOut, char *title);
300void doPrintColumns(SDDS_DATASET *inTable, PRINT_COLUMN *printColumn, long printColumns,
301 long width, FILE *fpOut, unsigned long spreadsheetFlags, char *spreadsheetDelimiter, char *spreadsheetQuoteMark,
302 long latexFormat, char *latexTitle, char *latexLabel, char *latexGroupColumn,
303 long htmlFormat, char *htmlTitle,
304 PAGINATION *pagination, char *title, long noLabels);
305long checkPagination(FILE *fpOut, PAGINATION *pagination, char *title);
306void replaceFormatWidth(char *buffer, char *format, long width);
307void CreateSCHFile(char *output, char *input, unsigned long flags, char *delimiter, char *quote,
308 PRINT_COLUMN *printColumn, long printColumns);
309htab *readTranslationTable(char *TranslationFile);
310char *findTranslation(htab *ht, char *key);
311char *modifyUnitsWithFactor(char *units0, double factor, unsigned long latexFormat);
312
313static char **defaultFormat = NULL;
314static char **csvFormat = NULL;
315static char *latexJustify = NULL;
316
317#define SPREADSHEET_ON 0x0001U
318#define SPREADSHEET_DELIMITER 0x0002U
319#define SPREADSHEET_QUOTEMARK 0x0004U
320#define SPREADSHEET_NOLABELS 0x0008U
321#define SPREADSHEET_CSV 0x0010UL
322
323int main(int argc, char **argv) {
324 SDDS_DATASET SDDS_dataset;
325 long i, i_arg, pageNumber, width;
326 SCANNED_ARG *s_arg;
327 char *input, *output, **name, *format, *title, *label, *editLabel, *schFile;
328 PRINT_COLUMN *printColumn;
329 PRINT_PARAMETER *printParameter;
330 PRINT_ARRAY *printArray;
331 long printColumns, printParameters, printArrays, firstPage, bufferLines;
332 long fromPage, toPage, names, pageAdvance, noTitle, noLabels, noWarnings;
333 int32_t blankLines;
334 unsigned long latexFormat, htmlFormat;
335 FILE *fpOut;
336 unsigned long flags, pipeFlags, spreadsheetFlags, dummyFlags, postPageLines, CSV = 0;
337 char *spreadsheetDelimiter, *spreadsheetQuoteMark;
338 PAGINATION pagination;
339 char **formatDefaultArg;
340 long formatDefaultArgs;
341 static char formatbuffer[100], formatbuffer2[100];
342 char *latexLabel, *latexCaption = NULL, *latexGroup, *latexTranslationFile, *latexComment = NULL;
343 char *latexCaptionBuffer=NULL, *latexLabelBuffer=NULL;
344 htab *TranslationTable;
345 char *htmlCaption = NULL, *htmlTranslationFile;
346 double factor;
347
349 argc = scanargs(&s_arg, argc, argv);
350 if (argc < 3)
351 bomb(NULL, USAGE);
352
353 input = output = NULL;
354 fromPage = toPage = 0;
355 printColumn = NULL;
356 printParameter = NULL;
357 printArray = NULL;
358 width = 130;
359 setDefaultFormats();
360 printColumns = printParameters = printArrays = pipeFlags = flags = 0;
361 postPageLines = pageAdvance = noTitle = noLabels = 0;
362 title = NULL;
363 spreadsheetFlags = 0;
364 pagination.flags = pagination.currentLine = 0;
365 noWarnings = 0;
366 formatDefaultArgs = 0;
367 schFile = NULL;
368 formatDefaultArg = NULL;
369 bufferLines = 0;
370 latexFormat = 0;
371 TranslationTable = NULL;
372 htmlFormat = 0;
373
374 for (i_arg = 1; i_arg < argc; i_arg++) {
375 if (s_arg[i_arg].arg_type == OPTION) {
376 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
377 case SET_COLUMNS:
378 if (s_arg[i_arg].n_items < 2) {
379 s_arg[i_arg].n_items = 2;
380 s_arg[i_arg].list = SDDS_Realloc(s_arg[i_arg].list, sizeof(*s_arg[i_arg].list) * 2);
381 SDDS_CopyString(&s_arg[i_arg].list[1], "*");
382 }
383 name = makeListOfNames(s_arg[i_arg].list[1], &names);
384 printColumn = SDDS_Realloc(printColumn, sizeof(*printColumn) * (names + printColumns));
385 s_arg[i_arg].n_items -= 2;
386 format = NULL;
387 blankLines = 0;
388 factor = 1;
389 if (!scanItemList(&flags, s_arg[i_arg].list + 2, &s_arg[i_arg].n_items, 0,
390 "format", SDDS_STRING, &format, 1, 0,
391 "endsline", -1, NULL, 0, ENDSLINE,
392 "usedefaultformat", -1, NULL, 0, USEDEFAULTFORMAT,
393 "blanklines", SDDS_LONG, &blankLines, 1, 0,
394 "editlabel", SDDS_STRING, &editLabel, 1, EDITLABEL_GIVEN,
395 "label", SDDS_STRING, &label, 1, LABEL_GIVEN,
396 "nounits", -1, NULL, 0, NO_UNITS,
397 "factor", SDDS_DOUBLE, &factor, 1, FACTOR_GIVEN, NULL))
398 SDDS_Bomb("invalid -columns syntax");
399 for (i = 0; i < names; i++) {
400 SDDS_ZeroMemory(printColumn + i + printColumns, sizeof(*printColumn));
401 printColumn[i + printColumns].name = name[i];
402 if (format) {
403 replaceString(formatbuffer, format, "ld", PRId32, -1, 0);
404 replaceString(formatbuffer2, formatbuffer, "lu", PRIu32, -1, 0);
405 SDDS_CopyString(&printColumn[i + printColumns].format, formatbuffer2);
406 }
407 if (flags & ENDSLINE && (i == names - 1))
408 printColumn[i + printColumns].endsLine = 1;
409 if (flags & USEDEFAULTFORMAT)
410 printColumn[i + printColumns].useDefaultFormat = 1;
411 printColumn[i + printColumns].label = printColumn[i + printColumns].editLabel = NULL;
412 if (flags & LABEL_GIVEN)
413 printColumn[i + printColumns].label = label;
414 if (flags & EDITLABEL_GIVEN)
415 printColumn[i + printColumns].editLabel = editLabel;
416 printColumn[i + printColumns].noUnits = flags & NO_UNITS ? 1 : 0;
417 printColumn[i + printColumns].factor = factor;
418 printColumn[i + printColumns].blankLines = blankLines;
419 }
420 free(name);
421 printColumns += names;
422 break;
423 case SET_PARAMETERS:
424 if (s_arg[i_arg].n_items < 2) {
425 s_arg[i_arg].n_items = 2;
426 s_arg[i_arg].list = SDDS_Realloc(s_arg[i_arg].list, sizeof(*s_arg[i_arg].list) * 2);
427 SDDS_CopyString(&s_arg[i_arg].list[1], "*");
428 }
429 name = makeListOfNames(s_arg[i_arg].list[1], &names);
430 printParameter = SDDS_Realloc(printParameter, sizeof(*printParameter) * (names + printParameters));
431 s_arg[i_arg].n_items -= 2;
432 format = NULL;
433 blankLines = 0;
434 factor = 1;
435 if (!scanItemList(&flags, s_arg[i_arg].list + 2, &s_arg[i_arg].n_items, 0,
436 "format", SDDS_STRING, &format, 1, 0,
437 "endsline", -1, NULL, 0, ENDSLINE,
438 "usedefaultformat", -1, NULL, 0, USEDEFAULTFORMAT,
439 "blanklines", SDDS_LONG, &blankLines, 1, 0,
440 "editlabel", SDDS_STRING, &editLabel, 1, EDITLABEL_GIVEN,
441 "label", SDDS_STRING, &label, 1, LABEL_GIVEN,
442 "factor", SDDS_DOUBLE, &factor, 1, FACTOR_GIVEN, NULL))
443 SDDS_Bomb("invalid -parameters syntax");
444 for (i = 0; i < names; i++) {
445 SDDS_ZeroMemory(printParameter + i + printParameters, sizeof(*printParameter));
446 printParameter[i + printParameters].name = name[i];
447 if (format) {
448 replaceString(formatbuffer, format, "ld", PRId32, -1, 0);
449 replaceString(formatbuffer2, formatbuffer, "lu", PRIu32, -1, 0);
450 SDDS_CopyString(&printParameter[i + printParameters].format, formatbuffer2);
451 }
452 if (flags & ENDSLINE && (i == names - 1))
453 printParameter[i + printParameters].endsLine = 1;
454 if (flags & USEDEFAULTFORMAT)
455 printParameter[i + printParameters].useDefaultFormat = 1;
456 printParameter[i + printParameters].label = printParameter[i + printParameters].editLabel = NULL;
457 if (flags & LABEL_GIVEN)
458 printParameter[i + printParameters].label = label;
459 if (flags & EDITLABEL_GIVEN)
460 printParameter[i + printParameters].editLabel = editLabel;
461 printParameter[i + printParameters].factor = factor;
462 printParameter[i + printParameters].blankLines = blankLines;
463 }
464 free(name);
465 printParameters += names;
466 break;
467 case SET_ARRAYS:
468 if (s_arg[i_arg].n_items < 2) {
469 s_arg[i_arg].n_items = 2;
470 s_arg[i_arg].list = SDDS_Realloc(s_arg[i_arg].list, sizeof(*s_arg[i_arg].list) * 2);
471 SDDS_CopyString(&s_arg[i_arg].list[1], "*");
472 }
473 name = makeListOfNames(s_arg[i_arg].list[1], &names);
474 printArray = SDDS_Realloc(printArray, sizeof(*printArray) * (names + printArrays));
475 s_arg[i_arg].n_items -= 2;
476 format = NULL;
477 if (!scanItemList(&flags, s_arg[i_arg].list + 2, &s_arg[i_arg].n_items, 0,
478 "format", SDDS_STRING, &format, 1, 0, NULL))
479 SDDS_Bomb("invalid -arrays syntax");
480 for (i = 0; i < names; i++) {
481 printArray[i + printArrays].name = name[i];
482 if (format) {
483 replaceString(formatbuffer, format, "ld", PRId32, -1, 0);
484 replaceString(formatbuffer2, formatbuffer, "lu", PRIu32, -1, 0);
485 SDDS_CopyString(&printArray[i + printArrays].format, formatbuffer2);
486 }
487 }
488 free(name);
489 printArrays += names;
490 break;
491 case SET_FROMPAGE:
492 if (s_arg[i_arg].n_items < 2)
493 SDDS_Bomb("invalid -fromPage syntax");
494 if (fromPage != 0)
495 SDDS_Bomb("invalid syntax: specify -fromPage once only");
496 if (sscanf(s_arg[i_arg].list[1], "%ld", &fromPage) != 1 || fromPage <= 0)
497 SDDS_Bomb("invalid -fromPage syntax or value");
498 break;
499 case SET_TOPAGE:
500 if (s_arg[i_arg].n_items < 2)
501 SDDS_Bomb("invalid -toPage syntax");
502 if (toPage != 0)
503 SDDS_Bomb("invalid syntax: specify -toPage once only");
504 if (sscanf(s_arg[i_arg].list[1], "%ld", &toPage) != 1 || toPage <= 0)
505 SDDS_Bomb("invalid -toPage syntax or value");
506 break;
507 case SET_FORMATDEFAULTS:
508 formatDefaultArg = s_arg[i_arg].list + 1;
509 formatDefaultArgs = s_arg[i_arg].n_items - 1;
510 break;
511 case SET_WIDTH:
512 if (s_arg[i_arg].n_items != 2 || sscanf(s_arg[i_arg].list[1], "%ld", &width) != 1 || (width < 40 && width))
513 SDDS_Bomb("invalid -width syntax or value");
514 break;
515 case SET_PIPE:
516 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
517 SDDS_Bomb("invalid -pipe syntax");
518 break;
519 case SET_PAGEADVANCE:
520 pageAdvance = 1;
521 break;
522 case SET_NOTITLE:
523 noTitle = 1;
524 break;
525 case SET_TITLE:
526 if (s_arg[i_arg].n_items != 2)
527 SDDS_Bomb("invalid -title syntax");
528 title = s_arg[i_arg].list[1];
529 break;
530 case SET_SPREADSHEET:
531 s_arg[i_arg].n_items--;
532 spreadsheetDelimiter = NULL;
533 spreadsheetQuoteMark = "";
534 if (!scanItemList(&spreadsheetFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
535 "delimiter", SDDS_STRING, &spreadsheetDelimiter, 1, SPREADSHEET_DELIMITER,
536 "quotemark", SDDS_STRING, &spreadsheetQuoteMark, 1, SPREADSHEET_QUOTEMARK,
537 "nolabels", -1, NULL, 0, SPREADSHEET_NOLABELS, "csv", -1, NULL, 0, SPREADSHEET_CSV,
538 "schfile", SDDS_STRING, &schFile, 1, 0, NULL))
539 SDDS_Bomb("invalid -spreadsheet syntax");
540 if (!spreadsheetDelimiter || !(spreadsheetFlags & SPREADSHEET_DELIMITER))
541 spreadsheetDelimiter = "\t";
542 if (spreadsheetFlags & SPREADSHEET_CSV) {
543 spreadsheetDelimiter = ",";
544 spreadsheetFlags |= SPREADSHEET_DELIMITER;
545 spreadsheetFlags |= SPREADSHEET_QUOTEMARK;
546 spreadsheetQuoteMark = "\"";
547 noTitle = 1;
548 CSV = 1;
549 }
550 spreadsheetFlags |= SPREADSHEET_ON;
551 width = 0;
552 break;
553 case SET_PAGINATE:
554 s_arg[i_arg].n_items--;
555 pagination.lines = 66;
556 if (!scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
557 "lines", SDDS_LONG, &pagination.lines, 1, 0,
558 "notitle", -1, NULL, 0, PAGINATION_NOTITLE,
559 "nolabels", -1, NULL, 0, PAGINATION_NOLABELS, NULL) ||
560 pagination.lines <= 3)
561 SDDS_Bomb("invalid -paginate syntax/values");
562 pagination.flags |= PAGINATION_ON;
563 break;
564 case SET_NOWARNINGS:
565 noWarnings = 1;
566 break;
567 case SET_POSTPAGELINES:
568 if (s_arg[i_arg].n_items != 2 || sscanf(s_arg[i_arg].list[1], "%ld", &postPageLines) != 1)
569 SDDS_Bomb("invalid -postPageLines syntax/values");
570 break;
571 case SET_NOLABELS:
572 noLabels = 1;
573 break;
574 case SET_BUFFERLINES:
575 if (s_arg[i_arg].n_items < 2)
576 SDDS_Bomb("invalid -bufferLines syntax");
577 if (sscanf(s_arg[i_arg].list[1], "%ld", &bufferLines) != 1 || bufferLines < 0)
578 SDDS_Bomb("invalid -bufferLines syntax or value");
579 break;
580 case SET_LATEXFORMAT:
581 s_arg[i_arg].n_items--;
582 latexLabel = NULL;
583 latexCaption = NULL;
584 latexComment = NULL;
585 if (!scanItemList(&latexFormat, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
586 "longtable", -1, NULL, 0, LATEX_LONGTABLE,
587 "booktable", -1, NULL, 0, LATEX_BOOKTABLE,
588 "sideways", -1, NULL, 0, LATEX_SIDEWAYS,
589 "label", SDDS_STRING, &latexLabel, 1, LATEX_LABEL,
590 "caption", SDDS_STRING, &latexCaption, 1, LATEX_CAPTION,
591 "comment", SDDS_STRING, &latexComment, 1, LATEX_COMMENT,
592 "group", SDDS_STRING, &latexGroup, 1, LATEX_GROUP,
593 "translate", SDDS_STRING, &latexTranslationFile, 1, LATEX_TRANSLATE,
594 "justify", SDDS_STRING, &latexJustify, 1, LATEX_JUSTIFY,
595 "complete", -1, NULL, 0, LATEX_COMPLETE, NULL))
596 SDDS_Bomb("invalid -latexFormat syntax/values");
597 latexFormat |= LATEX_FORMAT;
598 if (latexFormat & LATEX_LONGTABLE && latexFormat & LATEX_SIDEWAYS)
599 SDDS_Bomb("invalid -latexFormat syntax/values: give only one of longtable and sideways");
600 break;
601 case SET_HTMLFORMAT:
602 s_arg[i_arg].n_items--;
603 htmlCaption = NULL;
604 if (!scanItemList(&htmlFormat, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
605 "caption", SDDS_STRING, &htmlCaption, 1, HTML_CAPTION,
606 "translate", SDDS_STRING, &htmlTranslationFile, 1, HTML_TRANSLATE, NULL))
607 SDDS_Bomb("invalid -htmlFormat syntax/values");
608 htmlFormat |= HTML_FORMAT;
609 break;
610 default:
611 fprintf(stderr, "error: unknown switch: %s\n", s_arg[i_arg].list[0]);
612 SDDS_Bomb(NULL);
613 break;
614 }
615 } else {
616 if (!input)
617 input = s_arg[i_arg].list[0];
618 else if (!output)
619 output = s_arg[i_arg].list[0];
620 else
621 SDDS_Bomb("too many filenames");
622 }
623 }
624
625 pipeFlags |= DEFAULT_STDOUT;
626 processFilenames("sddsprintout", &input, &output, pipeFlags, noWarnings, NULL);
627
628 if (formatDefaultArgs)
629 changeDefaultFormats(formatDefaultArg, formatDefaultArgs, noWarnings);
630
631 if (pageAdvance) {
632 if (postPageLines)
633 SDDS_Bomb("-pageAdvance and -postPageLines are incompatible");
634 if (pagination.flags & PAGINATION_ON)
635 SDDS_Bomb("-pageAdvance and -paginate are incompatible");
636 }
637 if (pagination.flags & PAGINATION_ON && postPageLines)
638 SDDS_Bomb("-postPageLines and -paginate are incompatible");
639
640 if (!printColumns && !printParameters && !printArrays)
641 SDDS_Bomb("you must specify at least one of -columns, -parameters, or -arrays");
642 if (fromPage && toPage && fromPage > toPage)
643 SDDS_Bomb("invalid -fromPage and -toPage");
644 if (latexFormat && htmlFormat)
645 SDDS_Bomb("-latexFormat and -htmlFormat are incompatible");
646
647 if (latexFormat & LATEX_TRANSLATE)
648 TranslationTable = readTranslationTable(latexTranslationFile);
649 if (htmlFormat & HTML_TRANSLATE)
650 TranslationTable = readTranslationTable(htmlTranslationFile);
651
652 if (!SDDS_InitializeInput(&SDDS_dataset, input)) {
653 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
654 exit(1);
655 }
656
657
658 fpOut = stdout;
659 if (output && !(fpOut = fopen(output, "w")))
660 SDDS_Bomb("unable to open output file");
661
662 printColumns = processPrintColumns(&printColumn, printColumns, &SDDS_dataset, noWarnings,
663 spreadsheetFlags, CSV, latexFormat, TranslationTable, htmlFormat);
664 printParameters = processPrintParameters(&printParameter, printParameters, &SDDS_dataset, noWarnings, noLabels, CSV);
665 /* printArrays = processPrintArrays(&printArray, printArrays, &SDDS_dataset); */
666
667 SDDS_SetTerminateMode(TERMINATE_DONT_FREE_TABLE_STRINGS + TERMINATE_DONT_FREE_ARRAY_STRINGS);
668
669 firstPage = 1;
670 pagination.flags |= noTitle ? PAGINATION_NOTITLE : 0;
671 if (!title) {
672 title = tmalloc(sizeof(*title) * ((input ? strlen(input) : 10) + 100));
673 if (htmlFormat)
674 sprintf(title, "Printout for SDDS file %s", input ? input : "stdin");
675 else
676 sprintf(title, "Printout for SDDS file %s%s", input ? input : "stdin", latexFormat ? "" : "\n");
677 }
678
679 if (schFile) {
680 if (printArrays || printParameters || !printColumns)
681 SDDS_Bomb("Can't create schFile except for pure column printout.");
682 CreateSCHFile(schFile, input, spreadsheetFlags, spreadsheetDelimiter, spreadsheetQuoteMark, printColumn, printColumns);
683 }
684 if (latexFormat) {
685 noTitle = 1;
686 if (latexFormat & LATEX_LABEL && latexLabel[0]=='@') {
687 memmove(latexLabel, latexLabel+1, strlen(latexLabel));
688 if (SDDS_CheckParameter(&SDDS_dataset, latexLabel, NULL, SDDS_STRING, stderr)!=SDDS_CHECK_OK) {
689 fprintf(stderr, "sddsprintout: error: parameter %s not found in input file\n", latexLabel);
690 exit(1);
691 }
692 latexFormat |= LATEX_LABEL_PARAM;
693 }
694 if (latexFormat & LATEX_CAPTION && latexCaption[0]=='@') {
695 memmove(latexCaption, latexCaption+1, strlen(latexCaption));
696 if (SDDS_CheckParameter(&SDDS_dataset, latexCaption, NULL, SDDS_STRING, stderr)!=SDDS_CHECK_OK) {
697 fprintf(stderr, "sddsprintout: error: parameter %s not found in input file\n", latexCaption);
698 exit(1);
699 }
700 latexFormat |= LATEX_CAPTION_PARAM;
701 }
702 if (latexFormat & LATEX_COMPLETE) {
703 fprintf(fpOut, "\\documentclass{report}\n\\pagestyle{empty}\n");
704 if (latexFormat & LATEX_BOOKTABLE)
705 fprintf(fpOut, "\\usepackage{booktabs}\n");
706 if (latexFormat & LATEX_SIDEWAYS)
707 fprintf(fpOut, "\\usepackage{rotating}\n");
708 fprintf(fpOut, "\\begin{document}\n");
709 }
710 if (latexComment)
711 fprintf(fpOut, "%% %s\n", latexComment);
712 }
713 if (htmlFormat) {
714 noTitle = 1;
715 }
716
717 while ((pageNumber = SDDS_ReadPageSparse(&SDDS_dataset, 0, printColumns || SDDS_dataset.layout.data_mode.column_major ? 1 : 1000000, 0, 0)) > 0) {
718 if ((fromPage && pageNumber < fromPage) || (toPage && pageNumber > toPage))
719 continue;
720 if (pagination.flags & PAGINATION_ON) {
721 if (!firstPage) {
722 fputc('\014', fpOut);
723 pagination.currentLine = 1;
724 }
725 if (!noTitle)
726 pagination.currentLine += printPageTitle(fpOut, title);
727 } else {
728 if (firstPage) {
729 if (!noTitle)
730 printPageTitle(fpOut, title);
731 } else if (pageAdvance)
732 fputc('\014', fpOut);
733 else if (postPageLines > 0) {
734 long line = postPageLines;
735 while (line--)
736 fputc('\n', fpOut);
737 }
738 }
739 if (!latexFormat && !htmlFormat)
740 doPrintParameters(&SDDS_dataset, printParameter, printParameters, width, fpOut, spreadsheetFlags,
741 spreadsheetDelimiter, spreadsheetQuoteMark, &pagination, title, noLabels);
742 /* doPrintArrays(&SDDS_dataset, printArray, printArrays, width, fpOut, &pagination); */
743 latexCaptionBuffer = latexLabelBuffer = NULL;
744 if (latexFormat&LATEX_CAPTION_PARAM && !(latexCaptionBuffer = SDDS_GetParameterAsString(&SDDS_dataset, latexCaption, NULL))) {
745 char buffer[1024];
746 snprintf(buffer, 1024, "Error: can't read latex caption parameter %s\n", latexCaption);
747 SDDS_Bomb(buffer);
748 }
749 if (latexFormat&LATEX_LABEL_PARAM && !(latexLabelBuffer = SDDS_GetParameterAsString(&SDDS_dataset, latexLabel, NULL))) {
750 char buffer[1024];
751 snprintf(buffer, 1024, "Error: can't read latex label parameter %s\n", latexLabel);
752 SDDS_Bomb(buffer);
753 }
754 doPrintColumns(&SDDS_dataset, printColumn, printColumns, width, fpOut, spreadsheetFlags, spreadsheetDelimiter,
755 spreadsheetQuoteMark, latexFormat,
756 latexFormat&LATEX_CAPTION_PARAM ? latexCaptionBuffer : latexCaption,
757 latexFormat&LATEX_LABEL_PARAM ? latexLabelBuffer : latexLabel,
758 latexGroup, htmlFormat, htmlCaption,
759 &pagination, title, noLabels);
760 if (latexFormat&LATEX_CAPTION_PARAM && latexCaptionBuffer)
761 free(latexCaptionBuffer);
762 if (latexFormat&LATEX_LABEL_PARAM && latexLabelBuffer)
763 free(latexLabelBuffer);
764 if (bufferLines) {
765 for (i = 0; i < bufferLines; i++)
766 fputc('\n', fpOut);
767 }
768 firstPage = 0;
769 }
770
771 if (!SDDS_Terminate(&SDDS_dataset))
772 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
773 for (i = 0; i < printColumns; i++) {
774 if (printColumn[i].headers)
775 free(printColumn[i].header);
776 }
777 if (latexFormat & LATEX_COMPLETE)
778 fprintf(fpOut, "\\end{document}\n");
779
780 free(printColumn);
781 free_scanargs(&s_arg, argc);
782 return 0;
783}
784
785long processPrintColumns(PRINT_COLUMN **printRequestPtr, long printRequests, SDDS_DATASET *inTable, long noWarnings,
786 unsigned long spreadsheetFlags, long csv, unsigned long latexFormat, htab *TranslationTable, unsigned long htmlFormat) {
787 PRINT_COLUMN *printColumn, *printRequest;
788 long i, irequest, iname, printColumns, names, *columnUsed, columnLimit;
789 int64_t index;
790 char **name, *units, *format;
791
792 if (printRequests < 1 || !(printRequest = *printRequestPtr))
793 return 0;
794 if ((columnLimit = SDDS_ColumnCount(inTable)) < 0) {
795 if (!noWarnings)
796 fprintf(stderr, "warning: no column data in input file\n");
797 return 0;
798 }
799 columnUsed = tmalloc(sizeof(*columnUsed) * columnLimit);
800 for (i = 0; i < columnLimit; i++)
801 columnUsed[i] = 0;
802 printColumn = tmalloc(sizeof(*printColumn) * columnLimit);
803 printColumns = 0;
804 name = NULL;
805
806 for (irequest = 0; irequest < printRequests; irequest++) {
807 if ((names = SDDS_MatchColumns(inTable, &name, SDDS_MATCH_STRING, FIND_ANY_TYPE, printRequest[irequest].name, SDDS_0_PREVIOUS | SDDS_OR)) > 0) {
808 for (iname = 0; iname < names; iname++) {
809 if ((index = SDDS_GetColumnIndex(inTable, name[iname])) < 0)
810 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
811 if (!columnUsed[index]) {
812 if (SDDS_GetColumnInformation(inTable, "units", &units, SDDS_GET_BY_INDEX, index) != SDDS_STRING)
813 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
814 SDDS_CopyString(&printColumn[printColumns].name, name[iname]);
815 printColumn[printColumns].index = index;
816 if (iname == names - 1)
817 printColumn[printColumns].endsLine = printRequest[irequest].endsLine;
818 else
819 printColumn[printColumns].endsLine = 0;
820 printColumn[printColumns].type = SDDS_GetColumnType(inTable, index);
821 printColumn[printColumns].blankLines = printRequest[irequest].blankLines;
822 if (SDDS_GetColumnInformation(inTable, "format_string", &format, SDDS_GET_BY_INDEX, index) != SDDS_STRING)
823 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
824 if (csv) {
825 SDDS_CopyString(&printColumn[printColumns].format, csvFormat[printColumn[printColumns].type - 1]);
826 } else {
827 if (printRequest[irequest].format) {
828 if (printRequest[irequest].format[0]!='@') {
829 if (!SDDS_VerifyPrintfFormat(printRequest[irequest].format, printColumn[printColumns].type)) {
830 fprintf(stderr, "error: given format (\"%s\") for column %s is invalid\n",
831 printRequest[irequest].format, name[iname]);
832 exit(1);
833 }
834 } else {
835 long index;
836 if ((index=SDDS_GetColumnIndex(inTable, printRequest[irequest].format+1))<0 ||
837 SDDS_GetColumnType(inTable, index)!=SDDS_STRING) {
838 fprintf(stderr, "error: given format column (\"%s\") for column %s is absent or not string type\n",
839 printRequest[irequest].format+1, name[iname]);
840 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
841 exit(1);
842 }
843 }
844 SDDS_CopyString(&printColumn[printColumns].format, printRequest[irequest].format);
845 } else if (SDDS_StringIsBlank(format) || printRequest[irequest].useDefaultFormat)
846 SDDS_CopyString(&printColumn[printColumns].format, defaultFormat[printColumn[printColumns].type - 1]);
847 else
848 SDDS_CopyString(&printColumn[printColumns].format, format);
849 }
850 printColumn[printColumns].headers =
851 makeColumnHeaders(&printColumn[printColumns].header, &printColumn[printColumns].fieldWidth,
852 printRequest[irequest].label ? printRequest[irequest].label : name[iname],
853 printRequest[irequest].editLabel,
854 printRequest[irequest].noUnits?NULL:units, printRequest[irequest].factor,
855 &printColumn[printColumns].format, spreadsheetFlags, latexFormat, TranslationTable, htmlFormat);
856#if defined(DEBUG)
857 fprintf(stderr, "%s has format >%s<\n",
858 printRequest[irequest].label ? printRequest[irequest].label : name[iname], printColumn[printColumns].format);
859#endif
860 printColumn[printColumns].data = NULL;
861 printColumn[printColumns].factor = printRequest[irequest].factor;
862 printColumns++;
863 columnUsed[index] = 1;
864 if (units)
865 free(units);
866 }
867 free(name[iname]);
868 }
869 free(name);
870 } else if (names < 0)
871 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
872 else if (!noWarnings)
873 fprintf(stderr, "warning: no column matches %s\n", printRequest[irequest].name);
874 free(printRequest[irequest].name);
875 if (printRequest[irequest].format)
876 free(printRequest[irequest].format);
877 }
878 free(printRequest);
879 *printRequestPtr = printColumn;
880 return printColumns;
881}
882
883long processPrintParameters(PRINT_PARAMETER **printRequestPtr, long printRequests, SDDS_DATASET *inTable,
884 long noWarnings, long noLabels, long csv) {
885 PRINT_PARAMETER *printParameter, *printRequest;
886 long i, irequest, iname, printParameters, names, *parameterUsed, parameterLimit, maxFieldWidth, index;
887 char **name, *units, *format;
888
889 if (printRequests < 1 || !(printRequest = *printRequestPtr))
890 return 0;
891 if ((parameterLimit = SDDS_ParameterCount(inTable)) < 0) {
892 if (!noWarnings)
893 fprintf(stderr, "warning: no parameter data in input file\n");
894 return 0;
895 }
896 parameterUsed = tmalloc(sizeof(*parameterUsed) * parameterLimit);
897 for (i = 0; i < parameterLimit; i++)
898 parameterUsed[i] = 0;
899 printParameter = tmalloc(sizeof(*printParameter) * parameterLimit);
900 printParameters = 0;
901 name = NULL;
902 maxFieldWidth = 0;
903 for (irequest = 0; irequest < printRequests; irequest++) {
904 if ((names = SDDS_MatchParameters(inTable, &name, SDDS_MATCH_STRING, FIND_ANY_TYPE, printRequest[irequest].name, SDDS_0_PREVIOUS | SDDS_OR)) > 0) {
905 for (iname = 0; iname < names; iname++) {
906 if ((index = SDDS_GetParameterIndex(inTable, name[iname])) < 0)
907 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
908 if (!parameterUsed[index]) {
909 if (SDDS_GetParameterInformation(inTable, "units", &units, SDDS_GET_BY_INDEX, index) != SDDS_STRING)
910 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
911 SDDS_CopyString(&printParameter[printParameters].name, name[iname]);
912 printParameter[printParameters].index = index;
913 printParameter[printParameters].type = SDDS_GetParameterType(inTable, index);
914 if (iname == names - 1)
915 printParameter[printParameters].endsLine = printRequest[irequest].endsLine;
916 printParameter[printParameters].blankLines = printRequest[irequest].blankLines;
917 if (SDDS_GetParameterInformation(inTable, "format_string", &format, SDDS_GET_BY_INDEX, index) != SDDS_STRING)
918 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
919
920 if (csv) {
921 SDDS_CopyString(&printParameter[printParameters].format, csvFormat[printParameter[printParameters].type - 1]);
922 } else {
923 if (printRequest[irequest].format) {
924 if (!SDDS_VerifyPrintfFormat(printRequest[irequest].format, printParameter[printParameters].type)) {
925 fprintf(stderr, "error: given format (\"%s\") for parameter %s is invalid\n", printRequest[irequest].format, name[iname]);
926 exit(1);
927 }
928 SDDS_CopyString(&printParameter[printParameters].format, printRequest[irequest].format);
929 } else if (SDDS_StringIsBlank(format) || printRequest[irequest].useDefaultFormat)
930 SDDS_CopyString(&printParameter[printParameters].format, defaultFormat[printParameter[printParameters].type - 1]);
931 else
932 SDDS_CopyString(&printParameter[printParameters].format, format);
933 }
934
935 if (!noLabels) {
936 printParameter[printParameters].label =
937 makeParameterLabel(&printParameter[printParameters].fieldWidth, printRequest[irequest].label ? printRequest[irequest].label : name[iname], printRequest[irequest].editLabel, units, printRequest[irequest].factor, printParameter[printParameters].format);
938 } else {
939 printParameter[printParameters].label = "";
940 }
941 if (printParameter[printParameters].fieldWidth > maxFieldWidth)
942 maxFieldWidth = printParameter[printParameters].fieldWidth;
943 printParameter[printParameters].data = NULL;
944 printParameter[printParameters].factor = printRequest[irequest].factor;
945 printParameters++;
946 parameterUsed[index] = 1;
947 if (units)
948 free(units);
949 }
950 free(name[iname]);
951 }
952 free(name);
953 } else if (names < 0)
954 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
955 else if (!noWarnings)
956 fprintf(stderr, "warning: no parameter matches %s\n", printRequest[irequest].name);
957 free(printRequest[irequest].name);
958 if (printRequest[irequest].format)
959 free(printRequest[irequest].format);
960 }
961 for (i = 0; i < printParameters; i++) {
962 char *ptr;
963 if (printParameter[i].fieldWidth < maxFieldWidth) {
964 ptr = tmalloc(sizeof(*ptr) * (maxFieldWidth + 1));
965 strcpy(ptr, printParameter[i].label);
966 pad_with_spaces(ptr, maxFieldWidth - printParameter[i].fieldWidth);
967 free(printParameter[i].label);
968 printParameter[i].label = ptr;
969 printParameter[i].fieldWidth = maxFieldWidth;
970 }
971 }
972 free(printRequest);
973 *printRequestPtr = printParameter;
974 return printParameters;
975}
976
977#if SDDS_NUM_TYPES != 11
978# error "number of SDDS types is not 9 as expected"
979#endif
980
981void setDefaultFormats(void) {
982 defaultFormat = tmalloc(sizeof(*defaultFormat) * SDDS_NUM_TYPES);
983 SDDS_CopyString(defaultFormat + SDDS_LONGDOUBLE - 1, "%13.6e");
984 SDDS_CopyString(defaultFormat + SDDS_DOUBLE - 1, "%13.6e");
985 SDDS_CopyString(defaultFormat + SDDS_FLOAT - 1, "%13.6e");
986 SDDS_CopyString(defaultFormat + SDDS_LONG64 - 1, "%10" PRId64);
987 SDDS_CopyString(defaultFormat + SDDS_ULONG64 - 1, "%10" PRIu64);
988 SDDS_CopyString(defaultFormat + SDDS_LONG - 1, "%10" PRId32);
989 SDDS_CopyString(defaultFormat + SDDS_ULONG - 1, "%10" PRIu32);
990 SDDS_CopyString(defaultFormat + SDDS_SHORT - 1, "%5hd");
991 SDDS_CopyString(defaultFormat + SDDS_USHORT - 1, "%5hu");
992 SDDS_CopyString(defaultFormat + SDDS_CHARACTER - 1, "%c");
993 SDDS_CopyString(defaultFormat + SDDS_STRING - 1, "%16s");
994 csvFormat = tmalloc(sizeof(*csvFormat) * SDDS_NUM_TYPES);
995 SDDS_CopyString(csvFormat + SDDS_LONGDOUBLE - 1, "%13.6e");
996 SDDS_CopyString(csvFormat + SDDS_DOUBLE - 1, "%13.6e");
997 SDDS_CopyString(csvFormat + SDDS_FLOAT - 1, "%13.3e");
998 SDDS_CopyString(csvFormat + SDDS_LONG64 - 1, "%" PRId64);
999 SDDS_CopyString(csvFormat + SDDS_ULONG64 - 1, "%" PRIu64);
1000 SDDS_CopyString(csvFormat + SDDS_LONG - 1, "%" PRId32);
1001 SDDS_CopyString(csvFormat + SDDS_ULONG - 1, "%" PRIu32);
1002 SDDS_CopyString(csvFormat + SDDS_SHORT - 1, "%hd");
1003 SDDS_CopyString(csvFormat + SDDS_USHORT - 1, "%hu");
1004 SDDS_CopyString(csvFormat + SDDS_CHARACTER - 1, "%c");
1005 SDDS_CopyString(csvFormat + SDDS_STRING - 1, "%s");
1006}
1007
1008long changeDefaultFormats(char **argv, long argc, long noWarnings) {
1009 long i, type;
1010 char *format;
1011 static char formatbuffer[100], formatbuffer2[100];
1012
1013 for (i = 0; i < argc; i++) {
1014 if (!(format = strchr(argv[i], '='))) {
1015 fprintf(stderr, "-formatDefault syntax error with keyword \"%s\"\n", argv[i]);
1016 return 0;
1017 }
1018 *format++ = 0;
1019 if (!(type = SDDS_IdentifyType(argv[i]))) {
1020 fprintf(stderr, "-formatDefault error: unknown type \"%s\"\n", argv[i]);
1021 return 0;
1022 }
1023 if (!SDDS_VerifyPrintfFormat(format, type)) {
1024 fprintf(stderr, "-formatDefault error: invalid format string \"%s\" for type \"%s\"\n", format, argv[i]);
1025 return 0;
1026 }
1027 free(defaultFormat[type - 1]);
1028
1029 if (SDDS_LONG == type) {
1030 replaceString(formatbuffer, format, "ld", PRId32, -1, 0);
1031 replaceString(formatbuffer2, formatbuffer, "lu", PRIu32, -1, 0);
1032 SDDS_CopyString(defaultFormat + type - 1, formatbuffer2);
1033 } else {
1034 SDDS_CopyString(defaultFormat + type - 1, format);
1035 }
1036 if (!getFormatFieldLength(format, NULL) && !noWarnings)
1037 fprintf(stderr, "warning: no field length for default format \"%s\"---this will produce poor results\n", defaultFormat[type - 1]);
1038 }
1039 return 1;
1040}
1041
1042long makeColumnHeaders(char ***header, long *fieldWidth, char *name, char *editLabel, char *units, double factor,
1043 char **format, unsigned long spreadsheetHeaders, unsigned long latexFormat, htab *TranslationTable, unsigned long htmlFormat) {
1044 long formatWidth, unitsWidth, nameWidth, headers, i, formatPadding, formatExtraChars;
1045 static char buffer[1024], buffer2[1026];
1046 static char nameBuffer[1024];
1047
1048 formatWidth = 0;
1049
1050 if (latexFormat & LATEX_TRANSLATE) {
1051 name = findTranslation(TranslationTable, name);
1052 units = findTranslation(TranslationTable, units);
1053 }
1054 if (htmlFormat & HTML_TRANSLATE) {
1055 name = findTranslation(TranslationTable, name);
1056 units = findTranslation(TranslationTable, units);
1057 }
1058 if (factor != 1)
1059 units = modifyUnitsWithFactor(units, 1. / factor, latexFormat);
1060
1061 if (editLabel) {
1062 strcpy(nameBuffer, name);
1063 if (!edit_string(nameBuffer, editLabel))
1064 SDDS_Bomb("Problem editing column label");
1065 name = nameBuffer;
1066 }
1067
1068#if defined(DEBUG)
1069 fprintf(stderr, "name: >%s< format: >%s<\n", name, *format ? *format : "NULL");
1070#endif
1071
1072 /* the field width is the large of the units width and the column name width */
1073 unitsWidth = units ? strlen(units) : 0;
1074 nameWidth = strlen(name);
1075 *fieldWidth = unitsWidth > nameWidth ? unitsWidth : nameWidth;
1076
1077 if (!(spreadsheetHeaders & SPREADSHEET_ON)) {
1078 /* compare the field width to the width in the format string, if any.
1079 field width needs to be at least equal to the format width + 2 to
1080 provide buffer spaces
1081 */
1082 if (!*format || (*format && (*format)[0]!='@')) {
1083 if (*format) {
1084 formatWidth = getFormatFieldLength(*format, &formatExtraChars);
1085 if ((formatWidth + formatExtraChars) > *fieldWidth)
1086 *fieldWidth = formatWidth + formatExtraChars;
1087 }
1088 *fieldWidth += 2;
1089 if (*fieldWidth < 2)
1090 *fieldWidth = 2;
1091#if defined(DEBUG)
1092 fprintf(stderr, "fieldWidth = %ld, formatWidth = %ld, formatExtra = %ld\n", *fieldWidth, formatWidth, formatExtraChars);
1093#endif
1094 if (*format && (formatPadding = (*fieldWidth - 2 - formatExtraChars) - formatWidth) > 0) {
1095 /* come here if the format width is smaller than the field width less
1096 the extra char and buffer space. Change the format width to fill up the
1097 available space
1098 */
1099 formatWidth = *fieldWidth - 2 - formatExtraChars;
1100 replaceFormatWidth(buffer, *format, formatWidth);
1101#if defined(DEBUG)
1102 fprintf(stderr, "Adjusted format width to %ld: >%s<\n", formatWidth, buffer);
1103#endif
1104 free(*format);
1105 sprintf(buffer2, " %s ", buffer);
1106 SDDS_CopyString(format, buffer2);
1107 } else {
1108 sprintf(buffer, " %s ", *format);
1109 free(*format);
1110 SDDS_CopyString(format, buffer);
1111 }
1112 }
1113 }
1114
1115 *header = tmalloc(sizeof(**header) * (headers = 2));
1116 for (i = 0; i < headers; i++)
1117 (*header)[i] = tmalloc(sizeof(***header) * (*fieldWidth + 1));
1118
1119 /* first header is column name */
1120 copyAndPad((*header)[0], name, nameWidth, *fieldWidth);
1121 /* second header is column units */
1122 copyAndPad((*header)[1], units, unitsWidth, *fieldWidth);
1123#if defined(DEBUG)
1124 fprintf(stderr, "header0 padded to %ld: >%s<\n", *fieldWidth, (*header)[0]);
1125 (*header)[0][0] = '+';
1126 (*header)[0][strlen((*header)[0]) - 1] = '-';
1127 fprintf(stderr, "header1 padded to %ld: >%s<\n", *fieldWidth, (*header)[1]);
1128 (*header)[1][0] = '+';
1129 (*header)[1][strlen((*header)[1]) - 1] = '-';
1130#endif
1131
1132 return headers;
1133}
1134
1135void copyAndPad(char *target, char *source, long sourceWidth, long targetWidth) {
1136 long i, head, tail, excess;
1137 if ((excess = targetWidth - sourceWidth) < 0)
1138 SDDS_Bomb("negative excess in copyAndPad()---programming error");
1139 head = tail = excess / 2;
1140 if ((i = excess - head - tail))
1141 head += i;
1142 for (i = 0; i < head; i++)
1143 target[i] = ' ';
1144 target[i] = 0;
1145 if (source)
1146 strcat(target, source);
1147 for (i = strlen(target); i < targetWidth; i++)
1148 target[i] = ' ';
1149 target[i] = 0;
1150}
1151
1152/*
1153void copyAndPad(char *target, char *source, long sourceWidth, long targetWidth) {
1154 long i, head, tail, excess;
1155 if (source && *source!='@') {
1156 if ((excess = targetWidth - sourceWidth) < 0)
1157 SDDS_Bomb("negative excess in copyAndPad()---programming error");
1158 head = tail = excess / 2;
1159 if ((i = excess - head - tail))
1160 head += i;
1161 for (i = 0; i < head; i++)
1162 target[i] = ' ';
1163 target[i] = 0;
1164 if (source)
1165 strcat(target, source);
1166 for (i = strlen(target); i < targetWidth; i++)
1167 target[i] = ' ';
1168 target[i] = 0;
1169 } else if (source)
1170 strcat(target, source);
1171}
1172*/
1173
1174char *makeParameterLabel(long *fieldWidth, char *name, char *editLabel, char *units, double factor, char *format) {
1175 long formatWidth, labelWidth, extraFormatChars;
1176 char *label;
1177 static char buffer[1024];
1178
1179 if (editLabel) {
1180 strcpy(buffer, name);
1181 if (!edit_string(buffer, editLabel))
1182 SDDS_Bomb("Problem editing parameter label");
1183 name = buffer;
1184 }
1185
1186 *fieldWidth = (labelWidth = strlen(name) + 4 + (units && !SDDS_StringIsBlank(units) ? strlen(units) + 3 : 0)) + (formatWidth = getFormatFieldLength(format, &extraFormatChars));
1187 *fieldWidth += extraFormatChars;
1188 if (*fieldWidth < 2)
1189 *fieldWidth = 2;
1190 label = tmalloc(sizeof(*label) * (labelWidth + 1));
1191 if (factor != 1)
1192 units = modifyUnitsWithFactor(units, 1. / factor, 0);
1193 if (units && !SDDS_StringIsBlank(units))
1194 sprintf(label, "%s (%s) = ", name, units);
1195 else
1196 sprintf(label, "%s = ", name);
1197 return label;
1198}
1199
1200long getFormatFieldLength(char *format, long *extraChars) {
1201 long width;
1202 char *format0;
1203
1204 if (*format=='@')
1205 return 10;
1206 format0 = format;
1207 while (*format && *format != '%')
1208 format++;
1209 if (*format != '%') {
1210 fprintf(stderr, "Bad format string: %s\n", format0);
1211 exit(1);
1212 }
1213 if (extraChars)
1214 *extraChars = format - format0;
1215 while (*format && !isdigit(*format))
1216 if (*format == '.')
1217 break;
1218 else
1219 format++;
1220 if (!*format || !isdigit(*format))
1221 width = 0;
1222 else {
1223 width = atoi(format);
1224 }
1225 while (isdigit(*format) || *format == '.')
1226 format++;
1227 if (*format == 'l' || *format == 'h')
1228 format++;
1229 if (*format)
1230 format++;
1231 if (extraChars)
1232 *extraChars += strlen(format);
1233
1234 return width;
1235}
1236
1237void doPrintParameters(SDDS_DATASET *inTable, PRINT_PARAMETER *printParameter, long printParameters, long width,
1238 FILE *fpOut, unsigned long spreadsheetFlags, char *spreadsheetDelimiter,
1239 char *spreadsheetQuoteMark, PAGINATION *pagination, char *title, long noLabels) {
1240 long parameter, outputRow, length;
1241 char printBuffer[2 * SDDS_MAXLINE];
1242 static char *dataBuffer = NULL;
1243 char *format;
1244
1245 if (!printParameters)
1246 return;
1247 if (!dataBuffer && !(dataBuffer = malloc(sizeof(double) * 4)))
1248 SDDS_Bomb("Allocation failure in doPrintParameters");
1249
1250 outputRow = 0;
1251 for (parameter = 0; parameter < printParameters; parameter++) {
1252 format = NULL;
1253 if (printParameter[parameter].format && printParameter[parameter].format[0]=='@' &&
1254 !(format=SDDS_GetParameter(inTable, printParameter[parameter].format+1, NULL)))
1255 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1256 if (!SDDS_GetParameter(inTable, printParameter[parameter].name, dataBuffer))
1257 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1258 if (!SDDS_SprintTypedValueFactor((void *)dataBuffer, 0, printParameter[parameter].type,
1259 format?format:printParameter[parameter].format, printBuffer,
1260 SDDS_PRINT_NOQUOTES, printParameter[parameter].factor))
1261 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1262 if (spreadsheetFlags & SPREADSHEET_ON) {
1263 if (!(spreadsheetFlags & SPREADSHEET_NOLABELS))
1264 fprintf(fpOut, "%s%s", printParameter[parameter].name, spreadsheetDelimiter);
1265 fprintf(fpOut, "%s%s%s\n", spreadsheetQuoteMark, printBuffer, spreadsheetQuoteMark);
1266 continue;
1267 }
1268 length = strlen(printParameter[parameter].label) + strlen(printBuffer) + (parameter ? 2 : 0);
1269 if ((parameter && printParameter[parameter - 1].endsLine) || (outputRow && (outputRow + length) > width)) {
1270 fputc('\n', fpOut);
1271 checkPagination(fpOut, pagination, title);
1272 outputRow = length - 2;
1273 if (parameter && printParameter[parameter - 1].blankLines && printParameter[parameter - 1].endsLine) {
1274 long i;
1275 for (i = 1; i < printParameter[parameter - 1].blankLines; i++) {
1276 checkPagination(fpOut, pagination, title);
1277 fputc('\n', fpOut);
1278 }
1279 }
1280 } else {
1281 if (parameter)
1282 fputs(" ", fpOut);
1283 outputRow += length;
1284 }
1285 fputs(printParameter[parameter].label, fpOut);
1286 fputs(printBuffer, fpOut);
1287 if (printParameter[parameter].type == SDDS_STRING)
1288 free(*((char **)dataBuffer));
1289 }
1290 if (!(spreadsheetFlags & SPREADSHEET_ON)) {
1291 checkPagination(fpOut, pagination, title);
1292 fputc('\n', fpOut);
1293 checkPagination(fpOut, pagination, title);
1294 fputc('\n', fpOut);
1295 }
1296}
1297
1298char **makeListOfNames(char *string, long *names) {
1299 char **name, *ptr;
1300 long iName;
1301
1302 *names = characterCount(string, ',') + 1;
1303 name = tmalloc(sizeof(*name) * *names);
1304 for (iName = 0; string && iName < *names; iName++) {
1305 if ((ptr = strchr(string, ',')))
1306 *ptr++ = 0;
1307 SDDS_CopyString(name + iName, string);
1308 string = ptr;
1309 }
1310 if (iName != *names)
1311 SDDS_Bomb("problem occurred scanning list of names");
1312 return name;
1313}
1314
1315long characterCount(char *string, char c) {
1316 char *ptr;
1317 long count = 0;
1318 while ((ptr = strchr(string, c))) {
1319 count++;
1320 string = ptr + 1;
1321 }
1322 return count;
1323}
1324
1325long printPageTitle(FILE *fpOut, char *title) {
1326 long lines;
1327 char *ptr;
1328
1329 fprintf(fpOut, "%s\n", title);
1330 ptr = title;
1331 lines = 1;
1332 while ((ptr = strchr(ptr, '\n'))) {
1333 ptr++;
1334 lines++;
1335 }
1336 return lines;
1337}
1338
1339long checkPagination(FILE *fpOut, PAGINATION *pagination, char *title) {
1340 if (!(pagination->flags & PAGINATION_ON))
1341 return 0;
1342 if ((pagination->currentLine += 1) >= pagination->lines) {
1343 fputc('\014', fpOut);
1344 pagination->currentLine = 0;
1345 if (!(pagination->flags & PAGINATION_NOTITLE))
1346 pagination->currentLine += printPageTitle(fpOut, title);
1347 return 1;
1348 }
1349 return 0;
1350}
1351
1352void printColumnHeaders(FILE *fpOut, PRINT_COLUMN *printColumn, long printColumns, long width,
1353 PAGINATION *pagination, long latexFormat, char *latexTitle, long htmlFormat, char *htmlTitle) {
1354 char *label;
1355 long row, column, header, outputRow, maxOutputRow, length, noUnitsLine;
1356
1357 if (latexFormat) {
1358 if (latexFormat & LATEX_LONGTABLE) {
1359 fprintf(fpOut, "\\begin{longtable}{");
1360 if (latexFormat & LATEX_JUSTIFY) {
1361 fprintf(fpOut, "%s", latexJustify);
1362 } else {
1363 for (column = 0; column < printColumns; column++)
1364 fprintf(fpOut, "%s", latexFormat & LATEX_BOOKTABLE ? "c" : (column == 0 ? "|c|" : "c|"));
1365 }
1366 fprintf(fpOut, "}\n");
1367 if (latexTitle && strlen(latexTitle)) {
1368 fprintf(fpOut, "\\caption{%s}\\\\\n", latexTitle ? makeTexSafeString(latexTitle) : "No caption");
1369 }
1370 } else {
1371 fprintf(fpOut, "\\begin{%s}[htb]", latexFormat & LATEX_SIDEWAYS ? "sidewaystable" : "table");
1372 if (latexTitle && strlen(latexTitle)) {
1373 fprintf(fpOut, "\\caption{%s}\n", latexTitle ? makeTexSafeString(latexTitle) : "No caption");
1374 } else
1375 fprintf(fpOut, "\n");
1376 fprintf(fpOut, "\\begin{center}\n");
1377 fprintf(fpOut, "\\begin{tabular}{");
1378 if (latexFormat & LATEX_JUSTIFY) {
1379 fprintf(fpOut, "%s", latexJustify);
1380 } else {
1381 for (column = 0; column < printColumns; column++)
1382 fprintf(fpOut, "%s", latexFormat & LATEX_BOOKTABLE ? "c" : (column == 0 ? "|c|" : "c|"));
1383 }
1384 fprintf(fpOut, "}\n");
1385 }
1386
1387 if (latexFormat & LATEX_BOOKTABLE)
1388 fprintf(fpOut, "\\toprule\n");
1389 else
1390 fprintf(fpOut, "\\hline\n");
1391 }
1392 if (htmlFormat) {
1393 fprintf(fpOut, "<table style=\"width:100%%\">\n");
1394 if (htmlTitle && strlen(htmlTitle)) {
1395 fprintf(fpOut, " <caption>%s</caption>\n", htmlTitle);
1396 }
1397 }
1398 noUnitsLine = 1;
1399 header = 1;
1400 for (column = 0; column < printColumns; column++) {
1401 if (!SDDS_StringIsBlank(printColumn[column].header[header]))
1402 break;
1403 }
1404 if (column != printColumns)
1405 noUnitsLine = 0;
1406
1407 maxOutputRow = 0;
1408 for (header = 0; header < printColumn[0].headers; header++) {
1409 outputRow = 0;
1410 if (noUnitsLine && header == 1)
1411 continue;
1412 if (htmlFormat) {
1413 fprintf(fpOut, " <tr>\n");
1414 }
1415 for (column = 0; column < printColumns; column++) {
1416 label = printColumn[column].header[header];
1417 length = strlen(label);
1418 if (!latexFormat && !htmlFormat && ((column && printColumn[column - 1].endsLine) || (width && outputRow && (outputRow + length) > width))) {
1419 printColumn[column - 1].endsLine = 1;
1420 fputc('\n', fpOut);
1421 pagination->currentLine++;
1422 outputRow = 0;
1423 }
1424 if (latexFormat) {
1425 if (latexFormat & LATEX_TRANSLATE && strchr(label, '$'))
1426 fputs(label, fpOut);
1427 else if (strpbrk(label, "_^{}\\"))
1428 fprintf(fpOut, "$%s$", label);
1429 else
1430 fputs(makeTexSafeString(printColumn[column].header[header]), fpOut);
1431 fputs(column == printColumns - 1 ? (latexFormat & LATEX_BOOKTABLE ? " \\\\ \n" : " \\\\ \\hline") : " & ", fpOut);
1432 } else if (htmlFormat) {
1433 fprintf(fpOut, " <th>%s</th>\n", trim_spaces(label));
1434 } else {
1435 fputs(label, fpOut);
1436 outputRow += length;
1437 if (outputRow > maxOutputRow)
1438 maxOutputRow = outputRow;
1439 }
1440 }
1441 if (htmlFormat) {
1442 fprintf(fpOut, " </tr>");
1443 }
1444 fputc('\n', fpOut);
1445 pagination->currentLine++;
1446 }
1447 if (!latexFormat && !htmlFormat) {
1448 for (row = 0; row < maxOutputRow; row++)
1449 fputc('-', fpOut);
1450 fputc('\n', fpOut);
1451 } else if (latexFormat & LATEX_BOOKTABLE) {
1452 fputs("\\midrule\n", fpOut);
1453 }
1454 pagination->currentLine++;
1455}
1456
1457void doPrintColumns(SDDS_DATASET *inTable, PRINT_COLUMN *printColumn, long printColumns,
1458 long width, FILE *fpOut, unsigned long spreadsheetFlags, char *spreadsheetDelimiter, char *spreadsheetQuoteMark,
1459 long latexFormat, char *latexTitle, char *latexLabel, char *latexGroupColumn,
1460 long htmlFormat, char *htmlTitle,
1461 PAGINATION *pagination, char *title, long noLabels) {
1462 long column;
1463 int64_t row, rows, nGroups, maxGroupLength, groupLength;
1464 void **data;
1465 char **groupData = NULL;
1466 char ***format = NULL;
1467 char printBuffer[16 * SDDS_MAXLINE];
1468 char *t;
1469 if (!printColumns)
1470 return;
1471
1472 if ((rows = SDDS_CountRowsOfInterest(inTable)) < 0)
1473 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1474 else if (!rows)
1475 return;
1476
1477 if ((latexTitle != NULL) && (latexTitle[0] == '@')) {
1478 latexTitle = latexTitle + 1;
1479 t = SDDS_GetParameterAsString(inTable, latexTitle, &t);
1480 latexTitle = t;
1481 }
1482 if ((htmlTitle != NULL) && (htmlTitle[0] == '@')) {
1483 htmlTitle = htmlTitle + 1;
1484 t = SDDS_GetParameterAsString(inTable, htmlTitle, &t);
1485 htmlTitle = t;
1486 }
1487 if (!(spreadsheetFlags & SPREADSHEET_ON) && !noLabels)
1488 printColumnHeaders(fpOut, printColumn, printColumns, width, pagination,
1489 latexFormat, latexTitle ? latexTitle : title,
1490 htmlFormat, htmlTitle ? htmlTitle : title);
1491 else if (!(spreadsheetFlags & SPREADSHEET_NOLABELS) && !noLabels) {
1492 for (column = 0; column < printColumns; column++)
1493 fprintf(fpOut, "%s%s", printColumn[column].name, column != printColumns - 1 ? spreadsheetDelimiter : "\n");
1494 }
1495
1496 nGroups = 1;
1497 maxGroupLength = groupLength = 1;
1498 if (latexFormat & LATEX_GROUP) {
1499 if (!(groupData = SDDS_GetColumn(inTable, latexGroupColumn))) {
1500 fprintf(stderr, "Error: unable to get data for column %s\n", latexGroupColumn);
1501 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1502 }
1503 for (row = 1; row < rows; row++) {
1504 if (strcmp(groupData[row], groupData[row - 1])) {
1505 if (groupLength > maxGroupLength)
1506 maxGroupLength = groupLength;
1507 groupLength = 1;
1508 nGroups++;
1509 } else {
1510 groupLength++;
1511 }
1512 }
1513 if (groupLength > maxGroupLength)
1514 maxGroupLength = groupLength;
1515 if (latexFormat)
1516 fprintf(fpOut, "%% nGroups = %" PRId64 ", maxGroupLength = %" PRId64 "\n", nGroups, maxGroupLength);
1517 }
1518
1519 data = tmalloc(sizeof(*data) * printColumns);
1520 format = tmalloc(sizeof(*format) * printColumns);
1521 for (column = 0; column < printColumns; column++) {
1522 if (!(data[column] = SDDS_GetColumn(inTable, printColumn[column].name))) {
1523 fprintf(stderr, "Error: unable to get data for column %s\n", printColumn[column].name);
1524 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1525 }
1526 format[column] = NULL;
1527 if (printColumn[column].format && printColumn[column].format[0]=='@') {
1528 if (!(format[column] = SDDS_GetColumn(inTable, printColumn[column].format+1))) {
1529 fprintf(stderr, "Error: unable to get format data for column %s from %s\n",
1530 printColumn[column].name, printColumn[column].format+1);
1531 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1532 }
1533 }
1534 }
1535 for (row = 0; row < rows; row++) {
1536 if (htmlFormat) {
1537 if (row % 2 == 0)
1538 fprintf(fpOut, " <tr bgcolor=\"#ddd\">\n");
1539 else
1540 fprintf(fpOut, " <tr>\n");
1541 }
1542 if (latexFormat && nGroups > 1) {
1543 if (row == 0 || strcmp(groupData[row], groupData[row - 1])) {
1544 if (row != 0 && latexFormat & LATEX_BOOKTABLE)
1545 fprintf(fpOut, "\\midrule\n");
1546 fprintf(fpOut, "\\multicolumn{%ld}{l}{\\bf %s} \\\\ \n", printColumns, groupData[row]);
1547 }
1548 }
1549 for (column = 0; column < printColumns; column++) {
1550 if (htmlFormat) {
1551 fprintf(fpOut, " <td style=\"text-align:center\">");
1552 }
1553 if (printColumn[column].type == SDDS_STRING && SDDS_StringIsBlank(*((char **)(data[column]) + row))) {
1554 sprintf(printBuffer, format[column]?format[column][row]:printColumn[column].format, " ");
1555 } else {
1556 if (!SDDS_SprintTypedValueFactor(data[column], row, printColumn[column].type,
1557 format[column]?format[column][row]:printColumn[column].format,
1558 printBuffer, SDDS_PRINT_NOQUOTES,
1559 printColumn[column].factor)) {
1560 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1561 }
1562 }
1563 if (spreadsheetFlags & SPREADSHEET_ON) {
1564 fprintf(fpOut, "%s%s%s%s", spreadsheetQuoteMark, printBuffer, spreadsheetQuoteMark, column != printColumns - 1 ? spreadsheetDelimiter : "\n");
1565 continue;
1566 }
1567 if (latexFormat) {
1568 if (SDDS_FLOATING_TYPE(printColumn[column].type))
1569 fputs(makeTexExponentialString(printBuffer), fpOut);
1570 else
1571 fputs(makeTexSafeString(printBuffer), fpOut);
1572 fputs(column != printColumns - 1 ? " & " : (latexFormat & LATEX_BOOKTABLE ? " \\\\ " : " \\\\ \\hline"), fpOut);
1573 continue;
1574 }
1575 if (htmlFormat) {
1576 fputs(trim_spaces(printBuffer), fpOut);
1577 fprintf(fpOut, "</td>\n");
1578 continue;
1579 }
1580 fputs(printBuffer, fpOut);
1581 if (printColumn[column].endsLine) {
1582 long i;
1583 fputc('\n', fpOut);
1584 if (checkPagination(fpOut, pagination, title))
1585 printColumnHeaders(fpOut, printColumn, printColumns, width, pagination, latexFormat, latexTitle ? latexTitle : title, htmlFormat, htmlTitle ? htmlTitle : title);
1586 for (i = 0; i < printColumn[column].blankLines; i++) {
1587 fputc('\n', fpOut);
1588 if (checkPagination(fpOut, pagination, title))
1589 printColumnHeaders(fpOut, printColumn, printColumns, width, pagination, latexFormat, latexTitle ? latexTitle : title, htmlFormat, htmlTitle ? htmlTitle : title);
1590 }
1591 }
1592 }
1593 if (htmlFormat) {
1594 fprintf(fpOut, " </tr>\n");
1595 } else {
1596 if (!(spreadsheetFlags & SPREADSHEET_ON) && !printColumn[column - 1].endsLine) {
1597 fputc('\n', fpOut);
1598 if (!latexFormat && !htmlFormat && checkPagination(fpOut, pagination, title))
1599 printColumnHeaders(fpOut, printColumn, printColumns, width, pagination, latexFormat, latexTitle ? latexTitle : title, htmlFormat, htmlTitle ? htmlTitle : title);
1600 }
1601 }
1602 }
1603 if (latexFormat) {
1604 if (latexFormat & LATEX_BOOKTABLE)
1605 fputs("\\bottomrule\n", fpOut);
1606 if (latexFormat & LATEX_LONGTABLE) {
1607 if (latexLabel)
1608 fprintf(fpOut, "\\label{%s}\n", latexLabel);
1609 else
1610 fprintf(fpOut, "%%\\label{%s}\n", "tab:labelHere");
1611 fprintf(fpOut, "\\end{longtable}\n");
1612 } else {
1613 fprintf(fpOut, "\\end{tabular}\n");
1614 fprintf(fpOut, "\\end{center}\n");
1615 if (latexLabel)
1616 fprintf(fpOut, "\\label{%s}\n", latexLabel);
1617 else
1618 fprintf(fpOut, "%%\\label{%s}\n", "tab:labelHere");
1619 fprintf(fpOut, "\\end{%s}\n", latexFormat & LATEX_SIDEWAYS ? "sidewaystable" : "table");
1620 }
1621 }
1622 if (htmlFormat) {
1623 fprintf(fpOut, "</table><br>\n");
1624 }
1625 for (column = 0; column < printColumns; column++) {
1626 free(data[column]);
1627 if (format[column])
1628 free(format[column]);
1629 }
1630 free(data);
1631 free(format);
1632}
1633
1634void replaceFormatWidth(char *buffer, char *format, long width) {
1635 char *ptr;
1636 ptr = format;
1637 while (*ptr) {
1638 if (*ptr == '%' && *(ptr + 1) != '%')
1639 break;
1640 ptr++;
1641 }
1642 if (*ptr) {
1643 *ptr = 0;
1644 if (*(ptr + 1) == '-') {
1645 sprintf(buffer, "%s%%-%ld", format, width);
1646 ptr++;
1647 } else
1648 sprintf(buffer, "%s%%%ld", format, width);
1649 ptr++;
1650 while (*ptr && isdigit(*ptr))
1651 ptr++;
1652 strcat(buffer, ptr);
1653 } else {
1654 strcpy(buffer, format);
1655 }
1656}
1657
1658void CreateSCHFile(char *output, char *input, unsigned long flags, char *delimiter,
1659 char *quote, PRINT_COLUMN *printColumn, long printColumns) {
1660 FILE *fp;
1661 long i;
1662
1663 if (!(fp = fopen(output, "w")))
1664 SDDS_Bomb("Couldn't open SCHFile for writing.");
1665 fprintf(fp, "[%s]\nFiletype=Delimited\nDelimiter=%s\nSeparator=%s\nCharSet=ascii\n", input ? input : "NULL", quote, delimiter);
1666 for (i = 0; i < printColumns; i++) {
1667 printColumn[i].useDefaultFormat = 1;
1668 fprintf(fp, "Field%ld=%s,%s,00,00,00\n\n", i + 1, printColumn[i].name, SDDS_NUMERIC_TYPE(printColumn[i].type) ? "Float" : "Char");
1669 }
1670}
1671
1672char *makeTexSafeString(char *source) {
1673 static char *buffer = NULL;
1674 static long buflen = 0;
1675 long index = 0, length, inMath = 0;
1676 if (!source)
1677 return source;
1678 length = strlen(source);
1679 if (length > (buflen - 2)) {
1680 buflen = length * 2 + 2;
1681 if (!(buffer = SDDS_Realloc(buffer, sizeof(*buffer) * buflen)))
1682 SDDS_Bomb("memory allocation failure");
1683 }
1684 buffer[0] = 0;
1685 while (*source) {
1686 if (*source == '_' || *source == '^' || *source == '{' || *source == '}' || *source == '%' || *source == '#') {
1687 if (!inMath)
1688 buffer[index++] = '\\';
1689 buffer[index++] = *source++;
1690 } else if (*source == '<' || *source == '>' || *source == '|') {
1691 if (!inMath)
1692 buffer[index++] = '$';
1693 buffer[index++] = *source++;
1694 if (!inMath)
1695 buffer[index++] = '$';
1696 } else {
1697 if (*source == '$')
1698 inMath = !inMath;
1699 buffer[index++] = *source++;
1700 }
1701 if (index >= (buflen - 1)) {
1702 buflen = index * 2;
1703 if (!(buffer = SDDS_Realloc(buffer, sizeof(*buffer) * buflen)))
1704 SDDS_Bomb("memory allocation failure");
1705 }
1706 }
1707 buffer[index] = 0;
1708 return buffer;
1709}
1710
1711char *makeTexExponentialString(char *text) {
1712 char *ptr1, *ptr2;
1713 char buffer[100];
1714 long exponent;
1715 if ((ptr1 = ptr2 = strchr(text, 'e'))) {
1716 trim_spaces(ptr2);
1717 while (*ptr2 && !(isdigit(*ptr2) || *ptr2 == '-'))
1718 ptr2++;
1719 if (!*ptr2)
1720 return text;
1721 if (strlen(ptr2) >= 100)
1722 bomb("buffer overflow in makeTexExponentialString", NULL);
1723 sscanf(ptr2, "%ld", &exponent);
1724 *ptr1 = 0;
1725 if (exponent != 0) {
1726 sprintf(buffer, "%ld", exponent);
1727 sprintf(ptr1, "$\\times 10^{%s}$", buffer);
1728 }
1729 }
1730 return text;
1731}
1732
1733htab *readTranslationTable(char *TranslationFile) {
1734 htab *ht;
1735 SDDS_DATASET SDDSin;
1736 char **oldName, **newName;
1737 int64_t rows;
1738#if defined(_WIN32)
1739 fprintf(stderr, "The latex and html options in sddsprintout is not available on Windows\n");
1740 exit(1);
1741#else
1742 ht = hcreate(12);
1743 if (!SDDS_InitializeInput(&SDDSin, TranslationFile) ||
1744 SDDS_ReadPage(&SDDSin) < 0 ||
1745 (rows = SDDS_RowCount(&SDDSin)) <= 0 ||
1746 !(oldName = SDDS_GetColumn(&SDDSin, "OldName")) ||
1747 !(newName = SDDS_GetColumn(&SDDSin, "NewName"))) {
1748 SDDS_Bomb("Problem with translation file");
1749 } else {
1750 while (--rows >= 0)
1751 hadd(ht, oldName[rows], strlen(oldName[rows]), newName[rows]);
1752 }
1753 return ht;
1754#endif
1755}
1756
1757char *findTranslation(htab *ht, char *key) {
1758#if defined(_WIN32)
1759 SDDS_Bomb("The latex and html options in sddsprintout is not available on Windows");
1760#else
1761 if (key && ht && hfind(ht, key, strlen(key)) == TRUE)
1762 return (char *)hstuff(ht);
1763#endif
1764 return key;
1765}
1766
1767char *modifyUnitsWithFactor(char *units0, double factor, unsigned long latexFormat) {
1768 char *units, buffer[100];
1769
1770 units = tmalloc(sizeof(*units) * ((units0 ? strlen(units0) : 0) + 100));
1771
1772 if (latexFormat) {
1773 sprintf(buffer, "%.2g", factor);
1774 sprintf(units, "%s%s", makeTexExponentialString(buffer), units0 ? units0 : "");
1775 } else {
1776 sprintf(units, "%.2g%s", factor, units0 ? units0 : "");
1777 }
1778 return units;
1779}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
void * SDDS_GetColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves a copy of the data for a specified column, including only rows marked as "of interest".
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
char * SDDS_GetParameterAsString(SDDS_DATASET *SDDS_dataset, char *parameter_name, char **memory)
Retrieves the value of a specified parameter as a string from the current data table of an SDDS datas...
void * SDDS_GetParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory)
Retrieves the value of a specified parameter from the current data table of a data set.
int32_t SDDS_GetParameterInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified parameter in the SDDS dataset.
Definition SDDS_info.c:117
int32_t SDDS_GetColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified column in the SDDS dataset.
Definition SDDS_info.c:41
void SDDS_SetTerminateMode(uint32_t mode)
int32_t SDDS_ReadPageSparse(SDDS_DATASET *SDDS_dataset, uint32_t mode, int64_t sparse_interval, int64_t sparse_offset, int32_t sparse_statistics)
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_GetParameterType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a parameter in the SDDS dataset by its index.
int32_t SDDS_ZeroMemory(void *mem, int64_t n_bytes)
Sets a block of memory to zero.
int32_t SDDS_VerifyPrintfFormat(const char *string, int32_t type)
Verifies that a printf format string is compatible with a specified data type.
Definition SDDS_utils.c:750
int32_t SDDS_ParameterCount(SDDS_DATASET *page)
Retrieves the number of parameters in the SDDS dataset.
int32_t SDDS_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter in the SDDS dataset.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
int32_t SDDS_MatchParameters(SDDS_DATASET *SDDS_dataset, char ***nameReturn, int32_t matchMode, int32_t typeMode,...)
Matches and retrieves parameter names from an SDDS dataset based on specified criteria.
int32_t SDDS_ColumnCount(SDDS_DATASET *page)
Retrieves the number of columns in the SDDS dataset.
int32_t SDDS_SprintTypedValueFactor(void *data, int64_t index, int32_t type, const char *format, char *buffer, uint32_t mode, double factor)
Reallocates memory to a new size and zero-initializes the additional space.
Definition SDDS_utils.c:186
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
int32_t SDDS_IdentifyType(char *typeName)
Identifies the SDDS data type based on its string name.
int32_t SDDS_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
int32_t SDDS_MatchColumns(SDDS_DATASET *SDDS_dataset, char ***nameReturn, int32_t matchMode, int32_t typeMode,...)
Matches and retrieves column names from an SDDS dataset based on specified criteria.
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
int32_t SDDS_CheckParameter(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a parameter exists in the SDDS dataset with the specified name, units, and type.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
#define SDDS_NUM_TYPES
Total number of defined SDDS data types.
Definition SDDStypes.h:97
#define SDDS_ULONG
Identifier for the unsigned 32-bit integer data type.
Definition SDDStypes.h:67
#define SDDS_FLOAT
Identifier for the float data type.
Definition SDDStypes.h:43
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_ULONG64
Identifier for the unsigned 64-bit integer data type.
Definition SDDStypes.h:55
#define SDDS_FLOATING_TYPE(type)
Checks if the given type identifier corresponds to a floating-point type.
Definition SDDStypes.h:124
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_SHORT
Identifier for the signed short integer data type.
Definition SDDStypes.h:73
#define SDDS_CHARACTER
Identifier for the character data type.
Definition SDDStypes.h:91
#define SDDS_USHORT
Identifier for the unsigned short integer data type.
Definition SDDStypes.h:79
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
Definition SDDStypes.h:138
#define SDDS_LONGDOUBLE
Identifier for the long double data type.
Definition SDDStypes.h:31
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
Definition SDDStypes.h:49
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
htab * hcreate(word logsize)
Create a hash table.
Definition hashtab.c:124
word hadd(htab *t, ub1 *key, ub4 keyl, void *stuff)
Add an item to the hash table.
Definition hashtab.c:207
word hfind(htab *t, ub1 *key, ub4 keyl)
Find an item with a given key in the hash table.
Definition hashtab.c:178
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
char * pad_with_spaces(char *s, int n)
Adds a specified number of spaces to the end of a string.
int replaceString(char *t, char *s, char *orig, char *repl, long count_limit, long here)
Replace occurrences of one string with another string with additional options.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.
char * trim_spaces(char *s)
Trims leading and trailing spaces from a string.
Definition trim_spaces.c:28