# HG changeset patch # User David Bryant # Date 1348985485 -34200 # Node ID e33f37b14893be86b482ddd8fae30536096cdac8 # Parent a1c2b56cb44d7f0669ad65c7d9dba34db5a1e00d Port to 'no-more-make' https://github.com/GrahamStJack/no-more-make diff -r a1c2b56cb44d -r e33f37b14893 bob.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bob.cfg Sun Sep 30 15:41:25 2012 +0930 @@ -0,0 +1,155 @@ +############################################################################### + +# Example bob configuration file. +# +# Used by 'bob-config' to establish a build directory, from which a 'bob' +# command will build your project. +# +# This file should be located at the top level of a repository, below which +# are source directories. +# +# Before running bob-config, you need to: +# * Check out the project's source repository(s). +# * Ensure that all the project's external dependencies are available, +# either in standard system locations or in local project-specific +# locations. +# Bob does not verify external dependencies. +# +# If your project is built for a number of target architectures, use +# one config file for each architecture, and specify which one on the bob-config +# command-line. +# +############################################################################### +# +# Top-level syntax is a series of sections, each starting with a line: +# [section-name] +# +# Comment lines begin with '#'. +# +# The syntax for each section is section-specific, and described in each +# section. +# +############################################################################### + + +[defines] + +# Define variables. +# +# Any relative paths provided in variable definitions are relative to +# the directory this file is in, which is also the working directory +# of bob-config. +# +# A variable definition is: name = text +# +# Variables used by bob are: +# +# PROJECT - Path to directory containing the project's top-level Bobfile. +# REPOS - Paths to other repos (if any), below which are source +# directories that are available to build as part of this project. +# SYS_INC - Non-standard paths searched for system includes. +# SYS_LIB - Non-standard paths searched for system libraries. +# SYS_PATH - Non-standard paths searched for system utilities. +# SYS_IMP - Non-standard paths searched for D imports. +# C_EXTERN - Top-level C/C++ packages that are external to the project. +# D_EXTERN - Top-level D packages that are external to the project. +# +# Also required are build commands. +# +# Build-command variables are used by bob to create the output files specified +# in the project's Bobfile(s). They are of the form: +# (s) = command +# Reserved extensions with special meaning are: +# .obj -> object file +# .slib -> static library +# .dlib -> dynamic library +# .exe -> executable +# The extensions actually used vary with platform. +# Libraries and executables are built from object files. +# +# The commands that use object files to create libraries and executables are +# specified with the extension of the source files, not .obj. +# .c source files may be mixed with other types of source files, +# but others may not. .h files are assumed to be header files. +# +# Reserved variables defined by bob from information in Bobfiles are: +# +# INPUT - Paths of the input file(s) relative to the build dir. +# OUTPUT - Paths of the resultant built file(s) relative to the build dir. +# PROJ_INC - Project include or import paths. +# PROJ_LIB - Project library paths. +# LIBS - Required libraries. +# +# ${} expands a variable, cross-multiplying it with whatever it is adjacent to. +# eg, if HEADERS = one two three, then -I${HEADERS} becomes -Ione -Itwo -Ithree. +# If the variable is empty, the cross-multiplication is also empty. +# If there is no adjacent text, the variable's value is used. +# Variable expansion occurs just before a build command is issued, after +# all dependencies are known. + +# Required +PROJECT = doodle +REPOS = +SYS_IMP = +SYS_INC = +SYS_LIB = +SYS_PATH = +C_EXTERN = +D_EXTERN = core std glib gdk gtk gtkc cairo + +# Compiler switches +CFLAGS = -fpic -pedantic -Werror -Wall -Wno-long-long -Wundef -Wredundant-decls -DFILE_PATH=${INPUT} +C++FLAGS = ${CFLAGS} -Woverloaded-virtual -Wsign-promo -Wctor-dtor-privacy -Wnon-virtual-dtor +DFLAGS = -w -wi -gc -Isrc/gtk +LINKFLAGS = +DLINKFLAGS = -L-L/home/dbryant/source/d/GtkD + +# Build commands + +# Contrived example of source-code generation. +.H .h = cp ${INPUT} ${OUTPUT} +.CPP .cpp = cp ${INPUT} ${OUTPUT} + +# Documentation +.rst .html = rst2html ${INPUT} ${OUTPUT} + +# Object files +.c .obj = gcc -c ${INPUT} -isystem${SYS_INC} -iquote${PROJ_INC} ${CFLAGS} -o ${OUTPUT} +.cpp .obj = g++ -c ${INPUT} -isystem${SYS_INC} -iquote${PROJ_INC} ${C++FLAGS} -o ${OUTPUT} +.d .obj = dmd -c ${INPUT} -I${SYS_IMP} -I${PROJ_INC} ${DFLAGS} -of${OUTPUT} + +# Static libraries +.c .slib = rm -f ${OUTPUT} && ar csr ${OUTPUT} ${INPUT} +.cpp .slib = rm -f ${OUTPUT} && ar csr ${OUTPUT} ${INPUT} +.d .slib = rm -f ${OUTPUT} && ar csr ${OUTPUT} ${INPUT} + +# Dynamic libraries +.c .dlib = gcc -shared ${INPUT} ${LINKFLAGS} -L${SYS_LIB} -L${PROJ_LIB} -l{LIBS} -o ${OUTPUT} +.cpp .dlib = g++ -shared ${INPUT} ${LINKFLAGS} -L${SYS_LIB} -L${PROJ_LIB} -l{LIBS} -o ${OUTPUT} + +# Executables +.c .exe = gcc ${INPUT} ${LINKFLAGS} -L${SYS_LIB} -L${PROJ_LIB} -l${LIBS} -o ${OUTPUT} +.cpp .exe = g++ ${INPUT} ${LINKFLAGS} -L${SYS_LIB} -L${PROJ_LIB} -l${LIBS} -o ${OUTPUT} +.d .exe = dmd ${INPUT} ${DLINKFLAGS} -L-L${SYS_LIB} -L-L${PROJ_LIB} -L-l${LIBS} -of${OUTPUT} + +[modes] + +# For each mode, add to already-defined variables. +# Format of a mode is: the name of the mode, followed by indented +# variable additions. eg: +# +# debug +# CFLAGS += ggdb3 +# +# Exactly one mode is in use for a given build directory, and is specified +# on the bob-config command line. eg: mode=debug + +debug + CFLAGS += -O1 -ggdb3 + C++FLAGS += -O1 -ggdb3 + DFLAGS += + +release + CFLAGS += -O2 -NDEBUG + C++FLAGS += -O2 -NDEBUG + DFLAGS += -O -release diff -r a1c2b56cb44d -r e33f37b14893 configure.d --- a/configure.d Sun Sep 30 15:25:53 2012 +0930 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -// -// Configure script for the reuse repo -// - -import configure_functions; - -import std.process; -import std.string; -import std.file; - - -void main(string args[]) { - auto data = initialise(args, "doodle"); - - // - // open - // - - /* - // libssh2 and dependencies required by net - usePackage(data, "libssh2", Constraint.AtLeast, "1.2"); - useHeader( data, "gcrypt.h"); - useLibrary(data, "libgcrypt.so"); - */ - - // TAO is required by corba-tao - //useTao(data); - - - // - // reuse - // - - /* - usePackage(data, "libxml-2.0"); - usePackage(data, "libpng"); - usePackage(data, "freetype2"); - usePackage(data, "gtkmm-2.4", Constraint.AtLeast, "2.18"); - usePackage(data, "gtkglext-1.0"); - usePackage(data, "gstreamer-0.10", Constraint.AtLeast, "0.10.22"); - usePackage(data, "gstreamermm-0.10", Constraint.AtLeast, "0.10.1"); - usePackage(data, "xv"); - usePackage(data, "xext"); - usePackage(data, "xextproto"); - usePackage(data, "neon", Constraint.AtLeast, "0.28.2"); - usePackage(data, "libconfig", Constraint.AtLeast, "1.3.1"); - usePackage(data, "libconfig++", Constraint.AtLeast, "1.3.1"); - - useHeader( data, "jpeglib.h"); - useLibrary(data, "libjpeg.so"); - - useExecutable(data, "IMAGE_MAGICK_CONVERT", ["convert"]); - useExecutable(data, "ZIP", ["zip"]); - */ - - /* - appendBobVar(data, "CCFLAGS", - ["-DGTKMM_MACRO_SHADOW_ERROR", - "-DGTKMM_DISABLE_DEPRECATED", - "-DGDKMM_DISABLE_DEPRECATED", - "-DGLIBMM_DISABLE_DEPRECATED", - "-DGDK_DISABLE_DEPRECATED", - "-DG_DISABLE_DEPRECATED", - "-DLIBSIGC_DISABLE_DEPRECATED", - "-DGTK_DISABLE_DEPRECATED", - "-DGSEAL_ENABLE"]); - */ - - /* - if (exists("/opt/acacia/ecw")) { - string[][Use] dirs; - dirs[Use.Inc] = ["/opt/acacia/ecw/include"]; - dirs[Use.Lib] = ["/opt/acacia/ecw/lib"]; - setProjectDirs(data, dirs); - - useHeader( data, "NCSFile.h"); - useLibrary(data, "libNCSUtil.so"); - useLibrary(data, "libNCSCnet.so"); - useLibrary(data, "libNCSEcw.so"); - - appendBobVar(data, "CCFLAGS", ["-DUSE_ECW_CHARTING_RASTER_SOURCE"]); - appendBobVar(data, "ECW_LIBRARIES", ["NCSEcw", "NCSUtil", "NCSCnet"]); - } - */ - - - /* - appendRunVar(data, "GST_PLUGIN_PATH", ["${DIST_PATH}/lib/plugins"]); - */ - - - finalise(data, [/*"open"*/]); -} diff -r a1c2b56cb44d -r e33f37b14893 configure.sh --- a/configure.sh Sun Sep 30 15:25:53 2012 +0930 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -#!/bin/bash -rdmd -I. -Ibuild-tool configure.d $@ diff -r a1c2b56cb44d -r e33f37b14893 doodle/main/Bobfile --- a/doodle/main/Bobfile Sun Sep 30 15:25:53 2012 +0930 +++ b/doodle/main/Bobfile Sun Sep 30 15:41:25 2012 +0930 @@ -1,7 +1,7 @@ refer doodle/core doodle/dia doodle/fig doodle/gtk ; -dist-util chess : chess.d ; +dist-exe chess : chess.d ; -dist-util dupes : dupes.d : ; +dist-exe dupes : dupes.d : ; -dist-util doodle : doodle.d : dl gtkd ; +dist-exe doodle : doodle.d : dl gtkd ; diff -r a1c2b56cb44d -r e33f37b14893 doodle/main/chess.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doodle/main/chess.d Sun Sep 30 15:41:25 2012 +0930 @@ -0,0 +1,266 @@ +// +// Notes: +// ply = half move (ie black or white's half of the move) + +import std.stdio; +import std.ascii; +import std.traits; +import std.range; + +enum Side { + White, Black +} + +enum Name { + King, Queen, Rook, Bishop, Knight, Pawn +} + +struct Piece { + Side side; + Name name; +} + +string toString(Piece piece) { + return + [ + [ "\u2654", "\u2655", "\u2656", "\u2657", "\u2658", "\u2659" ], + [ "\u265A", "\u265B", "\u265C", "\u265D", "\u265E", "\u265F" ] + ] + [piece.side][piece.name]; +} + +// +// +// + +enum File { + _A, _B, _C, _D, _E, _F, _G, _H +} + +char toChar(File f) { + return "abcdefgh"[f]; +} + +enum Rank { + _1, _2, _3, _4, _5, _6, _7, _8 +} + +char toChar(Rank r) { + return "12345678"[r]; +} + +struct Coord { + File file; + Rank rank; +} + +string toString(in Coord coord) { + return toChar(coord.file) ~ "+" ~ toChar(coord.rank); +} + +// +// +// + +struct Board { + struct Square { + this(in Side side, in Name name) { + occupied = true; + piece = Piece(side, name); + } + + bool occupied = false; + Piece piece; // valid if occupied + } + + this(in Square[8][8] squares_) { + squares = squares_; + } + + Square square(Coord coord) const { + return squares[coord.file][coord.rank]; + } + +private: + Square * at(Coord coord) { + return &squares[coord.file][coord.rank]; + } + + void add(Piece piece, Coord coord) { + auto square = at(coord); + if (square.occupied) { + // error + } + else { + square.occupied = true; + square.piece = piece; + } + } + + void remove(Coord coord) { + auto square = at(coord); + if (square.occupied) { + square.occupied = false; + } + else { + // error + } + } + + void move(Coord source, Coord dest) { + auto source_sq = at(source); + auto dest_sq = at(dest); + + if (source_sq.occupied && !dest_sq.occupied) { + source_sq.occupied = false; + dest_sq.occupied = true; + dest_sq.piece = source_sq.piece; + } + else { + // error + } + } + + Square[8][8] squares = + [ + [ Square(Side.White, Name.Rook), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Rook) ], + [ Square(Side.White, Name.Knight), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Knight) ], + [ Square(Side.White, Name.Bishop), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Bishop) ], + [ Square(Side.White, Name.Queen), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Queen) ], + [ Square(Side.White, Name.King), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.King) ], + [ Square(Side.White, Name.Bishop), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Bishop) ], + [ Square(Side.White, Name.Knight), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Knight) ], + [ Square(Side.White, Name.Rook), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Rook) ] + ]; +} + +void dump(in Board board) { + bool light_square = true; + + foreach_reverse(r; EnumMembers!Rank) { + write(toChar(r)); + foreach(f; EnumMembers!File) { + + if (light_square) { + write("\033[47m"); + } + else { + write("\033[40m"); + } + + Board.Square square = board.square(Coord(f, r)); + if (square.occupied) { + write(toString(square.piece)); + } + else { + write(" "); + } + + light_square = !light_square; + } + writeln("\033[0m"); + + light_square = !light_square; + } + + write(" "); + foreach(f; EnumMembers!File) { + writef("%s", toChar(f)); + } + writeln(""); +} + +// +// +// + +enum KingState { + Safe, + Check, + CheckMate +} + +class Game { + struct SideState { + KingState kingState; + bool kingMoved; + bool queenRookMoved; + bool kingRookMoved; + } + + struct Ply { + this(Coord source_, Coord dest_) { + source = source_; + dest = dest_; + } + + Coord source; + Coord dest; + } + + @property Board board() { return _board; } + + struct Flags { + bool check; + bool mate; + } + + // Default initial pieces, white to play + this () { + } + + // Restore a previous game + this (Board board, Flags whiteFlags, Flags blackFlags, Side nextPly) { + _board = board; + _nextPly = nextPly; + } + + enum Acceptance { + Normal, + Check, + Mate, + Illegal + } + + Acceptance apply(in Ply ply) { + auto source = _board.square(ply.source); + auto dest = _board.square(ply.dest); + + /+ + auto sq1 = square(update.source); + auto sq2 = square(update.dest); + + if (sq1.piece == Piece.Pawn && update.dest.file != update.source.file) { + // en-passant + } + else if (sq1.piece == Piece.King && update.dest.file - update.source.file > 1) { + // castle + } + +/ + + return Acceptance.Normal; + } + + private { + struct PieceState { + bool uncaptured; + Coord coord; // valid if uncaptured + } + + Board _board; + Side _nextPly; + SideState _whiteSideState; + PieceState[8] _whitePieceState; + SideState _blackSideState; + PieceState[8] _blackPieceState; + } +} + +void main(string[] args) { + Board board; + dump(board); + + /+ + Game game; + +/ +} diff -r a1c2b56cb44d -r e33f37b14893 doodle/main/doodle.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doodle/main/doodle.d Sun Sep 30 15:41:25 2012 +0930 @@ -0,0 +1,114 @@ +module main.prog.doodler; + +// XXX bob problem, needs it to be like this... +import doodle.core.backtrace; +import doodle.core.logging; +import doodle.core.backtrace; + +import doodle.dia.standard_tools; +import doodle.dia.page_layer; +import doodle.dia.grid_layer; +import doodle.dia.tool_layer; + +import doodle.fig.diagram_layer; +import doodle.fig.select_tool; + +import doodle.fig.tools; + +import doodle.gtk.palette; + +import doodle.gtk.cairo_canvas; + +private { + /* + import doodle.core.backtrace; + import doodle.core.logging; + import doodle.core.backtrace; + + import doodle.dia.standard_tools; + import doodle.dia.page_layer; + import doodle.dia.grid_layer; + import doodle.dia.tool_layer; + + import doodle.fig.diagram_layer; + import doodle.fig.select_tool; + + import doodle.fig.tools; + + import doodle.gtk.palette; + + import doodle.gtk.cairo_canvas; + */ + + import gtk.Main; + import gtk.MainWindow; + import gtk.VBox; + + import std.stdio; +} + +final class TopLevel : /*private*/ IToolStackObserver { + this(string[] args) { + Main.init(args); + auto window = new MainWindow("Doodle"); + auto vbox = new VBox(false, 0); + + auto palette = new Palette!Tool; + _palette = palette; + + vbox.packStart(palette, false, false, 0); + + Tool[] tools; + tools ~= new PanTool; + tools ~= new ZoomTool; + tools ~= new SelectTool; + auto toolLayer = new ToolLayer(tools, this); + _toolStack = toolLayer; + + auto gridLayer = new GridLayer; + + auto diagramLayer = new DiagramLayer; + _diagram = diagramLayer; + + Layer[] layers; + layers ~= new PageLayer; + layers ~= gridLayer; + layers ~= diagramLayer; + layers ~= toolLayer; + + // assume the screen has PPI of 120.0 + immutable millimetersPerInch = 25.4; + immutable pixelsPerMillimetre = 120.0 / millimetersPerInch; + auto canvas = new CairoCanvas(layers, toolLayer, gridLayer, pixelsPerMillimetre); + + vbox.packStart(canvas, true, true, 0); + + Palette!Tool.Item[] items = [ + { "select.svg", "Select", "Select and modify elements", new SelectTool }, + { "rectangle.svg", "Rectangle", "Create rectangle", new CreateRectangleTool(_diagram) }, + { "ellipse.svg", "Ellipse", "Create ellipse", new CreateRectangleTool(_diagram) }, + { "polyline.svg", "Polyline", "Create polyline", new CreateRectangleTool(_diagram) } + ]; + + palette.configure(items, &_toolStack.use); + window.add(vbox); + window.setDefaultSize(640, 580); + window.showAll(); + Main.run(); + } + + void toolChanged(Tool tool) { + message("Tool changed %s", tool.name); + _palette.activate(tool); + } + + private { + IToolStack _toolStack; + IPalette!Tool _palette; + IDiagram _diagram; + } +} + +void main(string[] args) { + new TopLevel(args); +} diff -r a1c2b56cb44d -r e33f37b14893 doodle/main/dupes.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doodle/main/dupes.d Sun Sep 30 15:41:25 2012 +0930 @@ -0,0 +1,246 @@ +import std.stdio; +import std.string; +import std.exception; +import std.algorithm; +import std.file; +import std.md5; +import std.getopt; +import std.conv; +import std.ascii; +import std.c.stdlib; + +ulong string_to_size(string s) { + // Convert strings to sizes, eg: + // "50" -> 50 + // "80B" -> 80 + // "10K" -> 10240 + // "1M" -> 1048576 + // Throws ConvException + + immutable map = [ 'B':1UL, 'K':1UL<<10, 'M':1UL<<20, 'G':1UL<<30, 'T':1UL<<40 ]; + + if (s.length == 0) { + throw new ConvException("Empty string"); + } + else { + ulong multiplier = 1; + + if (isAlpha(s[$-1])) { + immutable ulong * m = (s[$-1] in map); + + if (m) { + multiplier = *m; + } + else { + throw new ConvException(format("Bad size unit character: %s", s[$-1])); + } + + s = s[0..$-1]; + } + + return multiplier * to!ulong(s); + } +} + +string size_to_string(in ulong size) { + /+ + immutable array = [ 'B', 'K', 'M', 'G', 'T' ]; + size_t index = 0; + + foreach (i, c; array) { + if (size / (1UL << i + + writefln("%s %s", i, c); + } + +/ + + return format("%sK", size / 1024); +} + +void find_duplicates(in string[] dirs, + in ulong file_size, + in ulong digest_size, + bool verbose) { + static ubyte[16] compute_md5(in string filename, in ulong max_bytes) { + size_t chunk_size = min(max_bytes, 4096 * 1024); + ubyte[16] digest; + + auto file = File(filename, "r"); + scope(exit) file.close(); + + MD5_CTX context; + context.start(); + ulong byte_count = 0; + foreach (ubyte[] buffer; chunks(file, chunk_size)) { + context.update(buffer); + byte_count += buffer.length; + if (byte_count >= max_bytes) { + break; + } + } + context.finish(digest); + + return digest; + } + + struct FileInfo { + string name; + ulong size; + } + + FileInfo[] file_array; + + writefln("Accumulating file list"); + + foreach (string dir; dirs) { + if (isDir(dir)) { + string last_entry; + try { + foreach (string filename; dirEntries(dir, SpanMode.depth, false)) { + last_entry = filename; + try { + if (!isSymlink(filename) && isFile(filename)) { + ulong size = getSize(filename); + if (size >= file_size) { + file_array ~= FileInfo(filename, size); + } + } + } + catch (Exception ex) { + writefln("Skipping %s", filename); + //writefln("Exception %s", ex); + // TODO accumulate errors and print after traversal + } + } + } + catch (FileException ex) { + // ignore + writefln("Error, dirEntries bailed out after: %s. Continuing anyway", last_entry); + } + } + else { + writefln("Not a dir: %s", dir); + } + } + + writefln("Processing %s files", file_array.length); + + uint[][ulong] size_to_file_indices; + bool[ulong] duplicate_sizes; + + foreach (uint index, file; file_array) { + //writefln("%s %s %s", index, file.name, file.size); + + if (uint[] * indices = (file.size in size_to_file_indices)) { + if (indices.length == 1) { + // Second time we've seen a file of this size, + // record it in the duplicate_sizes array + duplicate_sizes[file.size] = true; + } + + (*indices) ~= index; + } + else { + size_to_file_indices[file.size] = [ index ]; + } + } + + writefln("Number of files of duplicate size %s", duplicate_sizes.length); + + ulong total_waste = 0; + + foreach_reverse (size; duplicate_sizes.keys.sort) { + uint[] indices = size_to_file_indices[size]; + //writefln("For size %s there are %s files", size, indices.length); + + uint[][ubyte[16]] digest_to_indices; + + foreach (index; indices) { + const FileInfo file_info = file_array[index]; + + try { + ubyte[16] digest = compute_md5(file_info.name, digest_size); + + if (uint[] * duplicate_indices = (digest in digest_to_indices)) { + // A true duplicate + // index and index2 are the same + + (*duplicate_indices) ~= index; + } + else { + digest_to_indices[digest] ~= index; + } + } + catch (ErrnoException ex) { + //writefln("Skipping: %s", file_info.name); + } + + //writefln("\t%s", file_info.name); + } + + foreach (indices2; digest_to_indices) { + if (indices2.length > 1) { + // List the duplicates + foreach (i, index; indices) { + FileInfo file_info = file_array[index]; + if (i == 0) { + writefln("%s", size_to_string(file_info.size)); + total_waste += file_info.size; + } + writefln(" %s", file_info.name); + } + writefln(""); + } + } + } + + writefln("Done, total waste: %s", size_to_string(total_waste)); +} + +int main(string[] args) { + ulong file_size; + ulong digest_size; + bool verbose; + + try { + string file_size_string = "100K"; + string digest_size_string = "100K"; + + void help(in string) { + writefln("Usage: dupes [OPTION]... DIR...\n" + "Recursively locate duplicate files in a list of directories\n" + "\n" + "Options\n" + " -d, --digest-size=SIZE size of digest used for comparison [%s]\n" + " -f, --file-size=SIZE minimum size of files searched for duplication [%s]\n" + " -v, --verbose be verbose\n" + " --help display this help and exit\n" + "\n" + "SIZE is an integer, optionally followed by K, M, G, T", + file_size_string, + digest_size_string); + exit(1); + } + + getopt(args, + "file-size|f", &file_size_string, + "digest-size|d", &digest_size_string, + "verbose|v", &verbose, + "help", &help); + + file_size = string_to_size(file_size_string); + digest_size = string_to_size(digest_size_string); + } + catch (ConvException ex) { + writefln("Conversion error: %s", ex); + exit(2); + } + + if (verbose) { + writefln("file-size=%s, digest-size=%s", size_to_string(file_size), size_to_string(digest_size)); + } + + find_duplicates(args[1..$], file_size, digest_size, verbose); + + return 0; +} diff -r a1c2b56cb44d -r e33f37b14893 doodle/main/util/chess.d --- a/doodle/main/util/chess.d Sun Sep 30 15:25:53 2012 +0930 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,266 +0,0 @@ -// -// Notes: -// ply = half move (ie black or white's half of the move) - -import std.stdio; -import std.ascii; -import std.traits; -import std.range; - -enum Side { - White, Black -} - -enum Name { - King, Queen, Rook, Bishop, Knight, Pawn -} - -struct Piece { - Side side; - Name name; -} - -string toString(Piece piece) { - return - [ - [ "\u2654", "\u2655", "\u2656", "\u2657", "\u2658", "\u2659" ], - [ "\u265A", "\u265B", "\u265C", "\u265D", "\u265E", "\u265F" ] - ] - [piece.side][piece.name]; -} - -// -// -// - -enum File { - _A, _B, _C, _D, _E, _F, _G, _H -} - -char toChar(File f) { - return "abcdefgh"[f]; -} - -enum Rank { - _1, _2, _3, _4, _5, _6, _7, _8 -} - -char toChar(Rank r) { - return "12345678"[r]; -} - -struct Coord { - File file; - Rank rank; -} - -string toString(in Coord coord) { - return toChar(coord.file) ~ "+" ~ toChar(coord.rank); -} - -// -// -// - -struct Board { - struct Square { - this(in Side side, in Name name) { - occupied = true; - piece = Piece(side, name); - } - - bool occupied = false; - Piece piece; // valid if occupied - } - - this(in Square[8][8] squares_) { - squares = squares_; - } - - Square square(Coord coord) const { - return squares[coord.file][coord.rank]; - } - -private: - Square * at(Coord coord) { - return &squares[coord.file][coord.rank]; - } - - void add(Piece piece, Coord coord) { - auto square = at(coord); - if (square.occupied) { - // error - } - else { - square.occupied = true; - square.piece = piece; - } - } - - void remove(Coord coord) { - auto square = at(coord); - if (square.occupied) { - square.occupied = false; - } - else { - // error - } - } - - void move(Coord source, Coord dest) { - auto source_sq = at(source); - auto dest_sq = at(dest); - - if (source_sq.occupied && !dest_sq.occupied) { - source_sq.occupied = false; - dest_sq.occupied = true; - dest_sq.piece = source_sq.piece; - } - else { - // error - } - } - - Square[8][8] squares = - [ - [ Square(Side.White, Name.Rook), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Rook) ], - [ Square(Side.White, Name.Knight), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Knight) ], - [ Square(Side.White, Name.Bishop), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Bishop) ], - [ Square(Side.White, Name.Queen), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Queen) ], - [ Square(Side.White, Name.King), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.King) ], - [ Square(Side.White, Name.Bishop), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Bishop) ], - [ Square(Side.White, Name.Knight), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Knight) ], - [ Square(Side.White, Name.Rook), Square(Side.White, Name.Pawn), Square(), Square(), Square(), Square(), Square(Side.Black, Name.Pawn), Square(Side.Black, Name.Rook) ] - ]; -} - -void dump(in Board board) { - bool light_square = true; - - foreach_reverse(r; EnumMembers!Rank) { - write(toChar(r)); - foreach(f; EnumMembers!File) { - - if (light_square) { - write("\033[47m"); - } - else { - write("\033[40m"); - } - - Board.Square square = board.square(Coord(f, r)); - if (square.occupied) { - write(toString(square.piece)); - } - else { - write(" "); - } - - light_square = !light_square; - } - writeln("\033[0m"); - - light_square = !light_square; - } - - write(" "); - foreach(f; EnumMembers!File) { - writef("%s", toChar(f)); - } - writeln(""); -} - -// -// -// - -enum KingState { - Safe, - Check, - CheckMate -} - -class Game { - struct SideState { - KingState kingState; - bool kingMoved; - bool queenRookMoved; - bool kingRookMoved; - } - - struct Ply { - this(Coord source_, Coord dest_) { - source = source_; - dest = dest_; - } - - Coord source; - Coord dest; - } - - @property Board board() { return _board; } - - struct Flags { - bool check; - bool mate; - } - - // Default initial pieces, white to play - this () { - } - - // Restore a previous game - this (Board board, Flags whiteFlags, Flags blackFlags, Side nextPly) { - _board = board; - _nextPly = nextPly; - } - - enum Acceptance { - Normal, - Check, - Mate, - Illegal - } - - Acceptance apply(in Ply ply) { - auto source = _board.square(ply.source); - auto dest = _board.square(ply.dest); - - /+ - auto sq1 = square(update.source); - auto sq2 = square(update.dest); - - if (sq1.piece == Piece.Pawn && update.dest.file != update.source.file) { - // en-passant - } - else if (sq1.piece == Piece.King && update.dest.file - update.source.file > 1) { - // castle - } - +/ - - return Acceptance.Normal; - } - - private { - struct PieceState { - bool uncaptured; - Coord coord; // valid if uncaptured - } - - Board _board; - Side _nextPly; - SideState _whiteSideState; - PieceState[8] _whitePieceState; - SideState _blackSideState; - PieceState[8] _blackPieceState; - } -} - -void main(string[] args) { - Board board; - dump(board); - - /+ - Game game; - +/ -} diff -r a1c2b56cb44d -r e33f37b14893 doodle/main/util/doodle.d --- a/doodle/main/util/doodle.d Sun Sep 30 15:25:53 2012 +0930 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -module main.prog.doodler; - -// XXX bob problem, needs it to be like this... -import doodle.core.backtrace; -import doodle.core.logging; -import doodle.core.backtrace; - -import doodle.dia.standard_tools; -import doodle.dia.page_layer; -import doodle.dia.grid_layer; -import doodle.dia.tool_layer; - -import doodle.fig.diagram_layer; -import doodle.fig.select_tool; - -import doodle.fig.tools; - -import doodle.gtk.palette; - -import doodle.gtk.cairo_canvas; - -private { - /* - import doodle.core.backtrace; - import doodle.core.logging; - import doodle.core.backtrace; - - import doodle.dia.standard_tools; - import doodle.dia.page_layer; - import doodle.dia.grid_layer; - import doodle.dia.tool_layer; - - import doodle.fig.diagram_layer; - import doodle.fig.select_tool; - - import doodle.fig.tools; - - import doodle.gtk.palette; - - import doodle.gtk.cairo_canvas; - */ - - import gtk.Main; - import gtk.MainWindow; - import gtk.VBox; - - import std.stdio; -} - -final class TopLevel : /*private*/ IToolStackObserver { - this(string[] args) { - Main.init(args); - auto window = new MainWindow("Doodle"); - auto vbox = new VBox(false, 0); - - auto palette = new Palette!Tool; - _palette = palette; - - vbox.packStart(palette, false, false, 0); - - Tool[] tools; - tools ~= new PanTool; - tools ~= new ZoomTool; - tools ~= new SelectTool; - auto toolLayer = new ToolLayer(tools, this); - _toolStack = toolLayer; - - auto gridLayer = new GridLayer; - - auto diagramLayer = new DiagramLayer; - _diagram = diagramLayer; - - Layer[] layers; - layers ~= new PageLayer; - layers ~= gridLayer; - layers ~= diagramLayer; - layers ~= toolLayer; - - // assume the screen has PPI of 120.0 - immutable millimetersPerInch = 25.4; - immutable pixelsPerMillimetre = 120.0 / millimetersPerInch; - auto canvas = new CairoCanvas(layers, toolLayer, gridLayer, pixelsPerMillimetre); - - vbox.packStart(canvas, true, true, 0); - - Palette!Tool.Item[] items = [ - { "select.svg", "Select", "Select and modify elements", new SelectTool }, - { "rectangle.svg", "Rectangle", "Create rectangle", new CreateRectangleTool(_diagram) }, - { "ellipse.svg", "Ellipse", "Create ellipse", new CreateRectangleTool(_diagram) }, - { "polyline.svg", "Polyline", "Create polyline", new CreateRectangleTool(_diagram) } - ]; - - palette.configure(items, &_toolStack.use); - window.add(vbox); - window.setDefaultSize(640, 580); - window.showAll(); - Main.run(); - } - - void toolChanged(Tool tool) { - message("Tool changed %s", tool.name); - _palette.activate(tool); - } - - private { - IToolStack _toolStack; - IPalette!Tool _palette; - IDiagram _diagram; - } -} - -void main(string[] args) { - new TopLevel(args); -} diff -r a1c2b56cb44d -r e33f37b14893 doodle/main/util/dupes.d --- a/doodle/main/util/dupes.d Sun Sep 30 15:25:53 2012 +0930 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,246 +0,0 @@ -import std.stdio; -import std.string; -import std.exception; -import std.algorithm; -import std.file; -import std.md5; -import std.getopt; -import std.conv; -import std.ascii; -import std.c.stdlib; - -ulong string_to_size(string s) { - // Convert strings to sizes, eg: - // "50" -> 50 - // "80B" -> 80 - // "10K" -> 10240 - // "1M" -> 1048576 - // Throws ConvException - - immutable map = [ 'B':1UL, 'K':1UL<<10, 'M':1UL<<20, 'G':1UL<<30, 'T':1UL<<40 ]; - - if (s.length == 0) { - throw new ConvException("Empty string"); - } - else { - ulong multiplier = 1; - - if (isAlpha(s[$-1])) { - immutable ulong * m = (s[$-1] in map); - - if (m) { - multiplier = *m; - } - else { - throw new ConvException(format("Bad size unit character: %s", s[$-1])); - } - - s = s[0..$-1]; - } - - return multiplier * to!ulong(s); - } -} - -string size_to_string(in ulong size) { - /+ - immutable array = [ 'B', 'K', 'M', 'G', 'T' ]; - size_t index = 0; - - foreach (i, c; array) { - if (size / (1UL << i - - writefln("%s %s", i, c); - } - +/ - - return format("%sK", size / 1024); -} - -void find_duplicates(in string[] dirs, - in ulong file_size, - in ulong digest_size, - bool verbose) { - static ubyte[16] compute_md5(in string filename, in ulong max_bytes) { - size_t chunk_size = min(max_bytes, 4096 * 1024); - ubyte[16] digest; - - auto file = File(filename, "r"); - scope(exit) file.close(); - - MD5_CTX context; - context.start(); - ulong byte_count = 0; - foreach (ubyte[] buffer; chunks(file, chunk_size)) { - context.update(buffer); - byte_count += buffer.length; - if (byte_count >= max_bytes) { - break; - } - } - context.finish(digest); - - return digest; - } - - struct FileInfo { - string name; - ulong size; - } - - FileInfo[] file_array; - - writefln("Accumulating file list"); - - foreach (string dir; dirs) { - if (isDir(dir)) { - string last_entry; - try { - foreach (string filename; dirEntries(dir, SpanMode.depth, false)) { - last_entry = filename; - try { - if (!isSymlink(filename) && isFile(filename)) { - ulong size = getSize(filename); - if (size >= file_size) { - file_array ~= FileInfo(filename, size); - } - } - } - catch (Exception ex) { - writefln("Skipping %s", filename); - //writefln("Exception %s", ex); - // TODO accumulate errors and print after traversal - } - } - } - catch (FileException ex) { - // ignore - writefln("Error, dirEntries bailed out after: %s. Continuing anyway", last_entry); - } - } - else { - writefln("Not a dir: %s", dir); - } - } - - writefln("Processing %s files", file_array.length); - - uint[][ulong] size_to_file_indices; - bool[ulong] duplicate_sizes; - - foreach (uint index, file; file_array) { - //writefln("%s %s %s", index, file.name, file.size); - - if (uint[] * indices = (file.size in size_to_file_indices)) { - if (indices.length == 1) { - // Second time we've seen a file of this size, - // record it in the duplicate_sizes array - duplicate_sizes[file.size] = true; - } - - (*indices) ~= index; - } - else { - size_to_file_indices[file.size] = [ index ]; - } - } - - writefln("Number of files of duplicate size %s", duplicate_sizes.length); - - ulong total_waste = 0; - - foreach_reverse (size; duplicate_sizes.keys.sort) { - uint[] indices = size_to_file_indices[size]; - //writefln("For size %s there are %s files", size, indices.length); - - uint[][ubyte[16]] digest_to_indices; - - foreach (index; indices) { - const FileInfo file_info = file_array[index]; - - try { - ubyte[16] digest = compute_md5(file_info.name, digest_size); - - if (uint[] * duplicate_indices = (digest in digest_to_indices)) { - // A true duplicate - // index and index2 are the same - - (*duplicate_indices) ~= index; - } - else { - digest_to_indices[digest] ~= index; - } - } - catch (ErrnoException ex) { - //writefln("Skipping: %s", file_info.name); - } - - //writefln("\t%s", file_info.name); - } - - foreach (indices2; digest_to_indices) { - if (indices2.length > 1) { - // List the duplicates - foreach (i, index; indices) { - FileInfo file_info = file_array[index]; - if (i == 0) { - writefln("%s", size_to_string(file_info.size)); - total_waste += file_info.size; - } - writefln(" %s", file_info.name); - } - writefln(""); - } - } - } - - writefln("Done, total waste: %s", size_to_string(total_waste)); -} - -int main(string[] args) { - ulong file_size; - ulong digest_size; - bool verbose; - - try { - string file_size_string = "100K"; - string digest_size_string = "100K"; - - void help(in string) { - writefln("Usage: dupes [OPTION]... DIR...\n" - "Recursively locate duplicate files in a list of directories\n" - "\n" - "Options\n" - " -d, --digest-size=SIZE size of digest used for comparison [%s]\n" - " -f, --file-size=SIZE minimum size of files searched for duplication [%s]\n" - " -v, --verbose be verbose\n" - " --help display this help and exit\n" - "\n" - "SIZE is an integer, optionally followed by K, M, G, T", - file_size_string, - digest_size_string); - exit(1); - } - - getopt(args, - "file-size|f", &file_size_string, - "digest-size|d", &digest_size_string, - "verbose|v", &verbose, - "help", &help); - - file_size = string_to_size(file_size_string); - digest_size = string_to_size(digest_size_string); - } - catch (ConvException ex) { - writefln("Conversion error: %s", ex); - exit(2); - } - - if (verbose) { - writefln("file-size=%s, digest-size=%s", size_to_string(file_size), size_to_string(digest_size)); - } - - find_duplicates(args[1..$], file_size, digest_size, verbose); - - return 0; -} diff -r a1c2b56cb44d -r e33f37b14893 doodle/tk/Bobfile --- a/doodle/tk/Bobfile Sun Sep 30 15:25:53 2012 +0930 +++ b/doodle/tk/Bobfile Sun Sep 30 15:41:25 2012 +0930 @@ -1,6 +1,6 @@ refer doodle/core ; -test-util test1 : test1.d ; -test-util test2 : test2.d ; +#test-util test1 : test1.d ; +#test-util test2 : test2.d ; static-lib tk : color.d events.d geometry.d palette.d renderer.d screen_model.d; diff -r a1c2b56cb44d -r e33f37b14893 gtk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gtk Sun Sep 30 15:41:25 2012 +0930 @@ -0,0 +1,1 @@ +/home/dbryant/source/d/GtkD/src \ No newline at end of file diff -r a1c2b56cb44d -r e33f37b14893 nobuild/Boboptions --- a/nobuild/Boboptions Sun Sep 30 15:25:53 2012 +0930 +++ b/nobuild/Boboptions Sun Sep 30 15:41:25 2012 +0930 @@ -8,4 +8,5 @@ #DFLAGS = -w -wi -gc -I~/source/d/gtkD-trunk/src ; #DFLAGS = -w -wi -gc -I~/source/d/GtkD/src ; DFLAGS = -w -wi -gc -Isrc/gtk ; + DLINKFLAGS = -L-L/home/dbryant/source/d/GtkD ; diff -r a1c2b56cb44d -r e33f37b14893 nobuild/make-tags.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nobuild/make-tags.sh Sun Sep 30 15:41:25 2012 +0930 @@ -0,0 +1,3 @@ +#!/bin/bash + +find -L src -name \*.d | ctags -L- --extra=+f -f TAGS ;