diff -r 307800d4a01f Makefile
--- a/Makefile  Mon Jul 02 21:52:15 2012 +0200
+++ b/Makefile  Fri Oct 26 06:42:06 2012 +0000
@@ -57,6 +57,7 @@
        unicode\
        uniq\
        unutf\
+       urlencode\
        wc
 
 all:
diff -r 307800d4a01f TODO
--- a/TODO      Mon Jul 02 21:52:15 2012 +0200
+++ b/TODO      Fri Oct 26 06:42:06 2012 +0000
@@ -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 -r 307800d4a01f date/date.1
--- a/date/date.1       Mon Jul 02 21:52:15 2012 +0200
+++ b/date/date.1       Fri Oct 26 06:42:06 2012 +0000
@@ -24,6 +24,12 @@
 .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 @@
 .\" 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 -r 307800d4a01f date/date.c
--- a/date/date.c       Mon Jul 02 21:52:15 2012 +0200
+++ b/date/date.c       Fri Oct 26 06:42:06 2012 +0000
@@ -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 @@
 
        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 -r 307800d4a01f fmt/fmt.c
--- a/fmt/fmt.c Mon Jul 02 21:52:15 2012 +0200
+++ b/fmt/fmt.c Fri Oct 26 06:42:06 2012 +0000
@@ -12,14 +12,19 @@
 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 @@
 }
 
 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 @@
                        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 @@
        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)
-{
-       int i, j, n, 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){
-                       Bputc(&bout, '\n');
-                       if(++i == nw)   /* out of words */
-                               break;
-               }
-               /* emit leading indent */
-               col = extraindent+w[i]->indent;
-               printindent(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)
-                               break;  /* indent change */
-                       nsp = nspaceafter(w[i-1]->text);
-                       if(col+nsp+utflen(w[i]->text) > extraindent+length)
-                               break;  /* fold line */
-                       if(!join && w[i]->bol)
-                               break;
-                       for(j=0; j<nsp; j++)
-                               Bputc(&bout, ' ');      /* emit space; another 
word will follow */
-                       col += nsp;
-               }
-               /* emit newline */
-               Bputc(&bout, '\n');
-       }
-}
 
 void
 fmt(void)
 {
-       char *s;
-       int i, nw;
-       Word **w;
+       Word *w, *o;
+       int col, nsp;
 
-       nw = 0;
-       w = nil;
-       while((s = Brdstr(&bin, '\n', 1)) != nil){
-               w = parseline(s, w, &nw);
-               free(s);
+       w = getword();
+       while(w != nil){
+               if(w->indent == -1){
+                       Bputc(&bout, '\n');
+                       free(w);
+                       w = getword();
+                       if(w == nil)
+                               break;
+               }
+               col = w->indent;
+               printindent(extraindent+col);
+               /* emit words until overflow; always emit at least one word */
+               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(o->text);
+                       if(col+nsp+w->length > length)
+                               break;  /* fold line */
+                       if(!join && w->bol)
+                               break;
+                       while(--nsp >= 0){
+                               Bputc(&bout, ' ');      /* emit space; another 
word will follow */
+                               col++;
+                       }
+                       free(o);
+               }
+               free(o);
+               Bputc(&bout, '\n');
        }
-       printwords(w, nw);
-       for(i=0; i<nw; i++)
-               free(w[i]);
-       free(w);
 }
diff -r 307800d4a01f urlencode/Makefile
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/urlencode/Makefile        Fri Oct 26 06:42:06 2012 +0000
@@ -0,0 +1,10 @@
+# urlencode - url encode and decode files
+# Depends on ../lib9
+
+TARG      = urlencode
+
+include ../std.mk
+
+pre-uninstall:
+
+post-install:
diff -r 307800d4a01f urlencode/urlencode.1
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/urlencode/urlencode.1     Fri Oct 26 06:42:06 2012 +0000
@@ -0,0 +1,20 @@
+.TH URLENCODE 1
+.SH NAME
+urlencode \- URL encode and decode files
+.SH SYNOPSIS
+.B urlencode
+[
+.B -d
+] [
+.I file
+]
+.SH DESCRIPTION
+.I Urlencode
+is a helper program to URL encode and decode files. The
+.B -d
+flag insead of encoding, decodes URL encoded file. If no
+.I file
+is given, standard input is read. The resulting data
+is written to standard output.
+.SH SOURCE
+.B \*9/src/urlencode/urlencode.c
diff -r 307800d4a01f urlencode/urlencode.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/urlencode/urlencode.c     Fri Oct 26 06:42:06 2012 +0000
@@ -0,0 +1,103 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+
+Biobuf bin;
+Biobuf bout;
+int    dflag;
+
+char   hex[] = "0123456789abcdef";
+char   Hex[] = "0123456789ABCDEF";
+
+int
+hexdigit(int c)
+{
+       char *p;
+
+       if(c > 0){
+               if((p = strchr(Hex, c)) != 0)
+                       return p - Hex;
+               if((p = strchr(hex, c)) != 0)
+                       return p - hex;
+       }
+       return -1;
+}
+
+void
+usage(void)
+{
+       fprint(2, "Usage: %s [ -d ] [ file ]\n", argv0);
+       exits("usage");
+}
+
+void
+main(int argc, char *argv[])
+{
+       int c;
+
+       ARGBEGIN {
+       case 'd':
+               dflag = 1;
+               break;
+       default:
+               usage();
+       } ARGEND;
+
+       if(argc == 1){
+               int fd;
+
+               fd = open(*argv, OREAD);
+               if(fd < 0)
+                       sysfatal("%r");
+               if(fd != 0) dup(fd, 0);
+       } else if(argc > 1)
+               usage();
+
+       Binit(&bin, 0, OREAD);
+       Binit(&bout, 1, OWRITE);
+
+       if(dflag){
+               while((c = Bgetc(&bin)) >= 0){
+                       if(c == '%'){
+                               int c1, c2, x1, x2;
+
+                               if((c1 = Bgetc(&bin)) < 0)
+                                       break;
+                               if((x1 = hexdigit(c1)) < 0){
+                                       Bungetc(&bin);
+                                       Bputc(&bout, c);
+                                       continue;
+                               }
+                               if((c2 = Bgetc(&bin)) < 0)
+                                       break;
+                               if((x2 = hexdigit(c2)) < 0){
+                                       Bungetc(&bin);
+                                       Bputc(&bout, c);
+                                       Bputc(&bout, c1);
+                                       continue;
+                               }
+                               c = x1<<4 | x2;
+                       } else if(c == '+')
+                               c = ' ';
+                       Bputc(&bout, c);
+               }
+       } else {
+               while((c = Bgetc(&bin)) >= 0){
+                       if(c>0 && strchr("/$-_@.!*'(),", c)
+                       || 'a'<=c && c<='z'
+                       || 'A'<=c && c<='Z'
+                       || '0'<=c && c<='9')
+                               Bputc(&bout, c);
+                       else if(c == ' ')
+                               Bputc(&bout, '+');
+                       else {
+                               Bputc(&bout, '%');
+                               Bputc(&bout, Hex[c>>4]);
+                               Bputc(&bout, Hex[c&15]);
+                       }
+               }
+       }
+
+       Bflush(&bout);
+       exits(0);
+}

Reply via email to