История изменений
Исправление 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);
}