/* * fileobj.c * vim:tw=80:expandtab * * Copyright (c) 2011 Clemens Lang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #if HAVE_CONFIG_H #include #endif #include #include #include #include #include "fileobj.h" #include "registry.h" #include "util.h" const char* file_props[] = { "id", "path", "actual_path", "active", "binary", NULL }; /* ${file} prop ?value? */ static int file_obj_prop(Tcl_Interp* interp, reg_file* file, int objc, Tcl_Obj* const objv[]) { int index; if (objc > 3) { Tcl_WrongNumArgs(interp, 2, objv, "?value?"); return TCL_ERROR; } if (objc == 2) { /* ${file} prop; return the current value */ reg_registry* reg = registry_for(interp, reg_attached); if (reg == NULL) { return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], file_props, "prop", 0, &index) == TCL_OK) { char* key = Tcl_GetString(objv[1]); char* value; reg_error error; if (reg_file_propget(file, key, &value, &error)) { Tcl_Obj* result = Tcl_NewStringObj(value, -1); Tcl_SetObjResult(interp, result); free(value); return TCL_OK; } return registry_failed(interp, &error); } return TCL_ERROR; } else { /* ${file} prop name value; set a new value */ reg_registry* reg = registry_for(interp, reg_attached); if (reg == NULL) { return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], file_props, "prop", 0, &index) == TCL_OK) { char* key = Tcl_GetString(objv[1]); char* value = Tcl_GetString(objv[2]); reg_error error; if (reg_file_propset(file, key, value, &error)) { return TCL_OK; } return registry_failed(interp, &error); } return TCL_ERROR; } } typedef struct { char* name; int (*function)(Tcl_Interp* interp, reg_file* file, int objc, Tcl_Obj* const objv[]); } file_obj_cmd_type; static file_obj_cmd_type file_cmds[] = { /* keys */ { "path", file_obj_prop }, { "actual_path", file_obj_prop }, { "active", file_obj_prop }, { "binary", file_obj_prop }, { NULL, NULL } }; /* ${file} cmd ?arg ...? */ /* This function implements the command that will be called when a file * created by `registry::file` is used as a procedure. Since all data is kept * in a temporary sqlite3 database that is created for the current interpreter, * none of the sqlite3 functions used have any error checking. That should be a * safe assumption, since nothing outside of registry:: should ever have the * chance to touch it. */ int file_obj_cmd(ClientData clientData, Tcl_Interp* interp, int objc, Tcl_Obj* const objv[]) { int cmd_index; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObjStruct(interp, objv[1], file_cmds, sizeof(file_obj_cmd_type), "cmd", 0, &cmd_index) == TCL_OK) { file_obj_cmd_type* cmd = &file_cmds[cmd_index]; return cmd->function(interp, (reg_file*)clientData, objc, objv); } return TCL_ERROR; }