discardTask(): reset task->tso to avoid confusion later
[ghc-hetmet.git] / ghc / utils / unlit / unlit.c
index b15e568..3663021 100644 (file)
  * And \begin{pseudocode} ... \end{pseudocode}.  -- LA
  */
 
+#include <string.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <ctype.h>
 
 #define NULLSTR        ((char *)0)
 #define DEFNCHAR       '>'
 #define MISSINGBLANK   "unlit: Program line next to comment"
 #define EMPTYSCRIPT    "unlit: No definitions in file (perhaps you forgot the '>'s?)"
-#define USAGE          "usage: unlit [-q] [-n] [-c] file1 file2\n"
+#define USAGE          "usage: unlit [-q] [-n] [-c] [-#] [-P] [-h label] file1 file2\n"
 #define CANNOTOPEN     "unlit: cannot open \"%s\"\n"
+#define CANNOTWRITE    "unlit: error writing \"%s\"\n"
+#define CANNOTWRITESTDOUT "unlit: error writing standard output\n"
 #define DISTINCTNAMES  "unlit: input and output filenames must differ\n"
 #define MISSINGENDCODE "unlit: missing \\end{code}\n"
 
@@ -66,7 +70,7 @@
 #endif
 
 typedef enum { START, BLANK, TEXT, DEFN, BEGIN, /*PSEUDO,*/ END, HASH, SHEBANG } line;
-#define isWhitespace(c)  (c==' '  || c=='\t')
+#define isWhitespace(c)  (c==' '  || c=='\t' || c=='\r')
 #define isLineTerm(c)    (c=='\n' || c==EOF)
 
 static int noisy  = 1;   /* 0 => keep quiet about errors, 1 => report errors */
@@ -74,6 +78,11 @@ static int errors = 0;   /* count the number of errors reported              */
 static int crunchnl = 0; /* don't print \n for removed lines                 */
 static int leavecpp = 1; /* leave preprocessor lines */
 static int ignore_shebang = 1; /* Leave out shebang (#!) lines */
+static int no_line_pragma = 0; /* Leave out initial line pragma */
+
+static char* prefix_str = NULL; /* Prefix output with a string */
+
+static char *ofilename = NULL;
 
 /* complain(file,line,what)
  *
@@ -93,6 +102,24 @@ int lin; {
     }
 }
 
+writeerror()
+{
+    if (!strcmp(ofilename,"-")) {
+       fprintf(stderr, CANNOTWRITESTDOUT);
+    } else {
+       fprintf(stderr, CANNOTWRITE, ofilename);
+    }
+    exit(1);
+}
+
+myputc(c, ostream)
+char c;
+FILE *ostream; {
+    if (putc(c,ostream) == EOF) {
+       writeerror();
+    }  
+}
+
 #define TABPOS 8
 
 /* As getc, but does TAB expansion */
@@ -164,28 +191,28 @@ FILE *istream, *ostream; {
            while (c=egetc(istream), !isLineTerm(c)) ;
            return SHEBANG;
         }
-        putc(c, ostream);
+        myputc(c, ostream);
         c=c1;
       }
       if ( leavecpp ) {
-       putc(c, ostream);
+       myputc(c, ostream);
         while (c=egetc(istream), !isLineTerm(c))
-            putc(c,ostream);
-        putc('\n',ostream);
+            myputc(c,ostream);
+        myputc('\n',ostream);
         return HASH;
       }
     }
 
     if (c==DEFNCHAR) {
-/*     putc(' ',ostream);*/
+/*     myputc(' ',ostream);*/
         while (c=egetc(istream), !isLineTerm(c))
-            putc(c,ostream);
-        putc('\n',ostream);
+            myputc(c,ostream);
+        myputc('\n',ostream);
         return DEFN;
     }
 
     if (!crunchnl)
-       putc('\n',ostream);
+       myputc('\n',ostream);
 
     while (isWhitespace(c))
         c=egetc(istream);
@@ -248,7 +275,7 @@ FILE *ostream; {
                }
                linesread++;
                if (strncmp(lineb,ENDCODE,LENENDCODE) == 0) {
-                   putc('\n', ostream);
+                   myputc('\n', ostream);
                    break;
                }
                fputs(lineb, ostream);
@@ -264,7 +291,7 @@ FILE *ostream; {
                    exit(1);
                }
                linesread++;
-               putc('\n', ostream);
+               myputc('\n', ostream);
                if (strncmp(lineb,ENDPSEUDOCODE,LENENDPSEUDOCODE) == 0) {
                    break;
                }
@@ -281,8 +308,9 @@ FILE *ostream; {
  *
  * Main program.  Processes command line arguments, looking for leading:
  *  -q  quiet mode - do not complain about bad literate script files
- *  -n  noisy mpde - complain about bad literate script files.
+ *  -n  noisy mode - complain about bad literate script files.
  *  -r  remove cpp droppings in output.
+ *  -P  don't output any CPP line pragmas.
  * Expects two additional arguments, a file name for the input and a file
  * name for the output file.  These two names must normally be distinct.
  * An exception is made for the special name "-" which can be used in either
@@ -302,7 +330,18 @@ char **argv; {
             noisy = 0;
         else if (strcmp(*argv,"-c")==0)
            crunchnl = 1;
-        else if (strcmp(*argv,"-#")==0)
+        else if (strcmp(*argv,"-P")==0)
+           no_line_pragma = 1;
+        else if (strcmp(*argv,"-h")==0) {
+         if (argc > 1) {
+           argc--; argv++;
+           if (prefix_str) 
+             free(prefix_str);
+           prefix_str = (char*)malloc(sizeof(char)*(1+strlen(*argv)));
+           if (prefix_str) 
+             strcpy(prefix_str, *argv);
+         }
+        } else if (strcmp(*argv,"-#")==0)
            ignore_shebang = 0;
         else
             break;
@@ -328,6 +367,7 @@ char **argv; {
             exit(1);
         }
 
+    ofilename=argv[1];
     if (strcmp(argv[1], "-")==0) 
         ostream = stdout; 
     else
@@ -336,10 +376,26 @@ char **argv; {
             exit(1);
         }
 
+    /* Prefix the output with line pragmas */
+    if (!no_line_pragma && prefix_str) {
+      /* Both GHC and CPP understand the #line pragma.
+       * We used to throw in both a #line and a {-# LINE #-} pragma
+       * here, but CPP doesn't understand {-# LINE #-} so it thought
+       * the line numbers were off by one.  We could put the {-# LINE
+       * #-} before the #line, but there's no point since GHC
+       * understands #line anyhow.  --SDM 8/2003
+       */
+      fprintf(ostream, "#line 1 \"%s\"\n", prefix_str);
+    }
+
     unlit(file, istream, ostream);
 
-    fclose(istream);
-    fclose(ostream);
+    if (istream != stdin) fclose(istream);
+    if (ostream != stdout) {
+       if (fclose(ostream) == EOF) {
+           writeerror();
+       }
+    }
 
     exit(errors==0 ? 0 : 1);
 }