1/* 2 * convert.c -- 3 * 4 * Implements the C level procedures handling option processing 5 * of transformation reflecting the work to the tcl level. 6 * 7 * 8 * Copyright (c) 1997 Andreas Kupries (a.kupries@westend.com) 9 * All rights reserved. 10 * 11 * Permission is hereby granted, without written agreement and without 12 * license or royalty fees, to use, copy, modify, and distribute this 13 * software and its documentation for any purpose, provided that the 14 * above copyright notice and the following two paragraphs appear in 15 * all copies of this software. 16 * 17 * IN NO EVENT SHALL I LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, 18 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS 19 * SOFTWARE AND ITS DOCUMENTATION, EVEN IF I HAVE BEEN ADVISED OF THE 20 * POSSIBILITY OF SUCH DAMAGE. 21 * 22 * I SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND 25 * I HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 26 * ENHANCEMENTS, OR MODIFICATIONS. 27 * 28 * CVS: $Id: ref_opt.c,v 1.9 2009/05/07 04:57:27 andreas_kupries Exp $ 29 */ 30 31#include "reflect.h" 32 33/* 34 * forward declarations of all internally used procedures. 35 */ 36 37static Trf_Options 38CreateOptions _ANSI_ARGS_ ((ClientData clientData)); 39 40static void 41DeleteOptions _ANSI_ARGS_ ((Trf_Options options, 42 ClientData clientData)); 43static int 44CheckOptions _ANSI_ARGS_ ((Trf_Options options, 45 Tcl_Interp* interp, 46 CONST Trf_BaseOptions* baseOptions, 47 ClientData clientData)); 48 49static int 50SetOption _ANSI_ARGS_ ((Trf_Options options, 51 Tcl_Interp* interp, 52 CONST char* optname, 53 CONST Tcl_Obj* optvalue, 54 ClientData clientData)); 55 56static int 57QueryOptions _ANSI_ARGS_ ((Trf_Options options, 58 ClientData clientData)); 59 60static void 61SeekQueryOptions _ANSI_ARGS_ ((Tcl_Interp* interp, 62 Trf_Options options, 63 Trf_SeekInformation* seekInfo, 64 ClientData clientData)); 65 66/* 67 *------------------------------------------------------* 68 * 69 * TrfTransformOptions -- 70 * 71 * ------------------------------------------------* 72 * Accessor to the set of vectors realizing option 73 * processing for reflecting transformation. 74 * ------------------------------------------------* 75 * 76 * Sideeffects: 77 * None. 78 * 79 * Result: 80 * See above. 81 * 82 *------------------------------------------------------* 83 */ 84 85Trf_OptionVectors* 86TrfTransformOptions () 87{ 88 static Trf_OptionVectors optVec = /* THREADING: const, read-only => safe */ 89 { 90 CreateOptions, 91 DeleteOptions, 92 CheckOptions, 93 NULL, /* no string procedure for 'SetOption' */ 94 SetOption, 95 QueryOptions, 96 SeekQueryOptions /* Tcl level can change/define the ratio */ 97 }; 98 99 return &optVec; 100} 101 102/* 103 *------------------------------------------------------* 104 * 105 * CreateOptions -- 106 * 107 * ------------------------------------------------* 108 * Create option structure for reflecting transformation. 109 * ------------------------------------------------* 110 * 111 * Sideeffects: 112 * Allocates memory and initializes it as 113 * option structure for reflecting 114 * transformations. 115 * 116 * Result: 117 * A reference to the allocated block of 118 * memory. 119 * 120 *------------------------------------------------------* 121 */ 122 123static Trf_Options 124CreateOptions (clientData) 125ClientData clientData; 126{ 127 TrfTransformOptionBlock* o; 128 129 o = (TrfTransformOptionBlock*) ckalloc (sizeof (TrfTransformOptionBlock)); 130 o->mode = TRF_UNKNOWN_MODE; 131 o->command = (Tcl_Obj*) NULL; 132 133 return (Trf_Options) o; 134} 135 136/* 137 *------------------------------------------------------* 138 * 139 * DeleteOptions -- 140 * 141 * ------------------------------------------------* 142 * Delete option structure of a reflecting transformation 143 * ------------------------------------------------* 144 * 145 * Sideeffects: 146 * A memory block allocated by 'CreateOptions' 147 * is released. 148 * 149 * Result: 150 * None. 151 * 152 *------------------------------------------------------* 153 */ 154 155static void 156DeleteOptions (options, clientData) 157Trf_Options options; 158ClientData clientData; 159{ 160 TrfTransformOptionBlock* o = (TrfTransformOptionBlock*) options; 161 162 if (o->command != NULL) { 163 Tcl_DecrRefCount (o->command); 164 } 165 166 ckfree ((VOID*) o); 167} 168 169/* 170 *------------------------------------------------------* 171 * 172 * CheckOptions -- 173 * 174 * ------------------------------------------------* 175 * Check the given option structure for errors. 176 * ------------------------------------------------* 177 * 178 * Sideeffects: 179 * May modify the given structure to set 180 * default values into uninitialized parts. 181 * 182 * Result: 183 * A standard Tcl error code. 184 * 185 *------------------------------------------------------* 186 */ 187 188static int 189CheckOptions (options, interp, baseOptions, clientData) 190Trf_Options options; 191Tcl_Interp* interp; 192CONST Trf_BaseOptions* baseOptions; 193ClientData clientData; 194{ 195 TrfTransformOptionBlock* o = (TrfTransformOptionBlock*) options; 196 197 if (o->command == NULL) { 198 Tcl_AppendResult (interp, "command not specified", (char*) NULL); 199 return TCL_ERROR; 200 } 201 202 if ((o->command->bytes == 0) && (o->command->typePtr == NULL)) { 203 /* object defined, but empty, reject this too */ 204 Tcl_AppendResult (interp, "command specified, but empty", (char*) NULL); 205 return TCL_ERROR; 206 } 207 208 if (baseOptions->attach == (Tcl_Channel) NULL) /* IMMEDIATE? */ { 209 if (o->mode == TRF_UNKNOWN_MODE) { 210 Tcl_AppendResult (interp, "-mode option not set", (char*) NULL); 211 return TCL_ERROR; 212 } 213 } else /* ATTACH */ { 214 if (o->mode != TRF_UNKNOWN_MODE) { 215 /* operation mode irrelevant for attached transformation, 216 * and specification therefore ruled as illegal. 217 */ 218 Tcl_AppendResult (interp, "mode illegal for attached transformation", 219 (char*) NULL); 220 return TCL_ERROR; 221 } 222 o->mode = TRF_WRITE_MODE; 223 } 224 225 return TCL_OK; 226} 227 228/* 229 *------------------------------------------------------* 230 * 231 * SetOption -- 232 * 233 * ------------------------------------------------* 234 * Define value of given option. 235 * ------------------------------------------------* 236 * 237 * Sideeffects: 238 * Sets the given value into the option 239 * structure 240 * 241 * Result: 242 * A standard Tcl error code. 243 * 244 *------------------------------------------------------* 245 */ 246 247static int 248SetOption (options, interp, optname, optvalue, clientData) 249Trf_Options options; 250Tcl_Interp* interp; 251CONST char* optname; 252CONST Tcl_Obj* optvalue; 253ClientData clientData; 254{ 255 TrfTransformOptionBlock* o = (TrfTransformOptionBlock*) options; 256 int len; 257 CONST char* value; 258 259 len = strlen (optname+1); 260 261 switch (optname [1]) { 262 case 'm': 263 if (0 != strncmp (optname, "-mode", len)) 264 goto unknown_option; 265 266 value = Tcl_GetStringFromObj ((Tcl_Obj*) optvalue, NULL); 267 len = strlen (value); 268 269 switch (value [0]) { 270 case 'r': 271 if (0 != strncmp (value, "read", len)) 272 goto unknown_mode; 273 274 o->mode = TRF_READ_MODE; 275 break; 276 277 case 'w': 278 if (0 != strncmp (value, "write", len)) 279 goto unknown_mode; 280 281 o->mode = TRF_WRITE_MODE; 282 break; 283 284 default: 285 unknown_mode: 286 Tcl_AppendResult (interp, "unknown mode '", (char*) NULL); 287 Tcl_AppendResult (interp, value, (char*) NULL); 288 Tcl_AppendResult (interp, "', should be 'read' or 'write'", (char*) NULL); 289 return TCL_ERROR; 290 break; 291 } /* switch optvalue */ 292 break; 293 294 case 'c': 295 if (0 != strncmp (optname, "-command", len)) 296 goto unknown_option; 297 298 /* 'optvalue' contains the command to execute for a buffer */ 299 300 /* 301 * Store reference, tell the interpreter about it. 302 * We have to unCONST it explicitly to allow modification 303 * of its reference counter 304 */ 305 o->command = (Tcl_Obj*) optvalue; 306 Tcl_IncrRefCount (o->command); 307 break; 308 309 default: 310 goto unknown_option; 311 break; 312 } 313 314 return TCL_OK; 315 316 unknown_option: 317 Tcl_AppendResult (interp, "unknown option '", (char*) NULL); 318 Tcl_AppendResult (interp, optname, (char*) NULL); 319 Tcl_AppendResult (interp, "', should be '-mode' or '-command'", (char*) NULL); 320 return TCL_ERROR; 321} 322 323/* 324 *------------------------------------------------------* 325 * 326 * QueryOptions -- 327 * 328 * ------------------------------------------------* 329 * Returns a value indicating wether the encoder or 330 * decoder set of vectors is to be used by immediate 331 * execution. 332 * ------------------------------------------------* 333 * 334 * Sideeffects: 335 * None 336 * 337 * Result: 338 * 1 - use encoder vectors. 339 * 0 - use decoder vectors. 340 * 341 *------------------------------------------------------* 342 */ 343 344static int 345QueryOptions (options, clientData) 346Trf_Options options; 347ClientData clientData; 348{ 349 TrfTransformOptionBlock* o = (TrfTransformOptionBlock*) options; 350 351 return (o->mode == TRF_WRITE_MODE ? 1 : 0); 352} 353 354/* 355 *------------------------------------------------------* 356 * 357 * SeekQueryOptions -- 358 * 359 * ------------------------------------------------* 360 * Modifies the natural seek policy according to the 361 * configuration of the transformation (queries the 362 * tcl level). 363 * ------------------------------------------------* 364 * 365 * Sideeffects: 366 * May modify 'seekInfo'. 367 * 368 * Result: 369 * None. 370 * 371 *------------------------------------------------------* 372 */ 373 374static void 375SeekQueryOptions (interp, options, seekInfo, clientData) 376 Tcl_Interp* interp; 377 Trf_Options options; 378 Trf_SeekInformation* seekInfo; 379 ClientData clientData; 380{ 381 TrfTransformOptionBlock* o = (TrfTransformOptionBlock*) options; 382 ReflectControl rc; 383 384 START (SeekQueryOptions); 385 386 rc.interp = interp; 387 rc.naturalRatio.numBytesTransform = seekInfo->numBytesTransform; 388 rc.naturalRatio.numBytesDown = seekInfo->numBytesDown; 389 rc.command = o->command; 390 Tcl_IncrRefCount (rc.command); 391 392 393 PRINT ("in = (%d, %d)\n", 394 seekInfo->numBytesTransform, seekInfo->numBytesDown); FL; 395 396 RefExecuteCallback (&rc, (Tcl_Interp*) interp, 397 (unsigned char*) "query/ratio", 398 NULL, 0, TRANSMIT_RATIO /* -> naturalRatio */, 1); 399 400 seekInfo->numBytesTransform = rc.naturalRatio.numBytesTransform; 401 seekInfo->numBytesDown = rc.naturalRatio.numBytesDown; 402 403 Tcl_DecrRefCount (rc.command); 404 405 406 PRINT ("out = (%d, %d)\n", 407 seekInfo->numBytesTransform, seekInfo->numBytesDown); FL; 408 409 DONE (SeekQueryOptions); 410} 411