/*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * This file is distributed subject to a Software License Agreement found * in the file LICENSE that is included with this distribution. \*************************************************************************/ /* program: sddsprintout * purpose: make a printout from SDDS data * * Michael Borland, 1995 $Log: sddsprintout.c,v $ Revision 1.48 2011/07/24 22:23:54 borland Now makes nicer exponential strings in latex output mode. Revision 1.47 2009/08/05 15:35:23 soliday Updated to replace ld and lu in the format strings with PRId32 and PRIu32 Revision 1.46 2009/08/04 19:46:09 soliday Updated to convert %ld format strings to %d for 64 bit systems. Revision 1.45 2008/08/06 20:46:49 soliday Fixed the format strings. Revision 1.44 2008/06/06 18:10:32 soliday Fixed a problem with one of the elements has the maximum number of characters that SDDS will allow. Revision 1.43 2006/10/19 17:55:40 soliday Updated to work with linux-x86_64. Revision 1.42 2006/08/31 15:08:55 soliday Updated to work with SDDS2. Revision 1.41 2005/11/04 22:46:17 soliday Updated code to be compiled by a 64 bit processor. Revision 1.40 2004/04/21 20:07:52 shang the program will exit if checking datatype with format fails Revision 1.39 2004/01/08 03:33:46 borland Added escaping of latex output strings so that special characters don't cause latex processing problems. Revision 1.38 2004/01/06 20:11:25 borland Added cpation to latex table output. Revision 1.37 2003/12/03 00:11:17 borland Added -latexFormat option for output of a LaTeX table. Revision 1.36 2002/12/11 21:39:15 borland Provided a slight speedup in processing large files when no columns are printed by using SDDS_ReadPageSparse(). Revision 1.35 2002/08/14 17:12:51 soliday Added Open License Revision 1.34 2002/07/25 00:12:40 borland Now check return values from SDDS_SprintTypedValue(). Revision 1.33 2001/09/05 20:16:34 shang added cvs feature to -spreadsheet option, which has the same function as -spreadsheet=quote=\",delimiter=\\, -notitle. And modified the default format output to be the actual format when csv option is given. Revision 1.32 2001/01/10 19:35:43 soliday Standardized usage message. Revision 1.31 2000/04/13 19:51:20 soliday Added missing include statement. Revision 1.30 1999/08/11 17:50:29 borland Added -bufferlines option for putting blank lines between pages. Revision 1.29 1999/05/25 19:13:30 soliday Removed compiler warning on linux. Revision 1.28 1999/01/06 19:54:51 borland Fixed the version number in the usage message. Revision 1.27 1998/08/24 14:42:10 soliday Fixed bug when fromPage and toPage options are both used Revision 1.26 1998/08/21 20:58:52 soliday Added a noLabels option that works with columns and parameters Revision 1.25 1996/11/15 00:30:30 borland Added option to generate SCH file for spreadsheet output. Revision 1.24 1996/11/15 00:15:17 borland Added quote-mark and label control for spreadsheet mode. Revision 1.23 1996/11/12 20:45:16 borland Fixed bug with reuse of buffer used for edited column label. Revision 1.22 1996/11/11 20:11:02 borland Removed statements that added spaces after each field, as they aren't needed with new format string padding. Added sensitivity to spreadsheet mode for format string modification routine. Revision 1.21 1996/11/11 18:43:26 borland Some debugging statements added. Revision 1.20 1996/11/07 22:18:22 borland Better handling of field width adjustments for long labels. Now modifies user or default format string to fill available space, rather than trying to do symmetric space padding. * Revision 1.19 1996/07/05 16:09:49 borland * Removed routine cleanUpQuotes and started using SDDS_PRINT_NOQUOTES * mode to SDDS_SprintTypedValue. Also, detects blank string data * and substitutes " " to get proper filling of field. * * Revision 1.18 1996/05/13 20:33:58 borland * Added -postPageLines option to allow putting blank lines after a page. * * Revision 1.17 1996/02/29 18:20:00 borland * Added -noWarnings option, and implemented in all relevant subroutines. * * Revision 1.16 1996/02/21 16:08:38 borland * For spreadsheet output, now set width=0 and use this to flag no line breaks * for a row. User may reset width using -width option to get old behavior, * though I doubt anyone will. * * Revision 1.15 1996/02/14 01:05:33 borland * Changed over from scan_item_list() to scanItemList(). * * Revision 1.14 1996/02/07 18:13:25 borland * checkPagination now initializes currentLine to 0 rather than 1, which gets * the right number of lines per page. * * Revision 1.13 1996/02/07 17:43:19 borland * Added initialization for currentLine field of PAGINATION structure. * * Revision 1.12 1996/02/05 23:57:06 borland * Added -pagination option. * * Revision 1.11 1996/01/29 22:28:42 borland * Added editLabel qualifier to -column and -parameter options. * * Revision 1.10 1996/01/12 19:03:13 borland * Added -spreadsheet option. * * Revision 1.9 1995/09/25 16:37:13 borland * Modified header code for column output to eliminate units line if all units * are blank. * * Revision 1.8 1995/09/18 17:26:01 borland * Added label qualifers to -parameter and -column options. * * Revision 1.7 1995/09/15 21:31:40 borland * Added -title option, and changed -noHeader option to -noTitle. * * Revision 1.6 1995/09/15 15:24:00 borland * Added useDefaultFormat qualifer to -column and -parameter options. Added * code to ensure use of any format_string defined in the SDDS file before * any other string. * * Revision 1.5 1995/09/14 22:01:05 borland * Added blankLines qualifier to -parameter and -column options. * * Revision 1.4 1995/09/14 04:28:00 borland * Added -noHeader option to allow elimination of header on first page of * printout. * * Revision 1.3 1995/09/06 14:56:57 saunders * First test release of SDDS1.5 * */ #include #include "mdb.h" #include "SDDS.h" #include "scan.h" /*#include "SDDSaps.h"*/ #define SET_COLUMNS 0 #define SET_PARAMETERS 1 #define SET_ARRAYS 2 #define SET_FROMPAGE 3 #define SET_TOPAGE 4 #define SET_FORMATDEFAULTS 5 #define SET_WIDTH 6 #define SET_PIPE 7 #define SET_PAGEADVANCE 8 #define SET_NOTITLE 9 #define SET_TITLE 10 #define SET_SPREADSHEET 11 #define SET_PAGINATE 12 #define SET_NOWARNINGS 13 #define SET_POSTPAGELINES 14 #define SET_NOLABELS 15 #define SET_BUFFERLINES 16 #define SET_LATEXFORMAT 17 #define N_OPTIONS 18 char *option[N_OPTIONS] = { "columns", "parameters", "arrays", "frompage", "topage", "formatdefaults", "width", "pipe", "pageadvance", "notitle", "title", "spreadsheet", "paginate", "nowarnings", "postpagelines", "nolabels", "bufferlines", "latexformat" } ; char *USAGE = "sddsprintout [] [] [-pipe=[input][,output]] \n\ [-columns[=[,format=][,label=][,editLabel=][,useDefaultFormat][,endsline][,blankLines=]]] \n\ [-parameters[=[,format=][,label=][,editLabel=][,useDefaultFormat][,endsline][,blankLines=[,format=]] \n\ [-fromPage=] [-toPage=] \n\ [-formatDefaults==[,...]]\n\ [-width=] [-pageAdvance] [-paginate[=lines=][,notitle][,nolabels]]\n\ [-noTitle] [-title=] [-noLabels] [-postPageLines=]\n\ [-spreadsheet[=delimiter=][,quotemark=][,nolabels][,csv][,schfile=]]\n\ [-latexFormat] [-noWarnings]\n\ -spreadsheet=csv is the simple way of -spreadsheet=nolabels,quote=\",delimiter=\\, -notitle \n\n\ Program by Michael Borland. (This is version 7, August 1998.)\n"; #define PAGINATION_ON 0x0001U #define PAGINATION_NOTITLE 0x0002U #define PAGINATION_NOLABELS 0x0004U typedef struct { int32_t lines; long currentLine; unsigned long flags; } PAGINATION; #define ENDSLINE 0x0001U #define USEDEFAULTFORMAT 0x0002U #define LABEL_GIVEN 0x0004U #define EDITLABEL_GIVEN 0x0008U typedef struct { char *name, *format, **header, *label, *editLabel; long fieldWidth, index, headers, type, endsLine, blankLines, useDefaultFormat; void *data; } PRINT_COLUMN; typedef struct { char *name, *format, *label, *editLabel; long fieldWidth, index, type, endsLine, blankLines, useDefaultFormat; void *data; } PRINT_PARAMETER; typedef struct { char *name, *format, *label; long index; SDDS_ARRAY *array; } PRINT_ARRAY; char *makeTexSafeString(char *source); char *makeTexExponentialString(char *text); void copyAndPad(char *target, char *source, long sourceWidth, long targetWidth); long makeColumnHeaders(char ***header, long *fieldWidth, char *name, char *editLabel, char *units, char **format, unsigned long spreadsheetFlags); char *makeParameterLabel(long *fieldWidth, char *name, char *editLabel, char *units, char *format); long changeDefaultFormats(char **argv, long argc, long noWarnings); void setDefaultFormats(void); long processPrintColumns(PRINT_COLUMN **printRequestPtr, long printRequests, SDDS_DATASET *inTable, long noWarnings, unsigned long spreadsheetFlags,long csv); void printColumnHeaders(FILE *fpOut, PRINT_COLUMN *printColumn, long printColumns, long width, PAGINATION *pagination, long latexFormat, char *latexTitle); long processPrintParameters(PRINT_PARAMETER **printRequestPtr, long printRequests, SDDS_DATASET *inTable, long noWarnings, long noLabels,long csv); long processPrintArrays(PRINT_ARRAY **printRequestPtr, long printRequests, SDDS_DATASET *inTable); long getFormatFieldLength(char *format, long *extraChars); char **makeListOfNames(char *string, long *names); void doPrintParameters(SDDS_DATASET *inTable, PRINT_PARAMETER *printParameter, long printParameters, long width, FILE *fpOut, unsigned long spreadsheetFlags, char *spreadsheetDelimiter, char *spreadsheetQuoteMark, PAGINATION *pagination, char *title, long noLabels); long characterCount(char *string, char c); long printPageTitle(FILE *fpOut, char *title); void doPrintColumns(SDDS_DATASET *inTable, PRINT_COLUMN *printColumn, long printColumns, long width, FILE *fpOut, unsigned long spreadsheetFlags, char *spreadsheetDelimiter, char *spreadsheetQuoteMark, long latexFormat, char *latexTitle, PAGINATION *pagination, char *title, long noLabels); long checkPagination(FILE *fpOut, PAGINATION *pagination, char *title); void replaceFormatWidth(char *buffer, char *format, long width); void CreateSCHFile(char *output, char *input, unsigned long flags, char *delimiter, char *quote, PRINT_COLUMN *printColumn, long printColumns); static char **defaultFormat = NULL; static char **csvFormat=NULL; #define SPREADSHEET_ON 0x0001U #define SPREADSHEET_DELIMITER 0x0002U #define SPREADSHEET_QUOTEMARK 0x0004U #define SPREADSHEET_NOLABELS 0x0008U #define SPREADSHEET_CSV 0x0010UL int main(int argc, char **argv) { SDDS_DATASET SDDS_dataset; long i, i_arg, pageNumber, width; SCANNED_ARG *s_arg; char *input, *output, **name, *format, *title, *label, *editLabel, *schFile; PRINT_COLUMN *printColumn; PRINT_PARAMETER *printParameter; PRINT_ARRAY *printArray; long printColumns, printParameters, printArrays, firstPage, bufferLines; long fromPage, toPage, names, pageAdvance, noTitle, noLabels, noWarnings; int32_t blankLines; long latexFormat; FILE *fpOut; unsigned long flags, pipeFlags, spreadsheetFlags, dummyFlags, postPageLines,CSV=0; char *spreadsheetDelimiter, *spreadsheetQuoteMark; PAGINATION pagination; char **formatDefaultArg; long formatDefaultArgs; static char formatbuffer[100], formatbuffer2[100]; SDDS_RegisterProgramName(argv[0]); argc = scanargs(&s_arg, argc, argv); if (argc<3) bomb(NULL, USAGE); input = output = NULL; fromPage = toPage = 0; printColumn = NULL; printParameter = NULL; printArray = NULL; width = 130; setDefaultFormats(); printColumns = printParameters = printArrays = pipeFlags=flags=0; postPageLines = pageAdvance = noTitle = noLabels = 0; title = NULL; spreadsheetFlags = 0; pagination.flags = pagination.currentLine = 0; noWarnings = 0; formatDefaultArgs = 0; schFile = NULL; formatDefaultArg = NULL; bufferLines = 0; latexFormat = 0; for (i_arg=1; i_argtoPage) SDDS_Bomb("invalid -fromPage and -toPage"); if (!SDDS_InitializeInput(&SDDS_dataset, input)) { SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors); exit(1); } fpOut = stdout; if (output && !(fpOut=fopen(output, "w"))) SDDS_Bomb("unable to open output file"); printColumns = processPrintColumns(&printColumn, printColumns, &SDDS_dataset, noWarnings, spreadsheetFlags,CSV); printParameters = processPrintParameters(&printParameter, printParameters, &SDDS_dataset, noWarnings, noLabels,CSV); /* printArrays = processPrintArrays(&printArray, printArrays, &SDDS_dataset); */ SDDS_SetTerminateMode(TERMINATE_DONT_FREE_TABLE_STRINGS+ TERMINATE_DONT_FREE_ARRAY_STRINGS); firstPage = 1; pagination.flags |= noTitle?PAGINATION_NOTITLE:0; if (!title) { title = tmalloc(sizeof(*title)*( (input?strlen(input):10)+100)); sprintf(title, "Printout for SDDS file %s\n", input?input:"stdin"); } if (schFile) { if (printArrays || printParameters || !printColumns) SDDS_Bomb("Can't create schFile except for pure column printout."); CreateSCHFile(schFile, input, spreadsheetFlags, spreadsheetDelimiter, spreadsheetQuoteMark, printColumn, printColumns); } if (latexFormat) noTitle = 1; while ((pageNumber=SDDS_ReadPageSparse(&SDDS_dataset, 0, printColumns?1:1000000, 0))>0) { if ((fromPage && pageNumbertoPage)) continue; if (pagination.flags&PAGINATION_ON) { if (!firstPage) { fputc('\014', fpOut); pagination.currentLine = 1; } if (!noTitle) pagination.currentLine += printPageTitle(fpOut, title); } else { if (firstPage) { if (!noTitle) printPageTitle(fpOut, title); } else if (pageAdvance) fputc('\014', fpOut); else if (postPageLines>0) { long line=postPageLines; while (line--) fputc('\n', fpOut); } } doPrintParameters(&SDDS_dataset, printParameter, printParameters, width, fpOut, spreadsheetFlags, spreadsheetDelimiter, spreadsheetQuoteMark, &pagination, title, noLabels); /* doPrintArrays(&SDDS_dataset, printArray, printArrays, width, fpOut, &pagination); */ doPrintColumns(&SDDS_dataset, printColumn, printColumns, width, fpOut, spreadsheetFlags, spreadsheetDelimiter, spreadsheetQuoteMark, latexFormat, title, &pagination, title, noLabels); if (bufferLines) { for (i=0; i0) { for (iname=0; iname%s<\n", printRequest[irequest].label?printRequest[irequest].label:name[iname], printColumn[printColumns].format); #endif printColumn[printColumns].data = NULL; printColumns++; columnUsed[index] = 1; if (units) free(units); } free(name[iname]); } free(name); } else if (names<0) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); else if (!noWarnings) fprintf(stderr, "warning: no column matches %s\n", printRequest[irequest].name); free(printRequest[irequest].name); if (printRequest[irequest].format) free(printRequest[irequest].format); } free(printRequest); *printRequestPtr = printColumn; return printColumns; } long processPrintParameters(PRINT_PARAMETER **printRequestPtr, long printRequests, SDDS_DATASET *inTable, long noWarnings, long noLabels,long csv) { PRINT_PARAMETER *printParameter, *printRequest; long i, irequest, iname, printParameters, names, *parameterUsed, parameterLimit, maxFieldWidth, index; char **name, *units, *format; if (printRequests<1 || !(printRequest= *printRequestPtr)) return 0; if ((parameterLimit=SDDS_ParameterCount(inTable))<0) { if (!noWarnings) fprintf(stderr, "warning: no parameter data in input file\n"); return 0; } parameterUsed = tmalloc(sizeof(*parameterUsed)*parameterLimit); for (i=0; i0) { for (iname=0; inamemaxFieldWidth) maxFieldWidth = printParameter[printParameters].fieldWidth; printParameter[printParameters].data = NULL; printParameters++; parameterUsed[index] = 1; if (units) free(units); } free(name[iname]); } free(name); } else if (names<0) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); else if (!noWarnings) fprintf(stderr, "warning: no parameter matches %s\n", printRequest[irequest].name); free(printRequest[irequest].name); if (printRequest[irequest].format) free(printRequest[irequest].format); } for (i=0; i%s<\n", *fieldWidth, (*header)[1]); (*header)[1][0] = '+'; (*header)[1][strlen((*header)[1])-1] = '-'; #endif return headers; } void copyAndPad(char *target, char *source, long sourceWidth, long targetWidth) { long i, head, tail, excess; if ((excess=targetWidth-sourceWidth)<0) SDDS_Bomb("negative excess in copyAndPad()---programming error"); head = tail = excess/2; if ((i=excess-head-tail)) head += i; for (i=0; iwidth)) { fputc('\n', fpOut); checkPagination(fpOut, pagination, title); outputRow = length-2; if (parameter && printParameter[parameter-1].blankLines && printParameter[parameter-1].endsLine) { long i; for (i=1; iflags&PAGINATION_ON)) return 0; if ((pagination->currentLine+=1)>=pagination->lines) { fputc('\014', fpOut); pagination->currentLine = 0; if (!(pagination->flags&PAGINATION_NOTITLE)) pagination->currentLine += printPageTitle(fpOut, title); return 1; } return 0; } void printColumnHeaders(FILE *fpOut, PRINT_COLUMN *printColumn, long printColumns, long width, PAGINATION *pagination, long latexFormat, char *latexTitle) { long row, column, header, outputRow, maxOutputRow, length, noUnitsLine; if (latexFormat) { fprintf(fpOut, "\\begin{table}[htb]\\caption{%s}\n", latexTitle?makeTexSafeString(latexTitle):"No caption"); fprintf(fpOut, "\\begin{center}\n"); fprintf(fpOut, "\\begin{tabular}{|"); for (column=0; columnwidth))) { printColumn[column-1].endsLine = 1; fputc('\n', fpOut); pagination->currentLine ++; outputRow = 0; } if (latexFormat) { fputs(makeTexSafeString(printColumn[column].header[header]), fpOut); fputs(column==printColumns-1?" \\\\ \\hline ":" & ", fpOut); } else { fputs(printColumn[column].header[header], fpOut); outputRow += length; if (outputRow>maxOutputRow) maxOutputRow = outputRow; } } fputc('\n', fpOut); pagination->currentLine ++; } if (!latexFormat) { for (row=0; rowcurrentLine ++; } void doPrintColumns(SDDS_DATASET *inTable, PRINT_COLUMN *printColumn, long printColumns, long width, FILE *fpOut, unsigned long spreadsheetFlags, char *spreadsheetDelimiter, char *spreadsheetQuoteMark, long latexFormat, char *latexTitle, PAGINATION *pagination, char *title, long noLabels) { long row, column, rows; void **data; char printBuffer[16*SDDS_MAXLINE]; if (!printColumns) return; if ((rows=SDDS_CountRowsOfInterest(inTable))<0) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); else if (!rows) return; if (!(spreadsheetFlags&SPREADSHEET_ON) && !noLabels) printColumnHeaders(fpOut, printColumn, printColumns, width, pagination, latexFormat, latexTitle); else if (!(spreadsheetFlags&SPREADSHEET_NOLABELS) && !noLabels) { for (column=0; column(buflen-2)) { buflen = length*2+2; if (!(buffer = SDDS_Realloc(buffer, sizeof(*buffer)*buflen))) SDDS_Bomb("memory allocation failure"); } buffer[0] = 0; while (*source) { if (*source=='_' || *source=='^' || *source=='{' || *source=='}' || *source=='%') { buffer[index++] = '\\'; buffer[index++] = *source++; } else if (*source=='<' || *source=='>' || *source=='|') { buffer[index++] = '$'; buffer[index++] = *source++; buffer[index++] = '$'; } else buffer[index++] = *source++; if (index>=(buflen-1)) { buflen = index*2; if (!(buffer = SDDS_Realloc(buffer, sizeof(*buffer)*buflen))) SDDS_Bomb("memory allocation failure"); } } buffer[index] = 0; return buffer; } char *makeTexExponentialString(char *text) { char *ptr1, *ptr2; char buffer[100]; if (ptr1=ptr2=strchr(text, 'e')) { trim_spaces(ptr2); while (*ptr2 && !isdigit(*ptr2)) ptr2++; if (!*ptr2) return text; while (*ptr2=='0') ptr2++; if (!*ptr2) *ptr1 = NULL; else { if (strlen(ptr2)>=100) bomb("buffer overflow in makeTexExponentialString", NULL); strcpy(buffer, ptr2); sprintf(ptr1, "$\\times 10^{%s}$", buffer); } } return text; }