/* ############################################################################# # # # Copyright (C) 2003-2011 Michael Besteck (swdev@web.de) # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; version 2 of the License, no other version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, it is available under the URL # # http://www.gnu.org/licenses/gpl-2.0.html as of 2011-03-12, # # or write to the Free SoftwareFoundation, # # Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # # # # The author can be contacted by email to swdev@web.de # # # # More infos: http://techinfo.system33.de/LinuxOnGericom/index.html#BIPI # # # ############################################################################# */ /* * Motivation: Minimal "working skeleton" of a flex/C application where * flex means "fast lexical analyser generator". * See also the flex homepage at http://flex.sourceforge.net/ * * Allgemeine Funktionsweise: ersetzt LineBreak-Zeichen(folgen) durch andere * Functionality: replaces LineBreak strings by different ones * Input: stdin or file, Output: stdout or file * * To build: * * 1. flex -8 chgLineBreaks.flex * (outputs lex.yy.c, "chgLineBreaks.flex" is this file), * * 2. gcc -o chgLineBreaks lex.yy.c * (outputs executable "chgLineBreaks") * as of gcc version 4.4.3 * 4 warnings may appear which can be ignored in this case. * * Help: man flex (manual), gcc --help * */ %{ /* C code start */ /* VARIABLES */ int foundCR = 0; int foundCRLF = 0; int foundLF = 0; int foundLFCR = 0; int replaced = 0; int parm_help = 0; int parm_stats = 0; int convertCR = 0; int convertCRLF = 1; /* default line break type to change */ int convertLF = 0; int convertLFCR = 0; int convertEMPTY = 0; FILE* FP; FILE* FPar; FILE* FPtmp; char* pFilepath = NULL; static char *rpsN = "\n"; #define iLF 0 static char *rpsNR = "\n\r"; #define iLFCR 1 static char *rpsR = "\r"; #define iCR 2 static char *rpsRN = "\r\n"; #define iCRLF 3 static char *rpsNONE = ""; #define iNONE 4 static char *rpsUSERSTR = ""; #define iUSERSTR 5 char *replacementStr[6]; int replacementIdx = 0; /* default substitution char is "x", i.e. "\n" */ %} /* C code end */ %option noyywrap %pointer LF \n CR \r CRLF {CR}{LF} LFCR {LF}{CR} %{ /* C code start */ /** * Prints usage to stdout. */ void help() { fprintf(FP, "program chgLineBreaks\n"); fprintf(FP, "changes Line Breaks\n"); fprintf(FP, "typical use (X-Syntax):\n"); fprintf(FP, "\"chgLineBreaks -change win -set x -r FileToConvert.txt\"\n"); fprintf(FP, "typical streaming use (X-Syntax):\n"); fprintf(FP, "\"cat FileToConvert.txt | chgLineBreaks -q -change win -set x > ConvertedFile.txt\"\n"); fprintf(FP, "Syntax to start:\n"); fprintf(FP, "\nchgLineBreaks [-h] [-s] [-change mac|win|x|all|!|CR|LF|CRLF|LFCR] [[-set mac|win|x|CR|LF|CRLF|LFCR|none]|[-setstr ]] [-fo |-foa |-r ]\n\n"); fprintf(FP, "-h\tdisplay this help and exit\n\n"); fprintf(FP, "-s\tdisplay statistics to stdout after conversion\n\n"); fprintf(FP, "-change\tspecifies the type of line break characters to change.\n"); fprintf(FP, "\tDefault is \"win\"\n\n"); fprintf(FP, "-set\tspecifies the type of line break substitute character\n"); fprintf(FP, "\tDefault is \"x\"\n\n"); fprintf(FP, "\tmac\tsame as CR\n"); fprintf(FP, "\twin\tsame as CRLF\n"); fprintf(FP, "\tx\tsame as LF\n"); fprintf(FP, "\tCR\tASCII 13 (=0x0d)\n"); fprintf(FP, "\tCRLF\tASCII 13 (=0x0d), ASCII 10 (0x0a)\n"); fprintf(FP, "\tLF\tASCII 10 (=0x0a)\n"); fprintf(FP, "\tLFCR\tASCII 10 (=0x0a), ASCII 13 (0x0d) UNUSUAL LINE BREAK\n"); fprintf(FP, "\tall\tmac or win or x\n"); fprintf(FP, "\t!\tmac or win or x or LFCR\n"); fprintf(FP, "\tnone\tempty string (only valid for replacement to strip new line characters)\n\n"); fprintf(FP, "-setstr\tspecifies any string to substitute line breaks\n"); fprintf(FP, "\tThe parameter to -setstr is not optional, the string following on the command line will be used for replacement\n\n"); fprintf(FP, "\t\tany string (only valid for replacement)\n\n"); fprintf(FP, "If both, -set and -setstr, are specified, the latter noted will be applied.\n\n"); fprintf(FP, "-fo\twrites output to file\n"); fprintf(FP, "\tAny existing file of the same name will be deleted.\n\tDefault is stdout\n\n"); fprintf(FP, "-foa\tappends output to file\n"); fprintf(FP, "\tIf not exists the file will be created.\n\tDefault is stdout\n\n"); fprintf(FP, "-r\treplaces with the converted version\n"); fprintf(FP, "\tIf not exists the program will abruptly terminate with a status of -1 (255)\n\n"); fprintf(FP, "Actual settings:\n"); fprintf(FP, "Output to %s\n", ((pFilepath != NULL) ? pFilepath : "stdout")); fprintf(FP, "Change input CR: %s\n", ((convertCR == 0) ? "NO" : "YES")); fprintf(FP, "Change input CRLF: %s\n", ((convertCRLF == 0) ? "NO" : "YES")); fprintf(FP, "Change input LF: %s\n", ((convertLF == 0) ? "NO" : "YES")); fprintf(FP, "Change input LFCR: %s\n", ((convertLFCR == 0) ? "NO" : "YES")); fprintf(FP, "replace by : %s\n", ((replacementIdx == iCR) ? "CR" : (replacementIdx == iLF != 0) ? "LF" : (replacementIdx == iCRLF != 0) ? "CRLF" : (replacementIdx == iLFCR != 0) ? "LFCR" : (replacementIdx == iNONE != 0) ? "none" : "ERROR") ); } /** * Defines which line-break strings to convert by the token character * input'. * * @param s The string specifying the type of line break to convert. */ static void inputTypeByPar(char* s) { if (0 == strcmp("mac", s)) { convertCR = 1; convertCRLF = convertLF = convertLFCR = 0; } else if (0 == strcmp("win", s)) { convertCRLF = 1; convertCR = convertLF = convertLFCR = 0; } else if (0 == strcmp("x", s)) { convertLF = 1; convertCR = convertCRLF = convertLFCR = 0; } else if (0 == strcmp("all", s)) { convertLF = convertCRLF = convertCR = 1; convertLFCR = 0; } else if (0 == strcmp("!", s)) { convertLFCR = convertLF = convertCRLF = convertCR = 1; } else if (0 == strcmp("CR", s)) { convertCR = 1; convertCRLF = convertLF = convertLFCR = 0; } else if (0 == strcmp("CRLF", s)) { convertCRLF = 1; convertCR = convertLF = convertLFCR = 0; } else if (0 == strcmp("LF", s)) { convertLF = 1; convertCR = convertCRLF = convertLFCR = 0; } else if (0 == strcmp("LFCR", s)) { convertLFCR = 1; convertCR = convertCRLF = convertLF = 0; } /* else default stays CRLF */ } /** * Defines the line-break replacement string by the token character * input'. * * @param s The string specifying the type of line break replacement. * * @param s */ void outputTypeByPar(char* s) { if (0 == strcmp("mac", s)) { replacementIdx = iCR; } else if (0 == strcmp("win", s)) { replacementIdx = iCRLF; } else if (0 == strcmp("x", s)) { replacementIdx = iLF; } else if (0 == strcmp("CR", s)) { replacementIdx = iCR; } else if (0 == strcmp("CRLF", s)) { replacementIdx = iCRLF; } else if (0 == strcmp("LF", s)) { replacementIdx = iLF; } else if (0 == strcmp("LFCR", s)) { replacementIdx = iLFCR; } else if (0 == strcmp("none", s)) { replacementIdx = iNONE; } /* else replacementIdx stays default */ } /** * Prints a summary of processing after that is finished to stdout. */ void summary(FILE* output) { fprintf(output, "Output written to %s\n", ((pFilepath != NULL) ? pFilepath : "stdout")); fprintf(output, "CR converted\t%d\n", foundCR); fprintf(output, "CRLF converted\t%d\n", foundCRLF); fprintf(output, "LF converted\t%d\n", foundLF); fprintf(output, "LFCR converted\t%d\n", foundLFCR); fprintf(output, "Replacements total %d\n", replaced); fprintf(output, "program terminated.\n"); } /** * Copies a file binary. Does not close the source. * * @param source The source that is to be copied. * @param destFileName The file path name of the file to copy dest into. Any * existing destination file will be overwritten. * * @return 0 if copying was done without error, an error code not equal 0 if * an error occured, -1, i.e.e effectively 255, if the file specified by * destFileName could not be opened. */ int copyFile(FILE* source, char* destFileName) { int i; int j; char* buffer; FILE* dest; // copy source content into pFilepath/FP rewind(source); dest = fopen(pFilepath, "wb"); if (dest == NULL) { return -1; } i = -1; buffer = malloc(2048); for (;;) { i = fread(buffer, 1, 2048, source); j = ferror(source); if (j != 0) { fclose(dest); return j; } if (i > 0) { j = fwrite(buffer, 1, i, dest); if (j < i) { j = ferror(dest); fclose(dest); return j; } } if (feof(source) != 0) { fclose(dest); return 0; } } } %} /* C code end */ %% /* flex logic code start */ {CRLF} { if (convertCRLF != 0) { ++foundCRLF; ++replaced; fprintf(FP, replacementStr[replacementIdx]); } else { REJECT; } } {LFCR} { if (convertLFCR != 0) { ++foundLFCR; ++replaced; fprintf(FP, replacementStr[replacementIdx]); } else { REJECT; } } {CR} { if (convertCR == 0) { fprintf(FP, "\r"); } else { ++foundCR; ++replaced; fprintf(FP, replacementStr[replacementIdx]); } } {LF} { if (convertLF == 0) { fprintf(FP, "\n"); } else { ++foundLF; ++replaced; fprintf(FP, replacementStr[replacementIdx]); } } . fprintf(FP, "%s", yytext); %% /* flex logic code end */ /* C code */ /** * Analyses parameter, initializes, calls yylex to parse, de-initializes. */ main(int argc, char *argv[]) { int i; int parm_type; FP = stdout; FPar = NULL; replacementStr[iLF] = rpsN; replacementStr[iLFCR] = rpsNR; replacementStr[iCR] = rpsR; replacementStr[iCRLF] = rpsRN; replacementStr[iNONE] = rpsNONE; replacementStr[iUSERSTR] = rpsUSERSTR; if (argc > 1) { // help if (0 == strcmp("-h", argv[1])) { help(); exit(0); } // statistics else if (0 == strcmp("-s", argv[1])) { parm_stats = 1; } } parm_type = -1; for (i=1; i < argc; i++) { // change if (parm_type == 0) { inputTypeByPar(argv[i]); parm_type = -1; } // set else if (parm_type == 1) { outputTypeByPar(argv[i]); parm_type = -1; } // setstr else if (parm_type == 2) { replacementIdx = iUSERSTR; replacementStr[iUSERSTR] = malloc(strlen(argv[i]) + 1); strcpy(replacementStr[iUSERSTR], argv[i]); parm_type = -1; } // fo (file output) else if (parm_type == 3) { pFilepath = malloc(strlen(argv[i]) + 1); strcpy(pFilepath, argv[i]); FPar = fopen(pFilepath, "wb"); parm_type = -1; } // foa (file output append) else if (parm_type == 4) { pFilepath = malloc(strlen(argv[i]) + 1); strcpy(pFilepath, argv[i]); FPar = fopen(pFilepath, "ab"); parm_type = -1; } // r (replace file) else if (parm_type == 5) { pFilepath = malloc(strlen(argv[i]) + 1); strcpy(pFilepath, argv[i]); FPtmp = tmpfile(); yyin = fopen(pFilepath, "rb"); parm_type = -1; } if (parm_type >= 0) { continue; } if (0 == strcmp("-change", argv[i])) { parm_type = 0; } if (0 == strcmp("-set", argv[i])) { parm_type = 1; } if (0 == strcmp("-setstr", argv[i])) { parm_type = 2; } if (0 == strcmp("-fo", argv[i])) { parm_type = 3; } if (0 == strcmp("-foa", argv[i])) { parm_type = 4; } if (0 == strcmp("-r", argv[i])) { parm_type = 5; } } if (FPtmp != NULL) { FP = FPtmp; } else if (FPar != NULL) { FP = FPar; } else if ((parm_type == 5) && (FPtmp == NULL)) { exit(-1); } yylex(); if(parm_stats == 1) { summary(stdout); } i = 0; // return code preset, 0 = no error if (pFilepath != NULL) { if (FPtmp == NULL) { fclose(FP); } else { // copy FPtmp content into pFilepath rewind(FPtmp); i = copyFile(FPtmp, pFilepath); fclose(FP); } free(pFilepath); } exit(i); } // EOF