[project @ 2003-08-20 15:10:22 by simonmar]
[ghc-hetmet.git] / ghc / utils / unlit / unlit.c
index ff9c678..78d8de0 100644 (file)
  */
 
 #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 CANNOTOPEN    "unlit: cannot open \"%s\"\n"
-#define DISTINCTNAMES "unlit: input and output filenames must differ\n"
-#define MISSINGCODE   "unlit: missing %s\n"
+#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 CANNOTOPEN     "unlit: cannot open \"%s\"\n"
+#define DISTINCTNAMES  "unlit: input and output filenames must differ\n"
+#define MISSINGENDCODE "unlit: missing \\end{code}\n"
 
 #define BEGINCODE "\\begin{code}"
 #define LENBEGINCODE 12
 #define LENENDCODE 10
 #ifdef PSEUDOCODE
 /* According to Will Partain, the inventor of pseudocode, this gone now. */
+#define MISSINGENDPSEUDOCODE "unlit: missing \\end{pseudocode}\n"
 #define BEGINPSEUDOCODE "\\begin{pseudocode}"
 #define LENBEGINPSEUDOCODE 18
 #define ENDPSEUDOCODE "\\end{pseudocode}"
 #define LENENDPSEUDOCODE 16
 #endif
 
-typedef enum { START, BLANK, TEXT, DEFN, BEGIN, /*PSEUDO,*/ END, HASH } line;
+typedef enum { START, BLANK, TEXT, DEFN, BEGIN, /*PSEUDO,*/ END, HASH, SHEBANG } line;
 #define isWhitespace(c)  (c==' '  || c=='\t')
 #define isLineTerm(c)    (c=='\n' || c==EOF)
 
@@ -72,6 +74,9 @@ static int noisy  = 1;   /* 0 => keep quiet about errors, 1 => report errors */
 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 char* prefix_str = NULL; /* Prefix output with a string */
 
 /* complain(file,line,what)
  *
@@ -146,19 +151,32 @@ FILE *istream;
 
 line readline(istream,ostream)
 FILE *istream, *ostream; {
-    int c = egetc(istream);
+    int c, c1;
     char buf[100];
     int i;
 
+    c = egetc(istream);
+
     if (c==EOF)
         return END;
-
-    if (leavecpp && c=='#') {
+  
+    if ( c == '#' ) {
+      if ( ignore_shebang ) {
+         c1 = egetc(istream);
+         if ( c1 == '!' ) {
+           while (c=egetc(istream), !isLineTerm(c)) ;
+           return SHEBANG;
+        }
+        putc(c, ostream);
+        c=c1;
+      }
+      if ( leavecpp ) {
        putc(c, ostream);
         while (c=egetc(istream), !isLineTerm(c))
             putc(c,ostream);
         putc('\n',ostream);
         return HASH;
+      }
     }
 
     if (c==DEFNCHAR) {
@@ -228,7 +246,7 @@ FILE *ostream; {
            char lineb[1000];
            for(;;) {
                if (fgets(lineb, sizeof lineb, istream) == NULL) {
-                   fprintf(stderr, MISSINGCODE, ENDCODE);
+                   complain(file, linesread, MISSINGENDCODE);
                    exit(1);
                }
                linesread++;
@@ -245,7 +263,7 @@ FILE *ostream; {
            char lineb[1000];
            for(;;) {
                if (fgets(lineb, sizeof lineb, istream) == NULL) {
-                   fprintf(stderr, MISSINGCODE, ENDPSEUDOCODE);
+                   complain(file, linesread, MISSINGENDPSEUDOCODE);
                    exit(1);
                }
                linesread++;
@@ -266,7 +284,8 @@ 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.
  * 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
@@ -286,6 +305,17 @@ char **argv; {
             noisy = 0;
         else if (strcmp(*argv,"-c")==0)
            crunchnl = 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;
 
@@ -318,10 +348,22 @@ char **argv; {
             exit(1);
         }
 
+    /* Prefix the output with line pragmas */
+    if (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, prefix_str);
+    }
+
     unlit(file, istream, ostream);
 
-    fclose(istream);
-    fclose(ostream);
+    if (istream != stdin)  fclose(istream);
+    if (ostream != stdout) fclose(ostream);
 
     exit(errors==0 ? 0 : 1);
 }