Mercurial > ~dholland > hg > tradcpp > index.cgi
diff files.c @ 15:f6177d3ed5c2
handle directives
author | David A. Holland |
---|---|
date | Sun, 19 Dec 2010 21:42:01 -0500 |
parents | 120629a5d6bf |
children | daa801fe719e |
line wrap: on
line diff
--- a/files.c Sun Dec 19 19:51:36 2010 -0500 +++ b/files.c Sun Dec 19 21:42:01 2010 -0500 @@ -7,8 +7,10 @@ #include <err.h> #include "array.h" +#include "mode.h" #include "place.h" #include "files.h" +#include "directive.h" struct incdir { const char *name; @@ -84,8 +86,133 @@ //////////////////////////////////////////////////////////// // parsing +static +size_t +findnl(const char *buf, size_t start, size_t limit) +{ + size_t i; + + for (i=start; i<limit; i++) { + if (buf[i] == '\n') { + return i; + } + } + return limit; +} + +static void -file_read(const struct placefile *pf, int fd); +file_read(const struct placefile *pf, int fd, const char *name) +{ + struct place linestartplace, nextlinestartplace, ptmp; + size_t bufend, bufmax, linestart, lineend, nextlinestart, tmp; + ssize_t result; + bool ateof = false; + char *buf; + + place_setfilestart(&linestartplace, pf); + nextlinestartplace = linestartplace; + + bufmax = 128; + bufend = 0; + linestart = 0; + lineend = 0; + buf = domalloc(bufmax); + + while (1) { + if (lineend >= bufend) { + /* do not have a whole line in the buffer; read more */ + if (linestart > 0 && bufend > linestart) { + /* slide to beginning of buffer */ + memmove(buf, buf+linestart, bufend-linestart); + bufend -= linestart; + lineend -= linestart; + linestart = 0; + } + if (bufend >= bufmax) { + /* need bigger buffer */ + bufmax *= 2; + buf = dorealloc(buf, bufmax); + } + + if (ateof) { + /* don't read again, in case it's a socket */ + result = 0; + } else { + result = read(fd, buf+bufend, bufmax - bufend); + } + + if (result == -1) { + /* read error */ + warn("%s", name); + complain_fail(); + } else if (result == 0 && bufend == linestart) { + /* eof */ + ateof = true; + break; + } else if (result == 0) { + /* eof in middle of line */ + ateof = true; + ptmp = linestartplace; + ptmp.column += bufend - linestart; + complain(&ptmp, "No newline at end of file"); + if (mode.werror) { + complain_fail(); + } + assert(bufend < bufmax); + lineend = bufend++; + buf[lineend] = '\n'; + } else { + tmp = bufend; + bufend += (size_t)result; + lineend = findnl(buf, tmp, bufend); + } + /* loop in case we still don't have a whole line */ + continue; + } + + /* have a line */ + assert(buf[lineend] == '\n'); + buf[lineend] = '\0'; + nextlinestart = lineend+1; + nextlinestartplace.line++; + + /* check for CR/NL */ + if (lineend > 0 && buf[lineend-1] == '\r') { + buf[lineend-1] = '\0'; + lineend--; + } + + /* check for continuation line */ + if (lineend > 0 && buf[lineend-1]=='\\') { + lineend--; + tmp = nextlinestart - lineend; + if (bufend > nextlinestart) { + memmove(buf+lineend, buf+nextlinestart, + bufend - nextlinestart); + } + bufend -= tmp; + nextlinestart -= tmp; + lineend = findnl(buf, lineend, bufend); + /* might not have a whole line, so loop */ + continue; + } + + /* line now goes from linestart to lineend */ + assert(buf[lineend] == '\0'); + if (lineend > linestart) { + directive_gotline(&linestartplace, + buf+linestart, lineend-linestart); + } + + linestart = nextlinestart; + lineend = findnl(buf, linestart, bufend); + linestartplace = nextlinestartplace; + } + + directive_goteof(&linestartplace); + free(buf); +} //////////////////////////////////////////////////////////// // path search @@ -120,11 +247,13 @@ { int fd; + /* XXX check for non-regular files */ + fd = open(file, O_RDONLY); if (fd < 0) { return -1; } - /* XXX: do we need to do anything here or is this function pointless?*/ + return fd; } @@ -147,8 +276,8 @@ fd = file_tryopen(file); if (fd >= 0) { pf = place_addfile(place, file, id->issystem); + file_read(pf, fd, file); free(file); - file_read(pf, fd); close(fd); return; } @@ -184,6 +313,6 @@ die(); } pf = place_addfile(place, name, false); - file_read(pf, fd); + file_read(pf, fd, name); close(fd); }