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