LINUX.ORG.RU

История изменений

Исправление firkax, (текущая версия) :

Вот вариант с многострочными комментами и заодно варнингами про проблемный синтаксис и ошибки чтения:

/* (c) firk; may use without restrictions */
#include <stdio.h>
#include <assert.h>
#include <string.h>

static void handle_line(char *b, char const *eoln, char const *def_eoln, char *pq, unsigned long ln, int warnq);

int main(int argc, char const * const * argv) {
#define MAX_LINE_LEN 100000
  static char b[MAX_LINE_LEN];
  char q;
  unsigned long ln;
  int warnq;
  char * p;
  char const *eoln, *def_eoln;
  
  warnq = !(argc>=2 && !strcmp(argv[1],"--multistring"));
  def_eoln = "\n";
  q = 0;
  ln = 0;
  while(fgets(b,sizeof(b),stdin)) {
    ln++;
    p = strchr(b,'\n');
    if(p) {
      assert(!p[1]);
      if(p!=b && *(p-1)=='\r') { eoln = "\r\n"; *(p-1) = 0; }
      else { eoln = "\n"; *p = 0; }
      def_eoln = eoln;
    } else eoln = "";
    handle_line(b, eoln, def_eoln, &q, ln, warnq);
  }
  if(ferror(stdin)) fprintf(stderr, "error reading input (last read line is %lu)\n", ln);
  if(q=='/') fprintf(stderr, "warning: unterminated multiline comment at EOF (last line is %lu)\n", ln);
  else if(q) fprintf(stderr, "warning: unterminated quoted (%c) entity at EOF (last line is %lu)\n", q, ln);
  return 0;
}

static void handle_line(char *b, char const *eoln, char const *def_eoln, char *pq, unsigned long ln, int warnq) {
  size_t p, plen;
  char c, q;
  char q0;
  
  for(p=0; (c=b[p])==' ' || c=='\t'; p++);
  plen = p;
  q = q0 = *pq;
  while(c = b[p]) {
    if(q=='/') {
      p++;
      if(c=='*' && b[p]=='/') { p++; q = 0; }
      continue;
    }
    if(q) {
      p++;
      if(c==q) q=0;
      else if(c=='\\') { if(b[p]) p++; }
      continue;
    }
    if(c=='\'' || c=='"') { q=c; p++; continue; }
    if(c=='/' && b[p+1]=='*') { q='/'; p+=2; continue; }
    if(c!='/' || b[p+1]!='/') { p++; continue; }
    /* found unquoted // */
    if(q0) {
      if(q0=='/') fprintf(stderr, "warning: can't safely reorder //-comment due to pending multiline-comment at line %lu beginning\n", ln);
      else fprintf(stderr, "warning: can't safely reorder //-comment due to pending quoted (%c) entity at line %lu beginning\n", q, ln);
      break;
    }
    /* here q0==0 && q==0 */
    if(plen) fwrite(b, 1, plen, stdout);
    fputs(b+p, stdout);
    fputs(def_eoln, stdout);
    while(p && (b[p-1]==' ' || b[p-1]=='\t')) p--;
    if(p) { fwrite(b, 1, p, stdout); fputs(eoln, stdout); }
    return;
  }
  /* found EOLN w/o // */
  fputs(b, stdout); fputs(eoln, stdout);
  *pq = q;
  if(warnq && q && q!='/') fprintf(stderr, "warning: unterminated quoted (%c) entity at line %lu\n", q, ln);
}

Строки длиннее MAX_LINE_LEN с комментами всё так же молча дают неверный реультат (а со строками - лишние варнинги, но верный результат).

Исходная версия firkax, :

Вот вариант с многострочными комментами и заодно варнингами про проблемный синтаксис:

/* (c) firk; may use without restrictions */
#include <stdio.h>
#include <assert.h>
#include <string.h>

static void handle_line(char *b, char const *eoln, char const *def_eoln, char *pq, unsigned long ln, int warnq);

int main(int argc, char const * const * argv) {
#define MAX_LINE_LEN 100000
  static char b[MAX_LINE_LEN];
  char q;
  unsigned long ln;
  int warnq;
  char * p;
  char const *eoln, *def_eoln;
  
  warnq = !(argc>=2 && !strcmp(argv[1],"--multistring"));
  def_eoln = "\n";
  q = 0;
  ln = 0;
  while(fgets(b,sizeof(b),stdin)) {
    ln++;
    p = strchr(b,'\n');
    if(p) {
      assert(!p[1]);
      if(p!=b && *(p-1)=='\r') { eoln = "\r\n"; *(p-1) = 0; }
      else { eoln = "\n"; *p = 0; }
      def_eoln = eoln;
    } else eoln = "";
    handle_line(b, eoln, def_eoln, &q, ln, warnq);
  }
  if(ferror(stdin)) fprintf(stderr, "error reading input (last read line is %lu)\n", ln);
  if(q=='/') fprintf(stderr, "warning: unterminated multiline comment at EOF (last line is %lu)\n", ln);
  else if(q) fprintf(stderr, "warning: unterminated quoted (%c) entity at EOF (last line is %lu)\n", q, ln);
  return 0;
}

static void handle_line(char *b, char const *eoln, char const *def_eoln, char *pq, unsigned long ln, int warnq) {
  size_t p, plen;
  char c, q;
  char q0;
  
  for(p=0; (c=b[p])==' ' || c=='\t'; p++);
  plen = p;
  q = q0 = *pq;
  while(c = b[p]) {
    if(q=='/') {
      p++;
      if(c=='*' && b[p]=='/') { p++; q = 0; }
      continue;
    }
    if(q) {
      p++;
      if(c==q) q=0;
      else if(c=='\\') { if(b[p]) p++; }
      continue;
    }
    if(c=='\'' || c=='"') { q=c; p++; continue; }
    if(c=='/' && b[p+1]=='*') { q='/'; p+=2; continue; }
    if(c!='/' || b[p+1]!='/') { p++; continue; }
    /* found unquoted // */
    if(q0) {
      if(q0=='/') fprintf(stderr, "warning: can't safely reorder //-comment due to pending multiline-comment at line %lu beginning\n", ln);
      else fprintf(stderr, "warning: can't safely reorder //-comment due to pending quoted (%c) entity at line %lu beginning\n", q, ln);
      break;
    }
    /* here q0==0 && q==0 */
    if(plen) fwrite(b, 1, plen, stdout);
    fputs(b+p, stdout);
    fputs(def_eoln, stdout);
    while(p && (b[p-1]==' ' || b[p-1]=='\t')) p--;
    if(p) { fwrite(b, 1, p, stdout); fputs(eoln, stdout); }
    return;
  }
  /* found EOLN w/o // */
  fputs(b, stdout); fputs(eoln, stdout);
  *pq = q;
  if(warnq && q && q!='/') fprintf(stderr, "warning: unterminated quoted (%c) entity at line %lu\n", q, ln);
}