#include <stdio.h>
#include <string.h>
#include <assert.h>

/* Bug: appears to get %c wrong if followed by a trailing space */
/* Also Imp80 allows ... %c <newline> <newline> code ... */

#define huge 1000000
char outbuf[huge] = { 255 };
char *outp = outbuf+1;

#define maxline 4096
  char buffer[maxline+2];
  char *line, *s;
  int mode = '\n', savemode = '\n', c, pendch = -1, peek, bracedepth = 0;;

int lastch(void) {
int c;
  outp -= 1;
  c = *outp;  /* I don't trust *outp[-1] */
  outp += 1;
  return(c);
}

void outch(char c) {
  int x;

  if (c == '\0') { /* Explicit flush */
    /* for now we assume outout buffer bigger than source file */
    fwrite(outbuf+1, outp-outbuf-1, 1, stdout);
    outp = outbuf+1;
    return;
  }

  if ((c != '\n') || (mode == '!')) { *outp++ = c; return;}

  if (lastch() == 'c') {
    outp -= 1;
    fwrite(outbuf+1, outp-outbuf-1, 1, stdout);
    outp = outbuf+1; /* empty the buffer */
    return;
  }

  *outp++ = c;

}

int main(int argc, char **argv) {

  buffer[0] = '\n';
  for (;;) {
  line = fgets(buffer+1, maxline, stdin);
  if (line == NULL) break;

  /* zap all DOS-style CR's, just in case */
  while ((s = strchr(line, '\r')) != NULL) {
    memmove(s, s+1, strlen(s) /* incl NUL */);
  }

  s = line+strlen(line); /* points to NUL */
  if (s == line) break;
  if (*--s != '\n') {
    /* Line does not terminate in \n??? */
    exit(1);
  }
  while (*--s == ' ' || *s == '\t') /* strip trailing spaces */;
  *++s = '\n'; /* Reinsert newline - we can now guarantee %c\n */
  for (;;) {
    c = *line++;
    if (c == '\0') break;
    retry:
    switch (mode) {
    case '\n': /* pre-statement space */
      bracedepth = 0;
              if (isspace(c)) continue;
              if (c == ';') continue;
              assert(c != '\n');
              if ((c == '\'')
                ||(c == '%')
                ||(c == '!')) {
                if ((c == '\'') || (c == '!')) outch(c);
                /* why did I invent 'pendch'??? - use it here? ^ */
                bracedepth = 0;
                savemode = mode; mode = c; continue;
	      }
              mode = '.'; pendch = c;
              continue;
    case '+': /* post %c space */
              if ((c == ' ') || (c == '\t')) continue;
              mode = '.';
              goto retry;
    case '!': /* in ! comment */ /* ERROR: %c at end of comment matters! */
              /* %COMMENT not handled by this code */
              if (c == '%') {
                c = *line++;
                if (isalpha(c) && (toupper(c) == 'C') && (*line == '\n')) {
                  line++;
                  break; /* Join next line */
		} else {
                  outch('%'); outch(c);
		}
	      } else outch(c);
              if (c == '\n') mode = c;
              continue;
    case '%': /* in keyword */
              /* THIS DOES NOT HANDLE %comment CORRECTLY! */
              if (isalpha(c)) {
                c = tolower(c);
                peek = *line;
                if ((c == 'c') && (peek == '\n')) {
                  mode = '+'; line += 1; break;
		}
                outch(c);
              if (c == 't') {
                if (
		    ( *(outp-1) == 't') &&
                    ( *(outp-2) == 'n') &&
                    ( *(outp-3) == 'e') &&
                    ( *(outp-4) == 'm') &&
                    ( *(outp-5) == 'm') &&
                    ( *(outp-6) == 'o') &&
		    ( *(outp-7) == 'c'))
                {
                  // copy over rest of comment up to newline
                  mode = '!';
                  continue;
		}
	      }
                continue;
	      } else {
               mode = '.'; goto retry;
	      }
    case '\'': /* in 'const' */
              if ((c == mode) && (*line == mode)) {
                outch(c);
                outch(c);
                line += 1; /* past 2nd ' */
                continue;
	      }
              if (c == mode) {
                /* end of string */
                outch(c);
                mode = '.';
                continue; /* reclassify on next ch */
	      }
              outch(c);
              continue;
    case '.': /* everything else */;
              if (pendch >= 0) {
                if (isalpha(pendch) && islower(pendch)) pendch = toupper(pendch);
                outch(pendch);
                pendch = -1;
              };
              if (isalpha(c) && islower(c)) c = toupper(c);
              if (c == ' ' || c == '\t') continue;


	      if (
	       (c == '\'') &&
	       (
		      (isalpha(lastch()) && isupper(lastch()))
		      || isdigit(lastch())
                      || (lastch() == '\'')  // a X' or X'' variable...
                )) {
		outch(c); continue;
	      }



              if (c == '(') {
                bracedepth += 1;
	      } else if (c == ')') {
                bracedepth -= 1;
	      } else if ((c == ':') && (bracedepth == 0)) {
                /* emit label on line of its own - makes for easier parsing */
                outch(c);
                outch('\n');
                mode = '\n';
                continue;
	      }

              if (c == ';') c = '\n';
              if (strchr("\n%'", c) != NULL) {
                if (strchr("\n'", c) != NULL) outch(c);
                savemode = mode; mode = c;
                continue;
              };
              outch(c);
    }
  }
  }
  outch(0); /* Flush buffer */
}
