Annotation of qemu/roms/openbios/packages/cmdline.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *   Creation Date: <2003/12/28 14:16:31 samuel>
                      3:  *   Time-stamp: <2004/01/07 10:37:40 samuel>
                      4:  *
                      5:  *     <cmdline.c>
                      6:  *
                      7:  *     OpenFirmwware User Interface
                      8:  *
                      9:  *   Copyright (C) 2003, 2004 Samuel Rydh ([email protected])
                     10:  *
                     11:  *   This program is free software; you can redistribute it and/or
                     12:  *   modify it under the terms of the GNU General Public License
                     13:  *   version 2
                     14:  *
                     15:  */
                     16: 
                     17: #include "config.h"
                     18: #include "libopenbios/bindings.h"
                     19: #include "packages.h"
                     20: #include "libc/vsprintf.h"
                     21: 
                     22: typedef struct {
                     23:        char    *buf;           /* size: ncol+1 */
                     24:        char    *killbuf;       /* size: ncol+1 */
                     25:        char    *history;
                     26:        int     hsize;          /* size of history buffer */
                     27:        int     ncol;           /* #columns */
                     28: } cmdline_info_t;
                     29: 
                     30: DECLARE_NODE( cmdline, INSTALL_OPEN, sizeof(cmdline_info_t),
                     31:              "+/packages/cmdline" );
                     32: 
                     33: static void
                     34: emit( int ch )
                     35: {
                     36:        PUSH( ch );
                     37:        fword("emit");
                     38: }
                     39: 
                     40: static int
                     41: emit_str( const char *str )
                     42: {
                     43:        int n = 0;
                     44:        while( *str ) {
                     45:                n++;
                     46:                emit( *str++ );
                     47:        }
                     48:        return n;
                     49: }
                     50: 
                     51: static void
                     52: move_cursor( int n )
                     53: {
                     54:        if( n >= 0 ) {
                     55:                while( n-- )
                     56:                        emit( '\f' );
                     57:        } else {
                     58:                while( n++ )
                     59:                        emit( 8 );
                     60:        }
                     61: }
                     62: 
                     63: static void
                     64: clear( int n )
                     65: {
                     66:        int i;
                     67:        for( i=0; i<n; i++ )
                     68:                emit(' ');
                     69:        move_cursor( -n );
                     70: }
                     71: 
                     72: static void
                     73: clearline( int pos, int n )
                     74: {
                     75:        move_cursor( -pos );
                     76:        clear( n );
                     77: }
                     78: 
                     79: static int
                     80: key( void )
                     81: {
                     82:        fword("key");
                     83:        return POP();
                     84: }
                     85: 
                     86: /* ( -- flag ) */
                     87: static void
                     88: cmdline_open( cmdline_info_t *ci )
                     89: {
                     90:        ci->ncol = 80;
                     91:        ci->buf = malloc( ci->ncol + 1 );
                     92:        ci->killbuf = malloc( ci->ncol + 1 );
                     93: 
                     94:        ci->hsize = 40;
                     95:        ci->history = malloc( ci->hsize );
                     96:        ci->history[0] = 0;
                     97: 
                     98:        RET( -1 );
                     99: }
                    100: 
                    101: /* ( -- ) */
                    102: static void
                    103: cmdline_close( cmdline_info_t *ci )
                    104: {
                    105:        free( ci->buf );
                    106:        free( ci->killbuf );
                    107:        free( ci->history );
                    108: }
                    109: 
                    110: 
                    111: static char *
                    112: history_get( cmdline_info_t *ci, int n )
                    113: {
                    114:        char *p = ci->history;
                    115:        int len;
                    116: 
                    117:        while( n-- && p )
                    118:                if( (p=strchr(p,'\n')) )
                    119:                        p++;
                    120: 
                    121:        ci->buf[0] = 0;
                    122:        if( !p )
                    123:                 return NULL;
                    124: 
                    125:        for( len=0; len <= ci->ncol && p[len] != '\n' && p[len] ; len++ )
                    126:                ;
                    127:        memcpy( ci->buf, p, len );
                    128:        ci->buf[len] = 0;
                    129:        return p;
                    130: }
                    131: 
                    132: static int
                    133: history_remove( cmdline_info_t *ci, int line )
                    134: {
                    135:        char *s, *p = history_get( ci, line );
                    136: 
                    137:        if( !p || !(s=strchr(p, '\n')) )
                    138:                return 1;
                    139:        s++;
                    140:        memmove( p, s, strlen(s)+1 );
                    141:        return 0;
                    142: }
                    143: 
                    144: static int /* ( -- ) */
                    145: add_to_history( cmdline_info_t *ci, char *str )
                    146: {
                    147:        int n, len;
                    148: 
                    149:        if( !ci->history )
                    150:                return 0;
                    151:        len = strlen(str);
                    152:        if( !len )
                    153:                return 0;
                    154: 
                    155:        /* make room for line in history */
                    156:        for( ;; ) {
                    157:                char *p;
                    158:                n = strlen(ci->history) + 1;
                    159: 
                    160:                if( n + len + 1 <= ci->hsize )
                    161:                        break;
                    162: 
                    163:                if( !(p=strrchr(ci->history,'\n')) )
                    164:                        return 0;
                    165:                *p = 0;
                    166:                if( !(p=strrchr(ci->history, '\n')) )
                    167:                        p = ci->history-1;
                    168:                p[1] = 0;
                    169:        }
                    170: 
                    171:        memmove( ci->history + len + 1, ci->history, n );
                    172:        memcpy( ci->history, str, len );
                    173:        ci->history[ len ] = '\n';
                    174:        return 1;
                    175: }
                    176: 
                    177: static void /* ( -- ) */
                    178: cmdline_prompt( cmdline_info_t *ci )
                    179: {
                    180:        int cur_added=0, histind=0, ch, i, pos=0, n=0, prompt=1;
                    181:         char *buf;
                    182:        int terminate = 0;
                    183: 
                    184:        buf = ci->buf;
                    185:        selfword("prepare");
                    186: 
                    187:        emit('\n');
                    188: #ifdef NOLEAVE
                    189:        for (;;)
                    190: #else
                    191:        while (rstackcnt && !terminate)
                    192: #endif
                    193:        {
                    194:                int drop = 0;
                    195:                terminate = 0;
                    196: 
                    197:                if( prompt ) {
                    198:                        fword("print-prompt");
                    199:                        buf[0] = 0;
                    200:                        cur_added = prompt = histind = pos = n = 0;
                    201:                }
                    202: 
                    203:                ch = key();
                    204:                switch( ch ) {
                    205:                case 27:
                    206:                        switch( key() ) {
                    207:                        case 'f':
                    208:                                while( buf[pos] == ' ' )
                    209:                                        emit( buf[pos++] );
                    210:                                while( buf[pos] && buf[pos] != ' ' )
                    211:                                        emit( buf[pos++] );
                    212:                                break;
                    213: 
                    214:                        case 'b':
                    215:                                while( pos && buf[pos-1] == ' ' ) {
                    216:                                        move_cursor( -1 );
                    217:                                        pos--;
                    218:                                }
                    219:                                while( pos && buf[pos-1] != ' ' ) {
                    220:                                        move_cursor( -1 );
                    221:                                        pos--;
                    222:                                }
                    223:                                break;
                    224:                        case '[':
                    225:                                switch( key() ) {
                    226:                                case 'A':
                    227:                                        goto go_up;
                    228:                                case 'B':
                    229:                                        goto go_down;
                    230:                                case 'C':
                    231:                                        goto go_right;
                    232:                                case 'D':
                    233:                                        goto go_left;
                    234:                                case '3':
                    235:                                        key();
                    236:                                        goto delete;
                    237:                                }
                    238:                                break;
                    239:                        case 'O':
                    240:                                switch(key()) {
                    241:                                case 'F':
                    242:                                        goto go_end;
                    243:                                case 'H':
                    244:                                        goto go_home;
                    245:                                }
                    246:                                break;
                    247:                        }
                    248:                        break;
                    249:                case '\n':
                    250:                case '\r':
                    251:                        if( cur_added )
                    252:                                history_remove( ci, 0 );
                    253:                        add_to_history( ci, ci->buf );
                    254: 
                    255:                        emit_str( &buf[pos] );
                    256:                        emit(' ');
                    257:                        PUSH( feval(buf) );
                    258:                        fword("print-status");
                    259: 
                    260:                        /* Leave the interpreter if terminate? value set */
                    261:                        fword("terminate?");
                    262:                        if (POP())
                    263:                                terminate = 1;
                    264: 
                    265:                        prompt = 1;
                    266:                        break;
                    267: 
                    268:                case 3: /* ^c */
                    269:                        emit_str("\n");
                    270:                        prompt = 1;
                    271:                        if( cur_added )
                    272:                                history_remove( ci, 0 );
                    273:                        break;
                    274: 
                    275:                case 4: /* ^d */
                    276: delete:
                    277:                        if( pos == n )
                    278:                                break;
                    279:                        emit( buf[pos++] );
                    280:                        /* fall through */
                    281: 
                    282:                case 8: /* ^h */
                    283:                case 127: /* backspace */
                    284:                        drop = 1;
                    285:                        if( !pos )
                    286:                                break;
                    287:                        move_cursor( -1 );
                    288:                        emit_str( &buf[pos] );
                    289:                        emit(' ');
                    290:                        memmove( &buf[pos-1], &buf[pos], n+1-pos );
                    291:                        move_cursor( pos-n-1 );
                    292:                        pos--;
                    293:                        n--;
                    294:                        break;
                    295: 
                    296:                case 1: /* ^a */
                    297: go_home:
                    298:                        move_cursor( -pos );
                    299:                        pos = 0;
                    300:                        break;
                    301: 
                    302:                case 5: /* ^e */
                    303: go_end:
                    304:                        pos += emit_str( &buf[pos] );
                    305:                        break;
                    306: 
                    307:                //case 68: /* left */
                    308:                //      drop = 1;
                    309:                case 2: /* ^b */
                    310: go_left:
                    311:                        if( pos ) {
                    312:                                move_cursor( -1 );
                    313:                                pos--;
                    314:                        }
                    315:                        break;
                    316: 
                    317:                //case 67: /* right */
                    318:                //      drop = 1;
                    319:                case 6: /* ^f */
                    320: go_right:
                    321:                        if( pos < n )
                    322:                                emit( buf[pos++] );
                    323:                        break;
                    324: 
                    325:                case 11: /* ^k */
                    326:                        strcpy( ci->killbuf, &buf[pos] );
                    327:                        clear( n-pos );
                    328:                        n = pos;
                    329:                        buf[pos] = 0;
                    330:                        break;
                    331: 
                    332:                case 25: /* ^y */
                    333:                        for( i=0; n < ci->ncol && ci->killbuf[i] ; i++, n++ ) {
                    334:                                memmove( &buf[pos+1], &buf[pos], n+1-pos );
                    335:                                buf[pos] = ci->killbuf[i];
                    336:                                move_cursor( 1-emit_str(&buf[pos++]) );
                    337:                        }
                    338:                        break;
                    339: 
                    340:                case 9: /* TAB */
                    341:                        for( i=0; n < ci->ncol && (!i || (pos%4)) ; i++, n++ ) {
                    342:                                memmove( &buf[pos+1], &buf[pos], n+1-pos );
                    343:                                buf[pos] = ' ';
                    344:                                move_cursor( 1-emit_str(&buf[pos++]) );
                    345:                        }
                    346:                        break;
                    347: 
                    348:                case 12: /* ^l */
                    349:                        move_cursor( -ci->ncol -pos );
                    350:                        fword("print-prompt");
                    351:                        move_cursor( pos-emit_str(buf) );
                    352:                        break;
                    353: 
                    354:                //case 66: /* down */
                    355:                //      drop = 1;
                    356:                case 14: /* ^n */
                    357: go_down:
                    358:                        if( !histind )
                    359:                                break;
                    360:                        history_get( ci, --histind - 1);
                    361:                        clearline( pos, n );
                    362:                        emit_str( buf );
                    363:                        pos = n = strlen( buf );
                    364:                        if( !histind && cur_added ) {
                    365:                                cur_added = 0;
                    366:                                history_remove( ci, 0 );
                    367:                        }
                    368:                        break;
                    369: 
                    370:                //case 65: /* up */
                    371:                //      drop = 1;
                    372:                case 16: /* ^p */
                    373: go_up:
                    374:                        if( !histind && add_to_history(ci, ci->buf) ) {
                    375:                                cur_added = 1;
                    376:                                histind++;
                    377:                        }
                    378:                        if( history_get(ci, histind) )
                    379:                                histind++;
                    380:                        clearline( pos, n );
                    381:                        emit_str( buf );
                    382:                        pos = n = strlen( buf );
                    383:                        break;
                    384:                }
                    385:                if( (unsigned int)ch < 32 )
                    386:                        drop = 1;
                    387: 
                    388:                if( !drop && n < ci->ncol ) {
                    389:                        memmove( &buf[pos+1], &buf[pos], n+1-pos );
                    390:                        n++;
                    391:                        buf[pos] = ch;
                    392:                        move_cursor( 1-emit_str(&buf[pos++]) );
                    393:                }
                    394:        }
                    395: 
                    396:        /* we only get here if terminate? is non-zero; this should
                    397:          * only ever be done for a subordinate forth interpreter 
                    398:          * e.g. for debugging */
                    399: 
                    400:        /* Reset stack and terminate? */
                    401:        rstackcnt = dbgrstackcnt;
                    402:        feval("0 to terminate?");
                    403: }
                    404: 
                    405: NODE_METHODS( cmdline ) = {
                    406:        { "open",       cmdline_open      },
                    407:        { "close",      cmdline_close       },
                    408:        { "cmdline",     cmdline_prompt      },
                    409: };
                    410: 
                    411: void
                    412: cmdline_init( void )
                    413: {
                    414:        REGISTER_NODE( cmdline );
                    415: }

unix.superglobalmegacorp.com

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