xref: /plan9/sys/src/libndb/ndbparse.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier #include <ctype.h>
5*219b2ee8SDavid du Colombier #include <ndb.h>
63e12c5d1SDavid du Colombier #include "ndbhf.h"
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier /*
93e12c5d1SDavid du Colombier  *  Parse a data base entry.  Entries may span multiple
103e12c5d1SDavid du Colombier  *  lines.  An entry starts on a left margin.  All subsequent
113e12c5d1SDavid du Colombier  *  lines must be indented by white space.  An entry consists
123e12c5d1SDavid du Colombier  *  of tuples of the forms:
133e12c5d1SDavid du Colombier  *	attribute-name
143e12c5d1SDavid du Colombier  *	attribute-name=value
153e12c5d1SDavid du Colombier  *	attribute-name="value with white space"
163e12c5d1SDavid du Colombier  *
173e12c5d1SDavid du Colombier  *  The parsing returns a 2-dimensional structure.  The first
183e12c5d1SDavid du Colombier  *  dimension joins all tuples. All tuples on the same line
193e12c5d1SDavid du Colombier  *  form a ring along the second dimension.
203e12c5d1SDavid du Colombier  */
213e12c5d1SDavid du Colombier 
223e12c5d1SDavid du Colombier /*
233e12c5d1SDavid du Colombier  *  parse the next entry in the file
243e12c5d1SDavid du Colombier  */
253e12c5d1SDavid du Colombier Ndbtuple*
263e12c5d1SDavid du Colombier ndbparse(Ndb *db)
273e12c5d1SDavid du Colombier {
283e12c5d1SDavid du Colombier 	char *line;
293e12c5d1SDavid du Colombier 	Ndbtuple *t;
303e12c5d1SDavid du Colombier 	Ndbtuple *first, *last;
313e12c5d1SDavid du Colombier 	int len;
323e12c5d1SDavid du Colombier 
333e12c5d1SDavid du Colombier 	first = last = 0;
343e12c5d1SDavid du Colombier 	for(;;){
35*219b2ee8SDavid du Colombier 		if((line = Brdline(&db->b, '\n')) == 0)
363e12c5d1SDavid du Colombier 			break;
37*219b2ee8SDavid du Colombier 		len = Blinelen(&db->b);
38bd389b36SDavid du Colombier 		if(line[len-1] != '\n')
39bd389b36SDavid du Colombier 			break;
40*219b2ee8SDavid du Colombier 		if(first && !ISWHITE(*line) && *line != '#'){
41*219b2ee8SDavid du Colombier 			Bseek(&db->b, -len, 1);
423e12c5d1SDavid du Colombier 			return first;
433e12c5d1SDavid du Colombier 		}
44*219b2ee8SDavid du Colombier 		t = _ndbparseline(line);
453e12c5d1SDavid du Colombier 		if(t == 0)
463e12c5d1SDavid du Colombier 			continue;
473e12c5d1SDavid du Colombier 		if(first)
483e12c5d1SDavid du Colombier 			last->entry = t;
493e12c5d1SDavid du Colombier 		else
503e12c5d1SDavid du Colombier 			first = t;
513e12c5d1SDavid du Colombier 		last = t;
523e12c5d1SDavid du Colombier 		while(last->entry)
533e12c5d1SDavid du Colombier 			last = last->entry;
543e12c5d1SDavid du Colombier 	}
553e12c5d1SDavid du Colombier 	return first;
563e12c5d1SDavid du Colombier }
573e12c5d1SDavid du Colombier 
583e12c5d1SDavid du Colombier 
593e12c5d1SDavid du Colombier /*
603e12c5d1SDavid du Colombier  *  free the hash files belonging to a db
613e12c5d1SDavid du Colombier  */
623e12c5d1SDavid du Colombier static void
633e12c5d1SDavid du Colombier hffree(Ndb *db)
643e12c5d1SDavid du Colombier {
653e12c5d1SDavid du Colombier 	Ndbhf *hf, *next;
663e12c5d1SDavid du Colombier 
673e12c5d1SDavid du Colombier 	for(hf = db->hf; hf; hf = next){
683e12c5d1SDavid du Colombier 		next = hf->next;
693e12c5d1SDavid du Colombier 		close(hf->fd);
703e12c5d1SDavid du Colombier 		free(hf);
713e12c5d1SDavid du Colombier 	}
723e12c5d1SDavid du Colombier 	db->hf = 0;
733e12c5d1SDavid du Colombier }
743e12c5d1SDavid du Colombier 
753e12c5d1SDavid du Colombier int
763e12c5d1SDavid du Colombier ndbreopen(Ndb *db)
773e12c5d1SDavid du Colombier {
783e12c5d1SDavid du Colombier 	int fd;
793e12c5d1SDavid du Colombier 	Dir d;
803e12c5d1SDavid du Colombier 
813e12c5d1SDavid du Colombier 	/* forget what we know about the open files */
823e12c5d1SDavid du Colombier 	if(db->mtime){
833e12c5d1SDavid du Colombier 		hffree(db);
84*219b2ee8SDavid du Colombier 		close(Bfildes(&db->b));
85*219b2ee8SDavid du Colombier 		Bterm(&db->b);
863e12c5d1SDavid du Colombier 		db->mtime = 0;
873e12c5d1SDavid du Colombier 	}
883e12c5d1SDavid du Colombier 
893e12c5d1SDavid du Colombier 	/* try the open again */
903e12c5d1SDavid du Colombier 	fd = open(db->file, OREAD);
913e12c5d1SDavid du Colombier 	if(fd < 0)
923e12c5d1SDavid du Colombier 		return -1;
933e12c5d1SDavid du Colombier 	if(dirfstat(fd, &d) < 0){
943e12c5d1SDavid du Colombier 		close(fd);
953e12c5d1SDavid du Colombier 		return -1;
963e12c5d1SDavid du Colombier 	}
973e12c5d1SDavid du Colombier 
983e12c5d1SDavid du Colombier 	db->qid = d.qid;
993e12c5d1SDavid du Colombier 	db->mtime = d.mtime;
100*219b2ee8SDavid du Colombier 	db->length = d.length;
101*219b2ee8SDavid du Colombier 	Binits(&db->b, fd, OREAD, db->buf, sizeof(db->buf));
1023e12c5d1SDavid du Colombier 	return 0;
1033e12c5d1SDavid du Colombier }
1043e12c5d1SDavid du Colombier 
105*219b2ee8SDavid du Colombier static char *deffile = "/lib/ndb/local";
1063e12c5d1SDavid du Colombier 
107*219b2ee8SDavid du Colombier /*
108*219b2ee8SDavid du Colombier  *  lookup the list of files to use in the specified database file
109*219b2ee8SDavid du Colombier  */
110*219b2ee8SDavid du Colombier static Ndb*
111*219b2ee8SDavid du Colombier doopen(char *file)
112*219b2ee8SDavid du Colombier {
113*219b2ee8SDavid du Colombier 	Ndb *db;
1143e12c5d1SDavid du Colombier 
1153e12c5d1SDavid du Colombier 	db = (Ndb*)malloc(sizeof(Ndb));
1163e12c5d1SDavid du Colombier 	if(db == 0)
1173e12c5d1SDavid du Colombier 		return 0;
1183e12c5d1SDavid du Colombier 	strncpy(db->file, file, sizeof(db->file)-1);
1193e12c5d1SDavid du Colombier 	db->next = 0;
1203e12c5d1SDavid du Colombier 	db->hf = 0;
1213e12c5d1SDavid du Colombier 	db->mtime = 0;
1223e12c5d1SDavid du Colombier 
1233e12c5d1SDavid du Colombier 	if(ndbreopen(db) < 0){
1243e12c5d1SDavid du Colombier 		free(db);
1253e12c5d1SDavid du Colombier 		return 0;
1263e12c5d1SDavid du Colombier 	}
1273e12c5d1SDavid du Colombier 
1283e12c5d1SDavid du Colombier 	return db;
1293e12c5d1SDavid du Colombier }
130*219b2ee8SDavid du Colombier Ndb*
131*219b2ee8SDavid du Colombier ndbopen(char *file)
132*219b2ee8SDavid du Colombier {
133*219b2ee8SDavid du Colombier 	Ndb *db, *first, *last;
134*219b2ee8SDavid du Colombier 	Ndbs s;
135*219b2ee8SDavid du Colombier 	Ndbtuple *t, *nt;
136*219b2ee8SDavid du Colombier 
137*219b2ee8SDavid du Colombier 	if(file == 0)
138*219b2ee8SDavid du Colombier 		file = deffile;
139*219b2ee8SDavid du Colombier 	db = doopen(file);
140*219b2ee8SDavid du Colombier 	if(db == 0)
141*219b2ee8SDavid du Colombier 		return 0;
142*219b2ee8SDavid du Colombier 	first = last = db;
143*219b2ee8SDavid du Colombier 	t = ndbsearch(db, &s, "database", "");
144*219b2ee8SDavid du Colombier 	Bseek(&db->b, 0, 0);
145*219b2ee8SDavid du Colombier 	if(t == 0)
146*219b2ee8SDavid du Colombier 		return db;
147*219b2ee8SDavid du Colombier 	for(nt = t; nt; nt = nt->entry){
148*219b2ee8SDavid du Colombier 		if(strcmp(nt->attr, "file") != 0)
149*219b2ee8SDavid du Colombier 			continue;
150*219b2ee8SDavid du Colombier 		if(strcmp(nt->val, file) == 0){
151*219b2ee8SDavid du Colombier 			/* default file can be reordered in the list */
152*219b2ee8SDavid du Colombier 			if(first->next == 0)
153*219b2ee8SDavid du Colombier 				continue;
154*219b2ee8SDavid du Colombier 			if(strcmp(first->file, file) == 0){
155*219b2ee8SDavid du Colombier 				db = first;
156*219b2ee8SDavid du Colombier 				first = first->next;
157*219b2ee8SDavid du Colombier 				last->next = db;
158*219b2ee8SDavid du Colombier 				db->next = 0;
159*219b2ee8SDavid du Colombier 				last = db;
160*219b2ee8SDavid du Colombier 			}
161*219b2ee8SDavid du Colombier 			continue;
162*219b2ee8SDavid du Colombier 		}
163*219b2ee8SDavid du Colombier 		db = doopen(nt->val);
164*219b2ee8SDavid du Colombier 		if(db == 0)
165*219b2ee8SDavid du Colombier 			continue;
166*219b2ee8SDavid du Colombier 		last->next = db;
167*219b2ee8SDavid du Colombier 		last = db;
168*219b2ee8SDavid du Colombier 	}
169*219b2ee8SDavid du Colombier 	return first;
170*219b2ee8SDavid du Colombier }
1713e12c5d1SDavid du Colombier 
1723e12c5d1SDavid du Colombier void
1733e12c5d1SDavid du Colombier ndbclose(Ndb *db)
1743e12c5d1SDavid du Colombier {
1753e12c5d1SDavid du Colombier 	Ndb *nextdb;
1763e12c5d1SDavid du Colombier 
1773e12c5d1SDavid du Colombier 	for(; db; db = nextdb){
1783e12c5d1SDavid du Colombier 		nextdb = db->next;
1793e12c5d1SDavid du Colombier 		hffree(db);
180*219b2ee8SDavid du Colombier 		close(Bfildes(&db->b));
181*219b2ee8SDavid du Colombier 		Bterm(&db->b);
1823e12c5d1SDavid du Colombier 		free(db);
1833e12c5d1SDavid du Colombier 	}
1843e12c5d1SDavid du Colombier }
185