![]() |
Home | Libraries | Author | Links |
/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is the SysToMath C Libraries package (LibStmC). * * The Initial Developer of the Original Code is * Tom Michaelis, SysToMath. * Portions created by the Initial Developer are Copyright (C) 1993-2006 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /****************************************************************************** * First Release 1993-12-27 ******************************************************************************/ const char *Copyright = "(C) 1993-2006 Tom Michaelis, SysToMath"; const char *Version = "1.12-r341"; static const char *man [] = { "NAME ", " cuglify - c or c++ source code uglifier ", " ", "SYNOPSIS ", " cuglify [--keep-comments] [--c-plus-plus|--slash-slash-comments] ", " [--line-length=<linelen>] [--output=<outfile>] [<file>] ", " cuglify --help ", " cuglify --version ", " ", "DESCRIPTION ", " The command cuglify transforms the source code given by the <file> " " argument, or if no <file> argument is supplied, by standard input into" " an ugly and for a human viewer almost unreadable form which, however, " " compiles without errors. ", " Unless option --help or --version is supplied, the command returns " " with an exit code 0 on success and with an exit code 1, if any error " " did occur. ", " ", "OPTIONS ", " --help ", " -h Print this man page on standard output and exit with exit code " " 2. ", " ", " --version ", " -V Print version info on standard output and exit with exit code ", " 2. ", " ", " --keep-comments ", " -c Retain comments in the output. ", " ", " --cpp ", " --c-plus-plus ", " -C Assume c++ input. The default is c input. ", " ", " --slash-slash-comments ", " -D Assume c input with c++ one line comments. ", " ", " --line-length=<linelen> ", " -l <linelen> ", " Define the line length of the output, which defaults to 78. " " The argument <linelen> shall be greater than 15 and less than " " 32768 or 0. If it is 0, the length of output lines is " " unlimited. ", " ", " --output=<outfile> ", " --output-file=<outfile> ", " -o <outfile> ", " Direct the output to <outfile>. By default the output goes to " " standard output. " }; #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <limits.h> #include <errno.h> #include <stm/basetype.h> #include <stm/match.h> #include <stm/dvec.h> #include <stm/getopts.h> typedef enum LastChar LastChar; enum LastChar { NORMAL, PLUS, MINUS, GREATER, TIMES, AMPERSAND, POUND, IDCHAR }; typedef struct CuglifyEnv CuglifyEnv; struct CuglifyEnv { StmBool init; StmBool bsep; StmBool lbeg; StmBool clbeg; StmBool cnl; StmBool comments; StmBool cplusplus ; StmBool cplusplusComments; StmBool incomment; int linelen; int iflevel; int lnr; const char *filename; const char *prog; char *str; char *clbegstr; char *outstr; int outlen; StmBool ppline; FILE *instream; FILE *outstream; FILE *debug; jmp_buf jmpbuf; LastChar last; }; int main (int argc, char **argv); static int out (StmMtcFctCmd cmd, StmQreMtc qreMtc); static int errout (StmMtcFctCmd cmd, StmQreMtc qreMtc); static int pout (StmMtcFctCmd cmd, StmQreMtc qreMtc); static int bout (StmMtcFctCmd cmd, StmQreMtc qreMtc); static int pnlout (StmMtcFctCmd cmd, StmQreMtc qreMtc); static int cnlout (StmMtcFctCmd cmd, StmQreMtc qreMtc); static int commout (StmMtcFctCmd cmd, StmQreMtc qreMtc); static int setclbeg (StmMtcFctCmd cmd, StmQreMtc qreMtc); static int cmode (StmMtcFctCmd cmd, StmQreMtc qreMtc); static int incif (StmMtcFctCmd cmd, StmQreMtc qreMtc); static int chkif (StmMtcFctCmd cmd, StmQreMtc qreMtc); static int decif (StmMtcFctCmd cmd, StmQreMtc qreMtc); static int newlnr (StmMtcFctCmd cmd, StmQreMtc qreMtc); static int newfile (StmMtcFctCmd cmd, StmQreMtc qreMtc); static void defsreact (StmReCtrl reCtrl, CuglifyEnv *env); static StmBool readline (CuglifyEnv *env); static void flushout (CuglifyEnv *env); static void gatherout (CuglifyEnv *env, const char *str, int len); int main (int argc, char **argv) { int ret; StmDword optId; StmCmdOptSpec optSpec [] = { {StmId (h), "h\0help\0"}, {StmId (V), "V\0version\0"}, {StmId (c), "c\0keep-comments\0"}, {StmId (C), "C\0cpp\0c-plus-plus\0"}, {StmId (D), "D\0slash-slash-comments\0"}, {StmId (l), "l\0line-length\0", StmCmdOptSpecRequiresArg}, {StmId (o), "o\0output\0output-file\0", StmCmdOptSpecRequiresArg}, {0, NULL} }; StmCmdLine cmdLine = stmCmdLineCreate (argc, (const char **) argv, optSpec); StmReCtrl reCtrl = NULL; StmRe re1 = NULL, re2 = NULL, re3 = NULL; CuglifyEnv env; env.init = StmFalse; env.bsep = StmFalse; env.lbeg = StmFalse; env.clbeg = StmFalse; env.cnl = StmFalse; env.comments = StmFalse; env.cplusplus = StmFalse; env.cplusplusComments = StmFalse; env.incomment = StmFalse; env.linelen = 78; env.iflevel = 0; env.lnr = 0; env.filename = "-stdin-"; env.prog = stmCmdLineGetProg (cmdLine); env.str = NULL; env.clbegstr = NULL; env.outstr = NULL; env.outlen = 0; env.ppline = StmFalse; env.instream = stdin; env.outstream = stdout; env.debug = stderr; env.last = NORMAL; stmCmdLineSetErrfp (cmdLine, stderr); for (optId = stmCmdLineGetFirstOptionId (cmdLine); optId; optId = stmCmdLineGetNextOptionId (cmdLine)) { if (optId == StmId (h)) { FILE *pp; if (! (pp = popen ("more", "w"))) { fprintf (stderr, "system error in line %d: %s: aborted\n", __LINE__, strerror (errno)); exit (1); } stmPrintManual (pp, 79, Version, Copyright, StmElements (man), man); switch (pclose (pp)) { case 0: break; case EOF: fprintf (stderr, "system error in line %d: %s: aborted\n", __LINE__, strerror (errno)); exit (1); default: fprintf (stderr, "system error in line %d: pipe failed: aborted\n", __LINE__, strerror (errno)); exit (1); } exit (2); continue; } if (optId == StmId (V)) { fprintf (stdout, "%s\n", Version); exit (2); continue; } if (optId == StmId (c)) { env.comments = StmTrue; continue; } if (optId == StmId (C)) { if (env.cplusplusComments) { stmCmdLineSetError (cmdLine, StmCmdLineOptionArgError); } else env.cplusplus = StmTrue; continue; } if (optId == StmId (D)) { if (env.cplusplus) { stmCmdLineSetError (cmdLine, StmGetoptsOptionArgError); } else env.cplusplusComments = StmTrue; continue; } if (optId == StmId (l)) { const char *optarg = stmCmdLineGetCurrentOptionArg (cmdLine); char *end; long ll; assert (optarg); ll = strtol (optarg, &end, 10); if (*end || (ll < 16 || ll > 32767) && ll) { fprintf (stderr, "%s: option -l: illegal value: %s\n", env.prog, optarg); stmCmdLineSetError (cmdLine, StmCmdLineOptionArgError); } env.linelen = (int) ll; continue; } if (optId == StmId (o)) { const char *optarg = stmCmdLineGetCurrentOptionArg (cmdLine); assert (optarg); if (strcmp (optarg, "-")) { if (! (env.outstream = fopen (optarg, "w"))) { fprintf (stderr, "%s: option -o: cannot open output file %s\n", env.prog, optarg); stmCmdLineSetError (cmdLine, StmCmdLineOptionArgError); } } else env.outstream = stdout; continue; } } if (!stmCmdLineGetError (cmdLine) && stmCmdLineGetArgCount (cmdLine) - stmCmdLineGetCurrentArgIndex (cmdLine) > 1) { fprintf (stderr, "%s: at most one input file can be supplied\n", env.prog); stmCmdLineSetError (cmdLine, StmCmdLineArgumentError); } if (!stmCmdLineGetError (cmdLine) && stmCmdLineGetArgCount (cmdLine) - stmCmdLineGetCurrentArgIndex (cmdLine) == 1 && ! (env.instream = fopen ( env.filename = stmCmdLineGetArg ( cmdLine, stmCmdLineGetCurrentArgIndex (cmdLine) ), "r" ))) { fprintf (stderr, "%s: cannot open input file %s\n", env.prog, stmCmdLineGetArg (cmdLine, stmCmdLineGetCurrentArgIndex (cmdLine))); stmCmdLineSetError (cmdLine, StmCmdLineArgumentError); } if (stmCmdLineGetError (cmdLine)) { stmPrintSynopsis (stderr, 79, StmElements (man), man); exit (1); } if (! (ret = setjmp (env.jmpbuf))) { reCtrl = stmReCtrlCreate (env.debug, &env.jmpbuf, NULL, NULL); re1 = stmReCreate (reCtrl, "incommline", "&commend&&progLine&||&commline&", NULL); re2 = stmReCreate (reCtrl, "line", "&ws&(&controlLine&||&progLine&)", NULL); re3 = stmReCreate (reCtrl, "cwsline", "&cws&&line&", NULL); defsreact (reCtrl, &env); while (readline (&env)) { if (env.incomment ? !stmReMatch (re1, env.str, &env, NULL) : env.lnr > 1 ? !stmReMatch (re2, env.str, &env, NULL) : !stmReMatch (re3, env.str, &env, NULL)) { fprintf (stderr, "%s: internal error in file %s, line %d:\n\"%s\"\n", env.prog, env.filename, env.lnr, env.str); longjmp (env.jmpbuf, -1); } } flushout (&env); if (env.iflevel) { fprintf (stderr, "%s: %d #endif line%s missing at end of input\n", env.prog, env.iflevel, env.iflevel == 1 ? "" : "s"); longjmp (env.jmpbuf, 1); } } else { if (ret > 0) { fprintf (stderr, "%s: %s\n", env.prog, stmReCtrlGetErrorMsg (reCtrl)); } ret = 1; } stmReCtrlDestroy (reCtrl); stmCmdLineDestroy (cmdLine); return ret; } static int out (StmMtcFctCmd cmd, StmQreMtc qreMtc) { if (cmd.action) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); char ch; if (env -> lbeg) flushout (env); else if (stmQreMtcLen (qreMtc) && env -> bsep) { switch (ch = stmQreMtcStr (qreMtc) [0]) { case '+': if (env -> last == PLUS) gatherout (env, " ", 1); break; case '-': if (env -> last == MINUS) gatherout (env, " ", 1); break; case '>': if (env -> cplusplus && env -> last == GREATER) { gatherout (env, " ", 1); } break; case '&': if (env -> last == AMPERSAND) gatherout (env, " ", 1); break; case '=': if (env -> last == AMPERSAND || env -> last == TIMES) { gatherout (env, " ", 1); } break; case '#': if (env -> last == POUND) gatherout (env, " ", 1); break; default: if ((ch == '_' || isalnum (ch)) && env -> last == IDCHAR) { gatherout (env, " ", 1); } break; } } gatherout (env, stmQreMtcStr (qreMtc), stmQreMtcLen (qreMtc)); if (stmQreMtcLen (qreMtc) && ((ch = stmQreMtcStr (qreMtc) [stmQreMtcLen (qreMtc) - 1]) == '_' || isalnum (ch))) { env -> last = IDCHAR; } else if (stmQreMtcLen (qreMtc) == 1) switch (ch) { case '+': env -> last = PLUS; break; case '-': env -> last = MINUS; break; case '>': env -> last = env -> cplusplus ? GREATER : NORMAL; break; case '*': env -> last = TIMES; break; case '&': env -> last = AMPERSAND; break; case '#': env -> last = POUND; break; default: env -> last = NORMAL; break; } else env -> last = NORMAL; env -> bsep = env -> lbeg = env -> clbeg = env -> cnl = StmFalse; env -> clbegstr = stmDstrDel (env -> clbegstr, 0, 0); env -> init = StmTrue; } if (cmd.rollback) { fprintf (stderr, "out (rollback): str [%.*s]\n", stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc)); } return 0; } static int errout (StmMtcFctCmd cmd, StmQreMtc qreMtc) { if (cmd.action) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); fprintf ( stderr, "%s: syntax error near '%.*s' in file %s, line %d:\n\"%.*s\"\n", env -> prog, stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc), env -> filename, env -> lnr, strcspn (env -> str, "\n"), env -> str ); } if (cmd.rollback) { fprintf (stderr, "errout (rollback): str [%.*s]\n", stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc)); } return 0; } static int pout (StmMtcFctCmd cmd, StmQreMtc qreMtc) { if (cmd.action) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); if (env -> init) flushout (env); gatherout (env, "#", 1); env -> last = POUND; env -> init = StmTrue; env -> ppline = StmTrue; env -> bsep = env -> lbeg = env -> clbeg = env -> cnl = StmFalse; env -> clbegstr = stmDstrDel (env -> clbegstr, 0, 0); } if (cmd.rollback) { fprintf (stderr, "pout (rollback): str [%.*s]\n", stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc)); } return 0; } static int bout (StmMtcFctCmd cmd, StmQreMtc qreMtc) { if (cmd.action) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); if (stmQreMtcSimpleReMtcCount (qreMtc)) env -> bsep = StmTrue; } if (cmd.rollback) { fprintf (stderr, "bout (rollback): str [%.*s]\n", stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc)); } return 0; } static int pnlout (StmMtcFctCmd cmd, StmQreMtc qreMtc) { if (cmd.action) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); env -> ppline = StmFalse; env -> lbeg = StmTrue; } if (cmd.rollback) { fprintf (stderr, "pnlout (rollback): str [%.*s]\n", stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc)); } return 0; } static int cnlout (StmMtcFctCmd cmd, StmQreMtc qreMtc) { if (cmd.action) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); if (env -> cnl) env -> lbeg = StmTrue; env -> clbegstr = stmDstrDel (env -> clbegstr, 0, 0); if (stmQreMtcLen (qreMtc) && ! (env -> clbegstr = stmDstrApp (env -> clbegstr, stmQreMtcStr (qreMtc), (unsigned) stmQreMtcLen (qreMtc)))) { if (env -> debug) { fprintf (env -> debug, "%s: line %d: %s: aborted\n", env -> prog, __LINE__, strerror (errno)); } else perror (env -> prog); longjmp (env -> jmpbuf, -1); } } if (cmd.rollback) { fprintf (stderr, "cnlout (rollback): str [%.*s]\n", stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc)); } return 0; } static int commout (StmMtcFctCmd cmd, StmQreMtc qreMtc) { if (cmd.action) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); if (env -> comments) { if (env -> clbeg || env -> lbeg) flushout (env); if (env -> clbegstr) gatherout (env, env -> clbegstr, 0); gatherout (env, stmQreMtcStr (qreMtc), stmQreMtcLen (qreMtc)); env -> bsep = env -> lbeg = env -> clbeg = StmFalse; env -> clbegstr = stmDstrDel (env -> clbegstr, 0, 0); env -> cnl = StmTrue; env -> init = StmTrue; env -> last = NORMAL; } else env -> bsep = StmTrue; } if (cmd.rollback) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); fprintf (stderr, "commout (rollback): line %d: [%.*s]\n", env -> lnr, stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc)); } return 0; } static int setclbeg (StmMtcFctCmd cmd, StmQreMtc qreMtc) { if (cmd.action) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); env -> clbeg = StmTrue; } if (cmd.rollback) { fprintf (stderr, "setclbeg (rollback): str [%.*s]\n", stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc)); } return 0; } static int cmode (StmMtcFctCmd cmd, StmQreMtc qreMtc) { if (cmd.action) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); env -> incomment = stmQreMtcStr (qreMtc) [0] == '\n'; } if (cmd.rollback) { fprintf (stderr, "cmode (rollback): str [%.*s]\n", stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc)); } return 0; } static int incif (StmMtcFctCmd cmd, StmQreMtc qreMtc) { if (cmd.action) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); env -> iflevel ++; } if (cmd.rollback) { fprintf (stderr, "incif (rollback): str [%.*s]\n", stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc)); } return 0; } static int chkif (StmMtcFctCmd cmd, StmQreMtc qreMtc) { if (cmd.action) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); if (!env -> iflevel) { fprintf (stderr, "%s: #%.*s without #if in file %s, line %d:\n\"%s\"\n", env -> prog, stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc), env -> filename, env -> lnr, env -> str); return StmMtcFctFail; } } if (cmd.rollback) { fprintf (stderr, "chkif (rollback): str [%.*s]\n", stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc)); } return 0; } static int decif (StmMtcFctCmd cmd, StmQreMtc qreMtc) { if (cmd.action) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); if (!env -> iflevel) { fprintf (stderr, "%s: #endif without #if in file %s, line %d:\n\"%s\"\n", env -> prog, env -> filename, env -> lnr, env -> str); return StmMtcFctFail; } env -> iflevel --; } if (cmd.rollback) { fprintf (stderr, "decif (rollback): str [%.*s]\n", stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc)); } return 0; } static int newlnr (StmMtcFctCmd cmd, StmQreMtc qreMtc) { if (cmd.action) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); long ll = strtol (stmQreMtcStr (qreMtc), NULL, 0); if (ll > 0 && ll < INT_MAX) env -> lnr = (int) (ll - 1); } if (cmd.rollback) { fprintf (stderr, "newlnr (rollback): str [%.*s]\n", stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc)); } return 0; } static int newfile (StmMtcFctCmd cmd, StmQreMtc qreMtc) { if (cmd.action) { CuglifyEnv *env = stmQreMtcEnv (qreMtc); env -> filename = stmDstrSave (stmQreMtcStr (qreMtc), stmQreMtcLen (qreMtc)); } if (cmd.rollback) { fprintf (stderr, "newfile (rollback): str [%.*s]\n", stmQreMtcLen (qreMtc), stmQreMtcStr (qreMtc)); } return 0; } static void defsreact (StmReCtrl reCtrl, CuglifyEnv *env) { stmReCreate (reCtrl, "controlLine", "#:pout:&ws&((line):out:&sep&&integerConstant&:newlnr,out:" "(&ws&&stringLiteral&:newfile,out:)?||" "(include||line):out:&ws&&ppToken&+||" "(error||pragma):out:&ws&&ppToken&*||" "(define&_&&identifier&[( \t]?):out:" "&ws&&ppToken&*||" "(undef):out:&sep&&identifier&:out:||" "(ifn?def):incif,out:&sep&&identifier&:out:||" "(if):incif,out:&ws&&ppToken&+||" "(elif):chkif,out:&ws&&ppToken&+||" "(else):chkif,out:||" "(endif):decif,out:||" "(!&sep&[^\n]*):errout:" ")?&ws&&nl&:pnlout:", NULL); stmReCreate (reCtrl, "progLine", "&ppToken&*&cnl&", NULL); stmReCreate (reCtrl, "ppToken", env -> cplusplus || env -> cplusplusComments ? "!(%/[*/])'(&identifier&||" "&floatingConstant&||" "&integerConstant&||" "&characterConstant&||" "&stringLiteral&||" "&punctuator&||" "&operator&||" "[^ \t\n\f\v]):out:&ws&" : "!(%/%*)'(&identifier&||" "&floatingConstant&||" "&integerConstant&||" "&characterConstant&||" "&stringLiteral&||" "&punctuator&||" "&operator&||" "[^ \t\n\f\v]):out:&ws&", NULL); stmReCreate (reCtrl, "identifier", "[_a-zA-Z][_0-9a-zA-Z]*", NULL); stmReCreate (reCtrl, "floatingConstant", "(([0-9]*%.[0-9]+||[0-9]+%.)([eE][-+]?[0-9]+)?||" "[0-9]+[eE][-+]?[0-9])[flFL]?", NULL); stmReCreate (reCtrl, "integerConstant", "([1-9][0-9]*||" "0[xX][0-9a-fA-F]*||" "0[0-7]*)([uU][lL]?||[lL][uU]?)?", NULL); stmReCreate (reCtrl, "characterConstant", "L?%'([^'\\\n]||&escapeSequence&)+%'", NULL); stmReCreate (reCtrl, "stringLiteral", "L?\"([^\"\\\n]||&escapeSequence&)*\"", NULL); stmReCreate (reCtrl, "escapeSequence", "\\(['\"?\\abfnrtv]||[0-7]{1,3}||[xX][0-9a-fA-F]{1,2})", NULL); stmReCreate (reCtrl, "punctuator", "%.%.%.||[{};]", NULL); stmReCreate (reCtrl, "operator", "sizeof||" "%<%<=||" "%>%>=||" "%.%*||" "-%>%*||" "-%>||" "%+%+||" "--||" "%<%<||" "%>%>||" "%<=||" "%>=||" "==||" "%!=||" "%&%&||" "%|%|||" "%*=||" "%/=||" "%%=||" "%+=||" "-=||" "%&=||" "^=||" "%|=||" "##||" "%:%:||" "-||" "[][().&*+~!/%%<>^|?:=,#]", NULL); stmReCreate (reCtrl, "nl", env -> cplusplus || env -> cplusplusComments ? (env -> comments ? "((%/%/[^\n]*):out:\n:pnlout:||\n:setclbeg:)&cws&" : "(%/%/[^\n]*)?\n:setclbeg:&cws&") : "\n:setclbeg:&cws&", NULL); stmReCreate (reCtrl, "cnl", "&nl&||&commbeg&", NULL); stmReCreate (reCtrl, "ws", "([ \t\v\f]:bout:||&comment&)*", NULL); stmReCreate (reCtrl, "sep", "([ \t\v\f]:bout:||&comment&)+", NULL); stmReCreate (reCtrl, "cws", "[ \t]*:cnlout:", NULL); stmReCreate (reCtrl, "_", "[ \t]+:bout:", NULL); stmReCreate (reCtrl, "comment", "(%/%*!(%*%/)*%*%/):commout:", NULL); stmReCreate (reCtrl, "commbeg", "([ \t\v\f]*)(%/%*[^\n]*):commout:\n:setclbeg,cmode:&cws&", NULL); stmReCreate (reCtrl, "commline", "[^\n]*:commout:\n:setclbeg:&cws&", NULL); stmReCreate (reCtrl, "commend", "(!(%*%/)*%*%/:cmode:):commout:&ws&", NULL); stmQreActDef (reCtrl, "out", out); stmQreActDef (reCtrl, "errout", errout); stmQreActDef (reCtrl, "pout", pout); stmQreActDef (reCtrl, "bout", bout); stmQreActDef (reCtrl, "pnlout", pnlout); stmQreActDef (reCtrl, "cnlout", cnlout); stmQreActDef (reCtrl, "commout", commout); stmQreActDef (reCtrl, "setclbeg", setclbeg); stmQreActDef (reCtrl, "cmode", cmode); stmQreActDef (reCtrl, "incif", incif); stmQreActDef (reCtrl, "chkif", chkif); stmQreActDef (reCtrl, "decif", decif); stmQreActDef (reCtrl, "newlnr", newlnr); stmQreActDef (reCtrl, "newfile", newfile); return; } static StmBool readline (CuglifyEnv *env) { StmBool splice = StmFalse; StmBool tws = StmFalse; int ch; env -> str = stmDstrDel (env -> str, 0, 0); while ((ch = fgetc (env -> instream)) != EOF) { if (tws) switch (ch) { case ' ': case '\t': env -> str = stmDstrChApp (env -> str, (char) ch); break; default: ungetc (ch, env -> instream); ch = 0; break; } else { int r = stmDstrLen (env -> str) - 2; if (r >= 0 && !strncmp (env -> str + r, "??", 2)) switch (ch) { case '=': env -> str = stmDstrDel (env -> str, r, 2); ch = '#'; break; case '/': env -> str = stmDstrDel (env -> str, r, 2); ch = '\\'; break; case '\'': env -> str = stmDstrDel (env -> str, r, 2); ch = '^'; break; case '(': env -> str = stmDstrDel (env -> str, r, 2); ch = '['; break; case ')': env -> str = stmDstrDel (env -> str, r, 2); ch = ']'; break; case '!': env -> str = stmDstrDel (env -> str, r, 2); ch = '|'; break; case '<': env -> str = stmDstrDel (env -> str, r, 2); ch = '{'; break; case '>': env -> str = stmDstrDel (env -> str, r, 2); ch = '}'; break; case '-': env -> str = stmDstrDel (env -> str, r, 2); ch = '~'; break; } switch (ch) { case '\n': if (++ r >= 0 && env -> str [r] == '\r') { env -> str = stmDstrDel (env -> str, r, 1); } env -> lnr ++; if (splice) splice = StmFalse; else { int i; for (i = stmDstrLen (env -> str) - 1; i >= 0; -- i) { if (!strchr (" \t", env -> str [i])) break; } env -> str = stmDstrDel (env -> str, i + 1, 0); env -> str = stmDstrChApp (env -> str, (char) ch); tws = StmTrue; } break; case '\\': if (!splice) { splice = StmTrue; break; } /* fall through */ default: if (splice) { splice = StmFalse; env -> str = stmDstrChApp (env -> str, '\\'); } env -> str = stmDstrChApp (env -> str, (char) ch); break; } } if (!env -> str) { errno = ENOMEM; break; } if (!ch) break; } if (ch == EOF && stmDstrLen (env -> str) && !tws) { env -> lnr ++; env -> str = stmDstrChApp (env -> str, '\n'); } if (!env -> str || ferror (env -> instream)) { if (env -> debug) { fprintf (env -> debug, "%s: line %d: %s: aborted\n", env -> prog, __LINE__, strerror (errno)); } else perror (env -> prog); longjmp (env -> jmpbuf, -1); } return env -> str [0] != '\0'; } static void flushout (CuglifyEnv *env) { if (env -> linelen) { if (env -> outlen) { fprintf (env -> outstream, "%s\n", env -> outstr); env -> outstr = stmDstrDel (env -> outstr, 0, 0); env -> outlen = 0; } } else fprintf (env -> outstream, "\n"); return; } static void gatherout (CuglifyEnv *env, const char *str, int len) { if (!len) len = (int) strlen (str); if (env -> linelen) { if (!env -> outlen && env -> bsep && len && str [0] == ' ') { str ++; len --; } env -> bsep = StmFalse; if (len) { env -> outstr = stmDstrApp (env -> outstr, str, len); env -> outlen += len; while (env -> outlen >= env -> linelen) { int l = env -> outlen == env -> linelen && !env -> ppline ? env -> linelen : env -> linelen - 1; fprintf (env -> outstream, "%.*s", l, env -> outstr); env -> outstr = stmDstrDel (env -> outstr, 0, l); env -> outlen -= l; if (l < env -> linelen) fprintf (env -> outstream, "\\"); fprintf (env -> outstream, "\n"); } } } else if (len) fprintf (env -> outstream, "%.*s", len, str); return; }
© Copyright Tom Michaelis 2002-2007
Distributed under the SysToMath Software License (See the accompanying file license.txt or a copy at www.SysToMath.com).