Annotation of sbbs/src/sbbs3/js_uifc.c, revision 1.1.1.1

1.1       root        1: /* js_uifc.c */
                      2: 
                      3: /* Synchronet "uifc" (user interface) object */
                      4: 
                      5: /* $Id: js_uifc.c,v 1.10 2006/06/14 02:34:49 rswindell Exp $ */
                      6: 
                      7: /****************************************************************************
                      8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
                      9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
                     10:  *                                                                                                                                                     *
                     11:  * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html         *
                     12:  *                                                                                                                                                     *
                     13:  * This program is free software; you can redistribute it and/or                       *
                     14:  * modify it under the terms of the GNU General Public License                         *
                     15:  * as published by the Free Software Foundation; either version 2                      *
                     16:  * of the License, or (at your option) any later version.                                      *
                     17:  * See the GNU General Public License for more details: gpl.txt or                     *
                     18:  * http://www.fsf.org/copyleft/gpl.html                                                                                *
                     19:  *                                                                                                                                                     *
                     20:  * Anonymous FTP access to the most recent released source is available at     *
                     21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
                     22:  *                                                                                                                                                     *
                     23:  * Anonymous CVS access to the development source and modification history     *
                     24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
                     25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
                     26:  *     (just hit return, no password is necessary)                                                     *
                     27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
                     28:  *                                                                                                                                                     *
                     29:  * For Synchronet coding style and modification guidelines, see                                *
                     30:  * http://www.synchro.net/source.html                                                                          *
                     31:  *                                                                                                                                                     *
                     32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
                     33:  * format) via e-mail to [email protected]                                                                      *
                     34:  *                                                                                                                                                     *
                     35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
                     36:  ****************************************************************************/
                     37: 
                     38: #ifndef JAVASCRIPT
                     39: #define JAVASCRIPT
                     40: #endif
                     41: 
                     42: #include "sbbs.h"
                     43: #include "uifc.h"
                     44: #include "ciolib.h"
                     45: 
                     46: /* Properties */
                     47: enum {
                     48:         PROP_INITIALIZED       /* read-only */
                     49:        ,PROP_MODE
                     50:        ,PROP_CHANGES
                     51:        ,PROP_SAVNUM
                     52:        ,PROP_SCRN_LEN
                     53:     ,PROP_SCRN_WIDTH
                     54:        ,PROP_ESC_DELAY
                     55:        ,PROP_HELPBUF
                     56:        ,PROP_HCOLOR
                     57:        ,PROP_LCOLOR
                     58:        ,PROP_BCOLOR
                     59:        ,PROP_CCOLOR
                     60:        ,PROP_LBCOLOR
                     61:        ,PROP_LIST_HEIGHT
                     62: };
                     63: 
                     64: static JSBool js_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
                     65: {
                     66:     jsint              tiny;
                     67:        uifcapi_t*      uifc;
                     68: 
                     69:        if((uifc=(uifcapi_t*)JS_GetPrivate(cx,obj))==NULL)
                     70:                return(JS_FALSE);
                     71: 
                     72:     tiny = JSVAL_TO_INT(id);
                     73: 
                     74:        switch(tiny) {
                     75:                case PROP_INITIALIZED:
                     76:                        *vp=BOOLEAN_TO_JSVAL(uifc->initialized);
                     77:                        break;
                     78:                case PROP_MODE:
                     79:                        JS_NewNumberValue(cx,uifc->mode,vp);
                     80:                        break;
                     81:                case PROP_CHANGES:
                     82:                        *vp=BOOLEAN_TO_JSVAL(uifc->changes);
                     83:                        break;
                     84:                case PROP_SAVNUM:
                     85:                        *vp=INT_TO_JSVAL(uifc->savnum);
                     86:                        break;
                     87:                case PROP_SCRN_LEN:
                     88:                        *vp=INT_TO_JSVAL(uifc->scrn_len);
                     89:                        break;
                     90:                case PROP_SCRN_WIDTH:
                     91:                        *vp=INT_TO_JSVAL(uifc->scrn_width);
                     92:                        break;
                     93:                case PROP_ESC_DELAY:
                     94:                        *vp=INT_TO_JSVAL(uifc->esc_delay);
                     95:                        break;
                     96:                case PROP_HELPBUF:
                     97:                        *vp=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,uifc->helpbuf));
                     98:                        break;
                     99:                case PROP_HCOLOR:
                    100:                        *vp=INT_TO_JSVAL(uifc->hclr);
                    101:                        break;
                    102:                case PROP_LCOLOR:
                    103:                        *vp=INT_TO_JSVAL(uifc->lclr);
                    104:                        break;
                    105:                case PROP_BCOLOR:
                    106:                        *vp=INT_TO_JSVAL(uifc->bclr);
                    107:                        break;
                    108:                case PROP_CCOLOR:
                    109:                        *vp=INT_TO_JSVAL(uifc->cclr);
                    110:                        break;
                    111:                case PROP_LBCOLOR:
                    112:                        *vp=INT_TO_JSVAL(uifc->lbclr);
                    113:                        break;
                    114:                case PROP_LIST_HEIGHT:
                    115:                        *vp=INT_TO_JSVAL(uifc->list_height);
                    116:                        break;
                    117:        }
                    118: 
                    119:        return(JS_TRUE);
                    120: }
                    121: 
                    122: static JSBool js_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
                    123: {
                    124:     jsint              tiny;
                    125:        int32           i=0;
                    126:        uifcapi_t*      uifc;
                    127: 
                    128:        if((uifc=(uifcapi_t*)JS_GetPrivate(cx,obj))==NULL)
                    129:                return(JS_FALSE);
                    130: 
                    131:     tiny = JSVAL_TO_INT(id);
                    132: 
                    133:        switch(tiny) {
                    134:                case PROP_MODE:
                    135:                        JS_ValueToInt32(cx, *vp, (int32*)&uifc->mode);
                    136:                        break;
                    137:                case PROP_CHANGES:
                    138:                        JS_ValueToBoolean(cx,*vp,&uifc->changes);
                    139:                        break;
                    140:                case PROP_SAVNUM:
                    141:                        JS_ValueToInt32(cx, *vp, (int32*)&uifc->savnum);
                    142:                        break;
                    143:                case PROP_SCRN_LEN:
                    144:                        JS_ValueToInt32(cx, *vp, (int32*)&uifc->scrn_len);
                    145:                        break;
                    146:                case PROP_SCRN_WIDTH:
                    147:                        JS_ValueToInt32(cx, *vp, (int32*)&uifc->scrn_width);
                    148:                        break;
                    149:                case PROP_ESC_DELAY:
                    150:                        JS_ValueToInt32(cx, *vp, (int32*)&uifc->esc_delay);
                    151:                        break;
                    152:                case PROP_HELPBUF:
                    153:                        uifc->helpbuf=js_ValueToStringBytes(cx, *vp, NULL);
                    154:                        break;
                    155:                case PROP_LIST_HEIGHT:
                    156:                        JS_ValueToInt32(cx, *vp, (int32*)&uifc->list_height);
                    157:                        break;
                    158:                case PROP_HCOLOR:
                    159:                case PROP_LCOLOR:
                    160:                case PROP_BCOLOR:
                    161:                case PROP_CCOLOR:
                    162:                case PROP_LBCOLOR:
                    163:                        JS_ValueToInt32(cx, *vp, &i);
                    164:                        switch(tiny) {
                    165:                                case PROP_HCOLOR:
                    166:                                        uifc->hclr=(char)i;
                    167:                                        break;
                    168:                                case PROP_LCOLOR:
                    169:                                        uifc->lclr=(char)i;
                    170:                                        break;
                    171:                                case PROP_BCOLOR:
                    172:                                        uifc->bclr=(char)i;
                    173:                                        break;
                    174:                                case PROP_CCOLOR:
                    175:                                        uifc->cclr=(char)i;
                    176:                                        break;
                    177:                                case PROP_LBCOLOR:
                    178:                                        uifc->lbclr=(char)i;
                    179:                                        break;
                    180:                        }
                    181:                        break;
                    182:        }       
                    183: 
                    184:        return(JS_TRUE);
                    185: }
                    186: 
                    187: static jsSyncPropertySpec js_properties[] = {
                    188: /*              name,                          tinyid,                                         flags,          ver     */
                    189: 
                    190:        {       "initialized",          PROP_INITIALIZED,       JSPROP_ENUMERATE|JSPROP_READONLY, 314 },
                    191:        {       "mode",                         PROP_MODE,                      JSPROP_ENUMERATE,       314 },
                    192:        {       "changes",                      PROP_CHANGES,           JSPROP_ENUMERATE,       314 },
                    193:        {       "save_num",                     PROP_SAVNUM,            JSPROP_ENUMERATE,       314 },
                    194:        {       "screen_length",        PROP_SCRN_LEN,          JSPROP_ENUMERATE,       314 },
                    195:        {       "screen_width",         PROP_SCRN_WIDTH,        JSPROP_ENUMERATE,       314 },
                    196:        {       "list_height",          PROP_LIST_HEIGHT,       JSPROP_ENUMERATE,       314 },
                    197:        {       "esc_delay",            PROP_ESC_DELAY,         JSPROP_ENUMERATE,       314 },
                    198:        {       "help_text",            PROP_HELPBUF,           JSPROP_ENUMERATE,       314 },
                    199:        {       "background_color",     PROP_BCOLOR,            JSPROP_ENUMERATE,       314 },
                    200:        {       "frame_color",          PROP_HCOLOR,            JSPROP_ENUMERATE,       314 },
                    201:        {       "text_color",           PROP_LCOLOR,            JSPROP_ENUMERATE,       314 },
                    202:        {       "inverse_color",        PROP_CCOLOR,            JSPROP_ENUMERATE,       314 },
                    203:        {       "lightbar_color",       PROP_LBCOLOR,           JSPROP_ENUMERATE,       314 },
                    204:        {0}
                    205: };
                    206: 
                    207: /* Convenience functions */
                    208: static uifcapi_t* get_uifc(JSContext *cx, JSObject *obj)
                    209: {
                    210:        uifcapi_t* uifc;
                    211: 
                    212:        if((uifc=(uifcapi_t*)JS_GetPrivate(cx,obj))==NULL)
                    213:                return(NULL);
                    214: 
                    215:        if(!uifc->initialized) {
                    216:                JS_ReportError(cx,"UIFC not initialized");
                    217:                return(NULL);
                    218:        }
                    219: 
                    220:        return(uifc);
                    221: }
                    222: 
                    223: /* Methods */
                    224: 
                    225: static JSBool
                    226: js_uifc_init(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    227: {
                    228:        int             ciolib_mode=CIOLIB_MODE_AUTO;
                    229:        char*   title="Synchronet";
                    230:        char*   mode;
                    231:        uifcapi_t* uifc;
                    232: 
                    233:        *rval = JSVAL_FALSE;
                    234: 
                    235:        if((uifc=(uifcapi_t*)JS_GetPrivate(cx,obj))==NULL)
                    236:                return(JS_FALSE);
                    237: 
                    238:        if(argc && (title=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
                    239:                return(JS_FALSE);
                    240: 
                    241:        if(argc>1 && (mode=js_ValueToStringBytes(cx, argv[1], NULL))!=NULL) {
                    242:                if(!stricmp(mode,"STDIO"))
                    243:                        ciolib_mode=-1;
                    244:                else if(!stricmp(mode,"AUTO"))
                    245:                        ciolib_mode=CIOLIB_MODE_AUTO;
                    246:                else if(!stricmp(mode,"X"))
                    247:                        ciolib_mode=CIOLIB_MODE_X;
                    248:                else if(!stricmp(mode,"ANSI"))
                    249:                        ciolib_mode=CIOLIB_MODE_ANSI;
                    250:                else if(!stricmp(mode,"CONIO"))
                    251:                        ciolib_mode=CIOLIB_MODE_CONIO;
                    252:        }
                    253: 
                    254:        if(ciolib_mode==-1) {
                    255:                if(uifcinix(uifc))
                    256:                        return(JS_TRUE);
                    257:        } else {
                    258:                if(initciolib(ciolib_mode))
                    259:                        return(JS_TRUE);
                    260: 
                    261:                if(uifcini32(uifc))
                    262:                        return(JS_TRUE);
                    263:        }
                    264: 
                    265:        *rval = JSVAL_TRUE;
                    266:        uifc->scrn(title);
                    267:        return(JS_TRUE);
                    268: }
                    269: 
                    270: static JSBool
                    271: js_uifc_bail(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    272: {
                    273:        uifcapi_t* uifc;
                    274: 
                    275:        if((uifc=get_uifc(cx,obj))==NULL)
                    276:                return(JS_FALSE);
                    277: 
                    278:        uifc->bail();
                    279:        return(JS_TRUE);
                    280: }
                    281: 
                    282: static JSBool
                    283: js_uifc_msg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    284: {
                    285:        char*           str;
                    286:        uifcapi_t*      uifc;
                    287: 
                    288:        if((uifc=get_uifc(cx,obj))==NULL)
                    289:                return(JS_FALSE);
                    290: 
                    291:        if((str=js_ValueToStringBytes(cx, argv[0], NULL))==NULL)
                    292:                return(JS_FALSE);
                    293: 
                    294:        uifc->msg(str);
                    295:        return(JS_TRUE);
                    296: }
                    297: 
                    298: static JSBool
                    299: js_uifc_pop(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    300: {
                    301:        char*           str=NULL;
                    302:        uifcapi_t*      uifc;
                    303: 
                    304:        if((uifc=get_uifc(cx,obj))==NULL)
                    305:                return(JS_FALSE);
                    306: 
                    307:        if(argc)
                    308:                str=js_ValueToStringBytes(cx, argv[0], NULL);
                    309: 
                    310:        uifc->pop(str);
                    311:        return(JS_TRUE);
                    312: }
                    313: 
                    314: static JSBool
                    315: js_uifc_input(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    316: {
                    317:        char*           str;
                    318:        char*           org=NULL;
                    319:        char*           prompt=NULL;
                    320:        int32           maxlen=0;
                    321:        int32           left=0;
                    322:        int32           top=0;
                    323:        int32           mode=0;
                    324:        int32           kmode=0;
                    325:        uifcapi_t*      uifc;
                    326:        uintN           argn=0;
                    327: 
                    328:        if((uifc=get_uifc(cx,obj))==NULL)
                    329:                return(JS_FALSE);
                    330: 
                    331:        if(argn<argc && JSVAL_IS_NUMBER(argv[argn]) 
                    332:                && !JS_ValueToInt32(cx,argv[argn++],&mode))
                    333:                return(JS_FALSE);
                    334:        if(argn<argc && JSVAL_IS_NUMBER(argv[argn]) 
                    335:                && !JS_ValueToInt32(cx,argv[argn++],&left))
                    336:                return(JS_FALSE);
                    337:        if(argn<argc && JSVAL_IS_NUMBER(argv[argn]) 
                    338:                && !JS_ValueToInt32(cx,argv[argn++],&top))
                    339:                return(JS_FALSE);
                    340:        if(argn<argc && JSVAL_IS_STRING(argv[argn]) 
                    341:                && (prompt=js_ValueToStringBytes(cx,argv[argn++],NULL))==NULL)
                    342:                return(JS_FALSE);
                    343:        if(argn<argc && JSVAL_IS_STRING(argv[argn]) 
                    344:                && (org=js_ValueToStringBytes(cx,argv[argn++],NULL))==NULL)
                    345:                return(JS_FALSE);
                    346:        if(argn<argc && JSVAL_IS_NUMBER(argv[argn]) 
                    347:                && !JS_ValueToInt32(cx,argv[argn++],&maxlen))
                    348:                return(JS_FALSE);
                    349:        if(argn<argc && JSVAL_IS_NUMBER(argv[argn]) 
                    350:                && !JS_ValueToInt32(cx,argv[argn++],&kmode))
                    351:                return(JS_FALSE);
                    352: 
                    353:        if(!maxlen)
                    354:                maxlen=40;
                    355: 
                    356:        if((str=(char*)alloca(maxlen+1))==NULL)
                    357:                return(JS_FALSE);
                    358: 
                    359:        memset(str,0,maxlen+1);
                    360: 
                    361:        if(org)
                    362:                strncpy(str,org,maxlen);
                    363: 
                    364:        if(uifc->input(mode, left, top, prompt, str, maxlen, kmode)<0)
                    365:                return(JS_TRUE);
                    366: 
                    367:        *rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,str));
                    368: 
                    369:        return(JS_TRUE);
                    370: }
                    371: 
                    372: static JSBool
                    373: js_uifc_list(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
                    374: {
                    375:        char*           title=NULL;
                    376:        int32           left=0;
                    377:        int32           top=0;
                    378:        int32           width=0;
                    379:        int32           dflt=0;
                    380:        int32           bar=0;
                    381:        int32           mode=0;
                    382:        JSObject*       objarg;
                    383:        uifcapi_t*      uifc;
                    384:        uintN           argn=0;
                    385:        jsval           val;
                    386:        jsuint      i;
                    387:        jsuint          numopts;
                    388:        str_list_t      opts=NULL;
                    389: 
                    390:        if((uifc=get_uifc(cx,obj))==NULL)
                    391:                return(JS_FALSE);
                    392: 
                    393:        if(argn<argc && JSVAL_IS_NUMBER(argv[argn]) 
                    394:                && !JS_ValueToInt32(cx,argv[argn++],&mode))
                    395:                return(JS_FALSE);
                    396:        if(argn<argc && JSVAL_IS_NUMBER(argv[argn]) 
                    397:                && !JS_ValueToInt32(cx,argv[argn++],&left))
                    398:                return(JS_FALSE);
                    399:        if(argn<argc && JSVAL_IS_NUMBER(argv[argn]) 
                    400:                && !JS_ValueToInt32(cx,argv[argn++],&top))
                    401:                return(JS_FALSE);
                    402:        if(argn<argc && JSVAL_IS_NUMBER(argv[argn]) 
                    403:                && !JS_ValueToInt32(cx,argv[argn++],&width))
                    404:                return(JS_FALSE);
                    405:        if(argn<argc && JSVAL_IS_NUMBER(argv[argn]) 
                    406:                && !JS_ValueToInt32(cx,argv[argn++],&dflt))
                    407:                return(JS_FALSE);
                    408:        if(argn<argc && JSVAL_IS_NUMBER(argv[argn]) 
                    409:                && !JS_ValueToInt32(cx,argv[argn++],&bar))
                    410:                return(JS_FALSE);
                    411:        if(argn<argc && JSVAL_IS_STRING(argv[argn]) 
                    412:                && (title=js_ValueToStringBytes(cx,argv[argn++],NULL))==NULL)
                    413:                return(JS_FALSE);
                    414:        if(argn<argc && JSVAL_IS_OBJECT(argv[argn])) {
                    415:                if((objarg = JSVAL_TO_OBJECT(argv[argn++]))==NULL)
                    416:                        return(JS_FALSE);
                    417:                if(JS_IsArrayObject(cx, objarg)) {
                    418:                        if(!JS_GetArrayLength(cx, objarg, &numopts))
                    419:                                return(JS_TRUE);
                    420:                        opts=strListInit();
                    421:                        for(i=0;i<numopts;i++) {
                    422:                                if(!JS_GetElement(cx, objarg, i, &val))
                    423:                                        break;
                    424:                                strListPush(&opts,js_ValueToStringBytes(cx,val,NULL));
                    425:                        }
                    426:                }
                    427:        }
                    428: 
                    429:     *rval = INT_TO_JSVAL(uifc->list(mode,left,top,width,(int*)&dflt,(int*)&bar,title,opts));
                    430:        strListFree(&opts);
                    431:        return(JS_TRUE);
                    432: }
                    433: 
                    434: /* Destructor */
                    435: 
                    436: static void 
                    437: js_finalize(JSContext *cx, JSObject *obj)
                    438: {
                    439:        uifcapi_t* p;
                    440: 
                    441:        if((p=(uifcapi_t*)JS_GetPrivate(cx,obj))==NULL)
                    442:                return;
                    443:        
                    444:        free(p);
                    445:        JS_SetPrivate(cx,obj,NULL);
                    446: }
                    447: 
                    448: static jsSyncMethodSpec js_functions[] = {
                    449:        {"init",            js_uifc_init,       1,      JSTYPE_BOOLEAN, JSDOCSTR("string title")
                    450:        ,JSDOCSTR("initialize")
                    451:        ,314
                    452:        },              
                    453:        {"bail",                        js_uifc_bail,           0,      JSTYPE_VOID,    JSDOCSTR("")
                    454:        ,JSDOCSTR("uninitialize")
                    455:        ,314
                    456:        },
                    457:        {"msg",                         js_uifc_msg,            1,      JSTYPE_VOID,    JSDOCSTR("string text")
                    458:        ,JSDOCSTR("print a message")
                    459:        ,314
                    460:        },
                    461:        {"pop",                         js_uifc_pop,            1,      JSTYPE_VOID,    JSDOCSTR("[string text]")
                    462:        ,JSDOCSTR("popup (or down) a message")
                    463:        ,314
                    464:        },
                    465:        {"input",                       js_uifc_input,          0,      JSTYPE_STRING,  JSDOCSTR("[...]")
                    466:        ,JSDOCSTR("prompt for a string input")
                    467:        ,314
                    468:        },
                    469:        {"list",                        js_uifc_list,           0,      JSTYPE_STRING,  JSDOCSTR("[...]")
                    470:        ,JSDOCSTR("select from a list of options")
                    471:        ,314
                    472:        },
                    473:        {0}
                    474: };
                    475: 
                    476: 
                    477: static JSClass js_uifc_class = {
                    478:      "UIFC"                                    /* name                 */
                    479:     ,JSCLASS_HAS_PRIVATE       /* flags                */
                    480:        ,JS_PropertyStub                /* addProperty  */
                    481:        ,JS_PropertyStub                /* delProperty  */
                    482:        ,js_get                                 /* getProperty  */
                    483:        ,js_set                                 /* setProperty  */
                    484:        ,JS_EnumerateStub               /* enumerate    */
                    485:        ,JS_ResolveStub                 /* resolve              */
                    486:        ,JS_ConvertStub                 /* convert              */
                    487:        ,js_finalize                    /* finalize             */
                    488: };
                    489: 
                    490: JSObject* js_CreateUifcObject(JSContext* cx, JSObject* parent)
                    491: {
                    492:        JSObject*       obj;
                    493:        uifcapi_t*      api;
                    494: 
                    495:        if((obj = JS_DefineObject(cx, parent, "uifc", &js_uifc_class, NULL
                    496:                ,JSPROP_ENUMERATE|JSPROP_READONLY))==NULL)
                    497:                return(NULL);
                    498: 
                    499:        if((api=(uifcapi_t*)malloc(sizeof(uifcapi_t)))==NULL)
                    500:                return(NULL);
                    501: 
                    502:        memset(api,0,sizeof(uifcapi_t));
                    503:        api->size=sizeof(uifcapi_t);
                    504:        api->esc_delay=25;
                    505: 
                    506:        if(!JS_SetPrivate(cx, obj, api))        /* Store a pointer to uifcapi_t */
                    507:                return(NULL);
                    508: 
                    509:        if(!js_DefineSyncProperties(cx, obj, js_properties))    /* expose them */
                    510:                return(NULL);
                    511: 
                    512:        if(!js_DefineSyncMethods(cx, obj, js_functions, /* append? */ FALSE)) 
                    513:                return(NULL);
                    514: 
                    515:        return(obj);
                    516: }
                    517: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.