Index: trunk/ippMonitor/Makefile.in
===================================================================
--- trunk/ippMonitor/Makefile.in	(revision 14221)
+++ trunk/ippMonitor/Makefile.in	(revision 15784)
@@ -6,86 +6,93 @@
 DEF	=	def
 RAW	=	raw
-DESTBIN =       @HTDOCS@/ippMonitor
+SCRIPTS =       scripts
+DESTBIN	=       @BINDIR@
+DESTWWW =       @HTDOCS@/ippMonitor
+
+GENERATE = $(SCRIPTS)/generate
+
+PROGRAMS = \
+$(DESTBIN)/dbadmin
 
 RAWSRC = \
-$(DESTBIN)/ipp.css \
-$(DESTBIN)/ipp.php \
-$(DESTBIN)/site.php \
-$(DESTBIN)/ipp.menu.dat \
-$(DESTBIN)/ipp.copy.dat \
-$(DESTBIN)/ipp.science.dat \
-$(DESTBIN)/ipp.detrend.dat \
-$(DESTBIN)/ipp.imfiles.dat \
-$(DESTBIN)/ipp.warp.dat \
-$(DESTBIN)/ipp.diff.dat \
-$(DESTBIN)/ipp.stack.dat \
-$(DESTBIN)/Login.php \
-$(DESTBIN)/SelectProject.php \
-$(DESTBIN)/LoadSetup.php \
-$(DESTBIN)/ScienceSteps.php \
-$(DESTBIN)/DetrendSteps.php \
-$(DESTBIN)/ImfileTables.php \
-$(DESTBIN)/WarpSteps.php \
-$(DESTBIN)/DiffSteps.php \
-$(DESTBIN)/StackSteps.php \
-$(DESTBIN)/phptest.php \
-$(DESTBIN)/getimage.php
+$(DESTWWW)/ipp.css \
+$(DESTWWW)/ipp.php \
+$(DESTWWW)/site.php \
+$(DESTWWW)/ipp.menu.dat \
+$(DESTWWW)/ipp.copy.dat \
+$(DESTWWW)/ipp.science.dat \
+$(DESTWWW)/ipp.detrend.dat \
+$(DESTWWW)/ipp.imfiles.dat \
+$(DESTWWW)/ipp.warp.dat \
+$(DESTWWW)/ipp.diff.dat \
+$(DESTWWW)/ipp.stack.dat \
+$(DESTWWW)/Login.php \
+$(DESTWWW)/SelectProject.php \
+$(DESTWWW)/LoadSetup.php \
+$(DESTWWW)/ScienceSteps.php \
+$(DESTWWW)/DetrendSteps.php \
+$(DESTWWW)/ImfileTables.php \
+$(DESTWWW)/WarpSteps.php \
+$(DESTWWW)/DiffSteps.php \
+$(DESTWWW)/StackSteps.php \
+$(DESTWWW)/phptest.php \
+$(DESTWWW)/getimage.php
 
 DEFSRC = \
-$(DESTBIN)/keptDetrendFrames.php \
-$(DESTBIN)/masterDetrendFrames.php \
-$(DESTBIN)/masterDetrendImfiles.php \
-$(DESTBIN)/detInputExp.php \
-$(DESTBIN)/detMasterFrame.php \
-$(DESTBIN)/detMasterImfile.php \
-$(DESTBIN)/detNormalizedExp.php \
-$(DESTBIN)/detNormalizedImfile.php \
-$(DESTBIN)/detNormalizedStatImfile.php \
-$(DESTBIN)/detProcessedImfile.php \
-$(DESTBIN)/detProcessedExp.php \
-$(DESTBIN)/detResidExp.php \
-$(DESTBIN)/detResidImfile.php \
-$(DESTBIN)/detRun.php \
-$(DESTBIN)/detRunSummary.php \
-$(DESTBIN)/detStackedImfile.php \
-$(DESTBIN)/newExp.php \
-$(DESTBIN)/newImfile.php \
-$(DESTBIN)/guidePendingExp.php \
-$(DESTBIN)/chipPendingExp.php \
-$(DESTBIN)/chipPendingImfile.php \
-$(DESTBIN)/chipProcessedExp.php \
-$(DESTBIN)/chipProcessedImfile.php \
-$(DESTBIN)/camPendingExp.php \
-$(DESTBIN)/camProcessedExp.php \
-$(DESTBIN)/pzPendingExp.php \
-$(DESTBIN)/pzPendingImfile.php \
-$(DESTBIN)/rawUnknownExp.php \
-$(DESTBIN)/rawDetrendExp.php \
-$(DESTBIN)/rawDetrendExp_detrend.php \
-$(DESTBIN)/rawImfile.php \
-$(DESTBIN)/rawImfile_failed.php \
-$(DESTBIN)/rawExp_failed.php \
-$(DESTBIN)/rawScienceExp.php \
-$(DESTBIN)/rawExp.php \
-$(DESTBIN)/summitExp.php \
-$(DESTBIN)/warpRun.php \
-$(DESTBIN)/warpInputExp.php \
-$(DESTBIN)/warpSkycellMap.php \
-$(DESTBIN)/warpSkyfile.php \
-$(DESTBIN)/diffRun.php \
-$(DESTBIN)/diffInputSkyfile.php \
-$(DESTBIN)/diffSkyfile.php \
-$(DESTBIN)/stackRun.php \
-$(DESTBIN)/stackInputSkyfile.php \
-$(DESTBIN)/stackSumSkyfile.php
+$(DESTWWW)/keptDetrendFrames.php \
+$(DESTWWW)/masterDetrendFrames.php \
+$(DESTWWW)/masterDetrendImfiles.php \
+$(DESTWWW)/detInputExp.php \
+$(DESTWWW)/detMasterFrame.php \
+$(DESTWWW)/detMasterImfile.php \
+$(DESTWWW)/detNormalizedExp.php \
+$(DESTWWW)/detNormalizedImfile.php \
+$(DESTWWW)/detNormalizedStatImfile.php \
+$(DESTWWW)/detProcessedImfile.php \
+$(DESTWWW)/detProcessedExp.php \
+$(DESTWWW)/detResidExp.php \
+$(DESTWWW)/detResidImfile.php \
+$(DESTWWW)/detRun.php \
+$(DESTWWW)/detRunSummary.php \
+$(DESTWWW)/detStackedImfile.php \
+$(DESTWWW)/newExp.php \
+$(DESTWWW)/newImfile.php \
+$(DESTWWW)/guidePendingExp.php \
+$(DESTWWW)/chipPendingExp.php \
+$(DESTWWW)/chipPendingImfile.php \
+$(DESTWWW)/chipProcessedExp.php \
+$(DESTWWW)/chipProcessedImfile.php \
+$(DESTWWW)/camPendingExp.php \
+$(DESTWWW)/camProcessedExp.php \
+$(DESTWWW)/pzPendingExp.php \
+$(DESTWWW)/pzPendingImfile.php \
+$(DESTWWW)/rawUnknownExp.php \
+$(DESTWWW)/rawDetrendExp.php \
+$(DESTWWW)/rawDetrendExp_detrend.php \
+$(DESTWWW)/rawImfile.php \
+$(DESTWWW)/rawImfile_failed.php \
+$(DESTWWW)/rawExp_failed.php \
+$(DESTWWW)/rawScienceExp.php \
+$(DESTWWW)/rawExp.php \
+$(DESTWWW)/summitExp.php \
+$(DESTWWW)/warpRun.php \
+$(DESTWWW)/warpInputExp.php \
+$(DESTWWW)/warpSkycellMap.php \
+$(DESTWWW)/warpSkyfile.php \
+$(DESTWWW)/diffRun.php \
+$(DESTWWW)/diffInputSkyfile.php \
+$(DESTWWW)/diffSkyfile.php \
+$(DESTWWW)/stackRun.php \
+$(DESTWWW)/stackInputSkyfile.php \
+$(DESTWWW)/stackSumSkyfile.php
 
 
 PICTURES = \
-$(DESTBIN)/PScolorlogo2.jpg \
-$(DESTBIN)/missing.png
+$(DESTWWW)/PScolorlogo2.jpg \
+$(DESTWWW)/missing.png
 
-DESTLINK = $(DESTBIN)/index.php
+DESTLINK = $(DESTWWW)/index.php
 
-php: $(RAWSRC) $(DEFSRC) $(PICTURES) $(DESTLINK)
+php: $(RAWSRC) $(DEFSRC) $(PICTURES) $(DESTLINK) $(PROGRAMS)
 
 # dependancy rules for binary code #########################
@@ -93,73 +100,54 @@
 # .PRECIOUS: $(BIN)/%.$(ARCH)
 
-$(DESTLINK): $(DESTBIN)/Login.php
+$(DESTLINK): $(DESTWWW)/Login.php
 	rm -f $@
-	ln -s $(DESTBIN)/Login.php $@
+	ln -s $(DESTWWW)/Login.php $@
 
-$(SRC)/%.php: $(DEF)/%.d $(DEF)/autocode.php ./generate
+$(SRC)/%.php: $(DEF)/%.d $(DEF)/autocode.php $(GENERATE)
 	@if [ ! -d $(SRC) ]; then mkdir -p $(SRC); fi
-	./generate $< $(DEF)/autocode.php $@
-
-# $(SRC)/%.php: $(RAW)/%.php
-# 	@if [ ! -d $(SRC) ]; then mkdir -p $(SRC); fi
-# 	cp $< $@
-# 
-# $(SRC)/%.css: $(RAW)/%.css
-# 	@if [ ! -d $(SRC) ]; then mkdir -p $(SRC); fi
-# 	cp $< $@
-# 
-# $(SRC)/%.dat: $(RAW)/%.dat
-# 	@if [ ! -d $(SRC) ]; then mkdir -p $(SRC); fi
-# 	cp $< $@
-# 
-# $(SRC)/%.jpg: $(RAW)/%.jpg
-# 	@if [ ! -d $(SRC) ]; then mkdir -p $(SRC); fi
-# 	cp $< $@
-# 
-# $(SRC)/%.png: $(RAW)/%.png
-# 	@if [ ! -d $(SRC) ]; then mkdir -p $(SRC); fi
-# 	cp $< $@
-# 
-# $(SRC)/%.jpeg: $(RAW)/%.jpeg
-# 	@if [ ! -d $(SRC) ]; then mkdir -p $(SRC); fi
-# 	cp $< $@
+	$(GENERATE) $< $(DEF)/autocode.php $@
 
 # generated php code is built into SRC first
-$(DESTBIN)/%.php: $(SRC)/%.php
-	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN) || exit; fi
-	rm -f $(DESTBIN)/$*.php || exit
-	cp $(SRC)/$*.php $(DESTBIN)/$*.php || exit
+$(DESTWWW)/%.php: $(SRC)/%.php
+	@if [ ! -d $(DESTWWW) ]; then mkdir -p $(DESTWWW) || exit; fi
+	rm -f $(DESTWWW)/$*.php || exit
+	cp $(SRC)/$*.php $(DESTWWW)/$*.php || exit
 
 # non-generated php code is copied directly
-$(DESTBIN)/%.php: $(RAW)/%.php
-	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN) || exit; fi
-	rm -f $(DESTBIN)/$*.php || exit
-	cp $(RAW)/$*.php $(DESTBIN)/$*.php || exit
+$(DESTWWW)/%.php: $(RAW)/%.php
+	@if [ ! -d $(DESTWWW) ]; then mkdir -p $(DESTWWW) || exit; fi
+	rm -f $(DESTWWW)/$*.php || exit
+	cp $(RAW)/$*.php $(DESTWWW)/$*.php || exit
 
 # all other files are copied directly
-$(DESTBIN)/%.css: $(RAW)/%.css
+$(DESTWWW)/%.css: $(RAW)/%.css
+	@if [ ! -d $(DESTWWW) ]; then mkdir -p $(DESTWWW) || exit; fi
+	rm -f $(DESTWWW)/$*.css || exit
+	cp $(RAW)/$*.css $(DESTWWW)/$*.css || exit
+
+$(DESTWWW)/%.dat: $(RAW)/%.dat
+	@if [ ! -d $(DESTWWW) ]; then mkdir -p $(DESTWWW) || exit; fi
+	rm -f $(DESTWWW)/$*.dat || exit
+	cp $(RAW)/$*.dat $(DESTWWW)/$*.dat || exit
+
+$(DESTWWW)/%.jpg: $(RAW)/%.jpg
+	@if [ ! -d $(DESTWWW) ]; then mkdir -p $(DESTWWW) || exit; fi
+	rm -f $(DESTWWW)/$*.jpg || exit
+	cp $(RAW)/$*.jpg $(DESTWWW)/$*.jpg || exit
+
+$(DESTWWW)/%.jpeg: $(RAW)/%.jpeg
+	@if [ ! -d $(DESTWWW) ]; then mkdir -p $(DESTWWW) || exit; fi
+	rm -f $(DESTWWW)/$*.jpeg || exit
+	cp $(RAW)/$*.jpeg $(DESTWWW)/$*.jpeg || exit
+
+$(DESTWWW)/%.png: $(RAW)/%.png
+	@if [ ! -d $(DESTWWW) ]; then mkdir -p $(DESTWWW) || exit; fi
+	rm -f $(DESTWWW)/$*.png || exit
+	cp $(RAW)/$*.png $(DESTWWW)/$*.png || exit
+
+$(DESTBIN)/%: $(SCRIPTS)/%
 	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN) || exit; fi
-	rm -f $(DESTBIN)/$*.css || exit
-	cp $(RAW)/$*.css $(DESTBIN)/$*.css || exit
-
-$(DESTBIN)/%.dat: $(RAW)/%.dat
-	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN) || exit; fi
-	rm -f $(DESTBIN)/$*.dat || exit
-	cp $(RAW)/$*.dat $(DESTBIN)/$*.dat || exit
-
-$(DESTBIN)/%.jpg: $(RAW)/%.jpg
-	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN) || exit; fi
-	rm -f $(DESTBIN)/$*.jpg || exit
-	cp $(RAW)/$*.jpg $(DESTBIN)/$*.jpg || exit
-
-$(DESTBIN)/%.jpeg: $(RAW)/%.jpeg
-	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN) || exit; fi
-	rm -f $(DESTBIN)/$*.jpeg || exit
-	cp $(RAW)/$*.jpeg $(DESTBIN)/$*.jpeg || exit
-
-$(DESTBIN)/%.png: $(RAW)/%.png
-	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN) || exit; fi
-	rm -f $(DESTBIN)/$*.png || exit
-	cp $(RAW)/$*.png $(DESTBIN)/$*.png || exit
+	cp $(SCRIPTS)/$* $(DESTBIN)/$* || exit
+	chmod +x $(DESTBIN)/$* || exit
 
 # utilities #################################################
Index: trunk/ippMonitor/configure.tcsh
===================================================================
--- trunk/ippMonitor/configure.tcsh	(revision 14221)
+++ trunk/ippMonitor/configure.tcsh	(revision 15784)
@@ -158,5 +158,6 @@
 if (-e Makefile) mv -f Makefile Makefile~
 cat Makefile.in | sed "s|@HTDOCS@|$htdocs|" > tmp.1
-mv tmp.1 Makefile
+cat tmp.1       | sed "s|@BINDIR@|$bindir|" > Makefile
+rm -f tmp.1
 
 # convert raw/site.php.in to raw/site.php
Index: trunk/ippMonitor/dbadmin
===================================================================
--- trunk/ippMonitor/dbadmin	(revision 14221)
+++ 	(revision )
@@ -1,77 +1,0 @@
-#!/bin/csh -f
-## this script creates the tables needed by ippMonitor for user administration
-
-if ($#argv < 4) goto usage;
-
-if ("$1" == "init") then
-  if ($#argv != 4) goto usage;
-  set dbserver = $2
-  set dbuser = $3
-  set dbpass = $4
-
-  mysql -h $dbserver -u root -p <<EOF
-  create database ippadmin;
-  use ippadmin;
-  create table users (username char(20) not null, password varchar(255));
-  create table cookies (username char(20) not null, cookie varchar(255));
-  create table projects (projname char(20) not null);
-  grant all on *.* to $dbuser@localhost identified by '$dbpass';
-EOF
-    exit 0;
-endif
-
-if ("$1" == "client") then
-  if ($#argv != 5) goto usage;
-  set dbserver = $2
-  set dbuser = $3
-  set dbpass = $4
-  set client = $5
-
-  mysql -h $dbserver -u root -p <<EOF
-   grant all on *.* to $dbuser@"$client" identified by '$dbpass';
-EOF
-    exit 0;
-endif
-
-if ("$1" == "user") then
-  if ($#argv != 5) goto usage;
-  set dbserver = $2
-  set dbuser = $3
-  set user = $4
-  set pass = $5
-
-  mysql -h $dbserver -u $dbuser -p ippadmin <<EOF
-  insert into users (username, password) values ('$user', '$pass');
-EOF
-    exit 0;
-endif
-
-if ("$1" == "project") then
-  if ($#argv != 4) goto usage;
-  set dbserver = $2
-  set dbuser = $3
-  set dbname = $4
-
-  mysql -h $dbserver -u $dbuser -p ippadmin <<EOF
-   insert into projects (projname) values ('$dbname');
-   create database $dbname;
-EOF
-    exit 0;
-endif
-
-usage:
-  echo "USAGE: dbadmin (options)"
-  echo ""
-  echo "  dbadmin init (dbserver) (dbuser) (dbpassword)"
-  echo "      creates admin tables, basic db user -- requires root password"
-  echo ""
-  echo "  dbadmin client (dbserver) (dbuser) (dbpassword) (client)"
-  echo "      add client name or regex"
-  echo ""
-  echo "  dbadmin user (dbserver) (dbuser) (username) (password)"
-  echo "      create a new www user and password"
-  echo ""
-  echo "  dbadmin project (dbserver) (dbuser) (dbname)"
-  echo "      create a new ipp project (database)"
-  echo ""
-  exit 2
Index: trunk/ippMonitor/generate
===================================================================
--- trunk/ippMonitor/generate	(revision 14221)
+++ 	(revision )
@@ -1,600 +1,0 @@
-#!/usr/bin/env perl
-
-$VERBOSE = 0;
-
-if ($ARGV[0] eq "-v") { $VERBOSE = 1; shift @ARGV; }
-if (@ARGV != 3) { die "generate (schema) (template) (output)\n"; }
-
-$schema   = $ARGV[0];
-$template = $ARGV[1];
-$output   = $ARGV[2];
-
-# global variables:
-# @key, @value                         : paired list of keys and values
-# @headcode, @tailcode                 : additional HTML or PHP code before or after table
-# @field, @width, @name, @show, @link, @extras : properties of each table column
-# @imagedefs, %image: array of image defines
-
-&parse_schema;
-&parse_template;
-exit 0;
-
-sub parse_schema {
-    open (FILE, "$schema");
-    @list = <FILE>;
-    close (FILE);
-
-    &init_key ("MENU");
-    &init_key ("STYLE");
-    &init_key ("TABLE");
-    &init_key ("TITLE");
-    &init_key ("FILE");
-
-    &init_key ("FIELDS");
-
-    foreach $line (@list) {
-	chop $line;
-	($key, $value) = split (" ", $line, 2);
-	
-	# strip leading and trailing white space from the following
-	if ($key eq "TABLE") { ($value) = $value =~ m|^\s*(.+)\s*$|; }
-	if ($key eq "TYPE")  { ($value) = $value =~ m|^\s*(.+)\s*$|; }
-
-	&set_keypair ($key, $value);
-
-	# list of the table fields
- 	if ($key eq "FIELD") {
-	    ($field, $width, $name, $show, $link, $extras) = split (/,\s+/, $value, 6);
-	    if (! $name) { die "table $ARGV[0] missing required elements\n"; }
-	    # ($field) = $field =~ m|\s*(\S+)\s*|;
-
-	    if ($VERBOSE) { printf "%-20s %-20s %-20s %-20s %-20s\n", $field, $name, $show, $link, $extras; }
-	    if ($show eq "") {$show = "value";}
-	    push @field,   $field;
-	    push @width,   $width;
-	    push @name,    $name;
-	    push @show,    $show;
-	    push @link,    $link;
-	    push @extras,  $extras;
-	}
-
-	if ($key eq "FILE") {
-	    $myFile = $value;
-	}
-
-	# list of the table fields
- 	if ($key eq "HEAD") {
-	    push @headcode, $value;
-	}
-
-	# the IMAGE commands sets up a reference name
-	if ($key eq "IMAGE") {
-	    push @imagedefs, $value;
-	}
-
-	# the ARGS commands define arguments to FIELDS commands
-	if ($key eq "ARGS") {
-	    push @linkargs, $value;
-	}
-
-	# the OP commands define field operations
-	if ($key eq "OP") {
-	    push @opwords, $value;
-	}
-
-	# the TD_CLASS command sets up an alternate TD class
-	if ($key eq "TD_CLASS") {
-	    push @tdClasses, $value;
-	    # print STDERR "found TD_CLASS\n";
-	}
-
-	# list of the table fields
- 	if ($key eq "TAIL") {
-	    push @tailcode, $value;
-	}
-
-	# list of the table restrictions
-	# replace this with a flexible where statement?
- 	if ($key eq "WHERE") {
-	    ($field) = split (/,\s+/, $value, 1);
-	    if ($VERBOSE) { printf "%-20s\n", $field; }
-	    push @where,   $field;
-	}
-    }
-
-    # check on keys
-    &check_key ("MENU", "ipp.menu.dat");
-    &check_key ("STYLE", "ipp.css");
-    &check_key ("TABLE", "");
-    &check_key ("TITLE", "");
-    &check_key ("FILE", "");
-    
-    # these are used internally (not just a replacement)
-    for ($i = 0; $i < @key; $i++) {
-	if ($key[$i] eq "MENU") { $MENU = $value[$i]; }
-    }
-
-    # define FIELDS and WHERE strings, add to keypairs
-    &define_fields_count;
-    &define_fields_string (@field);
-    &define_where_string (@where);
-
-    foreach $linkarg (@linkargs) {
-	&parse_linkarg ($linkarg);
-    }
-
-    foreach $imagedef (@imagedefs) {
-	&parse_imagedef ($imagedef);
-    }
-
-    foreach $opword (@opwords) {
-	&parse_opwords ($opword);
-    }
-
-    if (0) {
-	print STDERR "show: $show[0]\n";
-	($a, $b, $c) = &parse_label ($show[0]);
-	print STDERR "a: $a, b: $b, c: $c\n";
-
-	print STDERR "extras: $extras[0]\n";
-	($a, $b, $c) = &parse_label ($extras[0]);
-	print STDERR "a: $a, b: $b, c: $c\n";
-
-	print STDERR "show: $show[1]\n";
-	($a, $b, $c) = &parse_label ($show[1]);
-	print STDERR "a: $a, b: $b, c: $c\n";
-
-	print STDERR "extras: $extras[1]\n";
-	($a, $b, $c) = &parse_label ($extras[1]);
-	print STDERR "a: $a, b: $b, c: $c\n";
-	exit 0;
-    }
-}
-
-sub parse_template {
-    open (FILE, $template);
-    @list = <FILE>;
-    close (FILE);
-
-    open (FILE, ">$output");
-
-    foreach $line (@list) {
-	
-	&check_keypairs;
-
-	print FILE $line;
-
-	# fill in table header
-	if ($line =~ m|// \*\* TABLE HEADER \*\*|) {
-	    &write_table_header;
-	}
-
-	# fill in TD_CLASS test
-	if ($line =~ m|// \*\* TD CLASS \*\*|) {
-	    &write_td_class;
-	}
-
-	# fill in table data
-	if ($line =~ m|// \*\* TABLE DATA \*\*|) {
-	    &write_table_data;
-	}
-
-	# fill in table query
-	if ($line =~ m|// \*\* TABLE QUERY \*\*|) {
-	    &write_table_query;
-	}
-
-	# fill in table restricts
-	if ($line =~ m|// \*\* TABLE RESTRICTIONS \*\*|) {
-	    &write_table_restrict;
-	}
-
-	# fill in table restricts
-	if ($line =~ m|// \*\* BUTTON RESTRICTIONS \*\*|) {
-	    &write_button_restrict;
-	}
-
-	# fill in head HTML or PHP code
-	if ($line =~ m|// \*\* HEAD CODE \*\*|) {
-	    &write_inline_code (@headcode);
-	}
-
-	# fill in tail HTML or PHP code
-	if ($line =~ m|// \*\* TAIL CODE \*\*|) {
-	    &write_inline_code (@tailcode);
-	}
-    }
-    close (FILE);
-}
-
-sub write_inline_code {
-    my (@code) = @_;
-    my ($i, $code, $type);
-    
-    for ($i = 0; $i < @code; $i++) {
-	($type, $line) = split (" ", $code[$i], 2);
-	if ($type eq "PHP") {
-	    printf FILE "$line\n";
-	}
-	if ($type eq "HTML") {
-	    printf FILE "?> $line <?\n";
-	}
-    }
-}
-
-# generate a table header cell (<th> </th>) for each field (show != none)
-sub write_table_header {
-
-    # add column sorting elements here
-    for ($i = 0; $i < @field; $i++) {
-	($label, $value, $string) = &parse_label ($show[$i]);
-	if ($show[$i] eq "none")  { next; }
-	# printf FILE "echo \"<th class=\\\"list\\\"> $name[$i] </th>\\n\";\n";
-	if ($label eq "op") {
-	    printf FILE "write_table_header (\"list\", \"$name[$i]\", \"$opf{$value}\", \$buttonLink, \$ID, '$myFile');\n";
-	} else {
-	    printf FILE "write_table_header (\"list\", \"$name[$i]\", \"$field[$i]\", \$buttonLink, \$ID, '$myFile');\n";
-	}
-    }
-}
-
-sub write_td_class {
-    my ($field, $testline);
-
-    if (@tdClasses == 0) { return; }
-    foreach $tdClass (@tdClasses) {
-	print STDERR "write TD CLASS: $tdClass...\n";
-
-	# TD_CLASS class field expression
-	($class, $field, $testline) = split (" ", $tdClass, 3);
-
-	$field = &parse_fieldname ($field);
-
-	printf FILE "  if ($field $testline) {\n";
-	printf FILE "    \$class = \"$class\";\n";
-	printf FILE "  }\n";
-
-	printf STDERR "  if ($field $testline) {\n";
-	printf STDERR "    \$class = \"$class\";\n";
-	printf STDERR "  }\n";
-    }
-}
-
-# generate a WHERE test for each field (field != *)
-sub write_table_restrict {
-
-    if ($WHERE) {
-	printf FILE "\$WHERE = \"WHERE $WHERE\";\n";
-    }	
-    for ($i = 0; $i < @field; $i++) {
-	$value = $field[$i];
-	if ($value eq "*") { next; }
-	printf FILE "\$WHERE = check_restrict ('$value', \$WHERE);\n";
-    }
-    printf FILE "\$WHERE = check_ordering (\$WHERE);\n";
-}
-
-# generate a button link entry for each field (field != *)
-sub write_button_restrict {
-
-    for ($i = 0; $i < @field; $i++) {
-	$value = $field[$i];
-	if ($value eq "*") { next; }
-	printf FILE "\$buttonLink = button_restrict ('$value', \$buttonLink);\n";
-    }
-}
-
-sub write_table_data {
-    my ($i, $Nrow);
-    my ($label, $value, $string);
-
-    for ($i = 0; $i < @field; $i++) {
-	($label, $value, $string) = &parse_label ($show[$i]);
-	$Nrow = $count[$i];
-
-	# create the link variable if this entry should be linked
-	if ($label eq "none")  { next; }
-
-	if ($label eq "value") {
-	    # create the basic link variable
-	    if ($link[$i]) {
-		printf FILE "  \$link = \"$link[$i]\" . \"?menu=$MENU&\" . \$ID['link'];\n";
-		# add extra GET data to target
-		if ($extras[$i]) { &parse_extras ($linkarg{$extras[$i]}); } 
-		$myLink = "\$link";
-	    } else {
-		$myLink = "\"\"";
-	    }
-	    # print the actual table cell line with the link...
-	    if (! $value && ($field[$i] ne "*")) { $value = "\$row[$Nrow]"; }
-	    printf FILE "  write_table_cell (\$class, $myLink, $value);\n";
-	    next;
-	}
-
-	if ($label eq "op") {
-	    # create the basic link variable
-	    if ($link[$i]) {
-		printf FILE "  \$link = \"$link[$i]\" . \"?menu=$MENU&\" . \$ID['link'];\n";
-		# add extra GET data to target
-		if ($extras[$i]) { &parse_extras ($linkarg{$extras[$i]}); } 
-		$myLink = "\$link";
-	    } else {
-		$myLink = "\"\"";
-	    }
-	    printf FILE "  write_table_cell (\$class, $myLink, $ops{$value});\n";
-	    next;
-	}
-
-	if (($label eq "image") && !$link[$i]) {
-	    # print the actual table cell line with the image...
-	    printf FILE "  echo \"<td class=\\\"\$class\\\"><img src=\\\"$image{$value}\\\"></td>\\n\";\n";
-	    next;
-	}
-
-	if (($label eq "image") && $link[$i]) {
-	    # create the basic link 
-	    printf FILE "  \$link = \"$link[$i]\" . \"?menu=$MENU&\" . \$ID['link'];\n";
-	    # add extra php data to target
-	    if ($extras[$i]) { &parse_extras ($linkarg{$extras[$i]}); } 
-	    # print the actual table cell line with the link...
-	    printf FILE "  echo \"<td class=\\\"\$class\\\"><a href=\\\"\$link\\\"> <img src=\\\"$image{$value}\\\"> </a></td>\\n\";\n";
-	    next;
-	}
-    }
-}
-
-sub write_table_query {
-    my ($i);
-    for ($i = 0; $i < @field; $i++) {
-	if ($show[$i] eq "none")  { next; }
-	if ($field[$i] eq "*")  { 
-	    # * fields create an empty cell 
-	    printf FILE "echo \"<td> &nbsp; </td>\\n\";\n";
-	} else {
-	    printf FILE "write_query_row ('$field[$i]', $width[$i]);\n";
-	}
-    }
-}
-
-sub define_fields_string {
-    my (@array) = @_;
-    my ($i, $FIELDS);
-
-    $FIELDS = "$array[0]";
-    for ($i = 1; $i < @array; $i++) {
-	# skip * fields (not a valid query element
-	if ($array[$i] eq "*") { next; }
-	$FIELDS = "$FIELDS,$array[$i]";
-    }
-    set_keypair ("FIELDS", $FIELDS);
-}
-
-sub define_fields_count {
-    my ($i, $Nrow);
-
-    @count = ();
-
-    $Nrow = 0;
-    for ($i = 0; $i < @field; $i++) {
-	# skip * fields (not a valid query element
-	if ($field[$i] eq "*") { 
-	    $count[$i] = -1;
-	} else {
-	    $count[$i] = $Nrow;
-	    $Nrow ++;
-	}
-    }
-}
-
-sub define_where_string {
-    my (@array) = @_;
-    my ($i, $FIELDS);
-
-    if (@array == 0) { return; }
-
-    $WHERE = "$array[0]";
-    for ($i = 1; $i < @array; $i++) {
-	$WHERE = "$WHERE AND $array[$i]";
-    }
-    
-    set_keypair ("WHERE", $WHERE);
-}
-
-sub parse_extras {
-    my ($extras) = $_[0];
-    my (@extfields);
-    my ($label, $value, $outline);
-    my ($i);
-
-    # examine the extras and parse the embedded fields (comma-separated)
-    @extfields = split (/,/, $extras);
-    for ($i = 0; $i < @extfields; $i++) {
-	($label, $value, $outline) = &parse_label ($extfields[$i]);
-	printf FILE "  \$link = \$link . \"&$outline\";\n";
-    }
-}
-
-# each linkarg is an entry of the form "word name=value"
-# the entries for matching words are concatenated together
-# separated by commas to create the value $linkarg{word}
-sub parse_linkarg {
-    my ($word, $value);
-
-    ($word, $value) = split (" ", $_[0]);
-
-    if ($linkarg{$word}) {
-	$linkarg{$word} = "$linkarg{$word},$value";
-    } else {
-	$linkarg{$word} = $value;
-    }	
-}
-
-# parse strings of the form label=value
-# if 'value' is of the form $field, try to match with 
-# a supplied DB field, and replace with $row[$n] if found
-sub parse_label {
-    my ($string) = $_[0];
-    my ($label, $value, $outline);
-    my ($Nrow, $i);
-
-    # unless we replace the value with the db row element, return the original string
-    $outline = $string;
-    $label = $string;
-    $value = "";
-
-    # search for embedded table fields and replace with row[N]
-    if ($VERBOSE) { print STDERR "string: $string\n"; }
-    if ($string =~ m|\S+=\S+|) {
-	($label, $value) = $string =~ m|(\S+)=(\S+)|;
-	if ($value =~ m|^\$|) {
-	  MATCH_LABEL:
-	    for ($i = 0; $i < @field; $i++) {
-		if ($field[$i] eq "*") { next; }
-		if ($value =~ m|^\$$field[$i]|) {
-		    # print "field: $field[$i]\n";
-		    ($name, $extra) = $value =~ m|^\$($field[$i])\@(\S+)|;
-		    # print "name: $name\n";
-		    # print "extra: $extra\n";
-		    # print "value: $value\n";
-
-		    $Nrow = $count[$i];
-		    if ($extra) {
-			$value = "\$row[$Nrow]\@$extra";
-		    } else {
-			$value = "\$row[$Nrow]";
-		    }
-		    # print "outval: $value\n";
-		    last MATCH_LABEL;
-		}
-	    }
-	    $outline = "$label=$value";
-	} 
-    }
-    return ($label, $value, $outline);
-}
-
-# given a variable of the form $fieldname, return the corresponding
-# row entry in the form $row[N], otherwise return $fieldname
-# globals: field (list of field names), count (list of sequence)
-sub parse_fieldname {
-    my ($variable) = $_[0];
-    my ($i);
-    
-    # print STDERR "variable: $variable\n";
-
-    unless ($variable =~ m|^\$|) {
-	return $variable;
-    }
-
-    $fieldname = substr ($variable, 1);
-
-    # print STDERR "fieldname: $fieldname\n";
-
-    for ($i = 0; $i < @field; $i++) {
-	# print STDERR "$i: $field[$i] : $fieldname\n";
-
-	if ($field[$i] eq "*") { next; }
-	if ($fieldname ne $field[$i]) { next; }
-
-
-	$Nrow = $count[$i];
-
-	$value = "\$row[$Nrow]";
-
-	# print STDERR "found : $i : $count[$i] : $Nrow : $value\n";
-	return $value;
-    }
-    return $variable;
-}
-
-sub parse_imagedef {
-    my ($value) = $_[0];
-
-    ($var, $name, $rule, $camera, $class) = split (" ", $value);
-    $name   = &parse_fieldname ($name);
-    $camera = &parse_fieldname ($camera);
-    $class  = &parse_fieldname ($class);
-    $image{$var} = "getimage.php?name=$name&rule=$rule&camera=$camera&class_id=$class";
-    return 1;
-}
-
-sub parse_opwords {
-    my ($value) = $_[0];
-
-    @words = split (" ", $value);
-    $name = shift (@words);
-
-    $opline = "";
-    foreach $word (@words) {
-	$fword = &parse_fieldname ($word);
-	push @outwords, $fword;
-	if ($word =~ m|^\$|) {
-	    $word = substr ($word, 1);
-	}
-	push @outfields, $word;
-    }
-    $outline = join (" ", @outwords);
-    $ops{$name} = $outline;
-    $outline = join (" ", @outfields);
-    $opf{$name} = $outline;
-
-    return 1;
-}
-
-sub init_key {
-    my ($key)   = $_[0];
-
-    push @key, $key;
-    push @value, "";
-}
-
-sub set_keypair {
-    my ($i);
-    my ($key)   = $_[0];
-    my ($value) = $_[1];
-
-    for ($i = 0; $i < @key; $i++) {
-	if ($key eq $key[$i]) {
-	    if ($value[$i] ne "") { die "key is multiply defined\n"; }
-	    $value[$i] = $value;
-	    if ($VERBOSE) { print STDERR "setting $key = $value\n"; }
-	    return;
-	}
-    }
-}
-
-sub check_key {
-    my ($i);
-    my ($key)     = $_[0];
-    my ($default) = $_[1];
-
-    for ($i = 0; $i < @key; $i++) {
-	if ($key eq $key[$i]) {
-	    if ($VERBOSE) { print "found $key: $key[$i]  -- $value[$i] (def: $default)\n"; }
-	    if (($default eq "") && ($value[$i] eq "")) { die "missing value for required key $key[$i]\n"; }
-	    if ($value[$i] eq "") { $value[$i] = $default; }
-	    return;
-	}
-    }
-    die "unknown key $key\n";
-}
-
-sub check_keypairs {
-    my ($i);
-    for ($i = 0; $i < @key; $i++) {
-	if ($VERBOSE) { print "$key[$i]  -- $value[$i]\n"; }
-	if ($line =~ m|\$$key[$i]|) {
-	    if ($value[$i] eq "") { die "missing value for required key $key[$i]\n"; }
-	    $line =~ s|\$$key[$i]|$value[$i]|g;
-	}
-    }
-}
-
-# we need to find the structure size, including padding 
-# i'm not sure I know the answer to this: it is probably 
-# the total number of bytes rounded up to the largest 
-# data item in the structure (ie, 8 for a double, etc)
-# if we have the size, then we can double check the structure
-# against the expectation at runtime.  for the moment,
-# calculate by hand and add to def.d file 
-
Index: trunk/ippMonitor/scripts/dbadmin
===================================================================
--- trunk/ippMonitor/scripts/dbadmin	(revision 15784)
+++ trunk/ippMonitor/scripts/dbadmin	(revision 15784)
@@ -0,0 +1,77 @@
+#!/bin/csh -f
+## this script creates the tables needed by ippMonitor for user administration
+
+if ($#argv < 4) goto usage;
+
+if ("$1" == "init") then
+  if ($#argv != 4) goto usage;
+  set dbserver = $2
+  set dbuser = $3
+  set dbpass = $4
+
+  mysql -h $dbserver -u root -p <<EOF
+  create database ippadmin;
+  use ippadmin;
+  create table users (username char(20) not null, password varchar(255));
+  create table cookies (username char(20) not null, cookie varchar(255));
+  create table projects (projname char(20) not null);
+  grant all on *.* to $dbuser@localhost identified by '$dbpass';
+EOF
+    exit 0;
+endif
+
+if ("$1" == "client") then
+  if ($#argv != 5) goto usage;
+  set dbserver = $2
+  set dbuser = $3
+  set dbpass = $4
+  set client = $5
+
+  mysql -h $dbserver -u root -p <<EOF
+   grant all on *.* to $dbuser@"$client" identified by '$dbpass';
+EOF
+    exit 0;
+endif
+
+if ("$1" == "user") then
+  if ($#argv != 5) goto usage;
+  set dbserver = $2
+  set dbuser = $3
+  set user = $4
+  set pass = $5
+
+  mysql -h $dbserver -u $dbuser -p ippadmin <<EOF
+  insert into users (username, password) values ('$user', '$pass');
+EOF
+    exit 0;
+endif
+
+if ("$1" == "project") then
+  if ($#argv != 4) goto usage;
+  set dbserver = $2
+  set dbuser = $3
+  set dbname = $4
+
+  mysql -h $dbserver -u $dbuser -p ippadmin <<EOF
+   insert into projects (projname) values ('$dbname');
+   create database $dbname;
+EOF
+    exit 0;
+endif
+
+usage:
+  echo "USAGE: dbadmin (options)"
+  echo ""
+  echo "  dbadmin init (dbserver) (dbuser) (dbpassword)"
+  echo "      creates admin tables, basic db user -- requires root password"
+  echo ""
+  echo "  dbadmin client (dbserver) (dbuser) (dbpassword) (client)"
+  echo "      add client name or regex"
+  echo ""
+  echo "  dbadmin user (dbserver) (dbuser) (username) (password)"
+  echo "      create a new www user and password"
+  echo ""
+  echo "  dbadmin project (dbserver) (dbuser) (dbname)"
+  echo "      create a new ipp project (database)"
+  echo ""
+  exit 2
Index: trunk/ippMonitor/scripts/generate
===================================================================
--- trunk/ippMonitor/scripts/generate	(revision 15784)
+++ trunk/ippMonitor/scripts/generate	(revision 15784)
@@ -0,0 +1,600 @@
+#!/usr/bin/env perl
+
+$VERBOSE = 0;
+
+if ($ARGV[0] eq "-v") { $VERBOSE = 1; shift @ARGV; }
+if (@ARGV != 3) { die "generate (schema) (template) (output)\n"; }
+
+$schema   = $ARGV[0];
+$template = $ARGV[1];
+$output   = $ARGV[2];
+
+# global variables:
+# @key, @value                         : paired list of keys and values
+# @headcode, @tailcode                 : additional HTML or PHP code before or after table
+# @field, @width, @name, @show, @link, @extras : properties of each table column
+# @imagedefs, %image: array of image defines
+
+&parse_schema;
+&parse_template;
+exit 0;
+
+sub parse_schema {
+    open (FILE, "$schema");
+    @list = <FILE>;
+    close (FILE);
+
+    &init_key ("MENU");
+    &init_key ("STYLE");
+    &init_key ("TABLE");
+    &init_key ("TITLE");
+    &init_key ("FILE");
+
+    &init_key ("FIELDS");
+
+    foreach $line (@list) {
+	chop $line;
+	($key, $value) = split (" ", $line, 2);
+	
+	# strip leading and trailing white space from the following
+	if ($key eq "TABLE") { ($value) = $value =~ m|^\s*(.+)\s*$|; }
+	if ($key eq "TYPE")  { ($value) = $value =~ m|^\s*(.+)\s*$|; }
+
+	&set_keypair ($key, $value);
+
+	# list of the table fields
+ 	if ($key eq "FIELD") {
+	    ($field, $width, $name, $show, $link, $extras) = split (/,\s+/, $value, 6);
+	    if (! $name) { die "table $ARGV[0] missing required elements\n"; }
+	    # ($field) = $field =~ m|\s*(\S+)\s*|;
+
+	    if ($VERBOSE) { printf "%-20s %-20s %-20s %-20s %-20s\n", $field, $name, $show, $link, $extras; }
+	    if ($show eq "") {$show = "value";}
+	    push @field,   $field;
+	    push @width,   $width;
+	    push @name,    $name;
+	    push @show,    $show;
+	    push @link,    $link;
+	    push @extras,  $extras;
+	}
+
+	if ($key eq "FILE") {
+	    $myFile = $value;
+	}
+
+	# list of the table fields
+ 	if ($key eq "HEAD") {
+	    push @headcode, $value;
+	}
+
+	# the IMAGE commands sets up a reference name
+	if ($key eq "IMAGE") {
+	    push @imagedefs, $value;
+	}
+
+	# the ARGS commands define arguments to FIELDS commands
+	if ($key eq "ARGS") {
+	    push @linkargs, $value;
+	}
+
+	# the OP commands define field operations
+	if ($key eq "OP") {
+	    push @opwords, $value;
+	}
+
+	# the TD_CLASS command sets up an alternate TD class
+	if ($key eq "TD_CLASS") {
+	    push @tdClasses, $value;
+	    # print STDERR "found TD_CLASS\n";
+	}
+
+	# list of the table fields
+ 	if ($key eq "TAIL") {
+	    push @tailcode, $value;
+	}
+
+	# list of the table restrictions
+	# replace this with a flexible where statement?
+ 	if ($key eq "WHERE") {
+	    ($field) = split (/,\s+/, $value, 1);
+	    if ($VERBOSE) { printf "%-20s\n", $field; }
+	    push @where,   $field;
+	}
+    }
+
+    # check on keys
+    &check_key ("MENU", "ipp.menu.dat");
+    &check_key ("STYLE", "ipp.css");
+    &check_key ("TABLE", "");
+    &check_key ("TITLE", "");
+    &check_key ("FILE", "");
+    
+    # these are used internally (not just a replacement)
+    for ($i = 0; $i < @key; $i++) {
+	if ($key[$i] eq "MENU") { $MENU = $value[$i]; }
+    }
+
+    # define FIELDS and WHERE strings, add to keypairs
+    &define_fields_count;
+    &define_fields_string (@field);
+    &define_where_string (@where);
+
+    foreach $linkarg (@linkargs) {
+	&parse_linkarg ($linkarg);
+    }
+
+    foreach $imagedef (@imagedefs) {
+	&parse_imagedef ($imagedef);
+    }
+
+    foreach $opword (@opwords) {
+	&parse_opwords ($opword);
+    }
+
+    if (0) {
+	print STDERR "show: $show[0]\n";
+	($a, $b, $c) = &parse_label ($show[0]);
+	print STDERR "a: $a, b: $b, c: $c\n";
+
+	print STDERR "extras: $extras[0]\n";
+	($a, $b, $c) = &parse_label ($extras[0]);
+	print STDERR "a: $a, b: $b, c: $c\n";
+
+	print STDERR "show: $show[1]\n";
+	($a, $b, $c) = &parse_label ($show[1]);
+	print STDERR "a: $a, b: $b, c: $c\n";
+
+	print STDERR "extras: $extras[1]\n";
+	($a, $b, $c) = &parse_label ($extras[1]);
+	print STDERR "a: $a, b: $b, c: $c\n";
+	exit 0;
+    }
+}
+
+sub parse_template {
+    open (FILE, $template);
+    @list = <FILE>;
+    close (FILE);
+
+    open (FILE, ">$output");
+
+    foreach $line (@list) {
+	
+	&check_keypairs;
+
+	print FILE $line;
+
+	# fill in table header
+	if ($line =~ m|// \*\* TABLE HEADER \*\*|) {
+	    &write_table_header;
+	}
+
+	# fill in TD_CLASS test
+	if ($line =~ m|// \*\* TD CLASS \*\*|) {
+	    &write_td_class;
+	}
+
+	# fill in table data
+	if ($line =~ m|// \*\* TABLE DATA \*\*|) {
+	    &write_table_data;
+	}
+
+	# fill in table query
+	if ($line =~ m|// \*\* TABLE QUERY \*\*|) {
+	    &write_table_query;
+	}
+
+	# fill in table restricts
+	if ($line =~ m|// \*\* TABLE RESTRICTIONS \*\*|) {
+	    &write_table_restrict;
+	}
+
+	# fill in table restricts
+	if ($line =~ m|// \*\* BUTTON RESTRICTIONS \*\*|) {
+	    &write_button_restrict;
+	}
+
+	# fill in head HTML or PHP code
+	if ($line =~ m|// \*\* HEAD CODE \*\*|) {
+	    &write_inline_code (@headcode);
+	}
+
+	# fill in tail HTML or PHP code
+	if ($line =~ m|// \*\* TAIL CODE \*\*|) {
+	    &write_inline_code (@tailcode);
+	}
+    }
+    close (FILE);
+}
+
+sub write_inline_code {
+    my (@code) = @_;
+    my ($i, $code, $type);
+    
+    for ($i = 0; $i < @code; $i++) {
+	($type, $line) = split (" ", $code[$i], 2);
+	if ($type eq "PHP") {
+	    printf FILE "$line\n";
+	}
+	if ($type eq "HTML") {
+	    printf FILE "?> $line <?\n";
+	}
+    }
+}
+
+# generate a table header cell (<th> </th>) for each field (show != none)
+sub write_table_header {
+
+    # add column sorting elements here
+    for ($i = 0; $i < @field; $i++) {
+	($label, $value, $string) = &parse_label ($show[$i]);
+	if ($show[$i] eq "none")  { next; }
+	# printf FILE "echo \"<th class=\\\"list\\\"> $name[$i] </th>\\n\";\n";
+	if ($label eq "op") {
+	    printf FILE "write_table_header (\"list\", \"$name[$i]\", \"$opf{$value}\", \$buttonLink, \$ID, '$myFile');\n";
+	} else {
+	    printf FILE "write_table_header (\"list\", \"$name[$i]\", \"$field[$i]\", \$buttonLink, \$ID, '$myFile');\n";
+	}
+    }
+}
+
+sub write_td_class {
+    my ($field, $testline);
+
+    if (@tdClasses == 0) { return; }
+    foreach $tdClass (@tdClasses) {
+	print STDERR "write TD CLASS: $tdClass...\n";
+
+	# TD_CLASS class field expression
+	($class, $field, $testline) = split (" ", $tdClass, 3);
+
+	$field = &parse_fieldname ($field);
+
+	printf FILE "  if ($field $testline) {\n";
+	printf FILE "    \$class = \"$class\";\n";
+	printf FILE "  }\n";
+
+	printf STDERR "  if ($field $testline) {\n";
+	printf STDERR "    \$class = \"$class\";\n";
+	printf STDERR "  }\n";
+    }
+}
+
+# generate a WHERE test for each field (field != *)
+sub write_table_restrict {
+
+    if ($WHERE) {
+	printf FILE "\$WHERE = \"WHERE $WHERE\";\n";
+    }	
+    for ($i = 0; $i < @field; $i++) {
+	$value = $field[$i];
+	if ($value eq "*") { next; }
+	printf FILE "\$WHERE = check_restrict ('$value', \$WHERE);\n";
+    }
+    printf FILE "\$WHERE = check_ordering (\$WHERE);\n";
+}
+
+# generate a button link entry for each field (field != *)
+sub write_button_restrict {
+
+    for ($i = 0; $i < @field; $i++) {
+	$value = $field[$i];
+	if ($value eq "*") { next; }
+	printf FILE "\$buttonLink = button_restrict ('$value', \$buttonLink);\n";
+    }
+}
+
+sub write_table_data {
+    my ($i, $Nrow);
+    my ($label, $value, $string);
+
+    for ($i = 0; $i < @field; $i++) {
+	($label, $value, $string) = &parse_label ($show[$i]);
+	$Nrow = $count[$i];
+
+	# create the link variable if this entry should be linked
+	if ($label eq "none")  { next; }
+
+	if ($label eq "value") {
+	    # create the basic link variable
+	    if ($link[$i]) {
+		printf FILE "  \$link = \"$link[$i]\" . \"?menu=$MENU&\" . \$ID['link'];\n";
+		# add extra GET data to target
+		if ($extras[$i]) { &parse_extras ($linkarg{$extras[$i]}); } 
+		$myLink = "\$link";
+	    } else {
+		$myLink = "\"\"";
+	    }
+	    # print the actual table cell line with the link...
+	    if (! $value && ($field[$i] ne "*")) { $value = "\$row[$Nrow]"; }
+	    printf FILE "  write_table_cell (\$class, $myLink, $value);\n";
+	    next;
+	}
+
+	if ($label eq "op") {
+	    # create the basic link variable
+	    if ($link[$i]) {
+		printf FILE "  \$link = \"$link[$i]\" . \"?menu=$MENU&\" . \$ID['link'];\n";
+		# add extra GET data to target
+		if ($extras[$i]) { &parse_extras ($linkarg{$extras[$i]}); } 
+		$myLink = "\$link";
+	    } else {
+		$myLink = "\"\"";
+	    }
+	    printf FILE "  write_table_cell (\$class, $myLink, $ops{$value});\n";
+	    next;
+	}
+
+	if (($label eq "image") && !$link[$i]) {
+	    # print the actual table cell line with the image...
+	    printf FILE "  echo \"<td class=\\\"\$class\\\"><img src=\\\"$image{$value}\\\"></td>\\n\";\n";
+	    next;
+	}
+
+	if (($label eq "image") && $link[$i]) {
+	    # create the basic link 
+	    printf FILE "  \$link = \"$link[$i]\" . \"?menu=$MENU&\" . \$ID['link'];\n";
+	    # add extra php data to target
+	    if ($extras[$i]) { &parse_extras ($linkarg{$extras[$i]}); } 
+	    # print the actual table cell line with the link...
+	    printf FILE "  echo \"<td class=\\\"\$class\\\"><a href=\\\"\$link\\\"> <img src=\\\"$image{$value}\\\"> </a></td>\\n\";\n";
+	    next;
+	}
+    }
+}
+
+sub write_table_query {
+    my ($i);
+    for ($i = 0; $i < @field; $i++) {
+	if ($show[$i] eq "none")  { next; }
+	if ($field[$i] eq "*")  { 
+	    # * fields create an empty cell 
+	    printf FILE "echo \"<td> &nbsp; </td>\\n\";\n";
+	} else {
+	    printf FILE "write_query_row ('$field[$i]', $width[$i]);\n";
+	}
+    }
+}
+
+sub define_fields_string {
+    my (@array) = @_;
+    my ($i, $FIELDS);
+
+    $FIELDS = "$array[0]";
+    for ($i = 1; $i < @array; $i++) {
+	# skip * fields (not a valid query element
+	if ($array[$i] eq "*") { next; }
+	$FIELDS = "$FIELDS,$array[$i]";
+    }
+    set_keypair ("FIELDS", $FIELDS);
+}
+
+sub define_fields_count {
+    my ($i, $Nrow);
+
+    @count = ();
+
+    $Nrow = 0;
+    for ($i = 0; $i < @field; $i++) {
+	# skip * fields (not a valid query element
+	if ($field[$i] eq "*") { 
+	    $count[$i] = -1;
+	} else {
+	    $count[$i] = $Nrow;
+	    $Nrow ++;
+	}
+    }
+}
+
+sub define_where_string {
+    my (@array) = @_;
+    my ($i, $FIELDS);
+
+    if (@array == 0) { return; }
+
+    $WHERE = "$array[0]";
+    for ($i = 1; $i < @array; $i++) {
+	$WHERE = "$WHERE AND $array[$i]";
+    }
+    
+    set_keypair ("WHERE", $WHERE);
+}
+
+sub parse_extras {
+    my ($extras) = $_[0];
+    my (@extfields);
+    my ($label, $value, $outline);
+    my ($i);
+
+    # examine the extras and parse the embedded fields (comma-separated)
+    @extfields = split (/,/, $extras);
+    for ($i = 0; $i < @extfields; $i++) {
+	($label, $value, $outline) = &parse_label ($extfields[$i]);
+	printf FILE "  \$link = \$link . \"&$outline\";\n";
+    }
+}
+
+# each linkarg is an entry of the form "word name=value"
+# the entries for matching words are concatenated together
+# separated by commas to create the value $linkarg{word}
+sub parse_linkarg {
+    my ($word, $value);
+
+    ($word, $value) = split (" ", $_[0]);
+
+    if ($linkarg{$word}) {
+	$linkarg{$word} = "$linkarg{$word},$value";
+    } else {
+	$linkarg{$word} = $value;
+    }	
+}
+
+# parse strings of the form label=value
+# if 'value' is of the form $field, try to match with 
+# a supplied DB field, and replace with $row[$n] if found
+sub parse_label {
+    my ($string) = $_[0];
+    my ($label, $value, $outline);
+    my ($Nrow, $i);
+
+    # unless we replace the value with the db row element, return the original string
+    $outline = $string;
+    $label = $string;
+    $value = "";
+
+    # search for embedded table fields and replace with row[N]
+    if ($VERBOSE) { print STDERR "string: $string\n"; }
+    if ($string =~ m|\S+=\S+|) {
+	($label, $value) = $string =~ m|(\S+)=(\S+)|;
+	if ($value =~ m|^\$|) {
+	  MATCH_LABEL:
+	    for ($i = 0; $i < @field; $i++) {
+		if ($field[$i] eq "*") { next; }
+		if ($value =~ m|^\$$field[$i]|) {
+		    # print "field: $field[$i]\n";
+		    ($name, $extra) = $value =~ m|^\$($field[$i])\@(\S+)|;
+		    # print "name: $name\n";
+		    # print "extra: $extra\n";
+		    # print "value: $value\n";
+
+		    $Nrow = $count[$i];
+		    if ($extra) {
+			$value = "\$row[$Nrow]\@$extra";
+		    } else {
+			$value = "\$row[$Nrow]";
+		    }
+		    # print "outval: $value\n";
+		    last MATCH_LABEL;
+		}
+	    }
+	    $outline = "$label=$value";
+	} 
+    }
+    return ($label, $value, $outline);
+}
+
+# given a variable of the form $fieldname, return the corresponding
+# row entry in the form $row[N], otherwise return $fieldname
+# globals: field (list of field names), count (list of sequence)
+sub parse_fieldname {
+    my ($variable) = $_[0];
+    my ($i);
+    
+    # print STDERR "variable: $variable\n";
+
+    unless ($variable =~ m|^\$|) {
+	return $variable;
+    }
+
+    $fieldname = substr ($variable, 1);
+
+    # print STDERR "fieldname: $fieldname\n";
+
+    for ($i = 0; $i < @field; $i++) {
+	# print STDERR "$i: $field[$i] : $fieldname\n";
+
+	if ($field[$i] eq "*") { next; }
+	if ($fieldname ne $field[$i]) { next; }
+
+
+	$Nrow = $count[$i];
+
+	$value = "\$row[$Nrow]";
+
+	# print STDERR "found : $i : $count[$i] : $Nrow : $value\n";
+	return $value;
+    }
+    return $variable;
+}
+
+sub parse_imagedef {
+    my ($value) = $_[0];
+
+    ($var, $name, $rule, $camera, $class) = split (" ", $value);
+    $name   = &parse_fieldname ($name);
+    $camera = &parse_fieldname ($camera);
+    $class  = &parse_fieldname ($class);
+    $image{$var} = "getimage.php?name=$name&rule=$rule&camera=$camera&class_id=$class";
+    return 1;
+}
+
+sub parse_opwords {
+    my ($value) = $_[0];
+
+    @words = split (" ", $value);
+    $name = shift (@words);
+
+    $opline = "";
+    foreach $word (@words) {
+	$fword = &parse_fieldname ($word);
+	push @outwords, $fword;
+	if ($word =~ m|^\$|) {
+	    $word = substr ($word, 1);
+	}
+	push @outfields, $word;
+    }
+    $outline = join (" ", @outwords);
+    $ops{$name} = $outline;
+    $outline = join (" ", @outfields);
+    $opf{$name} = $outline;
+
+    return 1;
+}
+
+sub init_key {
+    my ($key)   = $_[0];
+
+    push @key, $key;
+    push @value, "";
+}
+
+sub set_keypair {
+    my ($i);
+    my ($key)   = $_[0];
+    my ($value) = $_[1];
+
+    for ($i = 0; $i < @key; $i++) {
+	if ($key eq $key[$i]) {
+	    if ($value[$i] ne "") { die "key is multiply defined\n"; }
+	    $value[$i] = $value;
+	    if ($VERBOSE) { print STDERR "setting $key = $value\n"; }
+	    return;
+	}
+    }
+}
+
+sub check_key {
+    my ($i);
+    my ($key)     = $_[0];
+    my ($default) = $_[1];
+
+    for ($i = 0; $i < @key; $i++) {
+	if ($key eq $key[$i]) {
+	    if ($VERBOSE) { print "found $key: $key[$i]  -- $value[$i] (def: $default)\n"; }
+	    if (($default eq "") && ($value[$i] eq "")) { die "missing value for required key $key[$i]\n"; }
+	    if ($value[$i] eq "") { $value[$i] = $default; }
+	    return;
+	}
+    }
+    die "unknown key $key\n";
+}
+
+sub check_keypairs {
+    my ($i);
+    for ($i = 0; $i < @key; $i++) {
+	if ($VERBOSE) { print "$key[$i]  -- $value[$i]\n"; }
+	if ($line =~ m|\$$key[$i]|) {
+	    if ($value[$i] eq "") { die "missing value for required key $key[$i]\n"; }
+	    $line =~ s|\$$key[$i]|$value[$i]|g;
+	}
+    }
+}
+
+# we need to find the structure size, including padding 
+# i'm not sure I know the answer to this: it is probably 
+# the total number of bytes rounded up to the largest 
+# data item in the structure (ie, 8 for a double, etc)
+# if we have the size, then we can double check the structure
+# against the expectation at runtime.  for the moment,
+# calculate by hand and add to def.d file 
+
