tree.c (2954B)
1 #include <u.h> 2 #include <libc.h> 3 #include <String.h> 4 #include <thread.h> 5 6 #include "html5dom.h" 7 8 Treeconstrctl *tctl; 9 String *tstr; 10 char *tnode; 11 12 void 13 nwrite(char *strnode, char *strfile, char *data, long n) 14 { 15 int fd; 16 char *path; 17 path = smprint("%s/%s/%s", tctl->treeroot, strnode, strfile); 18 fd = create(path, OWRITE, 0); 19 if (fd < 0) sysfatal("failed to create %s, %r", path); 20 free(path); 21 write(fd, data, n); 22 write(fd, "\n", 1); 23 close(fd); 24 } 25 26 char* 27 newnode(void) 28 { 29 int fd; 30 long n; 31 char *strnew, *strnode; 32 strnode = mallocz(64, 1); 33 strnew = smprint("%s/new", tctl->treeroot); 34 fd = open(strnew, OREAD); 35 if (fd < 0) sysfatal("failed to open %s, %r", strnew); 36 free(strnew); 37 n = read(fd, strnode, 64); 38 close(fd); 39 if (strnode[n-1] == '\n') strnode[n-1] = '\0'; 40 return strnode; 41 } 42 43 char* 44 getparent(char *node) 45 { 46 int fd; 47 long n; 48 char *path; 49 char buf[1024]; 50 char *args[8]; 51 char *start, *end; 52 if (strcmp(node, "0") == 0) return strdup("0"); 53 path = smprint("%s/%s/ctl", tctl->treeroot, node); 54 fd = open(path, OREAD); 55 if (fd < 0) sysfatal("failed to open %s, %r", path); 56 free(path); 57 n = readn(fd, buf, 1024); 58 close(fd); 59 buf[n] = '\0'; 60 start = buf; 61 while (start < buf + n) { 62 for (end = start; *end != '\n'; end++) 63 if (*end == '\0') return 0; 64 *end = '\0'; 65 tokenize(start, args, 8); 66 if (strcmp(args[0], "parent") == 0) 67 return strdup(args[1]); 68 } 69 return 0; 70 } 71 72 void 73 adopt(char *parent, char *child) 74 { 75 char buf[1024]; 76 long n; 77 if (strcmp(parent, "0") != 0){ 78 n = snprint(buf, 1024, "adopt %s", child); 79 nwrite(parent, "ctl", buf, n); 80 } 81 } 82 83 void 84 pushchar(Rune c) 85 { 86 if (tnode == nil) { 87 tnode = newnode(); 88 nwrite(tnode, "type", "text", 4); 89 tstr = s_new(); 90 } 91 s_putc(tstr, c); 92 } 93 94 void 95 pushtext(void) 96 { 97 s_terminate(tstr); 98 nwrite(tnode, "text", s_to_c(tstr), strlen(s_to_c(tstr))); 99 s_free(tstr); 100 tstr = nil; 101 free(tnode); 102 tnode = nil; 103 } 104 105 void 106 threadtreeconstr(void *v) 107 { 108 char *tp; 109 char *strnode; 110 char *pnode; 111 int teof; 112 Token *tok; 113 teof = 0; 114 tctl = v; 115 tok = nil; 116 pnode = strdup("0"); 117 threadsetname("treeconstr"); 118 while(teof == 0){ 119 recv(tctl->in, &tok); 120 switch(tok->type){ 121 case TDOCT: 122 strnode = newnode(); 123 nwrite(strnode, "type", "doctype", 7); 124 nwrite(strnode, "name", s_to_c(tok->name), 125 strlen(s_to_c(tok->name))); 126 free(strnode); 127 break; 128 case TSTART: 129 if (tnode != nil) { 130 adopt(pnode, tnode); 131 pushtext(); 132 } 133 strnode = newnode(); 134 nwrite(strnode, "type", "element", 7); 135 nwrite(strnode, "name", s_to_c(tok->name), 136 strlen(s_to_c(tok->name))); 137 adopt(pnode, strnode); 138 if ((tok->flags & TF_SELF_CLOSING) == 0) { 139 tp = pnode; 140 pnode = strdup(strnode); 141 free(tp); 142 free(strnode); 143 } 144 break; 145 case TEND: 146 if (tnode != nil) { 147 adopt(pnode, tnode); 148 pushtext(); 149 } 150 tp = pnode; 151 pnode = getparent(pnode); 152 free(tp); 153 break; 154 case TCHAR: 155 pushchar(tok->c); 156 break; 157 case TEOF: 158 teof = 1; 159 } 160 t_free(tok); 161 } 162 }