#include <stdio.h>
#include <stdlib.h>
typedef struct String String;
struct String
{
size_t len;
size_t cap;
char *bytes;
};
int
Sinit(String *s, size_t cap)
{
char *bytes;
if (cap == 0)
cap = 32;
if (bytes == NULL)
return 0;
s->len = 0;
s->cap = cap;
s->bytes = bytes;
s->bytes[0] = '\0';
return 1;
}
void
Sterm(String *s)
{
s->len = 0;
s->cap = 0;
}
int
Sextend(String *s)
{
size_t cap;
char *bytes;
cap = s->cap * 2;
if (bytes == NULL)
return 0;
s->cap = cap;
s->bytes = bytes;
return 1;
}
int
Sappend(String *s, char c)
{
if (s->len+1 == s->cap && !Sextend(s))
return 0;
s->bytes[s->len] = c;
s->len++;
s->bytes[s->len] = '\0';
return 1;
}
size_t
Slen(String *s)
{
return s->len;
}
char *
Schars(String *s)
{
return s->bytes;
}
void
Sclear(String *s)
{
s->bytes[0] = '\0';
s->len = 0;
}
int
Scopy(String *dst, String *src)
{
size_t cap;
while (src->len > dst->cap)
if (!Sextend(dst))
return 0;
strcpy(dst
->bytes
, src
->bytes
); dst->bytes[src->len] = '\0';
dst->len = src->len;
return 1;
}
/* -------------------------------- */
typedef struct Text Text;
struct Text
{
size_t len;
size_t cap;
String *lines;
};
int
Tinit(Text *t, size_t cap)
{
String *lines;
if (cap == 0)
cap = 4;
lines
= malloc(cap
* sizeof(String
)); if (lines == NULL)
return 0;
t->cap = cap;
t->len = 0;
t->lines = lines;
return 1;
}
void
Tterm(Text *t)
{
size_t i, len;
String *line;
len = t->len;
line = t->lines;
for (i = 0; i < len; i++, line++)
Sterm(line);
t->len = 0;
t->cap = 0;
}
int
Textend(Text *t)
{
size_t cap;
String *lines;
cap = t->cap * 2;
lines
= realloc(t
->lines
, cap
* sizeof(String
)); if (lines == NULL)
return 0;
t->cap = cap;
t->lines = lines;
return 1;
}
int
Tappend(Text *t, String *s)
{
if (t->len == t->cap && !Textend(t))
return 0;
if (!Sinit(&t->lines[t->len], Slen(s)+1))
return 0;
Scopy(&t->lines[t->len], s);
t->len++;
return 1;
}
size_t
Tlen(Text *t)
{
return t->len;
}
String *
Tline(Text *t, size_t i)
{
return &t->lines[i];
}
/* -------------------------------- */
#define IN 1
#define OUT 0
int
main(void)
{
int i, state, result;
char c;
String s;
Text t;
if (!Tinit(&t, 0)) {
result = 1;
goto errT;
}
if (!Sinit(&s, 0)) {
result = 1;
goto errS;
}
state = OUT;
result = 0;
if (state == IN) {
state = OUT;
if (!Tappend(&t, &s)) {
result = 1;
goto end;
}
Sclear(&s);
}
} else {
state = IN;
if (!Sappend(&s, c)) {
result = 1;
goto end;
}
}
}
if (state == IN)
if (!Tappend(&t, &s)) {
result = 1;
goto end;
}
for (i = 0; i < Tlen(&t); i++)
printf("%s\n", Schars
(Tline
(&t
, i
)));
end:
Tterm(&t);
errS:
Sterm(&s);
errT:
return result;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KCgoKdHlwZWRlZiBzdHJ1Y3QgU3RyaW5nIFN0cmluZzsKc3RydWN0IFN0cmluZwp7CglzaXplX3QgIGxlbjsKCXNpemVfdCAgY2FwOwoJY2hhciAgICpieXRlczsKfTsKCmludApTaW5pdChTdHJpbmcgKnMsIHNpemVfdCBjYXApCnsKCWNoYXIgKmJ5dGVzOwoKCWlmIChjYXAgPT0gMCkKCQljYXAgPSAzMjsKCWJ5dGVzID0gbWFsbG9jKGNhcCk7CglpZiAoYnl0ZXMgPT0gTlVMTCkKCQlyZXR1cm4gMDsKCXMtPmxlbiA9IDA7CglzLT5jYXAgPSBjYXA7CglzLT5ieXRlcyA9IGJ5dGVzOwoJcy0+Ynl0ZXNbMF0gPSAnXDAnOwoJcmV0dXJuIDE7Cn0KCnZvaWQKU3Rlcm0oU3RyaW5nICpzKQp7CglmcmVlKHMtPmJ5dGVzKTsKCXMtPmxlbiA9IDA7CglzLT5jYXAgPSAwOwp9CgppbnQKU2V4dGVuZChTdHJpbmcgKnMpCnsKCXNpemVfdCAgY2FwOwoJY2hhciAgICpieXRlczsKCgljYXAgPSBzLT5jYXAgKiAyOwoJYnl0ZXMgPSByZWFsbG9jKHMtPmJ5dGVzLCBjYXApOwoJaWYgKGJ5dGVzID09IE5VTEwpCgkJcmV0dXJuIDA7CglzLT5jYXAgPSBjYXA7CglzLT5ieXRlcyA9IGJ5dGVzOwoJcmV0dXJuIDE7Cn0KCmludApTYXBwZW5kKFN0cmluZyAqcywgY2hhciBjKQp7CglpZiAocy0+bGVuKzEgPT0gcy0+Y2FwICYmICFTZXh0ZW5kKHMpKQoJCXJldHVybiAwOwoJcy0+Ynl0ZXNbcy0+bGVuXSA9IGM7CglzLT5sZW4rKzsKCXMtPmJ5dGVzW3MtPmxlbl0gPSAnXDAnOwoJcmV0dXJuIDE7Cn0KCnNpemVfdApTbGVuKFN0cmluZyAqcykKewoJcmV0dXJuIHMtPmxlbjsKfQoKY2hhciAqClNjaGFycyhTdHJpbmcgKnMpCnsKCXJldHVybiBzLT5ieXRlczsKfQoKdm9pZApTY2xlYXIoU3RyaW5nICpzKQp7CglzLT5ieXRlc1swXSA9ICdcMCc7CglzLT5sZW4gPSAwOwp9CgppbnQKU2NvcHkoU3RyaW5nICpkc3QsIFN0cmluZyAqc3JjKQp7CglzaXplX3QgY2FwOwoKCXdoaWxlIChzcmMtPmxlbiA+IGRzdC0+Y2FwKQoJCWlmICghU2V4dGVuZChkc3QpKQoJCQlyZXR1cm4gMDsKCXN0cmNweShkc3QtPmJ5dGVzLCBzcmMtPmJ5dGVzKTsKCWRzdC0+Ynl0ZXNbc3JjLT5sZW5dID0gJ1wwJzsKCWRzdC0+bGVuID0gc3JjLT5sZW47CglyZXR1cm4gMTsKfQoKLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi8KCnR5cGVkZWYgc3RydWN0IFRleHQgVGV4dDsKc3RydWN0IFRleHQKewoJc2l6ZV90ICBsZW47CglzaXplX3QgIGNhcDsKCVN0cmluZyAqbGluZXM7Cn07CgppbnQKVGluaXQoVGV4dCAqdCwgc2l6ZV90IGNhcCkKewoJU3RyaW5nICpsaW5lczsKCglpZiAoY2FwID09IDApCgkJY2FwID0gNDsKCWxpbmVzID0gbWFsbG9jKGNhcCAqIHNpemVvZihTdHJpbmcpKTsKCWlmIChsaW5lcyA9PSBOVUxMKQoJCXJldHVybiAwOwoJdC0+Y2FwID0gY2FwOwoJdC0+bGVuID0gMDsKCXQtPmxpbmVzID0gbGluZXM7CglyZXR1cm4gMTsKfQoKdm9pZApUdGVybShUZXh0ICp0KQp7CglzaXplX3QgIGksIGxlbjsKCVN0cmluZyAqbGluZTsKCQoJbGVuICA9IHQtPmxlbjsKCWxpbmUgPSB0LT5saW5lczsKCWZvciAoaSA9IDA7IGkgPCBsZW47IGkrKywgbGluZSsrKQoJCVN0ZXJtKGxpbmUpOwoJZnJlZSh0LT5saW5lcyk7Cgl0LT5sZW4gPSAwOwoJdC0+Y2FwID0gMDsKfQoKaW50ClRleHRlbmQoVGV4dCAqdCkKewoJc2l6ZV90ICBjYXA7CglTdHJpbmcgKmxpbmVzOwoKCWNhcCA9IHQtPmNhcCAqIDI7CglsaW5lcyA9IHJlYWxsb2ModC0+bGluZXMsIGNhcCAqIHNpemVvZihTdHJpbmcpKTsKCWlmIChsaW5lcyA9PSBOVUxMKQoJCXJldHVybiAwOwoJdC0+Y2FwID0gY2FwOwoJdC0+bGluZXMgPSBsaW5lczsKCXJldHVybiAxOwp9CgppbnQKVGFwcGVuZChUZXh0ICp0LCBTdHJpbmcgKnMpCnsKCWlmICh0LT5sZW4gPT0gdC0+Y2FwICYmICFUZXh0ZW5kKHQpKQoJCXJldHVybiAwOwoJaWYgKCFTaW5pdCgmdC0+bGluZXNbdC0+bGVuXSwgU2xlbihzKSsxKSkKCQlyZXR1cm4gMDsKCVNjb3B5KCZ0LT5saW5lc1t0LT5sZW5dLCBzKTsKCXQtPmxlbisrOwoJcmV0dXJuIDE7Cn0KCnNpemVfdApUbGVuKFRleHQgKnQpCnsKCXJldHVybiB0LT5sZW47Cn0KClN0cmluZyAqClRsaW5lKFRleHQgKnQsIHNpemVfdCBpKQp7CglyZXR1cm4gJnQtPmxpbmVzW2ldOwp9CgovKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqLwoKI2RlZmluZSBJTiAgMQojZGVmaW5lIE9VVCAwCgppbnQKbWFpbih2b2lkKQp7CglpbnQgaSwgc3RhdGUsIHJlc3VsdDsKCWNoYXIgYzsKCVN0cmluZyBzOwoJVGV4dCB0OwoKCWlmICghVGluaXQoJnQsIDApKSB7CgkJcmVzdWx0ID0gMTsKCQlnb3RvIGVyclQ7Cgl9CglpZiAoIVNpbml0KCZzLCAwKSkgewoJCXJlc3VsdCA9IDE7CgkJZ290byBlcnJTOwoJfQoJc3RhdGUgPSBPVVQ7CglyZXN1bHQgPSAwOwoJd2hpbGUgKChjID0gZ2V0Y2hhcigpKSAhPSBFT0YpIHsKCQlpZiAoaXNzcGFjZShjKSkgewoJCQlpZiAoc3RhdGUgPT0gSU4pIHsKCQkJCXN0YXRlID0gT1VUOwoJCQkJaWYgKCFUYXBwZW5kKCZ0LCAmcykpIHsKCQkJCQlyZXN1bHQgPSAxOwoJCQkJCWdvdG8gZW5kOwoJCQkJfQoJCQkJU2NsZWFyKCZzKTsKCQkJfQoJCX0gZWxzZSB7CgkJCXN0YXRlID0gSU47CgkJCWlmICghU2FwcGVuZCgmcywgYykpIHsKCQkJCXJlc3VsdCA9IDE7CgkJCQlnb3RvIGVuZDsKCQkJfQoJCX0KCX0KCglpZiAoc3RhdGUgPT0gSU4pCgkJaWYgKCFUYXBwZW5kKCZ0LCAmcykpIHsKCQkJcmVzdWx0ID0gMTsKCQkJZ290byBlbmQ7CgkJfQoKCWZvciAoaSA9IDA7IGkgPCBUbGVuKCZ0KTsgaSsrKQoJCXByaW50ZigiJXNcbiIsIFNjaGFycyhUbGluZSgmdCwgaSkpKTsKCmVuZDoKCVR0ZXJtKCZ0KTsKZXJyUzoKCVN0ZXJtKCZzKTsKZXJyVDoKCXJldHVybiByZXN1bHQ7Cn0=