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);
 }