272 {
274 long i, i_arg, pageNumber, width;
275 SCANNED_ARG *s_arg;
276 char *input, *output, **name, *format, *title, *label, *editLabel, *schFile;
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;
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)
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);
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,
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,
346 "nounits", -1, NULL, 0, NO_UNITS,
347 "factor",
SDDS_DOUBLE, &factor, 1, FACTOR_GIVEN, NULL))
349 for (i = 0; i < names; i++) {
351 printColumn[i + printColumns].name = name[i];
352 if (format) {
354 replaceString(formatbuffer2, formatbuffer,
"lu", PRIu32, -1, 0);
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);
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,
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,
392 "factor",
SDDS_DOUBLE, &factor, 1, FACTOR_GIVEN, NULL))
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) {
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);
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,
430 for (i = 0; i < names; i++) {
431 printArray[i + printArrays].name = name[i];
432 if (format) {
434 replaceString(formatbuffer2, formatbuffer,
"lu", PRIu32, -1, 0);
436 }
437 }
438 free(name);
439 printArrays += names;
440 break;
441 case SET_FROMPAGE:
442 if (s_arg[i_arg].n_items < 2)
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)
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))
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)
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,
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,
540 "caption",
SDDS_STRING, &latexCaption, 1, LATEX_CAPTION,
541 "comment",
SDDS_STRING, &latexComment, 1, LATEX_COMMENT,
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)
563 markdownFormat |= MARKDOWN_FORMAT;
564 break;
565 default:
566 fprintf(stderr, "error: unknown switch: %s\n", s_arg[i_arg].list[0]);
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
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
609 exit(EXIT_FAILURE);
610 }
611
612 fpOut = stdout;
613 if (output && !(fpOut = fopen(output, "w")))
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
620
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));
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));
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
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);
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);
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
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);
745 return EXIT_SUCCESS;
746}
int32_t SDDS_ZeroMemory(void *mem, int64_t n_bytes)
Sets a block of memory to zero.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
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.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#define SDDS_DOUBLE
Identifier for the double data type.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
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.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
void free_scanargs(SCANNED_ARG **scanned, int argc)
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.