commit 19a07111123964b50fff2644882430398fded904
parent 21195c3217d3a4a69848735cb7cab5e669fad8de
Author: anselm@garbe.us <unknown>
Date:   Thu,  1 Nov 2012 18:07:57 +0100
applied sl's 9front patch
Diffstat:
| M | Makefile | | | 1 | + | 
| M | TODO | | | 3 | +-- | 
| M | date/date.1 | | | 13 | +++++++------ | 
| M | date/date.c | | | 58 | ++++++++++++++++++++++++++++++++++++++++++++++++++-------- | 
| M | fmt/fmt.c | | | 161 | +++++++++++++++++++++++++++++++++++++++---------------------------------------- | 
5 files changed, 139 insertions(+), 97 deletions(-)
diff --git a/Makefile b/Makefile
@@ -57,6 +57,7 @@ SUBDIRS  = lib9\
 	unicode\
 	uniq\
 	unutf\
+	urlencode\
 	wc
 
 all:
diff --git a/TODO b/TODO
@@ -1,6 +1,5 @@
 Missing commands:
 
-* ssam (script in p9p/bin/ssam)
-* rm
+* file (from 9front)
 * cp (also missing from p9p too)
 * mv (also missing from p9p too)
diff --git a/date/date.1 b/date/date.1
@@ -24,6 +24,12 @@ Report Greenwich Mean Time (GMT) rather than local time.
 .B -n
 Report the date as the number of seconds since the
 epoch, 00:00:00 GMT, January 1, 1970.
+.TP
+.B -i
+Report the date as ISO-8601 without time and timezone suffix.
+.TP
+.B -t
+Report the date as ISO-8601 with time and timezone suffix.
 .PP
 The conversion from Greenwich Mean Time to local time depends on the
 .B $timezone
@@ -49,10 +55,5 @@ the real time.
 .\" into
 .\" .BR /env/timezone .
 .\" .PD
-.\" .PP
-.\" .I Clock
-.\" draws a simple analog clock in its window.
 .SH SOURCE
-.B \*9/src/cmd/date.c
-.\" .br
-.\" .B \*9/src/cmd/draw/clock.c
+.B \*9/src/date/date.c
diff --git a/date/date.c b/date/date.c
@@ -1,17 +1,54 @@
 #include <u.h>
 #include <libc.h>
 
-int uflg, nflg;
+int uflg, nflg, iflg, tflg;
+
+char*
+isodate(Tm *t)
+{
+	static char c[25]; /* leave room to append isotime */
+	snprint(c, 11, "%04d-%02d-%02d", 
+		t->year + 1900, t->mon + 1, t->mday);
+	return c;
+}
+
+char*
+isotime(Tm *t)
+{
+	int tz;
+	char *c, *d;
+	d = isodate(t);
+	c = d+10;
+	snprint(c, 10, "T%02d:%02d:%02d",
+		t->hour, t->min, t->sec); /* append to isodate */
+	tz = t->tzoff / 60;
+	if(t->tzoff) {
+		/* localtime */
+		if (t->tzoff > 0) {
+			c[9] = '+';
+		} else {
+			c[9] = '-';
+			tz = -tz;
+		}
+		snprint(c+10, 5, "%02d%02d", tz / 60, tz % 60);
+	} else {
+		c[9] = 'Z';
+		c[10] = 0;
+	}
+	return d;
+}
 
 void
 main(int argc, char *argv[])
 {
 	ulong now;
-
+	Tm *tm;
 	ARGBEGIN{
 	case 'n':	nflg = 1; break;
 	case 'u':	uflg = 1; break;
-	default:	fprint(2, "usage: date [-un] [seconds]\n"); exits("usage");
+	case 't':	tflg = 1; /* implies -i */
+	case 'i':	iflg = 1; break;
+	default:	fprint(2, "usage: date [-itun] [seconds]\n"); exits("usage");
 	}ARGEND
 
 	if(argc == 1)
@@ -21,10 +58,15 @@ main(int argc, char *argv[])
 
 	if(nflg)
 		print("%ld\n", now);
-	else if(uflg)
-		print("%s", asctime(gmtime(now)));
-	else
-		print("%s", ctime(now));
-	
+	else {
+		tm = uflg ? gmtime(now) : localtime(now);
+		if(iflg) {
+			if(tflg)
+				print("%s\n", isotime(tm));
+			else
+				print("%s\n", isodate(tm));
+		} else
+			print("%s", asctime(tm));
+	}
 	exits(0);
 }
diff --git a/fmt/fmt.c b/fmt/fmt.c
@@ -12,14 +12,19 @@ int indent = 0;			/* current value of indent, before extra indent */
 int length = 70;		/* how many columns per output line */
 int join = 1;			/* can lines be joined? */
 int maxtab = 8;
+
 Biobuf bin;
 Biobuf bout;
 
 typedef struct Word Word;
-struct Word{
-	int	bol;
+struct Word
+{
+	Word	*next;
+
 	int	indent;
-	char	text[1];
+	int	length;
+	char	bol;
+	char	text[];
 };
 
 void	fmt(void);
@@ -84,17 +89,14 @@ main(int argc, char **argv)
 }
 
 int
-indentof(char **linep)
+indentof(char *s)
 {
-	int i, ind;
-	char *line;
+	int ind;
 
 	ind = 0;
-	line = *linep;
-	for(i=0; line[i]; i++)
-		switch(line[i]){
+	for(; *s != '\0'; s++)
+		switch(*s){
 		default:
-			*linep = line;
 			return ind;
 		case ' ':
 			ind++;
@@ -104,53 +106,65 @@ indentof(char **linep)
 			ind -= ind%maxtab;
 			break;
 		}
-			
+
 	/* plain white space doesn't change the indent */
-	*linep = "";
 	return indent;
 }
 
-Word**
-addword(Word **words, int *nwordp, char *s, int l, int indent, int bol)
+Word*
+newword(char *s, int n, int ind, int bol)
 {
 	Word *w;
 
-	w = malloc(sizeof(Word)+l+1);
-	memmove(w->text, s, l);
-	w->text[l] = '\0';
-	w->indent = indent;
+	w = malloc(sizeof(Word) + n+1);
+	w->next = nil;
+	w->indent = ind;
 	w->bol = bol;
-	words = realloc(words, (*nwordp+1)*sizeof(Word*));
-	words[(*nwordp)++] = w;
-	return words;
+	memmove(w->text, s, n);
+	w->text[n] = 0;
+	w->length = utflen(w->text);
+	return w;
 }
 
-Word**
-parseline(char *line, Word **words, int *nwordp)
+Word*
+getword(void)
 {
-	int ind, l, bol;
-
-	ind = indentof(&line);
-	indent = ind;
-	bol = 1;
+	static Word *head, *tail;
+	char *line, *s;
+	Word *w;
+	
+	w = head;
+	if(w != nil){
+		head = w->next;
+		return w;
+	}
+	line = Brdstr(&bin, '\n', 1);
+	if(line == nil)
+		return nil;
+	tail = nil;
+	indent = indentof(line);
 	for(;;){
-		/* find next word */
-		while(*line==' ' || *line=='\t')
+		while(*line == ' ' || *line == '\t')
 			line++;
 		if(*line == '\0'){
-			if(bol)
-				return addword(words, nwordp, "", 0, -1, bol);
+			if(head == nil)
+				return newword("", 0, -1, 1);
 			break;
 		}
 		/* how long is this word? */
-		for(l=0; line[l]; l++)
-			if(line[l]==' ' || line[l]=='\t')
+		for(s=line++; *line != '\0'; line++)
+			if(*line==' ' || *line=='\t')
 				break;
-		words = addword(words, nwordp, line, l, indent, bol);
-		bol = 0;
-		line += l;
+		w = newword(s, line-s, indent, head==nil);
+		if(head == nil)
+			head = w;
+		else
+			tail->next = w;
+		tail = w;
 	}
-	return words;
+	w = head;
+	head = w->next;
+	return w;
 }
 
 void
@@ -175,67 +189,52 @@ nspaceafter(char *s)
 	n = strlen(s);
 	if(n < 2)
 		return 1;
-	if(isupper((uchar)s[0]) && n < 4)
+	if(isupper(s[0]) && n < 4)
 		return 1;
 	if(strchr(".!?", s[n-1]) != nil)
 		return 2;
 	return 1;
 }
-	
 
 void
-printwords(Word **w, int nw)
+fmt(void)
 {
-	int i, j, n, col, nsp;
+	Word *w, *o;
+	int col, nsp;
 
-	/* one output line per loop */
-	for(i=0; i<nw; ){
-		/* if it's a blank line, print it */
-		if(w[i]->indent == -1){
+	w = getword();
+	while(w != nil){
+		if(w->indent == -1){
 			Bputc(&bout, '\n');
-			if(++i == nw)	/* out of words */
+			free(w);
+			w = getword();
+			if(w == nil)
 				break;
 		}
-		/* emit leading indent */
-		col = extraindent+w[i]->indent;
-		printindent(col);
+		col = w->indent;
+		printindent(extraindent+col);
 		/* emit words until overflow; always emit at least one word */
-		for(n=0;; n++){
-			Bprint(&bout, "%s", w[i]->text);
-			col += utflen(w[i]->text);
-			if(++i == nw)
-				break;	/* out of words */
-			if(w[i]->indent != w[i-1]->indent)
+		for(;;){
+			Bprint(&bout, "%s", w->text);
+			col += w->length;
+			o = w;
+			w = getword();
+			if(w == nil)
+				break;
+			if(w->indent != o->indent)
 				break;	/* indent change */
-			nsp = nspaceafter(w[i-1]->text);
-			if(col+nsp+utflen(w[i]->text) > extraindent+length)
+			nsp = nspaceafter(o->text);
+			if(col+nsp+w->length > length)
 				break;	/* fold line */
-			if(!join && w[i]->bol)
+			if(!join && w->bol)
 				break;
-			for(j=0; j<nsp; j++)
+			while(--nsp >= 0){
 				Bputc(&bout, ' ');	/* emit space; another word will follow */
-			col += nsp;
+				col++;
+			}
+			free(o);
 		}
-		/* emit newline */
+		free(o);
 		Bputc(&bout, '\n');
 	}
 }
-
-void
-fmt(void)
-{
-	char *s;
-	int i, nw;
-	Word **w;
-
-	nw = 0;
-	w = nil;
-	while((s = Brdstr(&bin, '\n', 1)) != nil){
-		w = parseline(s, w, &nw);
-		free(s);
-	}
-	printwords(w, nw);
-	for(i=0; i<nw; i++)
-		free(w[i]);
-	free(w);
-}