Charles.Forsyth20060303a828770d19 years agoHistory
234 lines · 4.3 KB · Brainfuck
RawDownload
implement Cfg; include "sys.m";include "bufio.m";include "cfg.m"; sys : Sys;bufio : Bufio; Iobuf : import bufio;ENOMOD : con "cannot load module";EBADPATH : con "bad path";  init(path : string) : string{	sys = load Sys Sys->PATH;	bufio = load Bufio Bufio->PATH;	if (bufio == nil)		return sys->sprint("%s: %r", ENOMOD); 	iob := bufio->open(path, Sys->OREAD);	if (iob == nil)		return sys->sprint("%s: %r", EBADPATH); 	# parse the config file	r : list of ref Tuple;	lnum := 0;	rlist : list of list of ref Tuple; 	while ((line := iob.gets('\n')) != nil) {		lnum++;		(tuple, err) := parseline(line, lnum);		if (err != nil)			return sys->sprint("%s:%d: %s", path, lnum, err); 		if (tuple == nil)			continue;		if (line[0] != ' ' && line[0] != '\t') {			# start of a new record			if (r != nil)				rlist = r :: rlist;			r = nil;		}		r = tuple :: r;	}	if (r != nil)		rlist = r :: rlist;	for (; rlist != nil; rlist = tl rlist)		insert(hd rlist);	return nil;} parseline(s : string, lnum : int) : (ref Tuple, string){	attrs : list of Attr;	quote := 0;	word := "";	lastword := "";	name := ""; loop:	for (i := 0 ; i < len s; i++) {		if (quote) {			if (s[i] == quote) {				if (i + 1 < len s && s[i+1] == quote) {					word[len word] = quote;					i++;				} else {					quote = 0;					continue;				}			} else				word[len word] = s[i];			continue;		}		case s[i] {		'\'' or '\"' =>			quote = s[i];			continue;		'#' =>			break loop;		' ' or '\t' or '\n' =>			if (word == nil)				continue;			if (lastword != nil) {				# lastword space word space				attrs = Attr(lastword, nil) :: attrs;			}			lastword = word;			word = nil; 			if (name != nil) {				# name = lastword space				attrs = Attr(name, lastword) :: attrs;				name = lastword = nil;			}		'=' =>			if (lastword == nil) {				# word=				lastword = word;				word = nil;			}			if (word != nil) {				# lastword word=				attrs = Attr(lastword, nil) :: attrs;				lastword = word;				word = nil;			}			if (lastword == nil)				return (nil, "empty name");			name = lastword;			lastword = nil;		* =>			word[len word] = s[i];		}	}	if (quote)		return (nil, "missing quote"); 	if (lastword == nil) {		lastword = word;		word = nil;	} 	if (name == nil) {		name = lastword;		lastword = nil;	} 	if (name != nil)		attrs = Attr(name, lastword) :: attrs; 	if (attrs == nil)		return (nil, nil); 	fattrs : list of Attr;	for (; attrs != nil; attrs = tl attrs)		fattrs = hd attrs :: fattrs;	return (ref Tuple(lnum, fattrs), nil);} lookup(name : string) : list of (string, ref Record){	l := buckets[hash(name)];	for (; l != nil; l = tl l) {		hr := hd l;		if (hr.name != name)			continue;		return hr.vrecs;	}	return nil;} Record.lookup(r : self ref Record, name : string) : (string, ref Tuple){	for (ts := r.tuples; ts != nil; ts = tl ts) {		t := hd ts;		for (as := t.attrs; as != nil; as = tl as) {			a := hd as;			if (a.name == name)				return (a.value, t);		}	}	return (nil, nil);} Tuple.lookup(t : self ref Tuple, name : string) : string{	for (as := t.attrs; as != nil; as = tl as) {		a := hd as;		if (a.name == name)			return a.value;	}	return nil;} reset(){	keynames = nil;	buckets = array[HSIZE+1] of list of ref HRecord;} # Record hash tableHRecord : adt {	name : string;	vrecs : list of (string, ref Record);}; keynames : list of string; HSIZE : con 16rff;	# must be (2^n)-1 due to hash() defnbuckets := array [HSIZE+1] of list of ref HRecord; hash(name : string) : int{	# maybe use hashPJW?	h := 0;	for (i := 0; i < len name; i++)		h = (h + name[i]) & HSIZE;	return h;} insert(rtups : list of ref Tuple) {	# tuple list is currently in reverse order	ftups : list of ref Tuple;	for (; rtups != nil; rtups = tl rtups)		ftups = hd rtups :: ftups;		maintuple := hd ftups;	mainattr := hd maintuple.attrs;	name := mainattr.name;	value := mainattr.value; 	# does name already exist?	hr : ref HRecord;	h := hash(name);	l := buckets[h];	for (; l != nil; l = tl l) {		hr = hd l;		if (hr.name == name)			break;	}	if (l == nil) {		keynames = name :: keynames;		buckets[h] = ref HRecord(name, (value, ref Record(ftups))::nil) :: buckets[h];	} else		hr.vrecs = (value, ref Record(ftups)) :: hr.vrecs;} getkeys() : list of string{	return keynames;}