View Source

[modwtcl]
apreq.h
dist/
libapreq1/
mod_wtcl.c
mod_wtcl.h
setupExclude.txt
util/
win.def
win.mak
wt1.1/
WtAppTable.c
WtAppTable.h
WtBasicCmds.c
WtBasicCmds.h
WtClientRequest.c
WtClientRequest.h
WtCollection.c
WtCollection.h
WtCollectionCmds.c
WtCollectionCmds.h
WtContext.c
WtContext.h
WtContextEvents.c
WtContextEvents.h
WtCookie.c
WtCookie.h
WtDbSession.c
WtDbSession.h
WtExecute.c
WtExecute.h
WtHtmlEntities.c
WtHtmlEntities.h
WtInitCmds.c
WtInitCmds.h
WtMtTable.c
WtMtTable.h
WtMultiTable.c
WtMultiTable.h
WtOS.h
WtProcSession.c
WtProcSession.h
WtResponse.c
WtResponse.h
WtServerCmds.c
WtServerCmds.h
WtSession.c
WtSession.h
WtSettings.c
WtSettings.h
WtTable.c
WtTable.h
WtTableCmds.c
WtTableCmds.h
WtTableUtil.c
WtTableUtil.h
WtUpload.c
WtUpload.h
WtUtil.c
WtUtil.h
WtWebErrors.c
WtWebErrors.h
WtWindows.h
File: / archive / modwtcl / WtExecute.c

Lines Size Modified Created Owner MIME Types
880 23,160 2010/05/09 04:03:46 2011/06/13 15:35:15 BUILTIN\Administrators text/x-csrc

0001
/*
0002
 * Copyright 2001 Alexander Boverman and the original authors.
0003
 * 
0004
 * Licensed under the Apache License, Version 2.0 (the "License");
0005
 * you may not use this file except in compliance with the License.
0006
 * You may obtain a copy of the License at
0007
 * 
0008
 *      http://www.apache.org/licenses/LICENSE-2.0
0009
 * 
0010
 * Unless required by applicable law or agreed to in writing, software
0011
 * distributed under the License is distributed on an "AS IS" BASIS,
0012
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013
 * See the License for the specific language governing permissions and
0014
 * limitations under the License.
0015
 */
0016
0017
#include "WtOS.h"
0018
#include "WtExecute.h"
0019
#include "WtContext.h"
0020
#include "WtUtil.h"
0021
#include "WtTable.h"
0022
#include "WtTableUtil.h"
0023
#include "WtBasicCmds.h"
0024
#include "WtWebErrors.h"
0025
#include "WtContextEvents.h"
0026
0027
void WtInitExecState(WtExecutionState *execState, WtContext *w, Tcl_Interp *interp)
0028
{
0029
  memset(execState, 0, sizeof(WtExecutionState));
0030
  execState->context = w;
0031
  execState->interp = interp;
0032
}
0033
0034
void WtDeleteExecState(WtExecutionState *execState)
0035
{
0036
  if (execState->requestedPath) {
0037
    Tcl_DecrRefCount(execState->requestedPath);
0038
    execState->requestedPath = NULL;
0039
  }
0040
0041
  if (execState->targetPath) {
0042
    Tcl_DecrRefCount(execState->targetPath);
0043
    execState->targetPath = NULL;
0044
  }
0045
0046
  if (execState->namesp) {
0047
    Tcl_DecrRefCount(execState->namesp);
0048
    execState->namesp = NULL;
0049
  }
0050
0051
  if (execState->genCode) {
0052
    Tcl_DecrRefCount(execState->genCode);
0053
    execState->genCode = NULL;
0054
  }
0055
}
0056
0057
int WtFindAndExecuteFile(WtContext *w, Tcl_Obj *requestedPath, Tcl_Interp *interp)
0058
{
0059
  int ok = 0;
0060
  WtExecutionState execState;
0061
0062
  WtInitExecState(&execState, w, interp);
0063
0064
  execState.requestedPath = requestedPath;
0065
  Tcl_IncrRefCount(execState.requestedPath);
0066
0067
  execState.targetPath = WtFindFile(&execState);
0068
0069
  if (execState.targetPath) {
0070
    Tcl_IncrRefCount(execState.targetPath);
0071
    ok = WtExecuteFile(&execState);
0072
  }
0073
0074
  WtDeleteExecState(&execState);
0075
0076
  return ok;
0077
}
0078
0079
Tcl_Obj *WtFindFile(WtExecutionState *execState)
0080
{
0081
  Tcl_Obj *path = WtResolvePath(execState->context,
0082
    execState->requestedPath, NULL);
0083
  if (!path) {
0084
    Tcl_AppendResult(execState->interp, "Failed to find file \"",
0085
                     WtToString(execState->requestedPath), "\": ",
0086
                     Tcl_PosixError(execState->interp), ".", NULL);
0087
  }
0088
  return path;
0089
}
0090
0091
Tcl_Obj *WtResolvePath(WtContext *w, Tcl_Obj *requestedPath, Tcl_Obj *dirs)
0092
{
0093
  int i, len;
0094
  char *bytes, *parts[2], *p;
0095
  Tcl_PathType pathType;
0096
  Tcl_DString joined;
0097
  Tcl_Obj *resolved = NULL, *item;
0098
0099
  bytes = Tcl_GetStringFromObj(requestedPath, &len);
0100
  pathType = Tcl_GetPathType(bytes);
0101
0102
  if (pathType == TCL_PATH_ABSOLUTE || pathType == TCL_PATH_VOLUME_RELATIVE) {
0103
    return Tcl_NewStringObj(bytes, len);
0104
  }
0105
0106
  if (!dirs) {
0107
    dirs = w->web->loader.includeSearchPath;
0108
  }
0109
0110
  /* XXX: Should have an interp */
0111
0112
  if (Tcl_ListObjLength(NULL, dirs, &len) != TCL_OK) {
0113
    return NULL;
0114
  }
0115
0116
  for (i = 0; i < len; ++i) {
0117
    if (Tcl_ListObjIndex(NULL, dirs, i, &item) != TCL_OK) {
0118
      break;
0119
    }
0120
    parts[0] = Tcl_GetStringFromObj(item, NULL);
0121
    parts[1] = bytes;
0122
0123
    Tcl_DStringInit(&joined);
0124
    p = Tcl_JoinPath(2, parts, &joined);
0125
0126
    if (p && Tcl_Access(p, 00) == 0) {
0127
      resolved = Tcl_NewStringObj(p, -1);
0128
    }
0129
0130
    Tcl_DStringFree(&joined);
0131
0132
    if (resolved) {
0133
      return resolved;
0134
    }
0135
  }
0136
0137
  return NULL;
0138
}
0139
0140
int WtExecuteFile(WtExecutionState *execState)
0141
{
0142
  int ok = 0, n;
0143
  Tcl_Obj *text;
0144
0145
  WtLog(HERE, APLOG_DEBUG | APLOG_NOERRNO, execState->context,
0146
    "Wtcl: WtExecuteFile (targetPath = \"%s\").",
0147
    Tcl_GetString(execState->targetPath));
0148
0149
  text = WtReadFile(execState->targetPath, &n, execState->interp);
0150
0151
  if (text) {
0152
    ok = WtExecuteString(execState, text, n);
0153
  }
0154
0155
  return ok;
0156
}
0157
0158
Tcl_Obj *WtReadFile(Tcl_Obj *path, int *bytes, Tcl_Interp *interp)
0159
{
0160
  int ok = 0, n = 0;
0161
  Tcl_Channel chan;
0162
  Tcl_Obj *text = NULL;
0163
0164
  chan = Tcl_OpenFileChannel(interp, WtToString(path), "r", 0666);
0165
0166
  if (chan) {
0167
    if (Tcl_SetChannelOption(interp, chan, "-translation",
0168
        "binary") == TCL_OK) {
0169
      text = Tcl_NewObj();
0170
      Tcl_IncrRefCount(text);
0171
      n = Tcl_ReadChars(chan, text, -1, 0);
0172
      if (n == -1) {
0173
        Tcl_AppendResult(interp, "Failed to read file \"",
0174
          path, "\": ", Tcl_PosixError(interp), ".", NULL);
0175
      } else {
0176
        ok = 1;
0177
      }
0178
    }
0179
    if (Tcl_Close(interp, chan) != TCL_OK) {
0180
      ok = 0;
0181
    }
0182
  }
0183
0184
  if (ok) {
0185
    if (bytes) {
0186
      *bytes = n;
0187
    }
0188
  } else {
0189
    if (text) {
0190
      Tcl_DecrRefCount(text);
0191
      text = NULL;
0192
    }
0193
    if (bytes) {
0194
      *bytes = -1;
0195
    }
0196
  }
0197
0198
  return text;
0199
}
0200
0201
int WtExecuteString(WtExecutionState *execState, Tcl_Obj *string, int len)
0202
{
0203
  int status = WT_STATUS_OK, rc, errorSetId = -1, errorCount;
0204
  Tcl_Obj *frame, *returnValue = NULL, *errMsg;
0205
  WtContext *w = execState->context;
0206
  WtWebContext *web = execState->context->web;
0207
  char str[128];
0208
0209
  WtLog(HERE, APLOG_DEBUG | APLOG_NOERRNO, w,
0210
    "Wtcl: WtExecuteString (len = %d).", len);
0211
0212
  if (!WtStartErrors(w, execState->interp, &errorSetId)) {
0213
    status = WT_STATUS_FATAL;
0214
  } else {
0215
    /* Add script to stack */
0216
0217
    frame = WtNewTableObj();
0218
    Tcl_IncrRefCount(frame);
0219
    WtTableSetStrToStr(frame, "state", "start");
0220
    WtTableSetStrToObj(frame, "requestedPath", execState->requestedPath ?
0221
      execState->requestedPath : WtNewString(NULL));
0222
    WtTableSetStrToObj(frame, "targetPath", execState->targetPath ?
0223
      execState->targetPath : WtNewString(NULL));
0224
    WtTableSetStrToObj(frame, "namespace",
0225
      execState->namesp ? execState->namesp : WtNewString(NULL));
0226
    WtTableSetStrToStr(frame, "parsed", "");
0227
    WtTableSetStrToBool(frame, "errorState", 0);
0228
0229
    web->loader.pageIndex++;
0230
0231
    if (!WtSetCurrentFrame(w, frame, execState->interp)) {
0232
      status = WT_STATUS_FATAL;
0233
      WtAddInterpError(execState->interp, w);
0234
    }
0235
    Tcl_DecrRefCount(frame);
0236
    frame = NULL;
0237
  }
0238
0239
  if (status == WT_STATUS_OK) {
0240
    /* Start hook */
0241
    if (!WtEvalEventHandlers(&w->web->ctxEventHandlers, "startInclude",
0242
        execState->interp, w)) {
0243
      status = WT_STATUS_ERROR;
0244
      WtAddInterpError(execState->interp, w);
0245
0246
      if (!WtSetFrameError(w, execState->interp)) {
0247
        status = WT_STATUS_FATAL;
0248
        WtAddInterpError(execState->interp, w);
0249
      }
0250
    }
0251
  }
0252
0253
  /* Parse script */
0254
0255
  if (status == WT_STATUS_OK) {
0256
    if (!(frame = WtGetCurrentFrame(w, execState->interp))) {
0257
      status = WT_STATUS_FATAL;
0258
      WtAddInterpError(execState->interp, w);
0259
    } else {
0260
      WtTableSetStrToStr(frame, "state", "parse");
0261
      if (!WtParseString(execState, string, len)) {
0262
        status = WT_STATUS_ERROR;
0263
        WtAddInterpError(execState->interp, w);
0264
        WtTableSetStrToBool(frame, "errorState", 1);
0265
      }
0266
      if (execState->genCode) {
0267
        WtTableSetStrToObj(frame, "parsed", execState->genCode);
0268
      }
0269
      if (!WtSetCurrentFrame(w, frame, execState->interp)) {
0270
        status = WT_STATUS_FATAL;
0271
        WtAddInterpError(execState->interp, w);
0272
      }
0273
      Tcl_DecrRefCount(frame);
0274
      frame = NULL;
0275
    }
0276
  }
0277
0278
  /* Run the script */
0279
0280
  if (status == WT_STATUS_OK &&
0281
      !WtSetFrameState(w, execState->interp, "run")) {
0282
    status = WT_STATUS_FATAL;
0283
    WtAddInterpError(execState->interp, w);
0284
  }
0285
0286
  if (status == WT_STATUS_OK) {
0287
    rc = Tcl_EvalObj(execState->interp, execState->genCode);
0288
0289
    if (rc == TCL_OK) {
0290
      returnValue = Tcl_GetObjResult(execState->interp);
0291
      if (returnValue) {
0292
        Tcl_IncrRefCount(returnValue);
0293
      }
0294
    } else {
0295
      status = WT_STATUS_ERROR;
0296
0297
      if (execState->targetPath &&
0298
          Tcl_GetCharLength(execState->targetPath)) {
0299
        errMsg = Tcl_NewStringObj("\n    (\"", 7);
0300
        Tcl_IncrRefCount(errMsg);
0301
        Tcl_AppendObjToObj(errMsg, execState->targetPath);
0302
        snprintf(str, sizeof(str), "\" include body line %d)",
0303
          execState->interp->errorLine);
0304
        Tcl_AppendToObj(errMsg, str, -1);
0305
        Tcl_AddObjErrorInfo(execState->interp,
0306
          WtToString(errMsg), -1);
0307
        Tcl_DecrRefCount(errMsg);
0308
      } else {
0309
        snprintf(str, sizeof(str), "\n    (include body line %d)",
0310
          execState->interp->errorLine);
0311
        Tcl_AddObjErrorInfo(execState->interp, str, -1);
0312
      }
0313
0314
      WtAddEvalError(execState->interp, w);
0315
0316
      if (!WtSetFrameError(w, execState->interp)) {
0317
        status = WT_STATUS_FATAL;
0318
        WtAddInterpError(execState->interp, w);
0319
      }
0320
    }
0321
0322
    WtLog(HERE, APLOG_DEBUG | APLOG_NOERRNO, execState->context,
0323
      "Wtcl: WtExecuteString: Tcl_EvalObj returned %d.", rc);
0324
  }
0325
0326
  /* End hook */
0327
0328
  if (status != WT_STATUS_FATAL) {
0329
    if (!WtSetFrameState(w, execState->interp, "end")) {
0330
      status = WT_STATUS_FATAL;
0331
      WtAddInterpError(execState->interp, w);
0332
    } else {
0333
      if (!WtEvalEventHandlers(&w->web->ctxEventHandlers, "endInclude",
0334
          execState->interp, w)) {
0335
        status = WT_STATUS_ERROR;
0336
        if (!WtAddInterpError(execState->interp, w)) {
0337
          status = WT_STATUS_FATAL;
0338
        }
0339
        if (!WtSetFrameError(w, execState->interp)) {
0340
          status = WT_STATUS_FATAL;
0341
          WtAddInterpError(execState->interp, w);
0342
        }
0343
      }
0344
    }
0345
  }
0346
0347
  if (!WtSetFrameState(w, execState->interp, "done")) {
0348
    status = WT_STATUS_FATAL;
0349
    WtAddInterpError(execState->interp, w);
0350
  }
0351
0352
  /* Pop script stack */
0353
0354
  web->loader.pageIndex--;
0355
0356
  /* Set return */
0357
0358
  if (errorSetId != -1) {
0359
    errorCount = WtStopErrors(w, execState->interp, errorSetId, 1);
0360
    if (errorCount == -1) {
0361
      status = WT_STATUS_FATAL;
0362
    } else if (errorCount == 0 && returnValue) {
0363
      Tcl_SetObjResult(execState->interp, returnValue);
0364
    }
0365
  }
0366
0367
  if (returnValue) {
0368
    Tcl_DecrRefCount(returnValue);
0369
  }
0370
0371
  WtLog(HERE, APLOG_DEBUG | APLOG_NOERRNO, execState->context,
0372
    "Wtcl: WtExecuteString: Returning %d.", status == WT_STATUS_OK);
0373
0374
  return status == WT_STATUS_OK;
0375
}
0376
0377
/* TODO: Add support for UTF. */
0378
0379
int WtParseString(WtExecutionState *execState, Tcl_Obj *string, int len)
0380
{
0381
  int ok = 1, inExpr = 0, inComment = 0;
0382
  char *startStr, *endStr;
0383
  int startLen, endLen;
0384
  char *buf = Tcl_GetString(string);
0385
  char *p = buf, *q, *end = buf + len;
0386
  char exprChar = '=';
0387
  char commentChar = '#';
0388
  Tcl_Obj *namesp;
0389
0390
  WtLog(HERE, APLOG_DEBUG | APLOG_NOERRNO, execState->context,
0391
    "Wtcl: WtParseString (len = %d).", len);
0392
0393
  if (!execState->genCode) {
0394
    execState->genCode = Tcl_NewStringObj(NULL, 0);
0395
    Tcl_IncrRefCount(execState->genCode);
0396
  }
0397
0398
  if (execState->context->web->loader.addHeaderTrailer) {
0399
    if (Tcl_GetCharLength(execState->context->web->loader.includeHeader)) {
0400
      Tcl_AppendObjToObj(execState->genCode,
0401
        execState->context->web->loader.includeHeader);
0402
    }
0403
  }
0404
0405
  namesp = execState->namesp ? execState->namesp :
0406
    execState->context->web->loader.includeNamespace;
0407
0408
  if (namesp && Tcl_GetCharLength(namesp)) {
0409
    Tcl_AppendToObj(execState->genCode, "namespace eval ", -1);
0410
    Tcl_AppendObjToObj(execState->genCode, namesp);
0411
    Tcl_AppendToObj(execState->genCode, " {", 2);
0412
  }
0413
0414
  startStr = WtToString(execState->context->web->loader.scriptStartString);
0415
  startLen = strlen(startStr);
0416
0417
  endStr = WtToString(execState->context->web->loader.scriptEndString);
0418
  endLen = strlen(endStr);
0419
0420
  do {
0421
    q = strstr(p, startStr);
0422
0423
    if (q) {
0424
      if (!WtParserAddContent(execState, p, q - p)) {
0425
        ok = 0;
0426
        break;
0427
      }
0428
0429
      if (q < end - startLen && q[startLen] == exprChar) {
0430
        inExpr = 1;
0431
        p = q + startLen + 1;
0432
      } else if (q < end - startLen && q[startLen] == commentChar) {
0433
        inComment = 1;
0434
        p = q + startLen + 1;
0435
      } else {
0436
        inExpr = 0;
0437
        inComment = 0;
0438
        p = q + startLen;
0439
      }
0440
0441
      q = strstr(p, endStr);
0442
0443
      if (q) {
0444
        if (inExpr) {
0445
          if (!WtParserAddExpr(execState, p, q - p)) {
0446
            ok = 0;
0447
            break;
0448
          }
0449
        } else if (inComment) {
0450
          ;
0451
        } else {
0452
          WtParserAddCode(execState, p, q - p);
0453
        }
0454
        p = q + endLen;
0455
      } else {
0456
        if (execState->targetPath) {
0457
          Tcl_AppendResult(execState->interp,
0458
            "Missing script end tag at end of file \"",
0459
            execState->targetPath, "\".", NULL);
0460
        } else {
0461
          Tcl_AppendResult(execState->interp,
0462
            "Missing script end tag.", NULL);
0463
        }
0464
        ok = 0;
0465
        break;
0466
      }
0467
    } else {
0468
      if (!WtParserAddContent(execState, p, end - p)) {
0469
        ok = 0;
0470
      }
0471
      break;
0472
    }
0473
  } while (p < end && ok);
0474
0475
  if (ok) {
0476
    if (namesp && Tcl_GetCharLength(namesp)) {
0477
      Tcl_AppendToObj(execState->genCode, "\n}", 2);
0478
    }
0479
0480
    if (execState->context->web->loader.addHeaderTrailer) {
0481
      if (Tcl_GetCharLength(execState->context->web->loader.includeTrailer)) {
0482
        Tcl_AppendObjToObj(execState->genCode,
0483
          execState->context->web->loader.includeTrailer);
0484
      }
0485
    }
0486
  }
0487
0488
  return ok;
0489
}
0490
0491
void WtParserAddCode(WtExecutionState *execState, char *buf, int len)
0492
{
0493
  Tcl_AppendToObj(execState->genCode, buf, len);
0494
  Tcl_AppendToObj(execState->genCode, "\n", 1);
0495
}
0496
0497
int WtParserAddExpr(WtExecutionState *execState, char *buf, int len)
0498
{
0499
  if (!len) {
0500
    if (execState->targetPath) {
0501
      Tcl_AppendResult(execState->interp, "Empty expression tag in file \"",
0502
        execState->targetPath, "\".", NULL);
0503
    } else {
0504
      Tcl_AppendResult(execState->interp, "Empty expression tag.", NULL);
0505
    }
0506
    return 0;
0507
  }
0508
0509
  if (Tcl_GetCharLength(execState->context->web->loader.exprHandler)) {
0510
    Tcl_AppendObjToObj(execState->genCode,
0511
      execState->context->web->loader.exprHandler);
0512
    Tcl_AppendToObj(execState->genCode, " ", 1);
0513
    Tcl_AppendToObj(execState->genCode, buf, len);
0514
    Tcl_AppendToObj(execState->genCode, "\n", 1);
0515
  } else {
0516
    Tcl_AppendToObj(execState->genCode, "puts -nonewline ", -1);
0517
    Tcl_AppendToObj(execState->genCode, buf, len);
0518
    Tcl_AppendToObj(execState->genCode, "\n", 1);
0519
  }
0520
  return 1;
0521
}
0522
0523
int WtParserAddContent(WtExecutionState *execState, char *buf, int len)
0524
{
0525
  char *stringLiteral;
0526
  int flags, literalLen;
0527
0528
  if (!len) {
0529
    return 1;
0530
  }
0531
0532
  literalLen = Tcl_ScanCountedElement(buf, len, &flags);
0533
  stringLiteral = Tcl_Alloc(literalLen);
0534
  ap_assert(stringLiteral);
0535
0536
  literalLen = Tcl_ConvertCountedElement(buf, len, stringLiteral, flags);
0537
0538
  if (Tcl_GetCharLength(execState->context->web->loader.textHandler)) {
0539
    Tcl_AppendObjToObj(execState->genCode,
0540
      execState->context->web->loader.textHandler);
0541
    Tcl_AppendToObj(execState->genCode, " ", 1);
0542
    Tcl_AppendToObj(execState->genCode, buf, len);
0543
    Tcl_AppendToObj(execState->genCode, "\n", 1);
0544
  } else {
0545
    Tcl_AppendToObj(execState->genCode, "puts -nonewline [subst ", -1);
0546
    Tcl_AppendToObj(execState->genCode, stringLiteral, literalLen);
0547
    Tcl_AppendToObj(execState->genCode, "]\n", 2);
0548
  }
0549
0550
  Tcl_Free(stringLiteral);
0551
  return 1;
0552
}
0553
0554
int WtExecuteRequest(WtContext *w, const char *requestedPath)
0555
{
0556
  int ok = 0;
0557
  WtExecutionState execState;
0558
  Tcl_Obj *result;
0559
0560
  WtLog(HERE, APLOG_DEBUG | APLOG_NOERRNO, w,
0561
    "Wtcl: WtExecuteRequest (requestedPath = \"%s\").",
0562
    requestedPath);
0563
0564
  WtInitExecState(&execState, w, w->web->interp);
0565
0566
  execState.requestedPath = Tcl_NewStringObj(requestedPath, -1);
0567
  Tcl_IncrRefCount(execState.requestedPath);
0568
0569
  execState.targetPath = Tcl_NewStringObj(requestedPath, -1);
0570
  Tcl_IncrRefCount(execState.targetPath);
0571
0572
  execState.genCode = NULL;
0573
0574
  if (Tcl_GetCharLength(w->web->taskNamespace)) {
0575
    execState.namesp = w->web->taskNamespace;
0576
    Tcl_IncrRefCount(execState.namesp);
0577
  }
0578
0579
  /* Execute the script */
0580
0581
  w->web->pageIsStarted = 1;
0582
  ok = WtExecuteFile(&execState);
0583
  w->web->pageIsStarted = 0;
0584
  if (!ok) {
0585
    result = Tcl_GetObjResult(execState.interp);
0586
    WtLog(HERE, APLOG_ERR | APLOG_NOERRNO, w, "%s",
0587
      (result ? WtSafeStr(WtToString(result)) : ""));
0588
  }
0589
0590
  /* Cleanup */
0591
0592
  WtDeleteExecState(&execState);
0593
0594
  WtLog(HERE, APLOG_DEBUG | APLOG_NOERRNO, execState.context,
0595
    "Wtcl: WtExecuteRequest: Returning %d.", ok);
0596
0597
  return ok;
0598
}
0599
0600
Tcl_Obj *WtGetCurrentFrame(WtContext *w, Tcl_Interp *interp)
0601
{
0602
  Tcl_Obj *frame = NULL;
0603
  int created;
0604
0605
  if (Tcl_ListObjIndex(interp, w->web->loader.pageStack,
0606
      w->web->loader.pageIndex, &frame) == TCL_OK) {
0607
    created = WtCopyOnWrite(&frame);
0608
    if (!WtConvertToTable(frame, interp)) {
0609
      if (created) {
0610
        Tcl_DecrRefCount(frame);
0611
      }
0612
      frame = NULL;
0613
    }
0614
    if (frame) {
0615
      Tcl_IncrRefCount(frame);
0616
    }
0617
  }
0618
0619
  return frame;
0620
}
0621
0622
int WtSetCurrentFrame(WtContext *w, Tcl_Obj *frame, Tcl_Interp *interp)
0623
{
0624
  int ok = 0, len, rc;
0625
0626
  Tcl_IncrRefCount(frame);
0627
  WtCopyOnWrite(&w->web->loader.pageStack);
0628
  if (Tcl_ListObjLength(interp, w->web->loader.pageStack, &len) == TCL_OK) {
0629
    rc = Tcl_ListObjReplace(interp, w->web->loader.pageStack,
0630
      w->web->loader.pageIndex, len - w->web->loader.pageIndex,
0631
      1, &frame);
0632
    ok = rc == TCL_OK;
0633
  }
0634
  Tcl_DecrRefCount(frame);
0635
0636
  return ok;
0637
}
0638
0639
int WtSetFrameState(WtContext *w, Tcl_Interp *interp, const char *state)
0640
{
0641
  int ok = 0;
0642
  Tcl_Obj *frame;
0643
0644
  if (frame = WtGetCurrentFrame(w, interp)) {
0645
    WtTableSetStrToStr(frame, "state", state);
0646
    if (WtSetCurrentFrame(w, frame, interp)) {
0647
      ok = 1;
0648
    }
0649
    Tcl_DecrRefCount(frame);
0650
  }
0651
0652
  return ok;
0653
}
0654
0655
int WtSetFrameError(WtContext *w, Tcl_Interp *interp)
0656
{
0657
  int ok = 0;
0658
  Tcl_Obj *frame;
0659
0660
  if (frame = WtGetCurrentFrame(w, interp)) {
0661
    WtTableSetStrToBool(frame, "errorState", 1);
0662
    if (WtSetCurrentFrame(w, frame, interp)) {
0663
      ok = 1;
0664
    }
0665
    Tcl_DecrRefCount(frame);
0666
  }
0667
0668
  return ok;
0669
}
0670
0671
/* Initialize commands */
0672
0673
void WtInitPageCommands(Tcl_Interp *interp)
0674
{
0675
  WtContext *w = WtGetAssocContext(interp);
0676
0677
  Tcl_CreateObjCommand(interp, "::wt::page::include",
0678
    WtIncludeCmd, NULL, NULL);
0679
0680
  Tcl_CreateObjCommand(interp, "::wt::page::includeString",
0681
    WtIncludeStringCmd, NULL, NULL);
0682
0683
  Tcl_CreateObjCommand(interp, "::wt::page::pageIndex",
0684
    WtPageIndexCmd, NULL, NULL);
0685
0686
  Tcl_CreateObjCommand(interp, "::wt::page::pageStack",
0687
    WtStackCmd, NULL, NULL);
0688
0689
  Tcl_CreateObjCommand(interp, "::wt::page::loader",
0690
    WtLoaderCmd, NULL, NULL);
0691
0692
  Tcl_CreateObjCommand(interp, "::wt::page::loaderInfo",
0693
    WtLoaderInfoCmd, NULL, NULL);
0694
}
0695
0696
/* include command */
0697
0698
int WtIncludeCmd(ClientData clientData, Tcl_Interp *interp,
0699
    int objc, Tcl_Obj *const objv[])
0700
{
0701
  int ret = TCL_ERROR;
0702
  WtContext *w = WtGetAssocContext(interp);
0703
0704
  if (objc != 2) {
0705
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0706
      Tcl_GetString(objv[0]), " path", NULL);
0707
  } else if (WtFindAndExecuteFile(w, objv[1], interp)) {
0708
    ret = TCL_OK;
0709
  }
0710
0711
  return ret;
0712
}
0713
0714
/* includeString command */
0715
0716
int WtIncludeStringCmd(ClientData clientData, Tcl_Interp *interp,
0717
    int objc, Tcl_Obj *const objv[])
0718
{
0719
  int ret = TCL_ERROR;
0720
  WtContext *w = WtGetAssocContext(interp);
0721
  WtExecutionState execState;
0722
0723
  if (objc != 2) {
0724
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0725
      Tcl_GetString(objv[0]), " string", NULL);
0726
  } else {
0727
    WtInitExecState(&execState, w, interp);
0728
    if (WtExecuteString(&execState, objv[1], Tcl_GetCharLength(objv[1]))) {
0729
      ret = TCL_OK;
0730
    }
0731
    WtDeleteExecState(&execState);
0732
  }
0733
0734
  return ret;
0735
}
0736
0737
/* pageIndex command */
0738
0739
int WtPageIndexCmd(ClientData clientData, Tcl_Interp *interp,
0740
    int objc, Tcl_Obj *const objv[])
0741
{
0742
  int ret = TCL_ERROR;
0743
  WtContext *w;
0744
0745
  if (objc != 1) {
0746
    Tcl_AppendResult(interp, wtBadUsagePrefix, WtToString(objv[0]), NULL);
0747
  } else {
0748
    w = WtGetAssocContext(interp);
0749
    Tcl_SetObjResult(interp, Tcl_NewIntObj(w->web->loader.pageIndex));
0750
    ret = TCL_OK;
0751
  }
0752
0753
  return ret;
0754
}
0755
0756
/* stack command */
0757
0758
int WtStackCmd(ClientData clientData, Tcl_Interp *interp,
0759
    int objc, Tcl_Obj *const objv[])
0760
{
0761
  int ret = TCL_ERROR;
0762
  WtContext *w = WtGetAssocContext(interp);
0763
0764
  if (objc != 1) {
0765
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0766
      WtToString(objv[0]), NULL);
0767
  } else {
0768
    Tcl_SetObjResult(interp, w->web->loader.pageStack);
0769
    ret = TCL_OK;
0770
  }
0771
0772
  return ret;
0773
}
0774
0775
/* loader command */
0776
0777
int WtLoaderCmd(ClientData clientData, Tcl_Interp *interp,
0778
    int objc, Tcl_Obj *const objv[])
0779
{
0780
  int ret = TCL_ERROR;
0781
  char *subCmd;
0782
0783
  if (objc >= 2) {
0784
    subCmd = WtToString(objv[1]);
0785
0786
    if (!strcmp(subCmd, "searchPath")) {
0787
      ret = WtLoaderSearchPathCmd(clientData, interp, objc, objv);
0788
    } else {
0789
      WtLoaderCmdUsage(interp, objv[0]);
0790
    }
0791
  } else {
0792
    WtLoaderCmdUsage(interp, objv[0]);
0793
  }
0794
0795
  return ret;
0796
}
0797
0798
/* searchPath command */
0799
0800
int WtLoaderSearchPathCmd(ClientData clientData, Tcl_Interp *interp,
0801
    int objc, Tcl_Obj *const objv[])
0802
{
0803
  int ret = TCL_ERROR;
0804
  WtContext *w;
0805
  WtPageLoader *loader;
0806
0807
  if (objc == 2 || objc == 3) {
0808
    w = WtGetAssocContext(interp);
0809
    loader = &w->web->loader;
0810
    if (objc == 2) {
0811
      Tcl_SetObjResult(interp, loader->includeSearchPath);
0812
    } else {
0813
      WtSetObj(&loader->includeSearchPath, objv[2]);
0814
      Tcl_SetObjResult(interp, loader->includeSearchPath);
0815
    }
0816
    ret = TCL_OK;
0817
  } else {
0818
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0819
      " ", WtToString(objv[0]), " searchPath ?searchPath?",
0820
      NULL);
0821
  }
0822
0823
  return ret;
0824
}
0825
0826
/* loader command usage */
0827
0828
void WtLoaderCmdUsage(Tcl_Interp *interp, Tcl_Obj *cmd)
0829
{
0830
  char *cmdStr = WtToString(cmd);
0831
0832
  Tcl_AppendResult(interp, wtBadUsagePrefix2, "\n",
0833
    cmdStr, " searchPath ?searchPath?\n",
0834
    cmdStr, " namespace ?namespace?\n",
0835
    cmdStr, " addHeaderTrailer ?addHeaderTrailer?\n",
0836
    cmdStr, " header ?header?\n",
0837
    cmdStr, " trailer ?trailer?\n",
0838
    cmdStr, " startString ?startString?\n",
0839
    cmdStr, " endString ?endString?\n",
0840
    cmdStr, " interpolateText ?interpolateText?\n",
0841
    cmdStr, " textHandler ?textHandler?\n",
0842
    cmdStr, " exprHandler ?exprHandler?\n",
0843
    cmdStr, " pageIndex\n",
0844
    cmdStr, " pageStack\n",
0845
    NULL);
0846
}
0847
0848
/* loaderInfo command */
0849
0850
int WtLoaderInfoCmd(ClientData clientData, Tcl_Interp *interp,
0851
    int objc, Tcl_Obj *const objv[])
0852
{
0853
  int ret = TCL_ERROR;
0854
  WtContext *w;
0855
  WtPageLoader *loader;
0856
  Tcl_Obj *tbl;
0857
0858
  if (objc != 1) {
0859
    Tcl_AppendResult(interp, wtBadUsagePrefix, WtToString(objv[0]), NULL);
0860
  } else {
0861
    w = WtGetAssocContext(interp);
0862
    loader = &w->web->loader;
0863
    tbl = WtNewTableObj();
0864
    WtTableSetStrToObj(tbl, "includeSearchPath", loader->includeSearchPath);
0865
    WtTableSetStrToObj(tbl, "includeNamespace", loader->includeNamespace);
0866
    WtTableSetStrToBool(tbl, "addHeaderTrailer", loader->addHeaderTrailer);
0867
    WtTableSetStrToObj(tbl, "includeHeader", loader->includeHeader);
0868
    WtTableSetStrToObj(tbl, "includeTrailer", loader->includeTrailer);
0869
    WtTableSetStrToObj(tbl, "scriptStartString", loader->scriptStartString);
0870
    WtTableSetStrToObj(tbl, "scriptEndString", loader->scriptEndString);
0871
    WtTableSetStrToBool(tbl, "interpolateText", loader->interpolateText);
0872
    WtTableSetStrToObj(tbl, "textHandler", loader->textHandler);
0873
    WtTableSetStrToObj(tbl, "exprHandler", loader->exprHandler);
0874
    WtTableSetStrToInt(tbl, "pageIndex", loader->pageIndex);
0875
    Tcl_SetObjResult(interp, tbl);
0876
    ret = TCL_OK;
0877
  }
0878
0879
  return ret;
0880
}