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